PYBS (Personel Yönetim Bilgi Sistemi) / Ramsa/modules/log-izleme.php
log-izleme.php 356 satır • 16.81 KB
<?php
// modules/log-izleme.php
session_start();
require_once '../config/db.php';
require_once '../config/functions.php';

// Sadece ROOT yetkisine sahip kişi görebilir.
yetkiKontrol(['root']);

// --- YARDIMCI FONKSİYON: ETKİLENEN PERSONELİ BUL ---
function etkilenenPersonelBul($pdo, $tablo, $id) {
    if (!$id || !$tablo) return null;
    
    try {
        $sql = "";
        if ($tablo == 'kullanicilar') {
            $sql = "SELECT id, ad, soyad FROM kullanicilar WHERE id = ?";
        } elseif ($tablo == 'calisma_donemleri') {
            $sql = "SELECT k.id, k.ad, k.soyad FROM calisma_donemleri d JOIN kullanicilar k ON d.calisan_id = k.id WHERE d.id = ?";
        } elseif (in_array($tablo, ['izin_talepleri', 'mesai_hareketleri', 'avans_hareketleri', 'maas_gecmisi'])) {
            $sql = "SELECT k.id, k.ad, k.soyad FROM $tablo t JOIN kullanicilar k ON t.calisan_id = k.id WHERE t.id = ?";
        }

        if ($sql) {
            $stmt = $pdo->prepare($sql);
            $stmt->execute([$id]);
            $res = $stmt->fetch(PDO::FETCH_ASSOC);
            if ($res) {
                return "<span class='text-primary fw-bold'><i class='fas fa-user-tag'></i> {$res['ad']} {$res['soyad']} (ID: {$res['id']})</span>";
            }
        }
        return "<span class='text-muted fst-italic'>(Kayıt silinmiş veya bulunamadı)</span>";
    } catch (Exception $e) {
        return "<span class='text-danger'>Hata</span>";
    }
}

// --- FİLTRELEME PARAMETRELERİ ---
$where = "WHERE 1=1";
$params = [];

if (!empty($_GET['islem_tipi'])) { 
    $where .= " AND l.islem_tipi = :tip"; 
    $params[':tip'] = $_GET['islem_tipi']; 
}
if (!empty($_GET['tablo_adi'])) { 
    $where .= " AND l.tablo_adi = :tbl"; 
    $params[':tbl'] = $_GET['tablo_adi']; 
}
if (!empty($_GET['kullanici_adi'])) { 
    $where .= " AND k.kullanici_adi LIKE :kadi"; 
    $params[':kadi'] = '%' . $_GET['kullanici_adi'] . '%'; 
}
if (!empty($_GET['baslangic'])) { 
    $where .= " AND l.tarih >= :bas"; 
    $params[':bas'] = $_GET['baslangic'] . " 00:00:00"; 
}
if (!empty($_GET['bitis'])) { 
    $where .= " AND l.tarih <= :bit"; 
    $params[':bit'] = $_GET['bitis'] . " 23:59:59"; 
}

// --- EXCEL ÇIKTISI ---
if (isset($_GET['format']) && $_GET['format'] == 'excel') {
    $filename = "Sistem_Loglari_" . date('Y-m-d_H-i') . ".xls";
    header("Content-Type: application/vnd.ms-excel; charset=utf-8");
    header("Content-Disposition: attachment; filename=$filename");
    echo "\xEF\xBB\xBF"; 
    
    $sql = "SELECT l.*, k.kullanici_adi, k.ad, k.soyad 
            FROM sistem_loglari l 
            LEFT JOIN kullanicilar k ON l.kullanici_id = k.id 
            $where ORDER BY l.id DESC";
    $stmt = $pdo->prepare($sql);
    $stmt->execute($params);
    $tum_loglar = $stmt->fetchAll();
    ?>
    <table border="1">
        <thead>
            <tr style="background-color:#ccc;">
                <th>Log ID</th><th>Tarih</th><th>İşlemi Yapan</th><th>İşlem Tipi</th><th>Modül/Tablo</th><th>Açıklama & Etkilenen Personel</th><th>IP Adresi</th>
            </tr>
        </thead>
        <tbody>
            <?php foreach($tum_loglar as $log): 
                $etkilenen = strip_tags(etkilenenPersonelBul($pdo, $log['tablo_adi'], $log['kayit_id']));
            ?>
            <tr>
                <td><?php echo $log['id']; ?></td>
                <td><?php echo $log['tarih']; ?></td>
                <td><?php echo $log['kullanici_adi'] . ' (' . $log['ad'] . ' ' . $log['soyad'] . ')'; ?></td>
                <td><?php echo $log['islem_tipi']; ?></td>
                <td><?php echo $log['tablo_adi']; ?></td>
                <td><?php echo $log['aciklama'] . " - " . $etkilenen; ?></td>
                <td><?php echo $log['ip_adresi']; ?></td>
            </tr>
            <?php endforeach; ?>
        </tbody>
    </table>
    <?php
    exit;
}

