Files
HRM-System/app/Http/Controllers/PayslipController.php
2026-04-13 08:16:56 +08:00

260 lines
9.8 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\PayrollEntry;
use App\Models\Payslip;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Inertia\Inertia;
class PayslipController extends Controller
{
public function index(Request $request)
{
if (Auth::user()->can('manage-payslips')) {
$query = Payslip::with(['employee', 'payrollEntry.payrollRun', 'creator'])->where(function ($q) {
if (Auth::user()->can('manage-any-payslips')) {
$q->whereIn('created_by', getCompanyAndUsersId());
} elseif (Auth::user()->can('manage-own-payslips')) {
$q->orWhere('employee_id', Auth::id());
} else {
$q->whereRaw('1 = 0');
}
});
// Handle search
if ($request->has('search') && ! empty($request->search)) {
$query->where(function ($q) use ($request) {
$q->where('payslip_number', 'like', '%'.$request->search.'%')
->orWhereHas('employee', function ($subQ) use ($request) {
$subQ->where('name', 'like', '%'.$request->search.'%');
});
});
}
// Handle employee filter
if ($request->has('employee_id') && ! empty($request->employee_id) && $request->employee_id !== 'all') {
$query->where('employee_id', $request->employee_id);
}
// Handle status filter
if ($request->has('status') && ! empty($request->status) && $request->status !== 'all') {
$query->where('status', $request->status);
}
// Handle date range filter
if ($request->has('date_from') && ! empty($request->date_from)) {
$query->where('pay_period_start', '>=', $request->date_from);
}
if ($request->has('date_to') && ! empty($request->date_to)) {
$query->where('pay_period_end', '<=', $request->date_to);
}
// Handle sorting
if ($request->has('sort_field') && ! empty($request->sort_field)) {
$sortField = $request->sort_field;
$sortDirection = $request->sort_direction ?? 'asc';
if (in_array($sortField, ['pay_date', 'created_at'])) {
$query->orderBy($sortField, $sortDirection);
} else {
$query->orderBy('pay_date', 'desc');
}
} else {
$query->orderBy('pay_date', 'desc');
}
$payslips = $query->paginate($request->per_page ?? 10);
// Get employees for filter dropdown
$employees = User::where('type', 'employee')
->whereIn('created_by', getCompanyAndUsersId())
->get(['id', 'name']);
return Inertia::render('hr/payslips/index', [
'payslips' => $payslips,
'employees' => $employees,
'filters' => $request->all(['search', 'employee_id', 'status', 'date_from', 'date_to', 'sort_field', 'sort_direction', 'per_page']),
]);
} else {
return redirect()->back()->with('error', __('Permission Denied.'));
}
}
public function generate(Request $request)
{
$validated = $request->validate([
'payroll_entry_ids' => 'required|array',
'payroll_entry_ids.*' => 'exists:payroll_entries,id',
]);
$generatedCount = 0;
$errors = [];
foreach ($validated['payroll_entry_ids'] as $entryId) {
try {
$payrollEntry = PayrollEntry::whereIn('created_by', getCompanyAndUsersId())
->find($entryId);
if (! $payrollEntry) {
continue;
}
// Check if payslip already exists
$exists = Payslip::where('payroll_entry_id', $entryId)->exists();
if ($exists) {
continue;
}
$payslipNumber = Payslip::generatePayslipNumber(
$payrollEntry->employee_id,
$payrollEntry->payrollRun->pay_date
);
$payslip = Payslip::create([
'payroll_entry_id' => $entryId,
'employee_id' => $payrollEntry->employee_id,
'payslip_number' => $payslipNumber,
'pay_period_start' => $payrollEntry->payrollRun->pay_period_start,
'pay_period_end' => $payrollEntry->payrollRun->pay_period_end,
'pay_date' => $payrollEntry->payrollRun->pay_date,
'status' => 'generated',
'created_by' => creatorId(),
]);
// Generate PDF
$payslip->generatePDF();
$generatedCount++;
} catch (\Exception $e) {
$errors[] = "Failed to generate payslip for entry ID {$entryId}: ".$e->getMessage();
}
}
if ($generatedCount > 0) {
$message = "Generated {$generatedCount} payslip(s) successfully.";
if (! empty($errors)) {
$message .= ' Some errors occurred: '.implode(', ', $errors);
}
return redirect()->back()->with('success', __($message));
} else {
return redirect()->back()->with('error', __('No payslips were generated. :errors', ['errors' => implode(', ', $errors)]));
}
}
// public function download($payslipId)
// {
// $payslip = Payslip::where('id', $payslipId)
// ->whereIn('created_by', getCompanyAndUsersId())
// ->first();
// if (!$payslip) {
// return redirect()->back()->with('error', __('Payslip not found.'));
// }
// if (!$payslip->file_path || !Storage::disk('public')->exists($payslip->file_path)) {
// // Generate PDF if not exists
// try {
// $payslip->generatePDF();
// } catch (\Exception $e) {
// return redirect()->back()->with('error', __('Failed to generate payslip PDF: :message', ['message' => $e->getMessage()]));
// }
// }
// $payslip->markAsDownloaded();
// return Storage::disk('public')->download($payslip->file_path, 'payslip-' . $payslip->payslip_number . '.pdf');
// }
public function download($payslipId)
{
try {
$payslip = Payslip::with(['employee', 'payrollEntry.payrollRun', 'payrollEntry.employee.employee'])
->where('id', $payslipId)
->whereIn('created_by', getCompanyAndUsersId())
->first();
if (!$payslip) {
return response()->json(['error' => __('Payslip not found.')], 404);
}
$payrollEntry = $payslip->payrollEntry;
$companySettings = settings();
$companyUser = User::find(getCompanyId(Auth::user()->id));
if ($companyUser) {
$companySettings = array_merge($companySettings, [
'companyEmail' => $companyUser->email ?? null,
]);
}
$data = [
'payslip' => $payslip,
'payrollEntry' => $payrollEntry,
'employee' => $payrollEntry->employee,
'payrollRun' => $payrollEntry->payrollRun,
'earnings' => $payrollEntry->earnings_breakdown ?? [],
'deductions' => $payrollEntry->deductions_breakdown ?? [],
'employeeData' => $payrollEntry->employee->employee,
'companySettings' => $companySettings,
];
$payslip->markAsDownloaded();
return view('payslips.template', $data);
} catch (\Exception $e) {
return response()->json(['error' => __('Failed to download payslip: :message', ['message' => $e->getMessage()])], 500);
}
}
public function bulkGenerate(Request $request)
{
$validated = $request->validate([
'payroll_run_id' => 'required|exists:payroll_runs,id',
]);
try {
$payrollEntries = PayrollEntry::where('payroll_run_id', $validated['payroll_run_id'])
->whereIn('created_by', getCompanyAndUsersId())
->get();
$generatedCount = 0;
foreach ($payrollEntries as $entry) {
// Check if payslip already exists
$exists = Payslip::where('payroll_entry_id', $entry->id)->exists();
if ($exists) {
continue;
}
$payslipNumber = Payslip::generatePayslipNumber(
$entry->employee_id,
$entry->payrollRun->pay_date
);
Payslip::create([
'payroll_entry_id' => $entry->id,
'employee_id' => $entry->employee_id,
'payslip_number' => $payslipNumber,
'pay_period_start' => $entry->payrollRun->pay_period_start,
'pay_period_end' => $entry->payrollRun->pay_period_end,
'pay_date' => $entry->payrollRun->pay_date,
'status' => 'generated',
'created_by' => creatorId(),
]);
// Generate PDF
// $payslip->generatePDF();
$generatedCount++;
}
return redirect()->back()->with('success', __('Generated :count payslips successfully.', ['count' => $generatedCount]));
} catch (\Exception $e) {
return redirect()->back()->with('error', __('Failed to generate payslips: :message', ['message' => $e->getMessage()]));
}
}
}