Heray-Was-Here
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
Directory :  /home/u390967363/domains/aibenproperties.com/public_html/app/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/u390967363/domains/aibenproperties.com/public_html/app/finance-approvals.php
<?php
session_start();
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/functions.php';
$role = $_SESSION['user_role'] ?? 'guest';
$role_norm = strtolower(str_replace([' ', '-'], '_', (string)$role));
if (!isset($_SESSION['user_id']) || !(in_array($role_norm, ['super_admin','admin','finance_manager','finance_officer','chairman_ceo']))) {
    include __DIR__ . '/includes/header.php';
    echo '<div class="container p-4"><div class="alert alert-danger">Access denied.</div></div>';
    include __DIR__ . '/includes/footer.php';
    exit;
}
$canApprovePayments = in_array($role_norm, ['finance_manager','super_admin','chairman_ceo'], true);

$companyId = getCurrentCompanyId();
$notice = null; $type = 'info';

function ap_generate_receipt_number(PDO $pdo) {
    try {
        $stmt = $pdo->query("SELECT MAX(CAST(SUBSTRING_INDEX(receipt_number,'-',-1) AS UNSIGNED)) FROM receipts WHERE receipt_number LIKE 'AIB-RCPT-%'");
        $max = (int)($stmt->fetchColumn() ?: 0);
        $next = $max + 1;
        return 'AIB-RCPT-' . str_pad((string)$next, 4, '0', STR_PAD_LEFT);
    } catch (Throwable $e) {
        return 'AIB-RCPT-' . str_pad((string)rand(1,9999), 4, '0', STR_PAD_LEFT);
    }
}

function ap_create_receipt_after_approval(PDO $pdo, $dealId, $invoiceId, $amountPaidNow, $verifiedBy) {
    if ($amountPaidNow <= 0) return null;
    try {
        $hasR = $pdo->query("SHOW TABLES LIKE 'receipts'")->rowCount() > 0;
        if (!$hasR) return null;
        $chk = null;
        if ($invoiceId) {
            $chk = $pdo->prepare("SELECT id FROM receipts WHERE invoice_id <=> ? AND amount_paid = ? ORDER BY id DESC LIMIT 1");
            $chk->execute([$invoiceId, $amountPaidNow]);
        } elseif ($dealId) {
            $chk = $pdo->prepare("SELECT id FROM receipts WHERE deal_id <=> ? AND amount_paid = ? ORDER BY id DESC LIMIT 1");
            $chk->execute([$dealId, $amountPaidNow]);
        }
        $exists = $chk ? (int)($chk->fetchColumn() ?: 0) : 0;
        if ($exists > 0) return $exists;
        $rcNo = ap_generate_receipt_number($pdo);
        $ins = $pdo->prepare("INSERT INTO receipts (deal_id, invoice_id, receipt_number, amount_paid, payment_method, verified_by) VALUES (?, ?, ?, ?, 'Bank Transfer', ?)");
        $ins->execute([$dealId ?: null, $invoiceId ?: null, $rcNo, $amountPaidNow, $verifiedBy ?: null]);
        return (int)$pdo->lastInsertId();
    } catch (Throwable $e) {
        return null;
    }
}

// Commission rate resolver from governance: project override > global > default 5%
$resolveCommissionRate = function($pdo, $allocationId = null) use ($companyId) {
    $rate = 0.0;
    try {
        $g = getSetting('global_commission_rate');
        if ($g !== null && $g !== '') $rate = (float)$g;
    } catch (Throwable $e) {}
    if ($allocationId) {
        try {
            $q = "SELECT e.config_json 
                  FROM allocations a 
                  JOIN properties p ON a.property_id = p.id 
                  JOIN estates e ON p.estate_id = e.id 
                  WHERE a.id = ?";
            $st = $pdo->prepare($q); $st->execute([(int)$allocationId]);
            $cfg = $st->fetchColumn();
            if ($cfg) {
                $j = json_decode($cfg, true);
                if (isset($j['commission_override'])) {
                    $rate = (float)$j['commission_override'];
                }
            }
        } catch (Throwable $e) {}
    }
    if ($rate <= 0) $rate = 5.0;
    return $rate;
};

