<?php
// modules/admin-mesai-ekle.php
session_start();
require_once '../config/db.php';
require_once '../config/functions.php';
// Sadece Yetkililer
yetkiKontrol(['root', 'muhasebe', 'insan_kaynaklari']);
include '../includes/header.php';
include '../includes/menu.php';
$mesaj = '';
$kullanici_id = $_SESSION['kullanici_id'];
$hedef = 'tekil'; // Varsayılan: Tekil
// Resmi Tatil Listesi
$tatiller = $pdo->query("SELECT tarih FROM resmi_tatiller")->fetchAll(PDO::FETCH_COLUMN);
$tatiller_json = json_encode($tatiller);
// SAAT SEÇENEKLERİ
$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>";
}
}
// İŞLEM
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
csrfKontrol($_POST['csrf_token']);
$hedef = $_POST['hedef_kitle'];
$eklenecekler = [];
if ($hedef == 'toplu') {
$eklenecekler = $pdo->query("SELECT id FROM kullanicilar WHERE durum=1 AND rol != 'root'")->fetchAll(PDO::FETCH_COLUMN);
} elseif ($hedef == 'coklu') {
$eklenecekler = $_POST['personel_id_coklu'] ?? [];
} elseif ($hedef == 'tekil') {
if (!empty($_POST['personel_id_tekil'])) {
$eklenecekler[] = $_POST['personel_id_tekil'];
}
}
$tarih = $_POST['tarih'];
$bas_saat = $_POST['baslangic_saati'];
$bit_saat = $_POST['bitis_saati'];
$mesai_turu = $_POST['mesai_turu'];
$aciklama = guvenlik($_POST['aciklama']);
// Brüt Süre Hesapla
$t1 = strtotime($bas_saat);
$t2 = strtotime($bit_saat);
if ($t2 < $t1) $t2 += 24 * 60 * 60;
$fark = round(($t2 - $t1) / 3600, 2);
$net_mesai_kayit = $fark; // Mola düşümü yok, net süre
$sayac = 0;
$hata_mesajlari = [];
$sql = "INSERT INTO mesai_hareketleri (calisan_id, hedef_yonetici_id, onaylayan_id, tarih, baslangic_saati, bitis_saati, toplam_saat, mesai_turu, aciklama, durum, onaylanma_tarihi)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, 'onaylandi', NOW())";
$stmt = $pdo->prepare($sql);
if (!empty($eklenecekler)) {
// Personel verilerini çek
$personel_data_stmt = $pdo->prepare("SELECT id, ad, soyad FROM kullanicilar WHERE id IN (" . implode(',', $eklenecekler) . ")");
$personel_data_stmt->execute();
$personel_bilgileri = $personel_data_stmt->fetchAll(PDO::FETCH_ASSOC | PDO::FETCH_GROUP);
foreach ($eklenecekler as $pid) {
$pid = (int)$pid;
$personel_info = $personel_bilgileri[$pid][0] ?? null;
if (!$personel_info) continue;
$personel_ad = $personel_info['ad'] . ' ' . $personel_info['soyad'];
$hata = false;
// 1. ZATEN MESAI VAR MI?
$kontrol_mesai = $pdo->prepare("SELECT count(*) FROM mesai_hareketleri WHERE calisan_id = ? AND tarih = ? AND durum = 'onaylandi' AND ( (baslangic_saati < ? AND bitis_saati > ?) )");
$kontrol_mesai->execute([$pid, $tarih, $bit_saat, $bas_saat]);
if ($kontrol_mesai->fetchColumn() > 0) {
$hata_mesajlari[] = "({$personel_ad}) $tarih tarihinde belirtilen saatlerde ($bas_saat - $bit_saat) zaten mesai kaydı var.";
$hata = true;
}
// 2. İZİN ÇAKIŞMASI
if (!$hata) {
$kontrol_izin = $pdo->prepare("SELECT izin_turu, baslangic_tarihi, bitis_tarihi FROM izin_talepleri WHERE calisan_id = ? AND durum = 'onaylandi' AND ? BETWEEN DATE(baslangic_tarihi) AND DATE(bitis_tarihi)");
$kontrol_izin->execute([$pid, $tarih]);
$izin_kaydi = $kontrol_izin->fetch();
if ($izin_kaydi) {
$i_bas_ts = strtotime($izin_kaydi['baslangic_tarihi']);
$i_bit_ts = strtotime($izin_kaydi['bitis_tarihi']);
$izin_bas_gun = date('Y-m-d', $i_bas_ts);
$izin_bit_gun = date('Y-m-d', $i_bit_ts);
if ($izin_bas_gun != $izin_bit_gun) {
$hata_mesajlari[] = "({$personel_ad}) Personel çok günlü izinli ({$izin_bas_gun} / {$izin_bit_gun}). Bu tarihte mesai yazılamaz.";
$hata = true;
}
else {
$izin_bitis_saati = date('H:i', $i_bit_ts);
$mesai_baslangic_saati = $bas_saat;
if ($mesai_baslangic_saati < $izin_bitis_saati) {
$hata_mesajlari[] = "({$personel_ad}) Tek günlük izin devam ediyor. Mesai saati ($bas_saat), izin bitişinden ($izin_bitis_saati) sonra olmalıdır.";
$hata = true;
}
}
}
}
if (!$hata) {
try {
$gercek_mesai_turu = $mesai_turu;
if ($mesai_turu === 'vardiya_gece') $gercek_mesai_turu = 'fazla_mesai';
$stmt->execute([$pid, $kullanici_id, $kullanici_id, $tarih, $bas_saat, $bit_saat, $net_mesai_kayit, $gercek_mesai_turu, $aciklama]);
$sayac++;
} catch (PDOException $e) {
$hata_mesajlari[] = "({$personel_ad}) Veritabanı Hatası: " . $e->getMessage();
}
}
}
}
$mesaj_html = "";
if ($sayac > 0) {
$mesaj_html .= '<div class="alert alert-success border-success border-5 border-start shadow-sm">
<h5 class="alert-heading fw-bold"><i class="fas fa-check-circle me-2"></i>Başarılı!</h5>
Toplam <strong>'.$sayac.'</strong> personele mesai girişi yapıldı.
</div>';
}
if (!empty($hata_mesajlari)) {
$hata_listesi = '<ul>';
foreach ($hata_mesajlari as $hata) $hata_listesi .= '<li>'.$hata.'</li>';
$hata_listesi .= '</ul>';
$mesaj_html .= '
<div class="alert alert-warning border-warning border-5 border-start shadow-sm">
<h5 class="alert-heading fw-bold"><i class="fas fa-exclamation-triangle me-2"></i>Mesai İşlemi Uyarıları!</h5>
Bazı kayıtlar kurallar gereği engellendi:
<button type="button" class="btn btn-sm btn-warning mt-2" data-bs-toggle="modal" data-bs-target="#hataModal">
<i class="fas fa-search me-1"></i> Detayları Gör
</button>
</div>
<div class="modal fade" id="hataModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header bg-warning text-dark"><h5 class="modal-title">Engellenen İşlemler</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div>
<div class="modal-body"><div class="alert alert-light border-warning">'.$hata_listesi.'</div></div>
<div class="modal-footer"><button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Kapat</button></div>
</div>
</div>
</div>';
}
if ($sayac == 0 && empty($hata_mesajlari)) {
$mesaj_html .= '<div class="alert alert-danger">Lütfen işlem yapılacak personel seçin.</div>';
}
$mesaj = $mesaj_html;
}
$personeller = $pdo->query("SELECT id, ad, soyad FROM kullanicilar WHERE durum=1 AND rol != 'root' ORDER BY ad ASC")->fetchAll();
?>
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<style>
body { background-color: #f8f9fa; }
.card { border: none; border-radius: 1.5rem; overflow: hidden; }
.card-header { background: linear-gradient(135deg, #0d6efd, #0dcaf0); color: white; }
.flatpickr-day.resmi-tatil { background: #ffebee !important; border-color: #ffcdd2 !important; color: #c62828 !important; font-weight: bold; }
.flatpickr-day.pazar-gunu { background: #fff3e0 !important; border-color: #ffe0b2 !important; color: #ef6c00 !important; font-weight: bold; }
</style>
</head>
<body>
<div class="container-fluid py-4 py-md-5">
<div class="row justify-content-center">
<div class="col-12 col-lg-10 col-xl-8">
<h3 class="mb-4 text-center text-primary fw-bold"><i class="fas fa-clock me-2"></i>Yönetici Mesai Girişi</h3>
<div class="card shadow-lg">
<div class="card-header py-4 text-center"><h5 class="mb-0 text-white fw-bold">Mesai Bilgilerini Giriniz</h5></div>
<div class="card-body p-4 p-md-5">
<?php echo $mesaj; ?>
<form method="POST" id="mesaiForm">
<input type="hidden" name="csrf_token" value="<?php echo csrfTokenOlustur(); ?>">
<div class="mb-4">
<label class="form-label fw-semibold">Kime Mesai Eklenecek?</label>
<div class="btn-group w-100">
<input type="radio" class="btn-check" name="hedef_kitle" id="toplu" value="toplu" onchange="togglePersonel()">
<label class="btn btn-outline-primary" for="toplu">Tüm Personel</label>
<input type="radio" class="btn-check" name="hedef_kitle" id="coklu" value="coklu" onchange="togglePersonel()">
<label class="btn btn-outline-primary" for="coklu">Çoklu Seçim</label>
<input type="radio" class="btn-check" name="hedef_kitle" id="tekil" value="tekil" checked onchange="togglePersonel()">
<label class="btn btn-outline-primary" for="tekil">Tek Personel</label>
</div>
</div>
<div class="mb-4" id="tekilDiv">
<label class="form-label fw-semibold">Personel Seçiniz</label>
<select name="personel_id_tekil" id="personel_id_tekil" class="form-select form-select-lg">
<option value="">Seçiniz...</option>
<?php foreach($personeller as $p) echo "<option value='{$p['id']}'>{$p['ad']} {$p['soyad']}</option>"; ?>
</select>
</div>
<div class="mb-4 d-none" id="cokluDiv">
<label class="form-label fw-semibold">Personelleri Seçiniz (Çoklu)</label>
<select name="personel_id_coklu[]" id="personel_id_coklu" class="form-select form-select-lg" multiple size="8">
<?php foreach($personeller as $p) echo "<option value='{$p['id']}'>{$p['ad']} {$p['soyad']}</option>"; ?>
</select>
<div class="form-text">Çoklu seçim için Ctrl tuşuna basılı tutun.</div>
</div>
<div class="row g-3 mb-4">
<div class="col-md-6">
<label class="form-label fw-semibold">Tarih</label>
<input type="text" name="tarih" id="mesaiTarihInput" class="form-control bg-white fw-bold" required value="<?php echo date('Y-m-d'); ?>">
</div>
<div class="col-md-6">
<label class="form-label fw-semibold">Mesai Türü</label>
<select name="mesai_turu" id="mesaiTuruSelect" class="form-select bg-light fw-bold">
<option value="fazla_mesai">Fazla Mesai (1.5x)</option>
<option value="resmi_tatil_mesaisi">Resmi Tatil / Bayram (2.0x)</option>
<option value="vardiya_gece">Vardiya Girişi</option>
</select>
</div>
</div>
<div class="row g-3 mb-4">
<div class="col-md-6">
<label class="form-label fw-semibold">Başlangıç Saati</label>
<select name="baslangic_saati" class="form-select form-select-lg" required>
<option value="">Seçiniz</option><?php echo $zaman_secenekleri; ?>
</select>
</div>
<div class="col-md-6">
<label class="form-label fw-semibold">Bitiş Saati</label>
<select name="bitis_saati" class="form-select form-select-lg" required>
<option value="">Seçiniz</option><?php echo $zaman_secenekleri; ?>
</select>
</div>
</div>
<div class="mb-4"><label class="form-label fw-semibold">Açıklama</label><input type="text" name="aciklama" class="form-control form-control-lg"></div>
<div class="d-grid"><button type="submit" class="btn btn-primary btn-lg shadow">KAYDET VE İŞLE</button></div>
</form>
</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 src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
const resmiTatiller = <?php echo $tatiller_json; ?>;
document.addEventListener('DOMContentLoaded', function() {
flatpickr("#mesaiTarihInput", {
locale: "tr",
dateFormat: "Y-m-d",
altInput: true,
altFormat: "d F Y",
defaultDate: "today",
disableMobile: true,
onChange: function(selectedDates, dateStr) { mesaiTuruOtoSec(dateStr); },
onDayCreate: function(dObj, dStr, fp, dayElem){
// DÜZELTME: toISOString() yerine Flatpickr'ın kendi formatlayıcısını kullanıyoruz
// Bu sayede timezone (saat dilimi) kayması önlenir.
let d = fp.formatDate(dayElem.dateObj, "Y-m-d");
if (resmiTatiller.includes(d)) {
dayElem.className += " resmi-tatil";
} else if (dayElem.dateObj.getDay() === 0) {
dayElem.className += " pazar-gunu";
}
}
});
togglePersonel();
mesaiTuruOtoSec(new Date().toISOString().split('T')[0]);
if(document.getElementById('hataModal')) new bootstrap.Modal(document.getElementById('hataModal')).show();
});
function togglePersonel() {
const hedef = document.querySelector('input[name="hedef_kitle"]:checked').value;
document.getElementById('tekilDiv').classList.toggle('d-none', hedef !== 'tekil');
document.getElementById('cokluDiv').classList.toggle('d-none', hedef !== 'coklu');
document.getElementById('personel_id_tekil').required = (hedef === 'tekil');
document.getElementById('personel_id_coklu').required = (hedef === 'coklu');
}
function mesaiTuruOtoSec(dateStr) {
if (!dateStr) return;
const date = new Date(dateStr);
const day = date.getDay();
let tur = (resmiTatiller.includes(dateStr) || day === 0) ? 'resmi_tatil_mesaisi' : 'fazla_mesai';
document.getElementById('mesaiTuruSelect').value = tur;
}
</script>
<?php include '../includes/footer.php'; ?>
</body>
</html>