Files
HRM-System/app/Http/Controllers/ThirteenthMonthController.php

177 lines
6.1 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Branch;
use App\Models\ThirteenthMonthRun;
use App\Models\ThirteenthMonthEntry;
use App\Services\ThirteenthMonthService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Inertia\Inertia;
class ThirteenthMonthController extends Controller
{
protected $service;
public function __construct(ThirteenthMonthService $service)
{
$this->service = $service;
}
/**
* Display the 13th Month Pay management index page.
*/
public function index(Request $request)
{
$selectedYear = (int) $request->input('year', date('Y'));
$selectedBranchId = $request->input('branch_id') ? (int) $request->input('branch_id') : null;
$startMonth = (int) $request->input('start_month', 1);
$endMonth = (int) $request->input('end_month', 12);
// Fetch available years for back-year filtering (last 5 years up to next year)
$currentYear = (int) date('Y');
$availableYears = range($currentYear - 4, $currentYear + 1);
// Fetch all branches
$branches = Branch::all(['id', 'name']);
// Check if there is an existing run saved for this year and branch
$existingRun = ThirteenthMonthRun::where('year', $selectedYear)
->when($selectedBranchId, function ($q) use ($selectedBranchId) {
$q->where('branch_id', $selectedBranchId);
}, function ($q) {
$q->whereNull('branch_id');
})
->with(['entries.employee.user', 'entries.employee.designation', 'entries.employee.department', 'branch', 'creator'])
->first();
if (!$existingRun) {
// Generate dynamic preview run on the fly (not saved to DB yet)
$existingRun = $this->service->generateRun($selectedYear, $selectedBranchId, $startMonth, $endMonth, null, Auth::id());
}
// Fetch historical saved runs list
$pastRuns = ThirteenthMonthRun::with(['branch', 'creator'])
->orderBy('year', 'desc')
->orderBy('created_at', 'desc')
->get();
return Inertia::render('hr/thirteenth-month/index', [
'activeRun' => $existingRun,
'pastRuns' => $pastRuns,
'branches' => $branches,
'availableYears' => array_values($availableYears),
'filters' => [
'year' => $selectedYear,
'branch_id' => $selectedBranchId,
'start_month' => $startMonth,
'end_month' => $endMonth,
],
]);
}
/**
* Generate or recalculate a 13th month batch run.
*/
public function store(Request $request)
{
$request->validate([
'year' => 'required|integer|min:2020|max:2035',
'branch_id' => 'nullable|exists:branches,id',
'start_month' => 'required|integer|min:1|max:12',
'end_month' => 'required|integer|min:1|max:12',
]);
$year = (int) $request->year;
$branchId = $request->branch_id ? (int) $request->branch_id : null;
$startMonth = (int) $request->start_month;
$endMonth = (int) $request->end_month;
$run = $this->service->generateRun($year, $branchId, $startMonth, $endMonth, null, Auth::id());
return redirect()->back()->with('success', "13th Month Pay for {$year} generated successfully!");
}
/**
* Update an individual employee's adjustment or note.
*/
public function updateEntry(Request $request, $id)
{
$request->validate([
'adjustment_amount' => 'required|numeric',
'notes' => 'nullable|string|max:255',
]);
$entry = ThirteenthMonthEntry::findOrFail($id);
$adjustment = (float) $request->adjustment_amount;
$entry->adjustment_amount = $adjustment;
$entry->final_payout = round($entry->computed_amount + $adjustment, 2);
if ($request->has('notes')) {
$entry->notes = $request->notes;
}
$entry->save();
// Recalculate parent run totals
$run = $entry->run;
if ($run) {
$run->total_payout = round($run->entries()->sum('final_payout'), 2);
$run->save();
}
return redirect()->back()->with('success', '13th Month entry updated successfully.');
}
/**
* Approve and lock the 13th Month Pay run.
*/
public function approveRun(Request $request, $id)
{
$run = ThirteenthMonthRun::findOrFail($id);
$run->status = 'approved';
$run->save();
return redirect()->back()->with('success', "13th Month Pay run for {$run->year} has been approved!");
}
/**
* Export 13th Month Payout Schedule as Bank CSV.
*/
public function exportCsv($id)
{
$run = ThirteenthMonthRun::with(['entries.employee.user', 'entries.employee.department', 'branch'])->findOrFail($id);
$filename = "13th_Month_Pay_{$run->year}_Export.csv";
$headers = [
'Content-Type' => 'text/csv',
'Content-Disposition' => "attachment; filename=\"{$filename}\"",
];
$callback = function () use ($run) {
$file = fopen('php://output', 'w');
fputcsv($file, ['Employee Code', 'Employee Name', 'Department', 'Total Base Earned', 'Computed 13th Month', 'Adjustment', 'Final Net Payout']);
foreach ($run->entries as $entry) {
$empCode = $entry->employee->employee_code ?? "EMP-{$entry->employee_id}";
$empName = $entry->employee->user->name ?? 'Staff';
$dept = $entry->employee->department->name ?? 'General';
fputcsv($file, [
$empCode,
$empName,
$dept,
number_format($entry->total_base_earned, 2, '.', ''),
number_format($entry->computed_amount, 2, '.', ''),
number_format($entry->adjustment_amount, 2, '.', ''),
number_format($entry->final_payout, 2, '.', ''),
]);
}
fclose($file);
};
return response()->stream($callback, 200, $headers);
}
}