« Back to History
offers_manage.php
|
20260920_164915.php
Initial Domain Snapshot
Copy Code
<?php /* ============================================================================ File: /erp/offers_manage.php Purpose: Offers Management - View, Send, Accept, or Reject Candidate Offers ============================================================================ */ header('X-Frame-Options: SAMEORIGIN'); error_reporting(E_ALL); ini_set('display_errors', '1'); /* ================= AUTH & CONTEXT ================= */ require_once __DIR__ . '/modules/auth/page_acl.php'; $ctx = page_require_access('attendance_dashboard'); $pdo = $ctx['pdo']; $COMPANY_ID = (int)$ctx['company_id']; $u = $ctx['user'] ?? null; function j($s){ return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); } function money0($n){ return number_format((float)$n, 2, '.', ''); } $message = ''; $error = ''; /* ================= HANDLE POST ACTIONS ================= */ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) { $action = $_POST['action']; $offer_id = (int)($_POST['offer_id'] ?? 0); $app_id = (int)($_POST['application_id'] ?? 0); try { $pdo->beginTransaction(); // Update Offer Status and log history accordingly if ($action === 'update_offer_status') { $new_offer_status = trim($_POST['new_offer_status']); // 'accepted', 'rejected', 'sent' $remarks = trim($_POST['remarks'] ?? ''); // 1. Update status in offers table $stmt = $pdo->prepare("UPDATE offers SET offer_status = ?, remarks = ? WHERE id = ? AND company_id = ?"); $stmt->execute([$new_offer_status, $remarks, $offer_id, $COMPANY_ID]); // 2. Map offer status to global application status column: application_status $new_app_status = 'Offered'; if ($new_offer_status === 'rejected') { $new_app_status = 'Rejected'; } // Update main job applications column name: application_status $stmt = $pdo->prepare("UPDATE job_applications SET application_status = ? WHERE id = ? AND company_id = ?"); $stmt->execute([$new_app_status, $app_id, $COMPANY_ID]); // 3. Log into status history trail $log_remarks = "Offer status changed to " . strtoupper($new_offer_status) . ". " . $remarks; $stmt = $pdo->prepare("INSERT INTO candidate_status_history (company_id, application_id, old_status, new_status, remarks) VALUES (?, ?, ?, ?, ?)"); $stmt->execute([$COMPANY_ID, $app_id, 'Offered', $new_app_status, $log_remarks]); $message = "Offer status successfully update karke record sync kar diya gaya hai."; } $pdo->commit(); } catch (Exception $e) { $pdo->rollBack(); $error = "Offer Action Error: " . $e->getMessage(); } } /* ================= FETCH ALL OFFERS WITH ISOLATED DATA LOOKUPS ================= */ try { // Base offers listing pull to avoid cross reference SQL breakdowns $sql = "SELECT * FROM offers WHERE company_id = ? ORDER BY id DESC"; $stmt = $pdo->prepare($sql); $stmt->execute([$COMPANY_ID]); $raw_offers = $stmt->fetchAll(PDO::FETCH_ASSOC); $offers = []; foreach ($raw_offers as $of) { // 1. Job Application Safe Pull $ja_stmt = $pdo->prepare("SELECT candidate_id, job_id FROM job_applications WHERE id = ?"); $ja_stmt->execute([$of['application_id']]); $app = $ja_stmt->fetch(PDO::FETCH_ASSOC); if (!$app) { continue; // Skip orphan entries } // 2. Candidate Info Lookup $c_stmt = $pdo->prepare("SELECT * FROM candidates WHERE id = ?"); $c_stmt->execute([$app['candidate_id']]); $cand = $c_stmt->fetch(PDO::FETCH_ASSOC); $resolved_name = 'Unknown'; if (!empty($cand)) { if (isset($cand['name'])) { $resolved_name = $cand['name']; } elseif (isset($cand['candidate_name'])) { $resolved_name = $cand['candidate_name']; } } $resolved_mobile = $cand['mobile'] ?? ($cand['candidate_mobile'] ?? '-'); // 3. Job Title and Code mapping (Using actual 'title' column name) $j_stmt = $pdo->prepare("SELECT title, job_code FROM jobs WHERE id = ?"); $j_stmt->execute([$app['job_id']]); $job = $j_stmt->fetch(PDO::FETCH_ASSOC); $offers[] = [ 'id' => $of['id'], 'application_id' => $of['application_id'], 'offered_salary' => $of['offered_salary'], 'joining_date' => $of['joining_date'], 'offer_status' => $of['offer_status'], 'remarks' => $of['remarks'], 'candidate_name' => $resolved_name, 'candidate_mobile' => $resolved_mobile, 'job_position' => $job['title'] ?? '-', 'job_code' => $job['job_code'] ?? '-' ]; } } catch (Exception $e) { $error = "Offers load karne me error: " . $e->getMessage(); $offers = []; } /* ================= HEADER ================= */ require_once __DIR__ . '/partials/header.php'; ?> <div class="container-fluid py-4"> <div class="d-flex justify-content-between align-items-center mb-4"> <h4 class="mb-0 fw-bold text-uppercase text-dark">Job Offers Rollout Management</h4> </div> <?php if (!empty($message)): ?> <div class="alert alert-success border-0 shadow-sm mb-4"><i class="bi bi-check-circle-fill me-2"></i> <?= j($message) ?></div> <?php endif; ?> <?php if (!empty($error)): ?> <div class="alert alert-danger border-0 shadow-sm mb-4"><i class="bi bi-exclamation-triangle-fill me-2"></i> <?= j($error) ?></div> <?php endif; ?> <div class="card shadow-sm border-0"> <div class="card-body p-0"> <div class="table-responsive"> <table class="table table-hover align-middle mb-0 text-nowrap"> <thead class="table-light"> <tr> <th class="ps-4">Candidate Name</th> <th>Offered Position</th> <th class="text-end">Monthly Package</th> <th class="text-center">Expected Joining</th> <th class="text-center">Offer Status</th> <th>Internal Remarks</th> <th class="text-end pe-4">Action</th> </tr> </thead> <tbody> <?php if (empty($offers)): ?> <tr> <td colspan="7" class="text-center py-5 text-muted fw-bold">Abhi tak koi offer letters issue nahi kiye gaye hain.</td> </tr> <?php else: ?> <?php foreach ($offers as $of): ?> <tr> <td class="ps-4"> <div class="fw-bold text-dark mb-0"><?= j($of['candidate_name']) ?></div> <div class="text-muted small"><i class="bi bi-telephone"></i> <?= j($of['candidate_mobile']) ?></div> </td> <td> <span class="fw-semibold text-secondary"><?= j($of['job_position']) ?></span> <?php if (!empty($of['job_code']) && $of['job_code'] !== '-'): ?> <span class="badge bg-light text-dark border ms-1"><?= j($of['job_code']) ?></span> <?php endif; ?> </td> <td class="text-end fw-bold text-success"> ₹<?= money0($of['offered_salary']) ?> </td> <td class="text-center fw-semibold text-dark"> <?= $of['joining_date'] ? j(date('d-M-Y', strtotime($of['joining_date']))) : '-' ?> </td> <td class="text-center"> <?php $of_class = 'bg-secondary'; if ($of['offer_status'] === 'draft') $of_class = 'bg-light text-dark border'; if ($of['offer_status'] === 'sent') $of_class = 'bg-primary text-white'; if ($of['offer_status'] === 'accepted') $of_class = 'bg-success text-white'; if ($of['offer_status'] === 'rejected') $of_class = 'bg-danger text-white'; if ($of['offer_status'] === 'expired') $of_class = 'bg-dark text-white'; ?> <span class="badge rounded-pill px-3 py-2 text-uppercase fs-7 <?= $of_class ?>"> <?= j($of['offer_status']) ?> </span> </td> <td class="small text-wrap" style="max-width: 200px;"><?= j($of['remarks'] ?: '-') ?></td> <td class="text-end pe-4"> <div class="d-inline-flex gap-1"> <?php if ($of['offer_status'] === 'sent' || $of['offer_status'] === 'draft'): ?> <button type="button" class="btn btn-sm btn-success fw-bold text-white shadow-xs" onclick="openStatusUpdateModal(<?= (int)$of['id'] ?>, <?= (int)$of['application_id'] ?>, 'accepted')"> <i class="bi bi-person-check-fill"></i> Accept </button> <button type="button" class="btn btn-sm btn-outline-danger fw-bold" onclick="openStatusUpdateModal(<?= (int)$of['id'] ?>, <?= (int)$of['application_id'] ?>, 'rejected')"> <i class="bi bi-person-x-fill"></i> Reject </button> <?php else: ?> <span class="text-muted small italic"><i class="bi bi-lock-fill"></i> Logged</span> <?php endif; ?> </div> </td> </tr> <?php endforeach; ?> <?php endif; ?> </tbody> </table> </div> </div> </div> </div> <div class="modal fade" id="offerActionModal" tabindex="-1" aria-hidden="true"> <div class="modal-dialog modal-dialog-centered"> <form method="POST" class="modal-content border-0 shadow"> <div class="modal-header bg-dark text-white"> <h5 class="modal-title fw-bold text-uppercase fs-6">Update Offer Decision to: <span id="targetStatusText" class="text-warning"></span></h5> <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button> </div> <div class="modal-body"> <input type="hidden" name="action" value="update_offer_status"> <input type="hidden" name="offer_id" id="modal_offer_id"> <input type="hidden" name="application_id" id="modal_app_id"> <input type="hidden" name="new_offer_status" id="modal_new_status"> <div class="mb-3"> <label class="form-label fw-semibold">Offer Remarks / Reason Log <span class="text-danger">*</span></label> <textarea class="form-control" name="remarks" rows="3" placeholder="Candidate terms, response notes, joining adjustments..." required></textarea> </div> </div> <div class="modal-footer bg-light"> <button type="button" class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancel</button> <button type="submit" class="btn btn-primary btn-sm fw-bold px-3">Confirm Update</button> </div> </form> </div> </div> <script> function openStatusUpdateModal(offerId, appId, targetStatus) { document.getElementById('modal_offer_id').value = offerId; document.getElementById('modal_app_id').value = appId; document.getElementById('modal_new_status').value = targetStatus; document.getElementById('targetStatusText').innerText = targetStatus.toUpperCase(); const myModal = new bootstrap.Modal(document.getElementById('offerActionModal')); myModal.show(); } </script> <?php /* ================= FOOTER ================= */ require_once __DIR__ . '/partials/footer.php'; ?>