|
Server : LiteSpeed System : Linux terra.hostitbro.com 5.14.0-611.54.3.el9_7.x86_64 #1 SMP PREEMPT_DYNAMIC Thu May 7 16:31:24 EDT 2026 x86_64 User : outerorb ( 1091) PHP Version : 8.1.34 Disable Function : mail Directory : /home2/outerorb/emp.outerorbittech.in/admin/ | |
|
Path: /home2/outerorb/emp.outerorbittech.in/admin/loans.php
Size: 21.17 KB
Permissions: 0666
<?php
require __DIR__ . '/../includes/helpers.php';
require_admin();
ensure_loans_table();
$admin = current_admin();
$roleLabel = (($admin['role'] ?? '') === 'super') ? 'Super Admin' : 'Admin';
$flash = flash();
$pdo = db();
// Handle approval/rejection
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (!isset($_POST['csrf_token']) || !verify_csrf($_POST['csrf_token'])) {
redirect_with_message('loans.php', 'Session expired. Please try again.', 'error');
}
$loanId = (int) $_POST['loan_id'];
$action = $_POST['action'] ?? '';
if ($action === 'approve') {
$tenureMonths = (int) $_POST['tenure_months'];
if ($tenureMonths < 3 || $tenureMonths > 60) {
redirect_with_message('loans.php', 'Invalid tenure months.', 'error');
}
$stmt = $pdo->prepare('SELECT * FROM employee_loans WHERE id = ? LIMIT 1');
$stmt->execute([$loanId]);
$loan = $stmt->fetch();
if (!$loan) {
redirect_with_message('loans.php', 'Loan not found.', 'error');
}
$monthlyInstallment = $loan['loan_amount'] / $tenureMonths;
$pdo->beginTransaction();
try {
$updateStmt = $pdo->prepare(
'UPDATE employee_loans
SET approval_status = "approved", loan_status = "approved",
approved_tenure_months = ?, monthly_installment = ?,
approved_by = ?, approved_at = NOW()
WHERE id = ?'
);
$updateStmt->execute([$tenureMonths, $monthlyInstallment, $admin['id'] ?? 0, $loanId]);
create_loan_installments($loanId, $tenureMonths, $monthlyInstallment);
$pdo->commit();
redirect_with_message('loans.php', 'Loan approved successfully!', 'success');
} catch (Exception $e) {
$pdo->rollBack();
redirect_with_message('loans.php', 'Failed to approve loan: ' . $e->getMessage(), 'error');
}
} elseif ($action === 'reject') {
$reason = sanitize_text($_POST['reason'] ?? '');
if (empty($reason)) {
redirect_with_message('loans.php', 'Please provide a reason for rejection.', 'error');
}
$stmt = $pdo->prepare(
'UPDATE employee_loans
SET approval_status = "rejected", loan_status = "rejected",
reason_for_rejection = ?
WHERE id = ?'
);
$stmt->execute([$reason, $loanId]);
redirect_with_message('loans.php', 'Loan rejected.', 'success');
}
}
// Get filter
$status = isset($_GET['status']) ? sanitize_text($_GET['status']) : 'pending';
$validStatuses = ['pending', 'approved', 'rejected', 'all'];
if (!in_array($status, $validStatuses)) $status = 'pending';
// Get loans
$where = ['l.deleted_at IS NULL', 'e.deleted_at IS NULL'];
$params = [];
if ($status !== 'all') {
$where[] = 'l.approval_status = ?';
$params[] = $status;
}
$sql = 'SELECT l.*, e.first_name, e.last_name, e.phone, e.department, e.designation_id
FROM employee_loans l
JOIN employees e ON l.employee_id = e.id
WHERE ' . implode(' AND ', $where) . '
ORDER BY l.requested_at DESC';
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$loans = $stmt->fetchAll();
// Get pending count
$pendingCount = (int) $pdo->query(
"SELECT COUNT(*) FROM employee_loans WHERE approval_status = 'pending' AND deleted_at IS NULL"
)->fetchColumn();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Loan Management - Admin</title>
<link rel="stylesheet" href="../assets/css/style.css">
<link rel="stylesheet" href="../assets/css/polish.css">
</head>
<body class="dashboard-layout">
<div class="app-wrapper">
<!-- SIDEBAR -->
<aside class="sidebar-wrapper" id="sidebar">
<div class="sidebar-header">
<div class="sidebar-logo">HR</div>
<div class="sidebar-company">
<div class="sidebar-company-name">Employee<br/>Records</div>
<div class="sidebar-company-role"><?php echo htmlspecialchars(is_super_admin() ? 'Super Admin' : 'Admin', ENT_QUOTES, 'UTF-8'); ?></div>
</div>
</div>
<nav class="sidebar-menu">
<!-- Employees Section -->
<div class="sidebar-section">
<div class="sidebar-section-title"><i class="fas fa-users"></i> EMPLOYEES</div>
<div class="sidebar-item">
<a href="dashboard.php" class="sidebar-link">Dashboard</a>
</div>
<div class="sidebar-item">
<a href="approvals.php" class="sidebar-link">
Approvals
</a>
</div>
<div class="sidebar-item">
<a href="loans.php" class="sidebar-link active">
Loans
<?php if ($pendingCount > 0): ?>
<span class="sidebar-badge"><?php echo $pendingCount; ?></span>
<?php endif; ?>
</a>
</div>
<div class="sidebar-item">
<a href="departments.php" class="sidebar-link">Departments</a>
</div>
<div class="sidebar-item">
<a href="designations.php" class="sidebar-link">Designations</a>
</div>
<div class="sidebar-item">
<a href="trash.php" class="sidebar-link">Trash</a>
</div>
</div>
<!-- Attendance & Leave -->
<div class="sidebar-section">
<div class="sidebar-section-title"><i class="fas fa-clipboard-list"></i> ATTENDANCE & LEAVE</div>
<div class="sidebar-item">
<a href="attendance.php" class="sidebar-link">Attendance</a>
</div>
<div class="sidebar-item">
<a href="leaves.php" class="sidebar-link">Leaves</a>
</div>
<div class="sidebar-item">
<a href="holidays.php?year=<?php echo date('Y'); ?>" class="sidebar-link">Holidays</a>
</div>
<div class="sidebar-item">
<a href="document_requests.php" class="sidebar-link">Requests</a>
</div>
</div>
<!-- Payroll -->
<div class="sidebar-section">
<div class="sidebar-section-title"><i class="fas fa-wallet"></i> PAYROLL</div>
<div class="sidebar-item">
<a href="salary.php" class="sidebar-link">Salary</a>
</div>
<div class="sidebar-item">
<a href="payroll.php" class="sidebar-link">Run Payroll</a>
</div>
</div>
<!-- HR Modules -->
<div class="sidebar-section">
<div class="sidebar-section-title"><i class="fas fa-cog"></i> HR MODULES</div>
<div class="sidebar-item">
<a href="appraisals.php" class="sidebar-link">Appraisals</a>
</div>
<div class="sidebar-item">
<a href="assets.php" class="sidebar-link">Assets</a>
</div>
<div class="sidebar-item">
<a href="recruitment.php" class="sidebar-link">Recruitment</a>
</div>
<div class="sidebar-item">
<a href="announcements.php" class="sidebar-link">Notices</a>
</div>
</div>
<!-- Reports -->
<div class="sidebar-section">
<div class="sidebar-section-title"><i class="fas fa-chart-bar"></i> REPORTS</div>
<div class="sidebar-item">
<a href="reports.php" class="sidebar-link">Analytics</a>
</div>
</div>
<?php if (is_super_admin()): ?>
<!-- Admin Settings -->
<div class="sidebar-section">
<div class="sidebar-section-title"><i class="fas fa-sliders-h"></i> SETTINGS</div>
<div class="sidebar-item">
<a href="admins.php" class="sidebar-link">Manage Admins</a>
</div>
</div>
<?php endif; ?>
</nav>
</aside>
<!-- MAIN CONTENT -->
<div class="main-content">
<!-- Top Bar -->
<div class="top-bar">
<button class="sidebar-toggle" id="sidebarToggle"><i class="fas fa-bars"></i></button>
<div><h1 class="page-title">Advanced Loan Management</h1></div>
<div class="top-bar-right">
<a href="logout.php" style="color: #cbd5e1; text-decoration: none; padding: 8px 12px; border-radius: 6px; transition: background 0.15s; font-size: 13px; font-weight: 600;" title="Logout">Logout</a>
</div>
</div>
<!-- Content -->
<div class="dashboard-container">
<?php if ($flash): ?>
<div class="alert <?php echo $flash['type'] === 'error' ? 'alert-error' : 'alert-success'; ?>">
<?php echo htmlspecialchars($flash['message'], ENT_QUOTES, 'UTF-8'); ?>
</div>
<?php endif; ?>
<!-- Status Filter -->
<div style="display: flex; gap: 8px; margin-bottom: 24px; flex-wrap: wrap;">
<a href="loans.php?status=pending" class="status-filter-btn <?php echo $status === 'pending' ? 'status-filter-btn-active' : ''; ?>">
<i class="fas fa-hourglass"></i> Pending <?php if ($pendingCount > 0): ?><span class="status-count"><?php echo $pendingCount; ?></span><?php endif; ?>
</a>
<a href="loans.php?status=approved" class="status-filter-btn <?php echo $status === 'approved' ? 'status-filter-btn-active' : ''; ?>">
<i class="fas fa-check-circle"></i> Approved
</a>
<a href="loans.php?status=rejected" class="status-filter-btn <?php echo $status === 'rejected' ? 'status-filter-btn-active' : ''; ?>">
<i class="fas fa-times-circle"></i> Rejected
</a>
<a href="loans.php?status=all" class="status-filter-btn <?php echo $status === 'all' ? 'status-filter-btn-active' : ''; ?>">
<i class="fas fa-list"></i> All
</a>
</div>
<!-- Loans Table -->
<div class="card">
<?php if (empty($loans)): ?>
<p style="text-align: center; color: #9ca3af; padding: 32px;">No loans to display</p>
<?php else: ?>
<div class="table-wrapper">
<table class="table">
<thead>
<tr>
<th>Employee</th>
<th>Amount</th>
<th>Requested Tenure</th>
<th>Status</th>
<th>Applied On</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($loans as $loan): ?>
<tr>
<td>
<strong><?php echo htmlspecialchars($loan['first_name'], ENT_QUOTES, 'UTF-8'); ?> <?php echo htmlspecialchars($loan['last_name'], ENT_QUOTES, 'UTF-8'); ?></strong>
<br><span style="font-size: 12px; color: #9ca3af;"><?php echo htmlspecialchars($loan['phone'], ENT_QUOTES, 'UTF-8'); ?></span>
</td>
<td><strong>₹<?php echo number_format($loan['loan_amount'], 2); ?></strong></td>
<td><?php echo $loan['requested_tenure_months']; ?> months</td>
<td>
<?php
$statusColor = [
'pending' => '#f59e0b',
'approved' => '#10b981',
'rejected' => '#ef4444',
'completed' => '#6b7280',
'cancelled' => '#9ca3af'
][$loan['approval_status']] ?? '#6b7280';
?>
<span style="background: <?php echo $statusColor; ?>; color: white; padding: 2px 8px; border-radius: 4px; font-size: 12px;">
<?php echo ucfirst($loan['approval_status']); ?>
</span>
</td>
<td><?php echo date('d M Y', strtotime($loan['requested_at'])); ?></td>
<td>
<a href="loan-detail.php?id=<?php echo $loan['id']; ?>" class="button-ghost" style="padding: 4px 8px; font-size: 12px; text-decoration: none; display: inline-flex; gap: 4px; align-items: center;">
<i class="fas fa-eye"></i> View
</a>
<?php if ($loan['approval_status'] === 'pending'): ?>
<button type="button" class="button-ghost" style="padding: 4px 8px; font-size: 12px; cursor: pointer;"
onclick="openApprovalModal(<?php echo $loan['id']; ?>, <?php echo htmlspecialchars($loan['loan_amount'], ENT_QUOTES, 'UTF-8'); ?>, <?php echo htmlspecialchars($loan['requested_tenure_months'], ENT_QUOTES, 'UTF-8'); ?>)">
<i class="fas fa-check"></i> Approve
</button>
<button type="button" class="button-ghost" style="padding: 4px 8px; font-size: 12px; cursor: pointer; color: #fca5a5;"
onclick="openRejectModal(<?php echo $loan['id']; ?>)">
<i class="fas fa-times"></i> Reject
</button>
<?php endif; ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
</div>
</div>
<!-- Approve Modal -->
<div id="approvalModal" style="display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center;">
<div style="background: #111827; border-radius: 8px; padding: 24px; max-width: 400px; width: 90%; box-shadow: 0 10px 40px rgba(0,0,0,0.3);">
<h3 style="margin: 0 0 16px 0; color: #f3f4f6;">Approve Loan Application</h3>
<form method="POST" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>">
<input type="hidden" name="action" value="approve">
<input type="hidden" name="loan_id" id="modal_loan_id">
<div style="margin-bottom: 16px;">
<label style="color: #d1d5db; display: block; margin-bottom: 4px;">Loan Details</label>
<div style="background: #1f2937; padding: 8px; border-left: 3px solid #2563eb; border-radius: 4px; font-size: 12px; color: #9ca3af;">
<div>Amount: <strong style="color: #f3f4f6;" id="modal_amount">₹0</strong></div>
<div>Requested Tenure: <span id="modal_tenure">0</span> months</div>
</div>
</div>
<div style="margin-bottom: 16px;">
<label for="modal_tenure_months" style="color: #d1d5db; display: block; margin-bottom: 4px;">Approved Tenure (months)</label>
<input id="modal_tenure_months" name="tenure_months" type="number" min="3" max="60" step="1"
style="width: 100%; padding: 8px; background: #1f2937; border: 1px solid #374151; color: #f3f4f6; border-radius: 4px;" required>
<div style="font-size: 12px; color: #9ca3af; margin-top: 4px;">
Monthly Installment: <strong style="color: #f3f4f6;" id="modal_monthly">₹0</strong>
</div>
</div>
<div style="display: flex; gap: 10px; margin-top: 24px;">
<button type="submit" class="button" style="background: #10b981; flex: 1;">
<i class="fas fa-check"></i> Approve
</button>
<button type="button" class="button-ghost" style="flex: 1;" onclick="document.getElementById('approvalModal').style.display = 'none';">
Cancel
</button>
</div>
</form>
</div>
</div>
<!-- Reject Modal -->
<div id="rejectModal" style="display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center;">
<div style="background: #111827; border-radius: 8px; padding: 24px; max-width: 400px; width: 90%;">
<h3 style="margin: 0 0 16px 0; color: #f3f4f6;">Reject Loan Application</h3>
<form method="POST">
<input type="hidden" name="csrf_token" value="<?php echo csrf_token(); ?>">
<input type="hidden" name="action" value="reject">
<input type="hidden" name="loan_id" id="reject_loan_id">
<div style="margin-bottom: 16px;">
<label for="reject_reason" style="color: #d1d5db; display: block; margin-bottom: 4px;">Reason for Rejection</label>
<textarea id="reject_reason" name="reason" rows="4" style="width: 100%; padding: 8px; background: #1f2937; border: 1px solid #374151; color: #f3f4f6; border-radius: 4px;" required></textarea>
</div>
<div style="display: flex; gap: 10px; margin-top: 24px;">
<button type="submit" class="button" style="background: #ef4444; flex: 1;">
<i class="fas fa-times"></i> Reject
</button>
<button type="button" class="button-ghost" style="flex: 1;" onclick="document.getElementById('rejectModal').style.display = 'none';">
Cancel
</button>
</div>
</form>
</div>
</div>
<div class="sidebar-overlay" id="sidebarOverlay"></div>
<script>
function openApprovalModal(loanId, amount, tenure) {
document.getElementById('modal_loan_id').value = loanId;
document.getElementById('modal_amount').textContent = '₹' + parseFloat(amount).toLocaleString('en-IN', {minimumFractionDigits: 2});
document.getElementById('modal_tenure').textContent = tenure;
document.getElementById('modal_tenure_months').value = tenure;
updateMonthlyInstallment(amount);
document.getElementById('approvalModal').style.display = 'flex';
}
function openRejectModal(loanId) {
document.getElementById('reject_loan_id').value = loanId;
document.getElementById('rejectModal').style.display = 'flex';
}
function updateMonthlyInstallment(amount) {
const tenureInput = document.getElementById('modal_tenure_months');
const monthlyInput = document.getElementById('modal_monthly');
const tenure = parseInt(tenureInput.value) || 1;
const monthly = (parseFloat(amount) / tenure).toFixed(2);
monthlyInput.textContent = '₹' + parseFloat(monthly).toLocaleString('en-IN', {minimumFractionDigits: 2});
}
document.getElementById('modal_tenure_months')?.addEventListener('input', function() {
const amountText = document.getElementById('modal_amount').textContent;
const amount = parseFloat(amountText.replace('₹', '').replace(/,/g, ''));
updateMonthlyInstallment(amount);
});
// Sidebar toggle
document.getElementById('sidebarToggle')?.addEventListener('click', () => {
document.getElementById('sidebar').classList.toggle('open');
document.getElementById('sidebarOverlay').classList.toggle('open');
});
// Close modals on overlay click
document.getElementById('sidebarOverlay')?.addEventListener('click', () => {
document.getElementById('sidebar').classList.remove('open');
document.getElementById('sidebarOverlay').classList.remove('open');
});
</script>
</body>
</html>