PYBS (Personel Yönetim Bilgi Sistemi) / Ramsa/modules/maas-hesapla.php
maas-hesapla.php 340 satır • 16.61 KB
<?php
// modules/maas-hesapla.php
session_start();
require_once '../config/db.php';
require_once '../config/functions.php';

// Yetki
yetkiKontrol(['root', 'yonetici', 'muhasebe', 'insan_kaynaklari']);

include '../includes/header.php';
include '../includes/menu.php';

// --- FİLTRELER ---
$yil = $_GET['yil'] ?? date('Y');
$ay = $_GET['ay'] ?? date('m');
$personel_filtre_id = $_GET['personel_id'] ?? 'tumu';

// --- HESAPLAMA PARAMETRELERİ ---
$gun_sayisi = cal_days_in_month(CAL_GREGORIAN, $ay, $yil);
$tarih_bas = date('Y-m-01', strtotime("$yil-$ay-01"));
$tarih_bit = date('Y-m-t', strtotime("$yil-$ay-01"));

// Helper: Saat Formatı
function formatSaatListeleme($saat) {
    if ($saat === null || $saat === 0.0 || $saat === 0) return 0;
    if ($saat == floor($saat)) return (int)$saat;
    return number_format($saat, 1, '.', '');
}

// Resmi Tatiller
$tatiller = $pdo->query("SELECT tarih FROM resmi_tatiller")->fetchAll(PDO::FETCH_COLUMN);

// Personel Filtreleme Sorgusu
$sql_per = "SELECT id, ad, soyad, rol, ise_giris_tarihi, isten_cikis_tarihi FROM kullanicilar WHERE rol != 'root'";
if ($personel_filtre_id !== 'tumu') { $sql_per .= " AND id = $personel_filtre_id"; }
$sql_per .= " ORDER BY ad ASC";
$personeller = $pdo->query($sql_per)->fetchAll();

$sonuc_tablosu = [];
$detay_data = [];
$secilen_personel_bilgi = null;

