feat: enhance transaction handling with error management and database transactions in CashAccountService and controllers
This commit is contained in:
parent
912f576c74
commit
d1f1d82099
@ -7,6 +7,7 @@
|
|||||||
use App\Models\CashTransaction;
|
use App\Models\CashTransaction;
|
||||||
use App\Services\Admin\Finance\CashAccountService;
|
use App\Services\Admin\Finance\CashAccountService;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
use Inertia\Response;
|
use Inertia\Response;
|
||||||
|
|
||||||
@ -28,36 +29,64 @@ public function index(): Response
|
|||||||
|
|
||||||
public function deposit(CashTransactionRequest $request): RedirectResponse
|
public function deposit(CashTransactionRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$this->service->deposit($request->validated());
|
try {
|
||||||
|
$this->service->deposit($request->validated());
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Deposit berhasil ditambahkan.']);
|
Inertia::flash('toast', ['type' => 'success', 'message' => 'Deposit berhasil ditambahkan.']);
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
$firstError = collect($e->errors())->flatten()->first();
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $firstError ?? 'Terjadi kesalahan.']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
|
||||||
return to_route('admin.finance.cash-accounts.index');
|
return to_route('admin.finance.cash-accounts.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function withdrawal(CashTransactionRequest $request): RedirectResponse
|
public function withdrawal(CashTransactionRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$this->service->withdrawal($request->validated());
|
try {
|
||||||
|
$this->service->withdrawal($request->validated());
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Withdrawal berhasil ditambahkan.']);
|
Inertia::flash('toast', ['type' => 'success', 'message' => 'Withdrawal berhasil ditambahkan.']);
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
$firstError = collect($e->errors())->flatten()->first();
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $firstError ?? 'Terjadi kesalahan.']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
|
||||||
return to_route('admin.finance.cash-accounts.index');
|
return to_route('admin.finance.cash-accounts.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(CashTransactionRequest $request, CashTransaction $transaction): RedirectResponse
|
public function update(CashTransactionRequest $request, CashTransaction $transaction): RedirectResponse
|
||||||
{
|
{
|
||||||
$this->service->updateTransaction($transaction, $request->validated());
|
try {
|
||||||
|
$this->service->updateTransaction($transaction, $request->validated());
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Transaksi berhasil diperbarui.']);
|
Inertia::flash('toast', ['type' => 'success', 'message' => 'Transaksi berhasil diperbarui.']);
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
$firstError = collect($e->errors())->flatten()->first();
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $firstError ?? 'Terjadi kesalahan.']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
|
||||||
return to_route('admin.finance.cash-accounts.index');
|
return to_route('admin.finance.cash-accounts.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(CashTransaction $transaction): RedirectResponse
|
public function destroy(CashTransaction $transaction): RedirectResponse
|
||||||
{
|
{
|
||||||
$this->service->deleteTransaction($transaction);
|
try {
|
||||||
|
$this->service->deleteTransaction($transaction);
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Transaksi berhasil dihapus.']);
|
Inertia::flash('toast', ['type' => 'success', 'message' => 'Transaksi berhasil dihapus.']);
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
$firstError = collect($e->errors())->flatten()->first();
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $firstError ?? 'Terjadi kesalahan.']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
|
||||||
return to_route('admin.finance.cash-accounts.index');
|
return to_route('admin.finance.cash-accounts.index');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
use App\Models\Expense;
|
use App\Models\Expense;
|
||||||
use App\Services\Admin\Finance\ExpenseService;
|
use App\Services\Admin\Finance\ExpenseService;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
|
use Illuminate\Validation\ValidationException;
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
use Inertia\Response;
|
use Inertia\Response;
|
||||||
|
|
||||||
@ -25,27 +26,45 @@ public function index(): Response
|
|||||||
|
|
||||||
public function store(ExpenseRequest $request): RedirectResponse
|
public function store(ExpenseRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$this->service->create($request->validated());
|
try {
|
||||||
|
$this->service->create($request->validated());
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Pengeluaran berhasil ditambahkan.']);
|
Inertia::flash('toast', ['type' => 'success', 'message' => 'Pengeluaran berhasil ditambahkan.']);
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
$firstError = collect($e->errors())->flatten()->first();
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $firstError ?? 'Terjadi kesalahan.']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
|
||||||
return to_route('admin.finance.expenses.index');
|
return to_route('admin.finance.expenses.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(ExpenseRequest $request, Expense $expense): RedirectResponse
|
public function update(ExpenseRequest $request, Expense $expense): RedirectResponse
|
||||||
{
|
{
|
||||||
$this->service->update($expense, $request->validated());
|
try {
|
||||||
|
$this->service->update($expense, $request->validated());
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Pengeluaran berhasil diperbarui.']);
|
Inertia::flash('toast', ['type' => 'success', 'message' => 'Pengeluaran berhasil diperbarui.']);
|
||||||
|
} catch (ValidationException $e) {
|
||||||
|
$firstError = collect($e->errors())->flatten()->first();
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $firstError ?? 'Terjadi kesalahan.']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
|
||||||
return to_route('admin.finance.expenses.index');
|
return to_route('admin.finance.expenses.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Expense $expense): RedirectResponse
|
public function destroy(Expense $expense): RedirectResponse
|
||||||
{
|
{
|
||||||
$this->service->delete($expense);
|
try {
|
||||||
|
$this->service->delete($expense);
|
||||||
|
|
||||||
Inertia::flash('toast', ['type' => 'success', 'message' => 'Pengeluaran berhasil dihapus.']);
|
Inertia::flash('toast', ['type' => 'success', 'message' => 'Pengeluaran berhasil dihapus.']);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
Inertia::flash('toast', ['type' => 'error', 'message' => $e->getMessage()]);
|
||||||
|
}
|
||||||
|
|
||||||
return to_route('admin.finance.expenses.index');
|
return to_route('admin.finance.expenses.index');
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
use App\Models\CashAccount;
|
use App\Models\CashAccount;
|
||||||
use App\Models\CashTransaction;
|
use App\Models\CashTransaction;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class CashAccountService
|
class CashAccountService
|
||||||
@ -31,100 +32,108 @@ public function getAllTransactions(): Collection
|
|||||||
|
|
||||||
public function deposit(array $data): CashTransaction
|
public function deposit(array $data): CashTransaction
|
||||||
{
|
{
|
||||||
$cashAccount = CashAccount::firstOrFail();
|
return DB::transaction(function () use ($data) {
|
||||||
$newBalance = $cashAccount->balance + $data['amount'];
|
$cashAccount = CashAccount::firstOrFail();
|
||||||
|
$newBalance = $cashAccount->balance + $data['amount'];
|
||||||
|
|
||||||
$cashAccount->update(['balance' => $newBalance]);
|
$cashAccount->update(['balance' => $newBalance]);
|
||||||
|
|
||||||
return CashTransaction::create([
|
return CashTransaction::create([
|
||||||
'cash_account_id' => $cashAccount->id,
|
'cash_account_id' => $cashAccount->id,
|
||||||
'created_by_id' => auth()->id(),
|
'created_by_id' => auth()->id(),
|
||||||
'amount' => $data['amount'],
|
'amount' => $data['amount'],
|
||||||
'balance_after' => $newBalance,
|
'balance_after' => $newBalance,
|
||||||
'type' => CashTransactionType::DEPOSIT,
|
'type' => CashTransactionType::DEPOSIT,
|
||||||
'description' => $data['description'],
|
'description' => $data['description'],
|
||||||
]);
|
]);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public function withdrawal(array $data): CashTransaction
|
public function withdrawal(array $data): CashTransaction
|
||||||
{
|
{
|
||||||
$cashAccount = CashAccount::firstOrFail();
|
return DB::transaction(function () use ($data) {
|
||||||
|
$cashAccount = CashAccount::firstOrFail();
|
||||||
|
|
||||||
if ($cashAccount->balance < $data['amount']) {
|
if ($cashAccount->balance < $data['amount']) {
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'amount' => 'Saldo tidak mencukupi.',
|
'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'],
|
||||||
]);
|
]);
|
||||||
}
|
});
|
||||||
|
|
||||||
$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
|
public function updateTransaction(CashTransaction $transaction, array $data): CashTransaction
|
||||||
{
|
{
|
||||||
if (! in_array($transaction->type, [CashTransactionType::DEPOSIT, CashTransactionType::WITHDRAWAL])) {
|
return DB::transaction(function () use ($transaction, $data) {
|
||||||
throw ValidationException::withMessages([
|
if (! in_array($transaction->type, [CashTransactionType::DEPOSIT, CashTransactionType::WITHDRAWAL])) {
|
||||||
'amount' => 'Transaksi ini tidak dapat diedit.',
|
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'],
|
||||||
]);
|
]);
|
||||||
}
|
|
||||||
|
|
||||||
$cashAccount = CashAccount::firstOrFail();
|
return $transaction;
|
||||||
$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
|
public function deleteTransaction(CashTransaction $transaction): bool
|
||||||
{
|
{
|
||||||
if (! in_array($transaction->type, [CashTransactionType::DEPOSIT, CashTransactionType::WITHDRAWAL])) {
|
return DB::transaction(function () use ($transaction) {
|
||||||
throw ValidationException::withMessages([
|
if (! in_array($transaction->type, [CashTransactionType::DEPOSIT, CashTransactionType::WITHDRAWAL])) {
|
||||||
'amount' => 'Transaksi ini tidak dapat dihapus.',
|
throw ValidationException::withMessages([
|
||||||
]);
|
'amount' => 'Transaksi ini tidak dapat dihapus.',
|
||||||
}
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
$cashAccount = CashAccount::firstOrFail();
|
$cashAccount = CashAccount::firstOrFail();
|
||||||
$isDeposit = $transaction->type === CashTransactionType::DEPOSIT;
|
$isDeposit = $transaction->type === CashTransactionType::DEPOSIT;
|
||||||
|
|
||||||
$newBalance = $isDeposit
|
$newBalance = $isDeposit
|
||||||
? $cashAccount->balance - $transaction->amount
|
? $cashAccount->balance - $transaction->amount
|
||||||
: $cashAccount->balance + $transaction->amount;
|
: $cashAccount->balance + $transaction->amount;
|
||||||
|
|
||||||
if ($newBalance < 0) {
|
if ($newBalance < 0) {
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
'amount' => 'Saldo tidak mencukupi untuk menghapus transaksi ini.',
|
'amount' => 'Saldo tidak mencukupi untuk menghapus transaksi ini.',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$cashAccount->update(['balance' => $newBalance]);
|
$cashAccount->update(['balance' => $newBalance]);
|
||||||
|
|
||||||
return $transaction->delete();
|
return $transaction->delete();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user