dstpabuaran.com/app/Services/Admin/Finance/EmployeeAdvanceService.php

152 lines
5.2 KiB
PHP

<?php
namespace App\Services\Admin\Finance;
use App\Enums\CashTransactionType;
use App\Enums\EmployeeAdvanceStatus;
use App\Models\CashAccount;
use App\Models\CashTransaction;
use App\Models\EmployeeAdvance;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
class EmployeeAdvanceService
{
public function getAll(): Collection
{
return EmployeeAdvance::select('id', 'employee_id', 'amount', 'paid_amount', 'description', 'due_date', 'status', 'created_at')
->with(['employee.user.userProfile'])
->latest()
->get();
}
public function create(array $data): EmployeeAdvance
{
return DB::transaction(function () use ($data) {
$cashAccount = CashAccount::firstOrFail();
$employee = auth()->user()->employee;
if (! $employee) {
throw new \Exception('Anda tidak terdaftar sebagai karyawan.');
}
if ($cashAccount->balance < $data['amount']) {
throw ValidationException::withMessages([
'amount' => 'Saldo tidak mencukupi.',
]);
}
$newBalance = $cashAccount->balance - $data['amount'];
$cashAccount->update(['balance' => $newBalance]);
$cashTransaction = CashTransaction::create([
'cash_account_id' => $cashAccount->id,
'created_by_id' => auth()->id(),
'amount' => $data['amount'],
'balance_after' => $newBalance,
'type' => CashTransactionType::EXPENSE,
'description' => 'Kasbon: '.$data['description'],
]);
return EmployeeAdvance::create([
'cash_transaction_id' => $cashTransaction->id,
'employee_id' => $employee->id,
'amount' => $data['amount'],
'description' => $data['description'],
'due_date' => $data['due_date'],
'status' => EmployeeAdvanceStatus::PENDING,
]);
});
}
public function update(EmployeeAdvance $employeeAdvance, array $data): EmployeeAdvance
{
return DB::transaction(function () use ($employeeAdvance, $data) {
$cashAccount = CashAccount::firstOrFail();
$cashTransaction = $employeeAdvance->cashTransaction;
$oldAmount = $employeeAdvance->amount;
$newAmount = $data['amount'];
$difference = $newAmount - $oldAmount;
if ($difference > 0 && $cashAccount->balance < $difference) {
throw ValidationException::withMessages([
'amount' => 'Saldo tidak mencukupi.',
]);
}
$newBalance = $cashAccount->balance - $difference;
$cashAccount->update(['balance' => $newBalance]);
$cashTransaction->update([
'amount' => $newAmount,
'balance_after' => $newBalance,
'description' => 'Kasbon: '.$data['description'],
]);
$employeeAdvance->update([
'amount' => $newAmount,
'description' => $data['description'],
'due_date' => $data['due_date'],
]);
return $employeeAdvance;
});
}
public function delete(EmployeeAdvance $employeeAdvance): bool
{
return DB::transaction(function () use ($employeeAdvance) {
$cashAccount = CashAccount::firstOrFail();
if ($employeeAdvance->status === EmployeeAdvanceStatus::PAID) {
$newBalance = $cashAccount->balance + $employeeAdvance->amount;
$cashAccount->update(['balance' => $newBalance]);
}
return $employeeAdvance->delete();
});
}
public function approve(EmployeeAdvance $employeeAdvance): EmployeeAdvance
{
$employeeAdvance->update([
'status' => EmployeeAdvanceStatus::APPROVED,
'verified_by_id' => auth()->id(),
'verified_at' => now(),
]);
return $employeeAdvance;
}
public function pay(EmployeeAdvance $employeeAdvance): EmployeeAdvance
{
return DB::transaction(function () use ($employeeAdvance) {
$cashAccount = CashAccount::firstOrFail();
$newBalance = $cashAccount->balance + $employeeAdvance->amount;
$cashAccount->update(['balance' => $newBalance]);
$cashTransaction = CashTransaction::create([
'cash_account_id' => $cashAccount->id,
'created_by_id' => auth()->id(),
'amount' => $employeeAdvance->amount,
'balance_after' => $newBalance,
'type' => CashTransactionType::DEPOSIT,
'description' => 'Pembayaran kasbon: '.$employeeAdvance->description,
]);
$employeeAdvance->update([
'status' => EmployeeAdvanceStatus::PAID,
'paid_by_id' => auth()->id(),
'paid_amount' => $employeeAdvance->amount,
'paid_at' => now(),
'repayment_cash_transaction_id' => $cashTransaction->id,
]);
return $employeeAdvance;
});
}
}