- Implemented routes for managing payroll periods, including current, close, and reopen functionalities. - Added payroll payment and cancellation routes. - Introduced payroll adjustments with store and delete functionalities. - Created comprehensive feature tests for payroll management, covering authentication, CRUD operations, and business logic. - Ensured proper handling of payroll adjustments and their impact on payroll totals. - Developed tests for generating payrolls and managing payroll periods, ensuring accurate status transitions and data integrity.
78 lines
2.3 KiB
PHP
78 lines
2.3 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Admin\Finance;
|
|
|
|
use App\Enums\PayrollAdjustmentType;
|
|
use App\Enums\PayrollStatus;
|
|
use App\Models\Payroll;
|
|
use App\Models\PayrollAdjustment;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Validation\ValidationException;
|
|
|
|
class PayrollAdjustmentService
|
|
{
|
|
public function create(Payroll $payroll, array $data): PayrollAdjustment
|
|
{
|
|
if ($payroll->status !== PayrollStatus::UNPAID) {
|
|
throw ValidationException::withMessages([
|
|
'payroll' => 'Hanya gaji berstatus belum dibayar yang bisa diadjust.',
|
|
]);
|
|
}
|
|
|
|
return DB::transaction(function () use ($payroll, $data) {
|
|
$adjustment = PayrollAdjustment::create([
|
|
'payroll_id' => $payroll->id,
|
|
'created_by_id' => auth()->id(),
|
|
'attendance_id' => $data['attendance_id'] ?? null,
|
|
'type' => $data['type'],
|
|
'amount' => $data['amount'],
|
|
'description' => $data['description'],
|
|
]);
|
|
|
|
$this->recalculatePayroll($payroll);
|
|
|
|
return $adjustment;
|
|
});
|
|
}
|
|
|
|
public function delete(PayrollAdjustment $adjustment): bool
|
|
{
|
|
$payroll = $adjustment->payroll;
|
|
|
|
if ($payroll->status !== PayrollStatus::UNPAID) {
|
|
throw ValidationException::withMessages([
|
|
'payroll' => 'Hanya gaji berstatus belum dibayar yang bisa diadjust.',
|
|
]);
|
|
}
|
|
|
|
return DB::transaction(function () use ($adjustment, $payroll) {
|
|
$result = $adjustment->delete();
|
|
|
|
$this->recalculatePayroll($payroll);
|
|
|
|
return $result;
|
|
});
|
|
}
|
|
|
|
private function recalculatePayroll(Payroll $payroll): void
|
|
{
|
|
$payroll->refresh();
|
|
|
|
$bonuses = $payroll->payrollAdjustments()
|
|
->where('type', PayrollAdjustmentType::BONUS)
|
|
->sum('amount');
|
|
|
|
$deductions = $payroll->payrollAdjustments()
|
|
->where('type', PayrollAdjustmentType::DEDUCTION)
|
|
->sum('amount');
|
|
|
|
$total = $payroll->base_salary + $bonuses - $deductions;
|
|
|
|
$payroll->update([
|
|
'bonus_amount' => $bonuses,
|
|
'deduction_amount' => $deductions,
|
|
'total_amount' => $total,
|
|
]);
|
|
}
|
|
}
|