dstpabuaran.com/app/Services/Admin/Finance/PayrollAdjustmentService.php
Yoga Pangestu 6dbe9da581 feat: add payroll management features including payroll periods, adjustments, and payment processing
- 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.
2026-07-30 17:06:52 +07:00

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,
]);
}
}