// Handle Approve/Reject actions
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $action = $_POST['fa_action'] ?? '';
    $payId = isset($_POST['payment_id']) ? (int)$_POST['payment_id'] : 0;
    if (in_array($action, ['approve','reject'], true) && !$canApprovePayments) {
        $notice = 'Only Finance Manager can approve or reject payments.';
        $type = 'danger';
    } elseif ($action === 'approve' && $payId > 0) {
        // Collect commission inputs
        $beneficiary_role = trim($_POST['beneficiary_role'] ?? '');
        $beneficiary_id = isset($_POST['beneficiary_id']) && ctype_digit($_POST['beneficiary_id']) ? (int)$_POST['beneficiary_id'] : 0;
        $allocation_id = isset($_POST['allocation_id']) && ctype_digit($_POST['allocation_id']) ? (int)$_POST['allocation_id'] : null;
        $commission_pct = isset($_POST['commission_pct']) ? (float)$_POST['commission_pct'] : 0;

        try {
            $pdo->beginTransaction();
            // Approve payment
            $params = [$payId];
            $sql = "UPDATE payments SET status = 'approved', approval_date = CURRENT_TIMESTAMP, approved_by = ?" . ($companyId && function_exists('tableHasColumn') && tableHasColumn('payments','company_id') ? " WHERE id = ? AND company_id = ?" : " WHERE id = ?");
            $params = [$_SESSION['user_id'], $payId];
            if ($companyId && function_exists('tableHasColumn') && tableHasColumn('payments','company_id')) $params[] = $companyId;
            $st = $pdo->prepare($sql); $st->execute($params);

            // Fetch amount + user for commission base
            $sel = ['amount','user_id','allocation_id'];
            if (function_exists('tableHasColumn') && tableHasColumn('payments','payment_type')) { $sel[] = 'payment_type'; }
            if (function_exists('tableHasColumn') && tableHasColumn('payments','meta_json')) { $sel[] = 'meta_json'; }
            $st2 = $pdo->prepare("SELECT " . implode(',', $sel) . " FROM payments WHERE id = ?" . ($companyId && function_exists('tableHasColumn') && tableHasColumn('payments','company_id') ? " AND company_id = ?" : ""));
            $p2 = [$payId]; if ($companyId && function_exists('tableHasColumn') && tableHasColumn('payments','company_id')) $p2[] = $companyId;
            $st2->execute($p2);
            $row = $st2->fetch(PDO::FETCH_ASSOC);
            $amount = (float)($row['amount'] ?? 0);
            $userId = isset($row['user_id']) ? (int)$row['user_id'] : null;
            if (!$allocation_id && !empty($row['allocation_id'])) $allocation_id = (int)$row['allocation_id'];

            $paymentType = '';
            try {
                if (isset($row['payment_type'])) { $paymentType = strtolower(trim((string)$row['payment_type'])); }
            } catch (Throwable $e) { $paymentType = ''; }
            if ($paymentType === '' && isset($row['meta_json'])) {
                try {
                    $mj = json_decode((string)$row['meta_json'], true);
                    if (is_array($mj) && isset($mj['payment_type'])) { $paymentType = strtolower(trim((string)$mj['payment_type'])); }
                } catch (Throwable $e) { $paymentType = ''; }
            }
            if ($paymentType === '') { $paymentType = 'land'; }
            $commissionEnabled = ($paymentType === 'land');

            // Compute commission percent default (LAND only)
            if ($commissionEnabled) {
                if ($commission_pct <= 0) {
                    $commission_pct = $resolveCommissionRate($pdo, $allocation_id);
                }
            } else {
                $commission_pct = 0.0;
            }
            $commission_amount = $commissionEnabled ? round($amount * ($commission_pct / 100), 2) : 0.0;

            // Create Commission if beneficiary provided (LAND only)
            if ($commissionEnabled && $beneficiary_id > 0 && $commission_amount > 0) {
                $cols = ['status','created_at','commission_percentage','commission_amount'];
                $vals = ['approved', date('Y-m-d H:i:s'), $commission_pct, $commission_amount];
                $ph = ['?','?','?','?'];
                if (function_exists('tableHasColumn') && tableHasColumn('commissions','company_id') && $companyId) { $cols[]='company_id'; $vals[]=$companyId; $ph[]='?'; }
                if (function_exists('tableHasColumn') && tableHasColumn('commissions','agent_id')) { $cols[]='agent_id'; $vals[]=$beneficiary_id; $ph[]='?'; }
                if (function_exists('tableHasColumn') && tableHasColumn('commissions','beneficiary_role')) { $cols[]='beneficiary_role'; $vals[]=$beneficiary_role; $ph[]='?'; }
                if (function_exists('tableHasColumn') && tableHasColumn('commissions','allocation_id') && $allocation_id) { $cols[]='allocation_id'; $vals[]=$allocation_id; $ph[]='?'; }
                if (function_exists('tableHasColumn') && tableHasColumn('commissions','property_id') && $allocation_id) {
                    try {
                        $pstmt = $pdo->prepare("SELECT property_id FROM allocations WHERE id = ?");
                        $pstmt->execute([$allocation_id]);
                        $propId = (int)$pstmt->fetchColumn();
                        if ($propId > 0) { $cols[]='property_id'; $vals[]=$propId; $ph[]='?'; }
                    } catch (Throwable $e) {}
                }
                if (function_exists('tableHasColumn') && tableHasColumn('commissions','client_id') && $userId) { $cols[]='client_id'; $vals[]=$userId; $ph[]='?'; }
                if (function_exists('tableHasColumn') && tableHasColumn('commissions','deal_id')) {
                    // Optional wiring if deals exist; skip for now (foundation)
                }
                $sql = "INSERT INTO commissions (" . implode(',', $cols) . ") VALUES (" . implode(',', $ph) . ")";
                $cs = $pdo->prepare($sql); $cs->execute($vals);
            }

            logActivity($_SESSION['user_id'], 'FINANCE_APPROVE_PAYMENT', "Payment #$payId approved; commission " . (($commissionEnabled && $beneficiary_id>0) ? 'created' : 'skipped'));
            try {
                $invId = null; $dealIdRc = null;
                $cols = [];
                if (function_exists('tableHasColumn') && tableHasColumn('payments','invoice_id')) $cols[] = 'invoice_id';
                if (function_exists('tableHasColumn') && tableHasColumn('payments','deal_id')) $cols[] = 'deal_id';
                if (!empty($cols)) {
                    $q = "SELECT ".implode(',', $cols)." FROM payments WHERE id = ?" . ($companyId && function_exists('tableHasColumn') && tableHasColumn('payments','company_id') ? " AND company_id = ?" : "") . " LIMIT 1";
                    $pp = [$payId]; if ($companyId && function_exists('tableHasColumn') && tableHasColumn('payments','company_id')) $pp[] = $companyId;
                    $sx = $pdo->prepare($q); $sx->execute($pp);
                    $pr = $sx->fetch(PDO::FETCH_ASSOC) ?: [];
                    if (isset($pr['invoice_id'])) $invId = (int)$pr['invoice_id'];
                    if (isset($pr['deal_id'])) $dealIdRc = (int)$pr['deal_id'];
                }
                try { createReceiptForApprovedPayment($payId); } catch (Throwable $e) {}
            } catch (Throwable $e) {}
            $pdo->commit();
            $notice = $commissionEnabled ? 'Payment approved. Commission marked payable.' : 'Payment approved.';
            $type = 'success';
        } catch (Exception $e) {
            try { if ($pdo->inTransaction()) $pdo->rollBack(); } catch (Throwable $__) {}
            $notice = 'Failed to approve: ' . $e->getMessage();
            $type = 'danger';
        }
    } elseif ($action === 'reject' && $payId > 0) {
        try {
            $sql = "UPDATE payments SET status = 'rejected'" . ($companyId && function_exists('tableHasColumn') && tableHasColumn('payments','company_id') ? " WHERE id = ? AND company_id = ?" : " WHERE id = ?");
            $params = $companyId && function_exists('tableHasColumn') && tableHasColumn('payments','company_id') ? [$payId, $companyId] : [$payId];
            $st = $pdo->prepare($sql); $st->execute($params);
            logActivity($_SESSION['user_id'], 'FINANCE_REJECT_PAYMENT', "Payment #$payId rejected");
            $notice = 'Payment rejected.';
            $type = 'success';
        } catch (Exception $e) {
            $notice = 'Failed to reject: ' . $e->getMessage();
            $type = 'danger';
        }
    }
    }
