Add user roles management page and update user permissions handling
- Created a new `user_roles.php` file for managing user roles and permissions. - Implemented pagination, filtering, and sorting for user roles. - Updated `users.php` to use the new authorization structure for permissions. - Changed API version from v1 to v2 in `users.php` for user data retrieval. - Modified `webhook_mollie.php` to include account hierarchy in license creation. - Refactored invoice generation and email sending logic in `webhook_mollie.php`. - Introduced a new `webhook_paypal.php` file to handle PayPal webhook notifications. - Implemented payment status updates and license creation logic in `webhook_paypal.php`. - Added helper functions for PayPal webhook signature verification and access token retrieval.
This commit is contained in:
13
.gitignore
vendored
13
.gitignore
vendored
@@ -15,3 +15,16 @@ settings/soveliti/soveliti_settings.php
|
||||
assets/database/dev_schema.sql
|
||||
assets/database/migration.sql
|
||||
assets/database/prod_schema.sql
|
||||
migration.sql
|
||||
assets/database/migration_triggers.sql
|
||||
assets/database/migration_v2.sql
|
||||
assets/database/migration_v3.sql
|
||||
.DS_Store
|
||||
api/.DS_Store
|
||||
api/v1/.DS_Store
|
||||
api/v2/.DS_Store
|
||||
api/.DS_Store
|
||||
assets/.DS_Store
|
||||
assets/images/.DS_Store
|
||||
assets/database/ManualUpdates.sql
|
||||
assets/database/migration_users_to_rbac.sql
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
# Payment Integration Implementation Summary
|
||||
|
||||
## Overview
|
||||
Complete payment integration for software upgrades using existing ecommerce infrastructure (transaction API, invoice API, PHPMailer, DomPDF).
|
||||
|
||||
## New Files to Create
|
||||
|
||||
### 1. `/webhook_mollie.php` (Root directory)
|
||||
**Purpose**: Mollie webhook handler specifically for software upgrades
|
||||
**Based on**: Existing webhook.php from commerce product
|
||||
**Key features**:
|
||||
- ✅ Uses `/v2/transactions/` API for status updates (consistent with commerce)
|
||||
- ✅ Uses `/v2/invoice/` API for invoice generation
|
||||
- ✅ Creates PDF invoice with DomPDF
|
||||
- ✅ Sends email via PHPMailer
|
||||
- ✅ Creates software license
|
||||
- ✅ Multi-language support
|
||||
- ✅ Sends to bookkeeping if configured
|
||||
|
||||
**Webhook URL**: `https://yourdomain.com/webhook_mollie.php`
|
||||
|
||||
### 2. `/api/v2/post/payment.php`
|
||||
**Purpose**: Create Mollie payment for software upgrade
|
||||
**Input**: serial_number, version_id, user_data
|
||||
**Output**: {checkout_url, payment_id}
|
||||
**Security**: Server-side price calculation
|
||||
|
||||
### 3. `/api/v2/get/payment.php`
|
||||
**Purpose**: Retrieve payment status
|
||||
**Input**: ?payment_id=xxx
|
||||
**Output**: {payment_id, payment_status, serial_number, equipment_id, ...}
|
||||
|
||||
## Modified Files
|
||||
|
||||
### 1. `/assets/functions.php`
|
||||
**Add new functions**:
|
||||
- `generateUniqueLicenseKey()` - Generate unique license keys
|
||||
- `generateSoftwareInvoice($invoice_data, $order_id, $language)` - Generate HTML invoice for software upgrades
|
||||
- Based on existing `generateInvoice()` function
|
||||
- Custom template for software licenses
|
||||
- Shows: Device serial number, software version, license key, expiry date
|
||||
- Returns: [$html_content, $customer_email, $order_id]
|
||||
|
||||
### 2. `/assets/softwaretool.js`
|
||||
**Modify**:
|
||||
- `processPayment()` - Call `/v2/post/payment` API
|
||||
- `downloadAndInstallSoftware()` - Add serial number verification
|
||||
|
||||
### 3. `/softwaretool.php`
|
||||
**Add**: Payment return detection (`?payment_id=xxx`)
|
||||
|
||||
## Database
|
||||
**No changes needed** - Uses existing:
|
||||
- `transactions` table (txn_id, payment_status, payment_amount, etc.)
|
||||
- `transactions_items` table (item_id, item_options with JSON)
|
||||
|
||||
## Payment Status Codes (Matching Commerce System)
|
||||
- `0` = Pending
|
||||
- `1` = Paid
|
||||
- `101` = Open/Pending (Mollie)
|
||||
- `102` = Failed
|
||||
- `103` = Expired
|
||||
- `999` = Canceled
|
||||
|
||||
## Implementation Order
|
||||
|
||||
1. ✅ Add Mollie constants to config.php
|
||||
2. Create helper functions in functions.php:
|
||||
- `generateUniqueLicenseKey()`
|
||||
- `generateSoftwareInvoice()`
|
||||
3. Create `/api/v2/post/payment.php`
|
||||
4. Create `/api/v2/get/payment.php`
|
||||
5. Create `/webhook_mollie.php`
|
||||
6. Modify frontend JavaScript
|
||||
7. Modify softwaretool.php
|
||||
8. Test in DEBUG mode
|
||||
9. Test with Mollie sandbox
|
||||
10. Deploy to production
|
||||
|
||||
## Key Benefits
|
||||
|
||||
1. **Consistent with ecommerce** - Uses same API structure
|
||||
2. **Professional invoices** - PDF generation + email delivery
|
||||
3. **Complete audit trail** - Transactions + invoices + licenses
|
||||
4. **Multi-language** - Invoice language based on customer country
|
||||
5. **Bookkeeping integration** - Auto-send to bookkeeping email
|
||||
6. **Refund handling** - Webhook detects refunds (TODO: disable license)
|
||||
|
||||
## Invoice Email Template
|
||||
|
||||
The email will include:
|
||||
- Subject: "Software Upgrade - Invoice: [ORDER_ID]"
|
||||
- HTML body with invoice details
|
||||
- PDF attachment (Invoice_[ORDER_ID].pdf)
|
||||
- Sent to customer email + bookkeeping (if configured)
|
||||
|
||||
**Invoice contains:**
|
||||
- Customer details (name, address, email)
|
||||
- Order ID / Transaction ID
|
||||
- Software upgrade details (version, device serial number)
|
||||
- License key + expiry date (2099-12-31)
|
||||
- Price breakdown
|
||||
- Company information
|
||||
@@ -1,825 +0,0 @@
|
||||
# Plan: Payment Flow with Redirect for Software Upgrade Tool
|
||||
|
||||
## User Request
|
||||
Design the payment flow for software upgrades using Mollie (payment provider) with the following requirements:
|
||||
1. User initiates paid upgrade
|
||||
2. System redirects to Mollie for payment
|
||||
3. After successful payment, Mollie redirects back to software tool
|
||||
4. System creates license connected to serialnumber
|
||||
5. Download and upload to device starts automatically
|
||||
|
||||
## Key Challenge
|
||||
**User Experience**: How to resume the upgrade flow after payment redirect, ensuring seamless transition from payment completion back to automatic download/upload.
|
||||
|
||||
---
|
||||
|
||||
## Current System Analysis
|
||||
|
||||
### Existing Infrastructure
|
||||
✅ **Transactions Table** - Ready for payment tracking (txn_id, payment_status, payment_amount)
|
||||
✅ **Licenses Table** - Has transaction_id field for linking (currently unused)
|
||||
✅ **Payment Modal UI** - Frontend form exists in softwaretool.js (lines 455-572)
|
||||
❌ **Payment Provider Integration** - No Mollie/Stripe/PayPal implementation exists
|
||||
❌ **Webhook Handlers** - No callback endpoints implemented
|
||||
❌ **Redirect Handling** - No return_url/cancel_url pattern
|
||||
❌ **License Auto-creation** - No logic to create licenses after successful payment
|
||||
❌ **Payment Session State** - No state persistence across redirect cycle
|
||||
|
||||
### Current Payment Flow (Simulated)
|
||||
```
|
||||
softwaretool.js:
|
||||
1. User clicks "Purchase & Install" → showPaymentModal()
|
||||
2. User fills form → processPayment()
|
||||
3. [SIMULATED 2-second delay - no actual payment]
|
||||
4. downloadAndInstallSoftware() → triggers upload.js
|
||||
```
|
||||
|
||||
**Problem**: Step 3 will become a redirect to Mollie, breaking the flow and losing all state.
|
||||
|
||||
---
|
||||
|
||||
## User's Preferred Flow (APPROVED)
|
||||
|
||||
The user wants a simpler, more elegant approach:
|
||||
|
||||
1. **Payment creates license** - Mollie webhook creates license linked to serial number
|
||||
2. **Return to software tool** - User redirected back with upgrade information in URL
|
||||
3. **Reconnect device** - User connects device (may be different device!)
|
||||
4. **Re-check software options** - System calls `software_update` API again
|
||||
5. **License automatically applied** - Paid upgrade now shows as FREE (license found)
|
||||
6. **Install button changes** - "Purchase & Install" becomes "Install Now" (free)
|
||||
7. **User proceeds** - Click install to download and upload
|
||||
|
||||
### Key Benefits
|
||||
- ✅ No complex state management needed
|
||||
- ✅ Existing license checking logic handles everything
|
||||
- ✅ User can connect different device (license is separate)
|
||||
- ✅ Clean separation: payment → license → upgrade check
|
||||
- ✅ Works with existing `software_update.php` license validation (lines 274-311)
|
||||
|
||||
### Critical Security Check
|
||||
**IMPORTANT**: Before starting upload, verify serial number matches the one from payment.
|
||||
- Store `serial_number` in payment session/URL
|
||||
- When user returns and reconnects device, compare:
|
||||
- `serialnumber_from_payment` vs `serialnumber_from_device`
|
||||
- If mismatch: Show warning "Different device detected - license applied to original device (SN: XXXXX)"
|
||||
|
||||
---
|
||||
|
||||
## Proposed Solution Architecture
|
||||
|
||||
### Database Changes
|
||||
**No new tables needed** - Use existing `transactions` and `transactions_items` tables
|
||||
|
||||
**`transactions` table fields:**
|
||||
- `txn_id` (varchar 255, UNIQUE) - Store Mollie payment_id here
|
||||
- `payment_status` (int 11) - Payment status code (need to define: 0=pending, 1=paid, 2=failed, 3=canceled, etc.)
|
||||
- `payment_amount` (decimal 7,2) - Price
|
||||
- `payer_email` (varchar 255) - Customer email
|
||||
- `first_name`, `last_name` - Customer name
|
||||
- `address_*` fields - Customer address
|
||||
- `account_id` (varchar 255) - Can store serial_number here or user account
|
||||
- `payment_method` (int 11) - Payment method ID
|
||||
- `created`, `updated` - Timestamps
|
||||
|
||||
**`transactions_items` table fields:**
|
||||
- `txn_id` (varchar 255) - Links to transactions.txn_id
|
||||
- `item_id` (int 11) - Store version_id (products_software_versions.rowID)
|
||||
- `item_price` (decimal 7,2) - Software version price
|
||||
- `item_quantity` (int 11) - Always 1 for software upgrades
|
||||
- `item_options` (varchar 255) - Store JSON with: `{"serial_number": "22110095", "equipment_id": 123, "hw_version": "r08"}`
|
||||
- `created`, `updated` - Timestamps
|
||||
|
||||
**Payment Status Codes** (matching existing webhook.php):
|
||||
- `0` = Pending (initial state, before Mollie call)
|
||||
- `1` = Paid (payment successful)
|
||||
- `101` = Open/Pending (Mollie isPending or isOpen)
|
||||
- `102` = Failed (Mollie isFailed)
|
||||
- `103` = Expired (Mollie isExpired)
|
||||
- `999` = Canceled (Mollie isCanceled)
|
||||
|
||||
### API Endpoints Needed (Following Standard Structure)
|
||||
1. **POST /api/v2/post/payment.php** - Initiates Mollie payment (create action)
|
||||
2. **GET /api/v2/get/payment.php** - Retrieves payment status and details
|
||||
3. **NEW `webhook_mollie.php`** - Separate webhook for software upgrades (based on webhook.php structure, but simplified for this use case)
|
||||
|
||||
### Simplified Flow Diagram
|
||||
```
|
||||
[User] → [Select Paid Upgrade] → [Payment Modal]
|
||||
↓
|
||||
processPayment() calls POST /v2/post/payment
|
||||
- Store pending payment in DB
|
||||
- Call Mollie API: create payment
|
||||
- Get checkout URL
|
||||
- Redirect user to Mollie
|
||||
↓
|
||||
User pays at Mollie ←→ [Mollie Payment Page]
|
||||
↓
|
||||
┌───────────────────────┴───────────────────────┐
|
||||
↓ ↓
|
||||
[Mollie redirects user back] [Mollie webhook fires asynchronously]
|
||||
softwaretool.php?payment_id={payment_id} NEW webhook_mollie.php receives POST
|
||||
- Calls GET /v2/get/payment?payment_id=X - Fetches payment from Mollie API
|
||||
- Shows status message - Updates transaction status (1=paid)
|
||||
- Display device connection button - Creates license in products_software_licenses
|
||||
- Updates equipment.sw_version_license
|
||||
↓
|
||||
[User clicks "Connect Device"]
|
||||
↓
|
||||
connectDeviceForSoftware()
|
||||
- User connects device (may be different device!)
|
||||
- Read SN, FW, HW from device
|
||||
↓
|
||||
checkSoftwareAvailability() → calls /v2/software_update
|
||||
- Existing license validation (lines 274-311) finds license
|
||||
- Paid upgrade now shows price = 0.00
|
||||
- Button text changes: "Purchase & Install" → "Install Now"
|
||||
↓
|
||||
[User clicks "Install Now"]
|
||||
↓
|
||||
selectUpgrade(option) → sees price = 0, skips payment modal
|
||||
↓
|
||||
downloadAndInstallSoftware()
|
||||
- CRITICAL: Verify serial number matches payment
|
||||
- If mismatch: Show warning but allow (license already applied)
|
||||
- Download firmware
|
||||
- Trigger upload.js
|
||||
```
|
||||
|
||||
### Key Design Decisions
|
||||
|
||||
**1. Leverage Existing License Logic**
|
||||
- No need to manually check licenses in frontend
|
||||
- `software_update.php` lines 274-311 already handle this perfectly
|
||||
- When license exists and is valid, price automatically becomes 0.00
|
||||
- Frontend just needs to check `if (price === 0)` to show different button
|
||||
|
||||
**2. Minimal State Management**
|
||||
- Store only essential data in `transactions` and `transactions_items`
|
||||
- URL parameters carry context back (payment_id)
|
||||
- No need to persist entire upgrade state
|
||||
- User reconnects device = fresh state from device
|
||||
|
||||
**3. Serial Number Verification**
|
||||
- Store `serial_number` in `transactions_items.item_options` JSON
|
||||
- After return, when user reconnects device, compare:
|
||||
- `serialnumber_from_payment` (from item_options JSON)
|
||||
- `deviceSerialNumber` (from connected device)
|
||||
- If mismatch: Show warning "Different device detected. License was applied to device SN: XXXXX"
|
||||
- Allow upload to proceed (license is already created for original SN)
|
||||
|
||||
**4. Separate Webhook for Software Upgrades**
|
||||
- Create new `webhook_mollie.php` based on structure from existing webhook.php
|
||||
- Specifically designed for software upgrade payments (no invoice generation needed)
|
||||
- Simplified logic: Just update transaction status and create license
|
||||
- Webhook URL: `https://site.com/webhook_mollie.php`
|
||||
- Webhook is authoritative for license creation
|
||||
- Return URL handler just shows status message
|
||||
- Race condition safe: user may see "payment successful" before webhook fires
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1: Database & Payment Infrastructure
|
||||
|
||||
**1.1 Database Table - No Changes Needed**
|
||||
```
|
||||
The existing transactions and transactions_items tables will be used.
|
||||
No schema modifications required.
|
||||
```
|
||||
|
||||
**1.2 Create `/api/v2/post/payment.php`**
|
||||
```php
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
// POST endpoint for payment creation
|
||||
// Input (JSON): serial_number, version_id, user_data (name, email, address)
|
||||
// Output (JSON): {checkout_url: "https://mollie.com/...", payment_id: "tr_xxx"}
|
||||
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//CONTENT FROM API (POST)
|
||||
$post_content = json_decode($input, true);
|
||||
|
||||
// SECURITY: Never trust price/currency from frontend!
|
||||
// Steps:
|
||||
1. Validate inputs (serial_number, version_id, user_data)
|
||||
2. SERVER-SIDE: Calculate actual price using software_update logic:
|
||||
a. Get equipment data from serial_number
|
||||
b. Get version data from version_id
|
||||
c. Check upgrade path pricing (same logic as software_update.php lines 237-253)
|
||||
d. Check license validity (same logic as software_update.php lines 274-311)
|
||||
e. Calculate FINAL price server-side
|
||||
3. Verify price > 0 (free upgrades shouldn't reach payment API)
|
||||
4. Call Mollie API FIRST to get payment_id:
|
||||
$mollie->payments->create([
|
||||
'amount' => ['currency' => 'EUR', 'value' => $final_price],
|
||||
'description' => 'Software upgrade to version X',
|
||||
'redirectUrl' => 'https://site.com/softwaretool.php?payment_return=1&payment_id={payment_id}',
|
||||
'webhookUrl' => 'https://site.com/webhook_mollie.php', // NEW webhook for software upgrades
|
||||
'metadata' => ['order_id' => $mollie_payment_id] // for compatibility
|
||||
])
|
||||
5. Store transaction in DB with Mollie payment_id:
|
||||
INSERT INTO transactions (txn_id, payment_amount, payment_status, payer_email, first_name, last_name, address_*, account_id, ...)
|
||||
VALUES ($mollie_payment_id, $final_price, 0, ...) -- 0 = pending
|
||||
6. Store transaction item:
|
||||
INSERT INTO transactions_items (txn_id, item_id, item_price, item_quantity, item_options, ...)
|
||||
VALUES ($mollie_payment_id, $version_id, $final_price, 1, '{"serial_number":"...", "equipment_id":...}', ...)
|
||||
7. Return JSON: {checkout_url: $mollie_checkout_url, payment_id: $mollie_payment_id}
|
||||
```
|
||||
|
||||
**1.3 Create `/api/v2/get/payment.php`**
|
||||
```php
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
// GET endpoint for payment status retrieval
|
||||
// Input (URL): ?payment_id=tr_xxx
|
||||
// Output (JSON): {payment_id, serial_number, version_id, payment_status, price, currency, user_data}
|
||||
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//NEW ARRAY
|
||||
$criterias = [];
|
||||
|
||||
//Check for $_GET variables
|
||||
if(isset($get_content) && $get_content!=''){
|
||||
$requests = explode("&", $get_content);
|
||||
foreach ($requests as $y){
|
||||
$v = explode("=", $y);
|
||||
$criterias[$v[0]] = $v[1];
|
||||
}
|
||||
}
|
||||
|
||||
// Steps:
|
||||
1. Validate payment_id from URL
|
||||
2. Fetch transaction: SELECT * FROM transactions WHERE txn_id = ?
|
||||
3. Fetch transaction item: SELECT * FROM transactions_items WHERE txn_id = ?
|
||||
4. Parse item_options JSON to get serial_number, equipment_id
|
||||
5. Return JSON with payment details:
|
||||
{
|
||||
"payment_id": txn_id,
|
||||
"payment_status": payment_status, // 0=pending, 1=paid, 2=failed, 3=canceled
|
||||
"payment_amount": payment_amount,
|
||||
"serial_number": from item_options JSON,
|
||||
"equipment_id": from item_options JSON,
|
||||
"version_id": item_id,
|
||||
"payer_email": payer_email,
|
||||
"customer_name": first_name + " " + last_name
|
||||
}
|
||||
6. If not found, return error
|
||||
```
|
||||
|
||||
**1.4 Create NEW `webhook_mollie.php`**
|
||||
```php
|
||||
<?php
|
||||
// NEW FILE - Webhook for software upgrade payments
|
||||
// Based on structure from existing webhook.php from commerce product
|
||||
// Uses existing transaction API + invoice API + email system
|
||||
|
||||
require_once 'assets/config.php';
|
||||
require_once 'assets/functions.php';
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//LOGIN TO API (same as commerce webhook.php)
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
$data = json_encode(array("clientID" => clientID, "clientsecret" => clientsecret), JSON_UNESCAPED_UNICODE);
|
||||
$responses = ioAPIv2('/v2/authorization', $data,'');
|
||||
//Decode Payload
|
||||
if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = '400';}
|
||||
$clientsecret = $responses['token'];
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// BASEURL is required for invoice template
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
$base_url = 'https://'.$_SERVER['SERVER_NAME'].'/';
|
||||
define('base_url', $base_url);
|
||||
|
||||
try {
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Initialize the Mollie API library
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
require "initialize.php"; // Mollie initialization (from commerce webhook)
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//Retrieve the payment's current state
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
$payment = $mollie->payments->get($_POST["id"]);
|
||||
$orderId = $payment->metadata->order_id;
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Update the transaction using existing API
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
if ($payment->isPaid() && !$payment->hasRefunds() && !$payment->hasChargebacks()) {
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// PAID - Update transaction status via API
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
$payload = json_encode(array("txn_id" => $orderId, "payment_status" => 1), JSON_UNESCAPED_UNICODE);
|
||||
$transaction = ioAPIv2('/v2/transactions/',$payload,$clientsecret);
|
||||
$transaction = json_decode($transaction,true);
|
||||
|
||||
if ($transaction !== null && !empty($transaction)) {
|
||||
if(count($transaction) > 0) {
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// CREATE LICENSE for software upgrade
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
// Fetch transaction items to find software upgrade
|
||||
$sql = 'SELECT * FROM transactions_items WHERE txn_id = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$orderId]);
|
||||
$items = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
foreach ($items as $item) {
|
||||
if (!empty($item['item_options'])) {
|
||||
$options = json_decode($item['item_options'], true);
|
||||
|
||||
// Check if this is a software upgrade (has serial_number and equipment_id)
|
||||
if (isset($options['serial_number']) && isset($options['equipment_id'])) {
|
||||
|
||||
// Check if license already exists for this transaction
|
||||
$sql = 'SELECT rowID FROM products_software_licenses WHERE transaction_id = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$orderId]);
|
||||
$existing_license = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$existing_license) {
|
||||
// Generate unique license key
|
||||
$license_key = generateUniqueLicenseKey();
|
||||
|
||||
// Create license
|
||||
$sql = 'INSERT INTO products_software_licenses
|
||||
(license_key, equipment_id, license_type, status, start_at, expires_at, transaction_id, created, createdby)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
$license_key,
|
||||
$options['equipment_id'],
|
||||
'upgrade',
|
||||
1, // active
|
||||
date('Y-m-d H:i:s'),
|
||||
'2099-12-31 23:59:59', // effectively permanent
|
||||
$orderId,
|
||||
date('Y-m-d H:i:s'),
|
||||
'webhook' // created by webhook
|
||||
]);
|
||||
|
||||
// Update equipment.sw_version_license
|
||||
$sql = 'UPDATE equipment SET sw_version_license = ? WHERE rowID = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$license_key, $options['equipment_id']]);
|
||||
|
||||
error_log("Webhook: License created for equipment_id: " . $options['equipment_id'] . ", license_key: " . $license_key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//Generate INVOICE RECORD via API
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
$payload = json_encode(array("txn_id" => $transaction['transaction_id']), JSON_UNESCAPED_UNICODE);
|
||||
$invoice = ioAPIv2('/v2/invoice/',$payload,$clientsecret);
|
||||
$invoice = json_decode($invoice,true);
|
||||
|
||||
if ($invoice !== null && !empty($invoice)) {
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//Generate INVOICE PDF and send email
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
$invoice_cust = ioAPIv2('/v2/invoice/list=invoice&id='.$invoice['invoice_id'],'',$clientsecret);
|
||||
$invoice_cust = json_decode($invoice_cust,true);
|
||||
|
||||
// Determine invoice language
|
||||
if (!empty($invoice_cust['customer']['language'])) {
|
||||
$invoice_language = strtoupper($invoice_cust['customer']['language']);
|
||||
} elseif (!empty($invoice_cust['customer']['country']) && isset($available_languages[strtoupper($invoice_cust['customer']['country'])])) {
|
||||
$invoice_language = $available_languages[strtoupper($invoice_cust['customer']['country'])];
|
||||
} else {
|
||||
$invoice_language = 'US'; // Default fallback
|
||||
}
|
||||
|
||||
// Generate invoice HTML (using custom template for software upgrades)
|
||||
list($data,$customer_email,$order_id) = generateSoftwareInvoice($invoice_cust,$orderId,$invoice_language);
|
||||
|
||||
//CREATE PDF using DomPDF
|
||||
$dompdf->loadHtml($data);
|
||||
$dompdf->setPaper('A4', 'portrait');
|
||||
$dompdf->render();
|
||||
$subject = ($invoice_software_subject ?? 'Software Upgrade - Invoice: ').$order_id;
|
||||
$attachment = $dompdf->output();
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//Send email via PHPMailer
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
send_mail_by_PHPMailer($customer_email, $subject, $data, $attachment, $subject);
|
||||
|
||||
if(invoice_bookkeeping){
|
||||
send_mail_by_PHPMailer(email_bookkeeping, $subject, $data, $attachment, $subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} elseif ($payment->isOpen()) {
|
||||
// OPEN/PENDING (101)
|
||||
$payload = json_encode(array("txn_id" => $orderId, "payment_status" => 101), JSON_UNESCAPED_UNICODE);
|
||||
$transaction = ioAPIv2('/v2/transactions/',$payload,$clientsecret);
|
||||
|
||||
} elseif ($payment->isPending()) {
|
||||
// PENDING (101)
|
||||
$payload = json_encode(array("txn_id" => $orderId, "payment_status" => 101), JSON_UNESCAPED_UNICODE);
|
||||
$transaction = ioAPIv2('/v2/transactions/',$payload,$clientsecret);
|
||||
|
||||
} elseif ($payment->isFailed()) {
|
||||
// FAILED (102)
|
||||
$payload = json_encode(array("txn_id" => $orderId, "payment_status" => 102), JSON_UNESCAPED_UNICODE);
|
||||
$transaction = ioAPIv2('/v2/transactions/',$payload,$clientsecret);
|
||||
|
||||
} elseif ($payment->isExpired()) {
|
||||
// EXPIRED (103)
|
||||
$payload = json_encode(array("txn_id" => $orderId, "payment_status" => 103), JSON_UNESCAPED_UNICODE);
|
||||
$transaction = ioAPIv2('/v2/transactions/',$payload,$clientsecret);
|
||||
|
||||
} elseif ($payment->isCanceled()) {
|
||||
// CANCELED (999)
|
||||
$payload = json_encode(array("txn_id" => $orderId, "payment_status" => 999), JSON_UNESCAPED_UNICODE);
|
||||
$transaction = ioAPIv2('/v2/transactions/',$payload,$clientsecret);
|
||||
|
||||
} elseif ($payment->hasRefunds()) {
|
||||
// REFUNDED (1 + refund flag)
|
||||
$payload = json_encode(array("txn_id" => $orderId, "payment_status" => 1), JSON_UNESCAPED_UNICODE);
|
||||
$transaction = ioAPIv2('/v2/transactions/',$payload,$clientsecret);
|
||||
// TODO: Disable license on refund
|
||||
}
|
||||
|
||||
} catch (\Mollie\Api\Exceptions\ApiException $e) {
|
||||
error_log("Webhook API call failed: " . htmlspecialchars($e->getMessage()));
|
||||
http_response_code(500);
|
||||
echo "API call failed: " . htmlspecialchars($e->getMessage());
|
||||
} catch (Exception $e) {
|
||||
error_log("Webhook error: " . htmlspecialchars($e->getMessage()));
|
||||
http_response_code(500);
|
||||
}
|
||||
```
|
||||
|
||||
**Key Features (matching commerce webhook.php):**
|
||||
- ✅ Uses `/v2/transactions/` API for status updates
|
||||
- ✅ Uses `/v2/invoice/` API for invoice generation
|
||||
- ✅ Generates PDF invoice with DomPDF
|
||||
- ✅ Sends email via PHPMailer
|
||||
- ✅ Creates license for software upgrade
|
||||
- ✅ Uses same payment status codes (0, 1, 101, 102, 103, 999)
|
||||
- ✅ Handles refunds (TODO: disable license)
|
||||
- ✅ Multi-language invoice support
|
||||
- ✅ Sends to bookkeeping if configured
|
||||
|
||||
### Phase 2: Frontend Integration
|
||||
|
||||
**2.1 Modify `processPayment()` in softwaretool.js (lines 574-608)**
|
||||
```javascript
|
||||
async function processPayment(paymentData, option, modal) {
|
||||
try {
|
||||
progressBar("10", "Processing payment...", "#04AA6D");
|
||||
|
||||
// SECURITY: Only send serial_number and version_id
|
||||
// Server will calculate the price to prevent tampering
|
||||
const response = await fetch(link + "/v2/post/payment", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": "Bearer " + document.getElementById("servicetoken").textContent
|
||||
},
|
||||
body: JSON.stringify({
|
||||
serial_number: deviceSerialNumber,
|
||||
version_id: option.version_id,
|
||||
user_data: paymentData // name, email, address only
|
||||
// REMOVED: price, currency - server calculates these
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
if (result.checkout_url) {
|
||||
await logCommunication(`Redirecting to payment provider`, 'sent');
|
||||
// Redirect to Mollie checkout
|
||||
window.location.href = result.checkout_url;
|
||||
} else {
|
||||
throw new Error(result.error || "Failed to create payment");
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
await logCommunication(`Payment error: ${error.message}`, 'error');
|
||||
progressBar("0", "Payment failed: " + error.message, "#ff6666");
|
||||
alert("Payment failed: " + error.message);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**2.2 Remove equipment_id tracking - NOT NEEDED**
|
||||
```javascript
|
||||
// SECURITY: We don't need to track equipment_id in frontend
|
||||
// The server will look it up from serial_number in the payment/create API
|
||||
// This prevents tampering with equipment_id
|
||||
```
|
||||
|
||||
**2.3 Add Serial Number Verification in `downloadAndInstallSoftware()` (lines 610-699)**
|
||||
```javascript
|
||||
async function downloadAndInstallSoftware(option) {
|
||||
// Check if we're returning from payment
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const paymentId = urlParams.get('payment_id');
|
||||
|
||||
if (paymentId) {
|
||||
// Verify serial number matches payment using GET /v2/get/payment
|
||||
const response = await fetch(link + `/v2/get/payment?payment_id=${paymentId}`, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Authorization": "Bearer " + document.getElementById("servicetoken").textContent
|
||||
}
|
||||
});
|
||||
|
||||
const paymentData = await response.json();
|
||||
|
||||
if (paymentData.serial_number !== deviceSerialNumber) {
|
||||
const confirmed = confirm(
|
||||
`WARNING: Different device detected!\n\n` +
|
||||
`License was created for device: ${paymentData.serial_number}\n` +
|
||||
`Currently connected device: ${deviceSerialNumber}\n\n` +
|
||||
`The license is already applied to the original device. ` +
|
||||
`Do you want to continue with this device anyway?`
|
||||
);
|
||||
|
||||
if (!confirmed) {
|
||||
progressBar("0", "Upload canceled by user", "#ff6666");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Continue with existing download logic...
|
||||
selectedSoftwareUrl = option.source;
|
||||
// ... rest of function unchanged
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: Serial number verification uses existing GET /v2/get/payment endpoint (no separate verify endpoint needed)
|
||||
|
||||
### Phase 3: Return URL Handling
|
||||
|
||||
**3.1 Modify `softwaretool.php` to detect return from payment**
|
||||
```php
|
||||
// Add near top of softwaretool.php (after includes, before $view)
|
||||
<?php
|
||||
$payment_return = isset($_GET['payment_id']) ? $_GET['payment_id'] : null;
|
||||
|
||||
if ($payment_return) {
|
||||
// Optionally fetch payment status via GET /v2/get/payment
|
||||
// and show appropriate message banner at top of page
|
||||
// "Payment successful! Please reconnect your device to continue."
|
||||
// User will then click "Connect Device" button
|
||||
// After connection, checkSoftwareAvailability() will run
|
||||
// License will be found via existing logic, price will be 0.00
|
||||
}
|
||||
?>
|
||||
```
|
||||
|
||||
**3.2 Optional: Auto-trigger device connection after payment return**
|
||||
```javascript
|
||||
// In softwaretool.js, check URL on page load
|
||||
window.addEventListener('DOMContentLoaded', function() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.has('payment_id')) {
|
||||
// Show message: "Payment successful! Please reconnect your device."
|
||||
// Optionally auto-show device connection UI
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Phase 4: Testing Strategy
|
||||
|
||||
**4.1 DEBUG Mode Testing (Complete Simulation)**
|
||||
```php
|
||||
// In /api/v2/post/payment.php, check if DEBUG mode
|
||||
if (defined('debug') && debug) {
|
||||
// FULL SIMULATION: No Mollie API connection, no device connection
|
||||
$fake_payment_id = 'DEBUG_' . uniqid();
|
||||
|
||||
// 1. Store transaction with status 0 (pending)
|
||||
$sql = 'INSERT INTO transactions
|
||||
(txn_id, payment_amount, payment_status, payer_email, first_name, last_name,
|
||||
address_street, address_city, address_state, address_zip, address_country, account_id)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
$fake_payment_id,
|
||||
$final_price,
|
||||
0, // 0 = pending
|
||||
$post_content['user_data']['email'],
|
||||
$post_content['user_data']['first_name'] ?? '',
|
||||
$post_content['user_data']['last_name'] ?? '',
|
||||
$post_content['user_data']['address_street'] ?? '',
|
||||
$post_content['user_data']['address_city'] ?? '',
|
||||
$post_content['user_data']['address_state'] ?? '',
|
||||
$post_content['user_data']['address_zip'] ?? '',
|
||||
$post_content['user_data']['address_country'] ?? '',
|
||||
$post_content['serial_number'] // store serial number in account_id
|
||||
]);
|
||||
|
||||
// 2. Store transaction item
|
||||
$item_options = json_encode([
|
||||
'serial_number' => $post_content['serial_number'],
|
||||
'equipment_id' => $equipment_id,
|
||||
'hw_version' => $hw_version
|
||||
]);
|
||||
$sql = 'INSERT INTO transactions_items
|
||||
(txn_id, item_id, item_price, item_quantity, item_options)
|
||||
VALUES (?, ?, ?, ?, ?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
$fake_payment_id,
|
||||
$post_content['version_id'],
|
||||
$final_price,
|
||||
1,
|
||||
$item_options
|
||||
]);
|
||||
|
||||
// 3. Immediately simulate webhook success (update status to paid + create license)
|
||||
$sql = 'UPDATE transactions SET payment_status = 1 WHERE txn_id = ?'; // 1 = paid
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$fake_payment_id]);
|
||||
|
||||
// 4. Create license
|
||||
$license_key = generateUniqueLicenseKey();
|
||||
$sql = 'INSERT INTO products_software_licenses
|
||||
(license_key, equipment_id, license_type, status, start_at, expires_at, transaction_id, created, createdby)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
$license_key,
|
||||
$equipment_id,
|
||||
'upgrade',
|
||||
1,
|
||||
date('Y-m-d H:i:s'),
|
||||
'2099-12-31 23:59:59',
|
||||
$fake_payment_id,
|
||||
date('Y-m-d H:i:s'),
|
||||
$username
|
||||
]);
|
||||
|
||||
// 5. Update equipment.sw_version_license
|
||||
$sql = 'UPDATE equipment SET sw_version_license = ? WHERE rowID = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$license_key, $equipment_id]);
|
||||
|
||||
// 6. Return fake checkout URL that redirects immediately
|
||||
$messages = [
|
||||
'checkout_url' => 'https://'.$_SERVER['SERVER_NAME'].'/softwaretool.php?payment_return=1&payment_id=' . $fake_payment_id,
|
||||
'payment_id' => $fake_payment_id
|
||||
];
|
||||
echo json_encode($messages);
|
||||
exit;
|
||||
}
|
||||
```
|
||||
|
||||
**Note**: In DEBUG mode, the entire payment + license creation flow is simulated without:
|
||||
- Calling Mollie API
|
||||
- Requiring physical device connection (works with DEBUG mode mock device data in softwaretool.js)
|
||||
|
||||
**4.2 Mollie Sandbox Testing**
|
||||
1. Use Mollie test API key
|
||||
2. Test successful payment flow
|
||||
3. Test failed payment flow
|
||||
4. Test canceled payment flow
|
||||
5. Test webhook delivery
|
||||
6. Test license creation
|
||||
|
||||
**4.3 Serial Number Mismatch Testing**
|
||||
1. Complete payment with device A (SN: 22110095)
|
||||
2. Disconnect device A
|
||||
3. Connect device B (different SN)
|
||||
4. Verify warning appears
|
||||
5. Verify license was created for device A
|
||||
|
||||
---
|
||||
|
||||
## Critical Files to Modify
|
||||
|
||||
### New Files
|
||||
- `/api/v2/post/payment.php` - Payment creation (POST)
|
||||
- `/api/v2/get/payment.php` - Payment status retrieval (GET)
|
||||
- `/webhook_mollie.php` - Mollie webhook handler for software upgrades (based on existing webhook.php structure)
|
||||
- `generateSoftwareInvoice()` function in `/assets/functions.php` - Invoice template for software upgrades
|
||||
|
||||
### Modified Files
|
||||
- `/assets/softwaretool.js`:
|
||||
- `processPayment()` (lines 574-608) - Call POST /v2/post/payment instead of simulation
|
||||
- `downloadAndInstallSoftware()` (lines 610-699) - Add serial number verification using GET /v2/get/payment
|
||||
- Add payment return detection on page load (optional)
|
||||
- `/softwaretool.php`:
|
||||
- Add payment return URL detection (check for ?payment_id=X)
|
||||
- Optionally show success message banner after payment
|
||||
- `/api/v2/get/software_update.php`:
|
||||
- **No changes needed** (existing license logic at lines 274-311 works perfectly!)
|
||||
|
||||
### Database & Helper Functions
|
||||
- No new tables needed (using existing `transactions` and `transactions_items`)
|
||||
- Add helper function `generateUniqueLicenseKey()` in `assets/functions.php`
|
||||
- Payment status codes already defined in existing webhook.php (0, 1, 101, 102, 103, 999)
|
||||
|
||||
---
|
||||
|
||||
## Security Architecture Summary
|
||||
|
||||
### ✅ **SECURE APPROACH: Server-Side Price Validation**
|
||||
|
||||
**Frontend sends:**
|
||||
- `serial_number` (from connected device)
|
||||
- `version_id` (which version they want)
|
||||
- `user_data` (name, email, address)
|
||||
|
||||
**Backend does:**
|
||||
1. Look up equipment from `serial_number`
|
||||
2. Look up version from `version_id`
|
||||
3. **Calculate actual price using same logic as software_update.php**:
|
||||
- Check upgrade path pricing (lines 244-260)
|
||||
- Check if license exists and reduces price (lines 274-311)
|
||||
- Get final server-calculated price
|
||||
4. Verify price > 0 (reject free upgrades)
|
||||
5. Create Mollie payment with **SERVER-CALCULATED price**
|
||||
6. Store pending payment with correct price
|
||||
|
||||
### ❌ **INSECURE APPROACH: Never Do This**
|
||||
```javascript
|
||||
// WRONG - User can modify price in browser console!
|
||||
body: JSON.stringify({
|
||||
serial_number: deviceSerialNumber,
|
||||
version_id: option.version_id,
|
||||
price: 0.01, // <-- Tampered from 49.99!
|
||||
currency: "EUR"
|
||||
})
|
||||
```
|
||||
|
||||
**Why this is dangerous:**
|
||||
- User can open browser console
|
||||
- Change `option.price = 0.01` before payment
|
||||
- Backend trusts this value = user pays 1 cent for €49.99 upgrade
|
||||
|
||||
### ✅ **CORRECT APPROACH**
|
||||
```javascript
|
||||
// SECURE - Only send identifiers, server calculates price
|
||||
body: JSON.stringify({
|
||||
serial_number: deviceSerialNumber, // Who is buying
|
||||
version_id: option.version_id, // What they want
|
||||
user_data: paymentData // Customer info
|
||||
// NO PRICE - server calculates it!
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Configuration & Requirements (USER CONFIRMED)
|
||||
|
||||
1. ✅ **Mollie API Credentials**: User has Mollie info - will be added as constants in `config.php`
|
||||
- `MOLLIE_API_KEY_TEST` (for sandbox)
|
||||
- `MOLLIE_API_KEY_LIVE` (for production)
|
||||
2. ✅ **License Duration**: `expires_at = '2099-12-31 23:59:59'` (effectively permanent until 2099)
|
||||
3. ✅ **Multiple Devices**: One license per device (license linked to specific equipment_id)
|
||||
4. ✅ **DEBUG Mode**: Full payment process simulation without Mollie connection AND without device connection
|
||||
5. ✅ **Transaction Logging**: Use existing ecommerce transaction APIs:
|
||||
- `transactions` table - main transaction record
|
||||
- `transaction_items` table - line items (software upgrade details)
|
||||
|
||||
---
|
||||
|
||||
## Next Steps After Plan Approval
|
||||
|
||||
1. ✅ Add Mollie constants to `config.php`:
|
||||
```php
|
||||
define('MOLLIE_API_KEY_TEST', 'test_xxxxx'); // User will provide
|
||||
define('MOLLIE_API_KEY_LIVE', 'live_xxxxx'); // User will provide
|
||||
```
|
||||
2. ✅ Mollie PHP SDK already installed (used by existing webhook.php)
|
||||
3. ✅ No database changes needed (using existing `transactions` and `transactions_items` tables)
|
||||
4. Create helper functions in `assets/functions.php`:
|
||||
- `generateUniqueLicenseKey()` - Generate unique license keys
|
||||
- `generateSoftwareInvoice()` - Generate HTML invoice for software upgrades (based on existing generateInvoice())
|
||||
5. ✅ Payment status codes already defined in existing webhook.php
|
||||
6. Implement NEW backend files:
|
||||
- `/api/v2/post/payment.php` (with DEBUG mode support)
|
||||
- `/api/v2/get/payment.php`
|
||||
- `/webhook_mollie.php` (based on existing webhook.php structure)
|
||||
8. Modify frontend JavaScript in `/assets/softwaretool.js`:
|
||||
- Update `processPayment()` to call POST /v2/post/payment
|
||||
- Add serial number verification in `downloadAndInstallSoftware()`
|
||||
9. Modify `/softwaretool.php` to detect payment return
|
||||
10. Test in DEBUG mode (full simulation without Mollie or device)
|
||||
11. Test with Mollie sandbox
|
||||
12. Deploy to production
|
||||
|
||||
188
access_element.php
Normal file
188
access_element.php
Normal file
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
}
|
||||
|
||||
include_once './assets/functions.php';
|
||||
include_once './settings/settings_redirector.php';
|
||||
|
||||
//SET ORIGIN FOR NAVIGATION
|
||||
$_SESSION['prev_origin_access_element'] = $_SERVER['REQUEST_URI'];
|
||||
$page = 'access_element';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$page_manage = 'access_element_manage';
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$update_allowed_edit = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
//GET Details from URL
|
||||
$GET_VALUES = urlGETdetails($_GET) ?? '';
|
||||
|
||||
//CALL TO API FOR General information
|
||||
$api_url = '/v2/access_elements/'.$GET_VALUES;
|
||||
$responses = ioServer($api_url,'');
|
||||
//Decode Payload
|
||||
if (!empty($responses)){$responses = json_decode($responses);}else{$responses = null;}
|
||||
$responses = $responses[0];
|
||||
|
||||
$element_id = $responses->rowID;
|
||||
|
||||
//CALL TO API FOR Roles using this access element
|
||||
$api_url = '/v2/role_access_permissions/access_id='.$element_id;
|
||||
$role_permissions = ioServer($api_url,'');
|
||||
//Decode Payload
|
||||
if (!empty($role_permissions)){$role_permissions = json_decode($role_permissions);}else{$role_permissions = null;}
|
||||
|
||||
//------------------------------
|
||||
//Variables
|
||||
//------------------------------
|
||||
$status_text = ($responses->is_active == 1) ? ($enabled ?? 'Active') : ($disabled ?? 'Inactive');
|
||||
$status_class = ($responses->is_active == 1) ? 'id1' : 'id0';
|
||||
|
||||
// Handle success messages
|
||||
if (isset($_GET['success_msg'])) {
|
||||
if ($_GET['success_msg'] == 1) {
|
||||
$success_msg = ($message_access_1 ?? 'Access element created successfully');
|
||||
}
|
||||
if ($_GET['success_msg'] == 2) {
|
||||
$success_msg = ($message_access_2 ?? 'Access element updated successfully');
|
||||
}
|
||||
if ($_GET['success_msg'] == 3) {
|
||||
$success_msg = ($message_access_3 ?? 'Access element deleted successfully');
|
||||
}
|
||||
}
|
||||
|
||||
template_header(($access_element_title ?? 'Access Element'), 'access_element', 'view');
|
||||
$view = '
|
||||
<div class="content-title responsive-flex-wrap responsive-pad-bot-3">
|
||||
<h2 class="responsive-width-100">'.($view_access_h2 ?? 'Access Element').' - '.$responses->access_name.'</h2>
|
||||
<a href="index.php?page='.$_SESSION['origin'].'&p='.$_SESSION['p'].$_SESSION['status'].$_SESSION['sort'].$_SESSION['search'].'" class="btn alt mar-right-2">←</a>
|
||||
';
|
||||
|
||||
if ($update_allowed_edit === 1){
|
||||
$view .= '<a href="index.php?page=access_element_manage&rowID='.$responses->rowID.'" class="btn">✏️</a>';
|
||||
}
|
||||
|
||||
$view .= '</div>';
|
||||
|
||||
if (isset($success_msg)){
|
||||
$view .= ' <div class="msg success">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
<p>'.$success_msg.'</p>
|
||||
<i class="fas fa-times"></i>
|
||||
</div>';
|
||||
}
|
||||
|
||||
$view .= '<div class="content-block-wrapper">';
|
||||
|
||||
// Access Element Information Block
|
||||
$view .= ' <div class="content-block order-details">
|
||||
<div class="block-header">
|
||||
<i class="fa-solid fa-circle-info"></i>'.($view_access_information ?? 'Access Element Information').'
|
||||
</div>
|
||||
<div class="order-detail">
|
||||
<h3>'.($general_status ?? 'Status').'</h3>
|
||||
<p><span class="status '.$status_class.'">'.$status_text.'</span></p>
|
||||
</div>
|
||||
<div class="order-detail">
|
||||
<h3>'.($access_element_name ?? 'Name').'</h3>
|
||||
<p>'.$responses->access_name.'</p>
|
||||
</div>
|
||||
<div class="order-detail">
|
||||
<h3>'.($access_element_path ?? 'Path').'</h3>
|
||||
<p>'.$responses->access_path.'</p>
|
||||
</div>
|
||||
<div class="order-detail">
|
||||
<h3>'.($access_element_group ?? 'Group').'</h3>
|
||||
<p>'.($responses->access_group ?? '-').'</p>
|
||||
</div>
|
||||
<div class="order-detail">
|
||||
<h3>'.($role_description ?? 'Description').'</h3>
|
||||
<p>'.($responses->description ?? '-').'</p>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
|
||||
$view .= '</div>'; // Close content-block-wrapper
|
||||
|
||||
// Roles Using This Access Element
|
||||
$view .= '<div class="content-block">
|
||||
<div class="block-header">
|
||||
<i class="fa-solid fa-user-shield fa-sm"></i>'.($view_access_roles ?? 'Roles Using This Element').'
|
||||
</div>
|
||||
<div class="table">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>'.($role_name ?? 'Role Name').'</th>
|
||||
<th>'.($permission_create ?? 'C').'</th>
|
||||
<th>'.($permission_read ?? 'R').'</th>
|
||||
<th>'.($permission_update ?? 'U').'</th>
|
||||
<th>'.($permission_delete ?? 'D').'</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
|
||||
if (!empty($role_permissions)){
|
||||
foreach ($role_permissions as $role_perm){
|
||||
$can_create = ($role_perm->can_create == 1) ? '<i class="fa-solid fa-check" style="color:green;"></i>' : '<i class="fa-solid fa-times" style="color:red;"></i>';
|
||||
$can_read = ($role_perm->can_read == 1) ? '<i class="fa-solid fa-check" style="color:green;"></i>' : '<i class="fa-solid fa-times" style="color:red;"></i>';
|
||||
$can_update = ($role_perm->can_update == 1) ? '<i class="fa-solid fa-check" style="color:green;"></i>' : '<i class="fa-solid fa-times" style="color:red;"></i>';
|
||||
$can_delete = ($role_perm->can_delete == 1) ? '<i class="fa-solid fa-check" style="color:green;"></i>' : '<i class="fa-solid fa-times" style="color:red;"></i>';
|
||||
|
||||
$view .= '<tr onclick="window.location.href=\'index.php?page=user_role&rowID='.$role_perm->role_id.'\'" style="cursor: pointer;">
|
||||
<td>'.$role_perm->role_name.'</td>
|
||||
<td>'.$can_create.'</td>
|
||||
<td>'.$can_read.'</td>
|
||||
<td>'.$can_update.'</td>
|
||||
<td>'.$can_delete.'</td>
|
||||
</tr>';
|
||||
}
|
||||
} else {
|
||||
$view .= '<tr>
|
||||
<td colspan="5" style="text-align:center;">'.($no_roles_using ?? 'No roles are using this access element').'</td>
|
||||
</tr>';
|
||||
}
|
||||
|
||||
$view .= ' </tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
|
||||
// Metadata Block
|
||||
$view .= '<div class="content-block">
|
||||
<div class="block-header">
|
||||
<i class="fa-solid fa-bars fa-sm"></i>'.($tab3 ?? 'Details').'
|
||||
</div>
|
||||
<div class="table order-table">
|
||||
<table>
|
||||
<tr>
|
||||
<td style="width:25%;">'.($general_created ?? 'Created').'</td>
|
||||
<td>'.getRelativeTime($responses->created).'</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="width:25%;">'.($general_updated ?? 'Updated').'</td>
|
||||
<td>'.getRelativeTime($responses->updated).'</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
|
||||
//OUTPUT
|
||||
echo $view;
|
||||
|
||||
template_footer()
|
||||
|
||||
?>
|
||||
168
access_element_manage.php
Normal file
168
access_element_manage.php
Normal file
@@ -0,0 +1,168 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
}
|
||||
|
||||
include_once './assets/functions.php';
|
||||
include_once './settings/settings_redirector.php';
|
||||
|
||||
$page = 'access_element_manage';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
// Default input values
|
||||
$element = [
|
||||
'rowID' => '',
|
||||
'access_name' => '',
|
||||
'access_path' => '',
|
||||
'access_group' => '',
|
||||
'description' => '',
|
||||
'is_active' => 1,
|
||||
'created' => '',
|
||||
'createdby' => $_SESSION['authorization']['clientID'],
|
||||
'updated' => '',
|
||||
'updatedby' => ''
|
||||
];
|
||||
|
||||
$element_ID = $_GET['rowID'] ?? '';
|
||||
|
||||
if ($element_ID !=''){
|
||||
$url = 'index.php?page=access_element&rowID='.$element_ID.'';
|
||||
} else {
|
||||
$url = 'index.php?page=access_elements';
|
||||
}
|
||||
|
||||
if (isset($_GET['rowID'])) {
|
||||
// ID param exists, edit an existing element
|
||||
//CALL TO API
|
||||
$api_url = '/v2/access_elements/rowID='.$element_ID;
|
||||
$responses = ioServer($api_url,'');
|
||||
//Decode Payload
|
||||
if (!empty($responses)){$responses = json_decode($responses,true);}else{$responses = null;}
|
||||
|
||||
$element = $responses[0];
|
||||
|
||||
if ($update_allowed === 1){
|
||||
if (isset($_POST['submit'])) {
|
||||
//GET ALL POST DATA
|
||||
$data = json_encode($_POST, JSON_UNESCAPED_UNICODE);
|
||||
//API call
|
||||
$responses = ioServer('/v2/access_elements', $data);
|
||||
|
||||
if ($responses === 'NOK'){
|
||||
|
||||
} else {
|
||||
header('Location: index.php?page=access_element&rowID='.$element_ID.'&success_msg=2');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($delete_allowed === 1){
|
||||
if (isset($_POST['delete'])) {
|
||||
//GET ALL POST DATA
|
||||
$data = json_encode($_POST , JSON_UNESCAPED_UNICODE);
|
||||
//API call
|
||||
$responses = ioServer('/v2/access_elements', $data);
|
||||
// Redirect and delete element
|
||||
if ($responses === 'NOK'){
|
||||
|
||||
} else {
|
||||
header('Location: index.php?page=access_elements&success_msg=3');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Create a new element
|
||||
if (isset($_POST['submit']) && $create_allowed === 1) {
|
||||
//GET ALL POST DATA
|
||||
$data = json_encode($_POST, JSON_UNESCAPED_UNICODE);
|
||||
//API call
|
||||
$responses = ioServer('/v2/access_elements', $data);
|
||||
if ($responses === 'NOK'){
|
||||
|
||||
} else {
|
||||
header('Location: index.php?page=access_elements&success_msg=1');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template_header(($access_element_title ?? 'Access Element'), 'access_element', 'manage');
|
||||
|
||||
$label_h2 = (($element_ID !='')? ($manage_access_h2 ?? 'Edit Access Element') : ($button_create_access ?? 'Create Access Element'));
|
||||
$view ='
|
||||
<form action="" method="post">
|
||||
<div class="content-title responsive-flex-wrap responsive-pad-bot-3">
|
||||
<h2 class="responsive-width-100">'.$label_h2.'</h2>
|
||||
<a href="'.$url.'" class="btn alt mar-right-2">←</a>
|
||||
';
|
||||
|
||||
if ($delete_allowed === 1 && $element_ID != ''){
|
||||
$view .= '<input type="submit" name="delete" value="X" class="btn red mar-right-2" onclick="return confirm(\''.($confirm_delete_access ?? 'Are you sure you want to delete this access element?').'\')">';
|
||||
}
|
||||
if ($update_allowed === 1 || ($create_allowed === 1 && $element_ID == '')){
|
||||
$view .= '<input type="submit" name="submit" value="💾" class="btn">';
|
||||
}
|
||||
|
||||
$view .= '</div>';
|
||||
|
||||
$view .= '<div class="tabs">
|
||||
<a href="#" class="active">'.($tab1 ?? 'General').'</a>
|
||||
</div>
|
||||
<div class="content-block tab-content active">
|
||||
<div class="form responsive-width-100">
|
||||
<label for="is_active">'.($general_status ?? 'Status').'</label>
|
||||
<select id="is_active" name="is_active">
|
||||
<option value="1" '.($element['is_active']==1?' selected':'').'>'.($enabled ?? 'Active').'</option>
|
||||
<option value="0" '.($element['is_active']==0?' selected':'').'>'.($disabled ?? 'Inactive').'</option>
|
||||
</select>
|
||||
<label for="access_name">'.($access_element_name ?? 'Name').' <i class="required">*</i></label>
|
||||
<input id="access_name" type="text" name="access_name" placeholder="'.($access_element_name ?? 'Name').'" value="'.$element['access_name'].'" required>
|
||||
<label for="access_path">'.($access_element_path ?? 'Path').' <i class="required">*</i></label>
|
||||
<input id="access_path" type="text" name="access_path" placeholder="'.($access_element_path_placeholder ?? 'e.g., equipments, equipment_manage').'" value="'.$element['access_path'].'" required>
|
||||
<label for="access_group">'.($access_element_group ?? 'Group').'</label>
|
||||
<input id="access_group" type="text" name="access_group" placeholder="'.($access_element_group_placeholder ?? 'e.g., Views, API, Admin').'" value="'.($element['access_group'] ?? '').'">
|
||||
<label for="description">'.($role_description ?? 'Description').'</label>
|
||||
<textarea id="description" name="description" placeholder="'.($role_description ?? 'Description').'" style="height: 100px;">'.$element['description'].'</textarea>
|
||||
<input type="hidden" name="rowID" value="'.$element_ID.'">
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
//DISPLAY TAB 2 - Metadata
|
||||
if ($element_ID != ''){
|
||||
$view .= '<div class="tabs">
|
||||
<a href="#">'.($tab3 ?? 'Details').'</a>
|
||||
</div>
|
||||
<div class="content-block tab-content">
|
||||
<div class="form responsive-width-100">
|
||||
<label for="created">'.($general_created ?? 'Created').'</label>
|
||||
<input id="created" type="text" name="" placeholder="'.($general_created ?? 'Created').'" value="'.$element['created'].'" readonly>
|
||||
<label for="createdby">'.($general_createdby ?? 'Created By').'</label>
|
||||
<input id="createdby" type="text" name="" placeholder="'.($general_createdby ?? 'Created By').'" value="'.$element['createdby'].'" readonly>
|
||||
<label for="updated">'.($general_updated ?? 'Updated').'</label>
|
||||
<input id="updated" type="text" name="" placeholder="'.($general_updated ?? 'Updated').'" value="'.$element['updated'].'" readonly>
|
||||
<label for="updatedby">'.($general_updatedby ?? 'Updated By').'</label>
|
||||
<input id="updatedby" type="text" name="" placeholder="'.($general_updatedby ?? 'Updated By').'" value="'.$element['updatedby'].'" readonly>
|
||||
</div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
$view .= '</form>';
|
||||
|
||||
//Output
|
||||
echo $view;
|
||||
template_footer()?>
|
||||
317
access_elements.php
Normal file
317
access_elements.php
Normal file
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
}
|
||||
include_once './assets/functions.php';
|
||||
include_once './settings/settings_redirector.php';
|
||||
|
||||
//SET PAGE ORIGIN FOR NAVIGATION AND SECURITY
|
||||
$prev_page = $_SESSION['prev_origin'] ?? '';
|
||||
$page = $_SESSION['origin'] = 'access_elements';
|
||||
|
||||
//create backbutton to prev_origin
|
||||
$back_btn_orgin = ($prev_page != '')? '<a href="'.$prev_page.'" class="btn alt mar-right-2">←</a>':'';
|
||||
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$page_manage = 'access_element_manage';
|
||||
$update_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
// Function to scan project for new PHP files and add to access_elements
|
||||
function scan_and_update_access_elements() {
|
||||
$new_elements = [];
|
||||
$base_path = dirname(__FILE__);
|
||||
|
||||
// Scan root PHP files (excluding index, login, logout)
|
||||
$root_files = glob($base_path . '/*.php');
|
||||
foreach ($root_files as $file) {
|
||||
$filename = basename($file, '.php');
|
||||
if (!in_array($filename, ['index', 'login', 'logout'])) {
|
||||
// Only add if not already in array (first occurrence wins)
|
||||
if (!isset($new_elements[$filename])) {
|
||||
$new_elements[$filename] = [
|
||||
'name' => ucwords(str_replace('_', ' ', $filename)),
|
||||
'path' => $filename,
|
||||
'group' => 'Views',
|
||||
'description' => 'Auto-scanned: ' . $filename
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scan API v2 get folder - only add if not already found in root
|
||||
$get_files = glob($base_path . '/api/v2/get/*.php');
|
||||
foreach ($get_files as $file) {
|
||||
$filename = basename($file, '.php');
|
||||
if (!isset($new_elements[$filename])) {
|
||||
$new_elements[$filename] = [
|
||||
'name' => ucwords(str_replace('_', ' ', $filename)),
|
||||
'path' => $filename,
|
||||
'group' => 'API',
|
||||
'description' => 'Auto-scanned: ' . $filename
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Scan API v2 post folder - only add if not already found
|
||||
$post_files = glob($base_path . '/api/v2/post/*.php');
|
||||
foreach ($post_files as $file) {
|
||||
$filename = basename($file, '.php');
|
||||
if (!isset($new_elements[$filename])) {
|
||||
$new_elements[$filename] = [
|
||||
'name' => ucwords(str_replace('_', ' ', $filename)),
|
||||
'path' => $filename,
|
||||
'group' => 'API',
|
||||
'description' => 'Auto-scanned: ' . $filename
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Get existing access elements from API
|
||||
$api_url = '/v2/access_elements/';
|
||||
$existing = ioServer($api_url, '');
|
||||
$existing_paths = [];
|
||||
if (!empty($existing)) {
|
||||
$existing_data = json_decode($existing);
|
||||
foreach ($existing_data as $element) {
|
||||
$existing_paths[] = $element->access_path;
|
||||
}
|
||||
}
|
||||
|
||||
// Filter out elements that already exist
|
||||
$elements_to_add = [];
|
||||
foreach ($new_elements as $path => $element) {
|
||||
if (!in_array($path, $existing_paths)) {
|
||||
$elements_to_add[] = $element;
|
||||
}
|
||||
}
|
||||
|
||||
// Add new elements via API
|
||||
$added_count = 0;
|
||||
foreach ($elements_to_add as $element) {
|
||||
$data = json_encode([
|
||||
'access_name' => $element['name'],
|
||||
'access_path' => $element['path'],
|
||||
'access_group' => $element['group'],
|
||||
'description' => $element['description'],
|
||||
'is_active' => 1
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$response = ioServer('/v2/access_elements', $data);
|
||||
if ($response !== 'NOK') {
|
||||
$added_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return $added_count;
|
||||
}
|
||||
|
||||
// Handle scan request
|
||||
if (isset($_POST['scan_elements']) && $create_allowed === 1) {
|
||||
$added_count = scan_and_update_access_elements();
|
||||
header('Location: index.php?page=access_elements&elements_added=' . $added_count);
|
||||
exit;
|
||||
}
|
||||
|
||||
//GET PARAMETERS && STORE in SESSION for FURTHER USE/NAVIGATION
|
||||
$pagination_page = $_SESSION['p'] = isset($_GET['p']) ? $_GET['p'] : 1;
|
||||
$status = $_SESSION['status'] = isset($_GET['status']) ? '&status='.$_GET['status'] : '';
|
||||
$sort = $_SESSION['sort'] = isset($_GET['sort']) ? '&sort='.$_GET['sort'] : '';
|
||||
$search = $_SESSION['search'] = isset($_GET['search']) ? '&search='.$_GET['search'] : '';
|
||||
|
||||
//GET PARAMETERS FOR FILTERS
|
||||
$filter = urlGETdetailsFilter($_GET) ?? '';
|
||||
|
||||
// Determine the URL
|
||||
$url = 'index.php?page=access_elements'.$status.$search.$sort;
|
||||
//GET Details from URL
|
||||
$GET_VALUES = urlGETdetails($_GET) ?? '';
|
||||
//CALL TO API
|
||||
$api_url = '/v2/access_elements/'.$GET_VALUES;
|
||||
$responses = ioServer($api_url,'');
|
||||
//Decode Payload
|
||||
if (!empty($responses)){$responses = json_decode($responses);}else{$responses = null;}
|
||||
|
||||
//Return QueryTotal from API
|
||||
$total_url = ((!empty($GET_VALUES) && $GET_VALUES !='') ? '&totals=' : 'totals=' );
|
||||
$api_url = '/v2/access_elements/'.$GET_VALUES.$total_url;
|
||||
$query_total = ioServer($api_url,'');
|
||||
//Decode Payload
|
||||
if (!empty($query_total)){$query_total = json_decode($query_total);}else{$query_total = null;}
|
||||
|
||||
// Handle success messages
|
||||
if (isset($_GET['success_msg'])) {
|
||||
if ($_GET['success_msg'] == 1) {
|
||||
$success_msg = ($message_access_1 ?? 'Access element created successfully');
|
||||
}
|
||||
if ($_GET['success_msg'] == 2) {
|
||||
$success_msg = ($message_access_2 ?? 'Access element updated successfully');
|
||||
}
|
||||
if ($_GET['success_msg'] == 3) {
|
||||
$success_msg = ($message_access_3 ?? 'Access element deleted successfully');
|
||||
}
|
||||
}
|
||||
|
||||
// Handle elements added message from scan
|
||||
if (isset($_GET['elements_added'])) {
|
||||
$added_count = (int)$_GET['elements_added'];
|
||||
if ($added_count > 0) {
|
||||
$success_msg = $added_count . ' ' . ($message_elements_added ?? 'new access elements added');
|
||||
} else {
|
||||
$success_msg = ($message_no_new_elements ?? 'No new elements found. All elements are up to date.');
|
||||
}
|
||||
}
|
||||
|
||||
template_header(($access_elements_title ?? 'Access Elements'), 'access_elements','view');
|
||||
$view = '
|
||||
<div class="content-title">
|
||||
<div class="title">
|
||||
<i class="fa-solid fa-lock"></i>
|
||||
<div class="txt">
|
||||
<h2>'.($access_elements_h2 ?? 'Access Elements').' ('.$query_total.')</h2>
|
||||
<p>'.($access_elements_p ?? 'Manage system access elements and paths').'</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="title-actions">
|
||||
'.$back_btn_orgin;
|
||||
|
||||
// Scan button - only show if user has create permission
|
||||
if ($create_allowed === 1){
|
||||
$view .= '
|
||||
<form action="" method="post" style="display:inline;">
|
||||
<button type="submit" name="scan_elements" class="btn alt" title="'.($scan_elements_title ?? 'Scan for new files').'">
|
||||
<i class="fa-solid fa-sync-alt"></i>
|
||||
</button>
|
||||
</form>';
|
||||
$view .= '<a href="index.php?page=access_element_manage" class="btn">+</a>';
|
||||
}
|
||||
|
||||
$view .= '<button id="filter-toggle" class="btn alt" onclick="toggleFilters()">
|
||||
<i class="fa-solid fa-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>';
|
||||
|
||||
if (isset($success_msg)){
|
||||
$view .= ' <div class="msg success">
|
||||
<i class="fas fa-check-circle"></i>
|
||||
<p>'.$success_msg.'</p>
|
||||
<i class="fas fa-times"></i>
|
||||
</div>';
|
||||
}
|
||||
|
||||
$view .= '
|
||||
<div id="filter-panel" class="filter-panel" style="display: none;">
|
||||
<div class="filter-content">
|
||||
<form action="" method="get">
|
||||
'.$filter.'
|
||||
<div class="filter-row">
|
||||
<div class="filter-group">
|
||||
<select name="status">
|
||||
<option value="" disabled selected>'.($general_status ?? 'Status').'</option>
|
||||
<option value="1"'.(isset($_GET['status']) && $_GET['status']==1?' selected':'').'>'.($enabled ?? 'Active').'</option>
|
||||
<option value="0"'.(isset($_GET['status']) && $_GET['status']==0?' selected':'').'>'.($disabled ?? 'Inactive').'</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="filter-group">
|
||||
<select name="sort">
|
||||
<option value="" disabled selected>'.($general_sort ?? 'Sort').'</option>
|
||||
<option value="1"'.(isset($_GET['sort']) && $_GET['sort']==1?' selected':'').'>'.($access_element_name ?? 'Name').' '.($general_sort_type_1 ?? 'ASC').'</option>
|
||||
<option value="2"'.(isset($_GET['sort']) && $_GET['sort']==2?' selected':'').'>'.($access_element_name ?? 'Name').' '.($general_sort_type_2 ?? 'DESC').'</option>
|
||||
<option value="3"'.(isset($_GET['sort']) && $_GET['sort']==3?' selected':'').'>'.($access_element_path ?? 'Path').' '.($general_sort_type_1 ?? 'ASC').'</option>
|
||||
<option value="4"'.(isset($_GET['sort']) && $_GET['sort']==4?' selected':'').'>'.($access_element_path ?? 'Path').' '.($general_sort_type_2 ?? 'DESC').'</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="filter-group search-group">
|
||||
<input type="text" name="search" placeholder="'.($access_search ?? 'Search access elements...').'" value="">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter-actions">
|
||||
<button type="submit" class="btn"><i class="fas fa-level-down-alt fa-rotate-90"></i></button>
|
||||
<a class="btn alt" href="index.php?page=access_elements">X</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
$view .= '
|
||||
<div class="content-block">
|
||||
<div class="table">
|
||||
<table class="sortable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>'.($access_element_name ?? 'Name').'</th>
|
||||
<th>'.($access_element_path ?? 'Path').'</th>
|
||||
<th>'.($access_element_group ?? 'Group').'</th>
|
||||
<th class="responsive-hidden">'.($role_description ?? 'Description').'</th>
|
||||
<th>'.($general_status ?? 'Status').'</th>
|
||||
<th class="responsive-hidden">'.($general_created ?? 'Created').'</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
';
|
||||
|
||||
if (empty($responses)){
|
||||
|
||||
$view .= '
|
||||
<tr>
|
||||
<td colspan="6" style="text-align:center;">'.($message_no_access_elements ?? 'No access elements found').'</td>
|
||||
</tr>';
|
||||
}
|
||||
|
||||
foreach ($responses as $response){
|
||||
//Translate status INT to STR
|
||||
$status_text = ($response->is_active == 1) ? ($enabled ?? 'Active') : ($disabled ?? 'Inactive');
|
||||
$status_class = ($response->is_active == 1) ? 'id1' : 'id0';
|
||||
|
||||
$view .= '<tr onclick="window.location.href=\'index.php?page=access_element&rowID='.$response->rowID.'\'" style="cursor: pointer;">
|
||||
<td>'.$response->access_name.'</td>
|
||||
<td>'.$response->access_path.'</td>
|
||||
<td>'.($response->access_group ?? '-').'</td>
|
||||
<td class="responsive-hidden">'.($response->description ?? '-').'</td>
|
||||
<td><span class="status '.$status_class.'">'.$status_text.'</span></td>
|
||||
<td class="responsive-hidden">'.getRelativeTime($response->created).'</td>
|
||||
</tr>
|
||||
';
|
||||
}
|
||||
$view .= '
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
|
||||
$page_rows = $page_rows_equipment ?? 20;
|
||||
$view.='<div class="pagination">';
|
||||
if ($pagination_page > 1) {
|
||||
$page = $pagination_page-1;
|
||||
$view .= '<a href="'.$url.'&p=1">'.($general_first ?? 'First').'</a>';
|
||||
$view .= '<a href="'.$url.'&p='.$page.'">'.($general_prev ?? 'Prev').'</a>';
|
||||
}
|
||||
$totals = ceil($query_total / $page_rows) == 0 ? 1 : ceil($query_total / $page_rows);
|
||||
$view .= '<span> '.($general_page ?? 'Page ').$pagination_page.($general_page_of ?? ' of ').$totals.'</span>';
|
||||
if ($pagination_page * $page_rows < $query_total){
|
||||
$page = $pagination_page+1;
|
||||
$view .= '<a href="'.$url.'&p='.$page.'">'.($general_next ?? 'Next').'</a>';
|
||||
$view .= '<a href="'.$url.'&p='.$totals.'">'.($general_last ?? 'Last').'</a>';
|
||||
}
|
||||
|
||||
$view .= '</div>';
|
||||
//OUTPUT
|
||||
echo $view;
|
||||
|
||||
template_footer();
|
||||
?>
|
||||
16
account.php
16
account.php
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -15,15 +15,15 @@ $_SESSION['prev_origin'] = $_SERVER['REQUEST_URI'];
|
||||
$page = $_SESSION['origin'] = 'account';
|
||||
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$healthindex_allowed = isAllowed('report_healthindex' ,$_SESSION['profile'],$_SESSION['permission'],'R');
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
$healthindex_allowed = isAllowed('report_healthindex' ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R');
|
||||
|
||||
//GET Details from URL
|
||||
$GET_VALUES = urlGETdetails($_GET) ?? '';
|
||||
@@ -239,13 +239,13 @@ $soldto_id = explode("-",$account_hierarchy->soldto) ?? '';
|
||||
|
||||
//DISPLAY RELATED COMMUNICATION RECORDS
|
||||
$view_communication = '';
|
||||
if ($_SESSION['permission'] == 3 || $_SESSION['permission'] == 4){
|
||||
if (isAllowed('communications',$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 1){
|
||||
$view_communication = ' <a href="index.php?page=communications&partnerid='.$soldto_id[0].'" class="btn">'.$button_partner_assigned_communication.'</a>';
|
||||
}
|
||||
|
||||
//DISPLAY RELATED USERS
|
||||
$view_users ='';
|
||||
if ($_SESSION['permission'] == 3 || $_SESSION['permission'] == 4){
|
||||
if (isAllowed('users',$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 1){
|
||||
$view_users = ' <a href="index.php?page=users&partnerid='.$soldto_id[0].'" class="btn">'.$button_partner_assigned_users.'</a>';
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@ defined(page_security_key) or exit;
|
||||
|
||||
$page = 'account';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
// Default input product values
|
||||
$account = [
|
||||
@@ -43,7 +43,7 @@ $account = [
|
||||
'loghandleraccount' => ''
|
||||
],
|
||||
'created' => $date,
|
||||
'createdby' => $_SESSION['username'],
|
||||
'createdby' => $_SESSION['authorization']['clientID'],
|
||||
'accounthierarchy' => [
|
||||
'salesid' => '',
|
||||
'soldto' => ''
|
||||
@@ -140,7 +140,7 @@ if ($delete_allowed === 1){
|
||||
$view .= '<input type="submit" name="delete" value="X" class="btn red mar-right-2" onclick="return confirm(\'Are you sure you want to delete this account?\')">';
|
||||
}
|
||||
if ($update_allowed === 1){
|
||||
$view .= '<input type="submit" name="submit" value="💾+" class="btn">';
|
||||
$view .= '<input type="submit" name="submit" value="💾" class="btn">';
|
||||
}
|
||||
|
||||
$view .= '</div>';
|
||||
@@ -271,8 +271,8 @@ $view .= '<div class="tabs">
|
||||
|
||||
//Dropdown
|
||||
|
||||
$partner_data = json_decode($_SESSION['partnerhierarchy']);
|
||||
$soldto_dropdown = listPartner('soldto',$_SESSION['permission'],$accounthierarchy->soldto,'');
|
||||
$partner_data = json_decode($_SESSION['authorization']['partnerhierarchy']);
|
||||
$soldto_dropdown = listPartner('soldto',$_SESSION['authorization']['permission'],$accounthierarchy->soldto,'');
|
||||
|
||||
$view .= '<div class="tabs">
|
||||
<a href="#">'.$tab3.'</a>
|
||||
|
||||
10
accounts.php
10
accounts.php
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -15,15 +15,15 @@ $_SESSION['prev_origin'] = '';
|
||||
$page = 'accounts';
|
||||
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$page_manage = 'account_manage';
|
||||
$update_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
//GET PARAMETERS
|
||||
$pagination_page = isset($_GET['p']) ? $_GET['p'] : 1;
|
||||
|
||||
17
api.php
17
api.php
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
define('secure_34563$52', true);
|
||||
|
||||
|
||||
//------------------------------------------
|
||||
// Get DATA from API
|
||||
//------------------------------------------
|
||||
@@ -16,6 +17,17 @@ require_once './assets/functions.php';
|
||||
include './settings/settings_redirector.php';
|
||||
include './settings/config_redirector.php';
|
||||
|
||||
if (debug){
|
||||
set_error_handler(function($errno, $errstr, $errfile, $errline) {
|
||||
debuglog("PHP ERROR [$errno]: $errstr in $errfile on line $errline");
|
||||
return false; // Let PHP handle as usual (optional)
|
||||
});
|
||||
|
||||
set_exception_handler(function($exception) {
|
||||
debuglog("PHP EXCEPTION: " . $exception->getMessage() . " in " . $exception->getFile() . " on line " . $exception->getLine());
|
||||
});
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
// Header security - enabled via config
|
||||
//------------------------------------------
|
||||
@@ -122,7 +134,7 @@ if($is_jwt_valid && str_contains($version, 'v')) {
|
||||
//------------------------------------------
|
||||
// Check for maintenance mode, exclude debug user
|
||||
//------------------------------------------
|
||||
if(maintenance_mode == false|| debug_id == $user_data['id']){
|
||||
if(maintenance_mode == false || debug_id == $user_data['id']){
|
||||
|
||||
//------------------------------------------
|
||||
// Build up version and check if file is available
|
||||
@@ -154,7 +166,8 @@ if($is_jwt_valid && str_contains($version, 'v')) {
|
||||
// First check if endPoint is fileUpload
|
||||
//------------------------------------------
|
||||
$fileUploadEndpoints = [
|
||||
'media_upload'
|
||||
'media_upload',
|
||||
'marketing_upload'
|
||||
];
|
||||
|
||||
$isFileUploadEndpoint = in_array($collection, $fileUploadEndpoints);
|
||||
|
||||
BIN
api/.DS_Store
vendored
BIN
api/.DS_Store
vendored
Binary file not shown.
@@ -15,7 +15,7 @@ $user_data = $stmt->fetch();
|
||||
//Define User data
|
||||
$partnerhierarchy = $user_data['partnerhierarchy'];
|
||||
$permission = userRights($user_data['view']);
|
||||
$profile= getProfile($user_data['settings'],$permission);
|
||||
$profile= getUserPermissions($pdo, $user_data['id']);
|
||||
$username = $user_data['username'];
|
||||
$useremail = $user_data['email'];
|
||||
$servicekey = $user_data['service'];
|
||||
|
||||
@@ -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
BIN
api/v1/.DS_Store
vendored
Binary file not shown.
@@ -17,11 +17,13 @@ if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} el
|
||||
//default whereclause
|
||||
$whereclause = '';
|
||||
|
||||
switch ($permission) {
|
||||
case '4':
|
||||
$hierarchy_level = getHierarchyLevel($partner);
|
||||
|
||||
switch ($hierarchy_level) {
|
||||
case '0':
|
||||
$whereclause = '';
|
||||
break;
|
||||
case '3':
|
||||
case '1':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___%';
|
||||
$whereclause = 'WHERE c.accounthierarchy like :condition AND u.view IN (4,5)';
|
||||
break;
|
||||
@@ -29,7 +31,11 @@ switch ($permission) {
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search;
|
||||
$whereclause = 'WHERE c.accounthierarchy like :condition AND u.view IN (1,2,3)';
|
||||
break;
|
||||
default:
|
||||
case '3':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%';
|
||||
$whereclause = 'WHERE c.accounthierarchy like :condition AND u.view IN (1,2,3)';
|
||||
break;
|
||||
case '4':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%___location___'.substr($partner->location, 0, strpos($partner->location, "-")).'%';
|
||||
$whereclause = 'WHERE c.accounthierarchy like :condition AND u.view IN (1,2,3)';
|
||||
break;
|
||||
|
||||
@@ -14,11 +14,13 @@ if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} el
|
||||
//default whereclause
|
||||
$whereclause = '';
|
||||
|
||||
switch ($permission) {
|
||||
case '4':
|
||||
$hierarchy_level = getHierarchyLevel($partner);
|
||||
|
||||
switch ($hierarchy_level) {
|
||||
case '0':
|
||||
$whereclause = '';
|
||||
break;
|
||||
case '3':
|
||||
case '1':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___%';
|
||||
$whereclause = 'WHERE e.accounthierarchy like :condition ';
|
||||
break;
|
||||
@@ -26,11 +28,16 @@ switch ($permission) {
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search;
|
||||
$whereclause = 'WHERE e.accounthierarchy like :condition AND (type = "'.$type1.'" or type = "'.$type2.'" or type = "'.$type3.'" or type = "'.$type9.'" or type = "'.$type14.'" or type = "'.$type16.'")';
|
||||
break;
|
||||
default:
|
||||
case '3':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%___location___'.$soldto_search;
|
||||
$whereclause = 'WHERE e.accounthierarchy like :condition AND (type = "'.$type1.'" or type = "'.$type2.'" or type = "'.$type3.'" or type = "'.$type14.'" or type = "'.$type16.'")';
|
||||
break;
|
||||
case '4':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%___location___'.substr($partner->location, 0, strpos($partner->location, "-")).'%';
|
||||
$whereclause = 'WHERE e.accounthierarchy like :condition AND (type = "'.$type1.'" or type = "'.$type2.'" or type = "'.$type3.'" or type = "'.$type14.'" or type = "'.$type16.'")';
|
||||
break;
|
||||
}
|
||||
|
||||
//NEW ARRAY
|
||||
$criterias = [];
|
||||
$clause = '';
|
||||
|
||||
@@ -17,7 +17,7 @@ if ($stmt->rowCount() == 1) {
|
||||
//Define User data
|
||||
$partnerhierarchy = $user_data['partnerhierarchy'];
|
||||
$permission = userRights($user_data['view']);
|
||||
$profile= getProfile($user_data['settings'],$permission);
|
||||
$profile= getUserPermissions($pdo, $user_data['id']);
|
||||
$username = $user_data['username'];
|
||||
$useremail = $user_data['email'];
|
||||
$servicekey = $user_data['service'];
|
||||
|
||||
@@ -40,7 +40,7 @@ if ($id != ''){
|
||||
$salesid_new = (($post_content['salesid'] != '' && $post_content['salesid'] != $accounthierarchy_old->salesid)? $post_content['salesid'] : $accounthierarchy_old->salesid);
|
||||
$soldto_new = (($post_content['soldto'] != '' && $post_content['soldto'] != $accounthierarchy_old->soldto)? $post_content['soldto'] : $accounthierarchy_old->soldto);
|
||||
|
||||
if ($permission == 3 || $permission == 4){
|
||||
if (getHierarchyLevel($partner) == 1 || getHierarchyLevel($partner) == 0){
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$salesid_new,
|
||||
|
||||
@@ -15,7 +15,6 @@ if ($action !=''){
|
||||
//Connect to DB
|
||||
//------------------------------------------
|
||||
$pdo = dbConnect($dbname);
|
||||
$pdo2 = dbConnect($dbname);
|
||||
|
||||
//------------------------------------------
|
||||
//CONTENT FROM API (POST)
|
||||
@@ -28,11 +27,13 @@ if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} el
|
||||
//default whereclause
|
||||
$whereclause = 'WHERE';
|
||||
|
||||
switch ($permission) {
|
||||
case '4':
|
||||
$hierarchy_level = getHierarchyLevel($partner);
|
||||
|
||||
switch ($hierarchy_level) {
|
||||
case '0':
|
||||
$whereclause .= '';
|
||||
break;
|
||||
case '3':
|
||||
case '1':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___%';
|
||||
$whereclause = ' e.accounthierarchy like "'.$condition.'" AND ';
|
||||
break;
|
||||
@@ -40,7 +41,11 @@ switch ($permission) {
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search;
|
||||
$whereclause .= ' e.accounthierarchy like "'.$condition.'" AND ';
|
||||
break;
|
||||
default:
|
||||
case '3':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%';
|
||||
$whereclause .= ' e.accounthierarchy like "'.$condition.'" AND ';
|
||||
break;
|
||||
case '4':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%___location___'.substr($partner->location, 0, strpos($partner->location, "-")).'%';
|
||||
$whereclause .= ' e.accounthierarchy like "'.$condition.'" AND ';
|
||||
break;
|
||||
@@ -85,238 +90,148 @@ 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
|
||||
// --------------------------------------------
|
||||
if(is_array($post_content['sn'])){
|
||||
foreach ($post_content['sn'] as $sn){
|
||||
//Get equipmentid based on rowID
|
||||
$rowID = getrowID($dbname,'rowID','equipment','serialnumber="'.$sn.'"');
|
||||
|
||||
if ($rowID){
|
||||
//check if under warranty
|
||||
$warranty = getrowID($dbname,'rowID','equipment_history','equipmentid="'.$rowID['rowID'].'" && (type="'.$type9.'" || type="'.$type10.'" || type="'.$type11.'" || type="'.$type12.'")');
|
||||
if ($warranty){
|
||||
// --------------------------------------------
|
||||
// Already under contract
|
||||
// --------------------------------------------
|
||||
//Serialnumber under warranty
|
||||
$message_box[] = $sn.' - '.$register_message_2;
|
||||
$communication_check = 1;
|
||||
} else
|
||||
{
|
||||
// --------------------------------------------
|
||||
// Not under warranty
|
||||
// --------------------------------------------
|
||||
//Send user firmware account
|
||||
$firmware_account_send = 1;
|
||||
//create history
|
||||
// Prepare queries
|
||||
$sql = 'INSERT INTO equipment_history (equipmentid, type, description, created, createdby,updatedby) VALUES (?,?,?,?,?,?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$rowID['rowID'],$type9,$description,$timestamp,$post_content['email'],$post_content['email']]);
|
||||
// Normalize input to always be an array
|
||||
$serial_numbers = is_array($post_content['sn']) ? $post_content['sn'] : [$post_content['sn']];
|
||||
|
||||
//GET PARTNER DETAILS OF EQUIPMENT
|
||||
$partner_equipment = getrowID($dbname,'accounthierarchy','equipment','rowID="'.$rowID['rowID'].'"');
|
||||
$partner_equipment = json_decode($partner_equipment['accounthierarchy']);
|
||||
|
||||
//Setup partnerhierarchy (salesID)
|
||||
$partnerhierarchy =[
|
||||
"salesid"=>$partner_equipment->salesid,
|
||||
"soldto"=>$partner_equipment->soldto
|
||||
];
|
||||
|
||||
//Setup variables for partner
|
||||
$partnername = $post_content['organization'];
|
||||
$partnernotes = 'created based on user registration';
|
||||
$salesID = json_encode($partnerhierarchy, JSON_UNESCAPED_UNICODE);
|
||||
$createdby = 'system';
|
||||
|
||||
//Check if shipto is empty and if empty search partner or create
|
||||
if ($partner_equipment->shipto == ''){
|
||||
$partner_shipto = getrowID($dbname,'partnerID','partner','partnername = "'.$partnername.'" && partnertype="'.$partnertype3.'"');
|
||||
if ($partner_shipto){
|
||||
//Partner exists - Use it
|
||||
$partnerhierarchy['shipto'] = $partner_shipto['partnerID'].'-'.$partnername;
|
||||
} else {
|
||||
//Partner does not exist create
|
||||
$sql = 'INSERT INTO partner (partnertype,partnername,salesID,createdby,status) VALUES (?,?,?,?,?)';
|
||||
$stmt = $pdo2->prepare($sql);
|
||||
$stmt->execute([$partnertype3,$partnername,$salesID,$createdby,'1']);
|
||||
|
||||
//Get rowID of created partner and use it
|
||||
$partner_rowid = $pdo2->lastInsertId();
|
||||
$partnerhierarchy['shipto'] = $partner_rowid.'-'.$partnername;
|
||||
}
|
||||
} else {
|
||||
// Shipto exist use it
|
||||
$partnerhierarchy['shipto'] = $partner_equipment->shipto;
|
||||
}
|
||||
//Check if location is empty and if empty search partner or create
|
||||
if ($partner_equipment->location == ''){
|
||||
$partner_location = getrowID($dbname,'partnerID','partner','partnername = "'.$partnername.'" && partnertype="'.$partnertype4.'"');
|
||||
if ($partner_location){
|
||||
//Partner exists - Use it
|
||||
$partnerhierarchy['location'] = $partner_location['partnerID'].'-'.$partnername;
|
||||
|
||||
} else {
|
||||
//Partner does not exist create
|
||||
$sql = 'INSERT INTO partner (partnertype,partnername,salesID,createdby,status) VALUES (?,?,?,?,?)';
|
||||
$stmt = $pdo2->prepare($sql);
|
||||
$stmt->execute([$partnertype4,$partnername,$salesID,$createdby,'1']);
|
||||
|
||||
//Get rowID of created partner and use it
|
||||
$partner_rowid = $pdo2->lastInsertId();
|
||||
$partnerhierarchy['location'] = $partner_rowid.'-'.$partnername;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Location exist use it
|
||||
$partnerhierarchy['location'] = $partner_equipment->location;
|
||||
}
|
||||
|
||||
$shipto = $partnerhierarchy['shipto'] ?? '';
|
||||
$partnerhierarchy = json_encode($partnerhierarchy, JSON_UNESCAPED_UNICODE);
|
||||
// --------------------------------------------
|
||||
// Update equipment record warranty_date, partnerhierarchy, status equipment
|
||||
// --------------------------------------------
|
||||
$sql = 'UPDATE equipment SET status = ?, warranty_date = ?, accounthierarchy = ?,updatedby = ? WHERE rowID = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute(['4',$warranty_extended,$partnerhierarchy,$username,$rowID['rowID']]);
|
||||
|
||||
//Add warranty to changelog
|
||||
$warranty_user = $post_content['email'] ?? 'system';
|
||||
changelog($dbname,'equipment',$rowID['rowID'],'Warranty',$warranty_extended,$warranty_user);
|
||||
|
||||
//Serialnumber recognized
|
||||
$message_box[] = $sn.' - '.$register_message_3;
|
||||
$communication_check = 1;
|
||||
}
|
||||
} else {
|
||||
//Serialnumber not recognized
|
||||
$message_box[] = $sn.' - '.$register_message_1;
|
||||
}
|
||||
foreach ($serial_numbers as $sn) {
|
||||
// Get equipment ID based on serial number
|
||||
$sql = 'SELECT rowID, warranty_date, order_send_date from equipment where serialnumber = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$sn]);
|
||||
$rowID = $stmt->fetch();
|
||||
|
||||
if (!$rowID['rowID']) {
|
||||
// Serial number not recognized
|
||||
$message_box[] = $sn . ' - ' . $register_message_1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// --------------------------------------------
|
||||
//Get equipmentid based on rowID
|
||||
// --------------------------------------------
|
||||
$rowID = getrowID($dbname,'rowID','equipment','serialnumber="'.$post_content['sn'].'"');
|
||||
if ($rowID){
|
||||
//check if under warranty
|
||||
$warranty = getrowID($dbname,'rowID','equipment_history','equipmentid="'.$rowID['rowID'].'" && (type="'.$type9.'" || type="'.$type10.'" || type="'.$type11.'" || type="'.$type12.'")');
|
||||
if ($warranty){
|
||||
// --------------------------------------------
|
||||
|
||||
// Check if under warranty
|
||||
$warranty_types = [$type9, $type10, $type11, $type12];
|
||||
$warranty_condition = 'equipmentid="' . $rowID['rowID'] . '" && (type="' . implode('" || type="', $warranty_types) . '")';
|
||||
$warranty = getrowID($dbname, 'rowID', 'equipment_history', $warranty_condition);
|
||||
|
||||
if ($warranty) {
|
||||
// Already under contract
|
||||
// --------------------------------------------
|
||||
//Serialnumber not recognized
|
||||
$message_box[] = $post_content['sn'].' - '.$register_message_2;
|
||||
} else
|
||||
{
|
||||
// --------------------------------------------
|
||||
// Not under warranty
|
||||
// --------------------------------------------
|
||||
$firmware_account_send = 1;
|
||||
//create history
|
||||
$sql = 'INSERT INTO equipment_history (equipmentid, type, description, created, createdby, updatedby) VALUES (?,?,?,?,?,?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$rowID['rowID'],$type9,$description,$timestamp,$post_content['email'],$post_content['email']]);
|
||||
|
||||
//GET PARTNER DETAILS OF EQUIPMENT
|
||||
$partner_equipment = getrowID($dbname,'accounthierarchy','equipment','rowID="'.$rowID['rowID'].'"');
|
||||
$partner_equipment = json_decode($partner_equipment['accounthierarchy']);
|
||||
|
||||
//Setup partnerhierarchy (salesID)
|
||||
$partnerhierarchy =[
|
||||
"salesid"=>$partner_equipment->salesid,
|
||||
"soldto"=>$partner_equipment->soldto
|
||||
];
|
||||
|
||||
//Setup variables for partner
|
||||
$partnername = $post_content['organization'];
|
||||
$partnernotes = 'created based on user registration';
|
||||
$salesID = json_encode($partnerhierarchy, JSON_UNESCAPED_UNICODE);
|
||||
$createdby = 'system';
|
||||
|
||||
//Check if shipto is empty and if empty search partner or create
|
||||
if ($partner_equipment->shipto == ''){
|
||||
$partner_shipto = getrowID($dbname,'partnerID','partner','partnername = "'.$partnername.'" && partnertype="'.$partnertype3.'"');
|
||||
if ($partner_shipto){
|
||||
//Partner exists - Use it
|
||||
$partnerhierarchy['shipto'] = $partner_shipto['partnerID'].'-'.$partnername;
|
||||
} else {
|
||||
//Partner does not exist create
|
||||
$sql = 'INSERT INTO partner (partnertype, partnername,salesID,createdby,status) VALUES (?,?,?,?,?)';
|
||||
$stmt = $pdo2->prepare($sql);
|
||||
$stmt->execute([$partnertype3,$partnername,$salesID,$createdby,'1']);
|
||||
|
||||
//Get rowID of created partner and use it
|
||||
$partner_rowid = $pdo2->lastInsertId();
|
||||
$partnerhierarchy['shipto'] = $partner_rowid.'-'.$partnername;
|
||||
}
|
||||
} else {
|
||||
// Shipto exist use it
|
||||
$partnerhierarchy['shipto'] = $partner_equipment->shipto;
|
||||
}
|
||||
//Check if location is empty and if empty search partner or create
|
||||
if ($partner_equipment->location == ''){
|
||||
$partner_location = getrowID($dbname,'partnerID','partner','partnername = "'.$partnername.'" && partnertype="'.$partnertype4.'"');
|
||||
if ($partner_location){
|
||||
//Partner exists - Use it
|
||||
$partnerhierarchy['location'] = $partner_location['partnerID'].'-'.$partnername;
|
||||
|
||||
} else {
|
||||
//Partner does not exist create
|
||||
$sql = 'INSERT INTO partner (partnertype,partnername,salesID,createdby,status) VALUES (?,?,?,?,?)';
|
||||
$stmt = $pdo2->prepare($sql);
|
||||
$stmt->execute([$partnertype4,$partnername,$salesID,$createdby,'1']);
|
||||
|
||||
//Get rowID of created partner and use it
|
||||
$partner_rowid = $pdo2->lastInsertId();
|
||||
$partnerhierarchy['location'] = $partner_rowid.'-'.$partnername;
|
||||
}
|
||||
} else {
|
||||
// Location exist use it
|
||||
$partnerhierarchy['location'] = $partner_equipment->location;
|
||||
}
|
||||
|
||||
$partnerhierarchy = json_encode($partnerhierarchy, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
// --------------------------------------------
|
||||
// Update equipment record warranty_date, partnerhierarchy, status equipment
|
||||
// --------------------------------------------
|
||||
$sql = 'UPDATE equipment SET status = ?, warranty_date = ?, accounthierarchy = ?, updatedby = ? WHERE rowID = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute(['4',$warranty_extended,$partnerhierarchy,$username,$rowID['rowID']]);
|
||||
|
||||
//Add warranty to changelog
|
||||
$warranty_user = $post_content['email'] ?? 'system';
|
||||
changelog($dbname,'equipment',$rowID['rowID'],'Warranty',$warranty_extended,$warranty_user);
|
||||
|
||||
//Serialnumber recognized
|
||||
$message_box[] = $post_content['sn'].' - '.$register_message_3;
|
||||
}
|
||||
$message_box[] = $sn . ' - ' . $register_message_2;
|
||||
$communication_check = 1;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
//Serialnumber not recognized
|
||||
$message_box[] = $post_content['sn'].' - '.$register_message_1;
|
||||
|
||||
//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 (?,?,?,?,?,?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
$rowID['rowID'],
|
||||
$type9,
|
||||
$description,
|
||||
$timestamp,
|
||||
$post_content['email'],
|
||||
$post_content['email']
|
||||
]);
|
||||
|
||||
// Get partner details of equipment
|
||||
$partner_equipment = getrowID($dbname, 'accounthierarchy', 'equipment', 'rowID="' . $rowID['rowID'] . '"');
|
||||
$partner_equipment = json_decode($partner_equipment['accounthierarchy']);
|
||||
|
||||
// Setup partner hierarchy
|
||||
$partnerhierarchy = [
|
||||
"salesid" => $partner_equipment->salesid,
|
||||
"soldto" => $partner_equipment->soldto
|
||||
];
|
||||
|
||||
// Setup variables for partner
|
||||
$partnername = $post_content['organization'];
|
||||
$salesID = json_encode($partnerhierarchy, JSON_UNESCAPED_UNICODE);
|
||||
$createdby = 'system';
|
||||
|
||||
// Helper function to get or create partner
|
||||
$getOrCreatePartner = function($partnertype) use ($dbname, $partnername, $salesID, $createdby, $pdo) {
|
||||
$partner = getrowID($dbname, 'partnerID', 'partner', 'partnername = "' . $partnername . '" && partnertype="' . $partnertype . '"');
|
||||
|
||||
if ($partner) {
|
||||
return $partner['partnerID'] . '-' . $partnername;
|
||||
}
|
||||
|
||||
// Partner does not exist - create
|
||||
$sql = 'INSERT INTO partner (partnertype, partnername, salesID, createdby, status) VALUES (?,?,?,?,?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$partnertype, $partnername, $salesID, $createdby, '1']);
|
||||
|
||||
$partner_rowid = $pdo->lastInsertId();
|
||||
return $partner_rowid . '-' . $partnername;
|
||||
};
|
||||
|
||||
// Handle shipto
|
||||
$partnerhierarchy['shipto'] = empty($partner_equipment->shipto)
|
||||
? $getOrCreatePartner($partnertype3)
|
||||
: $partner_equipment->shipto;
|
||||
|
||||
// Handle location
|
||||
$partnerhierarchy['location'] = empty($partner_equipment->location)
|
||||
? $getOrCreatePartner($partnertype4)
|
||||
: $partner_equipment->location;
|
||||
|
||||
$partnerhierarchy_json = json_encode($partnerhierarchy, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
// Update equipment record
|
||||
$sql = 'UPDATE equipment SET status = ?, warranty_date = ?, accounthierarchy = ?, updatedby = ? WHERE rowID = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$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_end_date, $warranty_user);
|
||||
|
||||
// Serial number recognized
|
||||
$message_box[] = $sn . ' - ' . $register_message_3;
|
||||
$communication_check = 1;
|
||||
}
|
||||
|
||||
// --------------------------------------------
|
||||
// Send generic account to user for software updates
|
||||
|
||||
@@ -58,7 +58,7 @@ if ($id != ''){
|
||||
$shipto_new = (($post_content['shipto'] != '' && $post_content['shipto'] != $contract_old->shipto)? $post_content['shipto'] : $contract_old->shipto);
|
||||
$location_new = (($post_content['location'] != '' && $post_content['location'] != $contract_old->location)? $post_content['location'] : $contract_old->location);
|
||||
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
//ADMIN+ ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$salesid_new,
|
||||
@@ -67,7 +67,7 @@ if ($id != ''){
|
||||
"location"=>$location_new
|
||||
);
|
||||
}
|
||||
elseif ($permission == 3) {
|
||||
elseif (getHierarchyLevel($partner) == 1) {
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SOLD
|
||||
$account = array(
|
||||
"salesid"=>$contract_old->salesid,
|
||||
@@ -120,7 +120,7 @@ if ($id != ''){
|
||||
}
|
||||
else {
|
||||
//ID is empty => INSERT / NEW RECORD
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
$account = array(
|
||||
"salesid"=>$post_content['salesid'],
|
||||
"soldto"=>$post_content['soldto'],
|
||||
@@ -128,7 +128,7 @@ else {
|
||||
"location"=>$post_content['location']
|
||||
);
|
||||
}
|
||||
elseif ($permission == 3){
|
||||
elseif (getHierarchyLevel($partner) == 1){
|
||||
$account = array(
|
||||
"salesid"=>$partner->salesid,
|
||||
"soldto"=>$post_content['soldto'],
|
||||
@@ -160,7 +160,7 @@ if (isset($post_content['servicetool'])){
|
||||
if (isset($post_content['ignore_list'])){
|
||||
$post_content['ignore_list'] = json_encode($post_content['ignore_list'], JSON_UNESCAPED_UNICODE);
|
||||
//ONLY ADMINS ARE ALLOWED TO UPDATE IGNORE LIST
|
||||
if ($permission != 3 && $permission != 4){
|
||||
if (getHierarchyLevel($partner) != 1 && getHierarchyLevel($partner) != 0){
|
||||
unset($post_content['ignore_list']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ if ($id != ''){
|
||||
|
||||
$owner_equipment = (($equipment_data['createdby'] == $username)? 1 : 0);
|
||||
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
//ADMIN+ ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$salesid_new,
|
||||
@@ -57,7 +57,7 @@ if ($id != ''){
|
||||
"section"=>$section_new
|
||||
);
|
||||
}
|
||||
elseif ($permission == 3) {
|
||||
elseif (getHierarchyLevel($partner) == 1) {
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SOLD
|
||||
$account = array(
|
||||
"salesid"=>$equipment_old->salesid,
|
||||
@@ -79,7 +79,7 @@ if ($id != ''){
|
||||
}
|
||||
else {
|
||||
//ID is empty => INSERT / NEW RECORD
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
$account = array(
|
||||
"salesid"=>$post_content['salesid'],
|
||||
"soldto"=>$post_content['soldto'],
|
||||
@@ -89,7 +89,7 @@ else {
|
||||
|
||||
);
|
||||
}
|
||||
elseif ($permission == 3){
|
||||
elseif (getHierarchyLevel($partner) == 1){
|
||||
$account = array(
|
||||
"salesid"=>$partner->salesid,
|
||||
"soldto"=>$post_content['soldto'],
|
||||
|
||||
@@ -41,7 +41,7 @@ if ($id != ''){
|
||||
$salesid_new = (($post_content['salesid'] != '' && $post_content['salesid'] != $partnerhierarchy_old->salesid)? $post_content['salesid'] : $partnerhierarchy_old->salesid);
|
||||
$soldto_new = (($post_content['soldto'] != '' && $post_content['soldto'] != $partnerhierarchy_old->soldto)? $post_content['soldto'] : $partnerhierarchy_old->soldto);
|
||||
|
||||
if ($permission == 3 || $permission == 4){
|
||||
if (getHierarchyLevel($partner) == 1 || getHierarchyLevel($partner) == 0){
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$salesid_new,
|
||||
@@ -56,7 +56,7 @@ if ($id != ''){
|
||||
}
|
||||
else {
|
||||
//ID is empty => INSERT / NEW RECORD
|
||||
if ($permission == 3 || $permission == 4){
|
||||
if (getHierarchyLevel($partner) == 1 || getHierarchyLevel($partner) == 0){
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$partner->salesid,
|
||||
|
||||
@@ -50,7 +50,7 @@ $soldto_new = ((isset($post_content['soldto']) && $post_content['soldto'] != ''
|
||||
$shipto_new = (($post_content['shipto'] != '' && $post_content['shipto'] != $partnerhierarchy_old->shipto)? $post_content['shipto'] : $partnerhierarchy_old->shipto);
|
||||
$location_new = (($post_content['location'] != '' && $post_content['location'] != $partnerhierarchy_old->location)? $post_content['location'] : $partnerhierarchy_old->location);
|
||||
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
//ADMIN+ ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$salesid_new,
|
||||
@@ -58,7 +58,7 @@ $location_new = (($post_content['location'] != '' && $post_content['location'] !
|
||||
"shipto"=>$shipto_new,
|
||||
"location"=>$location_new
|
||||
);
|
||||
}elseif ($permission == 3) {
|
||||
}elseif (getHierarchyLevel($partner) == 1) {
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SOLD
|
||||
$account = array(
|
||||
"salesid"=>$partner->salesid,
|
||||
@@ -77,7 +77,7 @@ $location_new = (($post_content['location'] != '' && $post_content['location'] !
|
||||
}
|
||||
} elseif ($command == 'insert') {
|
||||
//ID is empty => INSERT / NEW RECORD
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
//ADMIN+ ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$post_content['salesid'],
|
||||
@@ -86,7 +86,7 @@ $location_new = (($post_content['location'] != '' && $post_content['location'] !
|
||||
"location"=>$post_content['location']
|
||||
);
|
||||
}
|
||||
elseif ($permission == 3){
|
||||
elseif (getHierarchyLevel($partner) == 1){
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SOLD
|
||||
$account = array(
|
||||
"salesid"=>$partner->salesid,
|
||||
|
||||
BIN
api/v2/.DS_Store
vendored
BIN
api/v2/.DS_Store
vendored
Binary file not shown.
BIN
api/v2/get/.DS_Store
vendored
BIN
api/v2/get/.DS_Store
vendored
Binary file not shown.
158
api/v2/get/access_elements.php
Normal file
158
api/v2/get/access_elements.php
Normal file
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Access Elements
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//------------------------------------------
|
||||
//NEW ARRAY
|
||||
//------------------------------------------
|
||||
$criterias = [];
|
||||
$clause = '';
|
||||
|
||||
//------------------------------------------
|
||||
//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];
|
||||
if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='success_msg' || $v[0] =='sort' || $v[0] =='all'){
|
||||
//do nothing
|
||||
}
|
||||
elseif ($v[0] == 'rowid') {
|
||||
//build up search by ID
|
||||
$clause .= ' AND a.rowID = :'.$v[0];
|
||||
}
|
||||
elseif ($v[0] == 'status') {
|
||||
//Update status based on status
|
||||
$clause .= ' AND a.is_active = :'.$v[0];
|
||||
}
|
||||
elseif ($v[0] == 'search') {
|
||||
//build up search
|
||||
$clause .= ' AND (a.access_name LIKE :'.$v[0].' OR a.access_path LIKE :'.$v[0].' OR a.description LIKE :'.$v[0].')';
|
||||
}
|
||||
elseif ($v[0] == 'access_path') {
|
||||
//build up path search
|
||||
$clause .= ' AND a.access_path = :'.$v[0];
|
||||
}
|
||||
else {
|
||||
//create clause
|
||||
$clause .= ' AND a.'.$v[0].' = :'.$v[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Build WHERE clause
|
||||
$whereclause = '';
|
||||
if ($clause != ''){
|
||||
$whereclause = 'WHERE '.substr($clause, 4);
|
||||
}
|
||||
|
||||
// GET SORT INDICATOR
|
||||
$sort_indicator = $criterias['sort'] ?? '';
|
||||
|
||||
switch ($sort_indicator){
|
||||
case 1:
|
||||
$sort = ' a.access_name ASC ';
|
||||
break;
|
||||
case 2:
|
||||
$sort = ' a.access_name DESC ';
|
||||
break;
|
||||
case 3:
|
||||
$sort = ' a.access_path ASC ';
|
||||
break;
|
||||
case 4:
|
||||
$sort = ' a.access_path DESC ';
|
||||
break;
|
||||
default:
|
||||
$sort = ' a.access_name ASC ';
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($criterias['totals']) && $criterias['totals'] ==''){
|
||||
//Request for total rows
|
||||
$sql = 'SELECT count(*) as count FROM access_elements a '.$whereclause;
|
||||
}
|
||||
elseif (isset($criterias['all']) && $criterias['all'] ==''){
|
||||
//Return all records (no paging)
|
||||
$sql = 'SELECT a.* FROM access_elements a '.$whereclause.' ORDER BY '.$sort;
|
||||
}
|
||||
else {
|
||||
//SQL
|
||||
$sql = 'SELECT a.* FROM access_elements a '.$whereclause.' ORDER BY '.$sort.' LIMIT :page,:num_rows';
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
//------------------------------------------
|
||||
//Bind to query
|
||||
//------------------------------------------
|
||||
if (!empty($criterias)){
|
||||
foreach ($criterias as $key => $value){
|
||||
$key_condition = ':'.$key;
|
||||
if (str_contains($sql, $key_condition)){
|
||||
if ($key == 'search'){
|
||||
$search_value = '%'.$value.'%';
|
||||
$stmt->bindValue($key, $search_value, PDO::PARAM_STR);
|
||||
}
|
||||
elseif ($key == 'p'){
|
||||
//Do nothing (bug)
|
||||
}
|
||||
else {
|
||||
$stmt->bindValue($key, $value, PDO::PARAM_STR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
// Debuglog
|
||||
//------------------------------------------
|
||||
if (debug){
|
||||
$message = $date.';'.$sql.';'.$username;
|
||||
debuglog($message);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//Add paging details
|
||||
//------------------------------------------
|
||||
$page_rows = $page_rows_equipment ?? 20;
|
||||
|
||||
if(isset($criterias['totals']) && $criterias['totals']==''){
|
||||
$stmt->execute();
|
||||
$messages = $stmt->fetch();
|
||||
$messages = $messages[0];
|
||||
}
|
||||
elseif(isset($criterias['all']) && $criterias['all']==''){
|
||||
//Return all records (no paging)
|
||||
$stmt->execute();
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
else {
|
||||
$current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1;
|
||||
$stmt->bindValue('page', ($current_page - 1) * $page_rows, PDO::PARAM_INT);
|
||||
$stmt->bindValue('num_rows', $page_rows, PDO::PARAM_INT);
|
||||
//Execute Query
|
||||
$stmt->execute();
|
||||
//Get results
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//JSON_EnCODE
|
||||
//------------------------------------------
|
||||
$messages = json_encode($messages, JSON_UNESCAPED_UNICODE);
|
||||
//------------------------------------------
|
||||
//Send results
|
||||
//------------------------------------------
|
||||
echo $messages;
|
||||
|
||||
?>
|
||||
@@ -17,19 +17,25 @@ if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} el
|
||||
//default whereclause
|
||||
$whereclause = '';
|
||||
|
||||
switch ($permission) {
|
||||
case '4':
|
||||
$hierarchy_level = getHierarchyLevel($partner);
|
||||
|
||||
switch ($hierarchy_level) {
|
||||
case '0':
|
||||
$whereclause = '';
|
||||
break;
|
||||
case '3':
|
||||
case '1':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___%';
|
||||
$whereclause = 'WHERE accounthierarchy like :condition AND u.view IN (4,5)';
|
||||
break;
|
||||
case '2':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search;
|
||||
$whereclause = 'WHERE accounthierarchy like :condition AND u.view IN (1,2,3)';
|
||||
break;
|
||||
case '3':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%';
|
||||
$whereclause = 'WHERE accounthierarchy like :condition AND u.view IN (1,2,3)';
|
||||
break;
|
||||
default:
|
||||
case '4':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%___location___'.substr($partner->location, 0, strpos($partner->location, "-")).'%';
|
||||
$whereclause = 'WHERE accounthierarchy like :condition AND u.view IN (1,2,3)';
|
||||
break;
|
||||
|
||||
116
api/v2/get/equipment_history.php
Normal file
116
api/v2/get/equipment_history.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
// Database connection
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
// ============================================
|
||||
// Input Validation & Sanitization
|
||||
// ============================================
|
||||
|
||||
$filters = [
|
||||
'serialnumber' => isset($_GET['serialnumber']) ? trim($_GET['serialnumber']) : null,
|
||||
'type' => isset($_GET['type']) ? trim($_GET['type']) : null,
|
||||
'start' => isset($_GET['start']) ? trim($_GET['start']) : date("Y-m-d", strtotime("-270 days")),
|
||||
'end' => isset($_GET['end']) ? trim($_GET['end']) : date("Y-m-d", strtotime("+1 days"))
|
||||
];
|
||||
|
||||
// ============================================
|
||||
// Build Query with Prepared Statements
|
||||
// ============================================
|
||||
|
||||
$whereClauses = [];
|
||||
$params = [];
|
||||
|
||||
// Serial Number Filter
|
||||
if ($filters['serialnumber']) {
|
||||
$whereClauses[] = 'h.description LIKE :serialnumber';
|
||||
$params[':serialnumber'] = "%historycreated%SN%:" . $filters['serialnumber'] . "%";
|
||||
$whereClauses[] = 'h.type != :excluded_type';
|
||||
$params[':excluded_type'] = 'SRIncluded';
|
||||
}
|
||||
|
||||
// Type Filter
|
||||
if ($filters['type']) {
|
||||
if ($filters['type'] === 'latest') {
|
||||
// Get only the latest record per equipment
|
||||
if ($filters['serialnumber']) {
|
||||
$whereClauses[] = 'h.rowID IN (
|
||||
SELECT MAX(h2.rowID)
|
||||
FROM equipment_history h2
|
||||
GROUP BY h2.equipmentid
|
||||
)';
|
||||
} else {
|
||||
$whereClauses[] = "h.description LIKE '%historycreated%'";
|
||||
$whereClauses[] = 'h.rowID IN (
|
||||
SELECT MAX(h2.rowID)
|
||||
FROM equipment_history h2
|
||||
WHERE h2.description LIKE :history_created
|
||||
GROUP BY h2.equipmentid
|
||||
)';
|
||||
$params[':history_created'] = '%historycreated%';
|
||||
}
|
||||
} else {
|
||||
// Specific type filter
|
||||
$whereClauses[] = 'h.type = :type';
|
||||
$params[':type'] = $filters['type'];
|
||||
}
|
||||
}
|
||||
|
||||
// Default filter if no other filters applied
|
||||
if (empty($whereClauses)) {
|
||||
$whereClauses[] = "h.description LIKE '%historycreated%'";
|
||||
}
|
||||
|
||||
// Date Range Filter
|
||||
$whereClauses[] = 'h.created BETWEEN :start_date AND :end_date';
|
||||
$params[':start_date'] = $filters['start'];
|
||||
$params[':end_date'] = $filters['end'];
|
||||
|
||||
// ============================================
|
||||
// Execute Query
|
||||
// ============================================
|
||||
|
||||
$whereClause = 'WHERE ' . implode(' AND ', $whereClauses);
|
||||
$sql = "SELECT h.rowID, h.description
|
||||
FROM equipment_history h
|
||||
$whereClause
|
||||
ORDER BY h.created DESC";
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($params);
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// ============================================
|
||||
// Format Response
|
||||
// ============================================
|
||||
|
||||
$results = [];
|
||||
foreach ($messages as $message) {
|
||||
$record = json_decode($message['description'], true);
|
||||
|
||||
// Handle JSON decode errors
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
continue; // Skip invalid JSON
|
||||
}
|
||||
|
||||
$record['historyID'] = (int)$message['rowID'];
|
||||
$results[] = $record;
|
||||
}
|
||||
|
||||
// Set proper headers
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
echo json_encode($results, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
// Log error (don't expose to client in production)
|
||||
error_log("Database error: " . $e->getMessage());
|
||||
|
||||
//header('Content-Type: application/json; charset=utf-8', true, 500);
|
||||
echo json_encode([
|
||||
'error' => 'An error occurred while processing your request'
|
||||
]);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -143,6 +143,10 @@ if(isset($get_content) && $get_content!=''){
|
||||
$clause .= ' AND e.serialnumber IN (:'.$v[0].')';
|
||||
}
|
||||
}
|
||||
elseif ($v[0] == 'validate') {
|
||||
// Set validation mode flag
|
||||
$validation_mode = true;
|
||||
}
|
||||
elseif ($v[0] == 'firmware') {
|
||||
//Assets with firmaware upgrade = 0 (1=latest version, 2=No software)
|
||||
$clause .= ' AND e.status != 5 AND e.sw_version_latest = 0';
|
||||
@@ -161,7 +165,7 @@ if(isset($get_content) && $get_content!=''){
|
||||
}
|
||||
}
|
||||
|
||||
if ($sw_version_latest_update == 1){
|
||||
if ($sw_version_latest_update == 1 || $clause == ''){
|
||||
//------------------------------------------
|
||||
//UPDATE SW_STATUS
|
||||
//------------------------------------------
|
||||
@@ -175,6 +179,10 @@ if (isset($criterias['download']) && $criterias['download'] ==''){
|
||||
//Request for download
|
||||
$sql = 'SELECT e.rowID as equipmentID, e.*, p.productcode, p.productname from equipment e LEFT JOIN products p ON e.productrowid = p.rowID '.$whereclause.' ORDER BY equipmentID';
|
||||
}
|
||||
elseif (isset($validation_mode) && $validation_mode === true) {
|
||||
// Validation mode - return count only for serial validation
|
||||
$sql = "SELECT count(rowID) as rowID from equipment e $whereclause";
|
||||
}
|
||||
elseif (isset($criterias['totals']) && $criterias['totals'] =='' && !isset($criterias['type'])){
|
||||
//Request for total rows
|
||||
$sql = 'SELECT count(*) as count from equipment e LEFT JOIN products p ON e.productrowid = p.rowID '.$whereclause.'';
|
||||
@@ -267,7 +275,7 @@ else {
|
||||
}
|
||||
|
||||
//SQL for Paging
|
||||
$sql = 'SELECT e.rowID as equipmentID, e.*, p.productcode, p.productname, p.product_media from equipment e LEFT JOIN products p ON e.productrowid = p.rowID '.$whereclause.' ORDER BY '.$sort.' LIMIT :page,:num_products';
|
||||
$sql = 'SELECT e.rowID as equipmentID, e.*, p.productcode, p.productname, p.product_media, psl.starts_at,psl.expires_at,psl.status as license_status from equipment e LEFT JOIN products p ON e.productrowid = p.rowID LEFT JOIN products_software_licenses psl ON e.sw_version_license = psl.license_key '.$whereclause.' ORDER BY '.$sort.' LIMIT :page,:num_products';
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
@@ -314,7 +322,19 @@ if (debug){
|
||||
//------------------------------------------
|
||||
//Add paging details
|
||||
//------------------------------------------
|
||||
if(isset($criterias['totals']) && $criterias['totals']==''){
|
||||
if (isset($validation_mode) && $validation_mode === true) {
|
||||
$stmt->execute();
|
||||
$messages = $stmt->fetch();
|
||||
|
||||
if ($messages[0] == 1) {
|
||||
echo json_encode(array('SN'=> TRUE));
|
||||
}
|
||||
else {
|
||||
echo json_encode(array('SN'=> FALSE));
|
||||
}
|
||||
return;
|
||||
}
|
||||
elseif(isset($criterias['totals']) && $criterias['totals']==''){
|
||||
$stmt->execute();
|
||||
$messages = $stmt->fetch();
|
||||
$messages = $messages[0];
|
||||
|
||||
@@ -13,27 +13,34 @@ if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} el
|
||||
|
||||
//default whereclause
|
||||
$whereclause = '';
|
||||
$hierarchy_level = getHierarchyLevel($partner);
|
||||
|
||||
switch ($permission) {
|
||||
case '4':
|
||||
switch ($hierarchy_level) {
|
||||
case '0':
|
||||
$whereclause = '';
|
||||
break;
|
||||
case '3':
|
||||
case '1':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___%';
|
||||
$whereclause = 'WHERE e.accounthierarchy like :condition';
|
||||
$whereclause = 'WHERE e.accounthierarchy like :condition ';
|
||||
break;
|
||||
case '2':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search;
|
||||
$whereclause = 'WHERE e.accounthierarchy like :condition AND (type = "'.$type1.'" or type = "'.$type2.'" or type = "'.$type3.'" or type = "'.$type9.'" or type = "'.$type14.'" or type = "'.$type16.'")';
|
||||
break;
|
||||
default:
|
||||
case '3':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%___location___'.$soldto_search;
|
||||
$whereclause = 'WHERE e.accounthierarchy like :condition AND (type = "'.$type1.'" or type = "'.$type2.'" or type = "'.$type3.'" or type = "'.$type14.'" or type = "'.$type16.'")';
|
||||
break;
|
||||
case '4':
|
||||
$condition = '__salesid___'.$partner->salesid.'___soldto___'.substr($partner->soldto, 0, strpos($partner->soldto, "-")).$soldto_search.'___shipto___'.substr($partner->shipto, 0, strpos($partner->shipto, "-")).'%___location___'.substr($partner->location, 0, strpos($partner->location, "-")).'%';
|
||||
$whereclause = 'WHERE e.accounthierarchy like :condition AND (type = "'.$type1.'" or type = "'.$type2.'" or type = "'.$type3.'" or type = "'.$type14.'" or type = "'.$type16.'")';
|
||||
break;
|
||||
}
|
||||
|
||||
//NEW ARRAY
|
||||
$criterias = [];
|
||||
$clause = '';
|
||||
$type_check = false;
|
||||
|
||||
//Check for $_GET variables and build up clause
|
||||
if(isset($get_content) && $get_content!=''){
|
||||
@@ -64,11 +71,65 @@ if(isset($get_content) && $get_content!=''){
|
||||
//build up search
|
||||
$clause .= ' AND (h.rowID like :'.$v[0].' OR h.createdby like :'.$v[0].')';
|
||||
}
|
||||
elseif ($v[0] == 'type' && $v[1] == 'servicereport') {
|
||||
//Filter out only relevant servicereports
|
||||
$filter_key_1 = '"%serialnumber%"';
|
||||
$filter_key_2 = '"ServiceReport"';
|
||||
$clause .= ' AND h.type = '.$filter_key_2.' AND NOT e.productrowid = "31" AND h.description like '.$filter_key_1;
|
||||
elseif ($v[0] == 'serialnumber') {
|
||||
//build up serialnumber
|
||||
//check if multiple serialnumbers are provided
|
||||
if (str_contains($v[1], ',')){
|
||||
$inputs = explode(",",$v[1]);
|
||||
$new_querystring = ''; //empty querystring
|
||||
$x=0;
|
||||
foreach($inputs as $input){
|
||||
//create key
|
||||
$new_key = $v[0].'_'.$x;
|
||||
//inject new key/value to array
|
||||
$criterias[$new_key] = $input;
|
||||
$new_querystring .= ':'.$new_key.',';
|
||||
$x++;
|
||||
}
|
||||
//remove obsolete last character from new_querystring
|
||||
$new_querystring = substr($new_querystring,0, -1);
|
||||
//add new_querystring to clause
|
||||
$clause .= ' AND e.serialnumber IN ('.$new_querystring.')';
|
||||
//remove original key/value from array
|
||||
unset($criterias[$v[0]]);
|
||||
}
|
||||
else {
|
||||
$clause .= ' AND e.serialnumber IN (:'.$v[0].')';
|
||||
}
|
||||
}
|
||||
elseif ($v[0] == 'type') {
|
||||
if ($v[1] == 'servicereport') {
|
||||
//Filter out only relevant servicereports
|
||||
$filter_key_1 = '"%serialnumber%"';
|
||||
$filter_key_2 = '"ServiceReport"';
|
||||
$clause .= ' AND h.type = '.$filter_key_2.' AND NOT e.productrowid = "31" AND h.description like '.$filter_key_1;
|
||||
//remove from criterias to prevent double binding
|
||||
unset($criterias[$v[0]]);
|
||||
}
|
||||
elseif (str_contains($v[1], ',')) {
|
||||
//check if multiple types are provided
|
||||
$inputs = explode(",",$v[1]);
|
||||
$new_querystring = ''; //empty querystring
|
||||
$x=0;
|
||||
foreach($inputs as $input){
|
||||
//create key
|
||||
$new_key = $v[0].'_'.$x;
|
||||
//inject new key/value to array
|
||||
$criterias[$new_key] = $input;
|
||||
$new_querystring .= ':'.$new_key.',';
|
||||
$x++;
|
||||
}
|
||||
//remove obsolete last character from new_querystring
|
||||
$new_querystring = substr($new_querystring,0, -1);
|
||||
//add new_querystring to clause
|
||||
$clause .= ' AND h.type IN ('.$new_querystring.')';
|
||||
//remove original key/value from array
|
||||
$type_check = true;
|
||||
unset($criterias[$v[0]]);
|
||||
}
|
||||
else {
|
||||
$clause .= ' AND h.type = :'.$v[0];
|
||||
}
|
||||
}
|
||||
elseif ($v[0] == 'created') {
|
||||
//build up search
|
||||
@@ -89,6 +150,9 @@ if(isset($criterias['totals']) && $criterias['totals'] ==''){
|
||||
//Request for total rows
|
||||
$sql ='SELECT count(h.rowID) as historyID FROM equipment_history h LEFT JOIN equipment e ON h.equipmentid = e.rowID '.$whereclause.'';
|
||||
}
|
||||
elseif($type_check){
|
||||
$sql ='SELECT h.rowID as historyID, e.rowID as equipmentID, e.serialnumber, h.type, h.description, h.created, h.createdby FROM equipment_history h LEFT JOIN equipment e ON h.equipmentid = e.rowID '.$whereclause.' ORDER BY h.created DESC';
|
||||
}
|
||||
else {
|
||||
//request history
|
||||
$sql ='SELECT h.rowID as historyID, e.rowID as equipmentID, e.serialnumber, h.type, h.description, h.created, h.createdby FROM equipment_history h LEFT JOIN equipment e ON h.equipmentid = e.rowID '.$whereclause.' ORDER BY h.created DESC LIMIT :page,:num_products';
|
||||
@@ -125,6 +189,12 @@ if(isset($criterias['totals']) && $criterias['totals']==''){
|
||||
$messages = $stmt->fetch();
|
||||
$messages = $messages[0];
|
||||
}
|
||||
elseif($type_check){
|
||||
//Excute Query
|
||||
$stmt->execute();
|
||||
//Get results
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
else {
|
||||
$current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1;
|
||||
$stmt->bindValue('page', ($current_page - 1) * $page_rows_history, PDO::PARAM_INT);
|
||||
@@ -136,10 +206,22 @@ else {
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
// Clean up nested JSON in description fields before final encoding
|
||||
if (!isset($criterias['totals']) || $criterias['totals'] != '') {
|
||||
foreach ($messages as &$message) {
|
||||
if (isset($message['description']) && is_string($message['description'])) {
|
||||
$decoded = json_decode($message['description'], true);
|
||||
if (json_last_error() === JSON_ERROR_NONE) {
|
||||
$message['description'] = json_encode($decoded, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//JSON_ENCODE
|
||||
//------------------------------------------
|
||||
$messages = json_encode($messages, JSON_UNESCAPED_UNICODE);
|
||||
$messages = json_encode($messages, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
//Send results
|
||||
echo $messages;
|
||||
|
||||
@@ -51,7 +51,7 @@ elseif (isset($criterias['list']) && $criterias['list'] =='invoice'){
|
||||
//SQL for Paging
|
||||
$sql = 'SELECT tx.*, txi.item_id as item_id,txi.item_price as item_price, txi.item_quantity as item_quantity, txi.item_options as item_options, p.productcode, p.productname, inv.id as invoice, inv.created as invoice_created, i.language as user_language
|
||||
FROM transactions tx
|
||||
left join invoice inv ON tx.id = inv.txn_id
|
||||
left join invoice inv ON tx.txn_id = inv.txn_id
|
||||
left join transactions_items txi ON tx.id = txi.txn_id
|
||||
left join products p ON p.rowID = txi.item_id
|
||||
left join identity i ON i.userkey = tx.account_id '.$whereclause;
|
||||
|
||||
152
api/v2/get/marketing_files.php
Normal file
152
api/v2/get/marketing_files.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Marketing Files
|
||||
//------------------------------------------
|
||||
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//SoldTo is empty
|
||||
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
|
||||
|
||||
//default whereclause
|
||||
$whereclause = '';
|
||||
|
||||
//NEW ARRAY
|
||||
$criterias = [];
|
||||
$clause = '';
|
||||
|
||||
//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];
|
||||
|
||||
if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] == 'action' || $v[0] =='success_msg' || $v[0] == '_t'){
|
||||
//do nothing
|
||||
}
|
||||
elseif ($v[0] == 'folder_id') {
|
||||
if ($v[1] === 'null' || $v[1] === '') {
|
||||
$clause .= ' AND folder_id IS NULL';
|
||||
} else {
|
||||
$clause .= ' AND folder_id = :folder_id';
|
||||
}
|
||||
}
|
||||
elseif ($v[0] == 'search') {
|
||||
$clause .= ' AND (title LIKE :search OR original_filename LIKE :search)';
|
||||
}
|
||||
elseif ($v[0] == 'tag') {
|
||||
$clause .= ' AND EXISTS (SELECT 1 FROM marketing_file_tags ft JOIN marketing_tags t ON ft.tag_id = t.id WHERE ft.file_id = mf.id AND t.tag_name = :tag)';
|
||||
}
|
||||
elseif ($v[0] == 'file_type') {
|
||||
$clause .= ' AND file_type = :file_type';
|
||||
}
|
||||
else {
|
||||
// Ignore unknown parameters
|
||||
}
|
||||
}
|
||||
if ($whereclause == '' && $clause !=''){
|
||||
$whereclause = 'WHERE '.substr($clause, 4);
|
||||
} else {
|
||||
$whereclause .= $clause;
|
||||
}
|
||||
}
|
||||
|
||||
//Set page
|
||||
$pagina = 1;
|
||||
if(isset($criterias['p']) && $criterias['p'] !='') {
|
||||
$pagina = $criterias['p'];
|
||||
}
|
||||
|
||||
//Set limit
|
||||
$limit = 50;
|
||||
if(isset($criterias['limit']) && $criterias['limit'] !='') {
|
||||
$limit = intval($criterias['limit']);
|
||||
}
|
||||
$offset = ($pagina - 1) * $limit;
|
||||
|
||||
//check for totals call
|
||||
if(isset($criterias['totals'])){
|
||||
$sql = 'SELECT COUNT(*) as found FROM marketing_files mf '.$whereclause.' ';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
// Bind parameters
|
||||
if (!empty($criterias)) {
|
||||
foreach ($criterias as $key => $value) {
|
||||
if ($key !== 'totals' && $key !== 'page' && $key !== 'p' && $key !== 'limit' && $key !== 'action') {
|
||||
if ($key == 'search') {
|
||||
$stmt->bindValue(':'.$key, '%'.$value.'%');
|
||||
} elseif ($key == 'folder_id' && ($value === 'null' || $value === '')) {
|
||||
continue;
|
||||
} else {
|
||||
$stmt->bindValue(':'.$key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
$found = $stmt->fetchColumn();
|
||||
echo $found;
|
||||
exit;
|
||||
}
|
||||
|
||||
// Main query
|
||||
$sql = "SELECT
|
||||
mf.*,
|
||||
GROUP_CONCAT(mt.tag_name) as tags
|
||||
FROM marketing_files mf
|
||||
LEFT JOIN marketing_file_tags mft ON mf.id = mft.file_id
|
||||
LEFT JOIN marketing_tags mt ON mft.tag_id = mt.id
|
||||
" . $whereclause . "
|
||||
GROUP BY mf.id
|
||||
ORDER BY mf.created DESC
|
||||
LIMIT " . $limit . " OFFSET " . $offset;
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
// Bind parameters
|
||||
if (!empty($criterias)) {
|
||||
foreach ($criterias as $key => $value) {
|
||||
if ($key !== 'totals' && $key !== 'page' && $key !== 'p' && $key !== 'limit') {
|
||||
if ($key == 'search') {
|
||||
$stmt->bindValue(':'.$key, '%'.$value.'%');
|
||||
} elseif ($key == 'folder_id' && ($value === 'null' || $value === '')) {
|
||||
continue;
|
||||
} else {
|
||||
$stmt->bindValue(':'.$key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
$marketing_files = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Process each file
|
||||
foreach ($marketing_files as &$file) {
|
||||
// Process tags
|
||||
$file['tags'] = $file['tags'] ? explode(',', $file['tags']) : [];
|
||||
|
||||
// Format file size
|
||||
$bytes = $file['file_size'];
|
||||
if ($bytes >= 1073741824) {
|
||||
$file['file_size_formatted'] = number_format($bytes / 1073741824, 2) . ' GB';
|
||||
} elseif ($bytes >= 1048576) {
|
||||
$file['file_size_formatted'] = number_format($bytes / 1048576, 2) . ' MB';
|
||||
} elseif ($bytes >= 1024) {
|
||||
$file['file_size_formatted'] = number_format($bytes / 1024, 2) . ' KB';
|
||||
} else {
|
||||
$file['file_size_formatted'] = $bytes . ' B';
|
||||
}
|
||||
}
|
||||
|
||||
// Return result
|
||||
echo json_encode($marketing_files, JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
165
api/v2/get/marketing_folders.php
Normal file
165
api/v2/get/marketing_folders.php
Normal file
@@ -0,0 +1,165 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
//------------------------------------------
|
||||
// Marketing Folders
|
||||
//------------------------------------------
|
||||
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
// Function to build hierarchical tree structure
|
||||
function buildFolderTree($folders, $parentId = null) {
|
||||
$tree = [];
|
||||
|
||||
foreach ($folders as $folder) {
|
||||
if ($folder['parent_id'] == $parentId) {
|
||||
$children = buildFolderTree($folders, $folder['id']);
|
||||
$folder['children'] = $children; // Always include children array, even if empty
|
||||
$tree[] = $folder;
|
||||
}
|
||||
}
|
||||
|
||||
return $tree;
|
||||
}
|
||||
|
||||
//SoldTo is empty
|
||||
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
|
||||
|
||||
//default whereclause
|
||||
$whereclause = '';
|
||||
|
||||
//NEW ARRAY
|
||||
$criterias = [];
|
||||
$clause = '';
|
||||
|
||||
//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];
|
||||
|
||||
if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] =='success_msg' || $v[0] == 'action' || $v[0] == 'tree'){
|
||||
//do nothing - these are not SQL parameters
|
||||
}
|
||||
elseif ($v[0] == 'parent_id') {
|
||||
if ($v[1] === 'null' || $v[1] === '') {
|
||||
$clause .= ' AND parent_id IS NULL';
|
||||
} else {
|
||||
$clause .= ' AND parent_id = :parent_id';
|
||||
}
|
||||
}
|
||||
elseif ($v[0] == 'search') {
|
||||
$clause .= ' AND (folder_name LIKE :search OR description LIKE :search)';
|
||||
}
|
||||
else {//create clause
|
||||
$clause .= ' AND '.$v[0].' = :'.$v[0];
|
||||
}
|
||||
}
|
||||
if ($whereclause == '' && $clause !=''){
|
||||
$whereclause = 'WHERE '.substr($clause, 4);
|
||||
} else {
|
||||
$whereclause .= $clause;
|
||||
}
|
||||
}
|
||||
|
||||
//Define Query
|
||||
if(isset($criterias['totals']) && $criterias['totals'] ==''){
|
||||
//Request for total rows
|
||||
$sql = 'SELECT count(*) as count FROM marketing_folders '.$whereclause.'';
|
||||
}
|
||||
elseif (isset($criterias['list']) && $criterias['list'] =='') {
|
||||
//SQL for list (no paging)
|
||||
$sql = "SELECT
|
||||
mf.*,
|
||||
(SELECT COUNT(*) FROM marketing_files WHERE folder_id = mf.id) as file_count,
|
||||
(SELECT COUNT(*) FROM marketing_folders WHERE parent_id = mf.id) as subfolder_count,
|
||||
CASE
|
||||
WHEN mf.parent_id IS NOT NULL THEN
|
||||
(SELECT folder_name FROM marketing_folders WHERE id = mf.parent_id)
|
||||
ELSE NULL
|
||||
END as parent_folder_name
|
||||
FROM marketing_folders mf
|
||||
" . $whereclause . "
|
||||
ORDER BY mf.folder_name ASC";
|
||||
}
|
||||
else {
|
||||
//SQL for paging
|
||||
$sql = "SELECT
|
||||
mf.*,
|
||||
(SELECT COUNT(*) FROM marketing_files WHERE folder_id = mf.id) as file_count,
|
||||
(SELECT COUNT(*) FROM marketing_folders WHERE parent_id = mf.id) as subfolder_count,
|
||||
CASE
|
||||
WHEN mf.parent_id IS NOT NULL THEN
|
||||
(SELECT folder_name FROM marketing_folders WHERE id = mf.parent_id)
|
||||
ELSE NULL
|
||||
END as parent_folder_name
|
||||
FROM marketing_folders mf
|
||||
" . $whereclause . "
|
||||
ORDER BY mf.folder_name ASC
|
||||
LIMIT :page,:num_folders";
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
if (!empty($criterias)){
|
||||
foreach ($criterias as $key => $value){
|
||||
$key_condition = ':'.$key;
|
||||
if (str_contains($whereclause, $key_condition)){
|
||||
if ($key == 'search'){
|
||||
$search_value = '%'.$value.'%';
|
||||
$stmt->bindValue($key, $search_value, PDO::PARAM_STR);
|
||||
}
|
||||
elseif ($key == 'parent_id' && ($value === 'null' || $value === '')) {
|
||||
// Skip binding for NULL parent_id
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
$stmt->bindValue($key, $value, PDO::PARAM_STR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Add paging details
|
||||
if(isset($criterias['totals']) && $criterias['totals']==''){
|
||||
$stmt->execute();
|
||||
$messages = $stmt->fetch();
|
||||
$messages = $messages[0];
|
||||
}
|
||||
elseif(isset($criterias['list']) && $criterias['list']==''){
|
||||
//Execute Query
|
||||
$stmt->execute();
|
||||
//Get results
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
else {
|
||||
$current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1;
|
||||
$stmt->bindValue('page', ($current_page - 1) * $page_rows_folders, PDO::PARAM_INT);
|
||||
$stmt->bindValue('num_folders', $page_rows_folders, PDO::PARAM_INT);
|
||||
|
||||
//Execute Query
|
||||
$stmt->execute();
|
||||
//Get results
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
// Check if tree structure is requested
|
||||
if (isset($criterias['tree']) && isset($messages) && is_array($messages)) {
|
||||
// Build hierarchical tree structure
|
||||
$messages = buildFolderTree($messages);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//JSON_ENCODE
|
||||
//------------------------------------------
|
||||
$messages = json_encode($messages, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
//Send results
|
||||
echo $messages;
|
||||
112
api/v2/get/marketing_tags.php
Normal file
112
api/v2/get/marketing_tags.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Marketing Tags
|
||||
//------------------------------------------
|
||||
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//SoldTo is empty
|
||||
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
|
||||
|
||||
//default whereclause
|
||||
$whereclause = '';
|
||||
|
||||
//NEW ARRAY
|
||||
$criterias = [];
|
||||
$clause = '';
|
||||
|
||||
//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];
|
||||
|
||||
if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='list' || $v[0] =='success_msg' || $v[0] == 'action'){
|
||||
//do nothing
|
||||
}
|
||||
elseif ($v[0] == 'search') {
|
||||
$clause .= ' AND tag_name LIKE :search';
|
||||
}
|
||||
elseif ($v[0] == 'used_only') {
|
||||
if ($v[1] === 'true') {
|
||||
$clause .= ' AND id IN (SELECT DISTINCT tag_id FROM marketing_file_tags)';
|
||||
}
|
||||
}
|
||||
else {//create clause
|
||||
$clause .= ' AND '.$v[0].' = :'.$v[0];
|
||||
}
|
||||
}
|
||||
if ($whereclause == '' && $clause !=''){
|
||||
$whereclause = 'WHERE '.substr($clause, 4);
|
||||
} else {
|
||||
$whereclause .= $clause;
|
||||
}
|
||||
}
|
||||
|
||||
//Set page
|
||||
$pagina = 1;
|
||||
if(isset($criterias['p']) && $criterias['p'] !='') {
|
||||
$pagina = $criterias['p'];
|
||||
}
|
||||
|
||||
//check for totals call
|
||||
if(isset($criterias['totals'])){
|
||||
$sql = 'SELECT COUNT(*) as found FROM marketing_tags mt '.$whereclause.' ';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
// Bind parameters
|
||||
if (!empty($criterias)) {
|
||||
foreach ($criterias as $key => $value) {
|
||||
if ($key !== 'totals' && $key !== 'page' && $key !== 'p' && $key !== 'used_only') {
|
||||
if ($key == 'search') {
|
||||
$stmt->bindValue(':'.$key, '%'.$value.'%');
|
||||
} else {
|
||||
$stmt->bindValue(':'.$key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
$found = $stmt->fetchColumn();
|
||||
echo $found;
|
||||
exit;
|
||||
}
|
||||
|
||||
// Main query
|
||||
$sql = "SELECT
|
||||
mt.*,
|
||||
COUNT(mft.file_id) as usage_count
|
||||
FROM marketing_tags mt
|
||||
LEFT JOIN marketing_file_tags mft ON mt.id = mft.tag_id
|
||||
" . $whereclause . "
|
||||
GROUP BY mt.id
|
||||
ORDER BY mt.tag_name ASC";
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
// Bind parameters
|
||||
if (!empty($criterias)) {
|
||||
foreach ($criterias as $key => $value) {
|
||||
if ($key !== 'totals' && $key !== 'page' && $key !== 'p' && $key !== 'used_only') {
|
||||
if ($key == 'search') {
|
||||
$stmt->bindValue(':'.$key, '%'.$value.'%');
|
||||
} else {
|
||||
$stmt->bindValue(':'.$key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$stmt->execute();
|
||||
$marketing_tags = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Return result
|
||||
echo json_encode($marketing_tags, JSON_UNESCAPED_UNICODE);
|
||||
@@ -49,7 +49,7 @@ if (!$transaction) {
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
$sql = 'SELECT * FROM transactions_items WHERE txn_id = ? LIMIT 1';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$payment_id]);
|
||||
$stmt->execute([$transaction['id']]);
|
||||
$item = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$item) {
|
||||
|
||||
@@ -12,7 +12,7 @@ $pdo = dbConnect($dbname);
|
||||
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
|
||||
|
||||
//default whereclause
|
||||
list($whereclause,$condition) = getWhereclauselvl2("software_upgrade_paths",$permission,$partner,'get');
|
||||
list($whereclause,$condition) = getWhereclauselvl2("",$permission,$partner,'get');
|
||||
|
||||
//NEW ARRAY
|
||||
$criterias = [];
|
||||
|
||||
@@ -12,7 +12,7 @@ $pdo = dbConnect($dbname);
|
||||
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
|
||||
|
||||
//default whereclause
|
||||
list($whereclause,$condition) = getWhereclauselvl2("software_versions",$permission,$partner,'get');
|
||||
list($whereclause,$condition) = getWhereclauselvl2("",$permission,$partner,'get');
|
||||
|
||||
//NEW ARRAY
|
||||
$criterias = [];
|
||||
|
||||
152
api/v2/get/report_builder.php
Normal file
152
api/v2/get/report_builder.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Report Builder - GET Endpoints
|
||||
//------------------------------------------
|
||||
|
||||
// Set content type to JSON
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
// Get the action parameter from URL
|
||||
$criterias = [];
|
||||
if (isset($get_content) && $get_content != '') {
|
||||
$requests = explode("&", $get_content);
|
||||
foreach ($requests as $y) {
|
||||
$v = explode("=", $y);
|
||||
if (isset($v[1])) {
|
||||
$criterias[$v[0]] = urldecode($v[1]);
|
||||
} else {
|
||||
$criterias[$v[0]] = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$action = strtolower($criterias['action'] ?? '');
|
||||
|
||||
/**
|
||||
* Validate table name - only allow alphanumeric, underscores, hyphens
|
||||
*/
|
||||
function sanitizeTableName($table) {
|
||||
if (!preg_match('/^[a-zA-Z0-9_-]+$/', $table)) {
|
||||
return false;
|
||||
}
|
||||
return $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of tables
|
||||
*/
|
||||
if ($action === 'gettables') {
|
||||
try {
|
||||
$result = $pdo->query("SHOW TABLES");
|
||||
$tables = [];
|
||||
while ($row = $result->fetch(PDO::FETCH_NUM)) {
|
||||
$tables[] = $row[0];
|
||||
}
|
||||
|
||||
$messages = json_encode([
|
||||
'success' => true,
|
||||
'tables' => $tables
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
$messages = json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Failed to fetch tables'
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get columns for a specific table
|
||||
*/
|
||||
elseif ($action === 'getcolumns') {
|
||||
$table = sanitizeTableName($criterias['table'] ?? '');
|
||||
|
||||
if (!$table) {
|
||||
http_response_code(400);
|
||||
$messages = json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Invalid table name'
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
} else {
|
||||
try {
|
||||
$result = $pdo->query("SHOW COLUMNS FROM `$table`");
|
||||
$columns = [];
|
||||
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
|
||||
$columns[] = $row['Field'];
|
||||
}
|
||||
|
||||
$messages = json_encode([
|
||||
'success' => true,
|
||||
'columns' => $columns
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
$messages = json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Failed to fetch columns'
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get table schema information
|
||||
*/
|
||||
elseif ($action === 'gettableschema') {
|
||||
$table = sanitizeTableName($criterias['table'] ?? '');
|
||||
|
||||
if (!$table) {
|
||||
http_response_code(400);
|
||||
$messages = json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Invalid table name'
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
} else {
|
||||
try {
|
||||
$result = $pdo->query("DESCRIBE `$table`");
|
||||
$schema = [];
|
||||
while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
|
||||
$schema[] = [
|
||||
'field' => $row['Field'],
|
||||
'type' => $row['Type'],
|
||||
'null' => $row['Null'],
|
||||
'key' => $row['Key'],
|
||||
'default' => $row['Default'],
|
||||
'extra' => $row['Extra']
|
||||
];
|
||||
}
|
||||
|
||||
$messages = json_encode([
|
||||
'success' => true,
|
||||
'schema' => $schema
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
} catch (Exception $e) {
|
||||
http_response_code(500);
|
||||
$messages = json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Failed to fetch table schema'
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalid or missing action
|
||||
*/
|
||||
else {
|
||||
http_response_code(400);
|
||||
$messages = json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Invalid or missing action parameter'
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
// Send results
|
||||
echo $messages;
|
||||
?>
|
||||
123
api/v2/get/role_access_permissions.php
Normal file
123
api/v2/get/role_access_permissions.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Role Access Permissions
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//------------------------------------------
|
||||
//NEW ARRAY
|
||||
//------------------------------------------
|
||||
$criterias = [];
|
||||
$clause = '';
|
||||
|
||||
//------------------------------------------
|
||||
//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];
|
||||
if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='success_msg'){
|
||||
//do nothing
|
||||
}
|
||||
elseif ($v[0] == 'rowid') {
|
||||
//build up search by ID
|
||||
$clause .= ' AND rap.rowID = :'.$v[0];
|
||||
}
|
||||
elseif ($v[0] == 'role_id') {
|
||||
//build up search by role_id
|
||||
$clause .= ' AND rap.role_id = :'.$v[0];
|
||||
}
|
||||
elseif ($v[0] == 'access_id') {
|
||||
//build up search by access_id
|
||||
$clause .= ' AND rap.access_id = :'.$v[0];
|
||||
}
|
||||
else {
|
||||
//create clause
|
||||
$clause .= ' AND rap.'.$v[0].' = :'.$v[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Build WHERE clause
|
||||
$whereclause = '';
|
||||
if ($clause != ''){
|
||||
$whereclause = 'WHERE '.substr($clause, 4);
|
||||
}
|
||||
|
||||
if (isset($criterias['totals']) && $criterias['totals'] ==''){
|
||||
//Request for total rows
|
||||
$sql = 'SELECT count(*) as count FROM role_access_permissions rap '.$whereclause;
|
||||
}
|
||||
else {
|
||||
//SQL with joined tables for names
|
||||
$sql = 'SELECT rap.*,
|
||||
r.name as role_name,
|
||||
ae.access_name,
|
||||
ae.access_path
|
||||
FROM role_access_permissions rap
|
||||
LEFT JOIN user_roles r ON rap.role_id = r.rowID
|
||||
LEFT JOIN access_elements ae ON rap.access_id = ae.rowID
|
||||
'.$whereclause.'
|
||||
ORDER BY ae.access_name ASC';
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
//------------------------------------------
|
||||
//Bind to query
|
||||
//------------------------------------------
|
||||
if (!empty($criterias)){
|
||||
foreach ($criterias as $key => $value){
|
||||
$key_condition = ':'.$key;
|
||||
if (str_contains($sql, $key_condition)){
|
||||
if ($key == 'p'){
|
||||
//Do nothing (bug)
|
||||
}
|
||||
else {
|
||||
$stmt->bindValue($key, $value, PDO::PARAM_STR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
// Debuglog
|
||||
//------------------------------------------
|
||||
if (debug){
|
||||
$message = $date.';'.$sql.';'.$username;
|
||||
debuglog($message);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//Execute Query
|
||||
//------------------------------------------
|
||||
if(isset($criterias['totals']) && $criterias['totals']==''){
|
||||
$stmt->execute();
|
||||
$messages = $stmt->fetch();
|
||||
$messages = $messages[0];
|
||||
}
|
||||
else {
|
||||
//Execute Query
|
||||
$stmt->execute();
|
||||
//Get results
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//JSON_EnCODE
|
||||
//------------------------------------------
|
||||
$messages = json_encode($messages, JSON_UNESCAPED_UNICODE);
|
||||
//------------------------------------------
|
||||
//Send results
|
||||
//------------------------------------------
|
||||
echo $messages;
|
||||
|
||||
?>
|
||||
82
api/v2/get/service.php
Normal file
82
api/v2/get/service.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
//------------------------------------------
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//------------------------------------------
|
||||
// Application related calls
|
||||
//------------------------------------------
|
||||
$request = explode('/', trim($_SERVER['PATH_INFO'],'/'));
|
||||
$action = $request[2] ?? '';
|
||||
|
||||
if ($action == 'init'){
|
||||
include './settings/systemservicetool_init.php';
|
||||
echo json_encode($init);
|
||||
}
|
||||
elseif ($action == 'questions' && (isset($_GET['type']) && $_GET['type'] != '')){
|
||||
|
||||
include './settings/systemservicetool.php';
|
||||
|
||||
//build questions
|
||||
switch ($_GET['type']) {
|
||||
case 'visual':
|
||||
$arrayQuestions = $arrayQuestions_visual;
|
||||
break;
|
||||
|
||||
case 'final':
|
||||
$arrayQuestions = $arrayQuestions_finalize;
|
||||
break;
|
||||
|
||||
case 'cartest':
|
||||
include './settings/systemcartest.php';
|
||||
$arrayQuestions = $arrayQuestions_cartest;
|
||||
break;
|
||||
}
|
||||
//Return JSON
|
||||
echo json_encode($arrayQuestions);
|
||||
}
|
||||
elseif ($action == 'products') {
|
||||
|
||||
$sql = "SELECT * FROM products";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute();
|
||||
//Get results
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode($messages);
|
||||
|
||||
}
|
||||
elseif ($action == 'equipments' && (isset($_GET['serialnumber']) && $_GET['serialnumber'] != '' && !isset($_GET['validate']))) {
|
||||
|
||||
$sql = "SELECT e.rowID as equipmentID, e.*, p.productcode, p.productname, p.product_media, psl.starts_at,psl.expires_at,psl.status as license_status from equipment e LEFT JOIN products p ON e.productrowid = p.rowID LEFT JOIN products_software_licenses psl ON e.sw_version_license = psl.license_key WHERE e.serialnumber = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$_GET['serialnumber']]);
|
||||
//Get results
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
echo json_encode($messages);
|
||||
|
||||
}
|
||||
elseif ($action == 'equipments' && (isset($_GET['serialnumber']) && $_GET['serialnumber'] != '' && isset($_GET['validate']))){
|
||||
|
||||
$sql = "SELECT count(rowID) as rowID from equipment e WHERE e.serialnumber = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$_GET['serialnumber']]);
|
||||
$messages = $stmt->fetch();
|
||||
|
||||
if ($messages[0] == 1) {
|
||||
echo json_encode(array('SN'=> TRUE));
|
||||
}
|
||||
else {
|
||||
echo json_encode(array('SN'=> FALSE));
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
http_response_code(400);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -62,6 +62,7 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
e.sw_version as current_sw_version,
|
||||
e.hw_version,
|
||||
e.sw_version_license,
|
||||
e.sw_version_upgrade,
|
||||
e.rowID as equipment_rowid
|
||||
FROM equipment e
|
||||
JOIN products p ON e.productrowid = p.rowID
|
||||
@@ -78,6 +79,7 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
$current_sw_version = $equipment_data['current_sw_version'];
|
||||
$hw_version = $equipment_data['hw_version'];
|
||||
$sw_version_license = $equipment_data['sw_version_license'];
|
||||
$sw_version_upgrade = $equipment_data['sw_version_upgrade'];
|
||||
$equipment_rowid = $equipment_data['equipment_rowid'];
|
||||
|
||||
if (debug) {
|
||||
@@ -85,7 +87,8 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
'product_rowid' => $product_rowid,
|
||||
'productcode' => $productcode,
|
||||
'current_sw_version_raw' => $current_sw_version,
|
||||
'hw_version' => $hw_version
|
||||
'hw_version' => $hw_version,
|
||||
'sw_version_upgrade' => $sw_version_upgrade
|
||||
];
|
||||
}
|
||||
|
||||
@@ -119,6 +122,77 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check if sw_version_upgrade is set - this overrides normal availability check
|
||||
if (!empty($sw_version_upgrade)) {
|
||||
if (debug) {
|
||||
$debug['sw_version_upgrade_check'] = [
|
||||
'sw_version_upgrade_id' => $sw_version_upgrade,
|
||||
'checking_override' => true
|
||||
];
|
||||
}
|
||||
|
||||
// Check if this version exists and is active
|
||||
$sql = 'SELECT
|
||||
psv.rowID as version_id,
|
||||
psv.version,
|
||||
psv.name,
|
||||
psv.description,
|
||||
psv.mandatory,
|
||||
psv.latest,
|
||||
psv.hw_version,
|
||||
psv.file_path,
|
||||
psv.status
|
||||
FROM products_software_versions psv
|
||||
WHERE psv.rowID = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$sw_version_upgrade]);
|
||||
$upgrade_version = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($upgrade_version && $upgrade_version['status'] == 1) {
|
||||
// Valid override found - check if different from current version
|
||||
$normalized_upgrade_version = strtolower(ltrim($upgrade_version['version'], '0'));
|
||||
|
||||
if (debug) {
|
||||
$debug['sw_version_upgrade_check']['found_version'] = [
|
||||
'version' => $upgrade_version['version'],
|
||||
'name' => $upgrade_version['name'],
|
||||
'normalized' => $normalized_upgrade_version,
|
||||
'status' => $upgrade_version['status'],
|
||||
'is_different_from_current' => ($current_sw_version != $normalized_upgrade_version)
|
||||
];
|
||||
}
|
||||
|
||||
if ($current_sw_version && $normalized_upgrade_version == $current_sw_version) {
|
||||
// Override version is same as current - no upgrade available
|
||||
$software_available = "no";
|
||||
if (debug) {
|
||||
$debug['sw_version_upgrade_check']['decision'] = 'Override version is same as current version';
|
||||
}
|
||||
} else {
|
||||
// Override version is different - upgrade is available
|
||||
$software_available = "yes";
|
||||
if (debug) {
|
||||
$debug['sw_version_upgrade_check']['decision'] = 'Override version is available';
|
||||
}
|
||||
}
|
||||
|
||||
$messages = ["software_available" => $software_available];
|
||||
|
||||
if (debug) {
|
||||
debuglog(json_encode($debug));
|
||||
}
|
||||
|
||||
echo json_encode($messages, JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
} else {
|
||||
// Override version not found or inactive - fall back to standard check
|
||||
if (debug) {
|
||||
$debug['sw_version_upgrade_check']['found_version'] = $upgrade_version ? 'found but inactive' : 'not found';
|
||||
$debug['sw_version_upgrade_check']['decision'] = 'Falling back to standard check';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//GET ALL ACTIVE SOFTWARE ASSIGNMENTS for this product with matching HW version
|
||||
$sql = 'SELECT
|
||||
psv.rowID as version_id,
|
||||
@@ -161,6 +235,7 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
$debug['decision'] = 'No active software assignments found';
|
||||
}
|
||||
} else {
|
||||
$available_upgrades = 0;
|
||||
$has_priced_options = false;
|
||||
$has_latest_version_different = false;
|
||||
|
||||
@@ -219,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);
|
||||
@@ -242,6 +318,8 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
}
|
||||
|
||||
if ($show_version) {
|
||||
$available_upgrades++;
|
||||
|
||||
//Check if there's a valid license for this upgrade
|
||||
if ($final_price > 0 && $sw_version_license) {
|
||||
//Check if the license is valid
|
||||
@@ -286,23 +364,18 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
}
|
||||
}
|
||||
|
||||
// Apply the logic:
|
||||
// 1. If there are priced options -> "yes"
|
||||
// 2. If no priced options but current version != latest flagged version -> "yes"
|
||||
// 3. Default -> "no"
|
||||
if ($has_priced_options) {
|
||||
// Simple logic: if any upgrades are available to show, return "yes"
|
||||
if ($available_upgrades > 0) {
|
||||
$software_available = "yes";
|
||||
$availability_reason = "Has priced upgrade options available";
|
||||
} elseif ($has_latest_version_different) {
|
||||
$software_available = "yes";
|
||||
$availability_reason = "Has free latest version available";
|
||||
$availability_reason = "Software upgrades available";
|
||||
} else {
|
||||
$software_available = "no";
|
||||
$availability_reason = "No upgrades available or already on latest";
|
||||
$availability_reason = "No upgrades available";
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
$debug['final_decision'] = [
|
||||
'available_upgrades' => $available_upgrades,
|
||||
'has_priced_options' => $has_priced_options,
|
||||
'has_latest_version_different' => $has_latest_version_different,
|
||||
'software_available' => $software_available,
|
||||
|
||||
@@ -55,16 +55,20 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
}
|
||||
|
||||
//GET EQUIPMENT AND PRODUCT DATA BASED ON SERIAL NUMBER
|
||||
$sql = 'SELECT
|
||||
$sql = "SELECT
|
||||
p.rowID as product_rowid,
|
||||
p.productcode,
|
||||
e.sw_version as current_sw_version,
|
||||
e.hw_version,
|
||||
e.sw_version_license,
|
||||
e.rowID as equipment_rowid
|
||||
e.sw_version_upgrade,
|
||||
e.rowID as equipment_rowid,
|
||||
partner.*
|
||||
FROM equipment e
|
||||
JOIN products p ON e.productrowid = p.rowID
|
||||
WHERE e.serialnumber = ?';
|
||||
LEFT JOIN partner ON partner.partnerID = SUBSTRING_INDEX(JSON_UNQUOTE(JSON_EXTRACT(e.accounthierarchy, '$.soldto')), '-', 1)
|
||||
AND partner.is_dealer = 1 AND partner.status = 1
|
||||
WHERE e.serialnumber = ?";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$criterias['sn']]);
|
||||
$equipment_data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
@@ -77,15 +81,28 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
$current_sw_version = $equipment_data['current_sw_version'];
|
||||
$hw_version = $equipment_data['hw_version'];
|
||||
$sw_version_license = $equipment_data['sw_version_license'];
|
||||
$sw_version_upgrade = $equipment_data['sw_version_upgrade'];
|
||||
$equipment_rowid = $equipment_data['equipment_rowid'];
|
||||
|
||||
$dealer_info = [
|
||||
'is_dealer' => $equipment_data['is_dealer'] ?? 0,
|
||||
'name' => $equipment_data['name'] ?? '',
|
||||
'address' => $equipment_data['address'] ?? '',
|
||||
'city' => $equipment_data['city'] ?? '',
|
||||
'postalcode' => $equipment_data['postalcode'] ?? '',
|
||||
'country' => $equipment_data['country'] ?? '',
|
||||
'email' => $equipment_data['email'] ?? '',
|
||||
'phone' => $equipment_data['phone'] ?? ''
|
||||
];
|
||||
|
||||
if (debug) {
|
||||
$debug['equipment_data'] = [
|
||||
'product_rowid' => $product_rowid,
|
||||
'productcode' => $productcode,
|
||||
'current_sw_version_raw' => $current_sw_version,
|
||||
'hw_version' => $hw_version,
|
||||
'sw_version_license' => $sw_version_license
|
||||
'sw_version_license' => $sw_version_license,
|
||||
'sw_version_upgrade' => $sw_version_upgrade
|
||||
];
|
||||
}
|
||||
|
||||
@@ -119,6 +136,95 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
exit;
|
||||
}
|
||||
|
||||
// Check if sw_version_upgrade is set - this overrides normal availability check
|
||||
if (!empty($sw_version_upgrade)) {
|
||||
if (debug) {
|
||||
$debug['sw_version_upgrade_check'] = [
|
||||
'sw_version_upgrade_id' => $sw_version_upgrade,
|
||||
'checking_override' => true
|
||||
];
|
||||
}
|
||||
|
||||
// Check if this version exists and is active
|
||||
$sql = 'SELECT
|
||||
psv.rowID as version_id,
|
||||
psv.version,
|
||||
psv.name,
|
||||
psv.description,
|
||||
psv.mandatory,
|
||||
psv.latest,
|
||||
psv.hw_version,
|
||||
psv.file_path,
|
||||
psv.status
|
||||
FROM products_software_versions psv
|
||||
WHERE psv.rowID = ?';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$sw_version_upgrade]);
|
||||
$upgrade_version = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($upgrade_version && $upgrade_version['status'] == 1) {
|
||||
// Valid override found - check if different from current version
|
||||
$normalized_upgrade_version = strtolower(ltrim($upgrade_version['version'], '0'));
|
||||
|
||||
if (debug) {
|
||||
$debug['sw_version_upgrade_check']['found_version'] = [
|
||||
'version' => $upgrade_version['version'],
|
||||
'name' => $upgrade_version['name'],
|
||||
'normalized' => $normalized_upgrade_version,
|
||||
'status' => $upgrade_version['status'],
|
||||
'is_different_from_current' => ($current_sw_version != $normalized_upgrade_version)
|
||||
];
|
||||
}
|
||||
|
||||
if (!$current_sw_version || $current_sw_version == '' || $normalized_upgrade_version != $current_sw_version) {
|
||||
// Override version is different from current (or no current) - return only this upgrade
|
||||
$output[] = [
|
||||
"productcode" => $productcode,
|
||||
"name" => $upgrade_version['name'] ?? '',
|
||||
"version" => $upgrade_version['version'],
|
||||
"version_id" => $upgrade_version['version_id'],
|
||||
"description" => $upgrade_version['description'] ?? '',
|
||||
"hw_version" => $upgrade_version['hw_version'] ?? '',
|
||||
"mandatory" => $upgrade_version['mandatory'] ?? '',
|
||||
"latest" => $upgrade_version['latest'] ?? '',
|
||||
"software" => $upgrade_version['file_path'] ?? '',
|
||||
"source" => '',
|
||||
"source_type" => '',
|
||||
"price" => '0.00',
|
||||
"currency" => '',
|
||||
"is_current" => false
|
||||
];
|
||||
|
||||
// Generate download token
|
||||
$download_token = create_download_url_token($criterias['sn'], $upgrade_version['version_id']);
|
||||
$download_url = 'https://'.$_SERVER['SERVER_NAME'].'/api.php/v2/software_download?token='.$download_token;
|
||||
$output[0]['source'] = $download_url;
|
||||
$output[0]['source_type'] = 'token_url';
|
||||
|
||||
if (debug) {
|
||||
$debug['sw_version_upgrade_check']['decision'] = 'Override version returned as only upgrade';
|
||||
$output[0]['_debug'] = $debug;
|
||||
}
|
||||
} else {
|
||||
// Override version is same as current - no upgrades
|
||||
if (debug) {
|
||||
$debug['sw_version_upgrade_check']['decision'] = 'Override version is same as current version - no upgrades';
|
||||
$output = ['message' => 'No upgrades available', 'debug' => $debug];
|
||||
}
|
||||
}
|
||||
|
||||
$messages = $output;
|
||||
echo json_encode($messages, JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
} else {
|
||||
// Override version not found or inactive - fall back to standard check
|
||||
if (debug) {
|
||||
$debug['sw_version_upgrade_check']['found_version'] = $upgrade_version ? 'found but inactive' : 'not found';
|
||||
$debug['sw_version_upgrade_check']['decision'] = 'Falling back to standard check';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//GET ALL ACTIVE SOFTWARE ASSIGNMENTS for this product with matching HW version
|
||||
$sql = 'SELECT
|
||||
psv.rowID as version_id,
|
||||
@@ -212,16 +318,13 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
$decision_reason = 'Skipped - is current version but no upgrades scenario';
|
||||
}
|
||||
} else {
|
||||
//Check if this is the current version and should be shown as disabled
|
||||
if ($is_current_version && $has_paid_upgrade_from_current && $version['latest'] == 1) {
|
||||
//Show current version as disabled only if it's the latest AND there's a paid upgrade available
|
||||
//Check if this is the current version - always show it
|
||||
if ($is_current_version) {
|
||||
$show_version = true;
|
||||
$is_current = true;
|
||||
$final_price = '0.00';
|
||||
$final_currency = '';
|
||||
$decision_reason = 'Showing as CURRENT - is latest version with paid upgrade available';
|
||||
} else if ($is_current_version && !($has_paid_upgrade_from_current && $version['latest'] == 1)) {
|
||||
$decision_reason = 'Skipped - is current version but not (latest + has_paid_upgrade)';
|
||||
$decision_reason = 'Showing as CURRENT - always show current version';
|
||||
} else if (!$is_current_version) {
|
||||
//Check if this version is part of ANY upgrade path system (either FROM or TO)
|
||||
$sql = 'SELECT COUNT(*) as path_count
|
||||
@@ -242,26 +345,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -310,7 +415,7 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
}
|
||||
}
|
||||
|
||||
$output[] = [
|
||||
$entry = [
|
||||
"productcode" => $productcode,
|
||||
"name" => $version['name'] ?? '',
|
||||
"version" => $version['version'],
|
||||
@@ -324,8 +429,11 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
"source_type" => '',
|
||||
"price" => $final_price,
|
||||
"currency" => $final_currency,
|
||||
"is_current" => $is_current
|
||||
"is_current" => $is_current,
|
||||
"dealer_info" => $dealer_info
|
||||
];
|
||||
|
||||
$output[] = $entry;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
@@ -360,6 +468,16 @@ if (isset($criterias['sn']) && $criterias['sn'] != ''){
|
||||
];
|
||||
}
|
||||
|
||||
// Sort output: is_current = true first, then by price low to high
|
||||
usort($output, function($a, $b) {
|
||||
// First priority: is_current (true comes before false)
|
||||
if ($a['is_current'] !== $b['is_current']) {
|
||||
return $b['is_current'] - $a['is_current'];
|
||||
}
|
||||
// Second priority: price (low to high)
|
||||
return floatval($a['price']) - floatval($b['price']);
|
||||
});
|
||||
|
||||
$messages = $output;
|
||||
|
||||
if (debug && !empty($output)) {
|
||||
|
||||
@@ -19,7 +19,7 @@ if ($stmt->rowCount() == 1) {
|
||||
//Define User data
|
||||
$partnerhierarchy = $user_data['partnerhierarchy'];
|
||||
$permission = userRights($user_data['view']);
|
||||
$profile= getProfile($user_data['settings'],$permission);
|
||||
$profile= getUserPermissions($pdo, $user_data['id']); //getProfile($user_data['settings'],$permission);
|
||||
$username = $user_data['username'];
|
||||
$useremail = $user_data['email'];
|
||||
$servicekey = $user_data['service'];
|
||||
|
||||
70
api/v2/get/user_permissions.php
Normal file
70
api/v2/get/user_permissions.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?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];
|
||||
}
|
||||
}
|
||||
|
||||
$user_key = $criterias['userkey'] ?? null;
|
||||
|
||||
if (!$user_key) {
|
||||
http_response_code(400);
|
||||
exit(json_encode(['error_code' => 'API_INPUT_1','error' => 'user_key is required']));
|
||||
}
|
||||
|
||||
//GET USER_DATA
|
||||
$stmt = $pdo->prepare('SELECT * FROM users WHERE userkey = ?');
|
||||
$stmt->execute([$user_key]);
|
||||
|
||||
if ($stmt->rowCount() == 1) {
|
||||
//Get results
|
||||
$user_data = $stmt->fetch();
|
||||
|
||||
//GET DATA
|
||||
$user_permissions['id'] = $user_data['id'];
|
||||
$user_permissions['email'] = $user_data['email'];
|
||||
$user_permissions['partnerhierarchy'] = $user_data['partnerhierarchy']; //clean;
|
||||
$user_permissions['permission'] = userRights($user_data['view']);
|
||||
$user_permissions['profile'] = getProfile($user_data['settings'],userRights($user_data['view']));
|
||||
|
||||
//NEW DATA REPLACING PROFILE AND LATER PERMISSION ABOVE
|
||||
$user_permissions['permissions'] = getUserPermissions($pdo, $user_data['id']);
|
||||
|
||||
if (!$user_permissions['permissions']) {
|
||||
http_response_code(404);
|
||||
exit(json_encode(['error_code' => 'API_NOT_FOUND','error' => 'No permissions found']));
|
||||
}
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++
|
||||
//Return as JSON
|
||||
//+++++++++++++++++++++++++++++++++++++++++++
|
||||
echo json_encode($user_permissions);
|
||||
}
|
||||
else {
|
||||
http_response_code(404);
|
||||
exit(json_encode(['error_code' => 'API_NOT_FOUND','error' => 'User not found']));
|
||||
}
|
||||
|
||||
?>
|
||||
128
api/v2/get/user_role_assignments.php
Normal file
128
api/v2/get/user_role_assignments.php
Normal file
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// User Role Assignments
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//------------------------------------------
|
||||
//NEW ARRAY
|
||||
//------------------------------------------
|
||||
$criterias = [];
|
||||
$clause = '';
|
||||
|
||||
//------------------------------------------
|
||||
//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];
|
||||
if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='success_msg'){
|
||||
//do nothing
|
||||
}
|
||||
elseif ($v[0] == 'rowid') {
|
||||
//build up search by ID
|
||||
$clause .= ' AND ura.rowID = :'.$v[0];
|
||||
}
|
||||
elseif ($v[0] == 'role_id') {
|
||||
//build up search by role_id
|
||||
$clause .= ' AND ura.role_id = :'.$v[0];
|
||||
}
|
||||
elseif ($v[0] == 'user_id') {
|
||||
//build up search by user_id
|
||||
$clause .= ' AND ura.user_id = :'.$v[0];
|
||||
}
|
||||
elseif ($v[0] == 'status') {
|
||||
//Update status based on status
|
||||
$clause .= ' AND ura.is_active = :'.$v[0];
|
||||
}
|
||||
else {
|
||||
//create clause
|
||||
$clause .= ' AND ura.'.$v[0].' = :'.$v[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Build WHERE clause
|
||||
$whereclause = '';
|
||||
if ($clause != ''){
|
||||
$whereclause = 'WHERE '.substr($clause, 4);
|
||||
}
|
||||
|
||||
if (isset($criterias['totals']) && $criterias['totals'] ==''){
|
||||
//Request for total rows
|
||||
$sql = 'SELECT count(*) as count FROM user_role_assignments ura '.$whereclause;
|
||||
}
|
||||
else {
|
||||
//SQL with joined tables for names
|
||||
$sql = 'SELECT ura.*,
|
||||
u.username,
|
||||
u.email,
|
||||
r.name as role_name,
|
||||
r.description as role_description
|
||||
FROM user_role_assignments ura
|
||||
LEFT JOIN users u ON ura.user_id = u.id
|
||||
LEFT JOIN user_roles r ON ura.role_id = r.rowID
|
||||
'.$whereclause.'
|
||||
ORDER BY u.username ASC';
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
//------------------------------------------
|
||||
//Bind to query
|
||||
//------------------------------------------
|
||||
if (!empty($criterias)){
|
||||
foreach ($criterias as $key => $value){
|
||||
$key_condition = ':'.$key;
|
||||
if (str_contains($sql, $key_condition)){
|
||||
if ($key == 'p'){
|
||||
//Do nothing (bug)
|
||||
}
|
||||
else {
|
||||
$stmt->bindValue($key, $value, PDO::PARAM_STR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
// Debuglog
|
||||
//------------------------------------------
|
||||
if (debug){
|
||||
$message = $date.';'.$sql.';'.$username;
|
||||
debuglog($message);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//Execute Query
|
||||
//------------------------------------------
|
||||
if(isset($criterias['totals']) && $criterias['totals']==''){
|
||||
$stmt->execute();
|
||||
$messages = $stmt->fetch();
|
||||
$messages = $messages[0];
|
||||
}
|
||||
else {
|
||||
//Execute Query
|
||||
$stmt->execute();
|
||||
//Get results
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//JSON_EnCODE
|
||||
//------------------------------------------
|
||||
$messages = json_encode($messages, JSON_UNESCAPED_UNICODE);
|
||||
//------------------------------------------
|
||||
//Send results
|
||||
//------------------------------------------
|
||||
echo $messages;
|
||||
|
||||
?>
|
||||
167
api/v2/get/user_roles.php
Normal file
167
api/v2/get/user_roles.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// User Roles
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//------------------------------------------
|
||||
//NEW ARRAY
|
||||
//------------------------------------------
|
||||
$criterias = [];
|
||||
$clause = '';
|
||||
|
||||
//------------------------------------------
|
||||
//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];
|
||||
if ($v[0] == 'page' || $v[0] =='p' || $v[0] =='totals' || $v[0] =='success_msg' || $v[0] =='sort' || $v[0] =='all'){
|
||||
//do nothing
|
||||
}
|
||||
elseif ($v[0] == 'rowid') {
|
||||
//build up search by ID
|
||||
$clause .= ' AND r.rowID = :'.$v[0];
|
||||
}
|
||||
elseif ($v[0] == 'status') {
|
||||
//Update status based on status
|
||||
$clause .= ' AND r.is_active = :'.$v[0];
|
||||
}
|
||||
elseif ($v[0] == 'search') {
|
||||
//build up search
|
||||
$clause .= ' AND (r.name LIKE :'.$v[0].' OR r.description LIKE :'.$v[0].')';
|
||||
}
|
||||
elseif ($v[0] == 'name') {
|
||||
//build up name search
|
||||
$clause .= ' AND r.name = :'.$v[0];
|
||||
}
|
||||
else {
|
||||
//create clause
|
||||
$clause .= ' AND r.'.$v[0].' = :'.$v[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Filter system roles for users without delete permission on user_roles
|
||||
if (isAllowed('user_roles', $profile, $permission, 'D') !== 1) {
|
||||
$clause .= ' AND r.is_system != 1';
|
||||
}
|
||||
|
||||
//Build WHERE clause
|
||||
$whereclause = '';
|
||||
if ($clause != ''){
|
||||
$whereclause = 'WHERE '.substr($clause, 4);
|
||||
}
|
||||
|
||||
// GET SORT INDICATOR
|
||||
$sort_indicator = $criterias['sort'] ?? '';
|
||||
|
||||
switch ($sort_indicator){
|
||||
case 1:
|
||||
$sort = ' r.name ASC ';
|
||||
break;
|
||||
case 2:
|
||||
$sort = ' r.name DESC ';
|
||||
break;
|
||||
case 3:
|
||||
$sort = ' r.created ASC ';
|
||||
break;
|
||||
case 4:
|
||||
$sort = ' r.created DESC ';
|
||||
break;
|
||||
default:
|
||||
$sort = ' r.rowID ';
|
||||
break;
|
||||
}
|
||||
|
||||
if (isset($criterias['totals']) && $criterias['totals'] ==''){
|
||||
//Request for total rows
|
||||
$sql = 'SELECT count(*) as count FROM user_roles r '.$whereclause;
|
||||
}
|
||||
elseif (isset($criterias['all']) && $criterias['all'] ==''){
|
||||
//Return all records (no paging)
|
||||
$sql = 'SELECT r.*,
|
||||
(SELECT COUNT(*) FROM role_access_permissions WHERE role_id = r.rowID) as permission_count
|
||||
FROM user_roles r '.$whereclause.' ORDER BY '.$sort;
|
||||
}
|
||||
else {
|
||||
//SQL with permission count
|
||||
$sql = 'SELECT r.*,
|
||||
(SELECT COUNT(*) FROM role_access_permissions WHERE role_id = r.rowID) as permission_count
|
||||
FROM user_roles r '.$whereclause.' ORDER BY '.$sort.' LIMIT :page,:num_rows';
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
//------------------------------------------
|
||||
//Bind to query
|
||||
//------------------------------------------
|
||||
if (!empty($criterias)){
|
||||
foreach ($criterias as $key => $value){
|
||||
$key_condition = ':'.$key;
|
||||
if (str_contains($sql, $key_condition)){
|
||||
if ($key == 'search'){
|
||||
$search_value = '%'.$value.'%';
|
||||
$stmt->bindValue($key, $search_value, PDO::PARAM_STR);
|
||||
}
|
||||
elseif ($key == 'p'){
|
||||
//Do nothing (bug)
|
||||
}
|
||||
else {
|
||||
$stmt->bindValue($key, $value, PDO::PARAM_STR);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
// Debuglog
|
||||
//------------------------------------------
|
||||
if (debug){
|
||||
$message = $date.';'.$sql.';'.$username;
|
||||
debuglog($message);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//Add paging details
|
||||
//------------------------------------------
|
||||
$page_rows = $page_rows_equipment ?? 20;
|
||||
|
||||
if(isset($criterias['totals']) && $criterias['totals']==''){
|
||||
$stmt->execute();
|
||||
$messages = $stmt->fetch();
|
||||
$messages = $messages[0];
|
||||
}
|
||||
elseif(isset($criterias['all']) && $criterias['all']==''){
|
||||
//Return all records (no paging)
|
||||
$stmt->execute();
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
else {
|
||||
$current_page = isset($criterias['p']) && is_numeric($criterias['p']) ? (int)$criterias['p'] : 1;
|
||||
$stmt->bindValue('page', ($current_page - 1) * $page_rows, PDO::PARAM_INT);
|
||||
$stmt->bindValue('num_rows', $page_rows, PDO::PARAM_INT);
|
||||
//Execute Query
|
||||
$stmt->execute();
|
||||
//Get results
|
||||
$messages = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
//JSON_EnCODE
|
||||
//------------------------------------------
|
||||
$messages = json_encode($messages, JSON_UNESCAPED_UNICODE);
|
||||
//------------------------------------------
|
||||
//Send results
|
||||
//------------------------------------------
|
||||
echo $messages;
|
||||
|
||||
?>
|
||||
BIN
api/v2/post/.DS_Store
vendored
BIN
api/v2/post/.DS_Store
vendored
Binary file not shown.
79
api/v2/post/access_elements.php
Normal file
79
api/v2/post/access_elements.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Access Elements
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//CONTENT FROM API (POST)
|
||||
$post_content = json_decode($input,true);
|
||||
|
||||
//SET PARAMETERS FOR QUERY
|
||||
$id = $post_content['rowID'] ?? '';
|
||||
$command = ($id == '')? 'insert' : 'update';
|
||||
if (isset($post_content['delete'])){$command = 'delete';}
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
//CREATE EMPTY STRINGS
|
||||
$clause = '';
|
||||
$clause_insert ='';
|
||||
$input_insert = '';
|
||||
$execute_input = [];
|
||||
$criterias = [];
|
||||
|
||||
//ADD STANDARD PARAMETERS TO ARRAY BASED ON INSERT OR UPDATE
|
||||
if ($command == 'update'){
|
||||
$post_content['updatedby'] = $username;
|
||||
$post_content['updated'] = $date;
|
||||
}
|
||||
elseif ($command == 'insert'){
|
||||
$post_content['created'] = $date;
|
||||
$post_content['createdby'] = $username;
|
||||
}
|
||||
|
||||
//CREAT NEW ARRAY AND MAP TO CLAUSE
|
||||
if(isset($post_content) && $post_content!=''){
|
||||
foreach ($post_content as $key => $var){
|
||||
if ($key == 'submit' || $key == 'rowID' || str_contains($key, 'old_')){
|
||||
//do nothing
|
||||
}
|
||||
else {
|
||||
$criterias[$key] = $var;
|
||||
$clause .= ' , '.$key.' = ?';
|
||||
$clause_insert .= ' , '.$key.'';
|
||||
$input_insert .= ', ?';
|
||||
$execute_input[]= $var;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//CLEAN UP INPUT
|
||||
$clause = substr($clause, 2);
|
||||
$clause_insert = substr($clause_insert, 2);
|
||||
$input_insert = substr($input_insert, 1);
|
||||
|
||||
//QUERY AND VERIFY ALLOWED
|
||||
if ($command == 'update' && isAllowed('access_element_manage',$profile,$permission,'U') === 1){
|
||||
$sql = 'UPDATE access_elements SET '.$clause.' WHERE rowID = ?';
|
||||
$execute_input[] = $id;
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($execute_input);
|
||||
}
|
||||
elseif ($command == 'insert' && isAllowed('access_element_manage',$profile,$permission,'C') === 1){
|
||||
$sql = 'INSERT INTO access_elements ('.$clause_insert.') VALUES ('.$input_insert.')';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($execute_input);
|
||||
}
|
||||
elseif ($command == 'delete' && isAllowed('access_element_manage',$profile,$permission,'D') === 1){
|
||||
//Delete role permissions using this access element first (foreign key constraint)
|
||||
$stmt = $pdo->prepare('DELETE FROM role_access_permissions WHERE access_id = ?');
|
||||
$stmt->execute([$id]);
|
||||
|
||||
//Delete access element
|
||||
$stmt = $pdo->prepare('DELETE FROM access_elements WHERE rowID = ?');
|
||||
$stmt->execute([$id]);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -38,7 +38,7 @@ if ($id != ''){
|
||||
$salesid_new = ((isset($post_content['salesid']) && $post_content['salesid'] != '' && $post_content['salesid'] != $accounthierarchy_old->salesid)? $post_content['salesid'] : $accounthierarchy_old->salesid);
|
||||
$soldto_new = ((isset($post_content['soldto']) && $post_content['soldto'] != '' && $post_content['soldto'] != $accounthierarchy_old->soldto)? $post_content['soldto'] : $accounthierarchy_old->soldto);
|
||||
|
||||
if ($permission == 3 || $permission == 4){
|
||||
if (getHierarchyLevel($partner) == 1 || getHierarchyLevel($partner) == 0){
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$salesid_new,
|
||||
|
||||
@@ -58,7 +58,7 @@ if ($id != ''){
|
||||
$shipto_new = ((isset($post_content['shipto']) && $post_content['shipto'] != '' && $post_content['shipto'] != $contract_old->shipto)? $post_content['shipto'] : $contract_old->shipto);
|
||||
$location_new = ((isset($post_content['location']) && $post_content['location'] != '' && $post_content['location'] != $contract_old->location)? $post_content['location'] : $contract_old->location);
|
||||
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
//ADMIN+ ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$salesid_new,
|
||||
@@ -67,7 +67,7 @@ if ($id != ''){
|
||||
"location"=>$location_new
|
||||
);
|
||||
}
|
||||
elseif ($permission == 3) {
|
||||
elseif (getHierarchyLevel($partner) == 1) {
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SOLD
|
||||
$account = array(
|
||||
"salesid"=>$contract_old->salesid,
|
||||
@@ -120,7 +120,7 @@ if ($id != ''){
|
||||
}
|
||||
else {
|
||||
//ID is empty => INSERT / NEW RECORD
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
$account = array(
|
||||
"salesid"=>$post_content['salesid'],
|
||||
"soldto"=>$post_content['soldto'],
|
||||
@@ -128,7 +128,7 @@ else {
|
||||
"location"=>$post_content['location']
|
||||
);
|
||||
}
|
||||
elseif ($permission == 3){
|
||||
elseif (getHierarchyLevel($partner) == 1){
|
||||
$account = array(
|
||||
"salesid"=>$partner->salesid,
|
||||
"soldto"=>$post_content['soldto'],
|
||||
@@ -161,7 +161,7 @@ if (isset($post_content['ignore_list'])){
|
||||
$post_content['ignore_list'] = json_encode($post_content['ignore_list'], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
//ONLY ADMINS ARE ALLOWED TO UPDATE IGNORE LIST
|
||||
if ($permission != 3 && $permission != 4){
|
||||
if (getHierarchyLevel($partner) != 1 && getHierarchyLevel($partner) != 0){
|
||||
unset($post_content['ignore_list']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ if ($id != ''){
|
||||
|
||||
$owner_equipment = (($equipment_data['createdby'] == $username)? 1 : 0);
|
||||
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
//ADMIN+ ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$salesid_new,
|
||||
@@ -57,7 +57,7 @@ if ($id != ''){
|
||||
"section"=>$section_new
|
||||
);
|
||||
}
|
||||
elseif ($permission == 3) {
|
||||
elseif (getHierarchyLevel($partner) == 1) {
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SOLD
|
||||
$account = array(
|
||||
"salesid"=>$equipment_old->salesid,
|
||||
@@ -79,7 +79,7 @@ if ($id != ''){
|
||||
}
|
||||
else {
|
||||
//ID is empty => INSERT / NEW RECORD
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
$account = array(
|
||||
"salesid"=>$post_content['salesid'],
|
||||
"soldto"=>$post_content['soldto'],
|
||||
@@ -89,7 +89,7 @@ else {
|
||||
|
||||
);
|
||||
}
|
||||
elseif ($permission == 3){
|
||||
elseif (getHierarchyLevel($partner) == 1){
|
||||
$account = array(
|
||||
"salesid"=>$partner->salesid,
|
||||
"soldto"=>$post_content['soldto'],
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// History
|
||||
//------------------------------------------
|
||||
@@ -23,7 +24,11 @@ function checkSerial($serialinput){
|
||||
}
|
||||
|
||||
//CHECK IF SN AND PAYLOAD IS SEND => FROM EXTERNAL APPS
|
||||
if (isset($post_content['sn']) && isset($post_content['payload'])){
|
||||
if (isset($post_content['sn']) && (isset($post_content['payload']) || isset($post_content['testdetails']))){
|
||||
|
||||
if (!isset($post_content['payload'])) {
|
||||
$post_content['payload'] = $post_content['testdetails'];
|
||||
}
|
||||
|
||||
if (!empty($post_content['sn']) && !empty($post_content['payload'])) {
|
||||
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
@@ -39,12 +44,16 @@ if (isset($post_content['sn']) && isset($post_content['payload'])){
|
||||
$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'];
|
||||
@@ -141,12 +150,21 @@ if (isset($post_content['sn']) && isset($post_content['payload'])){
|
||||
$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;
|
||||
$servicetoolHistoryUpdate = 1;
|
||||
$sn_service = $post_content['sn_service'];
|
||||
break;
|
||||
|
||||
case 'customer': //update from Portal
|
||||
$historytype = 'Customer';
|
||||
break;
|
||||
|
||||
default:
|
||||
$historytype = 'Other';
|
||||
@@ -155,14 +173,14 @@ if (isset($post_content['sn']) && isset($post_content['payload'])){
|
||||
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
//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);
|
||||
@@ -173,9 +191,9 @@ if (isset($post_content['sn']) && isset($post_content['payload'])){
|
||||
// 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();
|
||||
}
|
||||
|
||||
@@ -209,9 +227,8 @@ if (isset($post_content['sn']) && isset($post_content['payload'])){
|
||||
if ($equipmentUpdate == 1){
|
||||
//get HW + SW from PortalAPI
|
||||
if ($post_content['type'] == 'firmware'){
|
||||
$test = json_decode($post_content['payload']);
|
||||
$hw_version = $test->HW;
|
||||
$sw_version = $test->HEX_FW;
|
||||
$hw_version = $post_content['payload']['HW'];
|
||||
$sw_version = $post_content['payload']['HEX_FW'];
|
||||
}
|
||||
else {
|
||||
//GET HW + SW from object
|
||||
@@ -297,7 +314,7 @@ if (isset($post_content['sn']) && isset($post_content['payload'])){
|
||||
//Update Equipment record
|
||||
$sql = "UPDATE equipment SET service_date = ? $whereclause";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([$current_date]);
|
||||
$stmt->execute([$service_date]);
|
||||
}
|
||||
|
||||
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
@@ -349,6 +366,50 @@ if (isset($post_content['sn']) && isset($post_content['payload'])){
|
||||
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, accounthierarchy,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',
|
||||
$account,
|
||||
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
|
||||
{
|
||||
|
||||
93
api/v2/post/marketing_delete.php
Normal file
93
api/v2/post/marketing_delete.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Marketing Files Delete
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//CONTENT FROM API (POST)
|
||||
$post_content = json_decode($input,true);
|
||||
|
||||
//SoldTo is empty
|
||||
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
|
||||
|
||||
//default whereclause
|
||||
list($whereclause,$condition) = getWhereclauselvl2("",$permission,$partner,'');
|
||||
|
||||
$file_id = $post_content['file_id'] ?? '';
|
||||
|
||||
if (empty($file_id)) {
|
||||
echo json_encode(['error' => 'File ID is required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
//QUERY AND VERIFY ALLOWED
|
||||
if (isAllowed('marketing',$profile,$permission,'D') === 1){
|
||||
// Get file information for cleanup
|
||||
$file_sql = 'SELECT * FROM marketing_files WHERE id = ? AND accounthierarchy LIKE ?';
|
||||
$stmt = $pdo->prepare($file_sql);
|
||||
$stmt->execute([$file_id, '%' . $partner->soldto . '%']);
|
||||
$file_info = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$file_info) {
|
||||
echo json_encode(['error' => 'File not found or access denied']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// Remove file tags
|
||||
$delete_tags_sql = 'DELETE FROM marketing_file_tags WHERE file_id = ?';
|
||||
$stmt = $pdo->prepare($delete_tags_sql);
|
||||
$stmt->execute([$file_id]);
|
||||
|
||||
// Delete file record
|
||||
$delete_file_sql = 'DELETE FROM marketing_files WHERE id = ? AND accounthierarchy LIKE ?';
|
||||
$stmt = $pdo->prepare($delete_file_sql);
|
||||
$stmt->execute([$file_id, '%' . $partner->soldto . '%']);
|
||||
|
||||
// Delete physical files
|
||||
$base_path = dirname(__FILE__, 4) . "/";
|
||||
$main_file = $base_path . $file_info['file_path'];
|
||||
$thumbnail_file = $file_info['thumbnail_path'] ? $base_path . $file_info['thumbnail_path'] : null;
|
||||
|
||||
$files_deleted = [];
|
||||
$files_failed = [];
|
||||
|
||||
if (file_exists($main_file)) {
|
||||
if (unlink($main_file)) {
|
||||
$files_deleted[] = $file_info['file_path'];
|
||||
} else {
|
||||
$files_failed[] = $file_info['file_path'];
|
||||
}
|
||||
}
|
||||
|
||||
if ($thumbnail_file && file_exists($thumbnail_file)) {
|
||||
if (unlink($thumbnail_file)) {
|
||||
$files_deleted[] = $file_info['thumbnail_path'];
|
||||
} else {
|
||||
$files_failed[] = $file_info['thumbnail_path'];
|
||||
}
|
||||
}
|
||||
|
||||
$pdo->commit();
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'File deleted successfully',
|
||||
'files_deleted' => $files_deleted,
|
||||
'files_failed' => $files_failed
|
||||
]);
|
||||
|
||||
} catch (Exception $e) {
|
||||
$pdo->rollback();
|
||||
echo json_encode(['error' => 'Failed to delete file: ' . $e->getMessage()]);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['error' => 'Insufficient permissions']);
|
||||
}
|
||||
|
||||
?>
|
||||
105
api/v2/post/marketing_folders.php
Normal file
105
api/v2/post/marketing_folders.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Marketing Folders
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//CONTENT FROM API (POST)
|
||||
$post_content = json_decode($input,true);
|
||||
|
||||
//SoldTo is empty
|
||||
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
|
||||
|
||||
//default whereclause
|
||||
list($whereclause,$condition) = getWhereclauselvl2("",$permission,$partner,'');
|
||||
|
||||
//BUILD UP PARTNERHIERARCHY FROM USER
|
||||
$partner_hierarchy = json_encode(array("salesid"=>$partner->salesid,"soldto"=>$partner->soldto), JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$id = $post_content['id'] ?? ''; //check for rowID
|
||||
$command = ($id == '')? 'insert' : 'update'; //IF rowID = empty then INSERT
|
||||
if (isset($post_content['delete'])){$command = 'delete';} //change command to delete
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
//CREATE EMPTY STRINGS
|
||||
$clause = '';
|
||||
$clause_insert ='';
|
||||
$input_insert = '';
|
||||
|
||||
if ($command == 'update'){
|
||||
$post_content['updatedby'] = $username;
|
||||
$post_content['updated'] = $date;
|
||||
}
|
||||
if ($command == 'insert'){
|
||||
$post_content['createdby'] = $username;
|
||||
$post_content['accounthierarchy'] = $partner_hierarchy;
|
||||
}
|
||||
|
||||
//CREATE NEW ARRAY AND MAP TO CLAUSE
|
||||
if(isset($post_content) && $post_content!=''){
|
||||
foreach ($post_content as $key => $var){
|
||||
if ($key == 'submit' || $key == 'id' || $key == 'delete'){
|
||||
//do nothing
|
||||
}
|
||||
else {
|
||||
// Handle empty parent_id as NULL for foreign key constraint
|
||||
if ($key == 'parent_id' && $var === '') {
|
||||
$var = null;
|
||||
}
|
||||
$criterias[$key] = $var;
|
||||
$clause .= ' , '.$key.' = ?';
|
||||
$clause_insert .= ' , '.$key.'';
|
||||
$input_insert .= ', ?'; // ? for each insert item
|
||||
$execute_input[]= $var; // Build array for input
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//CLEAN UP INPUT
|
||||
$clause = substr($clause, 2); //Clean clause - remove first comma
|
||||
$clause_insert = substr($clause_insert, 2); //Clean clause - remove first comma
|
||||
$input_insert = substr($input_insert, 1); //Clean clause - remove first comma
|
||||
|
||||
//QUERY AND VERIFY ALLOWED
|
||||
if ($command == 'update' && isAllowed('marketing',$profile,$permission,'U') === 1){
|
||||
$sql = 'UPDATE marketing_folders SET '.$clause.' WHERE id = ? '.$whereclause.'';
|
||||
$execute_input[] = $id;
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($execute_input);
|
||||
echo json_encode(['success' => true, 'message' => 'Folder updated successfully']);
|
||||
}
|
||||
elseif ($command == 'insert' && isAllowed('marketing',$profile,$permission,'C') === 1){
|
||||
$sql = 'INSERT INTO marketing_folders ('.$clause_insert.') VALUES ('.$input_insert.')';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($execute_input);
|
||||
$folder_id = $pdo->lastInsertId();
|
||||
echo json_encode(['success' => true, 'rowID' => $folder_id, 'message' => 'Folder created successfully']);
|
||||
}
|
||||
elseif ($command == 'delete' && isAllowed('marketing',$profile,$permission,'D') === 1){
|
||||
// Check if folder has subfolders
|
||||
$subfolder_sql = 'SELECT COUNT(*) as count FROM marketing_folders WHERE parent_id = ? AND accounthierarchy LIKE ?';
|
||||
$stmt = $pdo->prepare($subfolder_sql);
|
||||
$stmt->execute([$id, '%' . $partner->soldto . '%']);
|
||||
$subfolder_count = $stmt->fetch()['count'];
|
||||
|
||||
// Check if folder has files
|
||||
$files_sql = 'SELECT COUNT(*) as count FROM marketing_files WHERE folder_id = ? AND accounthierarchy LIKE ?';
|
||||
$stmt = $pdo->prepare($files_sql);
|
||||
$stmt->execute([$id, '%' . $partner->soldto . '%']);
|
||||
$files_count = $stmt->fetch()['count'];
|
||||
|
||||
if ($subfolder_count > 0 || $files_count > 0) {
|
||||
echo json_encode(['error' => 'Cannot delete folder that contains subfolders or files']);
|
||||
} else {
|
||||
$stmt = $pdo->prepare('DELETE FROM marketing_folders WHERE id = ? '.$whereclause.'');
|
||||
$stmt->execute([ $id ]);
|
||||
echo json_encode(['success' => true, 'message' => 'Folder deleted successfully']);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['error' => 'Insufficient permissions or invalid operation']);
|
||||
}
|
||||
|
||||
?>
|
||||
94
api/v2/post/marketing_update.php
Normal file
94
api/v2/post/marketing_update.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Marketing Update
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//SoldTo is empty
|
||||
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
|
||||
|
||||
//default whereclause
|
||||
list($whereclause,$condition) = getWhereclauselvl2("",$permission,$partner,'');
|
||||
|
||||
//QUERY AND VERIFY ALLOWED
|
||||
if (isAllowed('marketing',$profile,$permission,'U') === 1){
|
||||
// Get JSON input
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
|
||||
$file_id = $input['file_id'] ?? '';
|
||||
|
||||
if (empty($file_id)) {
|
||||
echo json_encode(['success' => false, 'error' => 'File ID is required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
// First verify the file exists and user has access
|
||||
$check_sql = 'SELECT id FROM `marketing_files` WHERE `id` = ?';
|
||||
$check_stmt = $pdo->prepare($check_sql);
|
||||
$check_stmt->execute([$file_id]);
|
||||
|
||||
if ($check_stmt->rowCount() === 0) {
|
||||
echo json_encode(['success' => false, 'error' => 'File not found or access denied']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Build dynamic UPDATE query for only changed fields
|
||||
$update_fields = [];
|
||||
$update_params = [];
|
||||
|
||||
if (isset($input['title'])) {
|
||||
$update_fields[] = '`title` = ?';
|
||||
$update_params[] = $input['title'];
|
||||
}
|
||||
|
||||
if (isset($input['folder_id'])) {
|
||||
$update_fields[] = '`folder_id` = ?';
|
||||
$update_params[] = $input['folder_id'] ?: null;
|
||||
}
|
||||
|
||||
// Always update updatedby if there are changes
|
||||
if (!empty($update_fields)) {
|
||||
$update_fields[] = '`updatedby` = ?';
|
||||
$update_params[] = $username;
|
||||
$update_params[] = $file_id;
|
||||
|
||||
$update_sql = 'UPDATE `marketing_files` SET ' . implode(', ', $update_fields) . ' WHERE `id` = ?';
|
||||
$stmt = $pdo->prepare($update_sql);
|
||||
$stmt->execute($update_params);
|
||||
}
|
||||
|
||||
// Update tags only if provided
|
||||
if (isset($input['tags'])) {
|
||||
// Remove existing tags
|
||||
$pdo->prepare('DELETE FROM `marketing_file_tags` WHERE `file_id` = ?')->execute([$file_id]);
|
||||
|
||||
// Parse and insert new tags
|
||||
$tags_string = $input['tags'];
|
||||
$tags_array = array_filter(array_map('trim', explode(',', $tags_string)));
|
||||
|
||||
if (!empty($tags_array)) {
|
||||
$tag_sql = 'INSERT IGNORE INTO `marketing_tags` (`tag_name`) VALUES (?)';
|
||||
$tag_stmt = $pdo->prepare($tag_sql);
|
||||
|
||||
$file_tag_sql = 'INSERT INTO `marketing_file_tags` (`file_id`, `tag_id`) SELECT ?, id FROM marketing_tags WHERE tag_name = ?';
|
||||
$file_tag_stmt = $pdo->prepare($file_tag_sql);
|
||||
|
||||
foreach ($tags_array as $tag) {
|
||||
$tag_stmt->execute([$tag]);
|
||||
$file_tag_stmt->execute([$file_id, $tag]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode(['success' => true, 'message' => 'File updated successfully']);
|
||||
} catch (Exception $e) {
|
||||
echo json_encode(['success' => false, 'error' => 'Update failed: ' . $e->getMessage()]);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Insufficient permissions']);
|
||||
}
|
||||
?>
|
||||
336
api/v2/post/marketing_upload.php
Normal file
336
api/v2/post/marketing_upload.php
Normal file
@@ -0,0 +1,336 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Marketing Upload
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//SoldTo is empty
|
||||
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
|
||||
|
||||
//default whereclause
|
||||
list($whereclause,$condition) = getWhereclauselvl2("",$permission,$partner,'');
|
||||
|
||||
//BUILD UP PARTNERHIERARCHY FROM USER
|
||||
$partner_hierarchy = $condition;
|
||||
|
||||
//QUERY AND VERIFY ALLOWED
|
||||
if (isAllowed('marketing',$profile,$permission,'C') === 1){
|
||||
if (!isset($_FILES['file'])) {
|
||||
echo json_encode(['success' => false, 'error' => 'No file uploaded']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$file = $_FILES['file'];
|
||||
$folder_id = $_POST['folder_id'] ?? '';
|
||||
$tags = isset($_POST['tags']) ? json_decode($_POST['tags'], true) : [];
|
||||
$title = $_POST['title'] ?? pathinfo($file['name'], PATHINFO_FILENAME);
|
||||
|
||||
// Validate file type
|
||||
$allowedTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'pdf', 'doc', 'docx', 'xls', 'xlsx', 'mp4', 'mov', 'avi'];
|
||||
$filename = $file['name'];
|
||||
$ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
||||
|
||||
if (!in_array($ext, $allowedTypes)) {
|
||||
echo json_encode(['success' => false, 'error' => 'Invalid file type. Allowed: ' . implode(', ', $allowedTypes)]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||
$isImage = in_array($ext, $imageTypes);
|
||||
|
||||
// For images over 10MB, automatically compress
|
||||
if ($isImage && $file['size'] > 10000000) {
|
||||
$compressed = compressImage($file['tmp_name'], $ext, 10000000);
|
||||
if ($compressed === false) {
|
||||
echo json_encode(['success' => false, 'error' => 'Failed to compress large image. Please reduce file size manually.']);
|
||||
exit;
|
||||
}
|
||||
// Update file size after compression
|
||||
$file['size'] = filesize($file['tmp_name']);
|
||||
}
|
||||
|
||||
// Non-images must be under 10MB
|
||||
if (!$isImage && $file['size'] > 25000000) {
|
||||
echo json_encode(['success' => false, 'error' => 'File too large. Maximum size is 25MB.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Create unique filename
|
||||
$unique_filename = uniqid() . '_' . time() . '.' . $ext;
|
||||
$target_dir = dirname(__FILE__, 4) . "/marketing/uploads/";
|
||||
$target_file = $target_dir . $unique_filename;
|
||||
$logical_path = "marketing/uploads/" . $unique_filename;
|
||||
|
||||
// Ensure upload directory exists
|
||||
if (!file_exists($target_dir)) {
|
||||
mkdir($target_dir, 0755, true);
|
||||
}
|
||||
|
||||
if (move_uploaded_file($file['tmp_name'], $target_file)) {
|
||||
// Generate thumbnail
|
||||
$thumbnail_path = null;
|
||||
$thumb_dir = $target_dir . "thumbs/";
|
||||
if (!file_exists($thumb_dir)) {
|
||||
mkdir($thumb_dir, 0755, true);
|
||||
}
|
||||
|
||||
// Generate thumbnail for images
|
||||
if (in_array($ext, ['jpg', 'jpeg', 'png', 'gif', 'webp'])) {
|
||||
$thumbnail_file = $thumb_dir . $unique_filename;
|
||||
if (generateThumbnail($target_file, $thumbnail_file, 200, 200)) {
|
||||
$thumbnail_path = "marketing/uploads/thumbs/" . $unique_filename;
|
||||
}
|
||||
}
|
||||
// Generate thumbnail for videos
|
||||
elseif (in_array($ext, ['mp4', 'mov', 'avi'])) {
|
||||
$thumbnail_filename = pathinfo($unique_filename, PATHINFO_FILENAME) . '.jpg';
|
||||
$thumbnail_file = $thumb_dir . $thumbnail_filename;
|
||||
if (generateVideoThumbnail($target_file, $thumbnail_file)) {
|
||||
$thumbnail_path = "marketing/uploads/thumbs/" . $thumbnail_filename;
|
||||
}
|
||||
}
|
||||
|
||||
// Insert into database
|
||||
$insert_sql = 'INSERT INTO `marketing_files` (`title`, `original_filename`, `file_path`, `thumbnail_path`, `file_type`, `file_size`, `folder_id`, `tags`, `createdby`, `accounthierarchy`) VALUES (?,?,?,?,?,?,?,?,?,?)';
|
||||
$stmt = $pdo->prepare($insert_sql);
|
||||
$stmt->execute([
|
||||
$title,
|
||||
$filename,
|
||||
$logical_path,
|
||||
$thumbnail_path,
|
||||
$ext,
|
||||
$file['size'],
|
||||
$folder_id,
|
||||
json_encode($tags),
|
||||
$username,
|
||||
$partner_hierarchy
|
||||
]);
|
||||
|
||||
$file_id = $pdo->lastInsertId();
|
||||
|
||||
// Insert tags into separate table
|
||||
if (!empty($tags)) {
|
||||
$tag_sql = 'INSERT IGNORE INTO `marketing_tags` (`tag_name`) VALUES (?)';
|
||||
$tag_stmt = $pdo->prepare($tag_sql);
|
||||
|
||||
$file_tag_sql = 'INSERT INTO `marketing_file_tags` (`file_id`, `tag_id`) SELECT ?, id FROM marketing_tags WHERE tag_name = ?';
|
||||
$file_tag_stmt = $pdo->prepare($file_tag_sql);
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
$tag_stmt->execute([trim($tag)]);
|
||||
$file_tag_stmt->execute([$file_id, trim($tag)]);
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'file_id' => $file_id,
|
||||
'path' => $logical_path,
|
||||
'thumbnail' => $thumbnail_path,
|
||||
'message' => 'File uploaded successfully'
|
||||
]);
|
||||
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Failed to move uploaded file']);
|
||||
}
|
||||
} else {
|
||||
echo json_encode(['success' => false, 'error' => 'Insufficient permissions']);
|
||||
}
|
||||
|
||||
// Function to compress large images
|
||||
function compressImage($source, $ext, $maxSize) {
|
||||
$info = @getimagesize($source);
|
||||
if ($info === false) return false;
|
||||
|
||||
$mime = $info['mime'];
|
||||
|
||||
// Load image
|
||||
switch ($mime) {
|
||||
case 'image/jpeg':
|
||||
$image = @imagecreatefromjpeg($source);
|
||||
break;
|
||||
case 'image/png':
|
||||
$image = @imagecreatefrompng($source);
|
||||
break;
|
||||
case 'image/gif':
|
||||
$image = @imagecreatefromgif($source);
|
||||
break;
|
||||
case 'image/webp':
|
||||
$image = @imagecreatefromwebp($source);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($image === false) return false;
|
||||
|
||||
$width = imagesx($image);
|
||||
$height = imagesy($image);
|
||||
|
||||
// Start with 90% quality and reduce dimensions if needed
|
||||
$quality = 90;
|
||||
$scale = 1.0;
|
||||
$tempFile = $source . '.tmp';
|
||||
|
||||
// Try progressive compression
|
||||
while (true) {
|
||||
// Calculate new dimensions
|
||||
$newWidth = (int)($width * $scale);
|
||||
$newHeight = (int)($height * $scale);
|
||||
|
||||
// Create resized image
|
||||
$resized = imagecreatetruecolor($newWidth, $newHeight);
|
||||
|
||||
// Preserve transparency for PNG/GIF
|
||||
if ($mime === 'image/png' || $mime === 'image/gif') {
|
||||
imagealphablending($resized, false);
|
||||
imagesavealpha($resized, true);
|
||||
$transparent = imagecolorallocatealpha($resized, 255, 255, 255, 127);
|
||||
imagefilledrectangle($resized, 0, 0, $newWidth, $newHeight, $transparent);
|
||||
}
|
||||
|
||||
imagecopyresampled($resized, $image, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
|
||||
|
||||
// Save with current quality
|
||||
if ($ext === 'jpg' || $ext === 'jpeg') {
|
||||
imagejpeg($resized, $tempFile, $quality);
|
||||
} elseif ($ext === 'png') {
|
||||
// PNG compression level (0-9, where 9 is best compression)
|
||||
$pngQuality = (int)((100 - $quality) / 11);
|
||||
imagepng($resized, $tempFile, $pngQuality);
|
||||
} elseif ($ext === 'webp') {
|
||||
imagewebp($resized, $tempFile, $quality);
|
||||
} else {
|
||||
imagegif($resized, $tempFile);
|
||||
}
|
||||
|
||||
imagedestroy($resized);
|
||||
|
||||
$fileSize = filesize($tempFile);
|
||||
|
||||
// If file is small enough, use it
|
||||
if ($fileSize <= $maxSize) {
|
||||
imagedestroy($image);
|
||||
rename($tempFile, $source);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we've reduced too much, give up
|
||||
if ($quality < 50 && $scale < 0.5) {
|
||||
imagedestroy($image);
|
||||
@unlink($tempFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reduce quality or scale
|
||||
if ($quality > 50) {
|
||||
$quality -= 10;
|
||||
} else {
|
||||
$scale -= 0.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to generate thumbnail
|
||||
function generateThumbnail($source, $destination, $width, $height) {
|
||||
$info = getimagesize($source);
|
||||
if ($info === false) return false;
|
||||
|
||||
$mime = $info['mime'];
|
||||
|
||||
switch ($mime) {
|
||||
case 'image/jpeg':
|
||||
$image = imagecreatefromjpeg($source);
|
||||
break;
|
||||
case 'image/png':
|
||||
$image = imagecreatefrompng($source);
|
||||
break;
|
||||
case 'image/gif':
|
||||
$image = imagecreatefromgif($source);
|
||||
break;
|
||||
case 'image/webp':
|
||||
$image = imagecreatefromwebp($source);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($image === false) return false;
|
||||
|
||||
$original_width = imagesx($image);
|
||||
$original_height = imagesy($image);
|
||||
|
||||
// Calculate aspect ratio
|
||||
$aspect_ratio = $original_width / $original_height;
|
||||
|
||||
if ($width / $height > $aspect_ratio) {
|
||||
$new_width = $height * $aspect_ratio;
|
||||
$new_height = $height;
|
||||
} else {
|
||||
$new_height = $width / $aspect_ratio;
|
||||
$new_width = $width;
|
||||
}
|
||||
|
||||
$thumbnail = imagecreatetruecolor($new_width, $new_height);
|
||||
|
||||
// Preserve transparency
|
||||
imagealphablending($thumbnail, false);
|
||||
imagesavealpha($thumbnail, true);
|
||||
$transparent = imagecolorallocatealpha($thumbnail, 255, 255, 255, 127);
|
||||
imagefilledrectangle($thumbnail, 0, 0, $new_width, $new_height, $transparent);
|
||||
|
||||
imagecopyresampled($thumbnail, $image, 0, 0, 0, 0, $new_width, $new_height, $original_width, $original_height);
|
||||
|
||||
// Save thumbnail
|
||||
switch ($mime) {
|
||||
case 'image/jpeg':
|
||||
$result = imagejpeg($thumbnail, $destination, 85);
|
||||
break;
|
||||
case 'image/png':
|
||||
$result = imagepng($thumbnail, $destination, 8);
|
||||
break;
|
||||
case 'image/gif':
|
||||
$result = imagegif($thumbnail, $destination);
|
||||
break;
|
||||
case 'image/webp':
|
||||
$result = imagewebp($thumbnail, $destination, 85);
|
||||
break;
|
||||
default:
|
||||
$result = false;
|
||||
}
|
||||
|
||||
imagedestroy($image);
|
||||
imagedestroy($thumbnail);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Function to generate video thumbnail
|
||||
function generateVideoThumbnail($source, $destination) {
|
||||
// Check if ffmpeg is available
|
||||
$ffmpeg = trim(shell_exec('which ffmpeg 2>/dev/null'));
|
||||
if (empty($ffmpeg)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate thumbnail from video at 1 second mark
|
||||
// -i: input file
|
||||
// -ss: seek to 1 second
|
||||
// -vframes 1: extract one frame
|
||||
// -vf: scale to 200x200 maintaining aspect ratio
|
||||
$command = sprintf(
|
||||
'%s -i %s -ss 00:00:01 -vframes 1 -vf "scale=200:200:force_original_aspect_ratio=decrease" %s 2>&1',
|
||||
escapeshellarg($ffmpeg),
|
||||
escapeshellarg($source),
|
||||
escapeshellarg($destination)
|
||||
);
|
||||
|
||||
exec($command, $output, $return_code);
|
||||
|
||||
return $return_code === 0 && file_exists($destination);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -1,12 +1,9 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
defined($security_key) or exit;
|
||||
//------------------------------------------
|
||||
// Payment Creation (for Software Upgrades)
|
||||
//------------------------------------------
|
||||
// This endpoint creates a Mollie payment and stores transaction data
|
||||
// This endpoint creates a payment (Mollie or PayPal) and stores transaction data
|
||||
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
@@ -25,6 +22,14 @@ if (empty($post_content['serial_number']) || empty($post_content['version_id']))
|
||||
$serial_number = $post_content['serial_number'];
|
||||
$version_id = $post_content['version_id'];
|
||||
$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
|
||||
$vat_number = $user_data['vat_number'] ?? null; // VAT number
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// STEP 1: Get equipment data from serial_number
|
||||
@@ -42,7 +47,8 @@ if (!$equipment) {
|
||||
}
|
||||
|
||||
$equipment_id = $equipment['rowID'];
|
||||
$current_sw_version = trim(strtolower(ltrim($equipment['sw_version'], '0')));
|
||||
// Normalize software version for comparison (lowercase, trim leading zeros) - same as software_update.php line 96
|
||||
$current_sw_version = strtolower(ltrim($equipment['sw_version'], '0'));
|
||||
$sw_version_license = $equipment['sw_version_license'] ?? null;
|
||||
$hw_version = $equipment['hw_version'] ?? '';
|
||||
|
||||
@@ -77,10 +83,13 @@ $path_count_result = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$has_upgrade_paths = ($path_count_result['path_count'] > 0);
|
||||
|
||||
if (!$has_upgrade_paths) {
|
||||
// No upgrade paths defined = FREE (lines 240-242 in software_update.php)
|
||||
// No upgrade paths defined = FREE (lines 328-331 in software_update.php)
|
||||
$final_price = '0.00';
|
||||
if (debug) {
|
||||
debuglog("DEBUG: No upgrade paths defined for version_id $version_id - upgrade is FREE");
|
||||
}
|
||||
} else {
|
||||
// Check for valid upgrade path FROM current version
|
||||
// Check for valid upgrade path FROM current version (same logic as software_update.php lines 335-353)
|
||||
$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
|
||||
@@ -91,14 +100,28 @@ if (!$has_upgrade_paths) {
|
||||
$stmt->execute([$version_id, $current_sw_version]);
|
||||
$upgrade_path = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if (debug) {
|
||||
debuglog("DEBUG: Looking for upgrade path TO version_id=$version_id FROM current_sw_version='$current_sw_version'");
|
||||
debuglog("DEBUG: Upgrade path result: " . json_encode($upgrade_path));
|
||||
}
|
||||
|
||||
if ($upgrade_path) {
|
||||
$final_price = $upgrade_path['price'] ?? '0.00';
|
||||
$final_currency = $upgrade_path['currency'] ?? 'EUR';
|
||||
if (debug) {
|
||||
debuglog("DEBUG: Found upgrade path - price: $final_price $final_currency");
|
||||
}
|
||||
} else {
|
||||
// No upgrade path FROM current version
|
||||
|
||||
if (debug) {
|
||||
debuglog("ERROR: No valid upgrade path from current version '$current_sw_version' to version_id $version_id");
|
||||
}
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'No valid upgrade path from current version'], JSON_UNESCAPED_UNICODE);
|
||||
echo json_encode([
|
||||
'error' => 'No valid upgrade path from current version',
|
||||
'current_version' => $current_sw_version,
|
||||
'target_version_id' => $version_id
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
@@ -137,67 +160,159 @@ if ($final_price <= 0) {
|
||||
}
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// STEP 6: DEBUG MODE - Log but continue to real Mollie
|
||||
// STEP 6: DEBUG MODE - Log
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
if (debug) {
|
||||
debuglog("DEBUG MODE: Creating real Mollie payment for testing");
|
||||
debuglog("DEBUG MODE: Creating $payment_provider payment for testing");
|
||||
debuglog("DEBUG: Serial Number: $serial_number, Version ID: $version_id, Price: $final_price");
|
||||
}
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// STEP 7: Call Mollie API to create payment
|
||||
// STEP 7: Create payment based on provider
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
try {
|
||||
// Initialize Mollie
|
||||
require dirname(__FILE__, 4).'/initialize.php';
|
||||
// Use payment_amount (with tax) if provided, otherwise use final_price
|
||||
$amount_to_charge = $payment_amount ? (float)$payment_amount : (float)$final_price;
|
||||
|
||||
// Format price for Mollie (must be string with 2 decimals)
|
||||
$formatted_price = number_format((float)$final_price, 2, '.', '');
|
||||
// Format price (must be string with 2 decimals)
|
||||
$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 Mollie payment
|
||||
// STEP 7A: Generate transaction ID BEFORE creating payment
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Generate unique transaction ID (same as placeorder.php)
|
||||
$txn_id = strtoupper(uniqid('SC') . substr(md5(mt_rand()), 0, 5));
|
||||
|
||||
// Build webhook URL and redirect URL with actual transaction ID
|
||||
// Build URLs
|
||||
$protocol = 'https';
|
||||
$hostname = $_SERVER['SERVER_NAME'];
|
||||
$path = '/';
|
||||
$webhook_url = "{$protocol}://{$hostname}{$path}webhook_mollie.php";
|
||||
$redirect_url = "{$protocol}://{$hostname}{$path}?page=softwaretool&payment_return=1&order_id={$txn_id}";
|
||||
|
||||
if (debug) {
|
||||
debuglog("DEBUG: Transaction ID: {$txn_id}");
|
||||
debuglog("DEBUG: redirectUrl being sent to Mollie: " . $redirect_url);
|
||||
debuglog("DEBUG: Redirect URL: " . $redirect_url);
|
||||
}
|
||||
|
||||
// Create payment with Mollie
|
||||
$payment = $mollie->payments->create([
|
||||
'amount' => [
|
||||
'currency' => $final_currency ?: 'EUR',
|
||||
'value' => "{$formatted_price}"
|
||||
],
|
||||
'description' => "Software upgrade Order #{$txn_id}",
|
||||
'redirectUrl' => "{$redirect_url}",
|
||||
'webhookUrl' => "{$webhook_url}",
|
||||
'metadata' => [
|
||||
'order_id' => $txn_id,
|
||||
'serial_number' => $serial_number,
|
||||
'version_id' => $version_id,
|
||||
'equipment_id' => $equipment_id
|
||||
]
|
||||
]);
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Create payment based on selected provider
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
if ($payment_provider === 'paypal') {
|
||||
//==========================================
|
||||
// PAYPAL PAYMENT CREATION
|
||||
//==========================================
|
||||
$cancel_url = "{$protocol}://{$hostname}{$path}?page=softwaretool&payment_return=cancelled&order_id={$txn_id}";
|
||||
|
||||
// Get PayPal access token
|
||||
$access_token = getPayPalAccessToken();
|
||||
|
||||
$mollie_payment_id = $payment->id;
|
||||
$checkout_url = $payment->getCheckoutUrl();
|
||||
// Create PayPal order
|
||||
$order_data = [
|
||||
'intent' => 'CAPTURE',
|
||||
'purchase_units' => [[
|
||||
'custom_id' => $txn_id,
|
||||
'description' => "Software upgrade Order #{$txn_id}",
|
||||
'amount' => [
|
||||
'currency_code' => $final_currency ?: 'EUR',
|
||||
'value' => $formatted_price
|
||||
],
|
||||
'payee' => [
|
||||
'email_address' => email
|
||||
]
|
||||
]],
|
||||
'application_context' => [
|
||||
'return_url' => $redirect_url,
|
||||
'cancel_url' => $cancel_url,
|
||||
'brand_name' => site_name,
|
||||
'user_action' => 'PAY_NOW'
|
||||
]
|
||||
];
|
||||
|
||||
$ch = curl_init(PAYPAL_URL . '/v2/checkout/orders');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($order_data));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer ' . $access_token
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($http_code != 200 && $http_code != 201) {
|
||||
debuglog("PayPal API Error: HTTP $http_code - Response: $response");
|
||||
throw new Exception("PayPal order creation failed: HTTP $http_code");
|
||||
}
|
||||
|
||||
$paypal_order = json_decode($response, true);
|
||||
$payment_id = $paypal_order['id'] ?? null;
|
||||
|
||||
// Extract approval URL
|
||||
$checkout_url = '';
|
||||
foreach ($paypal_order['links'] ?? [] as $link) {
|
||||
if ($link['rel'] === 'approve') {
|
||||
$checkout_url = $link['href'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$checkout_url) {
|
||||
throw new Exception("No approval URL received from PayPal");
|
||||
}
|
||||
|
||||
$payment_method_id = 3; // PayPal
|
||||
$payment_metadata = 'paypal_order_id';
|
||||
|
||||
} else {
|
||||
//==========================================
|
||||
// MOLLIE PAYMENT CREATION
|
||||
//==========================================
|
||||
// Initialize Mollie
|
||||
require dirname(__FILE__, 4).'/initialize.php';
|
||||
|
||||
$webhook_url = "{$protocol}://{$hostname}{$path}webhook_mollie.php";
|
||||
|
||||
// Create payment with Mollie
|
||||
$payment = $mollie->payments->create([
|
||||
'amount' => [
|
||||
'currency' => $final_currency ?: 'EUR',
|
||||
'value' => "{$formatted_price}"
|
||||
],
|
||||
'description' => "Software upgrade Order #{$txn_id}",
|
||||
'redirectUrl' => "{$redirect_url}",
|
||||
'webhookUrl' => "{$webhook_url}",
|
||||
'metadata' => [
|
||||
'order_id' => $txn_id,
|
||||
'serial_number' => $serial_number,
|
||||
'version_id' => $version_id,
|
||||
'equipment_id' => $equipment_id
|
||||
]
|
||||
]);
|
||||
|
||||
$payment_id = $payment->id;
|
||||
$checkout_url = $payment->getCheckoutUrl();
|
||||
|
||||
if (debug) {
|
||||
debuglog("DEBUG: Mollie payment created successfully");
|
||||
debuglog("DEBUG: Payment ID: $payment_id");
|
||||
debuglog("DEBUG: Redirect URL sent: $redirect_url");
|
||||
debuglog("DEBUG: Checkout URL: $checkout_url");
|
||||
}
|
||||
|
||||
$payment_method_id = 1; // Mollie
|
||||
$payment_metadata = 'mollie_payment_id';
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
debuglog("DEBUG: Mollie payment created successfully");
|
||||
debuglog("DEBUG: Payment ID: $mollie_payment_id");
|
||||
debuglog("DEBUG: Redirect URL sent: $redirect_url");
|
||||
debuglog("DEBUG: Redirect URL from Mollie object: " . $payment->redirectUrl);
|
||||
debuglog("DEBUG: Full payment object: " . json_encode($payment));
|
||||
debuglog("DEBUG: Payment created via $payment_provider");
|
||||
debuglog("DEBUG: Payment ID: $payment_id");
|
||||
debuglog("DEBUG: Checkout URL: $checkout_url");
|
||||
}
|
||||
|
||||
@@ -213,13 +328,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,
|
||||
address_street, address_city, address_state, address_zip, address_country, account_id, payment_method, accounthierarchy, created)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
$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, vat_number)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
$txn_id, // Use generated transaction ID, not Mollie payment ID
|
||||
$final_price,
|
||||
$txn_id,
|
||||
$amount_to_charge, // Total amount including tax
|
||||
$tax_amount, // Tax amount
|
||||
0, // 0 = pending
|
||||
$user_data['email'] ?? '',
|
||||
$first_name,
|
||||
@@ -230,9 +346,10 @@ try {
|
||||
$user_data['postal'] ?? '',
|
||||
$user_data['country'] ?? '',
|
||||
$serial_number,
|
||||
0, // payment method
|
||||
$payment_method_id, // 0 = Mollie, 1 = PayPal
|
||||
$partner_product,
|
||||
date('Y-m-d H:i:s')
|
||||
date('Y-m-d H:i:s'),
|
||||
$vat_number
|
||||
]);
|
||||
|
||||
// Get the database ID
|
||||
@@ -245,16 +362,19 @@ try {
|
||||
'serial_number' => $serial_number,
|
||||
'equipment_id' => $equipment_id,
|
||||
'hw_version' => $hw_version,
|
||||
'mollie_payment_id' => $mollie_payment_id // Store Mollie payment ID in options
|
||||
$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, // Use database transaction ID (not txn_id string, not mollie_payment_id)
|
||||
$transaction_id,
|
||||
$version_id,
|
||||
$final_price,
|
||||
$item_price_to_store, // Price without VAT
|
||||
1,
|
||||
$item_options,
|
||||
date('Y-m-d H:i:s')
|
||||
@@ -265,7 +385,7 @@ try {
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
$messages = json_encode([
|
||||
'checkout_url' => $checkout_url,
|
||||
'payment_id' => $mollie_payment_id
|
||||
'payment_id' => $payment_id
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
echo $messages;
|
||||
|
||||
@@ -275,4 +395,27 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// Helper function to get PayPal access token
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
function getPayPalAccessToken() {
|
||||
$ch = curl_init(PAYPAL_URL . '/v1/oauth2/token');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, 'grant_type=client_credentials');
|
||||
curl_setopt($ch, CURLOPT_USERPWD, PAYPAL_CLIENT_ID . ':' . PAYPAL_CLIENT_SECRET);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
curl_close($ch);
|
||||
|
||||
if ($http_code != 200) {
|
||||
throw new Exception("Failed to get PayPal access token: HTTP $http_code");
|
||||
}
|
||||
|
||||
$result = json_decode($response, true);
|
||||
return $result['access_token'] ?? '';
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -46,7 +46,8 @@ if (isset($post_content['cart']) && isset($post_content['checkout_input']) && is
|
||||
'address_state' => $post_content['customer_details']['address_state'] ?? '',
|
||||
'address_zip' => $post_content['customer_details']['address_zip'] ?? '',
|
||||
'address_country' => $post_content['customer_details']['address_country'] ?? '',
|
||||
'address_phone' => $post_content['customer_details']['address_phone'] ?? ''
|
||||
'address_phone' => $post_content['customer_details']['address_phone'] ?? '',
|
||||
'vat_number' => $post_content['customer_details']['vat_number'] ?? ''
|
||||
];
|
||||
|
||||
//Initialize calculator
|
||||
@@ -75,7 +76,7 @@ if (isset($post_content['cart']) && isset($post_content['checkout_input']) && is
|
||||
$txn_id = strtoupper(uniqid('SC') . substr(md5(mt_rand()), 0, 5));
|
||||
|
||||
// Insert transaction header
|
||||
$stmt = $pdo->prepare('INSERT INTO transactions (txn_id, payment_amount, payment_status, payer_email, first_name, last_name, address_street, address_city, address_state, address_zip, address_country, address_phone, account_id, payment_method, shipping_method, shipping_amount, discount_amount, discount_code, tax_amount,accounthierarchy) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)');
|
||||
$stmt = $pdo->prepare('INSERT INTO transactions (txn_id, payment_amount, payment_status, payer_email, first_name, last_name, address_street, address_city, address_state, address_zip, address_country, address_phone, account_id, payment_method, shipping_method, shipping_amount, discount_amount, discount_code, tax_amount,accounthierarchy, vat_number) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)');
|
||||
$stmt->execute([
|
||||
$txn_id,
|
||||
$total,
|
||||
@@ -96,7 +97,8 @@ if (isset($post_content['cart']) && isset($post_content['checkout_input']) && is
|
||||
$discounttotal,
|
||||
$checkout_input['discount_code'],
|
||||
$taxtotal,
|
||||
$partner_product
|
||||
$partner_product,
|
||||
$customer_details['vat_number']
|
||||
]);
|
||||
// Get order ID
|
||||
$transaction_id = $pdo->lastInsertId();
|
||||
|
||||
@@ -22,7 +22,7 @@ $command = ($id == '')? 'insert' : 'update'; //IF rowID = empty then INSERT
|
||||
if (isset($post_content['delete'])){$command = 'delete';} //change command to delete
|
||||
|
||||
// Check for bulk creation
|
||||
$is_bulk = isset($post_content['bulk']) && $post_content['bulk'] === true;
|
||||
$is_bulk = isset($post_content['bulk']) && ($post_content['bulk'] === "true" || $post_content['bulk'] === true);
|
||||
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
@@ -37,12 +37,24 @@ $input_insert = '';
|
||||
if ($command == 'insert' && $is_bulk && isAllowed('products_software_licenses',$profile,$permission,'C') === 1){
|
||||
|
||||
$version_id = $post_content['version_id'] ?? '';
|
||||
$serials = $post_content['serials'] ?? [];
|
||||
$serials_input = $post_content['serials'] ?? '';
|
||||
|
||||
// Convert comma-separated string to array and trim whitespace
|
||||
if (is_string($serials_input)) {
|
||||
$serials = array_map('trim', explode(',', $serials_input));
|
||||
} elseif (is_array($serials_input)) {
|
||||
$serials = $serials_input;
|
||||
} else {
|
||||
$serials = [];
|
||||
}
|
||||
|
||||
$transaction_id = $post_content['transaction_id'] ?? '';
|
||||
$license_type = $post_content['license_type'] ?? 0;
|
||||
$status = $post_content['status'] ?? 0;
|
||||
$status = $post_content['status'] ?? 1;
|
||||
$starts_at = $post_content['starts_at'] ?? date('Y-m-d H:i:s');
|
||||
$expires_at = $post_content['expires_at'] ?? '2099-12-31 23:59:59'; // effectively permanent
|
||||
|
||||
if (empty($version_id) || empty($serials) || !is_array($serials)) {
|
||||
if (empty($version_id) || empty($serials)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Invalid parameters for bulk creation']);
|
||||
exit;
|
||||
@@ -51,8 +63,8 @@ if ($command == 'insert' && $is_bulk && isAllowed('products_software_licenses',$
|
||||
$accounthierarchy = json_encode(array("salesid"=>$partner->salesid,"soldto"=>$partner->soldto), JSON_UNESCAPED_UNICODE);
|
||||
|
||||
// Prepare statement for bulk insert
|
||||
$sql = 'INSERT INTO products_software_licenses (version_id, license_key, license_type, status, transaction_id, accounthierarchy, created, createdby)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
$sql = 'INSERT INTO products_software_licenses (version_id, license_key, license_type, status, starts_at, expires_at, transaction_id, accounthierarchy, created, createdby)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
|
||||
$created_count = 0;
|
||||
@@ -60,13 +72,7 @@ if ($command == 'insert' && $is_bulk && isAllowed('products_software_licenses',$
|
||||
if (empty($serial)) continue;
|
||||
|
||||
// Generate UUID for license key
|
||||
$license_key = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0x0fff) | 0x4000,
|
||||
mt_rand(0, 0x3fff) | 0x8000,
|
||||
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
|
||||
);
|
||||
$license_key = generateUniqueLicenseKey();
|
||||
|
||||
try {
|
||||
$stmt->execute([
|
||||
@@ -74,6 +80,8 @@ if ($command == 'insert' && $is_bulk && isAllowed('products_software_licenses',$
|
||||
$license_key,
|
||||
$license_type,
|
||||
$status,
|
||||
$starts_at,
|
||||
$expires_at,
|
||||
$transaction_id,
|
||||
$accounthierarchy,
|
||||
$date,
|
||||
@@ -81,9 +89,9 @@ if ($command == 'insert' && $is_bulk && isAllowed('products_software_licenses',$
|
||||
]);
|
||||
|
||||
// Assign license to equipment if serial number exists
|
||||
$eq_sql = 'UPDATE equipment SET sw_version_license = ? WHERE serialnumber = ? AND accounthierarchy LIKE ?';
|
||||
$eq_sql = 'UPDATE equipment SET sw_version_license = ? WHERE serialnumber = ? ';
|
||||
$eq_stmt = $pdo->prepare($eq_sql);
|
||||
$eq_stmt->execute([$license_key, $serial, '%'.$partner->soldto.'%']);
|
||||
$eq_stmt->execute([$license_key, $serial]);
|
||||
|
||||
$created_count++;
|
||||
} catch (Exception $e) {
|
||||
@@ -104,17 +112,8 @@ if ($command == 'update'){
|
||||
$post_content['updatedby'] = $username;
|
||||
}
|
||||
elseif ($command == 'insert'){
|
||||
// Generate UUID for license key if not provided
|
||||
if (empty($post_content['license_key'])) {
|
||||
$post_content['license_key'] = sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
||||
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0xffff),
|
||||
mt_rand(0, 0x0fff) | 0x4000,
|
||||
mt_rand(0, 0x3fff) | 0x8000,
|
||||
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
|
||||
);
|
||||
}
|
||||
|
||||
// Generate UUID for license key
|
||||
$post_content['license_key'] = generateUniqueLicenseKey();
|
||||
$post_content['created'] = $date;
|
||||
$post_content['createdby'] = $username;
|
||||
$post_content['accounthierarchy'] = json_encode(array("salesid"=>$partner->salesid,"soldto"=>$partner->soldto), JSON_UNESCAPED_UNICODE);
|
||||
|
||||
@@ -14,7 +14,7 @@ $post_content = json_decode($input,true);
|
||||
if (empty($partner->soldto) || $partner->soldto == ''){$soldto_search = '%';} else {$soldto_search = '-%';}
|
||||
|
||||
//default whereclause
|
||||
list($whereclause,$condition) = getWhereclauselvl2("software_upgrade_paths",$permission,$partner,'');
|
||||
list($whereclause,$condition) = getWhereclauselvl2("",$permission,$partner,'');
|
||||
|
||||
//SET PARAMETERS FOR QUERY
|
||||
$id = $post_content['rowID'] ?? ''; //check for rowID
|
||||
|
||||
124
api/v2/post/report_builder.php
Normal file
124
api/v2/post/report_builder.php
Normal file
@@ -0,0 +1,124 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Report Builder - POST Endpoints
|
||||
//------------------------------------------
|
||||
|
||||
// Set content type to JSON
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
// Parse input data
|
||||
$data = json_decode($input, true);
|
||||
$action = strtolower($data['action'] ?? '');
|
||||
|
||||
/**
|
||||
* Security check: Only allow SELECT queries
|
||||
*/
|
||||
function isSelectQuery($query) {
|
||||
$query = trim($query);
|
||||
$query = preg_replace('/\s+/', ' ', $query); // Normalize whitespace
|
||||
|
||||
// Only allow SELECT queries
|
||||
if (!preg_match('/^SELECT\s/i', $query)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Block dangerous keywords that could be used for injection
|
||||
$dangerousPatterns = [
|
||||
'/;\s*DROP\s/i',
|
||||
'/;\s*DELETE\s/i',
|
||||
'/;\s*UPDATE\s/i',
|
||||
'/;\s*INSERT\s/i',
|
||||
'/;\s*CREATE\s/i',
|
||||
'/;\s*ALTER\s/i',
|
||||
'/;\s*TRUNCATE\s/i',
|
||||
'/INTO\s+OUTFILE\s/i',
|
||||
'/LOAD_FILE\s*\(/i',
|
||||
'/SLEEP\s*\(/i',
|
||||
'/BENCHMARK\s*\(/i',
|
||||
];
|
||||
|
||||
foreach ($dangerousPatterns as $pattern) {
|
||||
if (preg_match($pattern, $query)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a SELECT query
|
||||
*/
|
||||
if ($action === 'executequery') {
|
||||
$query = $data['query'] ?? '';
|
||||
|
||||
if (empty($query)) {
|
||||
http_response_code(400);
|
||||
$messages = json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Query parameter is required'
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
// Security check: only allow SELECT queries
|
||||
elseif (!isSelectQuery($query)) {
|
||||
http_response_code(400);
|
||||
$messages = json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Only SELECT queries are allowed'
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
} else {
|
||||
try {
|
||||
// Execute the query
|
||||
$stmt = $pdo->query($query);
|
||||
|
||||
// Fetch all results
|
||||
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
// Get row count
|
||||
$rowCount = count($results);
|
||||
|
||||
// Limit results to prevent memory issues
|
||||
$maxResults = 5000;
|
||||
if ($rowCount > $maxResults) {
|
||||
$results = array_slice($results, 0, $maxResults);
|
||||
$message = "Query executed successfully. Showing first $maxResults of $rowCount rows.";
|
||||
} else {
|
||||
$message = "Query executed successfully. $rowCount rows returned.";
|
||||
}
|
||||
|
||||
$messages = json_encode([
|
||||
'success' => true,
|
||||
'results' => $results,
|
||||
'rowCount' => $rowCount,
|
||||
'message' => $message
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
} catch (PDOException $e) {
|
||||
http_response_code(400);
|
||||
$messages = json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Query execution failed: ' . $e->getMessage()
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalid or missing action
|
||||
*/
|
||||
else {
|
||||
http_response_code(400);
|
||||
$messages = json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Invalid or missing action parameter'
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
// Send results
|
||||
echo $messages;
|
||||
?>
|
||||
75
api/v2/post/role_access_permissions.php
Normal file
75
api/v2/post/role_access_permissions.php
Normal file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// Role Access Permissions
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//CONTENT FROM API (POST)
|
||||
$post_content = json_decode($input,true);
|
||||
|
||||
//SET PARAMETERS FOR QUERY
|
||||
$id = $post_content['rowID'] ?? '';
|
||||
$command = ($id == '')? 'insert' : 'update';
|
||||
if (isset($post_content['delete'])){$command = 'delete';}
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
//CREATE EMPTY STRINGS
|
||||
$clause = '';
|
||||
$clause_insert ='';
|
||||
$input_insert = '';
|
||||
$execute_input = [];
|
||||
$criterias = [];
|
||||
|
||||
//ADD STANDARD PARAMETERS TO ARRAY BASED ON INSERT OR UPDATE
|
||||
if ($command == 'update'){
|
||||
$post_content['updatedby'] = $username;
|
||||
$post_content['updated'] = $date;
|
||||
}
|
||||
elseif ($command == 'insert'){
|
||||
$post_content['created'] = $date;
|
||||
$post_content['createdby'] = $username;
|
||||
}
|
||||
|
||||
//CREAT NEW ARRAY AND MAP TO CLAUSE
|
||||
if(isset($post_content) && $post_content!=''){
|
||||
foreach ($post_content as $key => $var){
|
||||
if ($key == 'submit' || $key == 'rowID' || str_contains($key, 'old_')){
|
||||
//do nothing
|
||||
}
|
||||
else {
|
||||
$criterias[$key] = $var;
|
||||
$clause .= ' , '.$key.' = ?';
|
||||
$clause_insert .= ' , '.$key.'';
|
||||
$input_insert .= ', ?';
|
||||
$execute_input[]= $var;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//CLEAN UP INPUT
|
||||
$clause = substr($clause, 2);
|
||||
$clause_insert = substr($clause_insert, 2);
|
||||
$input_insert = substr($input_insert, 1);
|
||||
|
||||
//QUERY AND VERIFY ALLOWED
|
||||
if ($command == 'update' && isAllowed('user_role_manage',$profile,$permission,'U') === 1){
|
||||
$sql = 'UPDATE role_access_permissions SET '.$clause.' WHERE rowID = ?';
|
||||
$execute_input[] = $id;
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($execute_input);
|
||||
}
|
||||
elseif ($command == 'insert' && isAllowed('user_role_manage',$profile,$permission,'C') === 1){
|
||||
$sql = 'INSERT INTO role_access_permissions ('.$clause_insert.') VALUES ('.$input_insert.')';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($execute_input);
|
||||
}
|
||||
elseif ($command == 'delete' && isAllowed('user_role_manage',$profile,$permission,'D') === 1){
|
||||
//Delete permission
|
||||
$stmt = $pdo->prepare('DELETE FROM role_access_permissions WHERE rowID = ?');
|
||||
$stmt->execute([$id]);
|
||||
}
|
||||
|
||||
?>
|
||||
141
api/v2/post/user_role_assignments.php
Normal file
141
api/v2/post/user_role_assignments.php
Normal file
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// User Role Assignments
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//CONTENT FROM API (POST)
|
||||
$post_content = json_decode($input,true);
|
||||
|
||||
//SET PARAMETERS FOR QUERY
|
||||
$id = $post_content['rowID'] ?? '';
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
//------------------------------------------
|
||||
// BATCH UPDATE - Update all roles for a user
|
||||
//------------------------------------------
|
||||
if (isset($post_content['batch_update']) && isset($post_content['user_id']) && isAllowed('user_manage',$profile,$permission,'U') === 1){
|
||||
$user_id = $post_content['user_id'];
|
||||
$selected_roles = $post_content['roles'] ?? [];
|
||||
|
||||
//Get currently assigned active roles
|
||||
$stmt = $pdo->prepare('SELECT role_id, rowID FROM user_role_assignments WHERE user_id = ? AND is_active = 1');
|
||||
$stmt->execute([$user_id]);
|
||||
$current_roles = [];
|
||||
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)){
|
||||
$current_roles[$row['role_id']] = $row['rowID'];
|
||||
}
|
||||
|
||||
//Remove roles that are no longer selected (soft delete)
|
||||
foreach ($current_roles as $role_id => $assignment_id){
|
||||
if (!in_array($role_id, $selected_roles)){
|
||||
$stmt = $pdo->prepare('UPDATE user_role_assignments SET is_active = 0, updatedby = ?, updated = ? WHERE rowID = ?');
|
||||
$stmt->execute([$username, $date, $assignment_id]);
|
||||
}
|
||||
}
|
||||
|
||||
//Add new roles that are selected but not currently assigned
|
||||
foreach ($selected_roles as $role_id){
|
||||
if (!array_key_exists($role_id, $current_roles)){
|
||||
//Check if this user-role combination existed before (inactive)
|
||||
$stmt = $pdo->prepare('SELECT rowID FROM user_role_assignments WHERE user_id = ? AND role_id = ? AND is_active = 0 LIMIT 1');
|
||||
$stmt->execute([$user_id, $role_id]);
|
||||
$existing = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($existing){
|
||||
//Reactivate existing assignment
|
||||
$stmt = $pdo->prepare('UPDATE user_role_assignments SET is_active = 1, assigned_by = ?, assigned_at = ?, updatedby = ?, updated = ? WHERE rowID = ?');
|
||||
$stmt->execute([$username, $date, $username, $date, $existing['rowID']]);
|
||||
} else {
|
||||
//Create new assignment
|
||||
$stmt = $pdo->prepare('INSERT INTO user_role_assignments (user_id, role_id, is_active, assigned_by, assigned_at, created, createdby) VALUES (?, ?, 1, ?, ?, ?, ?)');
|
||||
$stmt->execute([$user_id, $role_id, $username, $date, $date, $userkey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------
|
||||
// SINGLE OPERATIONS (for backward compatibility or direct API calls)
|
||||
//------------------------------------------
|
||||
else {
|
||||
$command = ($id == '')? 'insert' : 'update';
|
||||
if (isset($post_content['delete'])){$command = 'delete';}
|
||||
|
||||
//CREATE EMPTY STRINGS
|
||||
$clause = '';
|
||||
$clause_insert ='';
|
||||
$input_insert = '';
|
||||
$execute_input = [];
|
||||
$criterias = [];
|
||||
|
||||
//ADD STANDARD PARAMETERS TO ARRAY BASED ON INSERT OR UPDATE
|
||||
if ($command == 'update'){
|
||||
$post_content['updatedby'] = $username;
|
||||
$post_content['updated'] = $date;
|
||||
}
|
||||
elseif ($command == 'insert'){
|
||||
$post_content['created'] = $date;
|
||||
$post_content['createdby'] = $username;
|
||||
$post_content['assigned_by'] = $username;
|
||||
$post_content['assigned_at'] = $date;
|
||||
}
|
||||
|
||||
//CREAT NEW ARRAY AND MAP TO CLAUSE
|
||||
if(isset($post_content) && $post_content!=''){
|
||||
foreach ($post_content as $key => $var){
|
||||
if ($key == 'submit' || $key == 'rowID' || $key == 'delete' || $key == 'batch_update' || str_contains($key, 'old_')){
|
||||
//do nothing
|
||||
}
|
||||
else {
|
||||
$criterias[$key] = $var;
|
||||
$clause .= ' , '.$key.' = ?';
|
||||
$clause_insert .= ' , '.$key.'';
|
||||
$input_insert .= ', ?';
|
||||
$execute_input[]= $var;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//CLEAN UP INPUT
|
||||
$clause = substr($clause, 2);
|
||||
$clause_insert = substr($clause_insert, 2);
|
||||
$input_insert = substr($input_insert, 1);
|
||||
|
||||
//QUERY AND VERIFY ALLOWED
|
||||
if ($command == 'update' && isAllowed('user_manage',$profile,$permission,'U') === 1){
|
||||
$sql = 'UPDATE user_role_assignments SET '.$clause.' WHERE rowID = ?';
|
||||
$execute_input[] = $id;
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($execute_input);
|
||||
}
|
||||
elseif ($command == 'insert' && isAllowed('user_manage',$profile,$permission,'C') === 1){
|
||||
//Check if this user-role combination already exists (including inactive ones)
|
||||
$stmt = $pdo->prepare('SELECT rowID, is_active FROM user_role_assignments WHERE user_id = ? AND role_id = ? LIMIT 1');
|
||||
$stmt->execute([$post_content['user_id'], $post_content['role_id']]);
|
||||
$existing = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($existing){
|
||||
//If exists but inactive, reactivate it
|
||||
if ($existing['is_active'] == 0){
|
||||
$stmt = $pdo->prepare('UPDATE user_role_assignments SET is_active = 1, assigned_by = ?, assigned_at = ?, updatedby = ?, updated = ? WHERE rowID = ?');
|
||||
$stmt->execute([$username, $date, $username, $date, $existing['rowID']]);
|
||||
}
|
||||
//If already active, do nothing (or could throw an error)
|
||||
} else {
|
||||
//Insert new assignment
|
||||
$sql = 'INSERT INTO user_role_assignments ('.$clause_insert.') VALUES ('.$input_insert.')';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($execute_input);
|
||||
}
|
||||
}
|
||||
elseif ($command == 'delete' && isAllowed('user_manage',$profile,$permission,'D') === 1){
|
||||
//Soft delete by setting is_active to 0
|
||||
$stmt = $pdo->prepare('UPDATE user_role_assignments SET is_active = 0, updatedby = ?, updated = ? WHERE rowID = ?');
|
||||
$stmt->execute([$username, $date, $id]);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
123
api/v2/post/user_roles.php
Normal file
123
api/v2/post/user_roles.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
|
||||
//------------------------------------------
|
||||
// User Roles
|
||||
//------------------------------------------
|
||||
//Connect to DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
//CONTENT FROM API (POST)
|
||||
$post_content = json_decode($input,true);
|
||||
|
||||
//SET PARAMETERS FOR QUERY
|
||||
$id = $post_content['rowID'] ?? '';
|
||||
$command = ($id == '')? 'insert' : 'update';
|
||||
if (isset($post_content['delete'])){$command = 'delete';}
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
//CREATE EMPTY STRINGS
|
||||
$clause = '';
|
||||
$clause_insert ='';
|
||||
$input_insert = '';
|
||||
$execute_input = [];
|
||||
$criterias = [];
|
||||
|
||||
//ADD STANDARD PARAMETERS TO ARRAY BASED ON INSERT OR UPDATE
|
||||
if ($command == 'update'){
|
||||
$post_content['updatedby'] = $username;
|
||||
$post_content['updated'] = $date;
|
||||
}
|
||||
elseif ($command == 'insert'){
|
||||
$post_content['created'] = $date;
|
||||
$post_content['createdby'] = $username;
|
||||
}
|
||||
|
||||
//CREAT NEW ARRAY AND MAP TO CLAUSE
|
||||
if(isset($post_content) && $post_content!=''){
|
||||
foreach ($post_content as $key => $var){
|
||||
if ($key == 'submit' || $key == 'rowID' || $key == 'permissions' || str_contains($key, 'old_')){
|
||||
//do nothing
|
||||
}
|
||||
else {
|
||||
$criterias[$key] = $var;
|
||||
$clause .= ' , '.$key.' = ?';
|
||||
$clause_insert .= ' , '.$key.'';
|
||||
$input_insert .= ', ?';
|
||||
$execute_input[]= $var;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//CLEAN UP INPUT
|
||||
$clause = substr($clause, 2);
|
||||
$clause_insert = substr($clause_insert, 2);
|
||||
$input_insert = substr($input_insert, 1);
|
||||
|
||||
//QUERY AND VERIFY ALLOWED
|
||||
if ($command == 'update' && isAllowed('user_role_manage',$profile,$permission,'U') === 1){
|
||||
$sql = 'UPDATE user_roles SET '.$clause.' WHERE rowID = ?';
|
||||
$execute_input[] = $id;
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($execute_input);
|
||||
|
||||
//Handle permissions update
|
||||
if (isset($post_content['permissions'])){
|
||||
//First delete all existing permissions for this role
|
||||
$stmt = $pdo->prepare('DELETE FROM role_access_permissions WHERE role_id = ?');
|
||||
$stmt->execute([$id]);
|
||||
|
||||
//Insert new permissions
|
||||
foreach ($post_content['permissions'] as $access_id => $perms){
|
||||
$can_create = isset($perms['can_create']) ? 1 : 0;
|
||||
$can_read = isset($perms['can_read']) ? 1 : 0;
|
||||
$can_update = isset($perms['can_update']) ? 1 : 0;
|
||||
$can_delete = isset($perms['can_delete']) ? 1 : 0;
|
||||
|
||||
//Only insert if at least one permission is set
|
||||
if ($can_create || $can_read || $can_update || $can_delete){
|
||||
$stmt = $pdo->prepare('INSERT INTO role_access_permissions (role_id, access_id, can_create, can_read, can_update, can_delete, created, createdby) VALUES (?, ?, ?, ?, ?, ?, ?, ?)');
|
||||
$stmt->execute([$id, $access_id, $can_create, $can_read, $can_update, $can_delete, $date, $userkey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($command == 'insert' && isAllowed('user_role_manage',$profile,$permission,'C') === 1){
|
||||
$sql = 'INSERT INTO user_roles ('.$clause_insert.') VALUES ('.$input_insert.')';
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute($execute_input);
|
||||
|
||||
//Get the new role ID
|
||||
$new_role_id = $pdo->lastInsertId();
|
||||
|
||||
//Handle permissions for new role
|
||||
if (isset($post_content['permissions'])){
|
||||
foreach ($post_content['permissions'] as $access_id => $perms){
|
||||
$can_create = isset($perms['can_create']) ? 1 : 0;
|
||||
$can_read = isset($perms['can_read']) ? 1 : 0;
|
||||
$can_update = isset($perms['can_update']) ? 1 : 0;
|
||||
$can_delete = isset($perms['can_delete']) ? 1 : 0;
|
||||
|
||||
//Only insert if at least one permission is set
|
||||
if ($can_create || $can_read || $can_update || $can_delete){
|
||||
$stmt = $pdo->prepare('INSERT INTO role_access_permissions (role_id, access_id, can_create, can_read, can_update, can_delete, created, createdby) VALUES (?, ?, ?, ?, ?, ?, ?, ?)');
|
||||
$stmt->execute([$new_role_id, $access_id, $can_create, $can_read, $can_update, $can_delete, $date, $userkey]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($command == 'delete' && isAllowed('user_role_manage',$profile,$permission,'D') === 1){
|
||||
//Delete role permissions first (foreign key constraint)
|
||||
$stmt = $pdo->prepare('DELETE FROM role_access_permissions WHERE role_id = ?');
|
||||
$stmt->execute([$id]);
|
||||
|
||||
//Delete user role assignments
|
||||
$stmt = $pdo->prepare('DELETE FROM user_role_assignments WHERE role_id = ?');
|
||||
$stmt->execute([$id]);
|
||||
|
||||
//Delete role
|
||||
$stmt = $pdo->prepare('DELETE FROM user_roles WHERE rowID = ?');
|
||||
$stmt->execute([$id]);
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -44,12 +44,13 @@ $user_name_old = $user_data['username'];
|
||||
$view_old = $user_data['view'];
|
||||
$partnerhierarchy_old = json_decode($user_data['partnerhierarchy']);
|
||||
|
||||
$salesid_new = ((isset($post_content['salesid']) && $post_content['salesid'] != '' && $post_content['salesid'] != $partnerhierarchy_old->salesid)? $post_content['salesid'] : $partnerhierarchy_old->salesid);
|
||||
$soldto_new = ((isset($post_content['soldto']) && $post_content['soldto'] != '' && $post_content['soldto'] != $partnerhierarchy_old->soldto)? $post_content['soldto'] : $partnerhierarchy_old->soldto);
|
||||
$shipto_new = ((isset($post_content['shipto']) && $post_content['shipto'] != '' && $post_content['shipto'] != $partnerhierarchy_old->shipto)? $post_content['shipto'] : $partnerhierarchy_old->shipto);
|
||||
$location_new = ((isset($post_content['location']) && $post_content['location'] != '' && $post_content['location'] != $partnerhierarchy_old->location)? $post_content['location'] : $partnerhierarchy_old->location);
|
||||
// Allow clearing values by checking if key exists (even if empty)
|
||||
$salesid_new = (array_key_exists('salesid', $post_content)) ? $post_content['salesid'] : ($partnerhierarchy_old->salesid ?? '');
|
||||
$soldto_new = (array_key_exists('soldto', $post_content)) ? $post_content['soldto'] : ($partnerhierarchy_old->soldto ?? '');
|
||||
$shipto_new = (array_key_exists('shipto', $post_content)) ? $post_content['shipto'] : ($partnerhierarchy_old->shipto ?? '');
|
||||
$location_new = (array_key_exists('location', $post_content)) ? $post_content['location'] : ($partnerhierarchy_old->location ?? '');
|
||||
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
//ADMIN+ ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$salesid_new,
|
||||
@@ -57,7 +58,7 @@ $location_new = ((isset($post_content['location']) && $post_content['location']
|
||||
"shipto"=>$shipto_new,
|
||||
"location"=>$location_new
|
||||
);
|
||||
}elseif ($permission == 3) {
|
||||
}elseif (getHierarchyLevel($partner) == 1) {
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SOLD
|
||||
$account = array(
|
||||
"salesid"=>$partner->salesid,
|
||||
@@ -76,7 +77,7 @@ $location_new = ((isset($post_content['location']) && $post_content['location']
|
||||
}
|
||||
} elseif ($command == 'insert') {
|
||||
//ID is empty => INSERT / NEW RECORD
|
||||
if ($permission == 4){
|
||||
if (getHierarchyLevel($partner) == 0){
|
||||
//ADMIN+ ONLY ARE ALLOWED TO CHANGE SALES AND SOLD
|
||||
$account = array(
|
||||
"salesid"=>$post_content['salesid'],
|
||||
@@ -85,7 +86,7 @@ $location_new = ((isset($post_content['location']) && $post_content['location']
|
||||
"location"=>$post_content['location']
|
||||
);
|
||||
}
|
||||
elseif ($permission == 3){
|
||||
elseif (getHierarchyLevel($partner) == 1){
|
||||
//ADMIN ONLY ARE ALLOWED TO CHANGE SOLD
|
||||
$account = array(
|
||||
"salesid"=>$partner->salesid,
|
||||
@@ -153,12 +154,15 @@ else {
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++
|
||||
//RESET VIEW/PERMISSION BASED ON USER PERMISSION
|
||||
//+++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
$hierarchy_level = getHierarchyLevel($partner);
|
||||
|
||||
if($post_content['view']){
|
||||
switch ($permission) {
|
||||
case '4':
|
||||
switch ($hierarchy_level) {
|
||||
case '0':
|
||||
//ADMIN+ no override
|
||||
break;
|
||||
case '3':
|
||||
case '1':
|
||||
//ADMINS cannot set ADMIN+ => reset to admin
|
||||
$post_content['view'] = ($post_content['view'] == 5) ? 4 : $post_content['view'];
|
||||
break;
|
||||
|
||||
@@ -20,6 +20,66 @@ document.querySelector('.responsive-toggle').onclick = event => {
|
||||
localStorage.setItem('admin_menu', 'closed');
|
||||
}
|
||||
};
|
||||
|
||||
// Menu header collapse/expand functionality
|
||||
document.querySelectorAll('aside .menu-header').forEach(header => {
|
||||
header.addEventListener('click', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
// Toggle expanded state
|
||||
this.classList.toggle('expanded');
|
||||
|
||||
// Find the next sibling .sub element and toggle display
|
||||
const submenu = this.nextElementSibling;
|
||||
if (submenu && submenu.classList.contains('sub')) {
|
||||
submenu.classList.toggle('expanded');
|
||||
// Update inline style for display
|
||||
submenu.style.display = submenu.classList.contains('expanded') ? 'flex' : 'none';
|
||||
}
|
||||
|
||||
// Rotate chevron
|
||||
const chevron = this.querySelector('.menu-chevron');
|
||||
if (chevron) {
|
||||
chevron.style.transform = this.classList.contains('expanded') ? 'rotate(180deg)' : 'rotate(0deg)';
|
||||
}
|
||||
|
||||
// Store expanded state in localStorage for persistence
|
||||
const section = this.dataset.section;
|
||||
if (section) {
|
||||
const expandedSections = JSON.parse(localStorage.getItem('menu_expanded') || '{}');
|
||||
expandedSections[section] = this.classList.contains('expanded');
|
||||
localStorage.setItem('menu_expanded', JSON.stringify(expandedSections));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Restore menu expanded states from localStorage on page load
|
||||
(function restoreMenuState() {
|
||||
const expandedSections = JSON.parse(localStorage.getItem('menu_expanded') || '{}');
|
||||
|
||||
document.querySelectorAll('aside .menu-header').forEach(header => {
|
||||
const section = header.dataset.section;
|
||||
const submenu = header.nextElementSibling;
|
||||
const chevron = header.querySelector('.menu-chevron');
|
||||
|
||||
// If explicitly saved as expanded, apply it
|
||||
if (section && expandedSections[section] === true) {
|
||||
header.classList.add('expanded');
|
||||
if (submenu && submenu.classList.contains('sub')) {
|
||||
submenu.classList.add('expanded');
|
||||
submenu.style.display = 'flex';
|
||||
}
|
||||
if (chevron) chevron.style.transform = 'rotate(180deg)';
|
||||
}
|
||||
// If has selected child, always expand (override localStorage)
|
||||
if (submenu && submenu.querySelector('a.selected')) {
|
||||
header.classList.add('expanded');
|
||||
submenu.classList.add('expanded');
|
||||
submenu.style.display = 'flex';
|
||||
if (chevron) chevron.style.transform = 'rotate(180deg)';
|
||||
}
|
||||
});
|
||||
})();
|
||||
document.querySelectorAll('.tabs a').forEach((element, index) => {
|
||||
element.onclick = event => {
|
||||
event.preventDefault();
|
||||
@@ -1158,14 +1218,22 @@ function sortTextVal(a, b) {
|
||||
// Print DIV
|
||||
//------------------------------------------
|
||||
function printDiv(div) {
|
||||
var divContents = document.getElementById(div).innerHTML;
|
||||
var a = window.open('', '', '');
|
||||
a.document.write('<html>');
|
||||
a.document.write('<body > ');
|
||||
a.document.write(divContents);
|
||||
a.document.write('</body></html>');
|
||||
a.document.close();
|
||||
a.print();
|
||||
var divContents = document.getElementById(div).innerHTML;
|
||||
var printWindow = window.open('', '', 'height=600,width=800');
|
||||
printWindow.document.write('<html><head><title>Print</title>');
|
||||
printWindow.document.write('<style>');
|
||||
printWindow.document.write('body { font-family: Arial, sans-serif; margin: 20px; }');
|
||||
printWindow.document.write('table { border-collapse: collapse; width: 100%; }');
|
||||
printWindow.document.write('th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }');
|
||||
printWindow.document.write('th { background-color: #f2f2f2; }');
|
||||
printWindow.document.write('</style>');
|
||||
printWindow.document.write('</head><body>');
|
||||
printWindow.document.write(divContents);
|
||||
printWindow.document.write('</body></html>');
|
||||
printWindow.document.close();
|
||||
printWindow.focus();
|
||||
printWindow.print();
|
||||
printWindow.close();
|
||||
}
|
||||
|
||||
//------------------------------------------
|
||||
|
||||
114
assets/database/marketing_install.sql
Normal file
114
assets/database/marketing_install.sql
Normal file
@@ -0,0 +1,114 @@
|
||||
-- Marketing System Database Tables
|
||||
-- Run this script to create the necessary tables for the marketing file management system
|
||||
--
|
||||
-- Usage: Import this file into your MySQL database or run the commands individually
|
||||
-- Make sure to select the correct database before running these commands
|
||||
|
||||
-- Disable foreign key checks temporarily to avoid constraint errors
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- Create marketing_folders table
|
||||
CREATE TABLE IF NOT EXISTS `marketing_folders` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`folder_name` varchar(255) NOT NULL,
|
||||
`parent_id` int(11) DEFAULT NULL,
|
||||
`description` text DEFAULT NULL,
|
||||
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`createdby` varchar(100) DEFAULT NULL,
|
||||
`updated` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
`updatedby` varchar(100) DEFAULT NULL,
|
||||
`accounthierarchy` text DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `parent_id` (`parent_id`),
|
||||
KEY `accounthierarchy_idx` (`accounthierarchy`(100))
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Create marketing_files table
|
||||
CREATE TABLE IF NOT EXISTS `marketing_files` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) NOT NULL,
|
||||
`original_filename` varchar(255) NOT NULL,
|
||||
`file_path` varchar(500) NOT NULL,
|
||||
`thumbnail_path` varchar(500) DEFAULT NULL,
|
||||
`file_type` varchar(10) NOT NULL,
|
||||
`file_size` bigint(20) NOT NULL DEFAULT 0,
|
||||
`folder_id` int(11) DEFAULT NULL,
|
||||
`tags` json DEFAULT NULL,
|
||||
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`createdby` varchar(100) DEFAULT NULL,
|
||||
`updated` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
`updatedby` varchar(100) DEFAULT NULL,
|
||||
`accounthierarchy` text DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `folder_id` (`folder_id`),
|
||||
KEY `file_type` (`file_type`),
|
||||
KEY `accounthierarchy_idx` (`accounthierarchy`(100)),
|
||||
KEY `created_idx` (`created`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Create marketing_tags table
|
||||
CREATE TABLE IF NOT EXISTS `marketing_tags` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`tag_name` varchar(100) NOT NULL,
|
||||
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `tag_name` (`tag_name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Create marketing_file_tags junction table
|
||||
CREATE TABLE IF NOT EXISTS `marketing_file_tags` (
|
||||
`file_id` int(11) NOT NULL,
|
||||
`tag_id` int(11) NOT NULL,
|
||||
PRIMARY KEY (`file_id`, `tag_id`),
|
||||
KEY `file_id` (`file_id`),
|
||||
KEY `tag_id` (`tag_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- Add foreign key constraints after all tables are created
|
||||
ALTER TABLE `marketing_folders`
|
||||
ADD CONSTRAINT `fk_marketing_folders_parent`
|
||||
FOREIGN KEY (`parent_id`) REFERENCES `marketing_folders`(`id`) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE `marketing_files`
|
||||
ADD CONSTRAINT `fk_marketing_files_folder`
|
||||
FOREIGN KEY (`folder_id`) REFERENCES `marketing_folders`(`id`) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE `marketing_file_tags`
|
||||
ADD CONSTRAINT `fk_marketing_file_tags_file`
|
||||
FOREIGN KEY (`file_id`) REFERENCES `marketing_files`(`id`) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE `marketing_file_tags`
|
||||
ADD CONSTRAINT `fk_marketing_file_tags_tag`
|
||||
FOREIGN KEY (`tag_id`) REFERENCES `marketing_tags`(`id`) ON DELETE CASCADE;
|
||||
|
||||
-- Re-enable foreign key checks
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
-- Insert some default sample data (optional)
|
||||
-- Uncomment the lines below if you want to start with sample folders and tags
|
||||
|
||||
-- INSERT INTO `marketing_folders` (`folder_name`, `description`, `createdby`) VALUES
|
||||
-- ('Product Brochures', 'Marketing brochures and product information', 'system'),
|
||||
-- ('Technical Specifications', 'Technical documentation and specifications', 'system'),
|
||||
-- ('Images', 'Product images and photos', 'system'),
|
||||
-- ('Videos', 'Product videos and demonstrations', 'system');
|
||||
|
||||
-- INSERT INTO `marketing_tags` (`tag_name`) VALUES
|
||||
-- ('brochure'),
|
||||
-- ('specification'),
|
||||
-- ('manual'),
|
||||
-- ('image'),
|
||||
-- ('video'),
|
||||
-- ('product'),
|
||||
-- ('marketing'),
|
||||
-- ('technical');
|
||||
|
||||
-- Create upload directories (Note: This requires manual creation on file system)
|
||||
-- Create the following directories in your web server:
|
||||
-- - ./marketing/uploads/
|
||||
-- - ./marketing/uploads/thumbs/
|
||||
--
|
||||
-- Linux/macOS commands:
|
||||
-- mkdir -p marketing/uploads/thumbs
|
||||
-- chmod 755 marketing/uploads
|
||||
-- chmod 755 marketing/uploads/thumbs
|
||||
222
assets/database/migration_profiles_to_rbac.sql
Normal file
222
assets/database/migration_profiles_to_rbac.sql
Normal file
@@ -0,0 +1,222 @@
|
||||
-- ===================================================
|
||||
-- PROFILE TO RBAC MIGRATION SCRIPT
|
||||
-- Date: 2025-01-22
|
||||
-- Description: Migrate from settingsprofiles.php to user_roles RBAC system
|
||||
-- Note: Uses existing access_elements table (already populated)
|
||||
-- ===================================================
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
-- ===================================================
|
||||
-- PHASE 1: CREATE ROLES (matching existing profiles)
|
||||
-- ===================================================
|
||||
|
||||
INSERT INTO `user_roles` (`name`, `description`, `is_active`, `created`, `createdby`) VALUES
|
||||
('Standard', 'Basic user access - view equipment, history, service reports', 1, NOW(), 1),
|
||||
('Superuser', 'Extended access - manage equipment, products, users', 1, NOW(), 1),
|
||||
('Admin', 'Administrative access - full management capabilities', 1, NOW(), 1),
|
||||
('AdminPlus', 'System administrator - complete system access', 1, NOW(), 1),
|
||||
('Build', 'Build tool access only', 1, NOW(), 1),
|
||||
('Commerce', 'E-commerce and catalog management', 1, NOW(), 1),
|
||||
('Distribution', 'Distribution partner access', 1, NOW(), 1),
|
||||
('Firmware', 'Firmware/software update access only', 1, NOW(), 1),
|
||||
('Garage', 'Car testing and diagnostics', 1, NOW(), 1),
|
||||
('Interface', 'API/Interface access', 1, NOW(), 1),
|
||||
('Service', 'Service technician access', 1, NOW(), 1),
|
||||
('Other', 'Miscellaneous access level', 1, NOW(), 1)
|
||||
ON DUPLICATE KEY UPDATE `description` = VALUES(`description`);
|
||||
|
||||
-- ===================================================
|
||||
-- PHASE 2: CREATE ROLE_ACCESS_PERMISSIONS MAPPINGS
|
||||
-- ===================================================
|
||||
|
||||
-- Get role IDs
|
||||
SET @role_standard = (SELECT rowID FROM user_roles WHERE name = 'Standard' LIMIT 1);
|
||||
SET @role_superuser = (SELECT rowID FROM user_roles WHERE name = 'Superuser' LIMIT 1);
|
||||
SET @role_admin = (SELECT rowID FROM user_roles WHERE name = 'Admin' LIMIT 1);
|
||||
SET @role_adminplus = (SELECT rowID FROM user_roles WHERE name = 'AdminPlus' LIMIT 1);
|
||||
SET @role_build = (SELECT rowID FROM user_roles WHERE name = 'Build' LIMIT 1);
|
||||
SET @role_commerce = (SELECT rowID FROM user_roles WHERE name = 'Commerce' LIMIT 1);
|
||||
SET @role_distribution = (SELECT rowID FROM user_roles WHERE name = 'Distribution' LIMIT 1);
|
||||
SET @role_firmware = (SELECT rowID FROM user_roles WHERE name = 'Firmware' LIMIT 1);
|
||||
SET @role_garage = (SELECT rowID FROM user_roles WHERE name = 'Garage' LIMIT 1);
|
||||
SET @role_interface = (SELECT rowID FROM user_roles WHERE name = 'Interface' LIMIT 1);
|
||||
SET @role_service = (SELECT rowID FROM user_roles WHERE name = 'Service' LIMIT 1);
|
||||
SET @role_other = (SELECT rowID FROM user_roles WHERE name = 'Other' LIMIT 1);
|
||||
|
||||
-- ===================================================
|
||||
-- STANDARD ROLE PERMISSIONS (Read-only)
|
||||
-- Profile: application,firmwaretool,histories,history,servicereport,servicereports,dashboard,profile,equipment,equipments,products_software
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_standard, rowID, 0, 1, 0, 0 FROM access_elements WHERE access_path IN (
|
||||
'application', 'firmwaretool', 'histories', 'history', 'servicereport', 'servicereports',
|
||||
'dashboard', 'profile', 'equipment', 'equipments', 'products_software'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_read = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- SUPERUSER ROLE PERMISSIONS (Create, Read, Update)
|
||||
-- Profile: application,assets,firmwaretool,histories,history,history_manage,marketing,partner,partners,
|
||||
-- servicereport,servicereports,admin,dashboard,profile,equipment,equipment_manage,
|
||||
-- equipment_manage_edit,equipments,equipments_mass_update,product,product_manage,products,
|
||||
-- products_software,products_versions,user,user_manage,users
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_superuser, rowID, 1, 1, 1, 0 FROM access_elements WHERE access_path IN (
|
||||
'application', 'firmwaretool', 'histories', 'history', 'history_manage',
|
||||
'marketing', 'partner', 'partners', 'servicereport', 'servicereports',
|
||||
'dashboard', 'profile', 'equipment', 'equipment_manage',
|
||||
'equipments', 'equipments_mass_update', 'product', 'product_manage', 'products',
|
||||
'products_software', 'products_versions', 'user', 'users'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_create = 1, can_read = 1, can_update = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- ADMIN ROLE PERMISSIONS (Full CRUD)
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_admin, rowID, 1, 1, 1, 1 FROM access_elements WHERE access_path IN (
|
||||
'application', 'buildtool', 'cartest', 'cartest_manage', 'cartests',
|
||||
'changelog', 'communication', 'communication_send', 'communications', 'firmwaretool',
|
||||
'histories', 'history', 'history_manage', 'marketing', 'partner', 'partners',
|
||||
'servicereport', 'servicereports', 'software_available', 'software_download',
|
||||
'software_update', 'softwaretool', 'account', 'accounts', 'dashboard', 'profile',
|
||||
'contract', 'contract_manage', 'contracts', 'equipment', 'equipment_data',
|
||||
'equipment_healthindex', 'equipment_history', 'equipment_manage',
|
||||
'equipments', 'equipments_mass_update', 'product', 'product_manage', 'products',
|
||||
'products_software', 'products_software_assignment', 'products_software_assignments',
|
||||
'products_software_licenses', 'products_versions', 'report_build',
|
||||
'report_contracts_billing', 'report_healthindex', 'rma', 'rma_history',
|
||||
'rma_manage', 'rmas', 'user', 'users'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_create = 1, can_read = 1, can_update = 1, can_delete = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- ADMINPLUS ROLE PERMISSIONS (Full access to everything)
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_adminplus, rowID, 1, 1, 1, 1 FROM access_elements WHERE is_active = 1
|
||||
ON DUPLICATE KEY UPDATE can_create = 1, can_read = 1, can_update = 1, can_delete = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- BUILD ROLE PERMISSIONS
|
||||
-- Profile: application,buildtool,firmwaretool,dashboard,profile,products_software
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_build, rowID, 1, 1, 1, 0 FROM access_elements WHERE access_path IN (
|
||||
'application', 'buildtool', 'firmwaretool', 'dashboard', 'profile', 'products_software'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_create = 1, can_read = 1, can_update = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- COMMERCE ROLE PERMISSIONS
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_commerce, rowID, 1, 1, 1, 1 FROM access_elements WHERE access_path IN (
|
||||
'application', 'catalog', 'categories', 'category', 'checkout', 'discount', 'discounts',
|
||||
'identity', 'invoice', 'media', 'media_manage', 'order', 'orders', 'partner', 'partners',
|
||||
'placeorder', 'pricelists', 'pricelists_items', 'pricelists_manage', 'shipping',
|
||||
'shipping_manage', 'shopping_cart', 'taxes', 'transactions', 'transactions_items',
|
||||
'translation_manage', 'translations', 'translations_details', 'uploader',
|
||||
'dashboard', 'profile', 'product', 'product_manage', 'products', 'products_attributes',
|
||||
'products_attributes_items', 'products_attributes_manage', 'products_categories',
|
||||
'products_configurations', 'products_media', 'products_software', 'products_versions',
|
||||
'user', 'users'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_create = 1, can_read = 1, can_update = 1, can_delete = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- DISTRIBUTION ROLE PERMISSIONS
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_distribution, rowID, 1, 1, 1, 0 FROM access_elements WHERE access_path IN (
|
||||
'application', 'firmwaretool', 'histories', 'history', 'history_manage',
|
||||
'marketing', 'partner', 'partners', 'servicereport', 'servicereports',
|
||||
'dashboard', 'profile', 'equipment', 'equipment_manage',
|
||||
'equipments', 'equipments_mass_update', 'product', 'product_manage', 'products',
|
||||
'products_software', 'products_versions', 'user', 'users'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_create = 1, can_read = 1, can_update = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- FIRMWARE ROLE PERMISSIONS
|
||||
-- Profile: application,software_available,software_download,software_update,softwaretool,
|
||||
-- transactions,transactions_items,products_software_versions
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_firmware, rowID, 0, 1, 1, 0 FROM access_elements WHERE access_path IN (
|
||||
'application', 'software_available', 'software_download', 'software_update',
|
||||
'softwaretool', 'transactions', 'transactions_items', 'products_software_versions'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_read = 1, can_update = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- GARAGE ROLE PERMISSIONS
|
||||
-- Profile: application,cartest,cartest_manage,cartests,dashboard,profile,products_versions
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_garage, rowID, 1, 1, 1, 0 FROM access_elements WHERE access_path IN (
|
||||
'application', 'cartest', 'cartest_manage', 'cartests', 'dashboard', 'profile', 'products_versions'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_create = 1, can_read = 1, can_update = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- INTERFACE ROLE PERMISSIONS
|
||||
-- Profile: application,firmwaretool,invoice,payment,transactions,transactions_items,
|
||||
-- contract,contracts,equipment_manage,equipments,products_software,products_versions,users
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_interface, rowID, 1, 1, 1, 0 FROM access_elements WHERE access_path IN (
|
||||
'application', 'firmwaretool', 'invoice', 'payment', 'transactions', 'transactions_items',
|
||||
'contract', 'contracts', 'equipment_manage', 'equipments', 'products_software',
|
||||
'products_versions', 'users'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_create = 1, can_read = 1, can_update = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- SERVICE ROLE PERMISSIONS
|
||||
-- Profile: application,assets,firmwaretool,histories,history,history_manage,marketing,partner,partners,
|
||||
-- servicereport,servicereports,admin,dashboard,profile,equipment,equipment_manage,equipments,
|
||||
-- products_software,user,user_manage,users
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_service, rowID, 1, 1, 1, 0 FROM access_elements WHERE access_path IN (
|
||||
'application', 'firmwaretool', 'histories', 'history', 'history_manage',
|
||||
'marketing', 'partner', 'partners', 'servicereport', 'servicereports',
|
||||
'dashboard', 'profile', 'equipment', 'equipment_manage', 'equipments', 'products_software',
|
||||
'user', 'users'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_create = 1, can_read = 1, can_update = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- OTHER ROLE PERMISSIONS
|
||||
-- Profile: application,assets,firmwaretool,histories,history,history_manage,marketing,partner,partners,
|
||||
-- servicereport,servicereports,admin,dashboard,profile,equipment,equipment_manage,equipments,products_software
|
||||
-- ===================================================
|
||||
INSERT INTO `role_access_permissions` (`role_id`, `access_id`, `can_create`, `can_read`, `can_update`, `can_delete`)
|
||||
SELECT @role_other, rowID, 0, 1, 1, 0 FROM access_elements WHERE access_path IN (
|
||||
'application', 'firmwaretool', 'histories', 'history', 'history_manage',
|
||||
'marketing', 'partner', 'partners', 'servicereport', 'servicereports',
|
||||
'dashboard', 'profile', 'equipment', 'equipment_manage', 'equipments', 'products_software'
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE can_read = 1, can_update = 1;
|
||||
|
||||
-- ===================================================
|
||||
-- VERIFICATION QUERIES
|
||||
-- ===================================================
|
||||
|
||||
-- Check roles created
|
||||
SELECT rowID, name, description, is_active FROM user_roles ORDER BY rowID;
|
||||
|
||||
-- Check permissions per role
|
||||
SELECT ur.name as role_name, COUNT(rap.rowID) as permission_count
|
||||
FROM user_roles ur
|
||||
LEFT JOIN role_access_permissions rap ON ur.rowID = rap.role_id
|
||||
GROUP BY ur.rowID, ur.name
|
||||
ORDER BY ur.rowID;
|
||||
|
||||
-- ===================================================
|
||||
-- Change ROLLBACK to COMMIT when ready to apply
|
||||
-- ===================================================
|
||||
COMMIT;
|
||||
141
assets/database/migration_users_to_rbac.sql
Normal file
141
assets/database/migration_users_to_rbac.sql
Normal file
@@ -0,0 +1,141 @@
|
||||
-- ===================================================
|
||||
-- USER TO RBAC ROLE ASSIGNMENT MIGRATION SCRIPT
|
||||
-- Date: 2025-01-22
|
||||
-- Description: Migrate users from settings/view fields to user_role_assignments
|
||||
-- Prerequisites: Run migration_profiles_to_rbac.sql first to create roles
|
||||
-- ===================================================
|
||||
|
||||
START TRANSACTION;
|
||||
|
||||
-- ===================================================
|
||||
-- MAPPING REFERENCE:
|
||||
--
|
||||
-- users.settings field values -> role names:
|
||||
-- 'admin_profile' or view=4 -> TSS_Admin
|
||||
-- 'distribution' -> Distribution
|
||||
-- 'service' -> Service
|
||||
-- 'firmware' -> Software_Tool
|
||||
-- 'interface' -> Interface
|
||||
-- 'superuser_profile' or view=1 -> Service
|
||||
-- All others (including empty/NULL) -> Service
|
||||
--
|
||||
-- IGNORED/REMOVED PROFILES:
|
||||
-- 'standard_profile', 'adminplus_profile', 'build', 'commerce',
|
||||
-- 'garage', 'other'
|
||||
-- ===================================================
|
||||
|
||||
-- Get role IDs
|
||||
SET @role_tss_admin = (SELECT rowID FROM user_roles WHERE name = 'TSS_Admin' LIMIT 1);
|
||||
SET @role_distribution = (SELECT rowID FROM user_roles WHERE name = 'Distribution' LIMIT 1);
|
||||
SET @role_service = (SELECT rowID FROM user_roles WHERE name = 'Service' LIMIT 1);
|
||||
SET @role_software_tool = (SELECT rowID FROM user_roles WHERE name = 'Software_Tool' LIMIT 1);
|
||||
SET @role_interface = (SELECT rowID FROM user_roles WHERE name = 'Interface' LIMIT 1);
|
||||
|
||||
-- ===================================================
|
||||
-- PHASE 1: MIGRATE USERS BY SETTINGS FIELD (profile name)
|
||||
-- ===================================================
|
||||
|
||||
-- Users with 'admin_profile' setting -> TSS_Admin
|
||||
INSERT INTO `user_role_assignments` (`user_id`, `role_id`, `is_active`, `assigned_by`, `assigned_at`, `created`, `createdby`)
|
||||
SELECT id, @role_tss_admin, 1, 'migration_script', NOW(), NOW(), 1
|
||||
FROM users
|
||||
WHERE settings = 'admin_profile'
|
||||
ON DUPLICATE KEY UPDATE updated = NOW();
|
||||
|
||||
-- Users with 'distribution' setting -> Distribution
|
||||
INSERT INTO `user_role_assignments` (`user_id`, `role_id`, `is_active`, `assigned_by`, `assigned_at`, `created`, `createdby`)
|
||||
SELECT id, @role_distribution, 1, 'migration_script', NOW(), NOW(), 1
|
||||
FROM users
|
||||
WHERE settings = 'distribution'
|
||||
ON DUPLICATE KEY UPDATE updated = NOW();
|
||||
|
||||
-- Users with 'service' setting -> Service
|
||||
INSERT INTO `user_role_assignments` (`user_id`, `role_id`, `is_active`, `assigned_by`, `assigned_at`, `created`, `createdby`)
|
||||
SELECT id, @role_service, 1, 'migration_script', NOW(), NOW(), 1
|
||||
FROM users
|
||||
WHERE settings = 'service'
|
||||
ON DUPLICATE KEY UPDATE updated = NOW();
|
||||
|
||||
-- Users with 'firmware' setting -> Software_Tool
|
||||
INSERT INTO `user_role_assignments` (`user_id`, `role_id`, `is_active`, `assigned_by`, `assigned_at`, `created`, `createdby`)
|
||||
SELECT id, @role_software_tool, 1, 'migration_script', NOW(), NOW(), 1
|
||||
FROM users
|
||||
WHERE settings = 'firmware'
|
||||
ON DUPLICATE KEY UPDATE updated = NOW();
|
||||
|
||||
-- Users with 'interface' setting -> Interface
|
||||
INSERT INTO `user_role_assignments` (`user_id`, `role_id`, `is_active`, `assigned_by`, `assigned_at`, `created`, `createdby`)
|
||||
SELECT id, @role_interface, 1, 'migration_script', NOW(), NOW(), 1
|
||||
FROM users
|
||||
WHERE settings = 'interface'
|
||||
ON DUPLICATE KEY UPDATE updated = NOW();
|
||||
|
||||
-- Users with 'superuser_profile' setting -> Service
|
||||
INSERT INTO `user_role_assignments` (`user_id`, `role_id`, `is_active`, `assigned_by`, `assigned_at`, `created`, `createdby`)
|
||||
SELECT id, @role_service, 1, 'migration_script', NOW(), NOW(), 1
|
||||
FROM users
|
||||
WHERE settings = 'superuser_profile'
|
||||
ON DUPLICATE KEY UPDATE updated = NOW();
|
||||
|
||||
-- ===================================================
|
||||
-- PHASE 2: MIGRATE USERS WITH EMPTY/NULL SETTINGS (use view field)
|
||||
-- Only for users not already assigned a role
|
||||
-- ===================================================
|
||||
|
||||
-- Users with view=4 (Admin) and no settings -> TSS_Admin
|
||||
INSERT INTO `user_role_assignments` (`user_id`, `role_id`, `is_active`, `assigned_by`, `assigned_at`, `created`, `createdby`)
|
||||
SELECT u.id, @role_tss_admin, 1, 'migration_script', NOW(), NOW(), 1
|
||||
FROM users u
|
||||
LEFT JOIN user_role_assignments ura ON u.id = ura.user_id AND ura.is_active = 1
|
||||
WHERE (u.settings IS NULL OR u.settings = '')
|
||||
AND u.view = '4'
|
||||
AND ura.rowID IS NULL
|
||||
ON DUPLICATE KEY UPDATE updated = NOW();
|
||||
|
||||
-- ===================================================
|
||||
-- PHASE 3: CATCH-ALL - Any remaining users without role -> Service
|
||||
-- ===================================================
|
||||
|
||||
INSERT INTO `user_role_assignments` (`user_id`, `role_id`, `is_active`, `assigned_by`, `assigned_at`, `created`, `createdby`)
|
||||
SELECT u.id, @role_service, 1, 'migration_script', NOW(), NOW(), 1
|
||||
FROM users u
|
||||
LEFT JOIN user_role_assignments ura ON u.id = ura.user_id AND ura.is_active = 1
|
||||
WHERE ura.rowID IS NULL
|
||||
ON DUPLICATE KEY UPDATE updated = NOW();
|
||||
|
||||
-- ===================================================
|
||||
-- VERIFICATION QUERIES
|
||||
-- ===================================================
|
||||
|
||||
-- Check migration results: users per role
|
||||
SELECT
|
||||
ur.name as role_name,
|
||||
COUNT(ura.user_id) as user_count
|
||||
FROM user_roles ur
|
||||
LEFT JOIN user_role_assignments ura ON ur.rowID = ura.role_id AND ura.is_active = 1
|
||||
GROUP BY ur.rowID, ur.name
|
||||
ORDER BY user_count DESC;
|
||||
|
||||
-- Check for users without role assignments (should be 0)
|
||||
SELECT COUNT(*) as users_without_role
|
||||
FROM users u
|
||||
LEFT JOIN user_role_assignments ura ON u.id = ura.user_id AND ura.is_active = 1
|
||||
WHERE ura.rowID IS NULL;
|
||||
|
||||
-- Compare old vs new: show users with their old settings and new role
|
||||
SELECT
|
||||
u.id,
|
||||
u.username,
|
||||
u.settings as old_profile,
|
||||
u.view as old_view_level,
|
||||
ur.name as new_role
|
||||
FROM users u
|
||||
LEFT JOIN user_role_assignments ura ON u.id = ura.user_id AND ura.is_active = 1
|
||||
LEFT JOIN user_roles ur ON ura.role_id = ur.rowID
|
||||
ORDER BY u.id
|
||||
LIMIT 50;
|
||||
|
||||
-- ===================================================
|
||||
-- Change ROLLBACK to COMMIT when ready to apply
|
||||
-- ===================================================
|
||||
COMMIT;
|
||||
65
assets/database/user_rbac
Normal file
65
assets/database/user_rbac
Normal file
@@ -0,0 +1,65 @@
|
||||
CREATE TABLE `user_roles` (
|
||||
`rowID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) NOT NULL,
|
||||
`description` text DEFAULT NULL,
|
||||
`is_active` tinyint(1) NOT NULL DEFAULT 1,
|
||||
`created` timestamp NULL DEFAULT current_timestamp(),
|
||||
`createdby` int(11) DEFAULT NULL,
|
||||
`updated` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
`updatedby` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`rowID`),
|
||||
UNIQUE KEY `unique_role_name` (`name`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE `user_role_assignments` (
|
||||
`rowID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`user_id` int(11) NOT NULL,
|
||||
`role_id` int(11) NOT NULL,
|
||||
`is_active` tinyint(1) NOT NULL DEFAULT 1,
|
||||
`assigned_by` varchar(255) DEFAULT NULL,
|
||||
`assigned_at` timestamp NULL DEFAULT current_timestamp(),
|
||||
`expires_at` timestamp NULL DEFAULT NULL,
|
||||
`created` timestamp NULL DEFAULT current_timestamp(),
|
||||
`createdby` int(11) DEFAULT NULL,
|
||||
`updated` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
`updatedby` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`rowID`),
|
||||
UNIQUE KEY `unique_user_role_active` (`user_id`,`role_id`,`is_active`),
|
||||
KEY `role_id` (`role_id`),
|
||||
CONSTRAINT `user_role_assignments_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`rowID`) ON DELETE CASCADE,
|
||||
CONSTRAINT `user_role_assignments_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `user_roles` (`rowID`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
REATE TABLE `role_access_permissions` (
|
||||
`rowID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`role_id` int(11) NOT NULL,
|
||||
`access_id` int(11) NOT NULL,
|
||||
`can_create` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`can_read` tinyint(1) NOT NULL DEFAULT 1,
|
||||
`can_update` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`can_delete` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`created` timestamp NULL DEFAULT current_timestamp(),
|
||||
`createdby` int(11) DEFAULT NULL,
|
||||
`updated` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
`updatedby` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`rowID`),
|
||||
UNIQUE KEY `unique_role_view` (`role_id`,`access_id`),
|
||||
KEY `access_id` (`access_id`),
|
||||
CONSTRAINT `role_view_permissions_ibfk_1` FOREIGN KEY (`role_id`) REFERENCES `user_roles` (`rowID`) ON DELETE CASCADE,
|
||||
CONSTRAINT `role_view_permissions_ibfk_2` FOREIGN KEY (`access_id`) REFERENCES `system_views` (`rowID`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=112 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE `access_elements` (
|
||||
`rowID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`access_group` varchar(100) NOT NULL,
|
||||
`access_name` varchar(100) NOT NULL,
|
||||
`access_path` varchar(255) NOT NULL,
|
||||
`description` text DEFAULT NULL,
|
||||
`is_active` tinyint(1) NOT NULL DEFAULT 1,
|
||||
`created` timestamp NULL DEFAULT current_timestamp(),
|
||||
`createdby` int(11) DEFAULT NULL,
|
||||
`updated` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||
`updatedby` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`rowID`),
|
||||
UNIQUE KEY `unique_access_path` (`access_path`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=393 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
1097
assets/functions.php
1097
assets/functions.php
File diff suppressed because it is too large
Load Diff
BIN
assets/images/TSS_invoice_footer.png
Normal file
BIN
assets/images/TSS_invoice_footer.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 152 KiB |
BIN
assets/images/TSS_invoice_header.png
Normal file
BIN
assets/images/TSS_invoice_header.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 190 KiB |
164
assets/mail/email_template_invoice.php
Normal file
164
assets/mail/email_template_invoice.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
$payment_method = 'payment_method_'.$invoice_data['header']['payment_method'];
|
||||
|
||||
$message = '
|
||||
<!DOCTYPE html>
|
||||
<html lang="' . strtolower($language) . '">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>' . htmlspecialchars($lbl_invoice) . ' - Total Safety Solutions</title>
|
||||
</head>
|
||||
<body style="font-family: Arial, Helvetica, sans-serif; color: #000000; font-size: 14px; line-height: 1.6; margin: 0; padding: 0; background-color: #f4f4f4;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="background-color: #f4f4f4;">
|
||||
<tr>
|
||||
<td align="center" style="padding: 20px 0;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="600" style="background-color: #ffffff; max-width: 600px;">
|
||||
|
||||
<!-- Content -->
|
||||
<tr>
|
||||
<td style="padding: 30px 40px;">
|
||||
|
||||
<!-- Invoice Title -->
|
||||
<h1 style="font-size: 24px; font-weight: bold; color: #2c5f5d; margin: 0 0 25px 0;">' . htmlspecialchars($lbl_invoice) . '</h1>
|
||||
|
||||
<!-- Company Header -->
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin-bottom: 25px;">
|
||||
<tr>
|
||||
<td width="50%" style="vertical-align: top; font-size: 13px; line-height: 1.5;">
|
||||
<strong style="color: #2c5f5d; font-size: 14px;">Total Safety Solutions B.V.</strong><br>
|
||||
Laarakkerweg 8<br>
|
||||
5061 JR OISTERWIJK<br>
|
||||
Nederland
|
||||
</td>
|
||||
<td width="50%" style="vertical-align: top; text-align: left;">
|
||||
<strong style="color: #2c5f5d; font-size: 14px;">contact-details</strong><br>
|
||||
Ralf Adams<br>
|
||||
+31 13 8221480<br>
|
||||
ralfadams@totalsafetysolutions.nl
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- Customer -->
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin-bottom: 25px;">
|
||||
<tr>
|
||||
<td width="50%" style="vertical-align: top; font-size: 13px; line-height: 1.5;">
|
||||
<strong style="color: #2c5f5d; font-size: 14px;">Customer</strong><br>
|
||||
'.$invoice_data['customer']['name'].'<br>
|
||||
'.$invoice_data['customer']['street'].'<br>
|
||||
'.$invoice_data['customer']['zip'].', '.$invoice_data['customer']['city'].'<br>
|
||||
'.$invoice_data['customer']['country'].'
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- Invoice Details -->
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%" style="margin-bottom: 25px; font-size: 13px;">
|
||||
<tr>
|
||||
<td width="50%" style="vertical-align: top; padding-right: 10px;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||
<tr>
|
||||
<td style="padding: 3px 0;"><strong>Invoice Date:</strong></td>
|
||||
<td style="padding: 3px 0;">' . htmlspecialchars(date('d-m-Y', strtotime($invoice_date))) . '</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 3px 0;"><strong>Invoice Number:</strong></td>
|
||||
<td style="padding: 3px 0;">' . htmlspecialchars($order_id) . '</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 3px 0;"><strong>Your Vat Number:</strong></td>
|
||||
<td style="padding: 3px 0;">' . htmlspecialchars($invoice_data['customer']['vat_number'] ?? '') . '</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td width="50%" style="vertical-align: top; padding-left: 10px;">
|
||||
<table role="presentation" cellspacing="0" cellpadding="0" border="0" width="100%">
|
||||
<tr>
|
||||
<td style="padding: 3px 0;"><strong>Reference:</strong></td>
|
||||
<td style="padding: 3px 0;">Online order</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 3px 0;"><strong>Order number:</strong></td>
|
||||
<td style="padding: 3px 0;">' . htmlspecialchars($order_id) . '</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 3px 0;"><strong>Payment Methodr:</strong></td>
|
||||
<td style="padding: 3px 0;">' . (${$payment_method} ?? $invoice_data['header']['payment_method'] ). '</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!-- Items Table -->
|
||||
<table role="presentation" cellspacing="0" cellpadding="8" border="0" width="100%" style="margin-bottom: 20px; border-bottom: 2px solid #999999;">
|
||||
<thead>
|
||||
<tr style="background-color: #f8f8f8;">
|
||||
<th style="text-align: left; font-weight: bold; font-size: 12px; padding: 10px 8px; border-bottom: 1px solid #999999;">Item code</th>
|
||||
<th style="text-align: left; font-weight: bold; font-size: 12px; padding: 10px 8px; border-bottom: 1px solid #999999;">Description</th>
|
||||
<th style="text-align: center; font-weight: bold; font-size: 12px; padding: 10px 8px; border-bottom: 1px solid #999999;">Quantity</th>
|
||||
<th style="text-align: right; font-weight: bold; font-size: 12px; padding: 10px 8px; border-bottom: 1px solid #999999;">Price</th>
|
||||
<th style="text-align: right; font-weight: bold; font-size: 12px; padding: 10px 8px; border-bottom: 1px solid #999999;">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
|
||||
foreach ($items as $item) {
|
||||
$line_total = $item['price'] * $item['quantity'];
|
||||
$message .= '<tr>
|
||||
<td style="padding: 10px 8px; border-bottom: 1px solid #dddddd; font-size: 13px;">SOFTWARE</td>
|
||||
<td style="padding: 10px 8px; border-bottom: 1px solid #dddddd; font-size: 13px;">' . htmlspecialchars($item['name']);
|
||||
|
||||
if ($item['serial_number'] !== 'N/A') {
|
||||
$message .= '<br><span style="font-size: 12px; color: #666666;">Serial: ' . htmlspecialchars($item['serial_number']) . '</span>';
|
||||
}
|
||||
if ($item['license_key'] !== 'Pending') {
|
||||
$message .= '<br><span style="font-size: 12px; color: #666666;">License: ' . htmlspecialchars($item['license_key']) . '</span>';
|
||||
}
|
||||
|
||||
$message .= '</td>
|
||||
<td style="text-align: center; padding: 10px 8px; border-bottom: 1px solid #dddddd; font-size: 13px;">' . htmlspecialchars($item['quantity']) . '</td>
|
||||
<td style="text-align: right; padding: 10px 8px; border-bottom: 1px solid #dddddd; font-size: 13px;">€ ' . number_format($item['price'], 2) . '</td>
|
||||
<td style="text-align: right; padding: 10px 8px; border-bottom: 1px solid #dddddd; font-size: 13px;">€ ' . number_format($line_total, 2) . '</td>
|
||||
</tr>';
|
||||
}
|
||||
|
||||
$message .= '</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Totals -->
|
||||
<table role="presentation" cellspacing="0" cellpadding="5" border="0" width="250" align="right" style="margin-top: 10px; font-size: 13px;">
|
||||
<tr>
|
||||
<td style="text-align: left; padding: 5px 0;">' . htmlspecialchars($lbl_subtotal) . '</td>
|
||||
<td style="text-align: right; padding: 5px 0;">€ ' . number_format($subtotal, 2) . '</td>
|
||||
</tr>';
|
||||
|
||||
if ($tax_amount > 0) {
|
||||
$message .= '<tr>
|
||||
<td style="text-align: left; padding: 5px 0;">' . htmlspecialchars($lbl_tax) . '</td>
|
||||
<td style="text-align: right; padding: 5px 0;">€ ' . number_format($tax_amount, 2) . '</td>
|
||||
</tr>';
|
||||
} else {
|
||||
$message .= '<tr>
|
||||
<td style="text-align: left; padding: 5px 0;">VAT</td>
|
||||
<td style="text-align: right; padding: 5px 0;">included</td>
|
||||
</tr>';
|
||||
}
|
||||
|
||||
$message .= '<tr style="border-top: 2px solid #000000;">
|
||||
<td style="text-align: left; padding: 8px 0 5px 0;"><strong>' . htmlspecialchars($lbl_total) . '</strong></td>
|
||||
<td style="text-align: right; padding: 8px 0 5px 0;"><strong>€ ' . number_format($payment_amount, 2) . '</strong></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>';
|
||||
329
assets/mail/pdf_template_invoice.php
Normal file
329
assets/mail/pdf_template_invoice.php
Normal file
@@ -0,0 +1,329 @@
|
||||
<?php
|
||||
$payment_method = 'payment_method_'.$invoice_data['header']['payment_method'];
|
||||
|
||||
$pdf = '<!DOCTYPE html>
|
||||
<html lang="' . strtolower($language) . '">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>' . htmlspecialchars($lbl_invoice) . ' - Total Safety Solutions</title>
|
||||
<style>
|
||||
@page {margin: 220px 50px; }
|
||||
|
||||
body {
|
||||
font-family: "DejaVu Sans", Arial, sans-serif;
|
||||
color: #000;
|
||||
font-size: 11px;
|
||||
line-height: 1.4;
|
||||
margin: 10px auto;
|
||||
padding: 0;
|
||||
width:90%;
|
||||
}
|
||||
|
||||
#header {
|
||||
position: fixed;
|
||||
left: -52px;
|
||||
top: -220px;
|
||||
right: -50px;
|
||||
height: 200px;
|
||||
text-align: center;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#header img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#footer {
|
||||
position: fixed;
|
||||
left: -50px;
|
||||
bottom: -250px;
|
||||
right: -50px;
|
||||
height: 150px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#footer img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.invoice-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #2c5f5d;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.company-header {
|
||||
display: table;
|
||||
width: 100%;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.company-info, .contact-details {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.company-info h3 {
|
||||
font-weight: bold;
|
||||
margin: 0 0 5px 0;
|
||||
color: #2c5f5d;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.company-info p, .contact-details p {
|
||||
margin: 0;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.contact-details {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.contact-details h3 {
|
||||
font-weight: bold;
|
||||
margin: 0 0 5px 0;
|
||||
color: #2c5f5d;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.invoice-details {
|
||||
display: table;
|
||||
width: 100%;
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
|
||||
.invoice-left, .invoice-right {
|
||||
display: table-cell;
|
||||
vertical-align: top;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
.invoice-right {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.detail-row {
|
||||
margin-bottom: 2px;
|
||||
display: table;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.detail-label {
|
||||
display: table-cell;
|
||||
font-weight: normal;
|
||||
width: 140px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.detail-value {
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
.items-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 30px;
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
|
||||
.items-table th {
|
||||
padding: 8px 6px;
|
||||
font-weight: bold;
|
||||
text-align: left;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.items-table td {
|
||||
padding: 6px;
|
||||
border-bottom: 1px solid #999;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.items-table .qty-col {
|
||||
text-align: center;
|
||||
width: 70px;
|
||||
}
|
||||
|
||||
.items-table .price-col, .items-table .total-col {
|
||||
text-align: right;
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.items-table th.qty-col {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.items-table th.price-col, .items-table th.total-col {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.totals-section {
|
||||
float: right;
|
||||
width: 250px;
|
||||
margin-top: 20px;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.total-row {
|
||||
display: table;
|
||||
width: 100%;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.total-label {
|
||||
display: table-cell;
|
||||
text-align: left;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.total-amount {
|
||||
display: table-cell;
|
||||
text-align: right;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.final-total {
|
||||
border-top: 1px solid #000;
|
||||
padding-top: 5px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.final-total .total-amount {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
<img src="https://'.$portalURL.'/assets/images/TSS_invoice_header.png" alt="Invoice header">
|
||||
</div>
|
||||
<div id="footer">
|
||||
<img src="https://'.$portalURL.'/assets/images/TSS_invoice_footer.png" alt="Invoice footer">
|
||||
</div>
|
||||
|
||||
<div class="invoice-title">' . htmlspecialchars($lbl_invoice) . '</div>
|
||||
|
||||
<div class="company-header">
|
||||
<div class="company-info">
|
||||
<h3>Total Safety Solutions B.V.</h3>
|
||||
<p>Laarakkerweg 8</p>
|
||||
<p>5061 JR OISTERWIJK</p>
|
||||
<p>Nederland</p>
|
||||
</div>
|
||||
<div class="contact-details">
|
||||
<h3>contact-details</h3>
|
||||
<p>Ralf Adams</p>
|
||||
<p>+31 13 8221480</p>
|
||||
<p>ralfadams@totalsafetysolutions.nl</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="company-header">
|
||||
<div class="company-info">
|
||||
<h3>Customer</h3>
|
||||
<p>'.$invoice_data['customer']['name'].'</p>
|
||||
<p>'.$invoice_data['customer']['street'].'</p>
|
||||
<p>'.$invoice_data['customer']['zip'].', '.$invoice_data['customer']['city'].'</p>
|
||||
<p>'.$invoice_data['customer']['country'].'</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="invoice-details">
|
||||
<div class="invoice-left">
|
||||
<div class="detail-row">
|
||||
<div class="detail-label">Invoice Date</div>
|
||||
<div class="detail-value">: ' . htmlspecialchars(date('d-m-Y', strtotime($invoice_date))) . '</div>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<div class="detail-label">Invoice Number</div>
|
||||
<div class="detail-value">: ' . htmlspecialchars($order_id) . '</div>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<div class="detail-label">Your Vat Number</div>
|
||||
<div class="detail-value">: ' . htmlspecialchars($invoice_data['customer']['vat_number'] ?? '') . '</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="invoice-right">
|
||||
<div class="detail-row">
|
||||
<div class="detail-label">Reference</div>
|
||||
<div class="detail-value">: Online order</div>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<div class="detail-label">Order number</div>
|
||||
<div class="detail-value">: ' . htmlspecialchars($order_id) . '</div>
|
||||
</div>
|
||||
<div class="detail-row">
|
||||
<div class="detail-label">Payment Method</div>
|
||||
<div class="detail-value">: ' . (${$payment_method} ?? $invoice_data['header']['payment_method'] ). '</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="items-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Item code</th>
|
||||
<th>Description</th>
|
||||
<th class="qty-col">Quantity</th>
|
||||
<th class="price-col">Price</th>
|
||||
<th class="total-col">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>';
|
||||
|
||||
foreach ($items as $item) {
|
||||
$line_total = $item['price'] * $item['quantity'];
|
||||
$pdf .= '<tr>
|
||||
<td>SOFTWARE</td>
|
||||
<td>' . htmlspecialchars($item['name']);
|
||||
|
||||
if ($item['serial_number'] !== 'N/A') {
|
||||
$pdf .= '<br><small>Serial: ' . htmlspecialchars($item['serial_number']) . '</small>';
|
||||
}
|
||||
if ($item['license_key'] !== 'Pending') {
|
||||
$pdf .= '<br><small>License: ' . htmlspecialchars($item['license_key']) . '</small>';
|
||||
}
|
||||
|
||||
$pdf .= '</td>
|
||||
<td class="qty-col">' . htmlspecialchars($item['quantity']) . ' </td>
|
||||
<td class="price-col">€ ' . number_format($item['price'], 2) . '</td>
|
||||
<td class="total-col">€ ' . number_format($line_total, 2) . '</td>
|
||||
</tr>';
|
||||
}
|
||||
|
||||
$pdf .= '</tbody>
|
||||
</table>
|
||||
|
||||
<div class="totals-section">
|
||||
<div class="total-row">
|
||||
<div class="total-label">' . htmlspecialchars($lbl_subtotal) . '</div>
|
||||
<div class="total-amount">€ ' . number_format($subtotal, 2) . '</div>
|
||||
</div>';
|
||||
|
||||
if ($tax_amount > 0) {
|
||||
$pdf .= '<div class="total-row">
|
||||
<div class="total-label">' . htmlspecialchars($lbl_tax) . '</div>
|
||||
<div class="total-amount">€ ' . number_format($tax_amount, 2) . '</div>
|
||||
</div>';
|
||||
} else {
|
||||
$pdf .= '<div class="total-row">
|
||||
<div class="total-label">VAT</div>
|
||||
<div class="total-amount">included</div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
$pdf .= '<div class="total-row final-total">
|
||||
<div class="total-label">' . htmlspecialchars($lbl_total) . '</div>
|
||||
<div class="total-amount">€ ' . number_format($payment_amount, 2) . '</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>';
|
||||
1354
assets/marketing.js
Normal file
1354
assets/marketing.js
Normal file
File diff suppressed because it is too large
Load Diff
BIN
assets/mollie/.DS_Store
vendored
BIN
assets/mollie/.DS_Store
vendored
Binary file not shown.
BIN
assets/mollie/src/.DS_Store
vendored
BIN
assets/mollie/src/.DS_Store
vendored
Binary file not shown.
@@ -124,7 +124,7 @@ async function connectDevice() {
|
||||
// Log connection failure details
|
||||
await logCommunication(`Serial connection failed: ${error.message || 'Unknown error'}`, 'disconnected');
|
||||
|
||||
if (openPort === 1){
|
||||
if (openPort = 1){
|
||||
closePort();
|
||||
console.log("Closing port");
|
||||
alert("System is still trying to close the serial port. If this message continues to come up please refresh this page.");
|
||||
|
||||
@@ -10,11 +10,135 @@ let deviceVersion = "";
|
||||
let deviceHwVersion = "";
|
||||
let selectedSoftwareUrl = "";
|
||||
|
||||
// Helper function to generate country select options
|
||||
function generateCountryOptions(selectedCountry = '') {
|
||||
if (typeof COUNTRIES === 'undefined' || !COUNTRIES) {
|
||||
return `<option value="">${typeof TRANS_COUNTRY !== 'undefined' ? TRANS_COUNTRY : 'Country'}</option>`;
|
||||
}
|
||||
|
||||
// Sort countries alphabetically
|
||||
const sortedCountries = Object.values(COUNTRIES).sort((a, b) => {
|
||||
return a.country.localeCompare(b.country);
|
||||
});
|
||||
|
||||
let options = '<option value="">Select country</option>';
|
||||
sortedCountries.forEach(data => {
|
||||
const selected = (selectedCountry === data.country) ? 'selected' : '';
|
||||
options += `<option value="${data.country}" ${selected}>${data.country}</option>`;
|
||||
});
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
// Serial port variables (port, writer, textEncoder, writableStreamClosed declared in PHP)
|
||||
let reader;
|
||||
let readableStreamClosed;
|
||||
let keepReading = true;
|
||||
|
||||
// Browser compatibility check
|
||||
let isSerialSupported = false;
|
||||
|
||||
// Check browser compatibility on page load
|
||||
function checkBrowserCompatibility() {
|
||||
isSerialSupported = 'serial' in navigator;
|
||||
|
||||
if (!isSerialSupported) {
|
||||
// Show warning banner
|
||||
showBrowserWarningBanner();
|
||||
// Disable connect button
|
||||
disableSerialFunctionality();
|
||||
}
|
||||
|
||||
return isSerialSupported;
|
||||
}
|
||||
|
||||
function showBrowserWarningBanner() {
|
||||
const connectDevice = document.getElementById("connectdevice");
|
||||
if (!connectDevice) return;
|
||||
|
||||
const warningBanner = document.createElement("div");
|
||||
warningBanner.id = "browserWarningBanner";
|
||||
warningBanner.style.cssText = `
|
||||
background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
|
||||
color: white;
|
||||
padding: 15px 20px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
box-shadow: 0 4px 12px rgba(220, 53, 69, 0.3);
|
||||
`;
|
||||
|
||||
warningBanner.innerHTML = `
|
||||
<i class="fa-solid fa-exclamation-triangle" style="font-size: 24px;"></i>
|
||||
<div style="flex: 1;">
|
||||
<strong style="display: block; margin-bottom: 5px; font-size: 16px;">Browser Not Supported</strong>
|
||||
<p style="margin: 0; font-size: 14px; opacity: 0.95;">
|
||||
Please use <strong>Chrome</strong>, <strong>Edge</strong>, or <strong>Opera</strong> to access device connectivity features.
|
||||
</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
connectDevice.parentNode.insertBefore(warningBanner, connectDevice);
|
||||
}
|
||||
|
||||
function disableSerialFunctionality() {
|
||||
const connectButton = document.getElementById("connectButton");
|
||||
if (connectButton) {
|
||||
connectButton.disabled = true;
|
||||
connectButton.style.opacity = "0.5";
|
||||
connectButton.style.cursor = "not-allowed";
|
||||
connectButton.title = "Browser is not supported. Please use Chrome, Edge, or Opera.";
|
||||
}
|
||||
}
|
||||
|
||||
// Call on page load
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', checkBrowserCompatibility);
|
||||
} else {
|
||||
checkBrowserCompatibility();
|
||||
}
|
||||
|
||||
// Shared serial port reference for upload.js to use
|
||||
window.sharedSerialPort = null;
|
||||
|
||||
// Override requestPort to minimize user prompts
|
||||
// This intercepts all requestPort calls (including from upload.js) to reuse authorized ports
|
||||
if ('serial' in navigator) {
|
||||
const originalRequestPort = navigator.serial.requestPort.bind(navigator.serial);
|
||||
|
||||
navigator.serial.requestPort = async function(options) {
|
||||
// If we have a shared port, return it instead of prompting
|
||||
if (window.sharedSerialPort) {
|
||||
console.log('Using shared serial port (no prompt needed)');
|
||||
return window.sharedSerialPort;
|
||||
}
|
||||
|
||||
// Try already-authorized ports matching the filters
|
||||
const ports = await navigator.serial.getPorts();
|
||||
if (ports.length > 0 && options?.filters) {
|
||||
const match = ports.find(p => {
|
||||
const info = p.getInfo();
|
||||
return options.filters.some(f =>
|
||||
info.usbVendorId === f.usbVendorId &&
|
||||
info.usbProductId === f.usbProductId
|
||||
);
|
||||
});
|
||||
if (match) {
|
||||
console.log('Using previously authorized port (no prompt needed)');
|
||||
window.sharedSerialPort = match;
|
||||
return match;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: original prompt behavior
|
||||
const port = await originalRequestPort(options);
|
||||
window.sharedSerialPort = port; // Store for future use
|
||||
return port;
|
||||
};
|
||||
}
|
||||
|
||||
// Function to log communication to API (reused from scripts.js)
|
||||
async function logCommunication(data, direction) {
|
||||
// Only log if debug mode is enabled
|
||||
@@ -69,14 +193,37 @@ function progressBar(percentage, message, color){
|
||||
|
||||
// Connect device for software tool
|
||||
async function connectDeviceForSoftware() {
|
||||
// Browser compatibility check
|
||||
if (!isSerialSupported) {
|
||||
progressBar("100", "Browser not supported - Please use Chrome, Edge, or Opera", "#dc3545");
|
||||
await logCommunication('Connection attempt failed: Web Serial API not supported in browser', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
//clear input
|
||||
readBar.innerHTML = '';
|
||||
serialResultsDiv.innerHTML = '';
|
||||
|
||||
// Clear installation status if it exists
|
||||
const installStatus = document.getElementById("installationStatus");
|
||||
if (installStatus) {
|
||||
installStatus.remove();
|
||||
}
|
||||
|
||||
document.getElementById("softwareCheckStatus").style.display = "none";
|
||||
document.getElementById("softwareOptions").style.display = "none";
|
||||
document.getElementById("softwareOptionsContainer").style.display = "none";
|
||||
document.getElementById("noUpdatesMessage").style.display = "none";
|
||||
document.getElementById("uploadSection").style.display = "none";
|
||||
|
||||
// Reset softwareOptions visibility and blur state
|
||||
const softwareOptions = document.getElementById("softwareOptions");
|
||||
if (softwareOptions) {
|
||||
softwareOptions.style.display = "block";
|
||||
softwareOptions.style.filter = "blur(8px)";
|
||||
softwareOptions.style.opacity = "0.3";
|
||||
softwareOptions.style.pointerEvents = "none";
|
||||
}
|
||||
|
||||
// Reset data
|
||||
receivedDataBuffer = '';
|
||||
deviceSerialNumber = "";
|
||||
@@ -87,7 +234,7 @@ async function connectDeviceForSoftware() {
|
||||
progressBar("1", "", "");
|
||||
|
||||
// Check if DEBUG mode is enabled - use mock device data
|
||||
if (typeof DEBUG !== 'undefined' && DEBUG) {
|
||||
if (typeof DEBUG !== 'undefined' && DEBUG && typeof DEBUG_ID !== 'undefined' && DEBUG_ID) {
|
||||
// TEST MODE: Use mock device data
|
||||
deviceSerialNumber = "22110095";
|
||||
deviceVersion = "03e615af";
|
||||
@@ -161,7 +308,20 @@ async function connectDeviceForSoftware() {
|
||||
|
||||
} catch (error) {
|
||||
await logCommunication(`Connection error: ${error.message}`, 'error');
|
||||
progressBar("0", "Error: " + error.message, "#ff6666");
|
||||
|
||||
// Improved error messages with specific cases
|
||||
if (error.name === 'NotSupportedError' || !navigator.serial) {
|
||||
progressBar("100", "Browser not supported - Please use Chrome, Edge, or Opera", "#dc3545");
|
||||
} else if (error.message && error.message.includes('No port selected by the user')) {
|
||||
progressBar("100", "No device selected - Please try again", "#ff6666");
|
||||
} else if (error.name === 'NetworkError') {
|
||||
progressBar("100", "Connection failed - Please check device connection", "#ff6666");
|
||||
} else if (error.name === 'InvalidStateError') {
|
||||
progressBar("100", "Port already in use - Refreshing page...", "#ff9800");
|
||||
setTimeout(() => location.reload(), 2000);
|
||||
} else {
|
||||
progressBar("100", "Connection error: " + error.message, "#ff6666");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,7 +455,11 @@ async function closePortAfterRead() {
|
||||
await port.close();
|
||||
await logCommunication('Port closed successfully', 'info');
|
||||
|
||||
// Reset for next connection
|
||||
// Keep port reference in sharedSerialPort for upload.js to reuse
|
||||
// This prevents the need for another user prompt during firmware upload
|
||||
window.sharedSerialPort = port;
|
||||
|
||||
// Reset local variables for next connection
|
||||
reader = null;
|
||||
writer = null;
|
||||
readableStreamClosed = null;
|
||||
@@ -305,7 +469,12 @@ async function closePortAfterRead() {
|
||||
console.error('Error closing port after read:', error);
|
||||
await logCommunication(`Error closing port: ${error.message}`, 'error');
|
||||
|
||||
// Force reset even on error
|
||||
// Keep port reference even on error if port exists
|
||||
if (port) {
|
||||
window.sharedSerialPort = port;
|
||||
}
|
||||
|
||||
// Force reset local variables even on error
|
||||
reader = null;
|
||||
writer = null;
|
||||
readableStreamClosed = null;
|
||||
@@ -437,12 +606,28 @@ async function fetchSoftwareOptions() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Display options in table
|
||||
// Display options in table (blurred initially)
|
||||
displaySoftwareOptions(options);
|
||||
document.getElementById("softwareCheckStatus").style.display = "none";
|
||||
document.getElementById("softwareOptions").style.display = "block";
|
||||
document.getElementById("softwareOptionsContainer").style.display = "block";
|
||||
progressBar("100", "Software options loaded", "#04AA6D");
|
||||
|
||||
// Check if customer data already exists in sessionStorage
|
||||
const savedCustomerData = sessionStorage.getItem('customerData');
|
||||
|
||||
// Show user info modal only if no saved data and not in debug mode
|
||||
if ((typeof DEBUG === 'undefined' || !DEBUG || typeof DEBUG_ID === 'undefined' || !DEBUG_ID) && !savedCustomerData) {
|
||||
showUserInfoModal();
|
||||
} else {
|
||||
// Customer data already exists or 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');
|
||||
progressBar("0", "Error loading options: " + error.message, "#ff6666");
|
||||
@@ -458,6 +643,8 @@ function displaySoftwareOptions(options) {
|
||||
const price = parseFloat(option.price);
|
||||
const isFree = price === 0;
|
||||
const isCurrent = option.is_current === true || option.is_current === 1;
|
||||
const dealerInfo = option.dealer_info || {};
|
||||
const isDealer = dealerInfo.is_dealer === 1 || dealerInfo.is_dealer === '1';
|
||||
|
||||
// Create card with gradient background
|
||||
const card = document.createElement("div");
|
||||
@@ -562,92 +749,328 @@ function displaySoftwareOptions(options) {
|
||||
margin-top: auto;
|
||||
`;
|
||||
|
||||
const priceText = document.createElement("div");
|
||||
priceText.style.cssText = `
|
||||
font-size: ${isCurrent ? '18px' : '28px'};
|
||||
font-weight: ${isCurrent ? '600' : '800'};
|
||||
color: ${isCurrent ? '#6c757d' : (isFree ? '#04AA6D' : '#FF6B35')};
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
letter-spacing: 0.5px;
|
||||
`;
|
||||
// Check if this is a dealer customer - show dealer contact info instead of price/buy button
|
||||
if (isDealer && !isCurrent && !isFree) {
|
||||
// Dealer info section - replaces price and buy button
|
||||
const dealerSection = document.createElement("div");
|
||||
dealerSection.style.cssText = `
|
||||
background: linear-gradient(135deg, rgb(255, 107, 53) 0%, rgb(255, 69, 0) 100%);
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
if (isCurrent) {
|
||||
priceText.innerHTML = '<i class="fa-solid fa-check-circle"></i> INSTALLED';
|
||||
// Contact dealer message
|
||||
const dealerMessage = document.createElement("div");
|
||||
dealerMessage.style.cssText = `
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 12px;
|
||||
`;
|
||||
dealerMessage.innerHTML = '<i class="fa-solid fa-handshake" style="margin-right: 8px;"></i>Contact your dealer for pricing and upgrade options';
|
||||
dealerSection.appendChild(dealerMessage);
|
||||
|
||||
// Dealer contact details
|
||||
const dealerDetails = document.createElement("div");
|
||||
dealerDetails.style.cssText = `
|
||||
background: white;
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
text-align: left;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
`;
|
||||
|
||||
let dealerHtml = '';
|
||||
if (dealerInfo.name) {
|
||||
dealerHtml += `<div style="font-weight: 600; margin-bottom: 8px; color: #1565c0;"><i class="fa-solid fa-building" style="margin-right: 8px; width: 16px;"></i>${dealerInfo.name}</div>`;
|
||||
}
|
||||
if (dealerInfo.address || dealerInfo.city || dealerInfo.postalcode || dealerInfo.country) {
|
||||
dealerHtml += `<div style="margin-bottom: 6px; color: #666; display: flex; align-items: flex-start;"><i class="fa-solid fa-location-dot" style="margin-right: 8px; width: 16px; color: #999; margin-top: 2px;"></i><div>`;
|
||||
if (dealerInfo.address) {
|
||||
dealerHtml += `<div>${dealerInfo.address}</div>`;
|
||||
}
|
||||
if (dealerInfo.postalcode || dealerInfo.city) {
|
||||
dealerHtml += `<div>${[dealerInfo.postalcode, dealerInfo.city].filter(Boolean).join(' ')}</div>`;
|
||||
}
|
||||
if (dealerInfo.country) {
|
||||
dealerHtml += `<div>${dealerInfo.country}</div>`;
|
||||
}
|
||||
dealerHtml += `</div></div>`;
|
||||
}
|
||||
if (dealerInfo.email) {
|
||||
dealerHtml += `<div style="margin-bottom: 6px;"><i class="fa-solid fa-envelope" style="margin-right: 8px; width: 16px; color: #999;"></i><a href="mailto:${dealerInfo.email}" style="color: #1565c0; text-decoration: none;">${dealerInfo.email}</a></div>`;
|
||||
}
|
||||
if (dealerInfo.phone) {
|
||||
dealerHtml += `<div><i class="fa-solid fa-phone" style="margin-right: 8px; width: 16px; color: #999;"></i><a href="tel:${dealerInfo.phone}" style="color: #1565c0; text-decoration: none;">${dealerInfo.phone}</a></div>`;
|
||||
}
|
||||
|
||||
dealerDetails.innerHTML = dealerHtml;
|
||||
dealerSection.appendChild(dealerDetails);
|
||||
priceSection.appendChild(dealerSection);
|
||||
} else {
|
||||
priceText.innerHTML = isFree
|
||||
? 'Free'
|
||||
: `${option.currency || "€"} ${price.toFixed(2)}`;
|
||||
// Standard price display for non-dealer customers
|
||||
const priceText = document.createElement("div");
|
||||
priceText.style.cssText = `
|
||||
font-size: ${isCurrent ? '18px' : '28px'};
|
||||
font-weight: ${isCurrent ? '600' : '800'};
|
||||
color: ${isCurrent ? '#6c757d' : (isFree ? '#04AA6D' : '#FF6B35')};
|
||||
margin-bottom: 15px;
|
||||
text-align: center;
|
||||
letter-spacing: 0.5px;
|
||||
`;
|
||||
|
||||
if (isCurrent) {
|
||||
priceText.innerHTML = '<i class="fa-solid fa-check-circle"></i> INSTALLED';
|
||||
} else {
|
||||
priceText.innerHTML = isFree
|
||||
? 'Free'
|
||||
: `${option.currency || "€"} ${price.toFixed(2)} <small style="font-size: 12px; font-weight: 400; color: #888;">(excl. VAT)</small>`;
|
||||
}
|
||||
|
||||
priceSection.appendChild(priceText);
|
||||
|
||||
// Action button with gradient for paid
|
||||
const actionBtn = document.createElement("button");
|
||||
actionBtn.className = "btn";
|
||||
actionBtn.style.cssText = `
|
||||
width: 100%;
|
||||
background: ${isCurrent ? '#6c757d' : (isFree ? 'linear-gradient(135deg, #04AA6D 0%, #038f5a 100%)' : 'linear-gradient(135deg, #FF6B35 0%, #FF4500 100%)')};
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: ${isCurrent ? 'not-allowed' : 'pointer'};
|
||||
transition: all 0.3s ease;
|
||||
opacity: ${isCurrent ? '0.5' : '1'};
|
||||
box-shadow: ${isCurrent ? 'none' : '0 4px 12px rgba(0,0,0,0.15)'};
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
|
||||
if (isCurrent) {
|
||||
actionBtn.innerHTML = '<i class="fa-solid fa-check"></i> Currently Installed';
|
||||
actionBtn.disabled = true;
|
||||
} else if (isFree) {
|
||||
actionBtn.innerHTML = '<i class="fa-solid fa-download"></i>';
|
||||
actionBtn.onclick = () => selectUpgrade(option);
|
||||
actionBtn.onmouseenter = () => {
|
||||
actionBtn.style.background = 'linear-gradient(135deg, #038f5a 0%, #026b43 100%)';
|
||||
actionBtn.style.transform = 'translateY(-2px)';
|
||||
actionBtn.style.boxShadow = '0 6px 16px rgba(0,0,0,0.2)';
|
||||
};
|
||||
actionBtn.onmouseleave = () => {
|
||||
actionBtn.style.background = 'linear-gradient(135deg, #04AA6D 0%, #038f5a 100%)';
|
||||
actionBtn.style.transform = 'translateY(0)';
|
||||
actionBtn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
|
||||
};
|
||||
} else {
|
||||
actionBtn.innerHTML = '<i class="fa-solid fa-shopping-cart"></i>';
|
||||
actionBtn.onclick = () => selectUpgrade(option);
|
||||
actionBtn.onmouseenter = () => {
|
||||
actionBtn.style.background = 'linear-gradient(135deg, #FF4500 0%, #CC3700 100%)';
|
||||
actionBtn.style.transform = 'translateY(-2px)';
|
||||
actionBtn.style.boxShadow = '0 6px 16px rgba(255,107,53,0.4)';
|
||||
};
|
||||
actionBtn.onmouseleave = () => {
|
||||
actionBtn.style.background = 'linear-gradient(135deg, #FF6B35 0%, #FF4500 100%)';
|
||||
actionBtn.style.transform = 'translateY(0)';
|
||||
actionBtn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
|
||||
};
|
||||
}
|
||||
|
||||
priceSection.appendChild(actionBtn);
|
||||
}
|
||||
|
||||
priceSection.appendChild(priceText);
|
||||
|
||||
// Action button with gradient for paid
|
||||
const actionBtn = document.createElement("button");
|
||||
actionBtn.className = "btn";
|
||||
actionBtn.style.cssText = `
|
||||
width: 100%;
|
||||
background: ${isCurrent ? '#6c757d' : (isFree ? 'linear-gradient(135deg, #04AA6D 0%, #038f5a 100%)' : 'linear-gradient(135deg, #FF6B35 0%, #FF4500 100%)')};
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: ${isCurrent ? 'not-allowed' : 'pointer'};
|
||||
transition: all 0.3s ease;
|
||||
opacity: ${isCurrent ? '0.5' : '1'};
|
||||
box-shadow: ${isCurrent ? 'none' : '0 4px 12px rgba(0,0,0,0.15)'};
|
||||
letter-spacing: 0.5px;
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
|
||||
if (isCurrent) {
|
||||
actionBtn.innerHTML = '<i class="fa-solid fa-check"></i> Currently Installed';
|
||||
actionBtn.disabled = true;
|
||||
} else if (isFree) {
|
||||
actionBtn.innerHTML = '<i class="fa-solid fa-download"></i>';
|
||||
actionBtn.onclick = () => selectUpgrade(option);
|
||||
actionBtn.onmouseenter = () => {
|
||||
actionBtn.style.background = 'linear-gradient(135deg, #038f5a 0%, #026b43 100%)';
|
||||
actionBtn.style.transform = 'translateY(-2px)';
|
||||
actionBtn.style.boxShadow = '0 6px 16px rgba(0,0,0,0.2)';
|
||||
};
|
||||
actionBtn.onmouseleave = () => {
|
||||
actionBtn.style.background = 'linear-gradient(135deg, #04AA6D 0%, #038f5a 100%)';
|
||||
actionBtn.style.transform = 'translateY(0)';
|
||||
actionBtn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
|
||||
};
|
||||
} else {
|
||||
actionBtn.innerHTML = '<i class="fa-solid fa-shopping-cart"></i>';
|
||||
actionBtn.onclick = () => selectUpgrade(option);
|
||||
actionBtn.onmouseenter = () => {
|
||||
actionBtn.style.background = 'linear-gradient(135deg, #FF4500 0%, #CC3700 100%)';
|
||||
actionBtn.style.transform = 'translateY(-2px)';
|
||||
actionBtn.style.boxShadow = '0 6px 16px rgba(255,107,53,0.4)';
|
||||
};
|
||||
actionBtn.onmouseleave = () => {
|
||||
actionBtn.style.background = 'linear-gradient(135deg, #FF6B35 0%, #FF4500 100%)';
|
||||
actionBtn.style.transform = 'translateY(0)';
|
||||
actionBtn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.15)';
|
||||
};
|
||||
}
|
||||
|
||||
priceSection.appendChild(actionBtn);
|
||||
|
||||
card.appendChild(priceSection);
|
||||
grid.appendChild(card);
|
||||
});
|
||||
}
|
||||
|
||||
function showUserInfoModal() {
|
||||
// Create modal overlay
|
||||
const modal = document.createElement("div");
|
||||
modal.id = "userInfoModal";
|
||||
modal.style.cssText = `
|
||||
display: flex;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0,0,0,0.7);
|
||||
z-index: 2000;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
// Create modal content
|
||||
const modalContent = document.createElement("div");
|
||||
modalContent.style.cssText = `
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
max-width: 500px;
|
||||
width: 90%;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
margin: 20px;
|
||||
box-shadow: 0 20px 60px rgba(0,0,0,0.4);
|
||||
`;
|
||||
|
||||
modalContent.innerHTML = `
|
||||
<div style="padding: 30px; border-bottom: 2px solid #e0e0e0;">
|
||||
<h3 style="margin: 0; color: #333; font-size: 24px;">${typeof TRANS_USER_INFO_REQUIRED !== 'undefined' ? TRANS_USER_INFO_REQUIRED : 'User Information Required'}</h3>
|
||||
<p style="margin: 10px 0 0 0; color: #666; font-size: 14px;">${typeof TRANS_USER_INFO_DESCRIPTION !== 'undefined' ? TRANS_USER_INFO_DESCRIPTION : 'Please provide your information to continue with software updates'}</p>
|
||||
</div>
|
||||
<div style="padding: 30px;">
|
||||
<form id="userInfoForm" style="display: flex; flex-direction: column; gap: 15px;">
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 600;">${typeof TRANS_NAME !== 'undefined' ? TRANS_NAME : 'Name'} *</label>
|
||||
<input type="text" name="name" id="userInfoName" required style="width: 100%; padding: 12px; border: 2px solid #ddd; border-radius: 6px; font-size: 14px; transition: border 0.3s;" onfocus="this.style.borderColor='#04AA6D'" onblur="this.style.borderColor='#ddd'">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 600;">${typeof TRANS_EMAIL !== 'undefined' ? TRANS_EMAIL : 'Email'} *</label>
|
||||
<input type="email" name="email" id="userInfoEmail" required style="width: 100%; padding: 12px; border: 2px solid #ddd; border-radius: 6px; font-size: 14px; transition: border 0.3s;" onfocus="this.style.borderColor='#04AA6D'" onblur="this.style.borderColor='#ddd'">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 600;">${typeof TRANS_ADDRESS !== 'undefined' ? TRANS_ADDRESS : 'Address'} *</label>
|
||||
<input type="text" name="address" id="userInfoAddress" required placeholder="Street and number" style="width: 100%; padding: 12px; border: 2px solid #ddd; border-radius: 6px; font-size: 14px; margin-bottom: 10px; transition: border 0.3s;" onfocus="this.style.borderColor='#04AA6D'" onblur="this.style.borderColor='#ddd'">
|
||||
<input type="text" name="city" id="userInfoCity" required placeholder="${typeof TRANS_CITY !== 'undefined' ? TRANS_CITY : 'City'}" style="width: 100%; padding: 12px; border: 2px solid #ddd; border-radius: 6px; font-size: 14px; margin-bottom: 10px; transition: border 0.3s;" onfocus="this.style.borderColor='#04AA6D'" onblur="this.style.borderColor='#ddd'">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
|
||||
<input type="text" name="postal" id="userInfoPostal" required placeholder="${typeof TRANS_POSTAL !== 'undefined' ? TRANS_POSTAL : 'Postal code'}" style="padding: 12px; border: 2px solid #ddd; border-radius: 6px; font-size: 14px; transition: border 0.3s;" onfocus="this.style.borderColor='#04AA6D'" onblur="this.style.borderColor='#ddd'">
|
||||
<select name="country" id="userInfoCountry" required style="padding: 12px; border: 2px solid #ddd; border-radius: 6px; font-size: 14px; transition: border 0.3s;" onfocus="this.style.borderColor='#04AA6D'" onblur="this.style.borderColor='#ddd'">
|
||||
${generateCountryOptions()}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 10px; display: flex; gap: 10px;">
|
||||
<button type="button" onclick="location.reload()" style="padding: 15px 20px; background: #6c757d; color: white; border: none; border-radius: 8px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.3s;" onmouseover="this.style.background='#5a6268'" onmouseout="this.style.background='#6c757d'">
|
||||
<i class="fa-solid fa-times"></i>
|
||||
</button>
|
||||
<button type="submit" style="flex: 1; padding: 15px; background: linear-gradient(135deg, #04AA6D 0%, #038f5a 100%); color: white; border: none; border-radius: 8px; font-size: 16px; font-weight: 600; cursor: pointer; transition: all 0.3s;" onmouseover="this.style.transform='translateY(-2px)'; this.style.boxShadow='0 6px 16px rgba(4,170,109,0.3)'" onmouseout="this.style.transform='translateY(0)'; this.style.boxShadow='none'">
|
||||
${typeof TRANS_CONTINUE !== 'undefined' ? TRANS_CONTINUE : 'Continue'}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
`;
|
||||
|
||||
modal.appendChild(modalContent);
|
||||
document.body.appendChild(modal);
|
||||
|
||||
// Prefill form with customer data from sessionStorage if available
|
||||
const savedCustomerData = sessionStorage.getItem('customerData');
|
||||
if (savedCustomerData) {
|
||||
try {
|
||||
const customerData = JSON.parse(savedCustomerData);
|
||||
if (customerData.name) document.getElementById("userInfoName").value = customerData.name;
|
||||
if (customerData.email) document.getElementById("userInfoEmail").value = customerData.email;
|
||||
if (customerData.address) document.getElementById("userInfoAddress").value = customerData.address;
|
||||
if (customerData.city) document.getElementById("userInfoCity").value = customerData.city;
|
||||
if (customerData.postal) document.getElementById("userInfoPostal").value = customerData.postal;
|
||||
if (customerData.country) document.getElementById("userInfoCountry").value = customerData.country;
|
||||
} catch (e) {
|
||||
console.warn('Error parsing saved customer data:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle form submission
|
||||
document.getElementById("userInfoForm").onsubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
const formData = new FormData(e.target);
|
||||
const customerData = {
|
||||
name: formData.get("name"),
|
||||
email: formData.get("email"),
|
||||
address: formData.get("address"),
|
||||
city: formData.get("city"),
|
||||
postal: formData.get("postal"),
|
||||
country: formData.get("country")
|
||||
};
|
||||
|
||||
// Save customer data to sessionStorage
|
||||
sessionStorage.setItem('customerData', JSON.stringify(customerData));
|
||||
|
||||
// Send to API
|
||||
await sendUserInfoToAPI(customerData);
|
||||
|
||||
// Close modal
|
||||
document.body.removeChild(modal);
|
||||
|
||||
// Reveal software options by removing blur
|
||||
const softwareOptions = document.getElementById("softwareOptions");
|
||||
if (softwareOptions) {
|
||||
softwareOptions.style.filter = "none";
|
||||
softwareOptions.style.opacity = "1";
|
||||
softwareOptions.style.pointerEvents = "auto";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function sendUserInfoToAPI(customerData) {
|
||||
try {
|
||||
const serviceToken = document.getElementById("servicetoken")?.innerHTML || '';
|
||||
const url = link + '/v2/history';
|
||||
const bearer = 'Bearer ' + serviceToken;
|
||||
|
||||
const historyData = {
|
||||
sn: deviceSerialNumber,
|
||||
type: 'customer',
|
||||
sn_service: 'Portal',
|
||||
payload: customerData
|
||||
};
|
||||
|
||||
await logCommunication(`Sending user info to API: ${JSON.stringify(historyData)}`, 'sent');
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
withCredentials: true,
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Authorization': bearer,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(historyData)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
console.warn('Failed to send user info:', response.status);
|
||||
await logCommunication(`Failed to send user info: ${response.status}`, 'error');
|
||||
} else {
|
||||
const result = await response.json();
|
||||
console.log("User info sent successfully:", result);
|
||||
await logCommunication(`User info sent successfully: ${JSON.stringify(result)}`, 'received');
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Error sending user info:', error);
|
||||
await logCommunication(`Error sending user info: ${error.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function selectUpgrade(option) {
|
||||
const price = parseFloat(option.price || 0);
|
||||
const isFree = price === 0;
|
||||
|
||||
// If paid upgrade, show payment modal first
|
||||
// If paid upgrade, show payment modal with pre-filled data
|
||||
if (!isFree) {
|
||||
showPaymentModal(option);
|
||||
return;
|
||||
}
|
||||
|
||||
// Free upgrade - show confirmation modal first
|
||||
showFreeInstallModal(option);
|
||||
// Free upgrade - proceed directly with saved customer data
|
||||
const savedCustomerData = sessionStorage.getItem('customerData');
|
||||
if (savedCustomerData) {
|
||||
try {
|
||||
const customerData = JSON.parse(savedCustomerData);
|
||||
await downloadAndInstallSoftware(option, customerData);
|
||||
} catch (e) {
|
||||
console.warn('Error parsing saved customer data:', e);
|
||||
showFreeInstallModal(option);
|
||||
}
|
||||
} else {
|
||||
showFreeInstallModal(option);
|
||||
}
|
||||
}
|
||||
|
||||
function showFreeInstallModal(option) {
|
||||
@@ -693,22 +1116,24 @@ function showFreeInstallModal(option) {
|
||||
|
||||
<form id="freeInstallForm" style="display: flex; flex-direction: column; gap: 15px;">
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">Name *</label>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">${typeof TRANS_NAME !== 'undefined' ? TRANS_NAME : 'Name'} *</label>
|
||||
<input type="text" name="name" id="freeInstallName" required style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">Email *</label>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">${typeof TRANS_EMAIL !== 'undefined' ? TRANS_EMAIL : 'Email'} *</label>
|
||||
<input type="email" name="email" id="freeInstallEmail" required style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">Address *</label>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">${typeof TRANS_ADDRESS !== 'undefined' ? TRANS_ADDRESS : 'Address'} *</label>
|
||||
<input type="text" name="address" id="freeInstallAddress" required placeholder="Street and number" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; margin-bottom: 10px;">
|
||||
<input type="text" name="city" id="freeInstallCity" required placeholder="City" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; margin-bottom: 10px;">
|
||||
<input type="text" name="city" id="freeInstallCity" required placeholder="${typeof TRANS_CITY !== 'undefined' ? TRANS_CITY : 'City'}" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; margin-bottom: 10px;">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
|
||||
<input type="text" name="postal" id="freeInstallPostal" required placeholder="Postal code" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<input type="text" name="country" id="freeInstallCountry" required placeholder="Country" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<input type="text" name="postal" id="freeInstallPostal" required placeholder="${typeof TRANS_POSTAL !== 'undefined' ? TRANS_POSTAL : 'Postal code'}" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<select name="country" id="freeInstallCountry" required style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
${generateCountryOptions()}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -786,6 +1211,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 '<ul style="margin: 0; padding-left: 20px; color: #666; font-size: 13px; line-height: 1.6;">' +
|
||||
lines.map(line => `<li>${line}</li>`).join('') +
|
||||
'</ul>';
|
||||
};
|
||||
|
||||
// Create modal overlay
|
||||
const modal = document.createElement("div");
|
||||
modal.id = "paymentModal";
|
||||
@@ -823,40 +1259,58 @@ function showPaymentModal(option) {
|
||||
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-bottom: 20px;">
|
||||
<h4 style="margin: 0 0 10px 0; color: #333;">${option.name || "Software Update"}</h4>
|
||||
<p style="margin: 0 0 5px 0; color: #666;">Version: <strong>${option.version || "N/A"}</strong></p>
|
||||
<p style="margin: 0 0 15px 0; color: #666;">${option.description || ""}</p>
|
||||
<div style="font-size: 24px; font-weight: bold; color: #04AA6D;">
|
||||
${currency} ${price.toFixed(2)}
|
||||
<div style="margin: 0 0 15px 0;">${formatDescription(option.description)}</div>
|
||||
<div id="priceDisplay" style="font-size: 14px; color: #666;">
|
||||
<div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
|
||||
<span>Price (excl. VAT):</span>
|
||||
<span style="font-weight: 600;">${currency} ${price.toFixed(2)}</span>
|
||||
</div>
|
||||
<div id="taxDisplay" style="display: flex; justify-content: space-between; margin-bottom: 5px;">
|
||||
<span>VAT:</span>
|
||||
<span style="font-weight: 600;">-</span>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between; padding-top: 10px; border-top: 2px solid #ddd; margin-top: 10px;">
|
||||
<span style="font-weight: bold;">Total:</span>
|
||||
<span id="totalDisplay" style="font-size: 24px; font-weight: bold; color: #04AA6D;">${currency} ${price.toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="paymentForm" style="display: flex; flex-direction: column; gap: 15px;">
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">Name *</label>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">${typeof TRANS_NAME !== 'undefined' ? TRANS_NAME : 'Name'} *</label>
|
||||
<input type="text" name="name" id="paymentName" required style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">Email *</label>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">${typeof TRANS_EMAIL !== 'undefined' ? TRANS_EMAIL : 'Email'} *</label>
|
||||
<input type="email" name="email" id="paymentEmail" required style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">Address *</label>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">${typeof TRANS_ADDRESS !== 'undefined' ? TRANS_ADDRESS : 'Address'} *</label>
|
||||
<input type="text" name="address" id="paymentAddress" required placeholder="Street and number" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; margin-bottom: 10px;">
|
||||
<input type="text" name="city" id="paymentCity" required placeholder="City" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; margin-bottom: 10px;">
|
||||
<input type="text" name="city" id="paymentCity" required placeholder="${typeof TRANS_CITY !== 'undefined' ? TRANS_CITY : 'City'}" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px; margin-bottom: 10px;">
|
||||
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px;">
|
||||
<input type="text" name="postal" id="paymentPostal" required placeholder="Postal code" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<input type="text" name="country" id="paymentCountry" required placeholder="Country" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<input type="text" name="postal" id="paymentPostal" required placeholder="${typeof TRANS_POSTAL !== 'undefined' ? TRANS_POSTAL : 'Postal code'}" style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<select name="country" id="paymentCountry" required style="padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
${generateCountryOptions()}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">VAT Number</label>
|
||||
<input type="text" name="vat_number" id="paymentVatNumber" placeholder="Optional" style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style="display: block; margin-bottom: 5px; color: #333; font-weight: 500;">Payment Method *</label>
|
||||
<select name="payment_method" required style="width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; font-size: 14px;">
|
||||
<option value="">Select payment method</option>
|
||||
<option value="credit_card">Credit Card</option>
|
||||
<option value="paypal">PayPal</option>
|
||||
<option value="bank_transfer">Bank Transfer</option>
|
||||
${typeof MOLLIE_ENABLED !== 'undefined' && MOLLIE_ENABLED ? '<option value="1">Credit Card</option>' : ''}
|
||||
${typeof PAYPAL_ENABLED !== 'undefined' && PAYPAL_ENABLED ? '<option value="3">PayPal</option>' : ''}
|
||||
${typeof PAY_ON_DELIVERY_ENABLED !== 'undefined' && PAY_ON_DELIVERY_ENABLED ? '<option value="bank_transfer">Bank Transfer</option>' : ''}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
@@ -875,6 +1329,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 = `
|
||||
<span>VAT (${taxRate}%):</span>
|
||||
<span style="font-weight: 600;">${currency} ${taxAmount.toFixed(2)}</span>
|
||||
`;
|
||||
} else {
|
||||
taxDisplay.innerHTML = `
|
||||
<span>VAT:</span>
|
||||
<span style="font-weight: 600;">-</span>
|
||||
`;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -885,12 +1378,19 @@ 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.vat_number) document.getElementById("paymentVatNumber").value = customerData.vat_number;
|
||||
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);
|
||||
@@ -900,6 +1400,16 @@ function showPaymentModal(option) {
|
||||
document.getElementById("paymentForm").onsubmit = async (e) => {
|
||||
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 === '3') { // PayPal payment method ID
|
||||
paymentProvider = 'paypal';
|
||||
} 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"),
|
||||
@@ -907,9 +1417,13 @@ function showPaymentModal(option) {
|
||||
city: formData.get("city"),
|
||||
postal: formData.get("postal"),
|
||||
country: formData.get("country"),
|
||||
payment_method: formData.get("payment_method"),
|
||||
vat_number: formData.get("vat_number") || '',
|
||||
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
|
||||
};
|
||||
|
||||
@@ -920,7 +1434,8 @@ function showPaymentModal(option) {
|
||||
address: paymentData.address,
|
||||
city: paymentData.city,
|
||||
postal: paymentData.postal,
|
||||
country: paymentData.country
|
||||
country: paymentData.country,
|
||||
vat_number: paymentData.vat_number
|
||||
}));
|
||||
|
||||
await processPayment(paymentData, option, modal);
|
||||
@@ -1004,7 +1519,9 @@ async function processPayment(paymentData, option, modal) {
|
||||
const paymentRequest = {
|
||||
serial_number: deviceSerialNumber,
|
||||
version_id: option.version_id,
|
||||
user_data: paymentData // name, email, address only
|
||||
payment_method: paymentData.payment_method,
|
||||
payment_provider: paymentData.payment_provider,
|
||||
user_data: paymentData // name, email, address, etc.
|
||||
};
|
||||
|
||||
// Debug logging
|
||||
@@ -1012,13 +1529,15 @@ async function processPayment(paymentData, option, modal) {
|
||||
console.log("=== DEBUG: Payment Request ===");
|
||||
console.log("Serial Number:", deviceSerialNumber);
|
||||
console.log("Version ID:", option.version_id);
|
||||
console.log("Payment Method:", paymentData.payment_method);
|
||||
console.log("Payment Provider:", paymentData.payment_provider);
|
||||
console.log("User Data:", paymentData);
|
||||
console.log("Request payload:", paymentRequest);
|
||||
}
|
||||
|
||||
await logCommunication(`Payment initiated for version ${option.version_id}`, 'sent');
|
||||
await logCommunication(`Payment initiated for version ${option.version_id} via ${paymentData.payment_provider}`, 'sent');
|
||||
|
||||
// Call payment API to create Mollie payment
|
||||
// Call payment API (handles both Mollie and PayPal)
|
||||
const response = await fetch(link + "/v2/payment", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
@@ -1046,16 +1565,16 @@ async function processPayment(paymentData, option, modal) {
|
||||
}
|
||||
|
||||
if (result.checkout_url) {
|
||||
await logCommunication(`Redirecting to Mollie payment: ${result.payment_id}`, 'sent');
|
||||
await logCommunication(`Redirecting to ${paymentData.payment_provider} payment: ${result.payment_id}`, 'sent');
|
||||
|
||||
if (typeof DEBUG !== 'undefined' && DEBUG) {
|
||||
console.log("DEBUG: Redirecting to Mollie checkout...");
|
||||
console.log(`DEBUG: Redirecting to ${paymentData.payment_provider} checkout...`);
|
||||
}
|
||||
|
||||
// Close modal before redirect
|
||||
document.body.removeChild(modal);
|
||||
|
||||
// Redirect to Mollie checkout page
|
||||
// Redirect to payment checkout page
|
||||
window.location.href = result.checkout_url;
|
||||
} else {
|
||||
throw new Error(result.error || "No checkout URL received");
|
||||
@@ -1175,7 +1694,7 @@ async function downloadAndInstallSoftware(option, customerData = null) {
|
||||
window.upgraded_version = option.version || "";
|
||||
|
||||
// DEBUG MODE: Don't auto-trigger upload, let user manually test
|
||||
if (typeof DEBUG !== 'undefined' && DEBUG) {
|
||||
if (typeof DEBUG !== 'undefined' && DEBUG && typeof DEBUG_ID !== 'undefined' && DEBUG_ID) {
|
||||
// Show upload section and button for manual testing
|
||||
document.getElementById("uploadSection").style.display = "block";
|
||||
const uploadBtn = document.getElementById("uploadSoftware");
|
||||
@@ -1193,14 +1712,50 @@ async function downloadAndInstallSoftware(option, customerData = null) {
|
||||
console.log("Click the 'Install Software' button to test if upload.js can handle the file");
|
||||
alert("DEBUG MODE: Download complete!\n\nBlob size: " + blob.size + " bytes\n\nClick the 'Install Software' button to test upload.js");
|
||||
} else {
|
||||
// PRODUCTION MODE: Show upload button and automatically trigger
|
||||
// PRODUCTION MODE: Hide button and show installation in progress
|
||||
document.getElementById("uploadSection").style.display = "block";
|
||||
const uploadBtn = document.getElementById("uploadSoftware");
|
||||
uploadBtn.style.display = "block";
|
||||
uploadBtn.disabled = false;
|
||||
uploadBtn.style.display = "none";
|
||||
|
||||
// Hide device version information during installation
|
||||
const softwareOptions = document.getElementById("softwareOptions");
|
||||
if (softwareOptions) {
|
||||
softwareOptions.style.display = "none";
|
||||
}
|
||||
|
||||
// Create installation status indicator
|
||||
const installStatus = document.createElement("div");
|
||||
installStatus.id = "installationStatus";
|
||||
installStatus.style.cssText = `
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
|
||||
border-radius: 8px;
|
||||
margin: 10px 0;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
`;
|
||||
installStatus.innerHTML = `
|
||||
<i class="fa-solid fa-spinner fa-spin" style="font-size: 32px; color: #04AA6D; margin-bottom: 10px;"></i>
|
||||
<p style="margin: 0; font-size: 18px; font-weight: 600; color: #333;">Installing Software...</p>
|
||||
<p style="margin: 5px 0 0 0; color: #666; font-size: 14px;">Please keep your device connected and do not close this page</p>
|
||||
`;
|
||||
|
||||
// Insert status before the hidden upload section
|
||||
document.getElementById("uploadSection").parentNode.insertBefore(installStatus, document.getElementById("uploadSection"));
|
||||
|
||||
progressBar("60", "Ready to install, starting upload...", "#04AA6D");
|
||||
uploadBtn.click();
|
||||
progressBar("60", "Starting automatic installation...", "#04AA6D");
|
||||
|
||||
// Enable the upload button and automatically click it
|
||||
setTimeout(() => {
|
||||
uploadBtn.disabled = false;
|
||||
|
||||
// Start monitoring for completion
|
||||
if (typeof startUploadMonitoring === 'function') {
|
||||
startUploadMonitoring();
|
||||
}
|
||||
|
||||
uploadBtn.click();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -12,11 +12,11 @@ include_once './settings/settings_redirector.php';
|
||||
|
||||
$page = 'buildtool';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
$bearertoken = createCommunicationToken($_SESSION['userkey']);
|
||||
$bearertoken = createCommunicationToken($_SESSION['authorization']['userkey']);
|
||||
|
||||
//GET PRODUCTS FROM DB
|
||||
$pdo = dbConnect($dbname);
|
||||
|
||||
65
cartest.php
65
cartest.php
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -13,14 +13,14 @@ include_once './settings/systemcartest.php';
|
||||
|
||||
$page = 'cartest';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
//CALL TO API FOR cartest
|
||||
$api_url = '/v1/cartests/rowID='.$_GET['rowID'];
|
||||
@@ -129,41 +129,42 @@ $view .='<div class="content-block order-details">
|
||||
</div>';
|
||||
|
||||
$view .= '</div>';
|
||||
$view .= '<div class="content-block">
|
||||
|
||||
//Retrieve questions and awnsers
|
||||
if ($version == 0){
|
||||
$view .= '<div class="content-block">
|
||||
<div class="block-header">
|
||||
<i class="fa-solid fa-bars fa-sm"></i>'.$cartest_questions_text.'
|
||||
</div>
|
||||
<div class="table order-table">
|
||||
<table>';
|
||||
|
||||
//Retrieve questions and awnsers
|
||||
|
||||
if ($version == 0){
|
||||
|
||||
foreach ($cartest_questions as $key => $value){
|
||||
$view .= '<tr>
|
||||
<td style="width:25%;">'.$key.'</td>
|
||||
<td>'.((!empty($value)|| $value !='')?$value:$not_specified).'</td>
|
||||
</tr>';
|
||||
}
|
||||
} else {
|
||||
//CREATE OUTPUT BASED ON ARRAY
|
||||
$view .= '<div class="tabs">';
|
||||
foreach($arrayQuestions_cartest as $group){
|
||||
if ($group['Group_sequence'] == 1){
|
||||
$view .= '<a href="#" class="active">'.$group['Group'].'</a>';
|
||||
} else {
|
||||
$view .= '<a href="#">'.$group['Group'].'</a>';
|
||||
}
|
||||
}
|
||||
$view .= '</div>';
|
||||
foreach ($cartest_questions as $key => $value){
|
||||
$view .= '<tr>
|
||||
<td style="width:25%;">'.$key.'</td>
|
||||
<td>'.((!empty($value)|| $value !='')?$value:$not_specified).'</td>
|
||||
</tr>';
|
||||
}
|
||||
$view .= '
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
} else {
|
||||
//CREATE OUTPUT BASED ON ARRAY
|
||||
|
||||
foreach($arrayQuestions_cartest as $group){
|
||||
|
||||
if ($group['Group_sequence'] == 1){
|
||||
$view .= '<div class="tabs">
|
||||
<a href="#" class="active">'.$group['Group'].'</a>
|
||||
</div>';
|
||||
$view .= '<div class="content-block tab-content active">
|
||||
<div class="form responsive-width-100">';
|
||||
} else {
|
||||
$view .= '<div class="tabs">
|
||||
<a href="#">'.$group['Group'].'</a>
|
||||
</div>';
|
||||
$view .= '<div class="content-block tab-content">
|
||||
<div class="form responsive-width-100">';
|
||||
}
|
||||
@@ -197,14 +198,8 @@ $view .= '<div class="content-block">
|
||||
}
|
||||
$view .= ' </div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
}
|
||||
$view .= '
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
';
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($cartest_datapoints) && $cartest_datapoints !=''){
|
||||
$view .= '<div class="content-block">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -13,16 +13,16 @@ include_once './settings/systemcartest.php';
|
||||
|
||||
$page = 'cartest_manage';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
$bearertoken = createCommunicationToken($_SESSION['userkey']);
|
||||
$bearertoken = createCommunicationToken($_SESSION['authorization']['userkey']);
|
||||
|
||||
$rowID = $_GET['rowID'] ?? '';
|
||||
|
||||
@@ -40,7 +40,7 @@ $cartest = [
|
||||
'header' => [
|
||||
'CarVIN' => '',
|
||||
'year' => '',
|
||||
'NameTester'=> $_SESSION['username'],
|
||||
'NameTester'=> $_SESSION['authorization']['clientID'],
|
||||
'SN' =>'',
|
||||
'HW' =>'',
|
||||
'FW' =>''
|
||||
@@ -181,7 +181,7 @@ if ($delete_allowed === 1){
|
||||
$view .= '<input type="submit" name="delete" value="X" class="btn red mar-right-2" onclick="return confirm(\'Are you sure you want to delete this cartest?\')">';
|
||||
}
|
||||
if ($update_allowed === 1){
|
||||
$view .= '<input type="submit" name="submit" value="💾+" class="btn">';
|
||||
$view .= '<input type="submit" name="submit" value="💾" class="btn">';
|
||||
}
|
||||
|
||||
$view .= '</div>';
|
||||
@@ -242,17 +242,6 @@ $view .= '</div>';
|
||||
//BUILD TO INPUT FORM BASED ON ARRAY
|
||||
// ------------------------------
|
||||
|
||||
$view .= '<div class="tabs">';
|
||||
foreach($arrayQuestions_cartest as $group){
|
||||
|
||||
if ($group['Group_sequence'] == 1){
|
||||
$view .= '<a href="#" class="active">'.$group['Group'].'</a>';
|
||||
} else {
|
||||
$view .= '<a href="#">'.$group['Group'].'</a>';
|
||||
}
|
||||
}
|
||||
$view .= '</div>';
|
||||
|
||||
foreach($arrayQuestions_cartest as $group){
|
||||
|
||||
if ($group['Group_sequence'] == 1){
|
||||
|
||||
12
cartests.php
12
cartests.php
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -11,14 +11,14 @@ include_once './settings/settings_redirector.php';
|
||||
|
||||
$page = 'cartests';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
|
||||
//GET PARAMETERS
|
||||
@@ -112,7 +112,7 @@ $view .= '
|
||||
<a class="btn alt" href="index.php?page=cartests">'.$general_filters_clear.'</a>';
|
||||
|
||||
//SHOW DOWNLOAD TO EXCELL OPTION ONLY TO ADMIN USERS
|
||||
if ($_SESSION['permission'] == 3 || $_SESSION['permission'] == 4){
|
||||
if (isAllowed('cartests',$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D') === 1){
|
||||
$view .= '<a class="btn alt" href="index.php?page=cartests&download=">
|
||||
<i class="fa-solid fa-download"></i> Download
|
||||
</a>';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -15,7 +15,7 @@ $prev_page = $_SESSION['prev_origin'] ?? '';
|
||||
$page = $_SESSION['origin'] = 'catalog';
|
||||
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -15,7 +15,7 @@ $prev_page = $_SESSION['prev_origin'] ?? '';
|
||||
$page = $_SESSION['origin'] = 'categories';
|
||||
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
10
category.php
10
category.php
@@ -3,14 +3,14 @@ defined(page_security_key) or exit;
|
||||
|
||||
$page = 'category';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
$category = [
|
||||
'rowID' => '',
|
||||
@@ -104,7 +104,7 @@ if ($delete_allowed === 1){
|
||||
$view .= '<input type="submit" name="delete" value="X" class="btn red mar-right-2" onclick="return confirm(\'Are you sure you want to delete this category?\')">';
|
||||
}
|
||||
if ($update_allowed === 1){
|
||||
$view .= '<input type="submit" name="submit" value="💾+" class="btn">';
|
||||
$view .= '<input type="submit" name="submit" value="💾" class="btn">';
|
||||
}
|
||||
|
||||
$view .= '</div>';
|
||||
|
||||
@@ -3,14 +3,14 @@ defined(page_security_key) or exit;
|
||||
|
||||
$page = 'communication';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
// Default input communication values
|
||||
$communication = [
|
||||
@@ -106,7 +106,7 @@ if ($delete_allowed === 1){
|
||||
$view .= '<input type="submit" name="delete" value="X" class="btn red mar-right-2" onclick="return confirm(\'Are you sure you want to delete this communication?\')">';
|
||||
}
|
||||
if ($update_allowed === 1){
|
||||
$view .= '<input type="submit" name="submit" value="💾+" class="btn">';
|
||||
$view .= '<input type="submit" name="submit" value="💾" class="btn">';
|
||||
}
|
||||
|
||||
$view .= '</div>';
|
||||
|
||||
@@ -3,14 +3,14 @@ defined(page_security_key) or exit;
|
||||
|
||||
$page = 'communication_send';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
$url = 'index.php?page=communications';
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -19,15 +19,15 @@ $back_btn_orgin = ($prev_page != '')? '<a href="'.$prev_page.'" class="btn alt
|
||||
|
||||
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$page_manage = 'communication';
|
||||
$update_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
//GET PARAMETERS
|
||||
$pagination_page = isset($_GET['p']) ? $_GET['p'] : 1;
|
||||
@@ -83,7 +83,7 @@ if ($create_allowed === 1){
|
||||
$view .= '<a href="index.php?page=communication" class="btn">'.$button_create_communication.'</a>';
|
||||
}
|
||||
|
||||
if (isAllowed('communication_send',$_SESSION['profile'],$_SESSION['permission'],'U') === 1){
|
||||
if (isAllowed('communication_send',$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U') === 1){
|
||||
$view .= '<a href="index.php?page=communication_send" class="btn red mar-right-2">'.$button_create_communication_send.'</a>';
|
||||
}
|
||||
|
||||
|
||||
16
contract.php
16
contract.php
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -17,7 +17,7 @@ $page = 'contract';
|
||||
$back_btn_orgin = ($prev_page != '')? '<a href="'.$prev_page.'" class="btn alt mar-right-2">←</a>':'';
|
||||
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
@@ -27,11 +27,11 @@ $pagination_page = $_SESSION['p'] = isset($_GET['p']) ? $_GET['p'] : 1;
|
||||
|
||||
//PAGE Security
|
||||
$page_manage = 'contract_manage';
|
||||
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$update_allowed_edit = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$view_equipment = isAllowed('equipment' ,$_SESSION['profile'],$_SESSION['permission'],'R');
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$update_allowed_edit = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
$view_equipment = isAllowed('equipment' ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R');
|
||||
|
||||
//GET Details from URL
|
||||
$GET_VALUES = urlGETdetails($_GET) ?? '';
|
||||
@@ -309,7 +309,7 @@ $view .= '<div class="content-block">
|
||||
<tbody>';
|
||||
//Check for assigned tools
|
||||
foreach ($servicetools as $tools){
|
||||
$view .= '<tr><td>'.(($view_equipment == 1)? '<a href="index.php?page=equipment&serialnumber='.$tools.'" class="btn2">'.$tools.'</a>':$tools).'</td><tr>';
|
||||
$view .= '<tr><td>'.(($view_equipment == 1)? '<a href="index.php?page=equipment&serialnumber='.$tools.'" class="link-with-icon">'.$tools.' <i class="fa-solid fa-up-right-from-square"></i></a>':$tools).'</td><tr>';
|
||||
}
|
||||
$view .= '
|
||||
</tbody>
|
||||
|
||||
@@ -3,14 +3,14 @@ defined(page_security_key) or exit;
|
||||
|
||||
$page = 'contract_manage';
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$update_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
// Default input product values
|
||||
$contract = [
|
||||
@@ -31,7 +31,7 @@ $contract = [
|
||||
'reference' => '',
|
||||
'servicetool' => [],
|
||||
'assigned_users' => [],
|
||||
'accounthierarchy' => $_SESSION['partnerhierarchy'],
|
||||
'accounthierarchy' => $_SESSION['authorization']['partnerhierarchy'],
|
||||
'ignore_list' => []
|
||||
];
|
||||
|
||||
@@ -121,7 +121,7 @@ if ($delete_allowed === 1){
|
||||
$view .= '<input type="submit" name="delete" value="X" class="btn red mar-right-2" onclick="return confirm(\'Are you sure you want to delete this contract?\')">';
|
||||
}
|
||||
if ($update_allowed === 1){
|
||||
$view .= '<input type="submit" name="submit" value="💾+" class="btn">';
|
||||
$view .= '<input type="submit" name="submit" value="💾" class="btn">';
|
||||
}
|
||||
|
||||
$view .= '</div>';
|
||||
@@ -248,10 +248,10 @@ $view .=' </div>
|
||||
$partner_data = json_decode($contract['accounthierarchy']);
|
||||
|
||||
//BUID UP DROPDOWNS
|
||||
$salesid_dropdown = listPartner('salesid',$_SESSION['permission'],$partner_data->salesid,'');
|
||||
$soldto_dropdown = listPartner('soldto',$_SESSION['permission'],$partner_data->soldto,'');
|
||||
$shipto_dropdown = listPartner('shipto',$_SESSION['permission'],$partner_data->shipto,'');
|
||||
$location_dropdown = listPartner('location',$_SESSION['permission'],$partner_data->location,'');
|
||||
$salesid_dropdown = listPartner('salesid',$_SESSION['authorization']['permission'],$partner_data->salesid,'');
|
||||
$soldto_dropdown = listPartner('soldto',$_SESSION['authorization']['permission'],$partner_data->soldto,'');
|
||||
$shipto_dropdown = listPartner('shipto',$_SESSION['authorization']['permission'],$partner_data->shipto,'');
|
||||
$location_dropdown = listPartner('location',$_SESSION['authorization']['permission'],$partner_data->location,'');
|
||||
|
||||
//DISPLAY
|
||||
$view .= '<div class="tabs">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
defined(page_security_key) or exit;
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -18,15 +18,15 @@ $prev_page = ($_SESSION['origin'] == 'equipments') ? $_SESSION['prev_origin_equi
|
||||
$back_btn_orgin = ($prev_page != '')? '<a href="'.$prev_page.'" class="btn alt mar-right-2">←</a>':'';
|
||||
|
||||
//Check if allowed
|
||||
if (isAllowed($page,$_SESSION['profile'],$_SESSION['permission'],'R') === 0){
|
||||
if (isAllowed($page,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'R') === 0){
|
||||
header('location: index.php');
|
||||
exit;
|
||||
}
|
||||
//PAGE Security
|
||||
$page_manage = 'contract_manage';
|
||||
$update_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'U');
|
||||
$delete_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'D');
|
||||
$create_allowed = isAllowed($page_manage ,$_SESSION['profile'],$_SESSION['permission'],'C');
|
||||
$update_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'U');
|
||||
$delete_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'D');
|
||||
$create_allowed = isAllowed($page_manage ,$_SESSION['authorization']['permissions'],$_SESSION['authorization']['permission'],'C');
|
||||
|
||||
//Close Contracts when end_date expired
|
||||
closeContract();
|
||||
|
||||
@@ -5,7 +5,7 @@ include_once './assets/functions.php';
|
||||
include_once './settings/settings_redirector.php';
|
||||
include_once './settings/config_redirector.php';
|
||||
|
||||
if (debug && debug_id == $_SESSION['id']){
|
||||
if (debug && debug_id == $_SESSION['authorization']['id']){
|
||||
ini_set('display_errors', '1');
|
||||
ini_set('display_startup_errors', '1');
|
||||
error_reporting(E_ALL);
|
||||
@@ -62,12 +62,10 @@ foreach ($communications as $communication){
|
||||
$token ='';
|
||||
|
||||
$data = json_encode(array("username" => interface_user, "password" => interface_pw), JSON_UNESCAPED_UNICODE);
|
||||
//Secure data
|
||||
$payload = generate_payload($data);
|
||||
//API call
|
||||
$responses = ioServer('/v1/authorization', $payload);
|
||||
$responses = ioServer('/v2/authorization', $data);
|
||||
//Decode Payload
|
||||
if (!empty($responses)){$responses = decode_payload($responses);}else{$responses = '400';}
|
||||
if (!empty($responses)){$responses = json_decode($responses);}else{$responses = '400';}
|
||||
|
||||
if ($responses === 'NOK' || $responses === '400'){
|
||||
//Not allowed
|
||||
|
||||
@@ -19,7 +19,7 @@ $color_accent = '#2FAC66'; //'#ececec';
|
||||
// Database settings
|
||||
//------------------------------------------
|
||||
|
||||
require '/var/www/vhosts/morvalwatches.com/settings/soveliti_cloud_settings.php';
|
||||
require '/var/www/vhosts/morvalwatches.com/settings/bewellwell_cloud_settings.php';
|
||||
|
||||
//------------------------------------------
|
||||
// Menusetup & settings
|
||||
|
||||
@@ -327,7 +327,7 @@ $page_rows_software_versions = 50; //software versions
|
||||
//------------------------------------------
|
||||
// Languages supported
|
||||
//------------------------------------------
|
||||
$supportedLanguages = ['US', 'NL', 'DE', 'ES','PT'];
|
||||
$supportedLanguages = ['US', 'NL', 'DE', 'ES','PL','PT'];
|
||||
|
||||
//------------------------------------------
|
||||
// Pricing
|
||||
|
||||
102
custom/morvalwatches/mail/email_template_new.php
Normal file
102
custom/morvalwatches/mail/email_template_new.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
//------------------------------------------
|
||||
// Content Reset Email
|
||||
//------------------------------------------
|
||||
$newuser_subject = 'SoVeLiTi account created';
|
||||
$newuser_header = 'Dear user';
|
||||
|
||||
$newuser_text = 'Your administrator has provided access to SoVeLiTi.';
|
||||
$newuser_credential_text_1 = 'Your account has been created with username ';
|
||||
$newuser_credential_text_2 = 'Please click the button below to complete your registration.';
|
||||
|
||||
$newuser_closure = 'For security reasons this link is only active for 10 minutes.';
|
||||
|
||||
//------------------------------------------
|
||||
// Content Reset Email
|
||||
//------------------------------------------
|
||||
$subject = $newuser_subject;
|
||||
|
||||
$message = '
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>' . $subject . '</title>
|
||||
<style>
|
||||
@media screen and (max-width: 600px) {
|
||||
.content {
|
||||
width: 100% !important;
|
||||
display: block !important;
|
||||
padding: 10px !important;
|
||||
}
|
||||
.header, .body, .footer {
|
||||
padding: 20px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="font-family: Arial, sans-serif">
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="padding: 20px;">
|
||||
<table class="content" width="600" border="0" cellspacing="0" cellpadding="0" style="border-collapse: collapse; border: 1px solid #cccccc;">
|
||||
<!-- Header -->
|
||||
<tr>
|
||||
<td class="header" style="background-color:'.color.'; padding: 40px; text-align: center; color: white; font-size: 24px;">
|
||||
'.site_name.'
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Body -->
|
||||
<tr>
|
||||
<td class="body" style="padding: 40px; text-align: left; font-size: 16px; line-height: 1.6;">
|
||||
' . $newuser_header . ',
|
||||
<br>
|
||||
<br>
|
||||
'.$newuser_text.' '.$newuser_credential_text_1.'<b>'.$post_content['username'].'</b>
|
||||
<br>
|
||||
<br>
|
||||
'.$newuser_credential_text_2.'
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Call to action Button -->
|
||||
<tr>
|
||||
<td style="padding: 0px 40px 0px 40px; text-align: center;">
|
||||
<!-- CTA Button -->
|
||||
<table cellspacing="0" cellpadding="0" style="margin: auto;">
|
||||
<tr>
|
||||
<td align="center" style="background-color: '.color_accent.'; padding: 10px 20px; border-radius: 5px;">
|
||||
<a href="https://' . $portalURL . '/reset.php?resetkey='.$resetkey.'" target="_blank" style="color: #ffffff; text-decoration: none; font-weight: bold;">Reset Password</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="body" style="padding: 40px; text-align: left; font-size: 16px; line-height: 1.6;">
|
||||
' . $newuser_closure . '
|
||||
<br>
|
||||
<br>
|
||||
Kind regards,
|
||||
<br>
|
||||
<br>
|
||||
Service team
|
||||
<br>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Footer -->
|
||||
<tr>
|
||||
<td class="footer" style="background: url(\'https://'.$portalURL.emaillogo.'\');background-position: center center;background-repeat:no-repeat;background-size:contain;background-color: '.color.'; padding: 40px;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
';
|
||||
99
custom/morvalwatches/mail/email_template_reset.php
Normal file
99
custom/morvalwatches/mail/email_template_reset.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
defined($security_key) or exit;
|
||||
//------------------------------------------
|
||||
// Content Reset Email
|
||||
//------------------------------------------
|
||||
$changeuser_subject = 'SoVeLiTi - password reset requested';
|
||||
$changeuser_header = 'Dear user';
|
||||
$changeuser_text = 'A password reset has been requested for your account.';
|
||||
$changeuser_credential_text_1 = 'Please click the button below to reset the password of your SoVeLiTi account.';
|
||||
$changeuser_closure = 'For security reasons this link is only active for 10 minutes.';
|
||||
|
||||
//------------------------------------------
|
||||
// Content Reset Email
|
||||
//------------------------------------------
|
||||
$subject = $changeuser_subject;
|
||||
|
||||
$message = '
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>' . $subject . '</title>
|
||||
<style>
|
||||
@media screen and (max-width: 600px) {
|
||||
.content {
|
||||
width: 100% !important;
|
||||
display: block !important;
|
||||
padding: 10px !important;
|
||||
}
|
||||
.header, .body, .footer {
|
||||
padding: 20px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style="font-family: Arial, sans-serif">
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td align="center" style="padding: 20px;">
|
||||
<table class="content" width="600" border="0" cellspacing="0" cellpadding="0" style="border-collapse: collapse; border: 1px solid #cccccc;">
|
||||
<!-- Header -->
|
||||
<tr>
|
||||
<td class="header" style="background-color:'.color.'; padding: 40px; text-align: center; color: white; font-size: 24px;">
|
||||
'.site_title.'
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Body -->
|
||||
<tr>
|
||||
<td class="body" style="padding: 40px; text-align: left; font-size: 16px; line-height: 1.6;">
|
||||
' . $changeuser_header . ',
|
||||
<br>
|
||||
<br>
|
||||
'.$changeuser_text.'
|
||||
<br>
|
||||
<br>
|
||||
'.$changeuser_credential_text_1 .'
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Call to action Button -->
|
||||
<tr>
|
||||
<td style="padding: 0px 40px 0px 40px; text-align: center;">
|
||||
<!-- CTA Button -->
|
||||
<table cellspacing="0" cellpadding="0" style="margin: auto;">
|
||||
<tr>
|
||||
<td align="center" style="background-color: '.color_accent.'; padding: 10px 20px; border-radius: 5px;">
|
||||
<a href="https://' . $portalURL . '/reset.php?resetkey='.$resetkey.'" target="_blank" style="color: #ffffff; text-decoration: none; font-weight: bold;">Reset Password</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="body" style="padding: 40px; text-align: left; font-size: 16px; line-height: 1.6;">
|
||||
' . $changeuser_closure . '
|
||||
<br>
|
||||
<br>
|
||||
Kind regards,
|
||||
<br>
|
||||
<br>
|
||||
Service team
|
||||
<br>
|
||||
<br>
|
||||
</td>
|
||||
</tr>
|
||||
<!-- Footer -->
|
||||
<tr>
|
||||
<td class="footer" style="background: url(\'https://'.$portalURL.emaillogo.'\');background-position: center center;background-repeat:no-repeat;background-size:contain;background-color: '.color.'; padding: 40px;">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
';
|
||||
55
custom/morvalwatches/settings/morvalwatches_config.php
Normal file
55
custom/morvalwatches/settings/morvalwatches_config.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
require 'settingsprofiles.php';
|
||||
|
||||
// This will change the title on the website
|
||||
define('site_name','');
|
||||
define('site_name_footer','SoVeLiTi Cloud');
|
||||
// This will change the title on browser TAB
|
||||
define('site_title','SoVeLiTi');
|
||||
//Scriptversion
|
||||
define('script_version','v1');
|
||||
//Enable VeLiTi-issue mgt
|
||||
define('veliti_cim',true);
|
||||
//Enable VeLiTi-analytics
|
||||
define('veliti_analytics',false);
|
||||
//Rewrite rule
|
||||
define('rewrite_url',true);
|
||||
define('news','');
|
||||
//maintenance_mode
|
||||
define('maintenance_mode_communication',false);
|
||||
define('maintenance_mode_notification','Notice: Portal not accessible due to maintenance on May 15th between 12.00 - 13.00 CET.');
|
||||
define('maintenance_mode',false);
|
||||
define('maintenance_mode_text','System in maintenance');
|
||||
define('debug',true);
|
||||
define('debug_id','1');
|
||||
|
||||
/*Security*/
|
||||
// Page security
|
||||
define('page_security_key','secure_admin_342642');
|
||||
define('cronjob_number','25');
|
||||
define('header_security',false);
|
||||
|
||||
/* Email */
|
||||
// The from email that will appear on the customer's order details email
|
||||
define('mail_from','SoVeLiTi');
|
||||
// Your email
|
||||
define('email','CustomerPortal@veliti.nl');
|
||||
//Additional phpmailer-settings
|
||||
define('email_host_name','veliti.nl');
|
||||
define('email_reply_to','info@gewoonlekkerspaans.nl');
|
||||
define('email_outgoing_pw','306yc%X5f');
|
||||
define('email_outgoing_port','587');
|
||||
define('email_outgoing_security','ssl');
|
||||
|
||||
/*Appearance*/
|
||||
//Icon
|
||||
define('icon_image','/custom/soveliti/style/VeLiTi-Logo2.png');
|
||||
define('color','#527ee5');
|
||||
define('color_accent','#527ee5');
|
||||
define('emaillogo','/custom/soveliti/style/SoVeLiTi.png');
|
||||
|
||||
/*Default Users*/
|
||||
define('software_update_user','EMP-updater');
|
||||
define('software_update_pw','EMP-updater');
|
||||
define('interface_user','interface@test.nl');
|
||||
define('interface_pw','test1234');
|
||||
112
custom/morvalwatches/settings/morvalwatches_settings.php
Normal file
112
custom/morvalwatches/settings/morvalwatches_settings.php
Normal file
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
//------------------------------------------
|
||||
//EXCEPTION LIST
|
||||
//------------------------------------------
|
||||
$serialnumber_exceptions = array("22050695","22110095");
|
||||
|
||||
//------------------------------------------
|
||||
// Security
|
||||
//------------------------------------------
|
||||
$security_key = 'secure_34563$52';
|
||||
|
||||
//------------------------------------------
|
||||
// Base color
|
||||
//------------------------------------------
|
||||
$color = '#005655';//'#0b1054';
|
||||
$color_accent = '#2FAC66'; //'#ececec';
|
||||
|
||||
//------------------------------------------
|
||||
// Database settings
|
||||
//------------------------------------------
|
||||
|
||||
require '/var/www/vhosts/veliti.nl/settings/morvalwatches_cloud_settings.php';
|
||||
|
||||
//------------------------------------------
|
||||
// Menusetup & settings
|
||||
//------------------------------------------
|
||||
require 'settingsmenu.php';
|
||||
|
||||
//------------------------------------------
|
||||
// API BaseUrl
|
||||
//------------------------------------------
|
||||
$baseurl = 'https://'.$_SERVER['SERVER_NAME'].'/api.php'; //URL of API
|
||||
$portalURL = $_SERVER['SERVER_NAME'];
|
||||
|
||||
//------------------------------------------
|
||||
// Equipmentdetails
|
||||
//------------------------------------------
|
||||
$servicedate = date("Y-m-d", strtotime("-365 days"));
|
||||
$warrantydate = date("Y-m-d", strtotime("-365 days"));
|
||||
$warranty_extended = date("Y-m-d", strtotime("+365 days"));
|
||||
$date = date('Y-m-d H:i:s');
|
||||
|
||||
$curYear = date("Y", time());
|
||||
$curMonth = date("m", time());
|
||||
$curQuarter = (int)ceil($curMonth / 3);
|
||||
$curdateObj = DateTime::createFromFormat('!m', $curMonth);
|
||||
$curMonth_name = $curdateObj->format('F');
|
||||
|
||||
//------------------------------------------
|
||||
//History Type
|
||||
//------------------------------------------
|
||||
$type1 = 'General';
|
||||
$type2 = 'Customer';
|
||||
$type3 = 'Service';
|
||||
$type4 = 'Testing';
|
||||
$type5 = 'Data';
|
||||
$type6 = 'Other';
|
||||
$type7 = 'Internal';
|
||||
$type8 = 'Ignore';
|
||||
$type9 = 'Warranty';
|
||||
$type10 = 'Contract';
|
||||
$type11 = 'Warranty-Expired';
|
||||
$type12 = 'Contract-Expired';
|
||||
$type13 = "Order";
|
||||
$type14 = "ServiceReport";
|
||||
$type15 = "SRIncluded";
|
||||
$type16 = "Notes";
|
||||
$type17 = "Visual";
|
||||
|
||||
$HistoryType_1 = 'Bootloader';
|
||||
$HistoryType_2 = 'Firmware';
|
||||
$HistoryType_3 = 'SerialNumber';
|
||||
$HistoryType_4 = 'Visual_Test';
|
||||
$HistoryType_5 = 'Maintenance_Test';
|
||||
$HistoryType_6 = 'Assembly_Test';
|
||||
$HistoryType_7 = 'ProductNumber';
|
||||
$HistoryType_8 = 'Visual';
|
||||
$HistoryType_9 = 'ServiceReport';
|
||||
//------------------------------------------
|
||||
//Permissions CRUD
|
||||
//------------------------------------------
|
||||
$permission_4 = 'CRUD'; //Admin+
|
||||
$permission_3 = 'CRUD'; //Admin
|
||||
$permission_2 = 'CRU'; //SuperUser
|
||||
$permission_1 = 'CRU'; //CreateUpdate
|
||||
$permission_0 = 'R'; //Readonly
|
||||
|
||||
$permissionlabel1 = 'Permission';
|
||||
$permission1 = 'Superuser'; #1
|
||||
$permission2 = 'Create & Update'; #2
|
||||
$permission3 = 'read-only'; // #3
|
||||
$permission4 = 'Admin'; //#4
|
||||
$permission5 = 'Admin+'; // #5
|
||||
|
||||
$settingslabel1 = 'profile';
|
||||
$setting1 = 'firmware'; //Fix
|
||||
$setting2 = 'service';
|
||||
$setting3 = 'build'; //Fix
|
||||
$setting4 = 'distribution';
|
||||
$setting5 = '';
|
||||
$setting6 = '';
|
||||
$setting7 = ''; //Fix
|
||||
$setting8 = 'interface';
|
||||
|
||||
//------------------------------------------
|
||||
//Partners
|
||||
//------------------------------------------
|
||||
$partnertype1 = 'SalesID';
|
||||
$partnertype2 = 'SoldTo';
|
||||
$partnertype3 = 'ShipTo';
|
||||
$partnertype4 = 'Location';
|
||||
$partnertype5 = 'Section';
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user