// --- HESAPLAMA DÖNGÜSÜ ---
foreach ($personeller as $p) {
    $pid = $p['id'];
    
    // Aktiflik Kontrolü
    if ($p['ise_giris_tarihi'] > $tarih_bit) continue; 
    if (!empty($p['isten_cikis_tarihi']) && $p['isten_cikis_tarihi'] < $tarih_bas) continue;

    // Maaş
    $maas = maasGetir($pdo, $pid, $yil, $ay);
    if ($maas <= 0) continue; 

    // Standart Hesaplamalar (Ay = 30 gün, 225 saat)
    $gunluk_ucret = $maas / 30;
    $saatlik_ucret = $maas / 225;

    // Tekil Personel Bilgileri
    if ($personel_filtre_id != 'tumu' && $pid == $personel_filtre_id) {
        $secilen_personel_bilgi = [
            'ad_soyad' => $p['ad'] . ' ' . $p['soyad'],
            'maas' => $maas,
            'saatlik_normal' => $saatlik_ucret,
            'saatlik_15' => $saatlik_ucret * 1.5,
            'saatlik_20' => $saatlik_ucret * 2.0,
            'saatlik_kesinti' => $saatlik_ucret
        ];
    }

    $k15_saat = 0; 
    $k20_saat = 0; 
    $kesinti_saat_toplam = 0;
    $calisilmayan_gun = 0; 

    // DETAY ARRAYS
    $detay_data[$pid] = ['mesai'=>['normal'=>[],'tatil'=>[]], 'izin_kesinti'=>[]];

    // --- GÜNLÜK KONTROL ---
    for ($d=1; $d<=$gun_sayisi; $d++) {
        $tarih = "$yil-$ay-" . sprintf('%02d', $d);
        $gun_no = date('N', strtotime($tarih)); 
        
        // Kıst Gün (İşe giriş/çıkış)
        $aktif_gun = true;
        if ($tarih < $p['ise_giris_tarihi']) $aktif_gun = false;
        elseif (!empty($p['isten_cikis_tarihi']) && $tarih > $p['isten_cikis_tarihi']) $aktif_gun = false;

        if (!$aktif_gun) {
            $calisilmayan_gun++;
            continue;
        }

        $is_tatil = in_array($tarih, $tatiller);
        $is_calisma_gunu = ($gun_no < 6 && !$is_tatil); 

        // --- GÜNCELLENEN KISIM: İZİN KONTROLÜ (ÇOKLU İZİN DESTEĞİ) ---
        $gunluk_kesinti = 0;
        
        // fetch() yerine fetchAll() kullanıyoruz ki aynı gün hem Süt hem Saatlik varsa ikisini de alalım.
        $izinler = $pdo->query("SELECT * FROM izin_talepleri WHERE calisan_id=$pid AND durum='onaylandi' AND '$tarih' BETWEEN DATE(baslangic_tarihi) AND DATE(bitis_tarihi)")->fetchAll();
        
        foreach ($izinler as $izin) {
            // Sadece mesai günlerinde kesinti yapılır (Pazar günü ücretsiz izin alınmaz mantığı)
            if ($is_calisma_gunu && in_array($izin['izin_turu'], ['hastalik', 'saatlik', 'ucretsiz', 'mazeret', 'mesaiye_gelmedi'])) {
                $bu_izin_kesintisi = 0;
                
                if ($izin['izin_turu'] == 'saatlik' || $izin['izin_turu'] == 'mesaiye_gelmedi') {
                    $bu_izin_kesintisi = (float)$izin['saatlik_sure'];
                } else {
                    // Tam gün kesintiler (Hastalık, Mazeret vb.) -> 9 Saat (veya 7.5) kabul ediyoruz
                    // Eğer zaten tam gün kesinti işlendiyse tekrar eklememek lazım, ama burada basit toplama yapıyoruz.
                    $bu_izin_kesintisi = 9; 
                }
                
                $gunluk_kesinti += $bu_izin_kesintisi;
                
                if ($bu_izin_kesintisi > 0) {
                    $detay_data[$pid]['izin_kesinti'][] = [
                        'tarih'=>$tarih, 
                        'saat'=>$bu_izin_kesintisi, 
                        'turu'=>$izin['izin_turu'], 
                        'aciklama'=>$izin['aciklama']
                    ];
                }
            }
            // Süt izni (sut_izni) buraya girmez, dolayısıyla $gunluk_kesinti artmaz.
        }
        
        // Günlük kesintiyi mantıksal sınıra çek (Günde 9 saatten fazla kesinti olamaz)
        if ($gunluk_kesinti > 9) $gunluk_kesinti = 9;

        // Mesai (Kazanç)
        $gunluk_mesai = 0;
        $mesai = $pdo->query("SELECT * FROM mesai_hareketleri WHERE calisan_id=$pid AND durum='onaylandi' AND tarih='$tarih'")->fetch();
        if ($mesai) $gunluk_mesai = (float)$mesai['toplam_saat'];

        // Mahsuplaşma
        $net_kesinti = $gunluk_kesinti;
        $net_mesai = $gunluk_mesai;

        if ($gunluk_kesinti > 0 && $gunluk_mesai > 0) {
            if ($gunluk_mesai >= $gunluk_kesinti) { $net_mesai -= $gunluk_kesinti; $net_kesinti = 0; }
            else { $net_kesinti -= $gunluk_mesai; $net_mesai = 0; }
        }

        if ($net_kesinti > 0) $kesinti_saat_toplam += $net_kesinti;
        
        if ($net_mesai > 0) {
            $mesai_tur = $mesai['mesai_turu'];
            if ($is_tatil || $gun_no == 7 || $mesai_tur == 'resmi_tatil_mesaisi') {
                $k20_saat += $net_mesai;
                $detay_data[$pid]['mesai']['tatil'][] = ['tarih'=>$tarih, 'bas_saat'=>substr($mesai['baslangic_saati'],0,5), 'bit_saat'=>substr($mesai['bitis_saati'],0,5), 'net_saat'=>$net_mesai, 'aciklama'=>$mesai['aciklama']];
            } else {
                $k15_saat += $net_mesai;
                $detay_data[$pid]['mesai']['normal'][] = ['tarih'=>$tarih, 'bas_saat'=>substr($mesai['baslangic_saati'],0,5), 'bit_saat'=>substr($mesai['bitis_saati'],0,5), 'net_saat'=>$net_mesai, 'aciklama'=>$mesai['aciklama']];
            }
        }
    } 

    // --- TUTAR HESAPLAMA ---
    $tutar_15 = $k15_saat * $saatlik_ucret * 1.5;
    $tutar_20 = $k20_saat * $saatlik_ucret * 2.0;
    $toplam_mesai_kazanc = $tutar_15 + $tutar_20;
    $ikramiye_toplam = $pdo->query("SELECT SUM(miktar) FROM ikramiyeler WHERE calisan_id = $pid AND donem_tarihi BETWEEN '$tarih_bas' AND '$tarih_bit'")->fetchColumn() ?: 0;
    $avans_toplam = $pdo->query("SELECT SUM(avans_miktari) FROM avans_hareketleri WHERE calisan_id = $pid AND islem_tarihi BETWEEN '$tarih_bas' AND '$tarih_bit' AND durum='onaylandi'")->fetchColumn() ?: 0;
    $kesinti_ucret = $kesinti_saat_toplam * $saatlik_ucret;
    $kist_ucret = $calisilmayan_gun * $gunluk_ucret;
    $toplam_kesinti = $kesinti_ucret + $avans_toplam + $kist_ucret;

    $net_odenecek = ($maas + $toplam_mesai_kazanc + $ikramiye_toplam) - $toplam_kesinti;
    if($net_odenecek < 0) $net_odenecek = 0;

    $sonuc_tablosu[] = [
        'id' => $pid,
        'ad_soyad' => $p['ad'].' '.$p['soyad'],
        'net_maas' => $maas,
        'k15' => $k15_saat,
        'k20' => $k20_saat,
        'mesai_kazanc' => $toplam_mesai_kazanc,
        'ikramiye' => $ikramiye_toplam,
        'kesinti_saat' => $kesinti_saat_toplam,
        'kesinti_tutar' => $kesinti_ucret,
        'avans' => $avans_toplam,
        'kist_gun' => $calisilmayan_gun,
        'kist_tutar' => $kist_ucret,
        'net_odenecek' => $net_odenecek
    ];
}
?>

