140 lines
4.6 KiB
PHP
140 lines
4.6 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::first();
|
|
}
|
|
|
|
public function getAllTransactions(): Collection
|
|
{
|
|
$cashAccount = $this->get();
|
|
|
|
if (! $cashAccount) {
|
|
return collect();
|
|
}
|
|
|
|
return $cashAccount->cashTransactions()
|
|
->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();
|
|
});
|
|
}
|
|
}
|