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

141 lines
4.8 KiB
PHP

<?php
namespace App\Services\Admin\Finance;
use App\Enums\CashTransactionType;
use App\Models\CashAccount;
use App\Models\CashTransaction;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
class CashAccountService
{
public function get(): ?CashAccount
{
return CashAccount::select('id', 'name', 'balance')->first();
}
public function getAllTransactions(): Collection
{
$cashAccount = $this->get();
if (! $cashAccount) {
return collect();
}
return $cashAccount->cashTransactions()
->select('id', 'created_by_id', 'reference_type', 'reference_id', 'amount', 'balance_after', 'type', 'description', 'created_at')
->with('createdBy.userProfile')
->latest()
->get();
}
public function deposit(array $data): CashTransaction
{
return DB::transaction(function () use ($data) {
$cashAccount = CashAccount::firstOrFail();
$newBalance = $cashAccount->balance + $data['amount'];
$cashAccount->update(['balance' => $newBalance]);
return CashTransaction::create([
'cash_account_id' => $cashAccount->id,
'created_by_id' => auth()->id(),
'amount' => $data['amount'],
'balance_after' => $newBalance,
'type' => CashTransactionType::DEPOSIT,
'description' => $data['description'],
]);
});
}
public function withdrawal(array $data): CashTransaction
{
return DB::transaction(function () use ($data) {
$cashAccount = CashAccount::firstOrFail();
if ($cashAccount->balance < $data['amount']) {
throw ValidationException::withMessages([
'amount' => 'Saldo tidak mencukupi.',
]);
}
$newBalance = $cashAccount->balance - $data['amount'];
$cashAccount->update(['balance' => $newBalance]);
return CashTransaction::create([
'cash_account_id' => $cashAccount->id,
'created_by_id' => auth()->id(),
'amount' => $data['amount'],
'balance_after' => $newBalance,
'type' => CashTransactionType::WITHDRAWAL,
'description' => $data['description'],
]);
});
}
public function updateTransaction(CashTransaction $transaction, array $data): CashTransaction
{
return DB::transaction(function () use ($transaction, $data) {
if (! in_array($transaction->type, [CashTransactionType::DEPOSIT, CashTransactionType::WITHDRAWAL])) {
throw ValidationException::withMessages([
'amount' => 'Transaksi ini tidak dapat diedit.',
]);
}
$cashAccount = CashAccount::firstOrFail();
$oldAmount = $transaction->amount;
$newAmount = $data['amount'];
$isDeposit = $transaction->type === CashTransactionType::DEPOSIT;
$difference = $isDeposit ? $newAmount - $oldAmount : $oldAmount - $newAmount;
if ($difference < 0 && $cashAccount->balance < abs($difference)) {
throw ValidationException::withMessages([
'amount' => 'Saldo tidak mencukupi.',
]);
}
$newBalance = $cashAccount->balance + $difference;
$cashAccount->update(['balance' => $newBalance]);
$transaction->update([
'amount' => $newAmount,
'balance_after' => $newBalance,
'description' => $data['description'],
]);
return $transaction;
});
}
public function deleteTransaction(CashTransaction $transaction): bool
{
return DB::transaction(function () use ($transaction) {
if (! in_array($transaction->type, [CashTransactionType::DEPOSIT, CashTransactionType::WITHDRAWAL])) {
throw ValidationException::withMessages([
'amount' => 'Transaksi ini tidak dapat dihapus.',
]);
}
$cashAccount = CashAccount::firstOrFail();
$isDeposit = $transaction->type === CashTransactionType::DEPOSIT;
$newBalance = $isDeposit
? $cashAccount->balance - $transaction->amount
: $cashAccount->balance + $transaction->amount;
if ($newBalance < 0) {
throw ValidationException::withMessages([
'amount' => 'Saldo tidak mencukupi untuk menghapus transaksi ini.',
]);
}
$cashAccount->update(['balance' => $newBalance]);
return $transaction->delete();
});
}
}