PYBS (Personel Yönetim Bilgi Sistemi) / Ramsa/modules/puantaj-cetveli.php
puantaj-cetveli.php 417 satır • 20.98 KB
<?php
// modules/puantaj-cetveli.php
session_start();
require_once '../config/db.php';
require_once '../config/functions.php';

// Yetkiler
yetkiKontrol(['root', 'yonetici', 'muhasebe', 'insan_kaynaklari']);

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

// --- FİLTRELER ---
$yil = guvenlik($_GET['yil'] ?? date('Y'));
$ay = guvenlik($_GET['ay'] ?? date('m'));
$rol_filtre = guvenlik($_GET['rol'] ?? 'tumu');
$personel_id = guvenlik($_GET['personel_id'] ?? 'tumu');

$gun_sayisi = cal_days_in_month(CAL_GREGORIAN, $ay, $yil);
$month_start = "$yil-$ay-01";
$month_end   = date("Y-m-t", strtotime($month_start));

// --- PERSONEL LİSTESİ ÇEKME ---
$sql_per = "SELECT * FROM kullanicilar WHERE rol != 'root'";
if ($rol_filtre != 'tumu') $sql_per .= " AND rol = '$rol_filtre'";
if ($personel_id != 'tumu') $sql_per .= " AND id = " . (int)$personel_id;
$sql_per .= " ORDER BY ad ASC";
$tum_personeller = $pdo->query($sql_per)->fetchAll();

// --- FİLTRELEME ---
$personeller = [];
foreach ($tum_personeller as $p) {
    $giris = $p['ise_giris_tarihi'];
    $cikis = $p['isten_cikis_tarihi'];
    $is_active = true;
    if ($giris > $month_end) $is_active = false;
    if (!empty($cikis) && $cikis < $month_start) $is_active = false;
    
    if (!$is_active) {
        $has_mesai = $pdo->query("SELECT COUNT(*) FROM mesai_hareketleri WHERE calisan_id={$p['id']} AND tarih BETWEEN '$month_start' AND '$month_end' AND durum='onaylandi'")->fetchColumn();
        $has_izin = $pdo->query("SELECT COUNT(*) FROM izin_talepleri WHERE calisan_id={$p['id']} AND durum='onaylandi' AND (baslangic_tarihi <= '$month_end 23:59:59' AND bitis_tarihi >= '$month_start 00:00:00')")->fetchColumn();
        if ($has_mesai > 0 || $has_izin > 0) $is_active = true;
    }
    if ($is_active) $personeller[] = $p;
}

// --- SİSTEM VERİLERİ ---
$tatiller = $pdo->query("SELECT tarih FROM resmi_tatiller")->fetchAll(PDO::FETCH_COLUMN);
$gunluk_saat_std = (float)($pdo->query("SELECT ayar_degeri FROM site_ayarlari WHERE ayar_anahtari = 'gunluk_mesai_saati'")->fetchColumn() ?: 9);
$tum_liste_select = $pdo->query("SELECT id, ad, soyad FROM kullanicilar WHERE rol != 'root' ORDER BY ad ASC")->fetchAll();

$aylar_tr_uzun = ['01'=>'Ocak', '02'=>'Şubat', '03'=>'Mart', '04'=>'Nisan', '05'=>'Mayıs', '06'=>'Haziran', '07'=>'Temmuz', '08'=>'Ağustos', '09'=>'Eylül', '10'=>'Ekim', '11'=>'Kasım', '12'=>'Aralık'];

function gunIsmi($tarih) {
    $gunler = ['Mon'=>'Pzt', 'Tue'=>'Sal', 'Wed'=>'Çar', 'Thu'=>'Per', 'Fri'=>'Cum', 'Sat'=>'Cts', 'Sun'=>'Pzr'];
    return $gunler[date('D', strtotime($tarih))];
}
function tarihFormatOzel($tarih_str) {
    global $aylar_tr_uzun;
    $d = date('d', strtotime($tarih_str));
    $m = date('m', strtotime($tarih_str));
    $y = date('Y', strtotime($tarih_str));
    return $d . ' ' . $aylar_tr_uzun[$m] . ' ' . $y;
}