// Removed extra closing brace that caused syntax error

// Fetch pending/verified for approval
$rows = [];
try {
    $statusCol = 'status';
    $dateCol = 'payment_date';
    if (function_exists('tableHasColumn') && tableHasColumn('payments','date')) $dateCol = 'date';
    elseif (function_exists('tableHasColumn') && tableHasColumn('payments','payment_date')) $dateCol = 'payment_date';
    elseif (function_exists('tableHasColumn') && tableHasColumn('payments','created_at')) $dateCol = 'created_at';
$hasUserId = function_exists('tableHasColumn') && tableHasColumn('payments','user_id');
$hasInvoiceId = function_exists('tableHasColumn') && tableHasColumn('payments','invoice_id');
$clientSel = $hasUserId || $hasInvoiceId ? "u.name as client_name" : "'Unknown' as client_name";
$joins = "";
if ($hasUserId) {
    $joins = " LEFT JOIN users u ON p.user_id = u.id";
} elseif ($hasInvoiceId) {
    $joins = " LEFT JOIN invoices i ON p.invoice_id = i.id LEFT JOIN users u ON i.tenant_id = u.id";
}
$q = "SELECT p.*, $clientSel 
          FROM payments p 
          $joins 
          WHERE p.$statusCol IN ('pending_confirmation','verified','pending_verification')";
    $params = [];
    if ($companyId && function_exists('tableHasColumn') && tableHasColumn('payments','company_id')) { $q .= " AND p.company_id = ?"; $params[] = $companyId; }
    $q .= " ORDER BY p.id DESC";
    $st = $pdo->prepare($q); $st->execute($params);
    $rows = $st->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) { $rows = []; }

