403Webshell
Server IP : 72.60.21.38  /  Your IP : 216.73.217.154
Web Server : LiteSpeed
System : Linux uk-fast-web1372.main-hosting.eu 4.18.0-553.121.1.lve.el8.x86_64 #1 SMP Thu Apr 30 16:40:41 UTC 2026 x86_64
User : u390967363 ( 390967363)
PHP Version : 8.2.30
Disable Function : system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/u390967363/domains/aibenproperties.com/public_html/app/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/u390967363/domains/aibenproperties.com/public_html/app/payables.php
<?php
if (session_status() === PHP_SESSION_NONE) { session_start(); }
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/functions.php';

$role = $_SESSION['user_role'] ?? 'guest';
$roleNorm = strtolower(str_replace([' ', '-'], '_', (string)$role));
$canView = (function_exists('isFinanceTier') && isFinanceTier($role)) || (function_exists('isAdminTier') && isAdminTier($role)) || in_array($roleNorm, ['finance','finance_officer','finance_manager','admin','super_admin','super_admins'], true);
if (!$canView) {
    header('Location: dashboard.php');
    exit;
}

$companyId = function_exists('getCurrentCompanyId') ? getCurrentCompanyId() : ($_SESSION['company_id'] ?? null);
$companyId = $companyId ? (int)$companyId : null;
$currencySymbol = '₦';

$action = isset($_GET['action']) ? trim((string)$_GET['action']) : '';
$q = isset($_GET['q']) ? trim((string)$_GET['q']) : '';
$type = isset($_GET['type']) ? strtolower(trim((string)$_GET['type'])) : '';
$approval = isset($_GET['approval']) ? strtolower(trim((string)$_GET['approval'])) : '';
$payment = isset($_GET['payment']) ? strtolower(trim((string)$_GET['payment'])) : '';
$page = isset($_GET['page']) ? max(1, (int)$_GET['page']) : 1;
$perPage = isset($_GET['per_page']) ? (int)$_GET['per_page'] : 15;
$perPage = $perPage > 0 ? min(50, $perPage) : 15;

function px_money($amount, $currencySymbol = '₦') { return $currencySymbol . number_format((float)$amount, 2); }
function px_safe_date($d) { try { return $d ? date('M j, Y', strtotime((string)$d)) : '—'; } catch (Throwable $e) { return '—'; } }
function px_norm($s) { return strtolower(trim((string)$s)); }
function px_to_date_key($d) { try { return $d ? date('Y-m-d', strtotime((string)$d)) : ''; } catch (Throwable $e) { return ''; } }
function px_badge($text, $cls = 'bg-light text-secondary border') {
    $t = trim((string)$text);
    if ($t === '') $t = '—';
    return '<span class="badge ' . $cls . '" style="font-weight:800; font-size:.72rem">' . htmlspecialchars($t) . '</span>';
}
function px_priority_label($dueDateKey, $hasBalance) {
    if (!$hasBalance) return 'Normal';
    if ($dueDateKey === '') return 'Normal';
    $today = date('Y-m-d');
    if ($dueDateKey < $today) return 'Overdue';
    $soon = date('Y-m-d', strtotime('+7 days'));
    if ($dueDateKey <= $soon) return 'Due Soon';
    return 'Normal';
}
function px_workflow_status($approvalKey, $paymentKey, $amountDue, $amountPaid) {
    $approvalKey = px_norm($approvalKey);
    $paymentKey = px_norm($paymentKey);
    $amountDue = (float)$amountDue;
    $amountPaid = (float)$amountPaid;
    $bal = max(0.0, $amountDue - $amountPaid);
    if (in_array($approvalKey, ['rejected','declined','denied','cancelled','canceled'], true)) return 'Rejected';
    if ($bal <= 0.00001 && $amountDue > 0) return 'Paid';
    if ($amountPaid > 0 && $bal > 0.00001) return 'Partially Paid';
    if (in_array($approvalKey, ['pending','pending_approval','awaiting','processing','new','draft'], true)) return 'Pending Approval';
    if (in_array($approvalKey, ['approved','confirmed','authorized','accepted','completed'], true) && $paymentKey !== 'paid') return 'Awaiting Settlement';
    return 'Draft';
}

$kpi = [
    'outstanding' => ['count' => 0, 'amount' => 0.0],
    'pending_approval' => ['count' => 0, 'amount' => 0.0],
    'awaiting_settlement' => ['count' => 0, 'amount' => 0.0],
    'overdue' => ['count' => 0, 'amount' => 0.0],
];

$rows = [];