<div class="container-fluid">
    <div class="d-flex justify-content-between align-items-center mb-3 no-print">
        <h3><i class="fas fa-calculator text-primary"></i> Maaş Bordro Hesaplama</h3>
    </div>

    <div class="card bg-light border mb-4 no-print">
        <div class="card-body p-3">
            <form method="GET" id="maasForm" class="row g-2 align-items-end">
                <div class="col-md-2"><select name="ay" class="form-select"><?php foreach(['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'] as $k=>$v) echo "<option value='$k' ".($k==$ay?'selected':'').">$v</option>"; ?></select></div>
                <div class="col-md-2"><select name="yil" class="form-select"><?php for($y=2024;$y<=2030;$y++) echo "<option value='$y' ".($y==$yil?'selected':'').">$y</option>"; ?></select></div>
                <div class="col-md-3"><select name="personel_id" class="form-select"><option value="tumu">Tüm Personel</option><?php foreach($pdo->query("SELECT id, ad, soyad FROM kullanicilar WHERE rol!='root'") as $per) echo "<option value='{$per['id']}' ".($per['id']==$personel_filtre_id?'selected':'').">{$per['ad']} {$per['soyad']}</option>"; ?></select></div>
                
                <div class="col-md-3 d-flex gap-1">
                    <button type="button" onclick="submitForm('')" class="btn btn-primary w-100">Hesapla</button>
                    <div class="btn-group">
                        <button type="button" onclick="submitForm('excel')" class="btn btn-success" title="Excel"><i class="fas fa-file-excel"></i></button>
                        <button type="button" onclick="submitForm('print')" class="btn btn-danger" title="PDF"><i class="fas fa-file-pdf"></i></button>
                    </div>
                </div>
                <input type="hidden" name="format" id="exportFormat" value="">
            </form>
        </div>
    </div>

    <div class="card border-0 shadow-sm" id="printableArea">
        <div class="table-responsive">
            <table class="table table-hover table-bordered align-middle mb-0" style="font-size: 0.8rem;">
                <thead class="table-dark text-center">
                    <tr>
                        <th rowspan="2" class="align-middle">Personel</th>
                        <th rowspan="2" class="align-middle bg-secondary">Net Maaş</th>
                        <th colspan="3" class="bg-success">Kazançlar (+)</th>
                        <th colspan="4" class="bg-danger">Kesintiler (-)</th>
                        <th rowspan="2" class="align-middle bg-primary" style="min-width:100px;">ÖDENECEK</th>
                    </tr>
                    <tr>
                        <th>Mesai (1.5x)</th>
                        <th>Mesai (2.0x)</th>
                        <th class="bg-warning text-dark">İkramiye</th> 
                        <th>Üc.İzin</th>
                        <th>Avans</th>
                        <th>Kıst Gün</th>
                        <th>Top.Kes</th>
                    </tr>
                </thead>
                <tbody>
                    <?php foreach($sonuc_tablosu as $s): ?>
                    <tr>
                        <td class="fw-bold"><?php echo $s['ad_soyad']; ?></td>
                        <td class="text-end bg-light fw-bold"><?php echo number_format($s['net_maas'], 2); ?></td>
                        
                        <td class="text-center" style="cursor:pointer;" onclick="openDetail(<?php echo $s['id']; ?>, 'mesai', 'normal')">
                            <?php echo formatSaatListeleme($s['k15']); ?> s
                        </td>
                        <td class="text-center" style="cursor:pointer;" onclick="openDetail(<?php echo $s['id']; ?>, 'mesai', 'tatil')">
                            <?php echo formatSaatListeleme($s['k20']); ?> s
                        </td>
                        <td class="text-end bg-warning bg-opacity-10 fw-bold text-dark">
                            <?php echo ($s['ikramiye'] > 0) ? number_format($s['ikramiye'], 2) : '-'; ?>
                        </td>

                        <td class="text-center text-danger" style="cursor:pointer;" onclick="openDetail(<?php echo $s['id']; ?>, 'izin_kesinti', null)">
                            <?php echo ($s['kesinti_saat']>0) ? formatSaatListeleme($s['kesinti_saat']).' s' : '-'; ?>
                        </td>
                        <td class="text-end text-danger"><?php echo ($s['avans']>0) ? number_format($s['avans'], 2) : '-'; ?></td>
                        <td class="text-center text-danger"><?php echo ($s['kist_gun']>0) ? $s['kist_gun'].' G' : '-'; ?></td>
                        <td class="text-end text-danger fw-bold"><?php echo number_format($s['kesinti_tutar']+$s['avans']+$s['kist_tutar'], 2); ?></td>

                        <td class="text-end bg-primary text-white fw-bold fs-6">
                            <?php echo number_format($s['net_odenecek'], 2); ?> ₺
                        </td>
                    </tr>
                    <?php endforeach; ?>
                </tbody>
            </table>
        </div>
    </div>

    <?php if ($secilen_personel_bilgi): ?>
    <div class="row mt-4 no-print">
        <div class="col-12">
            <div class="card border-info shadow-sm">
                <div class="card-header bg-info text-white fw-bold">
                    <i class="fas fa-info-circle me-2"></i> Ücret Parametreleri: <?php echo $secilen_personel_bilgi['ad_soyad']; ?>
                </div>
                <div class="card-body">
                    <div class="row text-center">
                        <div class="col-md-3 border-end">
                            <small class="text-muted text-uppercase fw-bold">Saatlik Ücret (Net)</small>
                            <h4 class="text-dark mt-2 fw-bold"><?php echo number_format($secilen_personel_bilgi['saatlik_normal'], 2); ?> ₺</h4>
                        </div>
                        <div class="col-md-3 border-end">
                            <small class="text-muted text-uppercase fw-bold">Fazla Mesai (1.5x)</small>
                            <h4 class="text-success mt-2 fw-bold"><?php echo number_format($secilen_personel_bilgi['saatlik_15'], 2); ?> ₺</h4>
                        </div>
                        <div class="col-md-3 border-end">
                            <small class="text-muted text-uppercase fw-bold">Resmi Tatil Mesai (2.0x)</small>
                            <h4 class="text-success mt-2 fw-bold"><?php echo number_format($secilen_personel_bilgi['saatlik_20'], 2); ?> ₺</h4>
                        </div>
                        <div class="col-md-3">
                            <small class="text-muted text-uppercase fw-bold">Saat Başı Kesinti</small>
                            <h4 class="text-danger mt-2 fw-bold"><?php echo number_format($secilen_personel_bilgi['saatlik_kesinti'], 2); ?> ₺</h4>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <?php endif; ?>

