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

// Yetkiler: Root, Yönetici, Muhasebe, İK
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'));
$hafta = guvenlik($_GET['hafta'] ?? 'tumu');
$rol_filtre = guvenlik($_GET['rol'] ?? 'tumu');
$personel_id_filtre = guvenlik($_GET['personel_id'] ?? 'tumu');

// Standart Haftalık Çalışma Saati (45 Saat)
$haftalik_calisma_std = 45.0; 

// Standart Günlük Mesai (Ayarlardan) - 45/5 = 9 Saat
$gunluk_saat_std = (float)($pdo->query("SELECT ayar_degeri FROM site_ayarlari WHERE ayar_anahtari = 'gunluk_mesai_saati'")->fetchColumn() ?: 9);

// --- YARDIMCI FONKSİYONLAR ---
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 ayAdi($ay, $kisa = false) {
    $aylar = ['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'];
    return $aylar[ltrim($ay, '0')] ?? '';
}

// İzin Renkleri ve Etiketleri (Önceki dosyadan alındı)
function izinStili($tur) {
    $stiller = [
        'yillik'   => ['bg'=>'bg-info text-white', 't'=>'Y.İZ'],
        'mazeret'  => ['bg'=>'bg-warning text-dark', 't'=>'MAZ'],
        'hastalik' => ['bg'=>'bg-danger text-white', 't'=>'RAPOR'],
        'evlilik'  => ['bg'=>'bg-primary text-white', 't'=>'EVL'],
        'babalik'  => ['bg'=>'bg-primary text-white', 't'=>'BAB'],
        'olum'     => ['bg'=>'bg-dark text-white', 't'=>'ÖLM'],
        'saatlik'  => ['bg'=>'bg-warning bg-opacity-25 text-dark', 't'=>'S.İZ'],
        'diger'    => ['bg'=>'bg-danger bg-opacity-50 text-white', 't'=>'ÜCR.İZ']
    ];
    return $stiller[$tur] ?? ['bg'=>'bg-secondary text-white', 't'=>strtoupper($tur)];
}

// --- HAFTA HESAPLAMA ---
$tarih_start = "$yil-$ay-01";
$tarih_end = "$yil-$ay-" . cal_days_in_month(CAL_GREGORIAN, $ay, $yil);

$haftalar = [];
$gecerli_tarih = strtotime($tarih_start);
$hafta_sayac = 1;

while ($gecerli_tarih <= strtotime($tarih_end)) {
    // Haftanın Pazartesi gününü bul
    $pazartesi = date('N', $gecerli_tarih) == 1 ? $gecerli_tarih : strtotime('last monday', $gecerli_tarih);
    
    // Pazar gününü bul
    $pazar = strtotime('+6 days', $pazartesi);
    
    // Ay sınırlarını kontrol et
    $hafta_baslangic = max($pazartesi, strtotime($tarih_start));
    $hafta_bitis = min($pazar, strtotime($tarih_end));
    
    // TÜRKÇE HAFTA ETİKETİ
    $bas_gun = date('d', $hafta_baslangic);
    $bit_gun = date('d', $hafta_bitis);
    $bas_ay = ayAdi(date('m', $hafta_baslangic));
    $bit_ay = ayAdi(date('m', $hafta_bitis));

    $etiket = "Hafta {$hafta_sayac}: {$bas_gun} {$bas_ay} - {$bit_gun} {$bit_ay}";

    $haftalar[$hafta_sayac] = [
        'baslangic' => date('Y-m-d', $hafta_baslangic),
        'bitis' => date('Y-m-d', $hafta_bitis),
        'etiket' => $etiket,
        'baslangic_timestamp' => $hafta_baslangic,
        'bitis_timestamp' => $hafta_bitis
    ];
    
    // Bir sonraki Pazartesiye geç
    $gecerli_tarih = strtotime('+7 days', $pazartesi);
    $hafta_sayac++;

    // Bitiş tarihi Ay sonundan büyükse döngüyü kır
    if ($hafta_baslangic > strtotime($tarih_end) && $hafta_bitis > strtotime($tarih_end)) break;
}

// Eğer filtrelenecek hafta seçildiyse, tarih aralığını belirle
$secilen_hafta_bilgi = $haftalar[(int)$hafta] ?? null;
$baslangic_tarih = $secilen_hafta_bilgi['baslangic'] ?? $tarih_start;
$bitis_tarih = $secilen_hafta_bilgi['bitis'] ?? $tarih_end;

