TIFNJK_E41222887/app/Http/Controllers/Admin/PayrollController.php

130 lines
4.2 KiB
PHP

<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Employee;
use App\Models\Payroll;
use Illuminate\Http\Request;
use Inertia\Inertia;
class PayrollController extends Controller
{
/**
* Tampilkan daftar semua payroll dengan Eager Loading (hindari N+1).
*/
public function index()
{
$payrolls = Payroll::with('employee')
->latest()
->get()
->map(fn($p) => [
'id' => $p->id,
'period' => $p->period,
'net_salary' => $p->net_salary,
'status' => $p->status,
'employee_name' => $p->employee?->name ?? '-',
'employee_nip' => $p->employee?->nip ?? '-',
]);
return Inertia::render('admin/payrolls/index', [
'payrolls' => $payrolls,
]);
}
/**
* Tampilkan form Generate Payroll.
* Kirim daftar employees (beserta relasi position.basic_salary) ke frontend.
*/
public function create()
{
$employees = Employee::with(['position', 'department'])
->orderBy('name')
->get()
->map(fn($e) => [
'id' => $e->id,
'name' => $e->name,
'nip' => $e->nip,
'position' => [
'id' => $e->position?->id,
'name' => $e->position?->name,
'basic_salary' => $e->position?->basic_salary ?? 0,
],
'department' => [
'name' => $e->department?->name,
],
]);
return Inertia::render('admin/payrolls/create', [
'employees' => $employees,
]);
}
/**
* Simpan data payroll & hitung net_salary secara otomatis.
*
* Logika kalkulasi:
* net_salary = basic_salary
* + SUM(detail tipe "bonus")
* - SUM(detail tipe "deduction")
*/
public function store(Request $request)
{
$validated = $request->validate([
'employee_id' => 'required|exists:employees,id',
'period' => 'required|string|max:7',
'basic_salary' => 'required|integer|min:0',
'details' => 'nullable|array',
'details.*.name' => 'required|string|max:100',
'details.*.type' => 'required|in:bonus,deduction',
'details.*.amount' => 'required|integer|min:0',
]);
$net = $validated['basic_salary'];
foreach ($validated['details'] ?? [] as $item) {
$net += $item['type'] === 'bonus'
? $item['amount']
: -$item['amount'];
}
$net = max(0, $net);
Payroll::create([
'employee_id' => $validated['employee_id'],
'period' => $validated['period'],
'basic_salary' => $validated['basic_salary'],
'details' => $validated['details'] ?? [],
'net_salary' => $net,
'status' => 'pending',
]);
return redirect('/admin/payrolls')
->with('success', 'Payroll berhasil di-generate.');
}
/**
* Tampilkan detail slip gaji 1 payroll.
*/
public function show(Payroll $payroll)
{
$payroll->load('employee.position', 'employee.department');
return Inertia::render('admin/payrolls/show', [
'payroll' => [
'id' => $payroll->id,
'period' => $payroll->period,
'basic_salary' => $payroll->basic_salary,
'details' => $payroll->details ?? [],
'net_salary' => $payroll->net_salary,
'status' => $payroll->status,
'created_at' => $payroll->created_at->format('d F Y'),
'employee' => [
'name' => $payroll->employee?->name,
'nip' => $payroll->employee?->nip,
'position' => $payroll->employee?->position?->name,
'department' => $payroll->employee?->department?->name,
],
],
]);
}
}