try {
    $hasUsers = false;
    $hasVendors = false;
    $hasExpenses = false;
    $hasManual = false;
    $hasPayroll = false;
    $hasStaff = false;
    $hasCommissions = false;
    $hasMaintenance = false;

    try { $hasUsers = $pdo->query("SHOW TABLES LIKE 'users'")->rowCount() > 0; } catch (Throwable $e) {}
    try { $hasVendors = $pdo->query("SHOW TABLES LIKE 'vendors'")->rowCount() > 0; } catch (Throwable $e) {}
    try { $hasExpenses = $pdo->query("SHOW TABLES LIKE 'expenses'")->rowCount() > 0; } catch (Throwable $e) {}
    try { $hasManual = $pdo->query("SHOW TABLES LIKE 'expenses_manual'")->rowCount() > 0; } catch (Throwable $e) {}
    try { $hasPayroll = $pdo->query("SHOW TABLES LIKE 'hr_payroll'")->rowCount() > 0; } catch (Throwable $e) {}
    try { $hasStaff = $pdo->query("SHOW TABLES LIKE 'hr_staff'")->rowCount() > 0; } catch (Throwable $e) {}
    try { $hasCommissions = $pdo->query("SHOW TABLES LIKE 'commissions'")->rowCount() > 0; } catch (Throwable $e) {}
    try { $hasMaintenance = $pdo->query("SHOW TABLES LIKE 'maintenance_requests'")->rowCount() > 0; } catch (Throwable $e) {}

    $maxFetch = 500;
    $today = date('Y-m-d');

    if ($hasManual && function_exists('tableHasColumn') && tableHasColumn('expenses_manual', 'status') && tableHasColumn('expenses_manual', 'amount')) {
        $statusCol = 'status';
        $dateCol = tableHasColumn('expenses_manual', 'expense_date') ? 'expense_date' : (tableHasColumn('expenses_manual', 'created_at') ? 'created_at' : 'id');
        $updatedCol = tableHasColumn('expenses_manual', 'updated_at') ? 'updated_at' : (tableHasColumn('expenses_manual', 'created_at') ? 'created_at' : null);
        $hasPostedAt = tableHasColumn('expenses_manual', 'posted_at');
        $hasDept = tableHasColumn('expenses_manual', 'department');
        $hasRecId = tableHasColumn('expenses_manual', 'recorded_by_user_id');
        $hasVendorId = tableHasColumn('expenses_manual', 'vendor_id');

        $join = "";
        $selVendor = "NULL AS vendor_name";
        if ($hasVendors && $hasVendorId && tableHasColumn('vendors', 'id') && tableHasColumn('vendors', 'name')) {
            $join .= " LEFT JOIN vendors v ON v.id = em.vendor_id";
            $selVendor = "v.name AS vendor_name";
        }
        $selUser = "NULL AS requested_by";
        if ($hasUsers && $hasRecId && tableHasColumn('users', 'id')) {
            $userCol = tableHasColumn('users', 'name') ? 'name' : (tableHasColumn('users', 'full_name') ? 'full_name' : 'email');
            if ($userCol && tableHasColumn('users', $userCol)) {
                $join .= " LEFT JOIN users u ON u.id = em.recorded_by_user_id";
                $selUser = "u.$userCol AS requested_by";
            }
        }

        $where = [];
        $params = [];
        if (tableHasColumn('expenses_manual', 'is_reversed')) { $where[] = "COALESCE(em.is_reversed,0)=0"; }
        if ($companyId && tableHasColumn('expenses_manual', 'company_id')) { $where[] = "(em.company_id = ? OR em.company_id IS NULL)"; $params[] = $companyId; }
        $where[] = "LOWER(TRIM(em.$statusCol)) IN ('pending','approved','rejected')";
        $wSql = !empty($where) ? (" WHERE " . implode(" AND ", $where)) : "";

        $selTitle = tableHasColumn('expenses_manual', 'title') ? "NULLIF(TRIM(em.title),'')" : "NULL";
        $selCat = tableHasColumn('expenses_manual', 'category') ? "NULLIF(TRIM(em.category),'')" : "NULL";
        $selDept = $hasDept ? "NULLIF(TRIM(em.department),'')" : "NULL";
        $selUpdated = $updatedCol ? "em.$updatedCol" : "NULL";
        $selPosted = $hasPostedAt ? "em.posted_at" : "NULL";
        $sql = "SELECT
                    'expense' AS payable_type,
                    em.id AS ref_id,
                    COALESCE($selVendor, $selTitle, $selCat, 'Expense') AS party_name,
                    $selVendor,
                    COALESCE($selCat, 'Expense') AS payable_label,
                    COALESCE(em.amount,0) AS amount_due,
                    CASE
                        WHEN LOWER(TRIM(em.$statusCol))='approved' AND ($selPosted IS NOT NULL AND TRIM(COALESCE($selPosted,''))<>'') THEN COALESCE(em.amount,0)
                        ELSE 0
                    END AS amount_paid,
                    em.$dateCol AS due_date,
                    em.$statusCol AS approval_status,
                    CASE
                        WHEN LOWER(TRIM(em.$statusCol))='pending' THEN 'unpaid'
                        WHEN LOWER(TRIM(em.$statusCol))='approved' AND ($selPosted IS NULL OR TRIM(COALESCE($selPosted,''))='') THEN 'pending'
                        WHEN LOWER(TRIM(em.$statusCol))='rejected' THEN 'unpaid'
                        ELSE 'paid'
                    END AS payment_status,
                    $selDept AS department,
                    $selUser,
                    $selUpdated AS updated_at,
                    'expenses_manual' AS source,
                    em.id AS source_id
                FROM expenses_manual em
                $join
                $wSql
                ORDER BY $selUpdated DESC, em.id DESC
                LIMIT $maxFetch";
        $st = $pdo->prepare($sql);
        $st->execute($params);
        foreach (($st->fetchAll(PDO::FETCH_ASSOC) ?: []) as $r) {
            $rows[] = $r;
        }
    }

    if ($hasExpenses && function_exists('tableHasColumn') && tableHasColumn('expenses', 'status')) {
        $amountCol = tableHasColumn('expenses', 'amount') ? 'amount' : null;
        if ($amountCol) {
            $dateCol = tableHasColumn('expenses', 'due_date') ? 'due_date' : null;
            $updatedCol = tableHasColumn('expenses', 'updated_at') ? 'updated_at' : (tableHasColumn('expenses', 'created_at') ? 'created_at' : null);
            $hasVendorId = tableHasColumn('expenses', 'vendor_id');
            $hasDept = tableHasColumn('expenses', 'department');
            $hasReqBy = tableHasColumn('expenses', 'requested_by') || tableHasColumn('expenses', 'created_by') || tableHasColumn('expenses', 'recorded_by_user_id');

            $join = "";
            $selVendor = "NULL AS vendor_name";
            if ($hasVendors && $hasVendorId && tableHasColumn('vendors', 'id') && tableHasColumn('vendors', 'name')) {
                $join .= " LEFT JOIN vendors v ON v.id = e.vendor_id";
                $selVendor = "v.name AS vendor_name";
            }
            $selUser = "NULL AS requested_by";
            if ($hasUsers && $hasReqBy && tableHasColumn('users', 'id')) {
                $userCol = tableHasColumn('users', 'name') ? 'name' : (tableHasColumn('users', 'full_name') ? 'full_name' : 'email');
                $byCol = tableHasColumn('expenses', 'requested_by') ? 'requested_by' : (tableHasColumn('expenses', 'created_by') ? 'created_by' : (tableHasColumn('expenses', 'recorded_by_user_id') ? 'recorded_by_user_id' : null));
                if ($byCol) {
                    $join .= " LEFT JOIN users u2 ON u2.id = e.$byCol";
                    $selUser = "u2.$userCol AS requested_by";
                }
            }

            $where = [];
            $params = [];
            if ($companyId && tableHasColumn('expenses', 'company_id')) { $where[] = "(e.company_id = ? OR e.company_id IS NULL)"; $params[] = $companyId; }
            $where[] = "LOWER(TRIM(e.status)) IN ('pending','approved','paid','completed','rejected')";
            $wSql = " WHERE " . implode(" AND ", $where);

            $selDept = $hasDept ? "NULLIF(TRIM(e.department),'')" : "NULL";
            $selUpdated = $updatedCol ? "e.$updatedCol" : "NULL";
            $catCol = tableHasColumn('expenses', 'category') ? 'category' : null;
            $descCol = tableHasColumn('expenses', 'description') ? 'description' : null;
            $labelExpr = $catCol ? "NULLIF(TRIM(e.$catCol),'')" : ($descCol ? "NULLIF(TRIM(e.$descCol),'')" : "'Expense'");
            $dueExpr = $dateCol ? "e.$dateCol" : "NULL";
            $sql = "SELECT
                        'expense' AS payable_type,
                        e.id AS ref_id,
                        COALESCE($selVendor, $labelExpr, 'Expense') AS party_name,
                        $selVendor,
                        COALESCE($labelExpr,'Expense') AS payable_label,
                        COALESCE(e.$amountCol,0) AS amount_due,
                        CASE WHEN LOWER(TRIM(e.status)) IN ('paid','completed') THEN COALESCE(e.$amountCol,0) ELSE 0 END AS amount_paid,
                        $dueExpr AS due_date,
                        e.status AS approval_status,
                        CASE
                            WHEN LOWER(TRIM(e.status)) IN ('paid','completed') THEN 'paid'
                            WHEN LOWER(TRIM(e.status))='approved' THEN 'pending'
                            ELSE 'unpaid'
                        END AS payment_status,
                        $selDept AS department,
                        $selUser,
                        $selUpdated AS updated_at,
                        'expenses' AS source,
                        e.id AS source_id
                    FROM expenses e
                    $join
                    $wSql
                    ORDER BY $selUpdated DESC, e.id DESC
                    LIMIT $maxFetch";
            $st = $pdo->prepare($sql);
            $st->execute($params);
            foreach (($st->fetchAll(PDO::FETCH_ASSOC) ?: []) as $r) {
                $rows[] = $r;
            }
        }
    }

    if ($hasPayroll && function_exists('tableHasColumn') && tableHasColumn('hr_payroll', 'status')) {
        $amountCol = tableHasColumn('hr_payroll', 'net_pay') ? 'net_pay' : (tableHasColumn('hr_payroll', 'base_salary') ? 'base_salary' : null);
        if ($amountCol) {
            $updatedCol = tableHasColumn('hr_payroll', 'updated_at') ? 'updated_at' : (tableHasColumn('hr_payroll', 'created_at') ? 'created_at' : null);
            $join = "";
            $selStaff = "CONCAT('Staff #', p.staff_id)";
            $deptSel = "NULL";
            $reqSel = "NULL AS requested_by";
            if ($hasStaff && tableHasColumn('hr_staff', 'id')) {
                $staffNameCol = tableHasColumn('hr_staff', 'name') ? 'name' : (tableHasColumn('hr_staff', 'full_name') ? 'full_name' : null);
                if ($staffNameCol) {
                    $join .= " LEFT JOIN hr_staff s ON s.id = p.staff_id";
                    $selStaff = "COALESCE(NULLIF(TRIM(s.$staffNameCol),''), CONCAT('Staff #', p.staff_id))";
                }
                $deptCol = tableHasColumn('hr_staff', 'department') ? 'department' : null;
                if ($deptCol) { $deptSel = "NULLIF(TRIM(s.$deptCol),'')"; }
            }
            if ($hasUsers && function_exists('tableHasColumn') && tableHasColumn('hr_payroll', 'prepared_by') && tableHasColumn('users', 'id')) {
                $userCol = tableHasColumn('users', 'name') ? 'name' : (tableHasColumn('users', 'full_name') ? 'full_name' : 'email');
                $join .= " LEFT JOIN users up ON up.id = p.prepared_by";
                $reqSel = "up.$userCol AS requested_by";
            }

            $where = [];
            $params = [];
            if ($companyId && tableHasColumn('hr_payroll', 'company_id')) { $where[] = "(p.company_id = ? OR p.company_id IS NULL)"; $params[] = $companyId; }
            $where[] = "LOWER(TRIM(p.status)) IN ('pending_approval','approved','paid')";
            $wSql = " WHERE " . implode(" AND ", $where);
            $selUpdated = $updatedCol ? "p.$updatedCol" : "NULL";

            $hasPeriod = tableHasColumn('hr_payroll', 'period_month') && tableHasColumn('hr_payroll', 'period_year');
            $dueExpr = $hasPeriod ? "STR_TO_DATE(CONCAT(p.period_year,'-',LPAD(p.period_month,2,'0'),'-01'), '%Y-%m-%d')" : (tableHasColumn('hr_payroll', 'created_at') ? "p.created_at" : "NULL");
            $sql = "SELECT
                        'salary' AS payable_type,
                        p.id AS ref_id,
                        $selStaff AS party_name,
                        NULL AS vendor_name,
                        'Salary' AS payable_label,
                        COALESCE(p.$amountCol,0) AS amount_due,
                        CASE WHEN LOWER(TRIM(p.status))='paid' THEN COALESCE(p.$amountCol,0) ELSE 0 END AS amount_paid,
                        $dueExpr AS due_date,
                        p.status AS approval_status,
                        CASE
                            WHEN LOWER(TRIM(p.status))='paid' THEN 'paid'
                            WHEN LOWER(TRIM(p.status))='approved' THEN 'pending'
                            ELSE 'unpaid'
                        END AS payment_status,
                        $deptSel AS department,
                        $reqSel,
                        $selUpdated AS updated_at,
                        'hr_payroll' AS source,
                        p.id AS source_id
                    FROM hr_payroll p
                    $join
                    $wSql
                    ORDER BY $selUpdated DESC, p.id DESC
                    LIMIT $maxFetch";
            $st = $pdo->prepare($sql);
            $st->execute($params);
            foreach (($st->fetchAll(PDO::FETCH_ASSOC) ?: []) as $r) {
                $rows[] = $r;
            }
        }
    }

    if ($hasCommissions && function_exists('tableHasColumn')) {
        $statusCol = tableHasColumn('commissions', 'status') ? 'status' : (tableHasColumn('commissions', 'commission_status') ? 'commission_status' : (tableHasColumn('commissions', 'state') ? 'state' : null));
        $amountCol = tableHasColumn('commissions', 'amount') ? 'amount' : (tableHasColumn('commissions', 'commission_amount') ? 'commission_amount' : null);
        $dateCol = tableHasColumn('commissions', 'due_date') ? 'due_date' : null;
        $updatedCol = tableHasColumn('commissions', 'updated_at') ? 'updated_at' : (tableHasColumn('commissions', 'created_at') ? 'created_at' : null);

        if ($statusCol && $amountCol) {
            $join = "";
            $selAgent = "'Agent'";
            $hasAgentId = tableHasColumn('commissions', 'agent_id');
            if ($hasUsers && $hasAgentId && tableHasColumn('users', 'id')) {
                $userCol = tableHasColumn('users', 'name') ? 'name' : (tableHasColumn('users', 'full_name') ? 'full_name' : 'email');
                $join .= " LEFT JOIN users ua ON ua.id = c.agent_id";
                $selAgent = "COALESCE(NULLIF(TRIM(ua.$userCol),''), 'Agent')";
            }

            $where = [];
            $params = [];
            if ($companyId && tableHasColumn('commissions', 'company_id')) { $where[] = "(c.company_id = ? OR c.company_id IS NULL)"; $params[] = $companyId; }
            $where[] = "LOWER(TRIM(COALESCE(c.$statusCol,''))) IN ('pending','approved','processing','awaiting','new','confirmed','authorized','accepted','paid','settled','disbursed','completed','rejected','declined','denied')";
            $wSql = " WHERE " . implode(" AND ", $where);
            $selUpdated = $updatedCol ? "c.$updatedCol" : "NULL";
            $dueExpr = $dateCol ? "c.$dateCol" : "NULL";

            $sql = "SELECT
                        'commission' AS payable_type,
                        c.id AS ref_id,
                        $selAgent AS party_name,
                        NULL AS vendor_name,
                        'Commission' AS payable_label,
                        COALESCE(c.$amountCol,0) AS amount_due,
                        CASE WHEN LOWER(TRIM(COALESCE(c.$statusCol,''))) IN ('paid','settled','disbursed','completed') THEN COALESCE(c.$amountCol,0) ELSE 0 END AS amount_paid,
                        $dueExpr AS due_date,
                        c.$statusCol AS approval_status,
                        CASE
                            WHEN LOWER(TRIM(COALESCE(c.$statusCol,''))) IN ('paid','settled','disbursed','completed') THEN 'paid'
                            WHEN LOWER(TRIM(COALESCE(c.$statusCol,''))) IN ('approved','confirmed','authorized','accepted') THEN 'pending'
                            ELSE 'unpaid'
                        END AS payment_status,
                        NULL AS department,
                        NULL AS requested_by,
                        $selUpdated AS updated_at,
                        'commissions' AS source,
                        c.id AS source_id
                    FROM commissions c
                    $join
                    $wSql
                    ORDER BY $selUpdated DESC, c.id DESC
                    LIMIT $maxFetch";
            $st = $pdo->prepare($sql);
            $st->execute($params);
            foreach (($st->fetchAll(PDO::FETCH_ASSOC) ?: []) as $r) {
                $rows[] = $r;
            }
        }
    }

    if ($hasMaintenance && function_exists('tableHasColumn') && tableHasColumn('maintenance_requests', 'status') && tableHasColumn('maintenance_requests', 'cost')) {
        $dateCol = function_exists('expenseMaintenanceDateColumn') ? expenseMaintenanceDateColumn() : (tableHasColumn('maintenance_requests', 'updated_at') ? 'updated_at' : (tableHasColumn('maintenance_requests', 'created_at') ? 'created_at' : 'id'));
        $updatedCol = tableHasColumn('maintenance_requests', 'updated_at') ? 'updated_at' : (tableHasColumn('maintenance_requests', 'created_at') ? 'created_at' : null);
        $hasAssigned = tableHasColumn('maintenance_requests', 'assigned_to');
        $hasRecId = tableHasColumn('maintenance_requests', 'recorded_by_user_id');
        $join = "";
        $selAssigned = "NULL AS assigned_name";
        $selRecorder = "NULL AS requested_by";
        if ($hasUsers && $hasAssigned && tableHasColumn('users', 'id')) {
            $userCol = tableHasColumn('users', 'name') ? 'name' : (tableHasColumn('users', 'full_name') ? 'full_name' : 'email');
            $join .= " LEFT JOIN users umt ON umt.id = m.assigned_to";
            $selAssigned = "umt.$userCol AS assigned_name";
        }
        if ($hasUsers && $hasRecId && tableHasColumn('users', 'id')) {
            $userCol = tableHasColumn('users', 'name') ? 'name' : (tableHasColumn('users', 'full_name') ? 'full_name' : 'email');
            $join .= " LEFT JOIN users umr ON umr.id = m.recorded_by_user_id";
            $selRecorder = "umr.$userCol AS requested_by";
        }

        $where = [];
        $params = [];
        $where[] = "LOWER(TRIM(m.status)) = 'completed'";
        $where[] = "m.cost IS NOT NULL AND m.cost > 0";
        if ($companyId && tableHasColumn('maintenance_requests', 'company_id')) { $where[] = "(m.company_id = ? OR m.company_id IS NULL)"; $params[] = $companyId; }
        $wSql = " WHERE " . implode(" AND ", $where);

        $titleExpr = tableHasColumn('maintenance_requests', 'title') ? "NULLIF(TRIM(m.title),'')" : "NULL";
        $issueExpr = tableHasColumn('maintenance_requests', 'issue_type') ? "NULLIF(TRIM(m.issue_type),'')" : "NULL";
        $selUpdated = $updatedCol ? "m.$updatedCol" : "NULL";
        $sql = "SELECT
                    'maintenance' AS payable_type,
                    m.id AS ref_id,
                    COALESCE($selAssigned, 'Maintenance') AS party_name,
                    NULL AS vendor_name,
                    COALESCE($titleExpr, $issueExpr, 'Maintenance') AS payable_label,
                    COALESCE(m.cost,0) AS amount_due,
                    0 AS amount_paid,
                    m.$dateCol AS due_date,
                    m.status AS approval_status,
                    'pending' AS payment_status,
                    'Maintenance' AS department,
                    $selRecorder,
                    $selUpdated AS updated_at,
                    'maintenance_requests' AS source,
                    m.id AS source_id
                FROM maintenance_requests m
                $join
                $wSql
                ORDER BY $selUpdated DESC, m.id DESC
                LIMIT $maxFetch";
        $st = $pdo->prepare($sql);
        $st->execute($params);
        foreach (($st->fetchAll(PDO::FETCH_ASSOC) ?: []) as $r) {
            $rows[] = $r;
        }
    }

    $allRows = [];
    $mkHref = function(array $r) {
        $src = (string)($r['source'] ?? '');
        $id = (int)($r['source_id'] ?? ($r['ref_id'] ?? 0));
        if ($src === 'expenses_manual' && file_exists(__DIR__ . '/finance-expense-view.php') && $id > 0) return 'finance-expense-view.php?id=' . $id . '&source=manual';
        if ($src === 'expenses' && file_exists(__DIR__ . '/finance-expenses.php')) return 'finance-expenses.php?tab=property&highlight_id=' . $id;
        if ($src === 'hr_payroll' && file_exists(__DIR__ . '/hr-payroll.php')) return 'hr-payroll.php?highlight_id=' . $id;
        if ($src === 'commissions' && file_exists(__DIR__ . '/commissions.php')) return 'commissions.php?status=all&view_id=' . $id;
        if ($src === 'maintenance_requests' && file_exists(__DIR__ . '/maintenance.php')) return 'maintenance.php?view_id=' . $id;
        return '';
    };
    foreach ($rows as $r) {
        $amountDue = (float)($r['amount_due'] ?? 0);
        $amountPaid = (float)($r['amount_paid'] ?? 0);
        $balance = max(0.0, $amountDue - $amountPaid);
        $dueKey = px_to_date_key($r['due_date'] ?? '');
        $priority = px_priority_label($dueKey, $balance > 0.00001);
        $workflow = px_workflow_status($r['approval_status'] ?? '', $r['payment_status'] ?? '', $amountDue, $amountPaid);
        $r['balance'] = $balance;
        $r['priority'] = $priority;
        $r['workflow_status'] = $workflow;
        $r['source_type'] = (string)($r['source'] ?? '');
        $r['source_id'] = (int)($r['source_id'] ?? ($r['ref_id'] ?? 0));
        $r['view_href'] = $mkHref($r);
        $allRows[] = $r;
    }

    $filtered = [];
    foreach ($allRows as $r) {
        $party = (string)($r['party_name'] ?? '');
        $label = (string)($r['payable_label'] ?? '');
        $appr = px_norm($r['approval_status'] ?? '');
        $paySt = px_norm($r['payment_status'] ?? '');
        $tp = px_norm($r['payable_type'] ?? '');

        if ($type !== '' && $tp !== $type) continue;
        if ($approval !== '' && $appr !== $approval) continue;
        if ($payment !== '' && $paySt !== $payment) continue;
        if ($q !== '') {
            $needle = px_norm($q);
            $hay = px_norm($party . ' ' . $label . ' ' . ($r['vendor_name'] ?? '') . ' ' . ($r['department'] ?? '') . ' ' . ($r['requested_by'] ?? ''));
            if ($needle !== '' && strpos($hay, $needle) === false) continue;
        }

        $filtered[] = $r;
    }

    usort($filtered, function($a, $b){
        $ad = (string)($a['updated_at'] ?? '');
        $bd = (string)($b['updated_at'] ?? '');
        $at = $ad !== '' ? strtotime($ad) : 0;
        $bt = $bd !== '' ? strtotime($bd) : 0;
        if ($at === $bt) return ((int)($b['ref_id'] ?? 0) <=> (int)($a['ref_id'] ?? 0));
        return $bt <=> $at;
    });

    $kpi = [
        'outstanding' => ['count' => 0, 'amount' => 0.0],
        'pending_approval' => ['count' => 0, 'amount' => 0.0],
        'awaiting_settlement' => ['count' => 0, 'amount' => 0.0],
        'overdue' => ['count' => 0, 'amount' => 0.0],
    ];
    foreach ($allRows as $r) {
        $bal = (float)($r['balance'] ?? 0);
        if ($bal <= 0.00001) continue;
        $kpi['outstanding']['count']++;
        $kpi['outstanding']['amount'] += $bal;

        $appr = px_norm($r['approval_status'] ?? '');
        $paySt = px_norm($r['payment_status'] ?? '');
        if (in_array($appr, ['pending','pending_approval','awaiting','processing','new'], true)) {
            $kpi['pending_approval']['count']++;
            $kpi['pending_approval']['amount'] += $bal;
        }
        if (in_array($appr, ['approved','confirmed','authorized','accepted'], true) && $paySt !== 'paid') {
            $kpi['awaiting_settlement']['count']++;
            $kpi['awaiting_settlement']['amount'] += $bal;
        }
        $d = px_to_date_key($r['due_date'] ?? '');
        if ($d !== '' && $d < $today && $paySt !== 'paid') {
            $kpi['overdue']['count']++;
            $kpi['overdue']['amount'] += $bal;
        }
    }

    $intel = [
        'upcoming' => ['count' => 0, 'amount' => 0.0],
        'payroll_pending' => ['count' => 0, 'amount' => 0.0],
        'week_settlements' => ['count' => 0, 'amount' => 0.0],
        'most_owed_vendor' => ['name' => null, 'amount' => 0.0],
    ];
    $weekEnd = date('Y-m-d', strtotime('+7 days'));
    $vendorBuckets = [];
    foreach ($allRows as $r) {
        $bal = (float)($r['balance'] ?? 0);
        if ($bal <= 0.00001) continue;
        $dueKey = px_to_date_key($r['due_date'] ?? '');
        if ($dueKey !== '' && $dueKey <= $weekEnd) {
            $intel['upcoming']['count']++;
            $intel['upcoming']['amount'] += $bal;
            $intel['week_settlements']['count']++;
            $intel['week_settlements']['amount'] += $bal;
        }
        if (px_norm($r['source'] ?? '') === 'hr_payroll' && px_norm($r['approval_status'] ?? '') === 'pending_approval') {
            $intel['payroll_pending']['count']++;
            $intel['payroll_pending']['amount'] += $bal;
        }
        $vn = trim((string)($r['vendor_name'] ?? ''));
        if ($vn !== '') {
            if (!isset($vendorBuckets[$vn])) $vendorBuckets[$vn] = 0.0;
            $vendorBuckets[$vn] += $bal;
        }
    }
    if (!empty($vendorBuckets)) {
        arsort($vendorBuckets);
        $topName = array_key_first($vendorBuckets);
        $intel['most_owed_vendor']['name'] = $topName;
        $intel['most_owed_vendor']['amount'] = (float)$vendorBuckets[$topName];
    }

    if ($action === 'export') {
        header('Content-Type: text/csv; charset=utf-8');
        header('Content-Disposition: attachment; filename="payables_' . date('Ymd_His') . '.csv"');
        header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
        $out = fopen('php://output', 'w');
        fputcsv($out, ['Vendor/Staff','Payable Type','Amount Due','Amount Paid','Balance','Due Date','Workflow','Approval Status','Payment Status','Priority','Department','Requested By','Last Updated','Source Type','Source ID']);
        foreach ($filtered as $r) {
            $amountDue = (float)($r['amount_due'] ?? 0);
            $amountPaid = (float)($r['amount_paid'] ?? 0);
            $bal = (float)($r['balance'] ?? max(0, $amountDue - $amountPaid));
            fputcsv($out, [
                (string)($r['party_name'] ?? ''),
                (string)($r['payable_label'] ?? $r['payable_type'] ?? ''),
                number_format($amountDue, 2, '.', ''),
                number_format($amountPaid, 2, '.', ''),
                number_format($bal, 2, '.', ''),
                (string)($r['due_date'] ?? ''),
                (string)($r['workflow_status'] ?? ''),
                (string)($r['approval_status'] ?? ''),
                (string)($r['payment_status'] ?? ''),
                (string)($r['priority'] ?? ''),
                (string)($r['department'] ?? ''),
                (string)($r['requested_by'] ?? ''),
                (string)($r['updated_at'] ?? ''),
                (string)($r['source_type'] ?? $r['source'] ?? ''),
                (string)($r['source_id'] ?? $r['ref_id'] ?? ''),
            ]);
        }
        fclose($out);
        exit;
    }

    $total = count($filtered);
    $totalPages = max(1, (int)ceil($total / $perPage));
    $page = min($page, $totalPages);
    $offset = ($page - 1) * $perPage;
    $paged = array_slice($filtered, $offset, $perPage);
    $rows = $paged;
} catch (Throwable $e) {
    $rows = [];
}