$puantaj_datasi = []; 
$ucretsiz_izinler = ['hastalik', 'saatlik', 'mazeret', 'ucretsiz', 'mesaiye_gelmedi'];

foreach($personeller as $per) {
    $pid = $per['id'];
    $ise_giris = $per['ise_giris_tarihi'];
    $isten_cikis = $per['isten_cikis_tarihi'];

    for($d=1; $d<=$gun_sayisi; $d++) {
        $g_tarih = "$yil-$ay-" . sprintf('%02d', $d);
        $haftanin_gunu = date('N', strtotime($g_tarih));
        
        $gun_aktif = true;
        if ($g_tarih < $ise_giris) $gun_aktif = false;
        elseif (!empty($isten_cikis) && $g_tarih > $isten_cikis) $gun_aktif = false;

        $is_resmi_tatil = in_array($g_tarih, $tatiller);
        $is_haftasonu = ($haftanin_gunu >= 6); 
        $is_pazar = ($haftanin_gunu == 7);

        // --- GÜNCELLENEN KISIM: TÜM İZİNLERİ ÇEK (fetchAll) ---
        $stmt_izin = $pdo->prepare("SELECT * FROM izin_talepleri WHERE calisan_id=? AND durum='onaylandi' AND ? BETWEEN DATE(baslangic_tarihi) AND DATE(bitis_tarihi)");
        $stmt_izin->execute([$pid, $g_tarih]);
        $izinler = $stmt_izin->fetchAll(); // Çoklu izin
        
        $stmt_mesai = $pdo->prepare("SELECT SUM(toplam_saat) as toplam, baslangic_saati, bitis_saati FROM mesai_hareketleri WHERE calisan_id=? AND durum='onaylandi' AND tarih=? AND mesai_turu IN ('fazla_mesai', 'hafta_tatili', 'resmi_tatil_mesaisi')");
        $stmt_mesai->execute([$pid, $g_tarih]);
        $mesai_row = $stmt_mesai->fetch();
        $mesai_saat = $mesai_row['toplam'] ?: 0;
        
        $ham_kesinti = 0.0;
        $ham_mesai = (float)$mesai_saat;
        $izin_metinleri = []; 
        $gunluk_fiili_calisma = 0.0; 
        
        // Çoklu izin değişkenleri
        $sut_izni_var = false;
        $ucretsiz_izin_toplam_saat = 0;
        $tam_gun_izin_var = false;
        $tam_gun_izin_turu = '';

        // İzinleri Tara
        foreach ($izinler as $iz) {
            if ($iz['izin_turu'] == 'sut_izni') {
                $sut_izni_var = true;
                $b = date('H:i', strtotime($iz['baslangic_tarihi']));
                $e = date('H:i', strtotime($iz['bitis_tarihi']));
                $izin_metinleri[] = "SÜT ($b-$e)";
            } elseif (in_array($iz['izin_turu'], $ucretsiz_izinler)) {
                if ($iz['izin_turu'] == 'saatlik' || $iz['izin_turu'] == 'mesaiye_gelmedi') {
                    $ucretsiz_izin_toplam_saat += (float)$iz['saatlik_sure'];
                    $izin_metinleri[] = ($iz['izin_turu']=='mesaiye_gelmedi' ? 'Devamsız' : 'İzin') . ": -{$iz['saatlik_sure']}";
                } else {
                    $tam_gun_izin_var = true;
                    $tam_gun_izin_turu = $iz['izin_turu'];
                }
            } else {
                // Yıllık, babalık vb. (Ücretli tam gün)
                $tam_gun_izin_var = true;
                $tam_gun_izin_turu = $iz['izin_turu'];
            }
        }

        if (!$gun_aktif) {
            $ham_kesinti = 0; $ham_mesai = 0; $gunluk_fiili_calisma = 0;
        } 
        else {
            if (!$is_haftasonu && !$is_resmi_tatil) {
                if ($tam_gun_izin_var) {
                    $gunluk_fiili_calisma = 0; 
                    // Ücretli izinse (Yıllık vb.) maaştan kesilmez ama fiili çalışma 0'dır.
                    // Ücretsiz izinse (Hastalık vb.) maaştan kesilir (aşağıda ham_kesinti set edilecek).
                } else {
                    $gunluk_fiili_calisma = $gunluk_saat_std - $ucretsiz_izin_toplam_saat;
                }
            } else {
                $gunluk_fiili_calisma = 0;
            }
            if($gunluk_fiili_calisma < 0) $gunluk_fiili_calisma = 0;

            // Kesinti Hesabı
            if ($is_haftasonu || $is_resmi_tatil) {
                $ham_kesinti = 0;
            } else {
                if ($tam_gun_izin_var && in_array($tam_gun_izin_turu, $ucretsiz_izinler)) {
                    $ham_kesinti = $gunluk_saat_std;
                } else {
                    $ham_kesinti = $ucretsiz_izin_toplam_saat;
                }
            }
        }
        
        $net_kesinti = $ham_kesinti;
        $net_mesai = $ham_mesai;
        $mahsuplasma_var = false;

        if ($ham_kesinti > 0 && $ham_mesai > 0) {
            $mahsuplasma_var = true;
            if ($ham_mesai >= $ham_kesinti) {
                $net_mesai = $ham_mesai - $ham_kesinti;
                $net_kesinti = 0;
            } else {
                $net_kesinti = $ham_kesinti - $ham_mesai;
                $net_mesai = 0;
            }
        }

        $mesai_carpan = ($is_resmi_tatil || $is_haftasonu) ? 2.0 : 1.5;
        $mesai_net_hakedis = $net_mesai * $mesai_carpan;
        $mesai_saat_araligi = ($ham_mesai > 0) ? substr($mesai_row['baslangic_saati'],0,5).'-'.substr($mesai_row['bitis_saati'],0,5) : "";
        
        $puantaj_datasi[$pid][$g_tarih] = [
            'aktif_mi' => $gun_aktif,
            'gunluk_fiili_calisma' => $gunluk_fiili_calisma, 
            'is_resmi_tatil' => $is_resmi_tatil,
            'is_pazar' => $is_pazar,
            'haftanin_gunu' => $haftanin_gunu,
            'tatil_tipi' => ($is_resmi_tatil ? 'Resmi Tatil' : ($haftanin_gunu == 7 ? 'Pazar' : ($haftanin_gunu == 6 ? 'Cumartesi' : ''))),
            'ham_mesai' => $ham_mesai,
            'ham_kesinti' => $ham_kesinti,
            'net_mesai' => $net_mesai,
            'net_kesinti' => $net_kesinti,
            'mahsuplasma' => $mahsuplasma_var,
            'sut_var' => $sut_izni_var,
            'tam_gun_izin_var' => $tam_gun_izin_var,
            'tam_gun_izin_turu' => $tam_gun_izin_turu,
            'mesai_aralik' => $mesai_saat_araligi,
            'mesai_net_hakedis' => $mesai_net_hakedis,
            'detay_metinleri' => $izin_metinleri
        ];
    }
}
?>

