<?php
// modules/maas-rapor.php
session_start();
require_once '../config/db.php';
require_once '../config/functions.php';
// Yetkili Roller: Root, Yönetici, Muhasebe, İnsan Kaynakları
yetkiKontrol(['root', 'yonetici', 'muhasebe', 'insan_kaynaklari']);
// --- FİLTRELER VE PARAMETRELER ---
$yil = $_GET['yil'] ?? date('Y');
$ay = $_GET['ay'] ?? date('m');
$format = $_GET['format'] ?? 'print'; // 'excel' veya 'pdf' (print)
$personel_filtre_id = $_GET['personel_id'] ?? 'tumu'; // ID, Rol adı veya 'tumu'
// Rapor tarihi, saat ve zaman dilimi ayarı
date_default_timezone_set('Europe/Istanbul');
$rapor_tarihi_saati = date('d.m.Y H:i');
$ay_isimleri = ['01'=>'OCAK','02'=>'ŞUBAT','03'=>'MART','04'=>'NİSAN','05'=>'MAYIS','06'=>'HAZİRAN','07'=>'TEMMUZ','08'=>'AĞUSTOS','09'=>'EYLÜL','10'=>'EKİM','11'=>'KASIM','12'=>'ARALIK'];
// BAŞLIK
$baslik = "MAAŞ BORDROSU - " . $ay_isimleri[$ay] . " " . $yil;
// --- YARDIMCI FORMAT FONKSİYONU ---
function formatSaat($saat) {
if ($saat === null || $saat === 0.0 || $saat === 0) return 0;
// Eğer saat tam sayı ise ondalık kısmı gösterme (örn: 2.0 -> 2)
if ($saat == floor($saat)) {
return (int)$saat;
}
// Değilse, bir ondalık basamak göster (örn: 2.5)
return number_format($saat, 1, '.', '');
}
// -------------------------------------
// --- HESAPLAMA MANTIKLARI ---
$gun_sayisi = cal_days_in_month(CAL_GREGORIAN, $ay, $yil);
$carpan_15 = 1.5;
$carpan_20 = 2.0;
$gunluk_saat_std = 9.0; // Sabit 9 saat varsayımı
$tatiller = $pdo->query("SELECT tarih FROM resmi_tatiller")->fetchAll(PDO::FETCH_COLUMN);
// Rol Bazlı Toplu Filtreleme Seçenekleri (maas-hesapla.php'den taşındı)
$rol_filtreleri = [
'yonetici' => 'Tüm Yöneticiler',
'mudur' => 'Tüm Müdürler',
// Diğer roller...
];
// Personel Listesi SQL'i
// Sorguya TC No'yu da ekledik
$sql_per = "SELECT id, ad, soyad, aylik_net_maas, tc_no FROM kullanicilar WHERE durum=1 AND rol != 'root'"; // root hariç
$tek_personel_bilgi = null; // TC no bilgisini tutmak için
if ($personel_filtre_id != 'tumu') {
if (is_numeric($personel_filtre_id)) {
$sql_per .= " AND id = " . (int)$personel_filtre_id;
} elseif (isset($rol_filtreleri[$personel_filtre_id])) {
$sql_per .= " AND rol = " . $pdo->quote($personel_filtre_id);
}
}
$sql_per .= " ORDER BY ad ASC";
$personeller = $pdo->query($sql_per)->fetchAll();
// Raporlanacak veriyi tutacak dizi
$rapor_verileri = [];
// --- PUANTAJ DETAYI HAZIRLIĞI (Sadece tek kişi seçiliyse) ---
$puantaj_html = '';
$gun_kisa = ['Mon'=>'Pzt', 'Tue'=>'Sal', 'Wed'=>'Çar', 'Thu'=>'Per', 'Fri'=>'Cum', 'Sat'=>'Cts', 'Sun'=>'Pzr'];
$izin_turleri_map = ['yillik'=>'Y.İZ', 'mazeret'=>'MAZ', 'hastalik'=>'RAP', 'evlilik'=>'EVL', 'babalik'=>'BAB', 'olum'=>'ÖLM', 'diger'=>'ÜCR.İZ', 'saatlik'=>'S.İZ'];
if (count($personeller) == 1 && is_numeric($personel_filtre_id)) {
$per = $personeller[0];
$tek_personel_bilgi = $per; // TC No bilgisini çekmek için
// PUANTAJ BAŞLIK SATIRI
$puantaj_baslik_html = '<tr><th style="width: 150px; position: sticky; left: 0;">PERSONEL / GÜN</th>';
for($d=1; $d<=$gun_sayisi; $d++):
$tarih_str = "$yil-$ay-" . sprintf('%02d', $d);
$gun_ing = date('D', strtotime($tarih_str));
$gun_tr = $gun_kisa[$gun_ing];
$is_tatil_gunu = in_array($tarih_str, $tatiller) || $gun_ing == 'Sun';
$renk = $is_tatil_gunu ? 'style="background-color: #fdd; color: #a00;"' : '';
$puantaj_baslik_html .= "<th {$renk}>{$d}<br>{$gun_tr}</th>";
endfor;
$puantaj_baslik_html .= '</tr>';
$normal_calisma_satiri = '<tr class="normal-calisma-satiri" style="font-weight: bold;"><td>NM / İZ</td>';
$fazla_mesai_satiri = '<tr><td style="font-weight: bold;">FM</td>';
// VERİ SATIRLARI
for($d=1; $d<=$gun_sayisi; $d++) {
$g_tarih = "$yil-$ay-" . sprintf('%02d', $d);
$haftanin_gunu = date('N', strtotime($g_tarih));
$is_tatil = in_array($g_tarih, $tatiller);
$is_haftasonu = ($haftanin_gunu >= 6);
$is_tatil_gunu = $is_tatil || $is_haftasonu;
$nm_hucre_content = '';
$fm_hucre_content = '';
$nm_hucre_style = '';
$net_kesinti_saati = 0;
// --- 1. İzinleri Kontrol Et ---
$izin = $pdo->query("SELECT izin_turu, saatlik_sure, baslangic_tarihi, bitis_tarihi FROM izin_talepleri
WHERE calisan_id={$per['id']} AND durum='onaylandi' AND '$g_tarih' BETWEEN DATE(baslangic_tarihi) AND DATE(bitis_tarihi)")->fetch();
// --- 2. Mesaileri Kontrol Et ---
$mesai = $pdo->query("SELECT SUM(toplam_saat) FROM mesai_hareketleri
WHERE calisan_id={$per['id']} AND durum='onaylandi' AND tarih='$g_tarih'
AND mesai_turu IN ('fazla_mesai', 'hafta_tatili', 'resmi_tatil_mesaisi')")->fetchColumn() ?: 0;
// --- İZİN / NORMAL SAAT KONTROLÜ ---
if ($izin) {
$tur_kisaltma = $izin_turleri_map[$izin['izin_turu']] ?? 'İZ';
if (in_array($izin['izin_turu'], ['saatlik', 'diger'])) {
// Kesintili İzin Hesabı (Maaş Hesaplama mantığı ile uyumlu)
if ($izin['izin_turu'] == 'diger') {
$net_kesinti_saati = 9.0;
} elseif ($izin['izin_turu'] == 'saatlik') {
$bas_saat_str = date('H:i', strtotime($izin['baslangic_tarihi']));
$bit_saat_str = date('H:i', strtotime($izin['bitis_tarihi']));
if ($haftanin_gunu <= 5 && $bas_saat_str === '08:00' && $bit_saat_str === '12:00') {
$net_kesinti_saati = 4.0;
} elseif ($haftanin_gunu <= 5 && $bas_saat_str === '13:00' && $bit_saat_str === '18:00') {
$net_kesinti_saati = 5.0;
} else {
$net_kesinti_saati = (float)$izin['saatlik_sure'];
}
}
// Hücre İçeriği: Kesinti Gösterimi
$nm_hucre_content = "<span style='color: red;'>- " . formatSaat($net_kesinti_saati) . "</span>";
$nm_hucre_style = 'style="background-color: #fce4e4;"'; // Kırmızımsı arka plan
} else {
// Tam Gün Ücretli İzin
$nm_hucre_content = $tur_kisaltma;
$nm_hucre_style = 'style="background-color: #e3f2fd;"'; // Mavimsi arka plan
}
} elseif (!$is_tatil_gunu) {
// Hafta içi ve izinsiz: Tam Çalışma (Tik işareti)
$nm_hucre_content = '<span style="color: green; font-size: 1.2em;">✓</span>'; // Unicode tik işareti
$nm_hucre_style = 'style="background-color: #e6ffe6;"'; // Açık yeşil arka plan
} else {
// Tatil veya Hafta Sonu: T işareti (Tatil)
$nm_hucre_content = 'T';
$nm_hucre_style = 'style="background-color: #f7f7f7;"'; // Açık gri arka plan
}
// --- FAZLA MESAİ KONTROLÜ ---
if ($mesai > 0) {
$fm_hucre_content = "<span style='color: green;'>+ " . formatSaat($mesai) . "</span>";
} else {
$fm_hucre_content = '-';
}
$normal_calisma_satiri .= "<td {$nm_hucre_style}>{$nm_hucre_content}</td>";
$fazla_mesai_satiri .= "<td>{$fm_hucre_content}</td>";
}
$normal_calisma_satiri .= '</tr>';
$fazla_mesai_satiri .= '</tr>';
// Detaylı Puantaj HTML'i oluştur
$puantaj_html = '
<h2 style="font-size: 14px; margin-top: 30px; border-bottom: 1px solid #ccc; padding-bottom: 5px;">
Aylık Puantaj Detayı
</h2>
<table style="font-size: 10px; table-layout: fixed;">
<thead>
' . $puantaj_baslik_html . '
</thead>
<tbody>
' . $normal_calisma_satiri . '
' . $fazla_mesai_satiri . '
</tbody>
</table>
<p style="font-size: 9px; margin-top: 5px;">
Açıklamalar: NM/İZ: Normal Çalışma/İzin Durumu | FM: Onaylı Fazla Mesai Saati. | <span style="color: red;">- X</span>: Kesinti Saati | <span style="color: green;">✓</span>: Tam Çalışma (9s) | T: Tatil/Hafta Sonu.
</p>
';
}
// --- PUANTAJ DETAYI HAZIRLIĞI SONU ---
foreach($personeller as $per) {
// ... Finansal Hesaplamalar (Aynı kalır) ...
$aylik_net_maas = (float)$per['aylik_net_maas'];
if ($aylik_net_maas <= 0) continue;
$saatlik_ucret = $aylik_net_maas / 225;
$kazanc_15_saat = 0;
$kazanc_20_saat = 0;
$kesinti_saat = 0;
// --- AVANS ÇEKİMİ ---
$stmt_avans = $pdo->prepare("SELECT SUM(avans_miktari) FROM avans_hareketleri WHERE calisan_id = ? AND islem_tarihi BETWEEN ? AND ? AND durum = 'onaylandi'");
$stmt_avans->execute([$per['id'], date('Y-m-01', strtotime("$yil-$ay-01")), date('Y-m-t', strtotime("$yil-$ay-01"))]);
$aylik_avans_tutar = $stmt_avans->fetchColumn() ?: 0.00;
// ---------------------
// GÜNLÜK DÖNGÜ (Fazla mesai ve izin kesintilerini toplama)
for($d=1; $d<=$gun_sayisi; $d++) {
$tarih = "$yil-$ay-" . sprintf('%02d', $d);
$gun_no = date('N', strtotime($tarih));
$is_tatil = in_array($tarih, $tatiller);
$izin = $pdo->query("SELECT izin_turu, saatlik_sure, baslangic_tarihi, bitis_tarihi FROM izin_talepleri
WHERE calisan_id={$per['id']} AND durum='onaylandi'
AND '$tarih' BETWEEN DATE(baslangic_tarihi) AND DATE(bitis_tarihi)")->fetch();
if ($izin) {
if ($izin['izin_turu'] == 'diger') {
$kesinti_saat += 9;
} elseif ($izin['izin_turu'] == 'saatlik') {
$izin_sure = (float)$izin['saatlik_sure'];
$bas_saat_str = date('H:i', strtotime($izin['baslangic_tarihi']));
$bit_saat_str = date('H:i', strtotime($izin['bitis_tarihi']));
if ($gun_no <= 5 && $bas_saat_str === '08:00' && $bit_saat_str === '12:00') {
$kesinti_saat += 4.0;
} elseif ($gun_no <= 5 && $bas_saat_str === '13:00' && $bit_saat_str === '18:00') {
$kesinti_saat += 5.0;
} else {
$kesinti_saat += $izin_sure;
}
}
}
$mesai = $pdo->query("SELECT SUM(toplam_saat) FROM mesai_hareketleri
WHERE calisan_id={$per['id']} AND durum='onaylandi'
AND tarih='$tarih'
AND mesai_turu IN ('fazla_mesai', 'hafta_tatili', 'resmi_tatil_mesaisi')")->fetchColumn() ?: 0;
if ($mesai > 0) {
$gun_no = date('N', strtotime($tarih));
$is_pazar = ($gun_no == 7);
if ($is_pazar || $is_tatil) {
$kazanc_20_saat += $mesai;
} else {
$kazanc_15_saat += $mesai;
}
}
}
// Nihai Hesaplama
$tutar_15 = $kazanc_15_saat * ($saatlik_ucret * $carpan_15);
$tutar_20 = $kazanc_20_saat * ($saatlik_ucret * $carpan_20);
$toplam_ek = $tutar_15 + $tutar_20;
$tutar_izin_kesinti = $kesinti_saat * $saatlik_ucret;
$toplam_kesinti_tutar = $tutar_izin_kesinti + $aylik_avans_tutar;
$toplam_hakedis = $aylik_net_maas + $toplam_ek - $toplam_kesinti_tutar;
$rapor_verileri[] = [
'ad_soyad' => $per['ad'].' '.$per['soyad'],
'net_maas' => number_format($aylik_net_maas, 2, '.', ''),
'saat_15' => formatSaat($kazanc_15_saat),
'saat_20' => formatSaat($kazanc_20_saat),
'tutar_ek' => number_format($toplam_ek, 2, '.', ''),
'saat_izin_kesinti' => formatSaat($kesinti_saat),
'tutar_avans' => number_format($aylik_avans_tutar, 2, '.', ''),
'tutar_toplam_kesinti' => number_format($tutar_izin_kesinti + $aylik_avans_tutar, 2, '.', ''),
'toplam_hakedis' => number_format($toplam_hakedis, 2, '.', '')
];
}
// --- RAPOR ÇIKTI BAŞLIKLARI (Excel/PDF) ---
if ($format == 'excel') {
header("Content-Type: application/vnd.ms-excel; charset=utf-8");
header("Content-Disposition: attachment; filename=Maas_Bordrosu_{$yil}_{$ay}.xls");
header("Pragma: no-cache");
header("Expires: 0");
echo "\xEF\xBB\xBF"; // BOM
} elseif ($format == 'pdf') {
// Print/PDF çıktısı için özel CSS eklenecek
}
?>
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<title>Ramsa Makine Sanayii Personel Yönetim Bilgi Sistemi - Bordro</title>
<style>
body { font-family: Arial, sans-serif; font-size: 11px; margin: 0; padding: 20px; }
/* RAPOR ANTEPİ VE LOGO */
.rapor-header {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 3px solid #333;
padding-bottom: 10px;
margin-bottom: 20px;
}
.rapor-header img { max-height: 50px; }
.rapor-header h1 {
font-size: 16px;
font-weight: bold;
margin: 0;
color: #333;
}
.rapor-header p {
font-size: 10px;
margin: 0;
color: #666;
}
/* TABLO STİLİ */
table { width: 100%; border-collapse: collapse; margin-bottom: 20px; }
th, td { border: 1px solid #000; padding: 5px; text-align: center; }
th { background-color: #ddd; font-weight: bold; }
.text-start { text-align: left !important; }
.bg-success-light { background-color: #d1e7dd; }
/* İmza Alanı Stilleri */
.imza-blogu { display: flex; justify-content: space-around; margin-top: 50px; page-break-inside: avoid; }
.imza-kutu { width: 25%; text-align: center; padding: 10px; }
.imza-baslik { font-weight: bold; border-top: 1px solid #000; padding-top: 5px; margin-top: 40px; font-size: 11px; }
/* PUANTAJ DETAY TABLOSU ÖZEL STİLLER */
.puantaj-detay table { table-layout: fixed; width: 100%; }
.puantaj-detay th, .puantaj-detay td { padding: 3px; }
.puantaj-detay .normal-calisma-satiri td { font-size: 9px; }
.puantaj-detay .tik-isareti { font-family: Arial, "DejaVu Sans", sans-serif; font-weight: bold; font-size: 1.2em; color: green; }
/* PDF/PRINT ÖZEL STİLLER */
@media print {
body { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
.no-print { display: none; }
.rapor-header { border-bottom-color: #000; }
th { background-color: #eee !important; }
.bg-success-light { background-color: #d1e7dd !important; }
.imza-blogu { margin-top: 80px; }
.imza-baslik { border-top-color: #000 !important; }
/* Excel için tek sayfaya sığdırma (Sadece CSS'te yatay ayar ile desteklenir) */
@page {
size: landscape;
margin: 15mm;
/* Aşağıdaki satırlar URL'yi gizler */
@bottom-left { content: ""; }
@bottom-right { content: ""; }
@top-left { content: ""; }
@top-right { content: ""; }
}
}
</style>
</head>
<body>
<?php if($format == 'pdf'): ?>
<div class="no-print" style="margin-bottom: 20px;">
<button onclick="window.print()" style="padding: 10px 20px; font-weight: bold; cursor: pointer;">🖨️ YAZDIR / PDF OLUŞTUR</button>
</div>
<?php endif; ?>
<div class="rapor-header">
<img src="../assets/img/logo.png" alt="Şirket Logosu">
<div class="text-center">
<h1><?php echo $baslik; ?></h1>
<p>Rapor Tarihi: <?php echo $rapor_tarihi_saati; ?></p>
</div>
<div style="width: 50px;"></div>
</div>
<?php if ($tek_personel_bilgi): ?>
<table style="width: 50%; margin-bottom: 10px; font-size: 10px; float: left;">
<tr>
<td class="text-start" style="width: 30%; background-color: #eee; font-weight: bold;">Personel Adı Soyadı</td>
<td class="text-start"><?php echo $tek_personel_bilgi['ad'] . ' ' . $tek_personel_bilgi['soyad']; ?></td>
</tr>
<tr>
<td class="text-start" style="width: 30%; background-color: #eee; font-weight: bold;">TC Kimlik No</td>
<td class="text-start"><?php echo $tek_personel_bilgi['tc_no']; ?></td>
</tr>
</table>
<div style="clear: both;"></div>
<?php endif; ?>
<table>
<thead>
<tr>
<th rowspan="2" class="text-start">PERSONEL</th>
<th rowspan="2">NET MAAŞ</th>
<th colspan="3">EK KAZANÇLAR</th>
<th colspan="3">KESİNTİLER</th>
<th rowspan="2" class="bg-success-light">TOPLAM HAKEDİŞ</th>
</tr>
<tr>
<th>FM (1.5x) Saat</th>
<th>HT/RT (2.0x) Saat</th>
<th>Tutar</th>
<th>İzin Kesinti Saat</th>
<th>Avans (Tutar)</th>
<th>Toplam Tutar</th>
</tr>
</thead>
<tbody>
<?php foreach($rapor_verileri as $veri): ?>
<tr>
<td class="text-start"><?php echo $veri['ad_soyad']; ?></td>
<td><?php echo number_format($veri['net_maas'], 2); ?> ₺</td>
<td><?php echo $veri['saat_15']; ?> s</td>
<td><?php echo $veri['saat_20']; ?> s</td>
<td style="color: green; font-weight: bold;">+<?php echo number_format($veri['tutar_ek'], 2); ?> ₺</td>
<td><?php echo $veri['saat_izin_kesinti'] > 0 ? $veri['saat_izin_kesinti'].' s' : '-'; ?></td>
<td style="color: red; font-weight: bold;">-<?php echo number_format($veri['tutar_avans'], 2); ?> ₺</td>
<td style="color: red; font-weight: bold;">-<?php echo number_format($veri['tutar_toplam_kesinti'], 2); ?> ₺</td>
<td class="bg-success-light" style="font-weight: bold; font-size: 13px;"><?php echo number_format($veri['toplam_hakedis'], 2); ?> ₺</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<?php if ($personel_filtre_id != 'tumu' && count($personeller) == 1): ?>
<div class="puantaj-detay">
<?php echo $puantaj_html; ?>
</div>
<?php endif; ?>
<div class="imza-blogu">
<div class="imza-kutu">
<div class="imza-baslik">PERSONEL (Bordro Sahibi)</div>
</div>
<div class="imza-kutu">
<div class="imza-baslik">MUHASEBE YETKİLİSİ</div>
</div>
<div class="imza-kutu">
<div class="imza-baslik">YÖNETİCİ ONAYI</div>
</div>
</div>
<?php if($format == 'pdf'): ?>
<script>
// PDF/Print için otomatik tetikleme
window.onload = function() { setTimeout(function() { window.print(); }, 500); }
</script>
<?php endif; ?>
</body>
</html>