PYBS (Personel Yönetim Bilgi Sistemi) / Ramsa/modules/mesai-giris.php
mesai-giris.php 368 satır • 17.83 KB
<?php
// modules/mesai-giris.php
session_start();
require_once '../config/db.php';
require_once '../config/functions.php';

// Yetki Kontrolü
yetkiKontrol(['root', 'yonetici', 'mudur', 'vardiya_amiri', 'calisan', 'stajyer', 'muhasebe', 'insan_kaynaklari']);

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

$mesaj = '';
$kullanici_id = $_SESSION['kullanici_id'];
$rol = $_SESSION['rol'];
$yuksek_yetki = in_array($rol, ['root', 'yonetici', 'mudur', 'muhasebe', 'insan_kaynaklari']);

// --- İPTAL İŞLEMİ (YENİ EKLENDİ) ---
// Sadece beklemedeki kayıtlar silinebilir.
if (isset($_GET['iptal_id'])) {
    $iptal_id = (int)$_GET['iptal_id'];
    
    // Güvenlik: Sadece kendi ve 'beklemede' olan kaydı silebilir
    $stmt_check = $pdo->prepare("SELECT id FROM mesai_hareketleri WHERE id = ? AND calisan_id = ? AND durum = 'beklemede'");
    $stmt_check->execute([$iptal_id, $kullanici_id]);
    
    if ($stmt_check->fetch()) {
        $del = $pdo->prepare("DELETE FROM mesai_hareketleri WHERE id = ?");
        $del->execute([$iptal_id]);
        
        // Log kaydı (Opsiyonel ama iyi olur)
        logKaydet($pdo, $kullanici_id, 'silme', "Mesai talebi kullanıcı tarafından iptal edildi (ID: $iptal_id)", 'mesai_hareketleri', $iptal_id);
        
        $mesaj = "<div class='alert alert-warning alert-dismissible fade show'>
                    <i class='fas fa-trash'></i> Mesai bildirimi iptal edildi.
                    <button type='button' class='btn-close' data-bs-dismiss='alert'></button>
                  </div>";
    } else {
        $mesaj = "<div class='alert alert-danger'>Hata: Bu kayıt silinemez (Onaylanmış veya size ait değil).</div>";
    }
}

// Standart Günlük Çalışma Saati
$gunluk_saat_std = (float)($pdo->query("SELECT ayar_degeri FROM site_ayarlari WHERE ayar_anahtari = 'gunluk_mesai_saati'")->fetchColumn() ?: 9.00);

// Limitler (Bilgi amaçlı)
$maks_ek_mesai_saati_gunluk = 2.0; 
$maks_ek_mesai_saati_haftalik = 15.0; 
$maks_ek_mesai_saati_yillik = 270.0; 
$maks_tatil_calisma_saati = 10.0; 

// Resmi Tatil Listesi
$tatiller = $pdo->query("SELECT tarih FROM resmi_tatiller")->fetchAll(PDO::FETCH_COLUMN);
$tatiller_json = json_encode($tatiller);

// Saat Seçenekleri
$zaman_secenekleri = "";
for ($saat = 0; $saat < 24; $saat++) {
    foreach (['00', '30'] as $dakika) {
        $deger = sprintf('%02d:%s', $saat, $dakika); 
        $zaman_secenekleri .= "<option value='$deger'>$deger</option>";
    }
}

