- Menambahkan `AccountBalanceService` dengan transaksi PostgreSQL dan proper error handling. - Implementasi `BalanceServiceProvider` untuk mendukung dependency injection pattern. - Registrasi `BalanceServiceProvider` dalam `WebstatementServiceProvider`. - Penambahan `CAST` ke `DECIMAL(15,2)` untuk kompatibilitas PostgreSQL. - Perhitungan balance summary mencakup opening balance dan closing balance. - Agregasi transaksi dengan type casting yang aman. - Implementasi database transaction handling dengan mekanisme rollback dan commit. - Logging komprehensif untuk debugging dan audit trail. - Mendukung balance inquiry berdasarkan tanggal maupun periode tertentu. - Validasi akun dengan pengecekan `exists` untuk memastikan data valid.
131 lines
4.5 KiB
PHP
131 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace Modules\Webstatement\Services;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Carbon\Carbon;
|
|
use Modules\Webstatement\Models\AccountBalance;
|
|
use Modules\Webstatement\Models\StmtEntry;
|
|
|
|
class AccountBalanceService
|
|
{
|
|
/**
|
|
* Get balance summary (opening and closing balance)
|
|
*
|
|
* @param string $accountNumber
|
|
* @param string $startDate
|
|
* @param string $endDate
|
|
* @return array
|
|
*/
|
|
public function getBalanceSummary(string $accountNumber, string $startDate, string $endDate): array
|
|
{
|
|
return DB::transaction(function () use ($accountNumber, $startDate, $endDate) {
|
|
Log::info('Calculating balance summary', [
|
|
'account_number' => $accountNumber,
|
|
'start_date' => $startDate,
|
|
'end_date' => $endDate
|
|
]);
|
|
|
|
// Convert dates to Carbon instances
|
|
$startDateCarbon = Carbon::parse($startDate);
|
|
$endDateCarbon = Carbon::parse($endDate);
|
|
|
|
// Get opening balance (balance from previous day)
|
|
$openingBalanceDate = $startDateCarbon->copy()->subDay();
|
|
$openingBalance = $this->getAccountBalance($accountNumber, $openingBalanceDate);
|
|
|
|
// Get closing balance date (previous day from end date)
|
|
$closingBalanceDate = $endDateCarbon->copy()->subDay();
|
|
$closingBalanceBase = $this->getAccountBalance($accountNumber, $closingBalanceDate);
|
|
|
|
// Get transactions on end date
|
|
$transactionsOnEndDate = $this->getTransactionsOnDate($accountNumber, $endDate);
|
|
|
|
// Calculate closing balance
|
|
$closingBalance = $closingBalanceBase + $transactionsOnEndDate;
|
|
|
|
$result = [
|
|
'account_number' => $accountNumber,
|
|
'period' => [
|
|
'start_date' => $startDate,
|
|
'end_date' => $endDate
|
|
],
|
|
'opening_balance' => [
|
|
'date' => $openingBalanceDate->format('Y-m-d'),
|
|
'balance' => $openingBalance,
|
|
'formatted_balance' => number_format($openingBalance, 2)
|
|
],
|
|
'closing_balance' => [
|
|
'date' => $endDate,
|
|
'balance' => $closingBalance,
|
|
'formatted_balance' => number_format($closingBalance, 2),
|
|
'base_balance' => [
|
|
'date' => $closingBalanceDate->format('Y-m-d'),
|
|
'balance' => $closingBalanceBase,
|
|
'formatted_balance' => number_format($closingBalanceBase, 2)
|
|
],
|
|
'transactions_on_end_date' => $transactionsOnEndDate,
|
|
'formatted_transactions_on_end_date' => number_format($transactionsOnEndDate, 2)
|
|
]
|
|
];
|
|
|
|
Log::info('Balance summary calculated successfully', $result);
|
|
|
|
return $result;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Get account balance for specific date
|
|
*
|
|
* @param string $accountNumber
|
|
* @param Carbon $date
|
|
* @return float
|
|
*/
|
|
private function getAccountBalance(string $accountNumber, Carbon $date): float
|
|
{
|
|
$balance = AccountBalance::where('account_number', $accountNumber)
|
|
->where('period', $date->format('Ymd'))
|
|
->value('actual_balance');
|
|
|
|
if ($balance === null) {
|
|
Log::warning('Account balance not found', [
|
|
'account_number' => $accountNumber,
|
|
'date' => $date->format('Y-m-d'),
|
|
'period' => $date->format('Ymd')
|
|
]);
|
|
return 0.00;
|
|
}
|
|
|
|
return (float) $balance;
|
|
}
|
|
|
|
/**
|
|
* Get transactions on specific date
|
|
*
|
|
* @param string $accountNumber
|
|
* @param string $date
|
|
* @return float
|
|
*/
|
|
private function getTransactionsOnDate(string $accountNumber, string $date): float
|
|
{
|
|
$total = StmtEntry::where('account_number', $accountNumber)
|
|
->whereDate('value_date', $date)
|
|
->sum(DB::raw('CAST(amount_lcy AS DECIMAL(15,2))'));
|
|
|
|
return (float) $total;
|
|
}
|
|
|
|
/**
|
|
* Validate if account exists
|
|
*
|
|
* @param string $accountNumber
|
|
* @return bool
|
|
*/
|
|
public function validateAccount(string $accountNumber): bool
|
|
{
|
|
return AccountBalance::where('account_number', $accountNumber)->exists();
|
|
}
|
|
}
|