</div>

<div class="modal fade" id="detailModal" tabindex="-1"><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><h5 class="modal-title">Detaylar</h5><button type="button" class="btn-close" data-bs-dismiss="modal"></button></div><div class="modal-body"><table class="table table-sm"><thead><tr><th>Tarih</th><th>Tür/Saat</th><th>Miktar</th><th>Açıklama</th></tr></thead><tbody id="modalTableBody"></tbody></table></div></div></div></div>

<script>
    const DETAY = <?php echo json_encode($detay_data); ?>;
    
    function submitForm(type) {
        const form = document.getElementById('maasForm');
        document.getElementById('exportFormat').value = type;
        if (type === 'excel' || type === 'print') { 
            form.action = 'maas-rapor.php'; 
            form.target = '_blank'; 
        } else { 
            form.action = 'maas-hesapla.php'; 
            form.target = '_self'; 
        }
        form.submit();
    }

    function openDetail(pid, type, sub) {
        const tbody = document.getElementById('modalTableBody'); tbody.innerHTML = '';
        const data = DETAY[pid];
        if(!data) return;
        let list = (type === 'mesai') ? data.mesai[sub] : data.izin_kesinti;
        
        if (!list || list.length === 0) {
            tbody.innerHTML = '<tr><td colspan="4" class="text-center text-muted">Kayıt bulunamadı.</td></tr>';
        } else {
            list.forEach(i => {
                let val = (type === 'mesai') ? i.net_saat + ' Saat' : i.saat + ' Saat';
                let desc = (type === 'mesai') ? i.bas_saat+'-'+i.bit_saat : i.turu;
                tbody.innerHTML += `<tr><td>${i.tarih}</td><td>${desc}</td><td class='fw-bold'>${val}</td><td>${i.aciklama}</td></tr>`;
            });
        }
        new bootstrap.Modal(document.getElementById('detailModal')).show();
    }
</script>
<?php include '../includes/footer.php'; ?>