<style>
    .bg-holiday { background-color: #ffebee !important; } 
    .bg-saturday { background-color: #f8f9fa !important; }
    .bg-inactive { background-color: #e9ecef !important; background-image: repeating-linear-gradient(45deg, transparent, transparent 5px, #dee2e6 5px, #dee2e6 10px); }
    .cell-content { font-size: 0.7rem; line-height: 1.2; font-weight: bold; }
    .val-plus { color: #198754; display: block; } 
    .val-minus { color: #dc3545; display: block; } 
    .val-sut { color: #d63384; display: block; }
    .val-izin { color: #0d6efd; display: block; } 
</style>

<div class="container-fluid">
    <div class="d-flex justify-content-between align-items-center mb-3">
        <h3><i class="fas fa-table text-primary"></i> Puantaj Cetveli</h3>
    </div>
    
    <div class="card-box p-3 mb-3 border-top border-primary border-3">
        <form method="GET" id="puantajForm" class="row g-2 align-items-end">
            <div class="col-md-2"><label class="fw-bold small">Yıl</label><select name="yil" class="form-select form-select-sm"><?php for($y=2005; $y<=2030; $y++) echo "<option value='$y' ".($y==$yil?'selected':'').">$y</option>"; ?></select></div>
            <div class="col-md-2"><label class="fw-bold small">Ay</label><select name="ay" class="form-select form-select-sm"><?php foreach($aylar_tr_uzun as $k=>$v) echo "<option value='$k' ".($k==$ay?'selected':'').">$v</option>"; ?></select></div>
            <div class="col-md-2"><label class="fw-bold small">Departman</label><select name="rol" class="form-select form-select-sm"><option value="tumu">Tümü</option><option value="calisan">Personel</option><option value="vardiya_amiri">Vardiya Amiri</option><option value="mudur">Müdür</option></select></div>
            <div class="col-md-3"><label class="fw-bold small">Personel</label><select name="personel_id" class="form-select form-select-sm"><option value="tumu">Herkes</option><?php foreach($tum_liste_select as $p) echo "<option value='{$p['id']}' ".($p['id']==$personel_id?'selected':'').">{$p['ad']} {$p['soyad']}</option>"; ?></select></div>
            <div class="col-md-3 d-flex gap-1"><button type="button" onclick="submitForm('')" class="btn btn-primary btn-sm flex-grow-1">Listele</button><div class="btn-group"><button type="button" onclick="submitForm('excel')" class="btn btn-success btn-sm"><i class="fas fa-file-excel"></i></button><button type="button" onclick="submitForm('print')" class="btn btn-dark btn-sm"><i class="fas fa-print"></i></button></div></div>
            <input type="hidden" name="format" id="exportFormat" value="">
        </form>
    </div>

    <div class="card border-0 shadow-sm overflow-auto">
        <table class="table table-bordered table-sm text-center mb-0 align-middle" style="font-size: 0.7rem;">
            <thead class="table-dark">
                <tr>
                    <th rowspan="2" class="align-middle text-start ps-2" style="min-width: 150px; position: sticky; left: 0; z-index: 10;">Personel Adı</th>
                    <?php for($d=1; $d<=$gun_sayisi; $d++): 
                        $gun_tarih = "$yil-$ay-" . sprintf('%02d', $d);
                        $gun_kisa = gunIsmi($gun_tarih);
                        $is_resmi = in_array($gun_tarih, $tatiller);
                        $renk = ($gun_kisa == 'Pzr' || $is_resmi) ? 'bg-danger text-white' : (($gun_kisa == 'Cts') ? 'bg-secondary text-white' : '');
                    ?>
                        <th class="<?php echo $renk; ?>" style="min-width: 35px;">
                            <?php echo $d; ?><br><small><?php echo $gun_kisa; ?></small>
                        </th>
                    <?php endfor; ?>
                    <th class="bg-primary border-start">N.M</th>
                    <th class="bg-success text-white">Net FM</th>
                    <th class="bg-warning text-dark">İZ</th>
                </tr>
                <tr>
                    <th colspan="<?php echo $gun_sayisi; ?>" class="bg-dark text-white">GÜNLÜK VERİLER</th>
                    <th colspan="3" class="bg-primary border-start text-white">TOPLAMLAR</th>
                </tr>
            </thead>
            <tbody>
                <?php if(empty($personeller)): ?>
                    <tr><td colspan="<?php echo $gun_sayisi + 4; ?>" class="text-center py-4">Bu kriterlere uygun aktif personel bulunamadı.</td></tr>
                <?php endif; ?>

                <?php foreach($personeller as $per): 
                    $toplam_nm = 0; 
                    $toplam_net_fazla = 0; 
                    $toplam_izin_gun = 0;
                    $toplam_izin_saat = 0;
                ?>
                <tr>
                    <td class="text-start ps-2 fw-bold bg-light" style="position: sticky; left: 0; z-index: 5;">
                        <?php echo $per['ad'].' '.$per['soyad']; ?>
                    </td>
                    
                    <?php for($d=1; $d<=$gun_sayisi; $d++): 
                        $g_tarih = "$yil-$ay-" . sprintf('%02d', $d);
                        $data = $puantaj_datasi[$per['id']][$g_tarih] ?? [];
                        $aktif = $data['aktif_mi'] ?? false;
                        $is_resmi = $data['is_resmi_tatil'];
                        $is_pazar = $data['is_pazar'];
                        
                        if (!$aktif) $bg_class = "bg-inactive";
                        elseif ($is_resmi || $is_pazar) $bg_class = "bg-holiday";
                        elseif ($data['tatil_tipi'] == 'Cumartesi') $bg_class = "bg-saturday";
                        else $bg_class = "bg-white";
                        
                        $hucre_icerik = "";
                        
                        if (!$aktif) {
                            $hucre_icerik = "<span class='text-muted' style='font-size:0.6rem;'>X</span>";
                        } else {
                            // Süt İzni Varsa Göster
                            if ($data['sut_var']) {
                                $hucre_icerik .= "<div class='val-sut'>SÜT</div>";
                                $toplam_izin_saat += 1.5; // İstatistiki olarak süt iznini de ekleyebiliriz veya hariç tutabiliriz.
                            }

                            // Tam Gün İzin
                            if ($data['tam_gun_izin_var']) {
                                $izin_sayilsin = true;
                                if ($data['tam_gun_izin_turu'] == 'yillik' && ($is_resmi || $is_pazar)) $izin_sayilsin = false;
                                
                                if ($izin_sayilsin) {
                                    $toplam_izin_gun++;
                                    $tur = strtoupper(substr($data['tam_gun_izin_turu'], 0, 3));
                                    $hucre_icerik .= "<div class='val-izin'>{$tur}</div>";
                                }
                            }
                            // Saatlik Kesinti Varsa (Süt izni olsa bile altına eklenir)
                            elseif ($data['ham_kesinti'] > 0) {
                                $hucre_icerik .= "<div class='val-minus'>-{$data['ham_kesinti']}</div>";
                                $toplam_izin_saat += $data['ham_kesinti'];
                            }

                            if ($data['ham_mesai'] > 0) {
                                $hucre_icerik .= "<div class='val-plus'>+{$data['ham_mesai']}</div>";
                            }
                            
                            $toplam_net_fazla += $data['net_mesai'];
                            $toplam_nm += $data['gunluk_fiili_calisma'];

                            if (empty($hucre_icerik) && !($is_resmi || $is_pazar)) {
                                $hucre_icerik = "<i class='fas fa-check text-muted opacity-25' style='font-size:0.6rem;'></i>";
                            }
                        }
                        
                        $json_detay = htmlspecialchars(json_encode([
                            'tarih' => tarihFormatOzel($g_tarih),
                            'personel' => $per['ad'].' '.$per['soyad'],
                            'aktif' => $aktif,
                            'gunluk_fiili_calisma' => $data['gunluk_fiili_calisma'],
                            'ham_mesai' => $data['ham_mesai'],
                            'ham_kesinti' => $data['ham_kesinti'],
                            'sut_var' => $data['sut_var'],
                            'detaylar' => $data['detay_metinleri']
                        ], JSON_UNESCAPED_UNICODE), ENT_QUOTES, 'UTF-8');
                    ?>
                        <td class="<?php echo $bg_class; ?> cell-content align-middle" 
                            style="cursor: pointer; height: 45px;" 
                            onclick="gunDetayGoster(this)"
                            data-detay='<?php echo $json_detay; ?>'>
                            <?php echo $hucre_icerik; ?>
                        </td>
                    <?php endfor; ?>

                    <td class="fw-bold border-start bg-primary bg-opacity-10 text-primary"><?php echo $toplam_nm; ?></td>
                    <td class="fw-bold text-success">+<?php echo (float)$toplam_net_fazla; ?></td>
                    <td class="fw-bold text-warning" style="font-size: 0.65rem;">
                        <?php 
                            $izin_str = [];
                            if($toplam_izin_gun > 0) $izin_str[] = $toplam_izin_gun . "g";
                            if($toplam_izin_saat > 0) $izin_str[] = $toplam_izin_saat . "s";
                            echo empty($izin_str) ? '0' : implode(' ', $izin_str);
                        ?>
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>
</div>

<div class="modal fade" id="gunDetayModal" tabindex="-1">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content shadow border-0">
            <div class="modal-header bg-primary text-white py-2">
                <h6 class="modal-title mb-0"><i class="fas fa-info-circle me-2"></i> Hareket Analizi</h6>
                <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body p-3">
                <div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-3">
                    <span class="fw-bold text-dark" id="modalTarih"></span>
                    <span class="badge bg-secondary" id="modalPersonel"></span>
                </div>
                <div id="modalIcerik"></div>
            </div>
            <div class="modal-footer bg-light border-0 py-1">
                <button type="button" class="btn btn-sm btn-secondary w-100" data-bs-dismiss="modal">Kapat</button>
            </div>
        </div>
    </div>
</div>

<script>
function submitForm(type) {
    const form = document.getElementById('puantajForm');
    document.getElementById('exportFormat').value = type;
    if (type === 'excel' || type === 'print') { form.action = 'puantaj-rapor.php'; form.target = '_blank'; } 
    else { form.action = 'puantaj-cetveli.php'; form.target = '_self'; }
    form.submit();
}

function gunDetayGoster(tdElement) {
    const dataStr = tdElement.getAttribute('data-detay');
    if (!dataStr) return;
    const data = JSON.parse(dataStr);
    
    document.getElementById('modalTarih').innerText = data.tarih;
    document.getElementById('modalPersonel').innerText = data.personel;
    
    let html = '<ul class="list-group list-group-flush small">';
    
    if (!data.aktif) {
        html += `<li class="list-group-item bg-light text-muted text-center py-3"><i class="fas fa-user-slash fa-2x mb-2 opacity-25"></i><br>Personel bu tarihte şirkette aktif değil.</li>`;
    } else {
        html += `<li class="list-group-item d-flex justify-content-between"><span><i class="fas fa-briefcase text-primary me-2"></i> Normal Mesai (N.M):</span><span class="fw-bold text-primary">${data.gunluk_fiili_calisma} Saat</span></li>`;
        
        // Detayları Listele
        if (data.detaylar && data.detaylar.length > 0) {
            data.detaylar.forEach(d => {
                let color = d.includes('SÜT') ? 'text-danger' : 'text-primary';
                html += `<li class="list-group-item fw-bold ${color}">${d}</li>`;
            });
        }

        if (data.ham_mesai > 0) {
            html += `<li class="list-group-item"><strong class="text-success">Fazla Mesai: +${data.ham_mesai} Saat</strong></li>`;
        }
    }
    html += '</ul>';
    document.getElementById('modalIcerik').innerHTML = html;
    new bootstrap.Modal(document.getElementById('gunDetayModal')).show();
}
</script>
<?php include '../includes/footer.php'; ?>