// ÇAKIŞMA KONTROLÜ
$sql_cakisma = "SELECT * FROM mesai_hareketleri 
                WHERE calisan_id = ? 
                AND durum IN ('onaylandi', 'beklemede') 
                AND tarih = ? 
                AND (
                    (baslangic_saati < ? AND bitis_saati > ?) 
                )";

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    csrfKontrol($_POST['csrf_token']);

    $hedef_yonetici = $_POST['hedef_yonetici_id'];
    $tarih = $_POST['tarih'];
    $baslangic = $_POST['baslangic_saati'];
    $bitis = $_POST['bitis_saati'];
    $mesai_turu = $_POST['mesai_turu'];
    $aciklama = guvenlik($_POST['aciklama']); // Opsiyonel
    $hata = false;

    // 1. Temel Mantık Kontrolleri
    $t1 = strtotime($baslangic);
    $t2 = strtotime($bitis);
    
    // Gece yarısını geçiyorsa (Örn: 22:00 - 02:00)
    if ($t2 < $t1) {
        $t2 += 24 * 3600;
    }

    $sure = round(($t2 - $t1) / 3600, 2);

    if ($sure <= 0) {
        $mesaj = '<div class="alert alert-danger">Başlangıç ve bitiş saatleri hatalı.</div>';
        $hata = true;
    }

    // 3. Çakışma Kontrolü
    if (!$hata) {
        $db_bas = $baslangic . ':00';
        $db_bit = $bitis . ':00';
        
        $stmt_check = $pdo->prepare($sql_cakisma);
        $stmt_check->execute([$kullanici_id, $tarih, $db_bit, $db_bas]); 
        
        if ($stmt_check->fetch()) {
            $mesaj = "<div class='alert alert-danger'>HATA: Seçilen saatlerde zaten bir mesai kaydı mevcut.</div>";
            $hata = true;
        }
    }

    if (!$hata) {
        // Eğer giren kişi yetkiliyse direkt onaylanır, değilse onaya düşer
        $durum = ($yuksek_yetki && $hedef_yonetici == $kullanici_id) ? 'onaylandi' : 'beklemede';
        $onaylayan = ($durum == 'onaylandi') ? $kullanici_id : NULL;
        $onay_tarihi = ($durum == 'onaylandi') ? date('Y-m-d H:i:s') : NULL;

        $sql = "INSERT INTO mesai_hareketleri (calisan_id, hedef_yonetici_id, onaylayan_id, tarih, mesai_turu, baslangic_saati, bitis_saati, toplam_saat, aciklama, durum, onaylanma_tarihi) 
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
        $stmt = $pdo->prepare($sql);
        
        if ($stmt->execute([$kullanici_id, $hedef_yonetici, $onaylayan, $tarih, $mesai_turu, $db_bas, $db_bit, $sure, $aciklama, $durum, $onay_tarihi])) {
            
            logKaydet($pdo, $kullanici_id, 'ekleme', "Mesai girişi: $tarih ($sure Saat)", 'mesai_hareketleri', $pdo->lastInsertId());
            
            if ($durum == 'beklemede') {
                bildirimGonder($pdo, $hedef_yonetici, "Yeni Mesai Bildirimi", "Fazla mesai onayı bekliyor.", "../modules/tum-mesailer.php");
                $mesaj = '<div class="alert alert-success">Mesai bildiriminiz başarıyla iletildi. Yönetici onayı bekleniyor.</div>';
            } else {
                $mesaj = '<div class="alert alert-success">Mesai kaydı başarıyla oluşturuldu ve onaylandı.</div>';
            }
            
        } else {
            $mesaj = '<div class="alert alert-danger">Veritabanı hatası oluştu.</div>';
        }
    }
}

// Onaylayacak Kişiler Listesi (Sadece Yönetici ve Müdür)
$yoneticiler = $pdo->query("SELECT id, ad, soyad, rol FROM kullanicilar WHERE rol IN ('yonetici', 'mudur') AND durum=1 AND id != $kullanici_id")->fetchAll();

// --- GEÇMİŞ MESAİLERİ ÇEK ---
$sql_gecmis = "SELECT m.*, y.ad as y_ad, y.soyad as y_soyad, o.ad as o_ad, o.soyad as o_soyad
               FROM mesai_hareketleri m 
               LEFT JOIN kullanicilar y ON m.hedef_yonetici_id = y.id 
               LEFT JOIN kullanicilar o ON m.onaylayan_id = o.id 
               WHERE m.calisan_id = ? 
               ORDER BY m.tarih DESC, m.baslangic_saati DESC";
$stmt_gecmis = $pdo->prepare($sql_gecmis);
$stmt_gecmis->execute([$kullanici_id]);
$gecmis_mesailer = $stmt_gecmis->fetchAll();
?>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">

