<?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'; ?>