<?php
// modules/puantaj-cetveli.php
session_start();
require_once '../config/db.php';
require_once '../config/functions.php';
// Yetkiler
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'));
$rol_filtre = guvenlik($_GET['rol'] ?? 'tumu');
$personel_id = guvenlik($_GET['personel_id'] ?? 'tumu');
$gun_sayisi = cal_days_in_month(CAL_GREGORIAN, $ay, $yil);
$month_start = "$yil-$ay-01";
$month_end = date("Y-m-t", strtotime($month_start));
// --- PERSONEL LİSTESİ ÇEKME ---
$sql_per = "SELECT * FROM kullanicilar WHERE rol != 'root'";
if ($rol_filtre != 'tumu') $sql_per .= " AND rol = '$rol_filtre'";
if ($personel_id != 'tumu') $sql_per .= " AND id = " . (int)$personel_id;
$sql_per .= " ORDER BY ad ASC";
$tum_personeller = $pdo->query($sql_per)->fetchAll();
// --- FİLTRELEME ---
$personeller = [];
foreach ($tum_personeller as $p) {
$giris = $p['ise_giris_tarihi'];
$cikis = $p['isten_cikis_tarihi'];
$is_active = true;
if ($giris > $month_end) $is_active = false;
if (!empty($cikis) && $cikis < $month_start) $is_active = false;
if (!$is_active) {
$has_mesai = $pdo->query("SELECT COUNT(*) FROM mesai_hareketleri WHERE calisan_id={$p['id']} AND tarih BETWEEN '$month_start' AND '$month_end' AND durum='onaylandi'")->fetchColumn();
$has_izin = $pdo->query("SELECT COUNT(*) FROM izin_talepleri WHERE calisan_id={$p['id']} AND durum='onaylandi' AND (baslangic_tarihi <= '$month_end 23:59:59' AND bitis_tarihi >= '$month_start 00:00:00')")->fetchColumn();
if ($has_mesai > 0 || $has_izin > 0) $is_active = true;
}
if ($is_active) $personeller[] = $p;
}
// --- SİSTEM VERİLERİ ---
$tatiller = $pdo->query("SELECT tarih FROM resmi_tatiller")->fetchAll(PDO::FETCH_COLUMN);
$gunluk_saat_std = (float)($pdo->query("SELECT ayar_degeri FROM site_ayarlari WHERE ayar_anahtari = 'gunluk_mesai_saati'")->fetchColumn() ?: 9);
$tum_liste_select = $pdo->query("SELECT id, ad, soyad FROM kullanicilar WHERE rol != 'root' ORDER BY ad ASC")->fetchAll();
$aylar_tr_uzun = ['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'];
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 tarihFormatOzel($tarih_str) {
global $aylar_tr_uzun;
$d = date('d', strtotime($tarih_str));
$m = date('m', strtotime($tarih_str));
$y = date('Y', strtotime($tarih_str));
return $d . ' ' . $aylar_tr_uzun[$m] . ' ' . $y;
}
$puantaj_datasi = [];
$ucretsiz_izinler = ['hastalik', 'saatlik', 'mazeret', 'ucretsiz', 'mesaiye_gelmedi'];
foreach($personeller as $per) {
$pid = $per['id'];
$ise_giris = $per['ise_giris_tarihi'];
$isten_cikis = $per['isten_cikis_tarihi'];
for($d=1; $d<=$gun_sayisi; $d++) {
$g_tarih = "$yil-$ay-" . sprintf('%02d', $d);
$haftanin_gunu = date('N', strtotime($g_tarih));
$gun_aktif = true;
if ($g_tarih < $ise_giris) $gun_aktif = false;
elseif (!empty($isten_cikis) && $g_tarih > $isten_cikis) $gun_aktif = false;
$is_resmi_tatil = in_array($g_tarih, $tatiller);
$is_haftasonu = ($haftanin_gunu >= 6);
$is_pazar = ($haftanin_gunu == 7);
// --- GÜNCELLENEN KISIM: TÜM İZİNLERİ ÇEK (fetchAll) ---
$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([$pid, $g_tarih]);
$izinler = $stmt_izin->fetchAll(); // Çoklu izin
$stmt_mesai = $pdo->prepare("SELECT SUM(toplam_saat) as toplam, baslangic_saati, bitis_saati 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([$pid, $g_tarih]);
$mesai_row = $stmt_mesai->fetch();
$mesai_saat = $mesai_row['toplam'] ?: 0;
$ham_kesinti = 0.0;
$ham_mesai = (float)$mesai_saat;
$izin_metinleri = [];
$gunluk_fiili_calisma = 0.0;
// Çoklu izin değişkenleri
$sut_izni_var = false;
$ucretsiz_izin_toplam_saat = 0;
$tam_gun_izin_var = false;
$tam_gun_izin_turu = '';
// İzinleri Tara
foreach ($izinler as $iz) {
if ($iz['izin_turu'] == 'sut_izni') {
$sut_izni_var = true;
$b = date('H:i', strtotime($iz['baslangic_tarihi']));
$e = date('H:i', strtotime($iz['bitis_tarihi']));
$izin_metinleri[] = "SÜT ($b-$e)";
} elseif (in_array($iz['izin_turu'], $ucretsiz_izinler)) {
if ($iz['izin_turu'] == 'saatlik' || $iz['izin_turu'] == 'mesaiye_gelmedi') {
$ucretsiz_izin_toplam_saat += (float)$iz['saatlik_sure'];
$izin_metinleri[] = ($iz['izin_turu']=='mesaiye_gelmedi' ? 'Devamsız' : 'İzin') . ": -{$iz['saatlik_sure']}";
} else {
$tam_gun_izin_var = true;
$tam_gun_izin_turu = $iz['izin_turu'];
}
} else {
// Yıllık, babalık vb. (Ücretli tam gün)
$tam_gun_izin_var = true;
$tam_gun_izin_turu = $iz['izin_turu'];
}
}
if (!$gun_aktif) {
$ham_kesinti = 0; $ham_mesai = 0; $gunluk_fiili_calisma = 0;
}
else {
if (!$is_haftasonu && !$is_resmi_tatil) {
if ($tam_gun_izin_var) {
$gunluk_fiili_calisma = 0;
// Ücretli izinse (Yıllık vb.) maaştan kesilmez ama fiili çalışma 0'dır.
// Ücretsiz izinse (Hastalık vb.) maaştan kesilir (aşağıda ham_kesinti set edilecek).
} else {
$gunluk_fiili_calisma = $gunluk_saat_std - $ucretsiz_izin_toplam_saat;
}
} else {
$gunluk_fiili_calisma = 0;
}
if($gunluk_fiili_calisma < 0) $gunluk_fiili_calisma = 0;
// Kesinti Hesabı
if ($is_haftasonu || $is_resmi_tatil) {
$ham_kesinti = 0;
} else {
if ($tam_gun_izin_var && in_array($tam_gun_izin_turu, $ucretsiz_izinler)) {
$ham_kesinti = $gunluk_saat_std;
} else {
$ham_kesinti = $ucretsiz_izin_toplam_saat;
}
}
}
$net_kesinti = $ham_kesinti;
$net_mesai = $ham_mesai;
$mahsuplasma_var = false;
if ($ham_kesinti > 0 && $ham_mesai > 0) {
$mahsuplasma_var = true;
if ($ham_mesai >= $ham_kesinti) {
$net_mesai = $ham_mesai - $ham_kesinti;
$net_kesinti = 0;
} else {
$net_kesinti = $ham_kesinti - $ham_mesai;
$net_mesai = 0;
}
}
$mesai_carpan = ($is_resmi_tatil || $is_haftasonu) ? 2.0 : 1.5;
$mesai_net_hakedis = $net_mesai * $mesai_carpan;
$mesai_saat_araligi = ($ham_mesai > 0) ? substr($mesai_row['baslangic_saati'],0,5).'-'.substr($mesai_row['bitis_saati'],0,5) : "";
$puantaj_datasi[$pid][$g_tarih] = [
'aktif_mi' => $gun_aktif,
'gunluk_fiili_calisma' => $gunluk_fiili_calisma,
'is_resmi_tatil' => $is_resmi_tatil,
'is_pazar' => $is_pazar,
'haftanin_gunu' => $haftanin_gunu,
'tatil_tipi' => ($is_resmi_tatil ? 'Resmi Tatil' : ($haftanin_gunu == 7 ? 'Pazar' : ($haftanin_gunu == 6 ? 'Cumartesi' : ''))),
'ham_mesai' => $ham_mesai,
'ham_kesinti' => $ham_kesinti,
'net_mesai' => $net_mesai,
'net_kesinti' => $net_kesinti,
'mahsuplasma' => $mahsuplasma_var,
'sut_var' => $sut_izni_var,
'tam_gun_izin_var' => $tam_gun_izin_var,
'tam_gun_izin_turu' => $tam_gun_izin_turu,
'mesai_aralik' => $mesai_saat_araligi,
'mesai_net_hakedis' => $mesai_net_hakedis,
'detay_metinleri' => $izin_metinleri
];
}
}
?>
<style>
.bg-holiday { background-color: #ffebee !important; }
.bg-saturday { background-color: #f8f9fa !important; }
.bg-inactive { background-color: #e9ecef !important; background-image: repeating-linear-gradient(45deg, transparent, transparent 5px, #dee2e6 5px, #dee2e6 10px); }
.cell-content { font-size: 0.7rem; line-height: 1.2; font-weight: bold; }
.val-plus { color: #198754; display: block; }
.val-minus { color: #dc3545; display: block; }
.val-sut { color: #d63384; display: block; }
.val-izin { color: #0d6efd; display: block; }
</style>
<div class="container-fluid">
<div class="d-flex justify-content-between align-items-center mb-3">
<h3><i class="fas fa-table text-primary"></i> Puantaj Cetveli</h3>
</div>
<div class="card-box p-3 mb-3 border-top border-primary 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=2005; $y<=2030; $y++) echo "<option value='$y' ".($y==$yil?'selected':'').">$y</option>"; ?></select></div>
<div class="col-md-2"><label class="fw-bold small">Ay</label><select name="ay" class="form-select form-select-sm"><?php foreach($aylar_tr_uzun as $k=>$v) echo "<option value='$k' ".($k==$ay?'selected':'').">$v</option>"; ?></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">Tümü</option><option value="calisan">Personel</option><option value="vardiya_amiri">Vardiya Amiri</option><option value="mudur">Müdür</option></select></div>
<div class="col-md-3"><label class="fw-bold small">Personel</label><select name="personel_id" class="form-select form-select-sm"><option value="tumu">Herkes</option><?php foreach($tum_liste_select as $p) echo "<option value='{$p['id']}' ".($p['id']==$personel_id?'selected':'').">{$p['ad']} {$p['soyad']}</option>"; ?></select></div>
<div class="col-md-3 d-flex gap-1"><button type="button" onclick="submitForm('')" class="btn btn-primary btn-sm flex-grow-1">Listele</button><div class="btn-group"><button type="button" onclick="submitForm('excel')" class="btn btn-success btn-sm"><i class="fas fa-file-excel"></i></button><button type="button" onclick="submitForm('print')" class="btn btn-dark btn-sm"><i class="fas fa-print"></i></button></div></div>
<input type="hidden" name="format" id="exportFormat" value="">
</form>
</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.7rem;">
<thead class="table-dark">
<tr>
<th rowspan="2" class="align-middle text-start ps-2" style="min-width: 150px; position: sticky; left: 0; z-index: 10;">Personel Adı</th>
<?php for($d=1; $d<=$gun_sayisi; $d++):
$gun_tarih = "$yil-$ay-" . sprintf('%02d', $d);
$gun_kisa = gunIsmi($gun_tarih);
$is_resmi = in_array($gun_tarih, $tatiller);
$renk = ($gun_kisa == 'Pzr' || $is_resmi) ? 'bg-danger text-white' : (($gun_kisa == 'Cts') ? 'bg-secondary text-white' : '');
?>
<th class="<?php echo $renk; ?>" style="min-width: 35px;">
<?php echo $d; ?><br><small><?php echo $gun_kisa; ?></small>
</th>
<?php endfor; ?>
<th class="bg-primary border-start">N.M</th>
<th class="bg-success text-white">Net FM</th>
<th class="bg-warning text-dark">İZ</th>
</tr>
<tr>
<th colspan="<?php echo $gun_sayisi; ?>" class="bg-dark text-white">GÜNLÜK VERİLER</th>
<th colspan="3" class="bg-primary border-start text-white">TOPLAMLAR</th>
</tr>
</thead>
<tbody>
<?php if(empty($personeller)): ?>
<tr><td colspan="<?php echo $gun_sayisi + 4; ?>" class="text-center py-4">Bu kriterlere uygun aktif personel bulunamadı.</td></tr>
<?php endif; ?>
<?php foreach($personeller as $per):
$toplam_nm = 0;
$toplam_net_fazla = 0;
$toplam_izin_gun = 0;
$toplam_izin_saat = 0;
?>
<tr>
<td class="text-start ps-2 fw-bold bg-light" style="position: sticky; left: 0; z-index: 5;">
<?php echo $per['ad'].' '.$per['soyad']; ?>
</td>
<?php for($d=1; $d<=$gun_sayisi; $d++):
$g_tarih = "$yil-$ay-" . sprintf('%02d', $d);
$data = $puantaj_datasi[$per['id']][$g_tarih] ?? [];
$aktif = $data['aktif_mi'] ?? false;
$is_resmi = $data['is_resmi_tatil'];
$is_pazar = $data['is_pazar'];
if (!$aktif) $bg_class = "bg-inactive";
elseif ($is_resmi || $is_pazar) $bg_class = "bg-holiday";
elseif ($data['tatil_tipi'] == 'Cumartesi') $bg_class = "bg-saturday";
else $bg_class = "bg-white";
$hucre_icerik = "";
if (!$aktif) {
$hucre_icerik = "<span class='text-muted' style='font-size:0.6rem;'>X</span>";
} else {
// Süt İzni Varsa Göster
if ($data['sut_var']) {
$hucre_icerik .= "<div class='val-sut'>SÜT</div>";
$toplam_izin_saat += 1.5; // İstatistiki olarak süt iznini de ekleyebiliriz veya hariç tutabiliriz.
}
// Tam Gün İzin
if ($data['tam_gun_izin_var']) {
$izin_sayilsin = true;
if ($data['tam_gun_izin_turu'] == 'yillik' && ($is_resmi || $is_pazar)) $izin_sayilsin = false;
if ($izin_sayilsin) {
$toplam_izin_gun++;
$tur = strtoupper(substr($data['tam_gun_izin_turu'], 0, 3));
$hucre_icerik .= "<div class='val-izin'>{$tur}</div>";
}
}
// Saatlik Kesinti Varsa (Süt izni olsa bile altına eklenir)
elseif ($data['ham_kesinti'] > 0) {
$hucre_icerik .= "<div class='val-minus'>-{$data['ham_kesinti']}</div>";
$toplam_izin_saat += $data['ham_kesinti'];
}
if ($data['ham_mesai'] > 0) {
$hucre_icerik .= "<div class='val-plus'>+{$data['ham_mesai']}</div>";
}
$toplam_net_fazla += $data['net_mesai'];
$toplam_nm += $data['gunluk_fiili_calisma'];
if (empty($hucre_icerik) && !($is_resmi || $is_pazar)) {
$hucre_icerik = "<i class='fas fa-check text-muted opacity-25' style='font-size:0.6rem;'></i>";
}
}
$json_detay = htmlspecialchars(json_encode([
'tarih' => tarihFormatOzel($g_tarih),
'personel' => $per['ad'].' '.$per['soyad'],
'aktif' => $aktif,
'gunluk_fiili_calisma' => $data['gunluk_fiili_calisma'],
'ham_mesai' => $data['ham_mesai'],
'ham_kesinti' => $data['ham_kesinti'],
'sut_var' => $data['sut_var'],
'detaylar' => $data['detay_metinleri']
], JSON_UNESCAPED_UNICODE), ENT_QUOTES, 'UTF-8');
?>
<td class="<?php echo $bg_class; ?> cell-content align-middle"
style="cursor: pointer; height: 45px;"
onclick="gunDetayGoster(this)"
data-detay='<?php echo $json_detay; ?>'>
<?php echo $hucre_icerik; ?>
</td>
<?php endfor; ?>
<td class="fw-bold border-start bg-primary bg-opacity-10 text-primary"><?php echo $toplam_nm; ?></td>
<td class="fw-bold text-success">+<?php echo (float)$toplam_net_fazla; ?></td>
<td class="fw-bold text-warning" style="font-size: 0.65rem;">
<?php
$izin_str = [];
if($toplam_izin_gun > 0) $izin_str[] = $toplam_izin_gun . "g";
if($toplam_izin_saat > 0) $izin_str[] = $toplam_izin_saat . "s";
echo empty($izin_str) ? '0' : implode(' ', $izin_str);
?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<div class="modal fade" id="gunDetayModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content shadow border-0">
<div class="modal-header bg-primary text-white py-2">
<h6 class="modal-title mb-0"><i class="fas fa-info-circle me-2"></i> Hareket Analizi</h6>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body p-3">
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-3">
<span class="fw-bold text-dark" id="modalTarih"></span>
<span class="badge bg-secondary" id="modalPersonel"></span>
</div>
<div id="modalIcerik"></div>
</div>
<div class="modal-footer bg-light border-0 py-1">
<button type="button" class="btn btn-sm btn-secondary w-100" data-bs-dismiss="modal">Kapat</button>
</div>
</div>
</div>
</div>
<script>
function submitForm(type) {
const form = document.getElementById('puantajForm');
document.getElementById('exportFormat').value = type;
if (type === 'excel' || type === 'print') { form.action = 'puantaj-rapor.php'; form.target = '_blank'; }
else { form.action = 'puantaj-cetveli.php'; form.target = '_self'; }
form.submit();
}
function gunDetayGoster(tdElement) {
const dataStr = tdElement.getAttribute('data-detay');
if (!dataStr) return;
const data = JSON.parse(dataStr);
document.getElementById('modalTarih').innerText = data.tarih;
document.getElementById('modalPersonel').innerText = data.personel;
let html = '<ul class="list-group list-group-flush small">';
if (!data.aktif) {
html += `<li class="list-group-item bg-light text-muted text-center py-3"><i class="fas fa-user-slash fa-2x mb-2 opacity-25"></i><br>Personel bu tarihte şirkette aktif değil.</li>`;
} else {
html += `<li class="list-group-item d-flex justify-content-between"><span><i class="fas fa-briefcase text-primary me-2"></i> Normal Mesai (N.M):</span><span class="fw-bold text-primary">${data.gunluk_fiili_calisma} Saat</span></li>`;
// Detayları Listele
if (data.detaylar && data.detaylar.length > 0) {
data.detaylar.forEach(d => {
let color = d.includes('SÜT') ? 'text-danger' : 'text-primary';
html += `<li class="list-group-item fw-bold ${color}">${d}</li>`;
});
}
if (data.ham_mesai > 0) {
html += `<li class="list-group-item"><strong class="text-success">Fazla Mesai: +${data.ham_mesai} Saat</strong></li>`;
}
}
html += '</ul>';
document.getElementById('modalIcerik').innerHTML = html;
new bootstrap.Modal(document.getElementById('gunDetayModal')).show();
}
</script>
<?php include '../includes/footer.php'; ?>