<div class="container-fluid pb-5">
    
    <?php if($mesaj): ?><div class="mb-3"><?php echo $mesaj; ?></div><?php endif; ?>

    <div class="row">
        <div class="col-lg-5 mb-4">
            <div class="card border-0 shadow-sm rounded-4 h-100">
                <div class="card-header bg-white py-3 border-bottom-0">
                    <h5 class="mb-0 fw-bold text-primary"><i class="fas fa-business-time me-2"></i> Fazla Mesai Bildirimi</h5>
                </div>
                <div class="card-body p-4 pt-0">
                    <form method="POST">
                        <input type="hidden" name="csrf_token" value="<?php echo csrfTokenOlustur(); ?>">
                        
                        <div class="mb-3">
                            <label class="form-label fw-bold small">Onaylayacak Yönetici</label>
                            <select name="hedef_yonetici_id" class="form-select bg-light" required>
                                <option value="">Seçiniz...</option>
                                <?php foreach($yoneticiler as $y): ?>
                                    <option value="<?php echo $y['id']; ?>"><?php echo $y['ad'].' '.$y['soyad'].' ('.ucfirst(str_replace('_',' ',$y['rol'])).')'; ?></option>
                                <?php endforeach; ?>
                            </select>
                        </div>

                        <div class="row g-3 mb-3">
                            <div class="col-12">
                                <label class="form-label fw-bold small">Tarih</label>
                                <input type="text" name="tarih" id="mesaiTarih" class="form-control bg-white" required>
                            </div>
                            <div class="col-6">
                                <label class="form-label fw-bold small">Başlangıç</label>
                                <select name="baslangic_saati" class="form-select bg-white" id="baslangicSaatSelect">
                                    <?php echo $zaman_secenekleri; ?>
                                </select>
                            </div>
                            <div class="col-6">
                                <label class="form-label fw-bold small">Bitiş</label>
                                <select name="bitis_saati" class="form-select bg-white">
                                    <option value="18:00">18:00</option>
                                    <option value="18:30">18:30</option>
                                    <option value="19:00">19:00</option>
                                    <option value="20:00">20:00</option>
                                    <option value="21:00">21:00</option>
                                    <option value="22:00">22:00</option>
                                    <?php echo $zaman_secenekleri; ?>
                                </select>
                            </div>
                        </div>

                        <div class="mb-3">
                            <label class="form-label fw-bold small">Mesai Türü</label>
                            <select name="mesai_turu" id="mesaiTuru" class="form-select bg-light">
                                <option value="fazla_mesai">Normal Fazla Mesai (Hafta İçi - 1.5x)</option>
                                <option value="hafta_tatili">Hafta Tatili Mesaisi (Pazar - 2.0x)</option>
                                <option value="resmi_tatil_mesaisi">Resmi Tatil Mesaisi (Bayram - 2.0x)</option>
                                <option value="vardiya_gece">Vardiya / Gece Çalışması</option>
                            </select>
                            <small class="text-muted d-block mt-1" id="turBilgi" style="font-size:0.75rem;">Lütfen tarihi seçiniz, sistem otomatik önerecektir.</small>
                        </div>

                        <div class="mb-4">
                            <label class="form-label fw-bold small">Açıklama (Opsiyonel)</label>
                            <textarea name="aciklama" class="form-control bg-light" rows="2" placeholder="Örn: Arıza müdahalesi, Sipariş yetiştirme vb."></textarea>
                        </div>

                        <button type="submit" class="btn btn-primary w-100 fw-bold py-2">BİLDİRİMİ GÖNDER <i class="fas fa-paper-plane ms-2"></i></button>
                    </form>
                </div>
            </div>
        </div>

        <div class="col-lg-7">
            <div class="card border-0 shadow-sm rounded-4 h-100">
                <div class="card-header bg-white py-3 border-bottom-0">
                    <h5 class="mb-0 fw-bold text-dark"><i class="fas fa-history text-muted me-2"></i> Geçmiş Mesai Hareketleri</h5>
                </div>
                <div class="card-body p-0">
                    <div class="table-responsive">
                        <table class="table table-hover align-middle mb-0" style="font-size: 0.85rem;">
                            <thead class="bg-light text-muted">
                                <tr>
                                    <th class="ps-4">Tarih</th>
                                    <th>Saat Aralığı</th>
                                    <th>Süre</th>
                                    <th>Durum / İşlem Yapan</th>
                                    <th class="text-end pe-4">İşlem</th>
                                </tr>
                            </thead>
                            <tbody>
                                <?php if(empty($gecmis_mesailer)): ?>
                                    <tr><td colspan="5" class="text-center py-5 text-muted">Henüz bir mesai kaydınız bulunmuyor.</td></tr>
                                <?php endif; ?>
                                
                                <?php foreach($gecmis_mesailer as $m): 
                                    $renk = 'warning text-dark';
                                    $durum_txt = 'Bekliyor';
                                    if($m['durum']=='onaylandi') { $renk='success'; $durum_txt='Onaylandı'; }
                                    if($m['durum']=='reddedildi') { $renk='danger'; $durum_txt='Reddedildi'; }
                                    
                                    $bas = substr($m['baslangic_saati'], 0, 5);
                                    $bit = substr($m['bitis_saati'], 0, 5);
                                    $tur_label = ($m['mesai_turu'] == 'fazla_mesai') ? 'Normal (1.5x)' : 'Tatil/Vardiya (1.5x/2.0x)';
                                ?>
                                <tr>
                                    <td class="ps-4">
                                        <div class="fw-bold text-dark"><?php echo date('d.m.Y', strtotime($m['tarih'])); ?></div>
                                        <div class="text-muted small"><?php echo $tur_label; ?></div>
                                    </td>
                                    <td><span class="fw-bold text-secondary"><?php echo "$bas - $bit"; ?></span></td>
                                    <td><span class="badge bg-light text-dark border"><?php echo (float)$m['toplam_saat']; ?> Saat</span></td>
                                    <td>
                                        <span class="badge bg-<?php echo $renk; ?> mb-1"><?php echo $durum_txt; ?></span><br>
                                        <small class="text-muted" style="font-size:0.75rem;">
                                            <?php 
                                            if($m['durum']=='beklemede') echo "Yönetici: ".$m['y_ad'].' '.$m['y_soyad'];
                                            else echo "İşlem: ".$m['o_ad'].' '.$m['o_soyad'];
                                            ?>
                                        </small>
                                    </td>
                                    <td class="text-end pe-4">
                                        <?php if($m['durum'] == 'beklemede'): ?>
                                            <a href="?iptal_id=<?php echo $m['id']; ?>" class="btn btn-sm btn-outline-danger" onclick="return confirm('Bu mesai bildirimini iptal etmek istediğinize emin misiniz?')">
                                                <i class="fas fa-times"></i> İptal
                                            </a>
                                        <?php else: ?>
                                            <span class="text-muted disabled"><i class="fas fa-lock"></i></span>
                                        <?php endif; ?>
                                    </td>
                                </tr>
                                <?php endforeach; ?>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<script src="https://cdn.jsdelivr.net/npm/flatpickr/dist/l10n/tr.js"></script>

