feature/RVRNEXT-7-calculate-balance-for-community-members #37
							
								
								
									
										90
									
								
								src/Finance/BalanceCalculator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								src/Finance/BalanceCalculator.php
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,90 @@
 | 
			
		||||
<?php namespace RVR\Finance;
 | 
			
		||||
 | 
			
		||||
use RVR\PersistentData\Model\Community;
 | 
			
		||||
use RVR\Repository\CommunityMemberRepository;
 | 
			
		||||
use RVR\Repository\TransactionRepository;
 | 
			
		||||
 | 
			
		||||
class BalanceCalculator
 | 
			
		||||
{
 | 
			
		||||
    private Community $community;
 | 
			
		||||
 | 
			
		||||
    private TransactionRepository $transactionRepository;
 | 
			
		||||
 | 
			
		||||
    private CommunityMemberRepository $communityMemberRepository;
 | 
			
		||||
 | 
			
		||||
    private ExchangeRateCalculator $exchangeRateCalculator;
 | 
			
		||||
 | 
			
		||||
    private array $members;
 | 
			
		||||
 | 
			
		||||
    private array $payments;
 | 
			
		||||
 | 
			
		||||
    public function __construct(Community $community)
 | 
			
		||||
    {
 | 
			
		||||
        $this->community = $community;
 | 
			
		||||
        $this->transactionRepository = new TransactionRepository();
 | 
			
		||||
        $this->communityMemberRepository = new CommunityMemberRepository();
 | 
			
		||||
        $this->exchangeRateCalculator = new ExchangeRateCalculator($this->community->getMainCurrency());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function calculate(): array
 | 
			
		||||
    {
 | 
			
		||||
        $this->collectMembers();
 | 
			
		||||
        $this->createPaymentsMatrix();
 | 
			
		||||
        $this->sumTransactions();
 | 
			
		||||
        return $this->calculateActualDebts();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function collectMembers(): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->members = [];
 | 
			
		||||
        foreach ($this->communityMemberRepository->getAllByCommunity($this->community, true, ['user']) as $member) {
 | 
			
		||||
            $this->members[$member->getUserId()] = $member;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function createPaymentsMatrix(): void
 | 
			
		||||
    {
 | 
			
		||||
        $this->payments = [];
 | 
			
		||||
        foreach ($this->members as $payerUserId => $member) {
 | 
			
		||||
            $this->payments[$payerUserId] = [];
 | 
			
		||||
            foreach ($this->members as $payeeUserId => $member) {
 | 
			
		||||
                $this->payments[$payerUserId][$payeeUserId] = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function sumTransactions(): void
 | 
			
		||||
    {
 | 
			
		||||
        $membersCount = count($this->members);
 | 
			
		||||
        $transactions = $this->transactionRepository->getAllByCommunity($this->community, true, ['currency']);
 | 
			
		||||
 | 
			
		||||
        foreach ($transactions as $transaction) {
 | 
			
		||||
            $sum = $this->exchangeRateCalculator->calculate($transaction->getSum(), $transaction->getCurrency(), $transaction->getTimeDate());
 | 
			
		||||
 | 
			
		||||
            if ($transaction->getPayeeUserId()) {
 | 
			
		||||
                $this->payments[$transaction->getPayerUserId()][$transaction->getPayeeUserId()] += $sum;
 | 
			
		||||
            } else {
 | 
			
		||||
                foreach ($this->members as $payeeUserId => $member) {
 | 
			
		||||
                    $this->payments[$transaction->getPayerUserId()][$payeeUserId] += $sum / $membersCount;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private function calculateActualDebts(): array
 | 
			
		||||
    {
 | 
			
		||||
        $actualDebts = [];
 | 
			
		||||
 | 
			
		||||
        foreach ($this->payments as $payerUserId => $paymentsOfPayer) {
 | 
			
		||||
            foreach ($paymentsOfPayer as $payeeUserId => $sum) {
 | 
			
		||||
                $actualDebt = $this->payments[$payeeUserId][$payerUserId] - $sum;
 | 
			
		||||
 | 
			
		||||
                if (round($actualDebt, $this->community->getMainCurrency()->getRoundDigits()) > 0.0) {
 | 
			
		||||
                    $actualDebts[] = ['payer' => $this->members[$payerUserId], 'payee' => $this->members[$payeeUserId], 'amount' => $actualDebt];
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return $actualDebts;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user