sys/veri_detay/#008

PYBS (Personel Yönetim Bilgi Sistemi)

Son Senkronizasyon: 16.12.2025
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'; ?>
DATA_PAYLOAD (Açıklama)
Kapak

DEMO SÜRÜMÜDÜR TAM SÜRÜM İÇİN İLETİŞİM KURUN

📖 PYBS (Personel Yönetim Bilgi Sistemi) Kullanım Kılavuzu

🚀 Proje Tanımı

PYBS, personel bilgilerini, izinleri, maaş bordrolarını ve performans değerlendirmelerini merkezi ve dijital bir platformda yönetmek için tasarlanmış kapsamlı bir Personel Yönetim Bilgi Sistemi'dir. Amacımız, İnsan Kaynakları (İK) süreçlerini otomatikleştirerek verimliliği artırmak ve veri tutarlılığını sağlamaktır.

✨ Temel Özellikler

Personel Yönetimi: Çalışanların kişisel, iletişim ve görev bilgilerini kaydetme/güncelleme.

İzin Yönetimi: Çalışanların izin taleplerini oluşturma, onaylama/reddetme ve kalan izin haklarını takip etme.

Performans Değerlendirme: Yöneticilerin ve çalışanların performans hedeflerini belirlemesi ve değerlendirmeleri kaydetmesi.

Bordro Entegrasyonu: Maaş ve avans bilgilerini kaydetme ve bordro çıktılarını oluşturma (Harici sistemlerle entegrasyon potansiyeli).

Raporlama: İK yöneticileri için özet ve detaylı personel, izin ve bordro raporları oluşturma.

💻 Son Kullanıcı Kullanımı🔑 Giriş Yapma

Demo için kullanıcı adı : test.test

Demo için şifre : 123456

Demo hesabında root / yonetici vb yetki yoktur.

Tam sürüm için iletişime geçin.

Sistem "Ramsa Makine" tarafından aktif olarak kullanılmaktadır

Meta Veri (Özet)

İşyeri çalışanlarının maaş, fazla mesai ve puantaj ile bordro takip, kontrol ve raporlama sistemi

9,304
Sinyal (Ağ Hiti)
1.54 MB
Kapasite

Ağda Paylaş