include '../includes/header.php';
include '../includes/menu.php';

// --- SAYFALAMA ---
$sayfa = isset($_GET['sayfa']) ? (int)$_GET['sayfa'] : 1;
$limit = 50; 
$offset = ($sayfa - 1) * $limit;

// Toplam Sayı
$sql_count = "SELECT COUNT(*) FROM sistem_loglari l LEFT JOIN kullanicilar k ON l.kullanici_id = k.id $where";
$stmt_count = $pdo->prepare($sql_count);
$stmt_count->execute($params);
$toplam_kayit = $stmt_count->fetchColumn();
$toplam_sayfa = ceil($toplam_kayit / $limit);

// Verileri Çek
$sql = "SELECT l.*, k.kullanici_adi, k.ad, k.soyad 
        FROM sistem_loglari l 
        LEFT JOIN kullanicilar k ON l.kullanici_id = k.id 
        $where 
        ORDER BY l.id DESC 
        LIMIT $limit OFFSET $offset";

$stmt = $pdo->prepare($sql);
$stmt->execute($params);
$loglar = $stmt->fetchAll();

// URL Oluşturucu
function urlOlustur($sayfa_no) {
    $q = $_GET; 
    $q['sayfa'] = $sayfa_no;
    return '?' . http_build_query($q);
}
?>

