« Back to History
department_payment.php
|
20260920_164915.php
Initial Domain Snapshot
Copy Code
<?php /* ============================================================================= File: department_payment.php Purpose: Department-wise Bulk Payment (Employee) - Bootstrap Updated ============================================================================= */ header('X-Frame-Options: SAMEORIGIN'); error_reporting(E_ALL); ini_set('display_errors', 1); /* ---------------- AUTH + CTX ---------------- */ require_once __DIR__ . '/modules/auth/page_acl.php'; $ctx = page_require_access('department_payment'); $pdo = $ctx['pdo']; $company_id = (int)$ctx['company_id']; $user_id = (int)$ctx['user']['id']; require_once __DIR__ . '/helpers/activity_helper.php'; if (!function_exists('h')) { function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } } /* ---------------- CSRF ---------------- */ if (session_status() !== PHP_SESSION_ACTIVE) session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(16)); } function csrf_field(){ echo '<input type="hidden" name="csrf_token" value="'.h($_SESSION['csrf_token']).'">'; } function check_csrf(){ if (($_POST['csrf_token'] ?? '') !== ($_SESSION['csrf_token'] ?? '')) { http_response_code(403); exit('Bad CSRF'); } } /* ================= AJAX: LOAD EMPLOYEES ================= */ if (isset($_GET['ajax']) && $_GET['ajax']==='employees') { $dept = (int)($_GET['department_id'] ?? 0); $sql = "SELECT id, name FROM company_employee_master WHERE company_id = ? AND COALESCE(is_active,1) = 1"; $params = [$company_id]; if ($dept > 0) { $sql .= " AND department_id = ? "; $params[] = $dept; } $sql .= " ORDER BY name"; $st = $pdo->prepare($sql); $st->execute($params); header('Content-Type: application/json'); echo json_encode($st->fetchAll(PDO::FETCH_ASSOC)); exit; } /* ================= UI DATA ================= */ $departments = $pdo->prepare("SELECT id, name FROM company_departments WHERE company_id = ? AND is_active = 1 ORDER BY name"); $departments->execute([$company_id]); $departments = $departments->fetchAll(PDO::FETCH_ASSOC); /* ================= POST: SAVE + EXPORT ================= */ $msg = ''; if ($_SERVER['REQUEST_METHOD']==='POST') { check_csrf(); $department_id = (int)($_POST['department_id'] ?? 0); $payment_type = $_POST['payment_type'] ?? ''; $payment_mode = $_POST['payment_mode'] ?? 'BANK'; $pay_month = $_POST['pay_month'] ?? ''; $remark = trim($_POST['remark'] ?? ''); $rows = json_decode($_POST['rows_json'] ?? '[]', true); if ($department_id<=0 || $pay_month==='' || !is_array($rows)) { exit('Invalid input'); } if (!in_array($payment_type, ['advance','salary','extra','other'], true)) { exit('Invalid payment type'); } $payment_date = $pay_month.'-01'; $pdo->beginTransaction(); try { foreach ($rows as $r) { $eid = (int)($r['employee_id'] ?? 0); $amt = (float)($r['amount'] ?? 0); if ($eid<=0 || $amt<=0) continue; if ($payment_type === 'advance') { $pdo->prepare("INSERT INTO employee_advance (company_id, employee_id, amount, date, remark, deduct_parts, remaining_amount, status, created_by, created_at) VALUES (?,?,?,?,?,1,?,'OPEN',?,NOW())") ->execute([$company_id, $eid, $amt, $payment_date, $remark, $amt, $user_id]); } $pdo->prepare("INSERT INTO payments (company_id, person_type, person_id, payment_type, amount, payment_date, payment_mode, remark, created_by, created_at) VALUES (?,?,?,?,?,?,?,?,?,NOW())") ->execute([$company_id, 'employee', $eid, $payment_type, $amt, $payment_date, $payment_mode, $remark, $user_id]); } $pdo->commit(); activity_create('payment', 'department_payment_create', $department_id, 'Saved department bulk payments'); if (isset($_POST['do_export'])) { $_POST['salary_rows'] = json_encode($rows, JSON_UNESCAPED_UNICODE); require __DIR__ . '/expoeter_company_employee_master.php'; exit; } $msg = 'Department payment saved successfully'; } catch (Exception $e) { $pdo->rollBack(); $msg = 'Error: ' . $e->getMessage(); } } require_once __DIR__.'/partials/header.php'; ?> <div class="container py-4"> <div class="card border-0 shadow-sm"> <div class="card-header bg-primary text-white py-3"> <h5 class="mb-0"><i class="bi bi-people-fill me-2"></i>Department Bulk Payment</h5> </div> <div class="card-body p-4"> <?php if(!empty($msg)): ?> <div class="alert alert-success alert-dismissible fade show"> <?= h($msg) ?> <button type="button" class="btn-close" data-bs-dismiss="alert"></button> </div> <?php endif; ?> <form method="post" id="payForm"> <?php csrf_field(); ?> <div class="row g-3"> <div class="col-md-4"> <label class="form-label fw-bold">Department</label> <select name="department_id" id="department_id" class="form-select border-primary-subtle shadow-sm" required> <option value="">Select Department</option> <?php foreach($departments as $d): ?> <option value="<?= (int)$d['id'] ?>"><?= h($d['name']) ?></option> <?php endforeach; ?> </select> </div> <div class="col-md-4"> <label class="form-label fw-bold">Payment Month</label> <input type="month" name="pay_month" class="form-control" value="<?= date('Y-m') ?>" required> </div> <div class="col-md-2"> <label class="form-label fw-bold">Type</label> <select name="payment_type" class="form-select"> <option value="salary">Salary</option> <option value="advance">Advance</option> <option value="extra">Extra</option> <option value="other">Other</option> </select> </div> <div class="col-md-2"> <label class="form-label fw-bold">Mode</label> <select name="payment_mode" class="form-select fw-bold"> <option>BANK</option> <option>CASH</option> <option>UPI</option> <option>CHEQUE</option> </select> </div> <div class="col-md-4"> <label class="form-label fw-bold">Bulk Amount Control</label> <div class="input-group"> <select id="same_amount" class="form-select bg-light" style="max-width: 100px;"> <option value="1">Same</option> <option value="0">Diff</option> </select> <input type="number" step="0.01" id="same_amt" class="form-control fw-bold text-success" placeholder="Enter bulk amount" value="0"> </div> <div class="form-text small">Select 'Same' to apply this amount to all employees below.</div> </div> <div class="col-md-8"> <label class="form-label fw-bold">Remark</label> <input type="text" name="remark" class="form-control" placeholder="Optional remark for all entries"> </div> </div> <hr class="my-4 opacity-10"> <div class="table-responsive border rounded bg-white mb-4"> <table class="table table-hover align-middle mb-0" id="empTable"> <thead class="table-light"> <tr> <th class="ps-4">Employee Name</th> <th class="text-end pe-4" style="width: 250px;">Payment Amount</th> </tr> </thead> <tbody> <tr> <td colspan="2" class="text-center py-4 text-muted italic">Select a department to load employees</td> </tr> </tbody> </table> </div> <input type="hidden" name="rows_json" id="rows_json"> <div class="d-flex justify-content-end gap-2"> <button type="submit" class="btn btn-outline-primary px-4 btn-lg shadow-sm"> <i class="bi bi-save me-2"></i>Save Only </button> <button type="submit" name="do_export" value="1" class="btn btn-primary px-4 btn-lg shadow-sm fw-bold"> <i class="bi bi-file-earmark-excel me-2"></i>Save & Export </button> </div> </form> </div> </div> </div> <script> const deptSel = document.getElementById('department_id'); const tbody = document.querySelector('#empTable tbody'); const sameSel = document.getElementById('same_amount'); const sameAmt = document.getElementById('same_amt'); const rowsInp = document.getElementById('rows_json'); function updateInputState() { const isSame = sameSel.value === '1'; sameAmt.disabled = !isSame; document.querySelectorAll('.emp-amt').forEach(inp => { inp.disabled = isSame; if(isSame) inp.value = sameAmt.value; }); } sameSel.onchange = updateInputState; sameAmt.oninput = updateInputState; deptSel.onchange = () => { tbody.innerHTML = '<tr><td colspan="2" class="text-center py-4"><div class="spinner-border spinner-border-sm text-primary"></div> Loading...</td></tr>'; if(!deptSel.value) { tbody.innerHTML = '<tr><td colspan="2" class="text-center py-4 text-muted">Select a department</td></tr>'; return; } fetch(`department_payment.php?ajax=employees&department_id=${deptSel.value}`) .then(r=>r.json()) .then(list=>{ tbody.innerHTML = ''; if(list.length === 0) { tbody.innerHTML = '<tr><td colspan="2" class="text-center py-4 text-danger">No active employees found in this department</td></tr>'; return; } list.forEach(e=>{ const tr = document.createElement('tr'); tr.dataset.eid = e.id; tr.innerHTML = ` <td class="ps-4 fw-medium">${e.name}</td> <td class="pe-4"> <div class="input-group input-group-sm justify-content-end"> <span class="input-group-text bg-white">₹</span> <input type="number" step="0.01" class="form-control text-end fw-bold emp-amt" value="0" style="max-width: 150px;"> </div> </td>`; tbody.appendChild(tr); }); updateInputState(); }); }; document.getElementById('payForm').onsubmit = (e) => { let rows = []; const rowsFound = document.querySelectorAll('#empTable tbody tr[data-eid]'); if(rowsFound.length === 0) { alert("Please select a department with employees first."); e.preventDefault(); return; } rowsFound.forEach(tr=>{ rows.push({ employee_id: tr.dataset.eid, amount: sameSel.value==='1' ? sameAmt.value : tr.querySelector('.emp-amt').value }); }); rowsInp.value = JSON.stringify(rows); }; </script> <?php require_once __DIR__.'/partials/footer.php'; ?>