114 lines
3.6 KiB
PHP
114 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin\Finance;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Admin\Finance\SalaryAdjustmentRequest;
|
|
use App\Models\Payroll;
|
|
use App\Support\LogHelper;
|
|
use Carbon\Carbon;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\Artisan;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Inertia\Inertia;
|
|
use Inertia\Response;
|
|
use Throwable;
|
|
|
|
class PayrollController extends Controller
|
|
{
|
|
public function index(): Response
|
|
{
|
|
$currentMonth = Carbon::now()->format('Y-m');
|
|
|
|
return Inertia::render('admin/finance/payroll/index', [
|
|
'payrolls' => Payroll::with(['user.profile', 'adjustments'])
|
|
->where('period_month', '!=', $currentMonth)
|
|
->latest()
|
|
->get(),
|
|
'currentMonthPayrolls' => Payroll::with(['user.profile', 'adjustments'])
|
|
->where('period_month', $currentMonth)
|
|
->get(),
|
|
]);
|
|
}
|
|
|
|
public function generate(): RedirectResponse
|
|
{
|
|
Artisan::call('payroll:generate');
|
|
|
|
$output = Artisan::output();
|
|
|
|
return redirect()->back()->with('success', $output ?: 'Proses generate selesai.');
|
|
}
|
|
|
|
public function update(SalaryAdjustmentRequest $request, Payroll $payroll): RedirectResponse
|
|
{
|
|
$validated = $request->validated();
|
|
|
|
try {
|
|
DB::transaction(function () use ($payroll, $validated) {
|
|
$payroll->adjustments()->delete();
|
|
|
|
$totalBonus = 0;
|
|
$totalDeduction = 0;
|
|
|
|
if (isset($validated['adjustments'])) {
|
|
foreach ($validated['adjustments'] as $adj) {
|
|
$payroll->adjustments()->create([
|
|
'type' => $adj['type'],
|
|
'amount' => $adj['amount'],
|
|
'description' => $adj['description'],
|
|
]);
|
|
|
|
if ($adj['type'] === 'bonus') {
|
|
$totalBonus += $adj['amount'];
|
|
} else {
|
|
$totalDeduction += $adj['amount'];
|
|
}
|
|
}
|
|
}
|
|
|
|
$payroll->update([
|
|
'bonus' => $totalBonus,
|
|
'deduction' => $totalDeduction,
|
|
'total_salary' => $payroll->base_salary + $totalBonus - $totalDeduction,
|
|
]);
|
|
});
|
|
} catch (Throwable $e) {
|
|
LogHelper::logException($e, 'Payroll update failed', [
|
|
'payroll_id' => $payroll->id,
|
|
]);
|
|
|
|
return back()->withInput()->with('error', 'Gagal memperbarui data. Silakan coba lagi.');
|
|
}
|
|
|
|
return redirect()->back()->with('success', 'Data berhasil diperbarui');
|
|
}
|
|
|
|
public function togglePaid(Payroll $payroll): RedirectResponse
|
|
{
|
|
$payroll->update([
|
|
'is_paid' => ! $payroll->is_paid,
|
|
'paid_at' => ! $payroll->is_paid ? Carbon::now() : null,
|
|
]);
|
|
|
|
return redirect()->back()->with('success', 'Status pembayaran berhasil diubah');
|
|
}
|
|
|
|
public function destroy(Payroll $payroll): RedirectResponse
|
|
{
|
|
$payroll->delete();
|
|
|
|
return redirect()->back()->with('success', 'Data berhasil dihapus');
|
|
}
|
|
|
|
public function bulkDestroy(Request $request): RedirectResponse
|
|
{
|
|
$ids = $request->input('ids');
|
|
|
|
Payroll::whereIn('id', $ids)->delete();
|
|
|
|
return redirect()->back()->with('success', 'Data terpilih berhasil dihapus');
|
|
}
|
|
}
|