sys/veri_detay/#008

PYBS (Personel Yönetim Bilgi Sistemi)

Son Senkronizasyon: 16.12.2025
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'; ?>
DATA_PAYLOAD (Açıklama)
Kapak

DEMO SÜRÜMÜDÜR TAM SÜRÜM İÇİN İLETİŞİM KURUN

📖 PYBS (Personel Yönetim Bilgi Sistemi) Kullanım Kılavuzu

🚀 Proje Tanımı

PYBS, personel bilgilerini, izinleri, maaş bordrolarını ve performans değerlendirmelerini merkezi ve dijital bir platformda yönetmek için tasarlanmış kapsamlı bir Personel Yönetim Bilgi Sistemi'dir. Amacımız, İnsan Kaynakları (İK) süreçlerini otomatikleştirerek verimliliği artırmak ve veri tutarlılığını sağlamaktır.

✨ Temel Özellikler

Personel Yönetimi: Çalışanların kişisel, iletişim ve görev bilgilerini kaydetme/güncelleme.

İzin Yönetimi: Çalışanların izin taleplerini oluşturma, onaylama/reddetme ve kalan izin haklarını takip etme.

Performans Değerlendirme: Yöneticilerin ve çalışanların performans hedeflerini belirlemesi ve değerlendirmeleri kaydetmesi.

Bordro Entegrasyonu: Maaş ve avans bilgilerini kaydetme ve bordro çıktılarını oluşturma (Harici sistemlerle entegrasyon potansiyeli).

Raporlama: İK yöneticileri için özet ve detaylı personel, izin ve bordro raporları oluşturma.

💻 Son Kullanıcı Kullanımı🔑 Giriş Yapma

Demo için kullanıcı adı : test.test

Demo için şifre : 123456

Demo hesabında root / yonetici vb yetki yoktur.

Tam sürüm için iletişime geçin.

Sistem "Ramsa Makine" tarafından aktif olarak kullanılmaktadır

Meta Veri (Özet)

İşyeri çalışanlarının maaş, fazla mesai ve puantaj ile bordro takip, kontrol ve raporlama sistemi

9,312
Sinyal (Ağ Hiti)
1.54 MB
Kapasite

Ağda Paylaş