<script>
    const resmiTatiller = <?php echo $tatiller_json; ?>;
    const mesaiTuruSelect = document.getElementById('mesaiTuru');
    const turBilgi = document.getElementById('turBilgi');
    const baslangicSelect = document.getElementById('baslangicSaatSelect'); 

    function genelAyarla(selectedDates, dateStr, instance) {
        if (selectedDates.length === 0) return;
        
        let date = selectedDates[0];
        let gun = date.getDay(); // 0: Pazar, 1: Pzt ... 6: Cts
        
        if (resmiTatiller.includes(dateStr)) {
            mesaiTuruSelect.value = 'resmi_tatil_mesaisi';
            turBilgi.innerHTML = '<span class="text-danger fw-bold"><i class="fas fa-info-circle"></i> Resmi Tatil Günü Seçildi (2.0x)</span>';
        } else if (gun === 0) { // Pazar
            mesaiTuruSelect.value = 'hafta_tatili';
            turBilgi.innerHTML = '<span class="text-danger fw-bold"><i class="fas fa-info-circle"></i> Pazar Günü Seçildi (2.0x)</span>';
        } else {
            // Hafta İçi (Pzt-Cts)
            mesaiTuruSelect.value = 'fazla_mesai';
            turBilgi.innerHTML = '<span class="text-primary fw-bold"><i class="fas fa-info-circle"></i> Normal İş Günü Seçildi (1.5x)</span>';
            
            // Hafta İçi Otomatik Saat Ayarı (Pzt-Cuma)
            if (gun >= 1 && gun <= 5) {
                if(baslangicSelect) baslangicSelect.value = "18:00";
            }
        }
    }

    // Flatpickr Kurulumu
    flatpickr("#mesaiTarih", {
        locale: "tr",
        dateFormat: "Y-m-d",
        altInput: true,
        altFormat: "d F Y",
        defaultDate: "today",
        disableMobile: true,
        onChange: genelAyarla,
        onDayCreate: function(dObj, dStr, fp, dayElem){
            let yil = dayElem.dateObj.getFullYear();
            let ay = (dayElem.dateObj.getMonth() + 1).toString().padStart(2, '0');
            let gun = dayElem.dateObj.getDate().toString().padStart(2, '0');
            let tamTarih = `${yil}-${ay}-${gun}`;

            if (resmiTatiller.includes(tamTarih)) {
                dayElem.className += " resmi-tatil";
            }
            else if (dayElem.dateObj.getDay() === 0) {
                dayElem.className += " pazar-gunu";
            }
        }
    });

    // Sayfa Yüklendiğinde
    setTimeout(() => {
        let today = new Date().toISOString().split('T')[0];
        genelAyarla([new Date()], today, null);
    }, 100);

</script>

<style>
    .flatpickr-day.resmi-tatil { background: #ffebee !important; border-color: #ffcdd2; color: #c62828; font-weight: bold; }
    .flatpickr-day.pazar-gunu { background: #fff3e0 !important; border-color: #ffe0b2; color: #ef6c00; font-weight: bold; }
</style>

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