// --- PERSONEL LİSTESİ ---
$sql_per = "SELECT id, ad, soyad FROM kullanicilar WHERE durum=1";
if ($rol_filtre != 'tumu') $sql_per .= " AND rol = '$rol_filtre'";
if ($personel_id_filtre != 'tumu') $sql_per .= " AND id = " . (int)$personel_id_filtre;
$sql_per .= " ORDER BY ad ASC";
$personeller = $pdo->query($sql_per)->fetchAll();

// 1. Resmi Tatiller
$tatiller = $pdo->query("SELECT tarih FROM resmi_tatiller")->fetchAll(PDO::FETCH_COLUMN);

// 2. Tüm personeller (Filtre kutusu için)
$tum_personeller_query = $pdo->query("SELECT id, ad, soyad FROM kullanicilar WHERE durum=1 ORDER BY ad ASC")->fetchAll();

// --- HAFTALIK PUANTAJ VERİ TOPLAMA ---
$haftalik_puantaj_ozet = []; 

foreach($personeller as $per) {
    $personel_id = $per['id'];
    
    $toplam_calisma = 0.0;
    $toplam_izin_saat = 0.0;
    $toplam_mesai_saat = 0.0;
    $toplam_izin_gun = 0.0;
    
    $tarih_simdiki = strtotime($baslangic_tarih);
    $tarih_bitis = strtotime($bitis_tarih);

    while ($tarih_simdiki <= $tarih_bitis) {
        $g_tarih = date('Y-m-d', $tarih_simdiki);
        $haftanin_gunu = date('N', $tarih_simdiki); // 1 (Pzt) - 7 (Pzr)
        $is_haftaici = $haftanin_gunu <= 5;
        $is_tatil_gunu = in_array($g_tarih, $tatiller);
        
        // --- İZİN HESAPLAMA ---
        $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([$personel_id, $g_tarih]);
        $izin = $stmt_izin->fetch();

        $gunluk_normal_calisma = $is_haftaici && !$is_tatil_gunu ? $gunluk_saat_std : 0.0;
        $izin_kesinti_saati = 0.0;
        $gunluk_net_calisma = $gunluk_normal_calisma;

        if ($izin) {
            $izin_turu = $izin['izin_turu'];
            
            if ($izin_turu == 'saatlik') {
                $izin_saat = (float)$izin['saatlik_sure'];
                
                // Mola kuralı kontrolü (Sadece hafta içi 9 saatlik günlerde uygulanır varsayılır)
                if ($is_haftaici && $gunluk_saat_std == 9.0) {
                     $bas_saat_str = date('H:i', strtotime($izin['baslangic_tarihi']));
                     $bit_saat_str = date('H:i', strtotime($izin['bitis_tarihi']));

                    if ($bas_saat_str === '08:00' && $bit_saat_str === '12:00') {
                        $izin_kesinti_saati = 4.0; 
                    } elseif ($bas_saat_str === '13:00' && $bit_saat_str === '18:00') {
                        $izin_kesinti_saati = 5.0;
                    } else {
                        $izin_kesinti_saati = $izin_saat;
                    }
                } else {
                    $izin_kesinti_saati = $izin_saat;
                }
                
                $gunluk_net_calisma = max(0, $gunluk_normal_calisma - $izin_kesinti_saati);
                $toplam_izin_saat += $izin_kesinti_saati;
                
            } elseif ($izin_turu == 'diger') {
                // Ücretsiz izin (Tam gün kesinti)
                $izin_kesinti_saati = $gunluk_normal_calisma;
                $gunluk_net_calisma = 0.0;
                $toplam_izin_saat += $izin_kesinti_saati;
                $toplam_izin_gun += 1.0; 

            } elseif ($is_haftaici && $gunluk_normal_calisma > 0) {
                // Tam Gün Ücretli İzin (Yıllık, Mazeret vb.) - Kesinti 0, ancak normal çalışma saati düşer
                $gunluk_net_calisma = 0.0; 
                $toplam_izin_gun += 1.0; 
            }
        }
        
        // --- MESAİ HESAPLAMA ---
        $stmt_mesai = $pdo->prepare("SELECT SUM(toplam_saat) 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([$personel_id, $g_tarih]);
        $mesai_saat = $stmt_mesai->fetchColumn() ?: 0.0;
        
        $toplam_calisma += $gunluk_net_calisma;
        $toplam_mesai_saat += $mesai_saat;

        $tarih_simdiki = strtotime('+1 day', $tarih_simdiki);
    }
    
    // --- HAFTALIK ÖZET HESAPLAMA ---
    $toplam_saat_haftaici = $toplam_calisma; // Normal hafta içi çalışma (izinler düşülmüş)
    $haftalik_fazla_mesai_ici = 0.0;
    
    // Hafta içi fazla mesaiyi belirle
    if ($toplam_saat_haftaici > $haftalik_calisma_std) {
        $haftalik_fazla_mesai_ici = $toplam_saat_haftaici - $haftalik_calisma_std;
        $toplam_saat_haftaici = $haftalik_calisma_std; // Tavanı 45 saat yap
    }

    // Toplam Haftalık Normal Çalışma (Fazla mesai düşülmüş)
    $haftalik_normal_calisma = $toplam_saat_haftaici; 

    // Genel Fazla Mesai (Hafta içi fazla mesaisi + Hafta sonu/Tatil mesaisi)
    $genel_fazla_mesai = $haftalik_fazla_mesai_ici + $toplam_mesai_saat;

    $haftalik_puantaj_ozet[$personel_id] = [
        'ad_soyad' => $per['ad'] . ' ' . $per['soyad'],
        'normal_saat' => (float)number_format($haftalik_normal_calisma, 2),
        'izin_saat' => (float)number_format($toplam_izin_saat, 2),
        'izin_gun' => (float)number_format($toplam_izin_gun, 1),
        // Fazla mesai kaldırıldı, ancak hesaplamayı verinin içinde tuttuk
        'fazla_mesai' => (float)number_format($genel_fazla_mesai, 2), 
    ];
}
?>

<div class="container-fluid">
    <div class="d-flex justify-content-between align-items-center mb-3">
        <h3><i class="fas fa-calendar-alt text-success"></i> Haftalık Puantaj Özeti</h3>
    </div>
    
    <div class="card-box p-3 mb-3 border-top border-success 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=2024; $y<=2030; $y++): ?>
                        <option value='<?php echo $y; ?>' <?php echo ($y == $yil) ? 'selected' : ''; ?>>
                            <?php echo $y; ?>
                        </option>
                    <?php endfor; ?>
                </select>
            </div>
            <div class="col-md-2">
                <label class="fw-bold small">Ay</label>
                <select name="ay" class="form-select form-select-sm">
                    <?php 
                    $aylar = ['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'];
                    foreach($aylar as $k=>$v): 
                    ?>
                        <option value='<?php echo $k; ?>' <?php echo ($k == $ay) ? 'selected' : ''; ?>>
                            <?php echo $v; ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>
             <div class="col-md-2">
                <label class="fw-bold small">Hafta Aralığı</label>
                <select name="hafta" class="form-select form-select-sm" required>
                    <option value="tumu" <?php echo ('tumu' == $hafta) ? 'selected' : ''; ?>>Tüm Ay</option>
                    <?php foreach($haftalar as $k => $h): ?>
                        <option value='<?php echo $k; ?>' <?php echo ($k == $hafta) ? 'selected' : ''; ?>>
                            <?php echo $h['etiket']; ?>
                        </option>
                    <?php endforeach; ?>
                </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" <?php echo ('tumu' == $rol_filtre) ? 'selected' : ''; ?>>Tümü</option>
                    <option value="calisan" <?php echo ('calisan' == $rol_filtre) ? 'selected' : ''; ?>>Personel</option>
                    <option value="vardiya_amiri" <?php echo ('vardiya_amiri' == $rol_filtre) ? 'selected' : ''; ?>>Vardiya Amiri</option>
                    <option value="mudur" <?php echo ('mudur' == $rol_filtre) ? 'selected' : ''; ?>>Müdür</option>
                    </select>
            </div>
            <div class="col-md-2">
                <label class="fw-bold small">Personel</label>
                <select name="personel_id" class="form-select form-select-sm">
                    <option value="tumu" <?php echo ('tumu' == $personel_id_filtre) ? 'selected' : ''; ?>>Herkes</option>
                    <?php foreach($tum_personeller_query as $p): ?>
                        <option value='<?php echo $p['id']; ?>' <?php echo ($p['id'] == $personel_id_filtre) ? 'selected' : ''; ?>>
                            <?php echo $p['ad'] . ' ' . $p['soyad']; ?>
                        </option>
                    <?php endforeach; ?>
                </select>
            </div>
            
            <div class="col-md-2 d-flex gap-1">
                <button type="button" onclick="submitForm('')" class="btn btn-success btn-sm flex-grow-1"><i class="fas fa-search"></i> Listele</button>
                <div class="btn-group">
                    <button type="button" onclick="submitForm('excel')" class="btn btn-primary btn-sm" title="Excel İndir"><i class="fas fa-file-excel"></i></button>
                    <button type="button" onclick="submitForm('pdf')" class="btn btn-dark btn-sm" title="PDF İndir"><i class="fas fa-file-pdf"></i></button>
                </div>
            </div>
            <input type="hidden" name="format" id="exportFormat" value="">
        </form>
        <?php if ($secilen_hafta_bilgi): ?>
            <div class="alert alert-info small mt-3 mb-0 py-2">
                Gösterilen Tarih Aralığı: **<?php echo $secilen_hafta_bilgi['etiket']; ?>** (<?php echo $baslangic_tarih; ?> - <?php echo $bitis_tarih; ?>)
            </div>
        <?php endif; ?>
    </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.8rem;">
            <thead class="table-success text-white">
                <tr>
                    <th class="align-middle text-start ps-3" style="min-width: 180px; position: sticky; left: 0; z-index: 10;">Personel Adı</th>
                    <th style="min-width: 120px;">Haftalık Normal Çalışma (Saat)</th>
                    <th style="min-width: 120px;">İzin/Kesinti Süresi (Saat)</th>
                    <th style="min-width: 100px;">Toplam İzin Günü (Tam Gün)</th>
                    <th style="min-width: 180px;">Açıklama</th>
                </tr>
            </thead>
            <tbody>
                <?php if (empty($haftalik_puantaj_ozet)): ?>
                    <tr><td colspan="5" class="text-center text-muted p-4">Seçilen tarihlerde puantaj verisi bulunmamaktadır veya filtre uygulanmamıştır.</td></tr>
                <?php else: ?>
                    <?php foreach($haftalik_puantaj_ozet as $ozet): ?>
                    <tr>
                        <td class="text-start ps-3 fw-bold bg-light" style="position: sticky; left: 0; z-index: 5;">
                            <?php echo htmlspecialchars($ozet['ad_soyad']); ?>
                        </td>
                        <td class="fw-bold <?php echo ($ozet['normal_saat'] >= $haftalik_calisma_std) ? 'text-primary' : 'text-danger'; ?>">
                            <?php echo $ozet['normal_saat']; ?> / 45.00
                        </td>
                        <td class="fw-bold text-warning">
                            - <?php echo $ozet['izin_saat']; ?>
                        </td>
                        <td>
                            <?php echo $ozet['izin_gun']; ?>
                        </td>
                        <td class="small text-muted text-start">
                            <?php 
                                $aciklama = '';
                                if ($ozet['normal_saat'] < $haftalik_calisma_std) {
                                    $aciklama = "Haftalık hedef çalışma saati ($haftalik_calisma_std s.) aşılamadı.";
                                } else {
                                    $aciklama = "Haftalık hedef tamamlandı. ";
                                }
                                
                                if ($ozet['fazla_mesai'] > 0) {
                                    $aciklama .= "Toplam Fazla Mesai: " . $ozet['fazla_mesai'] . " saat.";
                                }

                                echo $aciklama;
                            ?>
                        </td>
                    </tr>
                    <?php endforeach; ?>
                <?php endif; ?>
            </tbody>
        </table>
    </div>
    
    <div class="mt-3 small text-muted border-top pt-2">
        **Hesaplama Notları:** Normal Çalışma, İzinler düşüldükten sonra 45 saat ile sınırlandırılmıştır. İzin/Kesinti Süresi, saatlik veya ücretsiz izin nedeniyle yapılan kesintilerdir.
    </div>
</div>

<script>
// -----------------------------------------------------------
function submitForm(type) {
    const form = document.getElementById('puantajForm');
    const hiddenInput = document.getElementById('exportFormat');
    
    hiddenInput.value = type;
    
    // Filtreleme yapılıyorsa (type boşsa), formu normal olarak gönderir
    if (type === 'excel' || type === 'pdf') {
        // Raporlama için yeni bir PHP dosyasına yönlendirilir (puantaj-rapor-haftalik.php)
        form.action = 'puantaj-rapor-haftalik.php'; 
        form.target = '_blank';
    } else {
        // Filtreleme için (Listele butonu)
        form.action = 'puantaj-cetveli-haftali.php'; // Sayfanın kendisine gönderir
        form.target = '_self';
    }
    form.submit();
}
// -----------------------------------------------------------
</script>

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