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/client-upload-proof.php
<?php
$sp = ini_get('session.save_path');
$bad = (!$sp || !@is_dir($sp) || !@is_writable($sp));
if (session_status() === PHP_SESSION_ACTIVE && $bad) { @session_write_close(); }
if ($bad) {
    $projRoot = __DIR__;
    $sessDir = $projRoot . DIRECTORY_SEPARATOR . 'tmp-sessions';
    if (!@is_dir($sessDir)) { @mkdir($sessDir, 0777, true); }
    if (@is_dir($sessDir) && @is_writable($sessDir)) {
        @ini_set('session.save_path', $sessDir);
    } else {
        $tmp = sys_get_temp_dir();
        if ($tmp && @is_dir($tmp) && @is_writable($tmp)) { @ini_set('session.save_path', $tmp); }
    }
}
if (session_status() === PHP_SESSION_NONE) { session_start(); }
$GLOBALS['SKIP_MIGRATIONS'] = true;
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/functions.php';
require_once __DIR__ . '/includes/mailer.php';

function isAjaxRequest(): bool {
    $xhr = !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower((string)$_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
    $acceptsJson = isset($_SERVER['HTTP_ACCEPT']) && stripos((string)$_SERVER['HTTP_ACCEPT'], 'application/json') !== false;
    return $xhr || $acceptsJson;
}
function respondClientUpload(bool $ok, string $message, string $type = 'success'): void {
    $redirect = "client-payments.php?toast=" . urlencode($message) . "&type=" . urlencode($type);
    if (isAjaxRequest()) {
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode(['ok' => $ok, 'message' => $message, 'redirect' => $redirect]);
        exit;
    }
    header("Location: " . $redirect);
    exit;
}

$roleNorm = strtolower(preg_replace('/[^a-z0-9]+/','_', (string)($_SESSION['user_role'] ?? '')));
if (!isset($_SESSION['user_id']) || $roleNorm !== 'client') {
    respondClientUpload(false, "Unauthorized", "danger");
}

$uid = (int)$_SESSION['user_id'];
$companyId = function_exists('getCurrentCompanyId') ? (int)getCurrentCompanyId() : 0;
$allocId = (int)($_POST['allocation_id'] ?? 0);
$propertyId = (int)($_POST['property_id'] ?? 0);
$amount = (float)($_POST['amount'] ?? 0);
$ref = trim($_POST['reference'] ?? '');
$paymentType = strtolower(trim((string)($_POST['payment_type'] ?? '')));
$planType = strtolower(trim((string)($_POST['plan_type'] ?? '')));
$customMonths = (int)($_POST['custom_months'] ?? 0);
$installmentStartDate = trim((string)($_POST['installment_start_date'] ?? ''));
$sqm = (float)str_replace(',', '', (string)($_POST['sqm'] ?? '0'));
$clientChargeId = (int)($_POST['client_charge_id'] ?? 0);
$proofPath = '';
$receiptHash = '';
$isDuplicate = false;

try {
    if (($allocId <= 0 && $propertyId <= 0) || $amount <= 0 || $ref === '') {
        respondClientUpload(false, "All fields are required", "danger");
    }

    $propTitleCol = null;
    try {
        if (function_exists('tableHasColumn') && tableHasColumn('properties','title')) {
            $propTitleCol = 'title';
        } elseif (function_exists('tableHasColumn') && tableHasColumn('properties','name')) {
            $propTitleCol = 'name';
        } elseif (function_exists('tableHasColumn') && tableHasColumn('properties','property_name')) {
            $propTitleCol = 'property_name';
        }
    } catch (Throwable $e) { $propTitleCol = null; }

    $allocIdFinal = 0;
    $propertyIdFinal = 0;
    $propertyTitle = '';

    if ($allocId > 0) {
        $ptSel = $propTitleCol ? ("p.`{$propTitleCol}`") : "NULL";
        $q = "SELECT a.id, a.property_id, {$ptSel} AS property_title FROM allocations a LEFT JOIN properties p ON a.property_id = p.id WHERE a.id = ? AND a.user_id = ?";
        $p = [$allocId, $uid];
        if ($companyId && function_exists('tableHasColumn') && tableHasColumn('allocations','company_id')) { $q .= " AND (a.company_id = ? OR a.company_id IS NULL OR a.company_id = 0)"; $p[] = $companyId; }
        $q .= " LIMIT 1";
        $st = $pdo->prepare($q); $st->execute($p);
        $row = $st->fetch(PDO::FETCH_ASSOC) ?: [];
        if (empty($row)) {
            respondClientUpload(false, "Invalid allocation", "danger");
        }
        $allocIdFinal = (int)($row['id'] ?? 0);
        $propertyIdFinal = (int)($row['property_id'] ?? 0);
        $propertyTitle = trim((string)($row['property_title'] ?? ''));
    } else {
        $ptSel = $propTitleCol ? ("`{$propTitleCol}` AS title") : "NULL AS title";
        $q = "SELECT id, {$ptSel} FROM properties WHERE id = ?";
        $p = [$propertyId];
        if ($companyId && function_exists('tableHasColumn') && tableHasColumn('properties','company_id')) { $q .= " AND (company_id = ? OR company_id IS NULL)"; $p[] = $companyId; }
        $q .= " LIMIT 1";
        $st = $pdo->prepare($q); $st->execute($p);
        $row = $st->fetch(PDO::FETCH_ASSOC) ?: [];
        if (empty($row)) {
            respondClientUpload(false, "Invalid property", "danger");
        }
        $propertyIdFinal = (int)($row['id'] ?? 0);
        $propertyTitle = trim((string)($row['title'] ?? ''));
        try {
            if ($propertyIdFinal > 0
                && $pdo->query("SHOW TABLES LIKE 'allocations'")->rowCount() > 0
                && function_exists('tableHasColumn')
                && tableHasColumn('allocations','property_id')
                && tableHasColumn('allocations','user_id')
            ) {
                $qa = "SELECT id FROM allocations WHERE user_id = ? AND property_id = ?";
                $pa = [$uid, $propertyIdFinal];
                if ($companyId && tableHasColumn('allocations','company_id')) { $qa .= " AND (company_id = ? OR company_id IS NULL OR company_id = 0)"; $pa[] = $companyId; }
                $qa .= " ORDER BY id DESC LIMIT 1";
                $as = $pdo->prepare($qa); $as->execute($pa);
                $guessAlloc = (int)($as->fetchColumn() ?: 0);
                if ($guessAlloc > 0) { $allocIdFinal = $guessAlloc; }
            }
        } catch (Throwable $e) {}
    }
    try {
        $proofPath = (string)(handleFileUpload('proof', 'uploads/payments/') ?: '');
    } catch (Throwable $e) {
        $proofPath = '';
    }
    if ($proofPath === '') {
        respondClientUpload(false, "Upload proof (PDF/JPG/PNG) to continue", "danger");
    }
    $absProof = __DIR__ . '/' . ltrim(str_replace('\\', '/', $proofPath), '/');
    if (is_file($absProof)) {
        try { $receiptHash = sha1_file($absProof) ?: ''; } catch (Throwable $e) { $receiptHash = ''; }
    }
    if ($receiptHash !== '') {
        try {
            if (function_exists('tableHasColumn') && tableHasColumn('payments','receipt_hash')) {
                $chk = $pdo->prepare("SELECT id FROM payments WHERE receipt_hash = ? AND status <> 'rejected' LIMIT 1");
                $chk->execute([$receiptHash]);
                $isDuplicate = (bool)$chk->fetchColumn();
            } elseif (function_exists('tableHasColumn') && tableHasColumn('payments','proof_file')) {
                $chk2 = $pdo->prepare("SELECT id FROM payments WHERE proof_file = ? AND status <> 'rejected' LIMIT 1");
                $chk2->execute([$proofPath]);
                $isDuplicate = (bool)$chk2->fetchColumn();
            } elseif (function_exists('tableHasColumn') && tableHasColumn('payments','receipt_file')) {
                $chk3 = $pdo->prepare("SELECT id FROM payments WHERE receipt_file = ? AND status <> 'rejected' LIMIT 1");
                $chk3->execute([$proofPath]);
                $isDuplicate = (bool)$chk3->fetchColumn();
            }
        } catch (Throwable $e) { $isDuplicate = false; }
    }

    $paymentMethod = 'bank_transfer';
    $status = $isDuplicate ? 'duplicate' : 'pending_verification';
    $nowTs = date('Y-m-d H:i:s');

    $dealIdFinal = 0;
    $dealSubmitId = 0;
    try {
        if (function_exists('tableHasColumn') && tableHasColumn('payments','deal_id')) {
            if ($allocIdFinal > 0 && function_exists('tableHasColumn') && tableHasColumn('allocations','deal_id')) {
                $qa = "SELECT deal_id FROM allocations WHERE id = ? AND user_id = ?";
                $pa = [$allocIdFinal, $uid];
                if ($companyId && tableHasColumn('allocations','company_id')) { $qa .= " AND company_id = ?"; $pa[] = $companyId; }
                $qa .= " LIMIT 1";
                $stA = $pdo->prepare($qa); $stA->execute($pa);
                $dealIdFinal = (int)($stA->fetchColumn() ?: 0);
            }
            if ($dealIdFinal > 0) {
                try {
                    if ($pdo->query("SHOW TABLES LIKE 'deals'")->rowCount() > 0) {
                        $chk = $pdo->prepare("SELECT id FROM deals WHERE id = ? LIMIT 1");
                        $chk->execute([$dealIdFinal]);
                        if (!(int)($chk->fetchColumn() ?: 0)) { $dealIdFinal = 0; }
                    } else {
                        $dealIdFinal = 0;
                    }
                } catch (Throwable $e) { $dealIdFinal = 0; }
            }
            if ($dealIdFinal <= 0 && $pdo->query("SHOW TABLES LIKE 'deals_submit'")->rowCount() > 0) {
                $clientCol = (function_exists('tableHasColumn') && tableHasColumn('deals_submit','client_id')) ? 'client_id' : ((function_exists('tableHasColumn') && tableHasColumn('deals_submit','user_id')) ? 'user_id' : null);
                if ($clientCol) {
                    $sqlD = "SELECT id FROM deals_submit WHERE {$clientCol} = ?";
                    $prm = [$uid];
                    if ($companyId && function_exists('tableHasColumn') && tableHasColumn('deals_submit','company_id')) {
                        $sqlD .= " AND (company_id = ? OR company_id IS NULL)";
                        $prm[] = $companyId;
                    }
                    $sqlD .= " ORDER BY created_at DESC, id DESC LIMIT 1";
                    $sd = $pdo->prepare($sqlD); $sd->execute($prm);
                    $dealSubmitId = (int)($sd->fetchColumn() ?: 0);
                }
            }
        }
    } catch (Throwable $e) { $dealIdFinal = 0; }

    $meta = [
        'allocation_id' => $allocIdFinal,
        'property_id' => $propertyIdFinal,
        'client_charge_id' => $clientChargeId,
        'payment_reference' => $ref,
        'payment_method' => $paymentMethod,
        'payment_type' => $paymentType,
        'plan_type' => $planType,
        'custom_months' => $customMonths,
        'installment_start_date' => $installmentStartDate,
        'sqm' => $sqm,
        'submitted_by_role' => 'client',
        'submitted_by_user' => $uid,
        'deal_id' => $dealIdFinal,
        'deal_submit_id' => $dealSubmitId,
    ];
    if (!isset($meta['transactions']) || !is_array($meta['transactions'])) {
        $meta['transactions'] = [[
            'date' => $nowTs,
            'amount' => $amount,
            'type' => $paymentType !== '' ? $paymentType : 'property_payment',
            'status' => $status
        ]];
    }

    $cols = ['user_id','amount','status'];
    $vals = [$uid, $amount, $status];
    if ($allocIdFinal > 0 && function_exists('tableHasColumn') && tableHasColumn('payments','allocation_id')) { $cols[]='allocation_id'; $vals[] = $allocIdFinal; }
    if ($propertyIdFinal > 0 && function_exists('tableHasColumn') && tableHasColumn('payments','property_id')) { $cols[]='property_id'; $vals[] = $propertyIdFinal; }
    if ($dealIdFinal > 0 && function_exists('tableHasColumn') && tableHasColumn('payments','deal_id')) { $cols[]='deal_id'; $vals[] = $dealIdFinal; }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','company_id') && $companyId) { $cols[]='company_id'; $vals[] = $companyId; }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','reference') && $ref !== '') { $cols[]='reference'; $vals[] = $ref; }
    elseif (function_exists('tableHasColumn') && tableHasColumn('payments','reference_number') && $ref !== '') { $cols[]='reference_number'; $vals[] = $ref; }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','payment_method')) { $cols[]='payment_method'; $vals[] = $paymentMethod; }
    elseif (function_exists('tableHasColumn') && tableHasColumn('payments','method')) { $cols[]='method'; $vals[] = $paymentMethod; }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','payment_type') && $paymentType !== '') { $cols[]='payment_type'; $vals[] = $paymentType; }
    if ($planType !== '' && function_exists('tableHasColumn') && tableHasColumn('payments','plan_type')) { $cols[]='plan_type'; $vals[] = $planType; }
    elseif ($planType !== '' && function_exists('tableHasColumn') && tableHasColumn('payments','payment_plan')) { $cols[]='payment_plan'; $vals[] = $planType; }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','client_charge_id') && $clientChargeId > 0) { $cols[]='client_charge_id'; $vals[] = $clientChargeId; }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','proof_file')) { $cols[]='proof_file'; $vals[] = $proofPath; }
    elseif (function_exists('tableHasColumn') && tableHasColumn('payments','receipt_file')) { $cols[]='receipt_file'; $vals[] = $proofPath; }
    if ($sqm > 0 && function_exists('tableHasColumn') && tableHasColumn('payments','sqm')) { $cols[]='sqm'; $vals[] = $sqm; }
    if ($receiptHash !== '' && function_exists('tableHasColumn') && tableHasColumn('payments','receipt_hash')) { $cols[]='receipt_hash'; $vals[] = $receiptHash; }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','submitted_by_user')) { $cols[]='submitted_by_user'; $vals[] = $uid; }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','submitted_by_role')) { $cols[]='submitted_by_role'; $vals[] = 'client'; }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','created_at')) { $cols[]='created_at'; $vals[] = $nowTs; }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','date')) { $cols[]='date'; $vals[] = date('Y-m-d', strtotime($nowTs)); }
    if (function_exists('tableHasColumn') && tableHasColumn('payments','payment_date')) { $cols[]='payment_date'; $vals[] = date('Y-m-d', strtotime($nowTs)); }

    $sql = "INSERT INTO payments (" . implode(',', $cols) . ") VALUES (" . implode(',', array_fill(0, count($cols), '?')) . ")";
    $ins = $pdo->prepare($sql); $ins->execute($vals);
    $pid = (int)$pdo->lastInsertId();

    if ($pid > 0 && function_exists('tableHasColumn') && tableHasColumn('payments','meta_json')) {
        try {
            $pdo->prepare("UPDATE payments SET meta_json = ? WHERE id = ?" . ($companyId && tableHasColumn('payments','company_id') ? " AND (company_id = ? OR company_id IS NULL)" : ""))->execute(
                $companyId && tableHasColumn('payments','company_id') ? [json_encode($meta, JSON_UNESCAPED_UNICODE), $pid, $companyId] : [json_encode($meta, JSON_UNESCAPED_UNICODE), $pid]
            );
        } catch (Throwable $e) {}
    }

    try {
        if ($pid > 0 && $allocIdFinal > 0 && function_exists('tableHasColumn') && tableHasColumn('payments','allocation_id')) {
            $pdo->prepare("UPDATE payments SET allocation_id = ? WHERE id = ?" . ($companyId && tableHasColumn('payments','company_id') ? " AND (company_id = ? OR company_id IS NULL)" : ""))->execute(
                $companyId && tableHasColumn('payments','company_id') ? [$allocIdFinal, $pid, $companyId] : [$allocIdFinal, $pid]
            );
        }
    } catch (Throwable $e) {}

    try {
        $planEff = $planType;
        if ($planEff === 'custom' && $customMonths > 0) { $planEff = 'custom_' . (int)$customMonths . '_months'; }
        $isInstallmentPlan = ($planEff === '3_months') || ($planEff === '6_months') || (bool)preg_match('/^\d+_months$/', $planEff) || (bool)preg_match('/^custom_\d+_months$/', $planEff);
        if ($allocIdFinal > 0 && $isInstallmentPlan && function_exists('generatePaymentSchedule')) {
            $hasInstTbl = $pdo->query("SHOW TABLES LIKE 'installments'")->rowCount() > 0;
            $hasPsTbl = $pdo->query("SHOW TABLES LIKE 'payment_schedules'")->rowCount() > 0;
            $hasExisting = false;
            if ($hasInstTbl && function_exists('tableHasColumn') && tableHasColumn('installments','allocation_id')) {
                $qC = "SELECT COUNT(*) FROM installments WHERE allocation_id = ?";
                if (tableHasColumn('installments','kind')) { $qC .= " AND kind = 'installment'"; }
                $stC = $pdo->prepare($qC); $stC->execute([$allocIdFinal]);
                $hasExisting = ((int)($stC->fetchColumn() ?: 0)) > 0;
            }
            if (!$hasExisting && $hasPsTbl && function_exists('tableHasColumn') && tableHasColumn('payment_schedules','allocation_id')) {
                $stC2 = $pdo->prepare("SELECT COUNT(*) FROM payment_schedules WHERE allocation_id = ?");
                $stC2->execute([$allocIdFinal]);
                $hasExisting = ((int)($stC2->fetchColumn() ?: 0)) > 0;
            }
            if (!$hasExisting) {
                $totalAmt = 0.0;
                $allocDealId = 0;
                try {
                    if (function_exists('tableHasColumn') && tableHasColumn('allocations','deal_id')) {
                        $qa = "SELECT deal_id FROM allocations WHERE id = ? AND user_id = ?" . ($companyId && tableHasColumn('allocations','company_id') ? " AND (company_id = ? OR company_id IS NULL OR company_id = 0)" : "") . " LIMIT 1";
                        $pa = [$allocIdFinal, $uid];
                        if ($companyId && tableHasColumn('allocations','company_id')) { $pa[] = $companyId; }
                        $stA = $pdo->prepare($qa); $stA->execute($pa);
                        $allocDealId = (int)($stA->fetchColumn() ?: 0);
                    }
                } catch (Throwable $e) { $allocDealId = 0; }
                if ($allocDealId > 0 && $pdo->query("SHOW TABLES LIKE 'deals'")->rowCount() > 0 && function_exists('tableHasColumn') && tableHasColumn('deals','amount_offered')) {
                    $discCol = tableHasColumn('deals','discount_amount') ? 'discount_amount' : null;
                    $qD = "SELECT amount_offered" . ($discCol ? ", $discCol AS discount_amount" : ", 0 AS discount_amount") . " FROM deals WHERE id = ? LIMIT 1";
                    $stD = $pdo->prepare($qD); $stD->execute([$allocDealId]);
                    $rD = $stD->fetch(PDO::FETCH_ASSOC) ?: null;
                    if ($rD) {
                        $off = (float)($rD['amount_offered'] ?? 0);
                        $disc = (float)($rD['discount_amount'] ?? 0);
                        if (!is_finite($off)) $off = 0.0;
                        if (!is_finite($disc)) $disc = 0.0;
                        $totalAmt = max(0.0, $off - max(0.0, $disc));
                    }
                }
                if ($totalAmt <= 0.01 && $propertyIdFinal > 0 && $pdo->query("SHOW TABLES LIKE 'properties'")->rowCount() > 0 && function_exists('tableHasColumn') && tableHasColumn('properties','price')) {
                    $qp = "SELECT price FROM properties WHERE id = ?" . ($companyId && tableHasColumn('properties','company_id') ? " AND (company_id = ? OR company_id IS NULL OR company_id = 0)" : "") . " LIMIT 1";
                    $pp = [$propertyIdFinal];
                    if ($companyId && tableHasColumn('properties','company_id')) { $pp[] = $companyId; }
                    $stP = $pdo->prepare($qp); $stP->execute($pp);
                    $pr = (float)($stP->fetchColumn() ?: 0);
                    if (!is_finite($pr)) $pr = 0.0;
                    $totalAmt = max(0.0, $pr);
                }
                if ($totalAmt <= 0.01) { $totalAmt = max(0.0, (float)$amount); }
                if ($totalAmt > 0.01) {
                    generatePaymentSchedule($pdo, $allocIdFinal, $totalAmt, $planEff, $installmentStartDate);
                }
            }
        }
    } catch (Throwable $e) {}

    try {
        $hasTx = $pdo->query("SHOW TABLES LIKE 'transactions'")->rowCount() > 0;
        if ($hasTx) {
            $tCols = []; $tPh = []; $tVals = [];
            if (function_exists('tableHasColumn') && tableHasColumn('transactions','user_id')) { $tCols[]='user_id'; $tPh[]='?'; $tVals[]=$uid; }
            if (function_exists('tableHasColumn') && tableHasColumn('transactions','amount')) { $tCols[]='amount'; $tPh[]='?'; $tVals[]=$amount; }
            if (function_exists('tableHasColumn') && tableHasColumn('transactions','transaction_type')) { $tCols[]='transaction_type'; $tPh[]='?'; $tVals[]='client_payment'; }
            if (function_exists('tableHasColumn') && tableHasColumn('transactions','status')) { $tCols[]='status'; $tPh[]='?'; $tVals[]=$status; }
            if (function_exists('tableHasColumn') && tableHasColumn('transactions','reference')) { $tCols[]='reference'; $tPh[]='?'; $tVals[]=$ref; }
            elseif (function_exists('tableHasColumn') && tableHasColumn('transactions','ref')) { $tCols[]='ref'; $tPh[]='?'; $tVals[]=$ref; }
            if ($companyId && function_exists('tableHasColumn') && tableHasColumn('transactions','company_id')) { $tCols[]='company_id'; $tPh[]='?'; $tVals[]=$companyId; }
            if (function_exists('tableHasColumn') && tableHasColumn('transactions','created_at')) { $tCols[]='created_at'; $tPh[]='?'; $tVals[]=$nowTs; }
            if (!empty($tCols)) {
                $pdo->prepare("INSERT INTO transactions (" . implode(',', $tCols) . ") VALUES (" . implode(',', $tPh) . ")")->execute($tVals);
            }
        }
    } catch (Throwable $e) {}
    try {
        $clientName = '';
        $uq = $pdo->prepare("SELECT name FROM users WHERE id = ? LIMIT 1");
        $uq->execute([$uid]);
        $clientName = (string)($uq->fetchColumn() ?: 'Client');
        $roles = ['finance','finance_officer','finance_manager'];
        $placeholders = implode(",", array_fill(0, count($roles), '?'));
        $rq = "SELECT id FROM users WHERE role IN ($placeholders)";
        $rparams = $roles;
        if ($companyId && function_exists('tableHasColumn') && tableHasColumn('users','company_id')) { $rq .= " AND company_id = ?"; $rparams[] = $companyId; }
        $rs = $pdo->prepare($rq); $rs->execute($rparams);
        $recips = $rs->fetchAll(PDO::FETCH_COLUMN);
        $subject = $propertyTitle !== '' ? $propertyTitle : ($propertyIdFinal > 0 ? ('Property #'.$propertyIdFinal) : ($allocIdFinal > 0 ? ('Allocation #'.$allocIdFinal) : 'Property'));
        foreach ($recips as $rid) {
            sendNotification((int)$rid, 'payment_proof_submitted', $clientName . " submitted proof for " . $subject . " NGN " . number_format($amount,2) . " Ref " . $ref, $pdo);
        }
        sendNotification($uid, 'payment_proof_received', "We received your payment proof for " . $subject . ". Finance will verify shortly.", $pdo);
    } catch (Exception $e) {}
    $msg = $isDuplicate ? "Proof submitted but flagged as duplicate. Finance will review." : "Proof submitted. Finance will verify shortly.";
    respondClientUpload(true, $msg, "success");
} catch (Exception $e) {
    $rid = 'UPL-' . date('YmdHis') . '-' . substr(sha1(uniqid('', true)), 0, 8);
    try { error_log("[client-upload-proof] {$rid} " . $e->getMessage()); } catch (Throwable $e2) {}
    respondClientUpload(false, "Submission failed. Please try again. Ref: {$rid}", "danger");
}
?>

Hry