<style>
    @media print {
        body * { visibility: hidden; }
        #printableArea, #printableArea * { visibility: visible; }
        #printableArea { position: absolute; left: 0; top: 0; width: 100%; }
        .no-print { display: none !important; }
        .card-box { border: none !important; box-shadow: none !important; }
        .table { font-size: 10px !important; }
        .badge { border: 1px solid #000; color: #000 !important; background: none !important; }
    }
    .json-pre { max-height: 300px; overflow-y: auto; font-size: 0.75rem; background-color: #2d2d2d; color: #f8f8f2; padding: 10px; border-radius: 5px; }
    .badge-info { background-color: #17a2b8; }
    .badge-danger { background-color: #dc3545; }
    .badge-success { background-color: #28a745; }
    .badge-warning { background-color: #ffc107; }
    .badge-primary { background-color: #007bff; }
    .badge-secondary { background-color: #6c757d; }
</style>

<div class="container-fluid">
    <div class="d-flex justify-content-between align-items-center mb-4">
        <h3><i class="fas fa-history text-primary"></i> Sistem Log İzleme</h3>
        <div class="d-flex gap-2 no-print">
            <a href="?format=excel" class="btn btn-sm btn-success"><i class="fas fa-file-excel"></i> Excel</a>
        </div>
    </div>

    <div class="card shadow-sm border-0">
        <div class="card-body">
            <!-- FİLTRE FORMU -->
            <form method="GET" id="filterForm" class="row g-2 mb-4">
                <div class="col-md-2">
                    <label class="form-label small">İşlem Tipi</label>
                    <select name="islem_tipi" class="form-select form-select-sm">
                        <option value="">Tümü</option>
                        <option value="ekleme" <?= ($_GET['islem_tipi']??'') == 'ekleme' ? 'selected' : '' ?>>Ekleme</option>
                        <option value="guncelleme" <?= ($_GET['islem_tipi']??'') == 'guncelleme' ? 'selected' : '' ?>>Güncelleme</option>
                        <option value="silme" <?= ($_GET['islem_tipi']??'') == 'silme' ? 'selected' : '' ?>>Silme</option>
                        <option value="işe_alim" <?= ($_GET['islem_tipi']??'') == 'işe_alim' ? 'selected' : '' ?>>İşe Alım</option>
                        <option value="isten_cikarma" <?= ($_GET['islem_tipi']??'') == 'isten_cikarma' ? 'selected' : '' ?>>İşten Çıkarma</option>
                        <option value="maas_guncelleme" <?= ($_GET['islem_tipi']??'') == 'maas_guncelleme' ? 'selected' : '' ?>>Maaş Güncelleme</option>
                    </select>
                </div>
                <div class="col-md-2">
                    <label class="form-label small">Modül/Tablo</label>
                    <select name="tablo_adi" class="form-select form-select-sm">
                        <option value="">Tümü</option>
                        <option value="kullanicilar" <?= ($_GET['tablo_adi']??'') == 'kullanicilar' ? 'selected' : '' ?>>Personel</option>
                        <option value="calisma_donemleri" <?= ($_GET['tablo_adi']??'') == 'calisma_donemleri' ? 'selected' : '' ?>>Çalışma Dönemleri</option>
                        <option value="izin_talepleri" <?= ($_GET['tablo_adi']??'') == 'izin_talepleri' ? 'selected' : '' ?>>İzin Talepleri</option>
                        <option value="mesai_hareketleri" <?= ($_GET['tablo_adi']??'') == 'mesai_hareketleri' ? 'selected' : '' ?>>Mesai</option>
                        <option value="maas_gecmisi" <?= ($_GET['tablo_adi']??'') == 'maas_gecmisi' ? 'selected' : '' ?>>Maaş Geçmişi</option>
                    </select>
                </div>
                <div class="col-md-2">
                    <label class="form-label small">İşlemi Yapan</label>
                    <input type="text" name="kullanici_adi" class="form-control form-control-sm" placeholder="Kullanıcı adı" value="<?= $_GET['kullanici_adi']??'' ?>">
                </div>
                <div class="col-md-2">
                    <label class="form-label small">Başlangıç</label>
                    <input type="date" name="baslangic" class="form-control form-control-sm" value="<?= $_GET['baslangic']??'' ?>">
                </div>
                <div class="col-md-2">
                    <label class="form-label small">Bitiş</label>
                    <input type="date" name="bitis" class="form-control form-control-sm" value="<?= $_GET['bitis']??'' ?>">
                </div>
                <div class="col-md-2 d-flex align-items-end gap-1">
                    <button type="submit" class="btn btn-primary btn-sm flex-grow-1">Filtrele</button>
                    <a href="log-izleme.php" class="btn btn-secondary btn-sm">Temizle</a>
                </div>
                <input type="hidden" name="format" id="exportFormat" value="">
            </form>

            <!-- TABLO -->
            <div class="table-responsive">
                <table class="table table-hover table-sm align-middle">
                    <thead class="table-light">
                        <tr>
                            <th>ID</th>
                            <th>Tarih</th>
                            <th>İşlemi Yapan</th>
                            <th>İşlem Tipi</th>
                            <th>Modül/Tablo</th>
                            <th>Açıklama</th>
                            <th>Etkilenen</th>
                            <th>IP</th>
                            <th>Detay</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php if(empty($loglar)): ?>
                            <tr><td colspan="9" class="text-center p-4 text-muted">Kayıt bulunamadı.</td></tr>
                        <?php else: ?>
                            <?php foreach($loglar as $log): 
                                $tip_badge = match($log['islem_tipi']) {
                                    'ekleme' => 'badge-success',
                                    'guncelleme' => 'badge-info',
                                    'silme' => 'badge-danger',
                                    'işe_alim' => 'badge-success',
                                    'isten_cikarma' => 'badge-danger',
                                    'maas_guncelleme' => 'badge-warning',
                                    default => 'badge-secondary'
                                };
                                $etkilenen = etkilenenPersonelBul($pdo, $log['tablo_adi'], $log['kayit_id']);
                            ?>
                            <tr>
                                <td><?= $log['id'] ?></td>
                                <td><?= date('d.m.Y H:i', strtotime($log['tarih'])) ?></td>
                                <td><?= htmlspecialchars($log['kullanici_adi'] ?? 'Sistem') ?> 
                                    <?php if($log['ad'] && $log['soyad']): ?>
                                        <small class="text-muted">(<?= $log['ad'] . ' ' . $log['soyad'] ?>)</small>
                                    <?php endif; ?>
                                </td>
                                <td><span class="badge <?= $tip_badge ?>"><?= $log['islem_tipi'] ?></span></td>
                                <td><?= htmlspecialchars($log['tablo_adi'] ?? '-') ?></td>
                                <td><?= htmlspecialchars($log['aciklama']) ?></td>
                                <td><?= $etkilenen ?></td>
                                <td><?= htmlspecialchars($log['ip_adresi'] ?? '-') ?></td>
                                <td>
                                    <?php if($log['eski_veri'] || $log['yeni_veri']): ?>
                                        <button class="btn btn-sm btn-outline-info detay-btn" 
                                                data-bs-toggle="modal" data-bs-target="#logDetayModal"
                                                data-eski='<?= htmlspecialchars($log['eski_veri'] ?? '') ?>'
                                                data-yeni='<?= htmlspecialchars($log['yeni_veri'] ?? '') ?>'>
                                            <i class="fas fa-eye"></i>
                                        </button>
                                    <?php endif; ?>
                                </td>
                            </tr>
                            <?php endforeach; ?>
                        <?php endif; ?>
                    </tbody>
                </table>
            </div>

            <!-- SAYFALAMA -->
            <?php if($toplam_sayfa > 1): ?>
            <nav aria-label="Sayfalama" class="mt-3 no-print">
                <ul class="pagination pagination-sm justify-content-center">
                    <li class="page-item <?= ($sayfa <= 1) ? 'disabled' : '' ?>">
                        <a class="page-link" href="<?= urlOlustur($sayfa-1) ?>">&laquo;</a>
                    </li>
                    <?php for($s=1; $s<=$toplam_sayfa; $s++): 
                        if ($s == 1 || $s == $toplam_sayfa || ($s >= $sayfa-2 && $s <= $sayfa+2)): ?>
                            <li class="page-item <?= ($sayfa == $s) ? 'active' : '' ?>">
                                <a class="page-link" href="<?= urlOlustur($s) ?>"><?= $s ?></a>
                            </li>
                        <?php elseif($s == $sayfa-3 || $s == $sayfa+3): ?>
                            <li class="page-item disabled"><span class="page-link">...</span></li>
                        <?php endif; 
                    endfor; ?>
                    <li class="page-item <?= ($sayfa >= $toplam_sayfa) ? 'disabled' : '' ?>">
                        <a class="page-link" href="<?= urlOlustur($sayfa+1) ?>">&raquo;</a>
                    </li>
                </ul>
            </nav>
            <?php endif; ?>
        </div>
    </div>
</div>

<!-- MODAL -->
<div class="modal fade" id="logDetayModal" tabindex="-1" aria-hidden="true">
    <div class="modal-dialog modal-lg modal-dialog-scrollable">
        <div class="modal-content">
            <div class="modal-header bg-dark text-white">
                <h5 class="modal-title">Veri Değişiklik Detayı</h5>
                <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body bg-light">
                <div class="row g-3">
                    <div class="col-md-6">
                        <div class="card border-danger h-100">
                            <div class="card-header bg-danger text-white py-2">Eski Veri</div>
                            <div class="card-body p-0">
                                <pre id="eskiVeriIcerik" class="json-pre mb-0"></pre>
                            </div>
                        </div>
                    </div>
                    <div class="col-md-6">
                        <div class="card border-success h-100">
                            <div class="card-header bg-success text-white py-2">Yeni Veri</div>
                            <div class="card-body p-0">
                                <pre id="yeniVeriIcerik" class="json-pre mb-0"></pre>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Kapat</button>
            </div>
        </div>
    </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', function() {
    const detayBtns = document.querySelectorAll('.detay-btn');
    const eskiDiv = document.getElementById('eskiVeriIcerik');
    const yeniDiv = document.getElementById('yeniVeriIcerik');

    detayBtns.forEach(btn => {
        btn.addEventListener('click', function() {
            let eski = this.getAttribute('data-eski');
            let yeni = this.getAttribute('data-yeni');
            try {
                if(eski) eski = JSON.stringify(JSON.parse(eski), null, 2);
                if(yeni) yeni = JSON.stringify(JSON.parse(yeni), null, 2);
            } catch(e) {}
            eskiDiv.textContent = eski || "Veri yok / Değişiklik yok.";
            yeniDiv.textContent = yeni || "Veri yok.";
        });
    });
});
</script>

<?php include '../includes/footer.php'; ?>