2015-02-07 08:23:44 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								< ? php 
							 
						 
					
						
							
								
									
										
										
										
											2022-12-24 05:06:39 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 12:41:23 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								/** 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  Steam . php 
							 
						 
					
						
							
								
									
										
										
										
											2020-02-16 13:56:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  Copyright  ( c )  2019  james @ firefly - iii . org 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 12:41:23 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-02 06:37:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  This  file  is  part  of  Firefly  III  ( https :// github . com / firefly - iii ) . 
							 
						 
					
						
							
								
									
										
										
										
											2016-10-05 06:52:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-02 06:37:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  This  program  is  free  software :  you  can  redistribute  it  and / or  modify 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  it  under  the  terms  of  the  GNU  Affero  General  Public  License  as 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  published  by  the  Free  Software  Foundation ,  either  version  3  of  the 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  License ,  or  ( at  your  option )  any  later  version . 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-21 08:40:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-02 06:37:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  This  program  is  distributed  in  the  hope  that  it  will  be  useful , 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-21 08:40:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  but  WITHOUT  ANY  WARRANTY ;  without  even  the  implied  warranty  of 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR  PURPOSE .   See  the 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-02 06:37:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  GNU  Affero  General  Public  License  for  more  details . 
							 
						 
					
						
							
								
									
										
										
										
											2017-10-21 08:40:00 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 * 
							 
						 
					
						
							
								
									
										
										
										
											2019-10-02 06:37:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  You  should  have  received  a  copy  of  the  GNU  Affero  General  Public  License 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								 *  along  with  this  program .   If  not ,  see  < https :// www . gnu . org / licenses />. 
							 
						 
					
						
							
								
									
										
										
										
											2016-05-20 12:41:23 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
									
										
										
										
											2017-04-09 07:44:22 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								declare ( strict_types = 1 ); 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-07 08:23:44 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								namespace  FireflyIII\Support ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								use  Carbon\Carbon ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  Exception ; 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-18 10:20:19 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  FireflyIII\Exceptions\FireflyException ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-07 08:23:44 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								use  FireflyIII\Models\Account ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  FireflyIII\Models\AccountMeta ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-10 07:39:59 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  FireflyIII\Models\Transaction ; 
							 
						 
					
						
							
								
									
										
										
										
											2020-03-20 04:37:45 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  FireflyIII\Models\TransactionCurrency ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-04 19:43:53 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  FireflyIII\Support\Facades\Amount ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								use  FireflyIII\Support\Http\Api\ExchangeRateConverter ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-10 06:53:08 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  FireflyIII\Support\Singleton\PreferencesSingleton ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-05 22:11:54 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  Illuminate\Support\Collection ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-26 09:16:17 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  Illuminate\Support\Facades\DB ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-08 20:06:23 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  Illuminate\Support\Facades\Log ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-23 12:47:04 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  Illuminate\Support\Str ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-05 12:57:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  Psr\Container\ContainerExceptionInterface ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								use  Psr\Container\NotFoundExceptionInterface ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 16:57:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  ValueError ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 17:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  function  Safe\parse_url ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								use  function  Safe\preg_replace ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 17:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2015-02-07 08:23:44 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								/** 
							 
						 
					
						
							
								
									
										
										
										
											2017-11-15 12:25:49 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								 *  Class  Steam . 
							 
						 
					
						
							
								
									
										
										
										
											2015-02-07 08:23:44 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							 
							
							
								 */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								class  Steam 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								{ 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-07 14:32:23 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  accountsBalancesOptimized ( Collection  $accounts ,  Carbon  $date ,  ? TransactionCurrency  $primary  =  null ,  ? bool  $convertToPrimary  =  null ,  bool  $inclusive  =  true ) :  array 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 06:44:48 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( sprintf ( 'accountsBalancesOptimized: Called for %d account(s) with date/time "%s" (inclusive: %s)' ,  $accounts -> count (),  $date -> toIso8601String (),  var_export ( $inclusive ,  true ))); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $result       =  []; 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $convertToPrimary  ? ? =  Amount :: convertToPrimary (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $primary           ? ? =  Amount :: getPrimaryCurrency (); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $currencies   =  $this -> getCurrencies ( $accounts ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // balance(s) in all currencies for ALL accounts.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $arrayOfSums  =  Transaction :: whereIn ( 'account_id' ,  $accounts -> pluck ( 'id' ) -> toArray ()) 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            -> leftJoin ( 'transaction_journals' ,  'transaction_journals.id' ,  '=' ,  'transactions.transaction_journal_id' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> leftJoin ( 'transaction_currencies' ,  'transaction_currencies.id' ,  '=' ,  'transactions.transaction_currency_id' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> where ( 'transaction_journals.date' ,  $inclusive  ?  '<='  :  '<' ,  $date -> format ( 'Y-m-d H:i:s' )) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> groupBy ([ 'transactions.account_id' ,  'transaction_currencies.code' ]) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> get ([ 'transactions.account_id' ,  'transaction_currencies.code' ,  DB :: raw ( 'SUM(transactions.amount) as sum_of_amount' )]) -> toArray () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( 'Array of sums: ' ,  $arrayOfSums ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /** @var Account $account */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        foreach  ( $accounts  as  $account )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $return                =  [ 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                'pc_balance'  =>  '0' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                'balance'     =>  '0' ,  // this key is overwritten right away, but I must remember it is always created.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ]; 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $currency              =  $currencies [ $account -> id ]; 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // second array
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $accountSums           =  array_filter ( $arrayOfSums ,  fn  ( $entry )  =>  $entry [ 'account_id' ]  ===  $account -> id ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( 0  ===  count ( $accountSums ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                $result [ $account -> id ]  =  $return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $sumsByCode            =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            foreach  ( $accountSums  as  $accountSum )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                // $accountSum  = array_values($accountSum)[0];
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                $sumOfAmount                      =  ( string ) $accountSum [ 'sum_of_amount' ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $sumOfAmount                      =  $this -> floatalize ( ''  ===  $sumOfAmount  ?  '0'  :  $sumOfAmount ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                $sumsByCode [ $accountSum [ 'code' ]]  =  $sumOfAmount ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // Log::debug('All balances are (joined)', $others);
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // if there is no request to convert, take this as "balance" and "pc_balance".
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $return [ 'balance' ]     =  $sumsByCode [ $currency -> code ]  ? ?  '0' ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( ! $convertToPrimary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                unset ( $return [ 'pc_balance' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Log::debug(sprintf('Set balance to %s, unset pc_balance', $return['balance']));
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // if there is a request to convert, convert to "pc_balance" and use "balance" for whichever amount is in the primary currency.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( $convertToPrimary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $return [ 'pc_balance' ]  =  $this -> convertAllBalances ( $sumsByCode ,  $primary ,  $date ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Log::debug(sprintf('Set pc_balance to %s', $return['pc_balance']));
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // either way, the balance is always combined with the virtual balance:
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $virtualBalance        =  ( string )( ''  ===  ( string ) $account -> virtual_balance  ?  '0'  :  $account -> virtual_balance ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( $convertToPrimary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // the primary currency balance is combined with a converted virtual_balance:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $converter             =  new  ExchangeRateConverter (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $pcVirtualBalance      =  $converter -> convert ( $currency ,  $primary ,  $date ,  $virtualBalance ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $return [ 'pc_balance' ]  =  bcadd ( $pcVirtualBalance ,  $return [ 'pc_balance' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Log::debug(sprintf('Primary virtual balance makes the primary total %s', $return['pc_balance']));
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! $convertToPrimary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // if not, also increase the balance + primary balance for consistency.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $return [ 'balance' ]  =  bcadd ( $return [ 'balance' ],  $virtualBalance ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                // Log::debug(sprintf('Virtual balance makes the (primary currency) total %s', $return['balance']));
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $final                 =  array_merge ( $return ,  $sumsByCode ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $result [ $account -> id ]  =  $final ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            Log :: debug ( sprintf ( 'Final balance for account #%d is' ,  $account -> id ),  $final ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $result ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 07:09:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /** 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Calls  accountsBalancesOptimized  for  the  given  accounts  and  makes  sure  that  inclusive  is  set  to  false ,  so  it  properly  gets  the  balance  of  a  range . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:54:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  accountsBalancesInRange ( Collection  $accounts ,  Carbon  $start ,  Carbon  $end ,  ? TransactionCurrency  $primary  =  null ,  ? bool  $convertToPrimary  =  null ) :  array 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-07 14:32:23 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $this -> accountsBalancesOptimized ( $accounts ,  $start ,  $primary ,  $convertToPrimary ,  inclusive :  false ), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $this -> accountsBalancesOptimized ( $accounts ,  $end ,  $primary ,  $convertToPrimary ), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /** 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  https :// stackoverflow . com / questions / 1642614 / how - to - ceil - floor - and - round - bcmath - numbers 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  function  bcround ( ? string  $number ,  int  $precision  =  0 ) :  string 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 08:43:12 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( null  ===  $number )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  '0' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ''  ===  trim ( $number ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  '0' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // if the number contains "E", it's in scientific notation, so we need to convert it to a normal number first.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( false  !==  stripos ( $number ,  'e' ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $number  =  sprintf ( '%.12f' ,  $number ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 08:43:12 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision));
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( str_contains ( $number ,  '.' ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( '-'  !==  $number [ 0 ])  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                return  bcadd ( $number ,  '0.' . str_repeat ( '0' ,  $precision ) . '5' ,  $precision ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  bcsub ( $number ,  '0.' . str_repeat ( '0' ,  $precision ) . '5' ,  $precision ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 08:43:12 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $number ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  filterAccountBalance ( array  $set ,  Account  $account ,  bool  $convertToPrimary ,  ? TransactionCurrency  $currency  =  null ) :  array 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Log :: debug ( sprintf ( 'filterAccountBalance(#%d)' ,  $account -> id ),  $set ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( 0  ===  count ( $set ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Log :: debug ( sprintf ( 'Return empty array for account #%d' ,  $account -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $primaryCurrency  =  Amount :: getPrimaryCurrency (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( $convertToPrimary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( $primaryCurrency -> id  ===  $currency ? -> id )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Log :: debug ( sprintf ( 'Unset [%s] for account #%d (no longer unset "pc_balance")' ,  $primaryCurrency -> code ,  $account -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                unset ( $set [ $primaryCurrency -> code ]); 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // todo rethink this logic.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( $currency  instanceof  TransactionCurrency  &&  $primaryCurrency -> id  !==  $currency -> id )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                Log :: debug ( sprintf ( 'Unset balance for account #%d' ,  $account -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                unset ( $set [ 'balance' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 17:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( ! $currency  instanceof  TransactionCurrency )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                Log :: debug ( sprintf ( 'Unset balance for account #%d' ,  $account -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                unset ( $set [ 'balance' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! $convertToPrimary )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 17:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( ! $currency  instanceof  TransactionCurrency )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 13:48:32 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                Log :: debug ( sprintf ( 'Unset pc_balance and make primaryCurrency balance the balance for account #%d' ,  $account -> id )); 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                $set [ 'balance' ]  =  $set [ $primaryCurrency -> code ]  ? ?  '0' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                unset ( $set [ $primaryCurrency -> code ]); 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 17:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( $currency  instanceof  TransactionCurrency )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                Log :: debug ( sprintf ( 'Unset [%s] + [%s] balance for account #%d' ,  $primaryCurrency -> code ,  $currency -> code ,  $account -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                unset ( $set [ $primaryCurrency -> code ],  $set [ $currency -> code ]); 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // put specific value first in array.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( array_key_exists ( 'pc_balance' ,  $set ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $set  =  [ 'pc_balance'  =>  $set [ 'pc_balance' ]]  +  $set ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( array_key_exists ( 'balance' ,  $set ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $set  =  [ 'balance'  =>  $set [ 'balance' ]]  +  $set ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Log :: debug ( sprintf ( 'Return #%d' ,  $account -> id ),  $set ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $set ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  filterAccountBalances ( array  $total ,  Account  $account ,  bool  $convertToPrimary ,  ? TransactionCurrency  $currency  =  null ) :  array 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Log :: debug ( sprintf ( 'filterAccountBalances(#%d)' ,  $account -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $return  =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        foreach  ( $total  as  $key  =>  $value )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $return [ $key ]  =  $this -> filterAccountBalance ( $value ,  $account ,  $convertToPrimary ,  $currency ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        Log :: debug ( sprintf ( 'end of filterAccountBalances(#%d)' ,  $account -> id )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  filterSpaces ( string  $string ) :  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $search  =  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0001} " ,  // start of heading
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0002} " ,  // start of text
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0003} " ,  // end of text
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0004} " ,  // end of transmission
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0005} " ,  // enquiry
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0006} " ,  // ACK
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0007} " ,  // BEL
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0008} " ,  // backspace
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 000E} " ,  // shift out
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 000F} " ,  // shift in
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0010} " ,  // data link escape
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0011} " ,  // DC1
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0012} " ,  // DC2
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0013} " ,  // DC3
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0014} " ,  // DC4
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0015} " ,  // NAK
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0016} " ,  // SYN
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0017} " ,  // ETB
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0018} " ,  // CAN
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 0019} " ,  // EM
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 001A} " ,  // SUB
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 001B} " ,  // escape
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 001C} " ,  // file separator
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 001D} " ,  // group separator
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 001E} " ,  // record separator
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 001F} " ,  // unit separator
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 007F} " ,  // DEL
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 00A0} " ,  // non-breaking space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 1680} " ,  // ogham space mark
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 180E} " ,  // mongolian vowel separator
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 2000} " ,  // en quad
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 2001} " ,  // em quad
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 2002} " ,  // en space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 2003} " ,  // em space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 2004} " ,  // three-per-em space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 2005} " ,  // four-per-em space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 2006} " ,  // six-per-em space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 2007} " ,  // figure space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 2008} " ,  // punctuation space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 2009} " ,  // thin space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 200A} " ,  // hair space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 200B} " ,  // zero width space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 202F} " ,  // narrow no-break space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { 3000} " ,  // ideographic space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \ u { FEFF} " ,  // zero width no -break space
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            " \x20 " ,  // plain old normal space,
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ' ' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // clear zalgo text
 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 17:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $string  =  preg_replace ( '/(\pM{2})\pM+/u' ,  '\1' ,  $string ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $string  =  preg_replace ( '/\s+/' ,  '' ,  $string ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  str_replace ( $search ,  '' ,  $string ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 16:41:55 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /** 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 07:09:42 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     *  @ deprecated 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 06:44:48 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     *  By  default  this  method  returns  " smaller than or equal to " ,  so  be  careful  with  END  OF  DAY . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  If  you  need  end  of  day  balance ,  use  " inclusive = false " . 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Returns  the  balance  of  an  account  at  exact  moment  given .  Array  with  at  least  one  value . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Always  returns : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  " balance " :  balance  in  the  account 's currency OR user' s  primary  currency  if  the  account  has  no  currency 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  " EUR " :  balance  in  EUR  ( or  whatever  currencies  the  account  has  balance  in ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  If  the  user  has  $convertToPrimary : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  " balance " :  balance  in  the  account 's currency OR user' s  primary  currency  if  the  account  has  no  currency 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  -->  " pc_balance " :  balance  in  the  user ' s  primary  currency ,  with  all  amounts  converted  to  the  primary  currency . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  " EUR " :  balance  in  EUR  ( or  whatever  currencies  the  account  has  balance  in ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 06:44:48 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  finalAccountBalance ( Account  $account ,  Carbon  $date ,  ? TransactionCurrency  $primary  =  null ,  ? bool  $convertToPrimary  =  null ,  bool  $inclusive  =  true ) :  array 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $cache              =  new  CacheProperties (); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $cache -> addProperty ( $account -> id ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $cache -> addProperty ( $date ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( $cache -> has ())  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 06:44:48 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            Log :: debug ( sprintf ( 'CACHED finalAccountBalance(#%d, %s, inclusive:%s)' ,  $account -> id ,  $date -> format ( 'Y-m-d H:i:s' ),  var_export ( $inclusive ,  true ))); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // return $cache->get();
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 06:44:48 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( sprintf ( 'finalAccountBalance(#%d, %s)' ,  $account -> id ,  $date -> format ( 'Y-m-d H:i:s' ))); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( null  ===  $convertToPrimary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $convertToPrimary  =  Amount :: convertToPrimary ( $account -> user ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! $primary  instanceof  TransactionCurrency )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $primary  =  Amount :: getPrimaryCurrencyByUserGroup ( $account -> user -> userGroup ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // account balance thing.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $currencyPresent    =  isset ( $account -> meta )  &&  array_key_exists ( 'currency' ,  $account -> meta )  &&  null  !==  $account -> meta [ 'currency' ]; 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( $currencyPresent )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $accountCurrency  =  $account -> meta [ 'currency' ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! $currencyPresent )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $accountCurrency  =  $this -> getAccountCurrency ( $account ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $hasCurrency        =  null  !==  $accountCurrency ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $currency           =  $hasCurrency  ?  $accountCurrency  :  $primary ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $return             =  [ 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            'pc_balance'  =>  '0' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            'balance'     =>  '0' ,  // this key is overwritten right away, but I must remember it is always created.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // balance(s) in all currencies.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $array              =  $account -> transactions () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> leftJoin ( 'transaction_journals' ,  'transaction_journals.id' ,  '=' ,  'transactions.transaction_journal_id' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> leftJoin ( 'transaction_currencies' ,  'transaction_currencies.id' ,  '=' ,  'transactions.transaction_currency_id' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> where ( 'transaction_journals.date' ,  $inclusive  ?  '<='  :  '<' ,  $date -> format ( 'Y-m-d H:i:s' )) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> get ([ 'transaction_currencies.code' ,  'transactions.amount' ]) -> toArray () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $others             =  $this -> groupAndSumTransactions ( $array ,  'code' ,  'amount' ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( 'All balances are (joined)' ,  $others ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // if there is no request to convert, take this as "balance" and "pc_balance".
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $return [ 'balance' ]  =  $others [ $currency -> code ]  ? ?  '0' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! $convertToPrimary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            unset ( $return [ 'pc_balance' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Log::debug(sprintf('Set balance to %s, unset pc_balance', $return['balance']));
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // if there is a request to convert, convert to "pc_balance" and use "balance" for whichever amount is in the primary currency.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( $convertToPrimary )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $return [ 'pc_balance' ]  =  $this -> convertAllBalances ( $others ,  $primary ,  $date ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // Log::debug(sprintf('Set pc_balance to %s', $return['pc_balance']));
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // either way, the balance is always combined with the virtual balance:
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $virtualBalance     =  ( string )( ''  ===  ( string ) $account -> virtual_balance  ?  '0'  :  $account -> virtual_balance ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( $convertToPrimary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // the primary currency balance is combined with a converted virtual_balance:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $converter             =  new  ExchangeRateConverter (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $pcVirtualBalance      =  $converter -> convert ( $currency ,  $primary ,  $date ,  $virtualBalance ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $return [ 'pc_balance' ]  =  bcadd ( $pcVirtualBalance ,  $return [ 'pc_balance' ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Log::debug(sprintf('Primary virtual balance makes the primary total %s', $return['pc_balance']));
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! $convertToPrimary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // if not, also increase the balance + primary balance for consistency.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $return [ 'balance' ]  =  bcadd ( $return [ 'balance' ],  $virtualBalance ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // Log::debug(sprintf('Virtual balance makes the (primary currency) total %s', $return['balance']));
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $final              =  array_merge ( $return ,  $others ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:12:30 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( 'Final balance is' ,  $final ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $cache -> store ( $final ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $final ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:54:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /** 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:17:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     *  Returns  the  balance  for  the  given  account  in  the  range ,  with  daily  precision . 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 08:54:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  finalAccountBalanceInRange ( Account  $account ,  Carbon  $start ,  Carbon  $end ,  bool  $convertToPrimary ) :  array 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 16:41:55 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 20:32:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // expand period.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-08 10:51:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $start -> startOfDay (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $end -> endOfDay (); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:17:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( sprintf ( 'called finalAccountBalanceInRange(#%d, %s, %s)' ,  $account -> id ,  $start -> format ( 'Y-m-d H:i:s' ),  $end -> format ( 'Y-m-d H:i:s' ))); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 16:41:55 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 20:32:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // set up cache
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $cache                 =  new  CacheProperties (); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 16:41:55 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $cache -> addProperty ( $account -> id ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 20:32:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $cache -> addProperty ( 'final-balance-in-range' ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 16:41:55 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $cache -> addProperty ( $start ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $cache -> addProperty ( $convertToPrimary ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 16:41:55 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $cache -> addProperty ( $end ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( $cache -> has ())  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:17:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            Log :: debug ( 'Return cached finalAccountBalanceInRange' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // return $cache->get();
 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $balances              =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $formatted             =  $start -> format ( 'Y-m-d' ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 09:52:27 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( 'Get first balance to start.' ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:17:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // 2025-10-08 replaced finalAccountBalance with accountsBalancesOptimized:
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $primaryCurrency       =  Amount :: getPrimaryCurrencyByUserGroup ( $account -> user -> userGroup ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $startBalance          =  $this -> accountsBalancesOptimized ( new  Collection () -> push ( $account ),  $start ,  $primaryCurrency ,  $convertToPrimary ,  false )[ $account -> id ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $accountCurrency       =  $this -> getAccountCurrency ( $account ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $hasCurrency           =  $accountCurrency  instanceof  TransactionCurrency ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $currency              =  $accountCurrency  ? ?  $primaryCurrency ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-26 05:11:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( sprintf ( 'Currency is %s' ,  $currency -> code )); 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 06:29:07 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // set start balances:
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $startBalance [ $currency -> code ]  ? ? =  '0' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( $hasCurrency )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $startBalance [ $accountCurrency -> code ]  ? ? =  '0' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-26 05:11:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! $hasCurrency )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            Log :: debug ( sprintf ( 'Also set start balance in %s' ,  $primaryCurrency -> code )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $startBalance [ $primaryCurrency -> code ]  ? ? =  '0' ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-26 05:11:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $currencies            =  [ 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 13:10:11 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $currency -> id         =>  $currency , 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $primaryCurrency -> id  =>  $primaryCurrency , 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 20:32:58 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ]; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 06:29:07 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $balances [ $formatted ]  =  $startBalance ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-26 05:11:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( 'Final start balance: ' ,  $startBalance ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 06:29:07 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // sums up the balance changes per day.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-08 10:51:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( sprintf ( 'Date >= %s and <= %s' ,  $start -> format ( 'Y-m-d H:i:s' ),  $end -> format ( 'Y-m-d H:i:s' ))); 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $set                   =  $account -> transactions () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> leftJoin ( 'transaction_journals' ,  'transactions.transaction_journal_id' ,  '=' ,  'transaction_journals.id' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> where ( 'transaction_journals.date' ,  '>=' ,  $start -> format ( 'Y-m-d H:i:s' )) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> where ( 'transaction_journals.date' ,  '<=' ,  $end -> format ( 'Y-m-d  H:i:s' )) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> groupBy ( 'transaction_journals.date' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> groupBy ( 'transactions.transaction_currency_id' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> orderBy ( 'transaction_journals.date' ,  'ASC' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> whereNull ( 'transaction_journals.deleted_at' ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> get ( 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                [  // @phpstan-ignore-line
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    'transaction_journals.date' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    'transactions.transaction_currency_id' , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                    DB :: raw ( 'SUM(transactions.amount) AS sum_of_day' ), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $currentBalance        =  $startBalance ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $converter             =  new  ExchangeRateConverter (); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /** @var Transaction $entry */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        foreach  ( $set  as  $entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 06:29:07 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // get date object
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $carbon                                =  new  Carbon ( $entry -> date ,  $entry -> date_tz ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $carbonKey                             =  $carbon -> format ( 'Y-m-d' ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 06:29:07 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // make sure sum is a string:
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $sumOfDay                              =  ( string )( $entry -> sum_of_day  ? ?  '0' ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-06-08 05:55:22 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // #10426 make sure sum is not in scientific notation.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $sumOfDay                              =  $this -> floatalize ( $sumOfDay ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-26 05:11:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 06:29:07 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // find currency of this entry, does not have to exist.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-07 14:49:49 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $currencies [ $entry -> transaction_currency_id ]  ? ? =  Amount :: getTransactionCurrencyById ( $entry -> transaction_currency_id ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-05 07:31:26 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-02-05 06:29:07 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // make sure this $entry has its own $entryCurrency
 
							 
						 
					
						
							
								
									
										
										
										
											2025-01-04 19:25:43 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            /** @var TransactionCurrency $entryCurrency */ 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $entryCurrency                         =  $currencies [ $entry -> transaction_currency_id ]; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-26 05:11:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-02-08 07:16:56 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            Log :: debug ( sprintf ( 'Processing transaction(s) on moment %s' ,  $carbon -> format ( 'Y-m-d H:i:s' ))); 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-12 06:38:21 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // add amount to current balance in currency code.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $currentBalance [ $entryCurrency -> code ]         ? ? =  '0' ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $currentBalance [ $entryCurrency -> code ]  =  bcadd ( $sumOfDay ,  ( string ) $currentBalance [ $entryCurrency -> code ]); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-26 05:11:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // if not requested to convert to primary currency, add the amount to "balance", do nothing else.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( ! $convertToPrimary )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                $currentBalance [ 'balance' ]  =  bcadd (( string ) $currentBalance [ 'balance' ],  $sumOfDay ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-01 12:31:01 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // if convert to primary currency add the converted amount to "pc_balance".
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            // if there is a request to convert, convert to "pc_balance" and use "balance" for whichever amount is in the primary currency.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( $convertToPrimary )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $pcSumOfDay                    =  $converter -> convert ( $entryCurrency ,  $primaryCurrency ,  $carbon ,  $sumOfDay ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                $currentBalance [ 'pc_balance' ]  =  bcadd (( string )( $currentBalance [ 'pc_balance' ]  ? ?  '0' ),  $pcSumOfDay ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-27 07:36:23 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                // if it's the same currency as the entry, also add to balance (see other code).
 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-12 10:50:48 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                if  ( $currency -> id  ===  $entryCurrency -> id )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                    $currentBalance [ 'balance' ]  =  bcadd (( string ) $currentBalance [ 'balance' ],  $sumOfDay ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-12 06:38:21 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                } 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-07-27 07:36:23 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // add to final array.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $balances [ $carbonKey ]                  =  $currentBalance ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-08 07:16:56 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            Log :: debug ( sprintf ( 'Updated entry [%s]' ,  $carbonKey ),  $currentBalance ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $cache -> store ( $balances ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-22 09:52:27 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( 'End of method finalAccountBalanceInRange' ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $balances ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /** 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     *  https :// framework . zend . com / downloads / archives 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     *  Convert  a  scientific  notation  to  float 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Additionally  fixed  a  problem  with  PHP  <=  5.2 . x  with  big  integers 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  floatalize ( string  $value ) :  string 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $value   =  strtoupper ( $value ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ! str_contains ( $value ,  'E' ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  $value ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-04 19:43:53 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        Log :: debug ( sprintf ( 'Floatalizing %s' ,  $value )); 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-04 19:43:53 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $number  =  substr ( $value ,  0 ,  ( int ) strpos ( $value ,  'E' )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( str_contains ( $number ,  '.' ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $post    =  strlen ( substr ( $number ,  ( int ) strpos ( $number ,  '.' )  +  1 )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $mantis  =  substr ( $value ,  ( int ) strpos ( $value ,  'E' )  +  1 ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( $mantis  <  0 )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $post  +=  abs (( int ) $mantis ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-04 19:43:53 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // TODO careless float could break financial math.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  number_format (( float ) $value ,  $post ,  '.' ,  '' ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-24 16:56:31 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-04 19:48:38 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // TODO careless float could break financial math.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  number_format (( float ) $value ,  0 ,  '.' ,  '' ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 19:42:06 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  getAccountCurrency ( Account  $account ) :  ? TransactionCurrency 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-26 05:11:32 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $type    =  $account -> accountType -> type ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $list    =  config ( 'firefly.valid_currency_account_types' ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-04 17:41:26 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // return null if not in this list.
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! in_array ( $type ,  $list ,  true ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $result  =  $account -> accountMeta () -> where ( 'name' ,  'currency_id' ) -> first (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( null  ===  $result )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  null ; 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-25 11:59:15 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-26 05:25:46 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-07 14:49:49 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  Amount :: getTransactionCurrencyById (( int ) $result -> data ); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-25 11:59:15 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-22 18:14:14 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  getHostName ( string  $ipAddress ) :  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 06:33:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $host  =  '' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-02-22 18:14:14 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        try  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $hostName  =  gethostbyaddr ( $ipAddress ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 16:57:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        }  catch  ( Exception  $e )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 06:44:48 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            Log :: error ( $e -> getMessage ()); 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 06:33:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $hostName  =  $ipAddress ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ''  !==  ( string ) $hostName  &&  $hostName  !==  $ipAddress )  { 
							 
						 
					
						
							
								
									
										
										
										
											2024-12-22 06:33:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $host  =  $hostName ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-22 18:14:14 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-20 19:35:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  ( string ) $host ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-02-22 18:14:14 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /** 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Get  user ' s  language . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  @ throws  FireflyException 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-05 12:57:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     *  @ throws  ContainerExceptionInterface 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  @ throws  NotFoundExceptionInterface 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  function  getLanguage () :  string  // get preference
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $preference  =  app ( 'preferences' ) -> get ( 'language' ,  config ( 'firefly.default_language' ,  'en_US' )) -> data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( ! is_string ( $preference ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            throw  new  FireflyException ( sprintf ( 'Preference "language" must be a string, but is unexpectedly a "%s".' ,  gettype ( $preference ))); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  str_replace ( '-' ,  '_' ,  $preference ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2016-04-05 22:00:03 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  getLastActivities ( array  $accounts ) :  array 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-20 15:23:36 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $list  =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $set   =  auth () -> user () -> transactions () 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> whereIn ( 'transactions.account_id' ,  $accounts ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> groupBy ([ 'transactions.account_id' ,  'transaction_journals.user_id' ]) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            -> get ([ 'transactions.account_id' ,  DB :: raw ( 'MAX(transaction_journals.date) AS max_date' )])  // @phpstan-ignore-line
 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-20 19:35:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-20 15:23:36 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-05 19:41:37 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /** @var Transaction $entry */ 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-20 15:23:36 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        foreach  ( $set  as  $entry )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $date                           =  new  Carbon ( $entry -> max_date ,  config ( 'app.timezone' )); 
							 
						 
					
						
							
								
									
										
										
										
											2020-07-17 18:52:34 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $date -> setTimezone ( config ( 'app.timezone' )); 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $list [( int ) $entry -> account_id ]  =  $date ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-01-20 15:23:36 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $list ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-09-18 10:26:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /** 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Get  user ' s  locale . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  function  getLocale () :  string  // get preference
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:09:44 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $singleton  =  PreferencesSingleton :: getInstance (); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 19:43:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $cached     =  $singleton -> getPreference ( 'locale' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( null  !==  $cached )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:09:44 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  $cached ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $locale     =  app ( 'preferences' ) -> get ( 'locale' ,  config ( 'firefly.default_locale' ,  'equal' )) -> data ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-28 05:31:26 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( is_array ( $locale ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $locale  =  'equal' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-18 10:26:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( 'equal'  ===  $locale )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $locale  =  $this -> getLanguage (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $locale     =  ( string ) $locale ; 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-28 05:31:26 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-09-18 10:26:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // Check for Windows to replace the locale correctly.
 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-20 19:35:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( 'WIN'  ===  strtoupper ( substr ( PHP_OS ,  0 ,  3 )))  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:09:44 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $locale  =  str_replace ( '_' ,  '-' ,  $locale ); 
							 
						 
					
						
							
								
									
										
										
										
											2021-09-18 10:26:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:09:44 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $singleton -> setPreference ( 'locale' ,  $locale ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 19:43:39 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2021-09-18 10:26:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  $locale ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  function  getLocaleArray ( string  $locale ) :  array 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  [ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            sprintf ( '%s.utf8' ,  $locale ), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            sprintf ( '%s.UTF-8' ,  $locale ), 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-03-29 14:59:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    /** 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Returns  the  previous  URL  but  refuses  to  send  you  to  specific  URLs . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  -  outside  domain 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  -  to  JS  files ,  API  or  JSON  routes 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Uses  the  session ' s  previousUrl ()  function  as  inspired  by  GitHub  user  @ z1r0 - 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     * 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *   session () -> previousUrl ()  uses  getSafeUrl ()  so  we  can  safely  return  it : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  function  getSafePreviousUrl () :  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-29 09:01:42 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // Log::debug(sprintf('getSafePreviousUrl: "%s"', session()->previousUrl()));
 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-29 14:59:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  session () -> previousUrl ()  ? ?  route ( 'index' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    /** 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     *  Make  sure  URL  is  safe . 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								     */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    public  function  getSafeUrl ( string  $unknownUrl ,  string  $safeUrl ) :  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-29 09:01:42 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // Log::debug(sprintf('getSafeUrl(%s, %s)', $unknownUrl, $safeUrl));
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $returnUrl       =  $safeUrl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $unknownHost     =  parse_url ( $unknownUrl ,  PHP_URL_HOST ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $safeHost        =  parse_url ( $safeUrl ,  PHP_URL_HOST ); 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-29 14:59:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        if  ( null  !==  $unknownHost  &&  $unknownHost  ===  $safeHost )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $returnUrl  =  $unknownUrl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        // URL must not lead to weird pages
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $forbiddenWords  =  [ 'jscript' ,  'json' ,  'debug' ,  'serviceworker' ,  'offline' ,  'delete' ,  '/login' ,  '/attachments/view' ]; 
							 
						 
					
						
							
								
									
										
										
										
											2025-02-23 12:47:04 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( Str :: contains ( $returnUrl ,  $forbiddenWords ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 17:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  $safeUrl ; 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-29 14:59:58 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $returnUrl ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-06-17 22:49:44 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  negative ( string  $amount ) :  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-05 06:14:13 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ''  ===  $amount )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  '0' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2022-03-26 18:13:02 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $amount  =  $this -> floatalize ( $amount ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-11-15 12:25:49 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( 1  ===  bccomp ( $amount ,  '0' ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 17:06:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  bcmul ( $amount ,  '-1' ); 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-17 22:49:44 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $amount ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-18 20:25:30 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  opposite ( ? string  $amount  =  null ) :  ? string 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-20 21:04:25 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2018-04-02 14:50:17 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( null  ===  $amount )  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-03-24 14:05:29 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  null ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-26 19:28:35 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-10-23 19:11:25 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  bcmul ( $amount ,  '-1' ); 
							 
						 
					
						
							
								
									
										
										
										
											2017-06-20 21:04:25 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-15 10:00:08 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  phpBytes ( string  $string ) :  int 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-19 14:30:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-26 19:28:35 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $string  =  str_replace ([ 'kb' ,  'mb' ,  'gb' ],  [ 'k' ,  'm' ,  'g' ],  strtolower ( $string )); 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-19 14:30:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-10-24 16:59:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( false  !==  stripos ( $string ,  'k' ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-19 14:30:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // has a K in it, remove the K and multiply by 1024.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-26 19:28:35 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $bytes  =  bcmul ( rtrim ( $string ,  'k' ),  '1024' ); 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-19 14:30:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  ( int ) $bytes ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-19 14:30:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-10-24 16:59:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( false  !==  stripos ( $string ,  'm' ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-19 14:30:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // has a M in it, remove the M and multiply by 1048576.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-26 19:28:35 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $bytes  =  bcmul ( rtrim ( $string ,  'm' ),  '1048576' ); 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-19 14:30:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  ( int ) $bytes ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-19 14:30:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2020-10-24 16:59:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( false  !==  stripos ( $string ,  'g' ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-05 20:54:59 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            // has a G in it, remove the G and multiply by (1024)^3.
 
							 
						 
					
						
							
								
									
										
										
										
											2021-01-26 19:28:35 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $bytes  =  bcmul ( rtrim ( $string ,  'g' ),  '1073741824' ); 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-05 20:54:59 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  ( int ) $bytes ; 
							 
						 
					
						
							
								
									
										
										
										
											2016-08-05 20:54:59 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  ( int ) $string ; 
							 
						 
					
						
							
								
									
										
										
										
											2015-07-19 14:30:20 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2017-02-11 09:34:04 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    public  function  positive ( string  $amount ) :  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2021-04-05 06:14:13 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        if  ( ''  ===  $amount )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            return  '0' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-20 19:35:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-04 20:32:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        try  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-20 19:35:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( - 1  ===  bccomp ( $amount ,  '0' ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-05-04 20:32:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                $amount  =  bcmul ( $amount ,  '-1' ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-05-27 16:57:36 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        }  catch  ( ValueError  $e )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-29 09:01:42 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            Log :: error ( sprintf ( 'ValueError in Steam::positive("%s"): %s' ,  $amount ,  $e -> getMessage ())); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            Log :: error ( $e -> getTraceAsString ()); 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-20 19:35:52 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-05-04 20:32:51 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            return  '0' ; 
							 
						 
					
						
							
								
									
										
										
										
											2017-02-11 09:34:04 +01:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $amount ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    private  function  convertAllBalances ( array  $others ,  TransactionCurrency  $primary ,  Carbon  $date ) :  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $total      =  '0' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $converter  =  new  ExchangeRateConverter (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $singleton  =  PreferencesSingleton :: getInstance (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        foreach  ( $others  as  $key  =>  $amount )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $preference  =  $singleton -> getPreference ( $key ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            try  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $currency  =  $preference  ? ?  Amount :: getTransactionCurrencyByCode ( $key ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            }  catch  ( FireflyException )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                continue ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( null  ===  $preference )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $singleton -> setPreference ( $key ,  $currency ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $current     =  $amount ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( $currency -> id  !==  $primary -> id )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $current  =  $converter -> convert ( $currency ,  $primary ,  $date ,  $amount ); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                Log :: debug ( sprintf ( 'Convert %s %s to %s %s' ,  $currency -> code ,  $amount ,  $primary -> code ,  $current )); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $total       =  bcadd (( string ) $current ,  $total ); 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $total ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								    private  function  getCurrencies ( Collection  $accounts ) :  array 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-07 05:55:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $currencies                =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $accountCurrencies         =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $accountPreferences        =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $primary                   =  Amount :: getPrimaryCurrency (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $currencies [ $primary -> id ]  =  $primary ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $ids                       =  $accounts -> pluck ( 'id' ) -> toArray (); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $result                    =  AccountMeta :: whereIn ( 'account_id' ,  $ids ) -> where ( 'name' ,  'currency_id' ) -> get (); 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:39:55 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        /** @var AccountMeta $item */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        foreach  ( $result  as  $item )  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-07 05:52:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            $integer  =  ( int ) $item -> data ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( 0  !==  $integer )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $accountPreferences [( int ) $item -> account_id ]  =  $integer ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-07 05:55:15 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        // collect those currencies, skip primary because we already have it.
 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        $set                       =  TransactionCurrency :: whereIn ( 'id' ,  $accountPreferences ) -> where ( 'id' ,  '!=' ,  $primary -> id ) -> get (); 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        foreach  ( $set  as  $item )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $currencies [ $item -> id ]  =  $item ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        /** @var Account $account */ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        foreach  ( $accounts  as  $account )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $accountId        =  $account -> id ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $currencyPresent  =  isset ( $account -> meta )  &&  array_key_exists ( 'currency' ,  $account -> meta )  &&  null  !==  $account -> meta [ 'currency' ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            if  ( $currencyPresent )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $currencyId                     =  $account -> meta [ 'currency' ] -> id ; 
							 
						 
					
						
							
								
									
										
										
										
											2025-10-08 09:22:12 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                $currencies [ $currencyId ]  ? ? =  $account -> meta [ 'currency' ]; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                $accountCurrencies [ $accountId ]  =  $account -> meta [ 'currency' ]; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-07 05:52:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( ! $currencyPresent  &&  ! array_key_exists ( $accountId ,  $accountPreferences ))  { 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								                $accountCurrencies [ $accountId ]  =  $primary ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-07 05:52:56 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            if  ( ! $currencyPresent  &&  array_key_exists ( $accountId ,  $accountPreferences ))  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								                $accountCurrencies [ $accountId ]  =  $currencies [ $accountPreferences [ $account -> id ]]; 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								            } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:39:55 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2025-08-06 20:15:02 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								        return  $accountCurrencies ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2025-09-26 06:05:37 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    private  function  groupAndSumTransactions ( array  $array ,  string  $group ,  string  $field ) :  array 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        $return  =  []; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        foreach  ( $array  as  $item )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $groupKey           =  $item [ $group ]  ? ?  'unknown' ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								            $return [ $groupKey ]  =  bcadd ( $return [ $groupKey ]  ? ?  '0' ,  ( string ) $item [ $field ]); 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								        return  $return ; 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							 
							
							
								    } 
							 
						 
					
						
							
								
									
										
										
										
											2015-03-29 08:14:32 +02:00 
										
									 
								 
							 
							
								
									
										 
									 
								
							 
							
								 
							 
							
							
								}