include __DIR__ . '/includes/header.php';
?>
<div class="container-fluid px-4">
    <div class="d-flex justify-content-between align-items-center mt-4 mb-3">
        <div>
            <h2 class="fw-bold text-navy">Finance & Approvals</h2>
            <div class="text-muted">Review and decision center</div>
        </div>
        <div class="d-flex gap-2">
            <a href="payments-verify.php" class="btn btn-sm btn-primary"><i class="fa-solid fa-shield-check me-2"></i>Verify Payments</a>
            <a href="transactions.php" class="btn btn-sm btn-outline-secondary"><i class="fa-solid fa-receipt me-2"></i>Payment Ledger</a>
        </div>
    </div>
    <?php if ($notice): ?>
        <div class="alert alert-<?= htmlspecialchars($type) ?>"><?= htmlspecialchars($notice) ?></div>
    <?php endif; ?>
    <div class="card shadow-sm">
        <div class="card-header bg-white d-flex justify-content-between align-items-center">
            <strong>Pending Submissions</strong>
        </div>
        <div class="card-body">
            <?php if (empty($rows)): ?>
                <div class="text-center text-muted py-4">
                    <div class="mb-2"><i class="fa-solid fa-folder-open fa-2x"></i></div>
                    <div>No items awaiting approval.</div>
                </div>
            <?php else: ?>
                <div class="table-responsive">
                    <table class="table table-hover align-middle">
                        <thead class="table-light">
                            <tr>
                                <th>Date</th>
                                <th>Client</th>
                                <th class="text-end">Amount</th>
                                <th>Method</th>
                                <th>Receipt</th>
                                <th>Status</th>
                                <th class="text-end">Actions</th>
                            </tr>
                        </thead>
                        <tbody>
                            <?php foreach ($rows as $r): ?>
                                <?php
                                    $dateDisplay = '-';
                                    if (!empty($r['payment_date'])) $dateDisplay = htmlspecialchars($r['payment_date']);
                                    elseif (!empty($r['date'])) $dateDisplay = htmlspecialchars($r['date']);
                                    elseif (!empty($r['created_at'])) $dateDisplay = htmlspecialchars($r['created_at']);
                                    $method = $r['method'] ?? ($r['payment_method'] ?? '');
                                    $proof = $r['proof_file'] ?? '';
                                ?>
                                <tr>
                                    <td><?= $dateDisplay ?></td>
                                    <td><?= htmlspecialchars($r['client_name'] ?? 'Unknown') ?></td>
                                    <td class="text-end fw-bold"><?= formatCurrency($r['amount'] ?? 0) ?></td>
                                    <td><?= htmlspecialchars($method ?: '-') ?></td>
                                    <td>
                                        <?php if ($proof): ?>
                                            <a href="<?= htmlspecialchars($proof) ?>" target="_blank" class="btn btn-sm btn-outline-secondary">View</a>
                                        <?php else: ?>
                                            <span class="text-muted">-</span>
                                        <?php endif; ?>
                                    </td>
                                    <td><span class="badge bg-warning text-dark"><?= htmlspecialchars($r['status']) ?></span></td>
                                    <td class="text-end">
                                        <?php if ($canApprovePayments): ?>
                                        <div class="btn-group btn-group-sm">
                                            <button class="btn btn-primary" 
                                                data-bs-toggle="modal" 
                                                data-bs-target="#approveModal"
                                                data-id="<?= (int)$r['id'] ?>"
                                                data-amount="<?= htmlspecialchars($r['amount']) ?>"
                                                data-allocation="<?= htmlspecialchars($r['allocation_id'] ?? '') ?>"
                                            ><i class="fa-solid fa-check me-1"></i>Approve</button>
                                            <form method="POST" class="d-inline">
                                                <input type="hidden" name="fa_action" value="reject">
                                                <input type="hidden" name="payment_id" value="<?= (int)$r['id'] ?>">
                                                <button class="btn btn-outline-danger"><i class="fa-solid fa-xmark me-1"></i>Reject</button>
                                            </form>
                                        </div>
                                        <?php else: ?>
                                            <span class="text-muted small">Awaiting manager approval</span>
                                        <?php endif; ?>
                                    </td>
                                </tr>
                            <?php endforeach; ?>
                        </tbody>
                    </table>
                </div>
            <?php endif; ?>
        </div>
    </div>
    <div class="text-muted small mt-2">Only Finance Manager can approve payments. Commission becomes payable upon approval.</div>