include __DIR__ . '/includes/header.php';
?>

<div class="container-fluid px-4">
    <style>
        .payables-table-wrap{display:block; width:100%; overflow:auto !important; -webkit-overflow-scrolling:touch}
        .payables-table{width:max-content; min-width:100%}
        .payables-table thead th{position:sticky; top:0; z-index:2; background:var(--bs-body-bg, #fff)}
        .payables-table td,.payables-table th{vertical-align:middle; white-space:nowrap}
        .payables-row{cursor:pointer}
        .payables-row:hover{background:rgba(2,6,23,.03)}
        .payables-table-wrap{touch-action:pan-x pan-y; cursor:grab}
        .payables-table-wrap.payables-grabbing{cursor:grabbing}
    </style>

    <div class="d-flex justify-content-between align-items-start flex-wrap gap-2 mt-4 mb-3">
        <div>
            <h1 class="h3 mb-0 text-gray-800">Payables</h1>
            <div class="text-muted small mt-1">Accounts payable workspace for obligations, approvals, and settlements.</div>
        </div>
        <div class="d-flex gap-2 flex-wrap">
            <?php $expQuery = ['action'=>'export','q'=>$q,'type'=>$type,'approval'=>$approval,'payment'=>$payment,'per_page'=>$perPage,'page'=>$page]; ?>
            <a href="payables.php?<?= htmlspecialchars(http_build_query($expQuery)) ?>" class="btn btn-outline-secondary btn-sm"><i class="fa-solid fa-file-export me-2"></i>Export</a>
            <?php if (file_exists(__DIR__ . '/finance-expenses.php')): ?>
                <a href="finance-expenses.php" class="btn btn-outline-secondary btn-sm"><i class="fa-solid fa-receipt me-2"></i>Open Expenses</a>
            <?php endif; ?>
            <?php if (file_exists(__DIR__ . '/hr-payroll.php')): ?>
                <a href="hr-payroll.php" class="btn btn-outline-secondary btn-sm"><i class="fa-solid fa-money-check-dollar me-2"></i>Open Payroll</a>
            <?php endif; ?>
            <?php if (file_exists(__DIR__ . '/commissions.php')): ?>
                <a href="commissions.php" class="btn btn-outline-secondary btn-sm"><i class="fa-solid fa-hand-holding-dollar me-2"></i>Open Commissions</a>
            <?php endif; ?>
        </div>
    </div>

    <div class="row g-3 mb-3">
        <div class="col-12 col-md-6 col-xl-3">
            <div class="card shadow-sm border-0 h-100">
                <div class="card-body">
                    <div class="text-muted small">Outstanding Obligations</div>
                    <div class="h5 fw-bold mb-1"><?= px_money((float)$kpi['outstanding']['amount'], $currencySymbol) ?></div>
                    <div class="text-muted small"><?= number_format((int)$kpi['outstanding']['count']) ?> items</div>
                </div>
            </div>
        </div>
        <div class="col-12 col-md-6 col-xl-3">
            <div class="card shadow-sm border-0 h-100">
                <div class="card-body">
                    <div class="text-muted small">Pending Approval</div>
                    <div class="h5 fw-bold mb-1"><?= px_money((float)$kpi['pending_approval']['amount'], $currencySymbol) ?></div>
                    <div class="text-muted small"><?= number_format((int)$kpi['pending_approval']['count']) ?> items</div>
                </div>
            </div>
        </div>
        <div class="col-12 col-md-6 col-xl-3">
            <div class="card shadow-sm border-0 h-100">
                <div class="card-body">
                    <div class="text-muted small">Awaiting Settlement</div>
                    <div class="h5 fw-bold mb-1"><?= px_money((float)$kpi['awaiting_settlement']['amount'], $currencySymbol) ?></div>
                    <div class="text-muted small"><?= number_format((int)$kpi['awaiting_settlement']['count']) ?> items</div>
                </div>
            </div>
        </div>
        <div class="col-12 col-md-6 col-xl-3">
            <div class="card shadow-sm border-0 h-100">
                <div class="card-body">
                    <div class="text-muted small">Overdue</div>
                    <div class="h5 fw-bold mb-1"><?= px_money((float)$kpi['overdue']['amount'], $currencySymbol) ?></div>
                    <div class="text-muted small"><?= number_format((int)$kpi['overdue']['count']) ?> items</div>
                </div>
            </div>
        </div>
    </div>

    <div class="row g-3 mb-3">
        <div class="col-12 col-md-6 col-xl-3">
            <div class="card shadow-sm border-0 h-100">
                <div class="card-body">
                    <div class="text-muted small">Upcoming Due Payments</div>
                    <div class="h6 fw-bold mb-1"><?= px_money((float)($intel['upcoming']['amount'] ?? 0), $currencySymbol) ?></div>
                    <div class="text-muted small"><?= number_format((int)($intel['upcoming']['count'] ?? 0)) ?> due within 7 days</div>
                </div>
            </div>
        </div>
        <div class="col-12 col-md-6 col-xl-3">
            <div class="card shadow-sm border-0 h-100">
                <div class="card-body">
                    <div class="text-muted small">Payroll Pending</div>
                    <div class="h6 fw-bold mb-1"><?= px_money((float)($intel['payroll_pending']['amount'] ?? 0), $currencySymbol) ?></div>
                    <div class="text-muted small"><?= number_format((int)($intel['payroll_pending']['count'] ?? 0)) ?> items</div>
                </div>
            </div>
        </div>
        <div class="col-12 col-md-6 col-xl-3">
            <div class="card shadow-sm border-0 h-100">
                <div class="card-body">
                    <div class="text-muted small">Most Owed Vendor</div>
                    <div class="h6 fw-bold mb-1"><?= htmlspecialchars((string)($intel['most_owed_vendor']['name'] ?? '—')) ?></div>
                    <div class="text-muted small"><?= px_money((float)($intel['most_owed_vendor']['amount'] ?? 0), $currencySymbol) ?></div>
                </div>
            </div>
        </div>
        <div class="col-12 col-md-6 col-xl-3">
            <div class="card shadow-sm border-0 h-100">
                <div class="card-body">
                    <div class="text-muted small">This Week Settlements</div>
                    <div class="h6 fw-bold mb-1"><?= px_money((float)($intel['week_settlements']['amount'] ?? 0), $currencySymbol) ?></div>
                    <div class="text-muted small"><?= number_format((int)($intel['week_settlements']['count'] ?? 0)) ?> items</div>
                </div>
            </div>
        </div>
    </div>

    <div class="card shadow-sm border-0" id="pxPayablesTable">
        <div class="card-header py-3 d-flex align-items-center justify-content-between flex-wrap gap-2">
            <div>
                <div class="fw-bold">Payables Ledger</div>
                <div class="small text-muted">What is owed, what is pending approval, and what needs settlement</div>
            </div>
            <form class="w-100" method="get">
                <input type="hidden" name="per_page" value="<?= (int)$perPage ?>">
                <div class="row gx-2 gy-2 align-items-center">
                    <div class="col-12 col-lg">
                        <input type="text" name="q" value="<?= htmlspecialchars($q) ?>" class="form-control form-control-sm" placeholder="Search vendor / staff / type">
                    </div>
                    <div class="col-6 col-lg-auto">
                        <select name="type" class="form-select form-select-sm">
                            <option value="" <?= $type === '' ? 'selected' : '' ?>>All Types</option>
                            <option value="expense" <?= $type === 'expense' ? 'selected' : '' ?>>Expense / Bill</option>
                            <option value="salary" <?= $type === 'salary' ? 'selected' : '' ?>>Salary</option>
                            <option value="commission" <?= $type === 'commission' ? 'selected' : '' ?>>Commission</option>
                        </select>
                    </div>
                    <div class="col-6 col-lg-auto">
                        <select name="approval" class="form-select form-select-sm">
                            <option value="" <?= $approval === '' ? 'selected' : '' ?>>All Approvals</option>
                            <option value="pending" <?= $approval === 'pending' ? 'selected' : '' ?>>Pending</option>
                            <option value="pending_approval" <?= $approval === 'pending_approval' ? 'selected' : '' ?>>Pending Approval</option>
                            <option value="approved" <?= $approval === 'approved' ? 'selected' : '' ?>>Approved</option>
                            <option value="rejected" <?= $approval === 'rejected' ? 'selected' : '' ?>>Rejected</option>
                        </select>
                    </div>
                    <div class="col-6 col-lg-auto">
                        <select name="payment" class="form-select form-select-sm">
                            <option value="" <?= $payment === '' ? 'selected' : '' ?>>All Payments</option>
                            <option value="unpaid" <?= $payment === 'unpaid' ? 'selected' : '' ?>>Unpaid</option>
                            <option value="pending" <?= $payment === 'pending' ? 'selected' : '' ?>>Awaiting Settlement</option>
                            <option value="paid" <?= $payment === 'paid' ? 'selected' : '' ?>>Paid</option>
                        </select>
                    </div>
                    <div class="col-6 col-lg-auto d-grid">
                        <button class="btn btn-sm btn-dark" type="submit"><i class="fa-solid fa-magnifying-glass me-2"></i>Filter</button>
                    </div>
                    <div class="col-6 col-lg-auto d-grid">
                        <a class="btn btn-sm btn-outline-secondary" href="payables.php"><i class="fa-solid fa-rotate-left me-2"></i>Reset</a>
                    </div>
                </div>
            </form>
        </div>
        <div class="card-body p-0">
            <div class="d-sm-none px-3 py-2 small text-muted border-bottom">Swipe left/right to see all columns.</div>
            <div class="table-responsive payables-table-wrap" style="<?= empty($rows) ? '' : 'max-height:560px' ?>">
                <table class="table mb-0 payables-table">
                    <thead>
                        <tr>
                            <th>Vendor/Staff</th>
                            <th>Payable Type</th>
                            <th class="text-end">Amount Due</th>
                            <th class="text-end">Amount Paid</th>
                            <th class="text-end">Balance</th>
                            <th>Due Date</th>
                            <th>Workflow</th>
                            <th>Approval Status</th>
                            <th>Payment Status</th>
                            <th>Priority</th>
                            <th>Department</th>
                            <th>Requested By</th>
                            <th>Last Updated</th>
                            <th class="text-end">Actions</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php if (empty($rows)): ?>
                            <tr>
                                <td colspan="14" class="text-muted fst-italic py-4 px-3">No payable obligations found for the selected filters.</td>
                            </tr>
                        <?php else: ?>
                            <?php foreach ($rows as $r): ?>
                                <?php
                                    $src = (string)($r['source_type'] ?? $r['source'] ?? '');
                                    $refId = (int)($r['source_id'] ?? $r['ref_id'] ?? 0);
                                    $party = trim((string)($r['party_name'] ?? '—'));
                                    $label = trim((string)($r['payable_label'] ?? '—'));
                                    $amt = (float)($r['amount_due'] ?? 0);
                                    $paidAmt = (float)($r['amount_paid'] ?? 0);
                                    $bal = (float)($r['balance'] ?? max(0, $amt - $paidAmt));
                                    $dueRaw = (string)($r['due_date'] ?? '');
                                    $dueLabel = px_safe_date($dueRaw);
                                    $appr = trim((string)($r['approval_status'] ?? '—'));
                                    $paySt = trim((string)($r['payment_status'] ?? '—'));
                                    $priority = (string)($r['priority'] ?? 'Normal');
                                    $dept = trim((string)($r['department'] ?? ''));
                                    $req = trim((string)($r['requested_by'] ?? ''));
                                    $upd = trim((string)($r['updated_at'] ?? ''));
                                    $viewHref = (string)($r['view_href'] ?? '');
                                    $workflow = (string)($r['workflow_status'] ?? '');
                                    $canApprove = false;
                                    if ($src === 'expenses_manual' && px_norm($appr) === 'pending') $canApprove = true;
                                    if ($src === 'hr_payroll' && px_norm($appr) === 'pending_approval') $canApprove = true;
                                ?>
                                <tr class="payables-row" <?= $viewHref !== '' ? ('data-href="' . htmlspecialchars($viewHref) . '"') : '' ?>>
                                    <td class="fw-semibold"><?= htmlspecialchars($party !== '' ? $party : '—') ?></td>
                                    <td class="text-muted"><?= htmlspecialchars($label !== '' ? $label : '—') ?></td>
                                    <td class="text-end fw-bold"><?= px_money($amt, $currencySymbol) ?></td>
                                    <td class="text-end"><?= px_money($paidAmt, $currencySymbol) ?></td>
                                    <td class="text-end fw-bold"><?= px_money($bal, $currencySymbol) ?></td>
                                    <td><?= htmlspecialchars($dueLabel) ?></td>
                                    <td><?= px_badge($workflow) ?></td>
                                    <td><?= px_badge(ucwords(str_replace('_',' ', strtolower($appr)))) ?></td>
                                    <td><?= px_badge(ucwords(str_replace('_',' ', strtolower($paySt)))) ?></td>
                                    <td><?= px_badge($priority) ?></td>
                                    <td class="text-muted"><?= htmlspecialchars($dept !== '' ? $dept : '—') ?></td>
                                    <td class="text-muted"><?= htmlspecialchars($req !== '' ? $req : '—') ?></td>
                                    <td class="text-muted"><?= htmlspecialchars($upd !== '' ? px_safe_date($upd) : '—') ?></td>
                                    <td class="text-end">
                                        <div class="dropdown">
                                            <button class="btn btn-sm btn-outline-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">Actions</button>
                                            <ul class="dropdown-menu dropdown-menu-end">
                                                <?php if ($viewHref !== ''): ?>
                                                    <li><a class="dropdown-item" href="<?= htmlspecialchars($viewHref) ?>">View</a></li>
                                                <?php else: ?>
                                                    <li><button class="dropdown-item" type="button" disabled>View</button></li>
                                                <?php endif; ?>
                                                <li><hr class="dropdown-divider"></li>
                                                <?php if ($canApprove && $src === 'expenses_manual' && file_exists(__DIR__ . '/finance-expense-view.php') && $refId > 0): ?>
                                                    <li>
                                                        <form method="post" action="finance-expense-view.php?id=<?= (int)$refId ?>&source=manual" class="px-3 py-1">
                                                            <input type="hidden" name="approve_manual_id" value="<?= (int)$refId ?>">
                                                            <button class="btn btn-sm btn-outline-primary w-100" type="submit">Approve</button>
                                                        </form>
                                                    </li>
                                                <?php elseif ($canApprove && $src === 'hr_payroll' && file_exists(__DIR__ . '/hr-payroll.php') && $refId > 0): ?>
                                                    <li>
                                                        <form method="post" action="hr-payroll.php" class="px-3 py-1">
                                                            <input type="hidden" name="approve_payroll_id" value="<?= (int)$refId ?>">
                                                            <button class="btn btn-sm btn-outline-primary w-100" type="submit">Approve</button>
                                                        </form>
                                                    </li>
                                                <?php else: ?>
                                                    <li><button class="dropdown-item" type="button" disabled>Approve</button></li>
                                                <?php endif; ?>
                                                <li><button class="dropdown-item" type="button" disabled>Partial Payment</button></li>
                                                <li><button class="dropdown-item" type="button" disabled>Mark as Paid</button></li>
                                                <li><button class="dropdown-item" type="button" disabled>Upload Receipt</button></li>
                                                <li><button class="dropdown-item" type="button" disabled>Generate Voucher</button></li>
                                                <li><button class="dropdown-item" type="button" disabled>View Approval Trail</button></li>
                                                <li><hr class="dropdown-divider"></li>
                                                <li><a class="dropdown-item" href="payables.php?<?= htmlspecialchars(http_build_query($expQuery)) ?>">Export</a></li>
                                            </ul>
                                        </div>
                                    </td>
                                </tr>
                            <?php endforeach; ?>
                        <?php endif; ?>
                    </tbody>
                </table>
            </div>
        </div>
        <?php
            $mkUrl = function($p) use ($q, $type, $approval, $payment, $perPage) {
                $arr = ['q'=>$q,'type'=>$type,'approval'=>$approval,'payment'=>$payment,'per_page'=>$perPage,'page'=>$p];
                $arr = array_filter($arr, fn($v) => $v !== '' && $v !== null);
                return 'payables.php?' . http_build_query($arr);
            };
        ?>
        <?php if (!empty($totalPages) && $totalPages > 1): ?>
        <div class="card-footer bg-white border-0 d-flex align-items-center justify-content-between flex-wrap gap-2">
            <div class="small px-muted">Page <?= (int)$page ?> of <?= (int)$totalPages ?></div>
            <nav>
                <ul class="pagination pagination-sm mb-0">
                    <li class="page-item <?= $page <= 1 ? 'disabled' : '' ?>"><a class="page-link" href="<?= htmlspecialchars($mkUrl(max(1, $page - 1))) ?>">Prev</a></li>
                    <li class="page-item <?= $page >= (int)$totalPages ? 'disabled' : '' ?>"><a class="page-link" href="<?= htmlspecialchars($mkUrl(min((int)$totalPages, $page + 1))) ?>">Next</a></li>
                </ul>
            </nav>
        </div>
        <?php endif; ?>
    </div>
</div>

<script>
(function(){
    var rows = document.querySelectorAll('tr.payables-row[data-href]');
    if (!rows.length) return;
    rows.forEach(function(tr){
        tr.addEventListener('click', function(ev){
            var t = ev.target;
            if (!t) return;
            if (t.closest('a,button,input,select,textarea,label,.dropdown-menu')) return;
            var href = tr.getAttribute('data-href') || '';
            if (href) window.location.href = href;
        });
    });
})();
</script>

<script>
(function(){
    var el = document.querySelector('.payables-table-wrap');
    if (!el) return;
    var isDown = false;
    var startX = 0;
    var scrollLeft = 0;
    el.addEventListener('mousedown', function(e){
        if (e.button !== 0) return;
        if (e.target && e.target.closest('a,button,input,select,textarea,label,.dropdown-menu')) return;
        isDown = true;
        el.classList.add('payables-grabbing');
        startX = e.pageX;
        scrollLeft = el.scrollLeft;
    });
    document.addEventListener('mouseup', function(){
        if (!isDown) return;
        isDown = false;
        el.classList.remove('payables-grabbing');
    });
    document.addEventListener('mousemove', function(e){
        if (!isDown) return;
        var walk = (e.pageX - startX);
        el.scrollLeft = scrollLeft - walk;
    });
})();
</script>

<?php require_once __DIR__ . '/includes/footer.php'; ?>

Youez - 2016 - github.com/yon3zu
LinuXploit