|  | @@ -5,11 +5,12 @@ namespace App\Services;
 | 
		
	
		
			
			| 5 | 5 |  use App\Contracts\AccountHandler;
 | 
		
	
		
			
			| 6 | 6 |  use App\Enums\Accounting\AccountCategory;
 | 
		
	
		
			
			| 7 | 7 |  use App\Models\Accounting\Account;
 | 
		
	
		
			
			|  | 8 | +use App\Models\Accounting\JournalEntry;
 | 
		
	
		
			
			| 8 | 9 |  use App\Models\Accounting\Transaction;
 | 
		
	
		
			
			| 9 |  | -use App\Models\Banking\BankAccount;
 | 
		
	
		
			
			| 10 | 10 |  use App\Repositories\Accounting\JournalEntryRepository;
 | 
		
	
		
			
			| 11 | 11 |  use App\Utilities\Currency\CurrencyAccessor;
 | 
		
	
		
			
			| 12 | 12 |  use App\ValueObjects\Money;
 | 
		
	
		
			
			|  | 13 | +use Illuminate\Support\Facades\DB;
 | 
		
	
		
			
			| 13 | 14 |  
 | 
		
	
		
			
			| 14 | 15 |  class AccountService implements AccountHandler
 | 
		
	
		
			
			| 15 | 16 |  {
 | 
		
	
	
		
			
			|  | @@ -67,22 +68,23 @@ class AccountService implements AccountHandler
 | 
		
	
		
			
			| 67 | 68 |  
 | 
		
	
		
			
			| 68 | 69 |      public function getRetainedEarnings(string $startDate): Money
 | 
		
	
		
			
			| 69 | 70 |      {
 | 
		
	
		
			
			| 70 |  | -        $revenueAccounts = Account::where('category', AccountCategory::Revenue)
 | 
		
	
		
			
			| 71 |  | -            ->get();
 | 
		
	
		
			
			| 72 |  | -
 | 
		
	
		
			
			| 73 |  | -        $expenseAccounts = Account::where('category', AccountCategory::Expense)
 | 
		
	
		
			
			| 74 |  | -            ->get();
 | 
		
	
		
			
			| 75 |  | -
 | 
		
	
		
			
			| 76 |  | -        $revenue = 0;
 | 
		
	
		
			
			| 77 |  | -        $expense = 0;
 | 
		
	
		
			
			| 78 |  | -
 | 
		
	
		
			
			| 79 |  | -        foreach ($revenueAccounts as $account) {
 | 
		
	
		
			
			| 80 |  | -            $revenue += $this->journalEntryRepository->sumCreditAmounts($account, $startDate);
 | 
		
	
		
			
			| 81 |  | -        }
 | 
		
	
		
			
			| 82 |  | -
 | 
		
	
		
			
			| 83 |  | -        foreach ($expenseAccounts as $account) {
 | 
		
	
		
			
			| 84 |  | -            $expense += $this->journalEntryRepository->sumDebitAmounts($account, $startDate);
 | 
		
	
		
			
			| 85 |  | -        }
 | 
		
	
		
			
			|  | 71 | +        $revenue = JournalEntry::whereHas('account', static function ($query) {
 | 
		
	
		
			
			|  | 72 | +            $query->where('category', AccountCategory::Revenue);
 | 
		
	
		
			
			|  | 73 | +        })
 | 
		
	
		
			
			|  | 74 | +            ->where('type', 'credit')
 | 
		
	
		
			
			|  | 75 | +            ->whereHas('transaction', static function ($query) use ($startDate) {
 | 
		
	
		
			
			|  | 76 | +                $query->where('posted_at', '<=', $startDate);
 | 
		
	
		
			
			|  | 77 | +            })
 | 
		
	
		
			
			|  | 78 | +            ->sum('amount');
 | 
		
	
		
			
			|  | 79 | +
 | 
		
	
		
			
			|  | 80 | +        $expense = JournalEntry::whereHas('account', static function ($query) {
 | 
		
	
		
			
			|  | 81 | +            $query->where('category', AccountCategory::Expense);
 | 
		
	
		
			
			|  | 82 | +        })
 | 
		
	
		
			
			|  | 83 | +            ->where('type', 'debit')
 | 
		
	
		
			
			|  | 84 | +            ->whereHas('transaction', static function ($query) use ($startDate) {
 | 
		
	
		
			
			|  | 85 | +                $query->where('posted_at', '<=', $startDate);
 | 
		
	
		
			
			|  | 86 | +            })
 | 
		
	
		
			
			|  | 87 | +            ->sum('amount');
 | 
		
	
		
			
			| 86 | 88 |  
 | 
		
	
		
			
			| 87 | 89 |          $retainedEarnings = $revenue - $expense;
 | 
		
	
		
			
			| 88 | 90 |  
 | 
		
	
	
		
			
			|  | @@ -149,20 +151,41 @@ class AccountService implements AccountHandler
 | 
		
	
		
			
			| 149 | 151 |  
 | 
		
	
		
			
			| 150 | 152 |      public function getTotalBalanceForAllBankAccounts(string $startDate, string $endDate): Money
 | 
		
	
		
			
			| 151 | 153 |      {
 | 
		
	
		
			
			| 152 |  | -        $bankAccounts = BankAccount::with('account')
 | 
		
	
		
			
			| 153 |  | -            ->get();
 | 
		
	
		
			
			| 154 |  | -
 | 
		
	
		
			
			| 155 |  | -        $totalBalance = 0;
 | 
		
	
		
			
			|  | 154 | +        $accountIds = Account::whereHas('bankAccount')
 | 
		
	
		
			
			|  | 155 | +            ->pluck('id')
 | 
		
	
		
			
			|  | 156 | +            ->toArray();
 | 
		
	
		
			
			| 156 | 157 |  
 | 
		
	
		
			
			| 157 |  | -        foreach ($bankAccounts as $bankAccount) {
 | 
		
	
		
			
			| 158 |  | -            $account = $bankAccount->account;
 | 
		
	
		
			
			| 159 |  | -
 | 
		
	
		
			
			| 160 |  | -            if ($account) {
 | 
		
	
		
			
			| 161 |  | -                $endingBalance = $this->getEndingBalance($account, $startDate, $endDate)?->getAmount() ?? 0;
 | 
		
	
		
			
			| 162 |  | -                $totalBalance += $endingBalance;
 | 
		
	
		
			
			| 163 |  | -            }
 | 
		
	
		
			
			|  | 158 | +        if (empty($accountIds)) {
 | 
		
	
		
			
			|  | 159 | +            return new Money(0, CurrencyAccessor::getDefaultCurrency());
 | 
		
	
		
			
			| 164 | 160 |          }
 | 
		
	
		
			
			| 165 | 161 |  
 | 
		
	
		
			
			|  | 162 | +        $result = DB::table('journal_entries')
 | 
		
	
		
			
			|  | 163 | +            ->join('transactions', 'journal_entries.transaction_id', '=', 'transactions.id')
 | 
		
	
		
			
			|  | 164 | +            ->whereIn('journal_entries.account_id', $accountIds)
 | 
		
	
		
			
			|  | 165 | +            ->where('transactions.posted_at', '<=', $endDate)
 | 
		
	
		
			
			|  | 166 | +            ->selectRaw('
 | 
		
	
		
			
			|  | 167 | +            SUM(CASE
 | 
		
	
		
			
			|  | 168 | +                WHEN transactions.posted_at <= ? AND journal_entries.type = "debit" THEN journal_entries.amount
 | 
		
	
		
			
			|  | 169 | +                WHEN transactions.posted_at <= ? AND journal_entries.type = "credit" THEN -journal_entries.amount
 | 
		
	
		
			
			|  | 170 | +                ELSE 0
 | 
		
	
		
			
			|  | 171 | +            END) AS totalStartingBalance,
 | 
		
	
		
			
			|  | 172 | +            SUM(CASE
 | 
		
	
		
			
			|  | 173 | +                WHEN transactions.posted_at BETWEEN ? AND ? AND journal_entries.type = "debit" THEN journal_entries.amount
 | 
		
	
		
			
			|  | 174 | +                WHEN transactions.posted_at BETWEEN ? AND ? AND journal_entries.type = "credit" THEN -journal_entries.amount
 | 
		
	
		
			
			|  | 175 | +                ELSE 0
 | 
		
	
		
			
			|  | 176 | +            END) AS totalNetMovement
 | 
		
	
		
			
			|  | 177 | +        ', [
 | 
		
	
		
			
			|  | 178 | +                $startDate,
 | 
		
	
		
			
			|  | 179 | +                $startDate,
 | 
		
	
		
			
			|  | 180 | +                $startDate,
 | 
		
	
		
			
			|  | 181 | +                $endDate,
 | 
		
	
		
			
			|  | 182 | +                $startDate,
 | 
		
	
		
			
			|  | 183 | +                $endDate,
 | 
		
	
		
			
			|  | 184 | +            ])
 | 
		
	
		
			
			|  | 185 | +            ->first();
 | 
		
	
		
			
			|  | 186 | +
 | 
		
	
		
			
			|  | 187 | +        $totalBalance = $result->totalStartingBalance + $result->totalNetMovement;
 | 
		
	
		
			
			|  | 188 | +
 | 
		
	
		
			
			| 166 | 189 |          return new Money($totalBalance, CurrencyAccessor::getDefaultCurrency());
 | 
		
	
		
			
			| 167 | 190 |      }
 | 
		
	
		
			
			| 168 | 191 |  
 |