</div>

<!-- Approve Modal -->
<div class="modal fade" id="approveModal" tabindex="-1" aria-hidden="true">
  <div class="modal-dialog modal-lg">
    <form method="POST" class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title">Approve Payment & Set Commission</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        <input type="hidden" name="fa_action" value="approve">
        <input type="hidden" name="payment_id" id="apPaymentId">
        <div class="row g-3">
            <div class="col-md-4">
                <label class="form-label">Allocation (optional)</label>
                <input type="number" name="allocation_id" id="apAllocationId" class="form-control" placeholder="Allocation ID">
            </div>
            <div class="col-md-4">
                <label class="form-label">Commission %</label>
                <input type="number" step="0.01" min="0" name="commission_pct" id="apCommissionPct" class="form-control">
                <div class="form-text">Defaults from governance.</div>
            </div>
            <div class="col-md-4">
                <label class="form-label">Beneficiary Role</label>
                <select class="form-select" name="beneficiary_role" id="apBeneficiaryRole">
                    <option>Agent</option>
                    <option>Marketer</option>
                    <option>Internal Staff</option>
                    <option>Contact Centre</option>
                </select>
            </div>
            <div class="col-12">
                <label class="form-label">Beneficiary</label>
                <select class="form-select" name="beneficiary_id" id="apBeneficiaryId" required>
                    <option value="">Select user</option>
                    <?php
                    try {
                        $uq = "SELECT id, name, role FROM users";
                        $paramsU = [];
                        if ($companyId && function_exists('tableHasColumn') && tableHasColumn('users','company_id')) { $uq .= " WHERE company_id = ?"; $paramsU[] = $companyId; }
                        $uq .= " ORDER BY name";
                        $us = $pdo->prepare($uq); $us->execute($paramsU);
                        $opts = $us->fetchAll(PDO::FETCH_ASSOC);
                        foreach ($opts as $o) {
                            echo '<option value="' . (int)$o['id'] . '">' . htmlspecialchars($o['name'] . ' — ' . $o['role']) . '</option>';
                        }
                    } catch (Exception $e) {}
                    ?>
                </select>
            </div>
            <div class="col-12">
                <div class="alert alert-info d-flex align-items-center" id="apAmountInfo" role="alert">
                    <i class="fa-solid fa-circle-info me-2"></i>
                    <div>Commission will be computed from this payment amount.</div>
                </div>
            </div>
        </div>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
        <button class="btn btn-success"><i class="fa-solid fa-check me-2"></i>Approve & Create Commission</button>
      </div>
    </form>
  </div>
</div>
<script>
document.addEventListener('show.bs.modal', function(e) {
    const trg = e.target;
    if (trg && trg.id === 'approveModal') {
        const btn = e.relatedTarget;
        if (!btn) return;
        const pid = btn.getAttribute('data-id');
        const amt = btn.getAttribute('data-amount') || '0';
        const alloc = btn.getAttribute('data-allocation') || '';
        document.getElementById('apPaymentId').value = pid;
        document.getElementById('apAllocationId').value = alloc;
        const info = document.getElementById('apAmountInfo');
        if (info) info.querySelector('div').textContent = 'Commission base: NGN ' + new Intl.NumberFormat().format(parseFloat(amt));
    }
});
</script>
<?php include __DIR__ . '/includes/footer.php'; ?>

Hry