mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	Compare commits
	
		
			136 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 50cf7f6a3b | ||
|  | eecb4db34c | ||
|  | 1f865d3ea4 | ||
|  | 623bb4b350 | ||
|  | dc8ad673a6 | ||
|  | 4914ad821e | ||
|  | f099cbadc3 | ||
|  | 42cda384c8 | ||
|  | 23c91b9990 | ||
|  | ff0379182e | ||
|  | e08a23948f | ||
|  | bd56de6d36 | ||
|  | 42970aea80 | ||
|  | 003a05ee8d | ||
|  | ffb11b01a6 | ||
|  | e426f5d5da | ||
|  | 6989f61e1b | ||
|  | 0e6677ccb3 | ||
|  | 8f104d555a | ||
|  | b1d3158db1 | ||
|  | 7645005d5a | ||
|  | 411f77fd29 | ||
|  | 568ab26db1 | ||
|  | 29652108f0 | ||
|  | f07e4dc711 | ||
|  | 8a2ac457c2 | ||
|  | 9e54eecfaa | ||
|  | 95ef691077 | ||
|  | 7a0ad5a587 | ||
|  | 42b49d0e4b | ||
|  | 9217c2f003 | ||
|  | fbdf66998d | ||
|  | deda9d3c54 | ||
|  | a5d78f20ae | ||
|  | 5ed09e3f38 | ||
|  | 3e9774cd66 | ||
|  | 54387c8fdf | ||
|  | 7eec949a13 | ||
|  | 4113c4ff40 | ||
|  | 1bf0968bfe | ||
|  | 374b90fb00 | ||
|  | 064e60e9d5 | ||
|  | b637455970 | ||
|  | 68158937d1 | ||
|  | adb1356b7a | ||
|  | d880ccb8e0 | ||
|  | 050fb1d1ef | ||
|  | 6580752bde | ||
|  | c9df265c9b | ||
|  | 098e5bc162 | ||
|  | 4b2dcc74d4 | ||
|  | a9254c5c9a | ||
|  | 7ce57e6ccb | ||
|  | 0fcb32a66f | ||
|  | 9946535f01 | ||
|  | 2b17396d6b | ||
|  | b01d5bc237 | ||
|  | b123860304 | ||
|  | 033f5b67db | ||
|  | 6280448dfb | ||
|  | 01cd3333e4 | ||
|  | 63050907b9 | ||
|  | beedf7d780 | ||
|  | 6b8194261f | ||
|  | dbb1c4d534 | ||
|  | e6263f9ff5 | ||
|  | 6ca119c4db | ||
|  | c483a1ab3a | ||
|  | 2e7edd033c | ||
|  | c576902501 | ||
|  | 66c2951594 | ||
|  | b812881cdb | ||
|  | cdeac2c6db | ||
|  | bca2ddd529 | ||
|  | e7285c6499 | ||
|  | bdff275672 | ||
|  | bec58a1ee6 | ||
|  | f64616748c | ||
|  | 512ce15973 | ||
|  | ed8b301574 | ||
|  | d22a6c019c | ||
|  | a0cb1b9d9e | ||
|  | a5294c62ea | ||
|  | e155d3311c | ||
|  | 0a372b0daf | ||
|  | 69143399d1 | ||
|  | 3270d3bf96 | ||
|  | 3896a66122 | ||
|  | b94781aef1 | ||
|  | bed1adc367 | ||
|  | ae54497efa | ||
|  | 06b747c221 | ||
|  | f159beee0d | ||
|  | 49d7dea086 | ||
|  | 3e65733dc5 | ||
|  | cc375d58bb | ||
|  | 911c7c662a | ||
|  | aae003be33 | ||
|  | aede03d8b2 | ||
|  | f0f5ada7de | ||
|  | 58365121a3 | ||
|  | d5a154d2e6 | ||
|  | b20f369aef | ||
|  | abb8aa0b29 | ||
|  | 5368a0f1d7 | ||
|  | d3897eece7 | ||
|  | a82b829da9 | ||
|  | 9f5058e81a | ||
|  | 5b19263720 | ||
|  | 9d5a0db0d9 | ||
|  | 4bd8a7014f | ||
|  | 353e96d951 | ||
|  | 149a6f92b0 | ||
|  | d66426c137 | ||
|  | 4fc9966392 | ||
|  | 417766f0db | ||
|  | de9ac97887 | ||
|  | 6be42f112a | ||
|  | 3895ae63c7 | ||
|  | 607d416d54 | ||
|  | 038693dc86 | ||
|  | cc9be13544 | ||
|  | 9c1474087f | ||
|  | 831de2bcf4 | ||
|  | eb687333bb | ||
|  | 5cc7966d54 | ||
|  | d1a34e7a6f | ||
|  | d63d791717 | ||
|  | 015570c741 | ||
|  | 8400ebc9c6 | ||
|  | 9f99e7c0af | ||
|  | 392c1fc399 | ||
|  | d3cea7a89c | ||
|  | 1dcf7407e6 | ||
|  | d543c033a3 | ||
|  | 2054b5b3dd | 
							
								
								
									
										27
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,5 +1,5 @@ | ||||
| # Firefly III | ||||
| #### v3.4.0.6 | ||||
| #### v3.4.0.8 | ||||
|  | ||||
| [](https://travis-ci.org/JC5/firefly-iii) | ||||
| [](http://stillmaintained.com/JC5/firefly-iii) | ||||
| @@ -34,20 +34,11 @@ and the philosophy behind it. | ||||
|  | ||||
| It's III, or 3, because [version 2](https://github.com/JC5/Firefly) and version 1 (not online) preceded it. It has been growing steadily ever since. | ||||
|  | ||||
| ## Running and installing | ||||
|  | ||||
| If you're still interested please read [the installation guide](https://github.com/JC5/firefly-iii/wiki/Installation),  | ||||
| [the upgrade guide](https://github.com/JC5/firefly-iii/wiki/Upgrade-instructions) (if applicable)  | ||||
| and the **[first use guide](https://github.com/JC5/firefly-iii/wiki/First-use)**. | ||||
|   | ||||
| If you want to try out Firefly III, you can do so on [this dedicated website](https://geld.nder.be/).  | ||||
| This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site. | ||||
|  | ||||
| ## Current features | ||||
|  | ||||
| - [A double-entry bookkeeping system](https://en.wikipedia.org/wiki/Double-entry_bookkeeping_system); | ||||
| - You can store, edit and remove [withdrawals, deposits and transfers](https://en.wikipedia.org/wiki/Financial_transaction). This allows you full financial management; | ||||
| - You can manage different types of accounts | ||||
| - You can manage different types of accounts; | ||||
|   - [Asset](https://en.wikipedia.org/wiki/Asset) accounts | ||||
|   - Shared [asset accounts](https://en.wikipedia.org/wiki/Asset) ([household accounts](https://en.wikipedia.org/wiki/Household)) | ||||
|   - Saving accounts | ||||
| @@ -65,8 +56,8 @@ Everything is organised: | ||||
| - Clear views that should show you how you're doing; | ||||
| - Easy navigation through your records; | ||||
| - Browse back and forth to see previous months or even years; | ||||
| - Lots of charts because we all love them. | ||||
| - Financial reporting showing you how well you are doing; | ||||
| - Lots of charts because we all love them; | ||||
| - Financial reporting showing you how well you are doing. | ||||
|  | ||||
| ## Screenshots | ||||
|  | ||||
| @@ -86,6 +77,16 @@ _Please note that everything in these screenshots is fictional and may not be re | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Running and installing | ||||
|  | ||||
| If you're still interested please read [the installation guide](https://github.com/JC5/firefly-iii/wiki/Installation),  | ||||
| [the upgrade guide](https://github.com/JC5/firefly-iii/wiki/Upgrade-instructions) (if applicable)  | ||||
| and the **[first use guide](https://github.com/JC5/firefly-iii/wiki/First-use)**. | ||||
|   | ||||
| If you want to try out Firefly III, you can do so on [this dedicated website](https://geld.nder.be/).  | ||||
| This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site. | ||||
|  | ||||
|  | ||||
| ## Current state | ||||
|  | ||||
| Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. One of the things on the todo-list | ||||
|   | ||||
| @@ -26,6 +26,8 @@ class Kernel extends ConsoleKernel | ||||
|      * | ||||
|      * @param  \Illuminate\Console\Scheduling\Schedule $schedule | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     protected function schedule(Schedule $schedule) | ||||
|   | ||||
| @@ -27,6 +27,7 @@ class Handler extends ExceptionHandler | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Exception               $e | ||||
|      * @SuppressWarnings(PHPMD.ShortVariable) | ||||
|      * | ||||
|      * @return \Illuminate\Http\Response | ||||
|      */ | ||||
| @@ -43,6 +44,7 @@ class Handler extends ExceptionHandler | ||||
|      * Report or log an exception. | ||||
|      * | ||||
|      * This is a great spot to send exceptions to Sentry, Bugsnag, etc. | ||||
|      * @SuppressWarnings(PHPMD.ShortVariable) | ||||
|      * | ||||
|      * @param  \Exception $e | ||||
|      * | ||||
|   | ||||
| @@ -6,7 +6,6 @@ use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class ConnectJournalToPiggyBank | ||||
| @@ -28,6 +27,8 @@ class ConnectJournalToPiggyBank | ||||
|     /** | ||||
|      * Handle the event when journal is saved. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * | ||||
|      * @param  JournalCreated $event | ||||
|      * | ||||
|      * @return boolean | ||||
| @@ -37,45 +38,25 @@ class ConnectJournalToPiggyBank | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         $journal     = $event->journal; | ||||
|         $piggyBankId = $event->piggyBankId; | ||||
|         if (intval($piggyBankId) < 1) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         Log::debug('JournalCreated event: ' . $journal->id . ', ' . $piggyBankId); | ||||
|  | ||||
|         /** @var PiggyBank $piggyBank */ | ||||
|         $piggyBank = Auth::user()->piggybanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']); | ||||
|  | ||||
|         if (is_null($piggyBank) || $journal->transactionType->type != 'Transfer') { | ||||
|             return false; | ||||
|         } | ||||
|         Log::debug('Found a piggy bank'); | ||||
|         $amount = $journal->amount; | ||||
|         Log::debug('Amount: ' . $amount); | ||||
|         if ($amount == 0) { | ||||
|         if (is_null($piggyBank)) { | ||||
|             return false; | ||||
|         } | ||||
|         // update piggy bank rep for date of transaction journal. | ||||
|         $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first(); | ||||
|         if (is_null($repetition)) { | ||||
|             Log::debug('Found no repetition for piggy bank for date ' . $journal->date->format('Y M d')); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         Log::debug('Found rep! ' . $repetition->id); | ||||
|  | ||||
|         /* | ||||
|          * Add amount when | ||||
|          */ | ||||
|         $amount = $journal->amount; | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($journal->transactions()->get() as $transaction) { | ||||
|             if ($transaction->account_id == $piggyBank->account_id) { | ||||
|                 if ($transaction->amount < 0) { | ||||
|                     $amount = $amount * -1; | ||||
|                     Log::debug('Transaction is away from piggy, so amount becomes ' . $amount); | ||||
|                 } else { | ||||
|                     Log::debug('Transaction is to from piggy, so amount stays ' . $amount); | ||||
|                     $amount = $transaction->amount * -1; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -83,14 +64,8 @@ class ConnectJournalToPiggyBank | ||||
|         $repetition->currentamount += $amount; | ||||
|         $repetition->save(); | ||||
|  | ||||
|         PiggyBankEvent::create( | ||||
|             [ | ||||
|                 'piggy_bank_id'          => $piggyBank->id, | ||||
|                 'transaction_journal_id' => $journal->id, | ||||
|                 'date'                   => $journal->date, | ||||
|                 'amount'                 => $amount | ||||
|             ] | ||||
|         ); | ||||
|         PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]); | ||||
|  | ||||
|         return true; | ||||
|  | ||||
|     } | ||||
|   | ||||
| @@ -1,36 +0,0 @@ | ||||
| <?php namespace FireflyIII\Handlers\Events; | ||||
|  | ||||
| use FireflyIII\Events\JournalDeleted; | ||||
|  | ||||
| /** | ||||
|  * Class JournalDeletedHandler | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Handlers\Events | ||||
|  */ | ||||
| class JournalDeletedHandler | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Create the event handler. | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Handle the event. | ||||
|      * | ||||
|      * @param  JournalDeleted $event | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function handle(JournalDeleted $event) | ||||
|     { | ||||
|         // | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| use FireflyIII\Events\JournalSaved; | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Models\PiggyBankRepetition; | ||||
|  | ||||
| /** | ||||
|  * Class UpdateJournalConnection | ||||
| @@ -39,7 +40,11 @@ class UpdateJournalConnection | ||||
|             return; | ||||
|         } | ||||
|         $piggyBank  = $event->piggyBank()->first(); | ||||
|         $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first(); | ||||
|         $repetition = null; | ||||
|         if ($piggyBank) { | ||||
|             /** @var PiggyBankRepetition $repetition */ | ||||
|             $repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first(); | ||||
|         } | ||||
|  | ||||
|         if (is_null($repetition)) { | ||||
|             return; | ||||
|   | ||||
							
								
								
									
										90
									
								
								app/Helpers/Collection/Account.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								app/Helpers/Collection/Account.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * Class Account | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Account | ||||
| { | ||||
|  | ||||
|     /** @var Collection */ | ||||
|     protected $accounts; | ||||
|     /** @var float */ | ||||
|     protected $difference; | ||||
|     /** @var float */ | ||||
|     protected $end; | ||||
|     /** @var float */ | ||||
|     protected $start; | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Support\Collection | ||||
|      */ | ||||
|     public function getAccounts() | ||||
|     { | ||||
|         return $this->accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param \Illuminate\Support\Collection $accounts | ||||
|      */ | ||||
|     public function setAccounts($accounts) | ||||
|     { | ||||
|         $this->accounts = $accounts; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getDifference() | ||||
|     { | ||||
|         return $this->difference; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $difference | ||||
|      */ | ||||
|     public function setDifference($difference) | ||||
|     { | ||||
|         $this->difference = $difference; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getEnd() | ||||
|     { | ||||
|         return $this->end; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $end | ||||
|      */ | ||||
|     public function setEnd($end) | ||||
|     { | ||||
|         $this->end = $end; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getStart() | ||||
|     { | ||||
|         return $this->start; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $start | ||||
|      */ | ||||
|     public function setStart($start) | ||||
|     { | ||||
|         $this->start = $start; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										64
									
								
								app/Helpers/Collection/Balance.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								app/Helpers/Collection/Balance.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class Balance | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Balance | ||||
| { | ||||
|  | ||||
|     /** @var  BalanceHeader */ | ||||
|     protected $balanceHeader; | ||||
|  | ||||
|     /** @var  Collection */ | ||||
|     protected $balanceLines; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->balanceLines = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BalanceLine $line | ||||
|      */ | ||||
|     public function addBalanceLine(BalanceLine $line) | ||||
|     { | ||||
|         $this->balanceLines->push($line); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return BalanceHeader | ||||
|      */ | ||||
|     public function getBalanceHeader() | ||||
|     { | ||||
|         return $this->balanceHeader; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BalanceHeader $balanceHeader | ||||
|      */ | ||||
|     public function setBalanceHeader($balanceHeader) | ||||
|     { | ||||
|         $this->balanceHeader = $balanceHeader; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Support\Collection | ||||
|      */ | ||||
|     public function getBalanceLines() | ||||
|     { | ||||
|         return $this->balanceLines; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										74
									
								
								app/Helpers/Collection/BalanceEntry.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								app/Helpers/Collection/BalanceEntry.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,74 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Account as AccountModel; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class BalanceEntry | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class BalanceEntry | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** @var  AccountModel */ | ||||
|     protected $account; | ||||
|     /** @var float */ | ||||
|     protected $left = 0.0; | ||||
|     /** @var float */ | ||||
|     protected $spent = 0.0; | ||||
|  | ||||
|     /** | ||||
|      * @return AccountModel | ||||
|      */ | ||||
|     public function getAccount() | ||||
|     { | ||||
|         return $this->account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountModel $account | ||||
|      */ | ||||
|     public function setAccount($account) | ||||
|     { | ||||
|         $this->account = $account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getLeft() | ||||
|     { | ||||
|         return $this->left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $left | ||||
|      */ | ||||
|     public function setLeft($left) | ||||
|     { | ||||
|         $this->left = $left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getSpent() | ||||
|     { | ||||
|         return $this->spent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $spent | ||||
|      */ | ||||
|     public function setSpent($spent) | ||||
|     { | ||||
|         $this->spent = $spent; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										46
									
								
								app/Helpers/Collection/BalanceHeader.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								app/Helpers/Collection/BalanceHeader.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Account as AccountModel; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class BalanceHeader | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class BalanceHeader | ||||
| { | ||||
|  | ||||
|     /** @var  Collection */ | ||||
|     protected $accounts; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->accounts = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountModel $account | ||||
|      */ | ||||
|     public function addAccount(AccountModel $account) | ||||
|     { | ||||
|         $this->accounts->push($account); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAccounts() | ||||
|     { | ||||
|         return $this->accounts; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										170
									
								
								app/Helpers/Collection/BalanceLine.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								app/Helpers/Collection/BalanceLine.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Budget as BudgetModel; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class BalanceLine | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class BalanceLine | ||||
| { | ||||
|  | ||||
|     const ROLE_DEFAULTROLE = 1; | ||||
|     const ROLE_TAGROLE     = 2; | ||||
|     const ROLE_DIFFROLE    = 3; | ||||
|  | ||||
|     /** @var  Collection */ | ||||
|     protected $balanceEntries; | ||||
|  | ||||
|     /** @var BudgetModel */ | ||||
|     protected $budget; | ||||
|  | ||||
|     /** @var  LimitRepetition */ | ||||
|     protected $repetition; | ||||
|  | ||||
|     protected $role = self::ROLE_DEFAULTROLE; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->balanceEntries = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BalanceEntry $balanceEntry | ||||
|      */ | ||||
|     public function addBalanceEntry(BalanceEntry $balanceEntry) | ||||
|     { | ||||
|         $this->balanceEntries->push($balanceEntry); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return string | ||||
|      */ | ||||
|     public function getTitle() | ||||
|     { | ||||
|         if ($this->getBudget() instanceof BudgetModel) { | ||||
|             return $this->getBudget()->name; | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_DEFAULTROLE) { | ||||
|             return trans('firefly.noBudget'); | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_TAGROLE) { | ||||
|             return trans('firefly.coveredWithTags'); | ||||
|         } | ||||
|         if ($this->getRole() == self::ROLE_DIFFROLE) { | ||||
|             return trans('firefly.leftUnbalanced'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return BudgetModel | ||||
|      */ | ||||
|     public function getBudget() | ||||
|     { | ||||
|         return $this->budget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BudgetModel $budget | ||||
|      */ | ||||
|     public function setBudget($budget) | ||||
|     { | ||||
|         $this->budget = $budget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return int | ||||
|      */ | ||||
|     public function getRole() | ||||
|     { | ||||
|         return $this->role; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param int $role | ||||
|      */ | ||||
|     public function setRole($role) | ||||
|     { | ||||
|         $this->role = $role; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * If a BalanceLine has a budget/repetition, each BalanceEntry in this BalanceLine | ||||
|      * should have a "spent" value, which is the amount of money that has been spent | ||||
|      * on the given budget/repetition. If you subtract all those amounts from the budget/repetition's | ||||
|      * total amount, this is returned: | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function leftOfRepetition() | ||||
|     { | ||||
|         $start = $this->getRepetition() ? $this->getRepetition()->amount : 0; | ||||
|         /** @var BalanceEntry $balanceEntry */ | ||||
|         foreach ($this->getBalanceEntries() as $balanceEntry) { | ||||
|             $start += $balanceEntry->getSpent(); | ||||
|         } | ||||
|  | ||||
|         return $start; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return LimitRepetition | ||||
|      */ | ||||
|     public function getRepetition() | ||||
|     { | ||||
|         return $this->repetition; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param LimitRepetition $repetition | ||||
|      */ | ||||
|     public function setRepetition($repetition) | ||||
|     { | ||||
|         $this->repetition = $repetition; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBalanceEntries() | ||||
|     { | ||||
|         return $this->balanceEntries; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Collection $balanceEntries | ||||
|      */ | ||||
|     public function setBalanceEntries($balanceEntries) | ||||
|     { | ||||
|         $this->balanceEntries = $balanceEntries; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * If the BalanceEntries for a BalanceLine have a "left" value, the amount | ||||
|      * of money left in the entire BalanceLine is returned here: | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function sumOfLeft() | ||||
|     { | ||||
|         $sum = 0.0; | ||||
|         /** @var BalanceEntry $balanceEntry */ | ||||
|         foreach ($this->getBalanceEntries() as $balanceEntry) { | ||||
|             $sum += $balanceEntry->getLeft(); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										57
									
								
								app/Helpers/Collection/Bill.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								app/Helpers/Collection/Bill.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Models\Bill as BillModel; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * Class Bill | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Bill | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @var Collection | ||||
|      */ | ||||
|     protected $bills; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->bills = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BillLine $bill | ||||
|      */ | ||||
|     public function addBill(BillLine $bill) | ||||
|     { | ||||
|         $this->bills->push($bill); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getBills() | ||||
|     { | ||||
|         $this->bills->sortBy( | ||||
|             function (BillLine $bill) { | ||||
|                 $active = intval($bill->getBill()->active) == 0 ? 1 : 0; | ||||
|                 $name   = $bill->getBill()->name; | ||||
|  | ||||
|                 return $active . $name; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         return $this->bills; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										127
									
								
								app/Helpers/Collection/BillLine.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								app/Helpers/Collection/BillLine.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,127 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Bill as BillModel; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class BillLine | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class BillLine | ||||
| { | ||||
|  | ||||
|     /** @var  bool */ | ||||
|     protected $active; | ||||
|     /** @var  float */ | ||||
|     protected $amount; | ||||
|     /** @var  BillModel */ | ||||
|     protected $bill; | ||||
|     /** @var  bool */ | ||||
|     protected $hit; | ||||
|     /** @var  float */ | ||||
|     protected $max; | ||||
|     /** @var  float */ | ||||
|     protected $min; | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getAmount() | ||||
|     { | ||||
|         return $this->amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $amount | ||||
|      */ | ||||
|     public function setAmount($amount) | ||||
|     { | ||||
|         $this->amount = $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return BillModel | ||||
|      */ | ||||
|     public function getBill() | ||||
|     { | ||||
|         return $this->bill; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BillModel $bill | ||||
|      */ | ||||
|     public function setBill($bill) | ||||
|     { | ||||
|         $this->bill = $bill; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getMax() | ||||
|     { | ||||
|         return $this->max; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $max | ||||
|      */ | ||||
|     public function setMax($max) | ||||
|     { | ||||
|         $this->max = $max; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getMin() | ||||
|     { | ||||
|         return $this->min; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $min | ||||
|      */ | ||||
|     public function setMin($min) | ||||
|     { | ||||
|         $this->min = $min; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function isActive() | ||||
|     { | ||||
|         return $this->active; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param boolean $active | ||||
|      */ | ||||
|     public function setActive($active) | ||||
|     { | ||||
|         $this->active = $active; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return boolean | ||||
|      */ | ||||
|     public function isHit() | ||||
|     { | ||||
|         return $this->hit; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param boolean $hit | ||||
|      */ | ||||
|     public function setHit($hit) | ||||
|     { | ||||
|         $this->hit = $hit; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										148
									
								
								app/Helpers/Collection/Budget.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								app/Helpers/Collection/Budget.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,148 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class Budget | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Budget | ||||
| { | ||||
|     /** @var  Collection */ | ||||
|     protected $budgetLines; | ||||
|     /** @var float */ | ||||
|     protected $budgeted = 0; | ||||
|     /** @var float */ | ||||
|     protected $left = 0; | ||||
|     /** @var float */ | ||||
|     protected $overspent = 0; | ||||
|     /** @var float */ | ||||
|     protected $spent = 0; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->budgetLines = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BudgetLine $budgetLine | ||||
|      */ | ||||
|     public function addBudgetLine(BudgetLine $budgetLine) | ||||
|     { | ||||
|         $this->budgetLines->push($budgetLine); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $add | ||||
|      */ | ||||
|     public function addBudgeted($add) | ||||
|     { | ||||
|         $this->budgeted += floatval($add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $add | ||||
|      */ | ||||
|     public function addLeft($add) | ||||
|     { | ||||
|         $this->left += floatval($add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $add | ||||
|      */ | ||||
|     public function addOverspent($add) | ||||
|     { | ||||
|         $this->overspent += floatval($add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $add | ||||
|      */ | ||||
|     public function addSpent($add) | ||||
|     { | ||||
|         $this->spent += floatval($add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Illuminate\Support\Collection | ||||
|      */ | ||||
|     public function getBudgetLines() | ||||
|     { | ||||
|         return $this->budgetLines; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getBudgeted() | ||||
|     { | ||||
|         return $this->budgeted; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $budgeted | ||||
|      */ | ||||
|     public function setBudgeted($budgeted) | ||||
|     { | ||||
|         $this->budgeted = $budgeted; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getLeft() | ||||
|     { | ||||
|         return $this->left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $left | ||||
|      */ | ||||
|     public function setLeft($left) | ||||
|     { | ||||
|         $this->left = $left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getOverspent() | ||||
|     { | ||||
|         return $this->overspent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $overspent | ||||
|      */ | ||||
|     public function setOverspent($overspent) | ||||
|     { | ||||
|         $this->overspent = $overspent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getSpent() | ||||
|     { | ||||
|         return $this->spent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $spent | ||||
|      */ | ||||
|     public function setSpent($spent) | ||||
|     { | ||||
|         $this->spent = $spent; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										130
									
								
								app/Helpers/Collection/BudgetLine.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								app/Helpers/Collection/BudgetLine.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,130 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Budget as BudgetModel; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class BudgetLine | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class BudgetLine | ||||
| { | ||||
|  | ||||
|     /** @var  BudgetModel */ | ||||
|     protected $budget; | ||||
|  | ||||
|     /** @var  LimitRepetition */ | ||||
|     protected $repetition; | ||||
|  | ||||
|     /** @var float */ | ||||
|     protected $budgeted = 0; | ||||
|     /** @var float */ | ||||
|     protected $left = 0; | ||||
|     /** @var float */ | ||||
|     protected $overspent = 0; | ||||
|     /** @var float */ | ||||
|     protected $spent = 0; | ||||
|  | ||||
|     /** | ||||
|      * @return BudgetModel | ||||
|      */ | ||||
|     public function getBudget() | ||||
|     { | ||||
|         return $this->budget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param BudgetModel $budget | ||||
|      */ | ||||
|     public function setBudget($budget) | ||||
|     { | ||||
|         $this->budget = $budget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getBudgeted() | ||||
|     { | ||||
|         return $this->budgeted; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $budgeted | ||||
|      */ | ||||
|     public function setBudgeted($budgeted) | ||||
|     { | ||||
|         $this->budgeted = $budgeted; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getLeft() | ||||
|     { | ||||
|         return $this->left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $left | ||||
|      */ | ||||
|     public function setLeft($left) | ||||
|     { | ||||
|         $this->left = $left; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getOverspent() | ||||
|     { | ||||
|         return $this->overspent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $overspent | ||||
|      */ | ||||
|     public function setOverspent($overspent) | ||||
|     { | ||||
|         $this->overspent = $overspent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getSpent() | ||||
|     { | ||||
|         return $this->spent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $spent | ||||
|      */ | ||||
|     public function setSpent($spent) | ||||
|     { | ||||
|         $this->spent = $spent; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return LimitRepetition | ||||
|      */ | ||||
|     public function getRepetition() | ||||
|     { | ||||
|         return $this->repetition; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param LimitRepetition $repetition | ||||
|      */ | ||||
|     public function setRepetition($repetition) | ||||
|     { | ||||
|         $this->repetition = $repetition; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										80
									
								
								app/Helpers/Collection/Category.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								app/Helpers/Collection/Category.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Created by PhpStorm. | ||||
|  * User: sander | ||||
|  * Date: 16/05/15 | ||||
|  * Time: 13:09 | ||||
|  */ | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\Category as CategoryModel; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class Category | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Category | ||||
| { | ||||
|  | ||||
|     /** @var  Collection */ | ||||
|     protected $categories; | ||||
|     /** @var float */ | ||||
|     protected $total = 0; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->categories = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param CategoryModel $category | ||||
|      */ | ||||
|     public function addCategory(CategoryModel $category) | ||||
|     { | ||||
|         if ($category->spent > 0) { | ||||
|             $this->categories->push($category); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param float $add | ||||
|      */ | ||||
|     public function addTotal($add) | ||||
|     { | ||||
|         $this->total += floatval($add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getCategories() | ||||
|     { | ||||
|         $this->categories->sortByDesc( | ||||
|             function (CategoryModel $category) { | ||||
|                 return $category->spent; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         return $this->categories; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getTotal() | ||||
|     { | ||||
|         return $this->total; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										82
									
								
								app/Helpers/Collection/Expense.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								app/Helpers/Collection/Expense.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
| use stdClass; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class Expense | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Expense | ||||
| { | ||||
|     /** @var Collection */ | ||||
|     protected $expenses; | ||||
|     /** @var float */ | ||||
|     protected $total; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->expenses = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $entry | ||||
|      */ | ||||
|     public function addOrCreateExpense(TransactionJournal $entry) | ||||
|     { | ||||
|  | ||||
|         $accountId = $entry->account_id; | ||||
|         if (!$this->expenses->has($accountId)) { | ||||
|             $newObject         = new stdClass; | ||||
|             $newObject->amount = floatval($entry->amount); | ||||
|             $newObject->name   = $entry->name; | ||||
|             $newObject->count  = 1; | ||||
|             $newObject->id     = $accountId; | ||||
|             $this->expenses->put($accountId, $newObject); | ||||
|         } else { | ||||
|             $existing = $this->expenses->get($accountId); | ||||
|             $existing->amount += floatval($entry->amount); | ||||
|             $existing->count++; | ||||
|             $this->expenses->put($accountId, $existing); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $add | ||||
|      */ | ||||
|     public function addToTotal($add) | ||||
|     { | ||||
|         $this->total += floatval($add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getExpenses() | ||||
|     { | ||||
|         $this->expenses->sortByDesc( | ||||
|             function (stdClass $object) { | ||||
|                 return $object->amount; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $this->expenses; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getTotal() | ||||
|     { | ||||
|         return $this->total; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										85
									
								
								app/Helpers/Collection/Income.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								app/Helpers/Collection/Income.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Helpers\Collection; | ||||
|  | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
| use stdClass; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * | ||||
|  * Class Income | ||||
|  * | ||||
|  * @package FireflyIII\Helpers\Collection | ||||
|  */ | ||||
| class Income | ||||
| { | ||||
|  | ||||
|     /** @var Collection */ | ||||
|     protected $incomes; | ||||
|     /** @var float */ | ||||
|     protected $total; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         $this->incomes = new Collection; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $entry | ||||
|      */ | ||||
|     public function addOrCreateIncome(TransactionJournal $entry) | ||||
|     { | ||||
|  | ||||
|         $accountId = $entry->account_id; | ||||
|         if (!$this->incomes->has($accountId)) { | ||||
|             $newObject         = new stdClass; | ||||
|             $newObject->amount = floatval($entry->amount); | ||||
|             $newObject->name   = $entry->name; | ||||
|             $newObject->count  = 1; | ||||
|             $newObject->id     = $accountId; | ||||
|             $this->incomes->put($accountId, $newObject); | ||||
|         } else { | ||||
|             $existing = $this->incomes->get($accountId); | ||||
|             $existing->amount += floatval($entry->amount); | ||||
|             $existing->count++; | ||||
|             $this->incomes->put($accountId, $existing); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $add | ||||
|      */ | ||||
|     public function addToTotal($add) | ||||
|     { | ||||
|         $this->total += floatval($add); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getIncomes() | ||||
|     { | ||||
|         $this->incomes->sortByDesc( | ||||
|             function (stdClass $object) { | ||||
|                 return $object->amount; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $this->incomes; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getTotal() | ||||
|     { | ||||
|         return $this->total; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -18,6 +18,7 @@ class Help implements HelpInterface | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $key | ||||
|      * | ||||
|      * @return string | ||||
| @@ -29,13 +30,14 @@ class Help implements HelpInterface | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getFromGithub($route) | ||||
|     { | ||||
|         $uri     = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md'; | ||||
|         $uri     = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/en/' . e($route) . '.md'; | ||||
|         $content = [ | ||||
|             'text'  => '<p>There is no help for this route!</p>', | ||||
|             'title' => $route, | ||||
| @@ -57,6 +59,7 @@ class Help implements HelpInterface | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return bool | ||||
| @@ -68,6 +71,7 @@ class Help implements HelpInterface | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param       $route | ||||
|      * @param array $content | ||||
|      * | ||||
| @@ -81,6 +85,7 @@ class Help implements HelpInterface | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $route | ||||
|      * | ||||
|      * @return bool | ||||
|   | ||||
| @@ -63,6 +63,30 @@ class ReminderHelper implements ReminderHelperInterface | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create all reminders for a piggy bank for a given date. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @param Carbon    $date | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function createReminders(PiggyBank $piggyBank, Carbon $date) | ||||
|     { | ||||
|         $ranges = $this->getReminderRanges($piggyBank); | ||||
|  | ||||
|         foreach ($ranges as $range) { | ||||
|             if ($date < $range['end'] && $date > $range['start']) { | ||||
|                 // create a reminder here! | ||||
|                 $this->createReminder($piggyBank, $range['start'], $range['end']); | ||||
|                 // stop looping, we're done. | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This routine will return an array consisting of two dates which indicate the start | ||||
|      * and end date for each reminder that this piggy bank will have, if the piggy bank has | ||||
|   | ||||
| @@ -4,6 +4,7 @@ namespace FireflyIII\Helpers\Reminders; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\PiggyBankRepetition; | ||||
| use FireflyIII\Models\Reminder; | ||||
|  | ||||
| /** | ||||
| @@ -49,4 +50,15 @@ interface ReminderHelperInterface | ||||
|      * @return Reminder | ||||
|      */ | ||||
|     public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Create all reminders for a piggy bank for a given date. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @param Carbon    $date | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function createReminders(PiggyBank $piggyBank, Carbon $date); | ||||
| } | ||||
|   | ||||
| @@ -3,12 +3,23 @@ | ||||
| namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use App; | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Collection\Account as AccountCollection; | ||||
| use FireflyIII\Helpers\Collection\Balance; | ||||
| use FireflyIII\Helpers\Collection\BalanceEntry; | ||||
| use FireflyIII\Helpers\Collection\BalanceHeader; | ||||
| use FireflyIII\Helpers\Collection\BalanceLine; | ||||
| use FireflyIII\Helpers\Collection\Bill as BillCollection; | ||||
| use FireflyIII\Helpers\Collection\BillLine; | ||||
| use FireflyIII\Helpers\Collection\Budget as BudgetCollection; | ||||
| use FireflyIII\Helpers\Collection\BudgetLine; | ||||
| use FireflyIII\Helpers\Collection\Category as CategoryCollection; | ||||
| use FireflyIII\Helpers\Collection\Expense; | ||||
| use FireflyIII\Helpers\Collection\Income; | ||||
| use FireflyIII\Models\Account; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Illuminate\Support\Collection; | ||||
| use Steam; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Budget as BudgetModel; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
|  | ||||
| /** | ||||
|  * Class ReportHelper | ||||
| @@ -18,47 +29,345 @@ use Steam; | ||||
| class ReportHelper implements ReportHelperInterface | ||||
| { | ||||
|  | ||||
|     /** @var ReportQueryInterface */ | ||||
|     protected $query; | ||||
|  | ||||
|     /** | ||||
|      * This method gets some kind of list for a monthly overview. | ||||
|      * @codeCoverageIgnore | ||||
|      * @param ReportQueryInterface $query | ||||
|      * | ||||
|      */ | ||||
|     public function __construct(ReportQueryInterface $query) | ||||
|     { | ||||
|         $this->query = $query; | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * This method generates a full report for the given period on all | ||||
|      * the users asset and cash accounts. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * @param bool   $showSharedReports | ||||
|      * @param Carbon $end | ||||
|      * @param        $shared | ||||
|      * | ||||
|      * @return Collection | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function getBudgetsForMonth(Carbon $date, $showSharedReports = false) | ||||
|     public function getAccountReport(Carbon $date, Carbon $end, $shared) | ||||
|     { | ||||
|         /** @var \FireflyIII\Helpers\Report\ReportQueryInterface $query */ | ||||
|         $query = App::make('FireflyIII\Helpers\Report\ReportQueryInterface'); | ||||
|  | ||||
|         $start = clone $date; | ||||
|         $start->startOfMonth(); | ||||
|         $end = clone $date; | ||||
|         $end->endOfMonth(); | ||||
|         $set = Auth::user()->budgets()->orderBy('budgets.name', 'ASC') | ||||
|                    ->leftJoin( | ||||
|                        'budget_limits', function (JoinClause $join) use ($date) { | ||||
|                        $join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d')); | ||||
|                    } | ||||
|                    ) | ||||
|                    ->get(['budgets.*', 'budget_limits.amount as queryAmount']); | ||||
|  | ||||
|         $budgets                   = Steam::makeArray($set); | ||||
|         $amountSet                 = $query->journalsByBudget($start, $end, $showSharedReports); | ||||
|         $amounts                   = Steam::makeArray($amountSet); | ||||
|         $budgets                   = Steam::mergeArrays($budgets, $amounts); | ||||
|         $budgets[0]['spent']       = isset($budgets[0]['spent']) ? $budgets[0]['spent'] : 0.0; | ||||
|         $budgets[0]['queryAmount'] = isset($budgets[0]['queryAmount']) ? $budgets[0]['queryAmount'] : 0.0; | ||||
|         $budgets[0]['name']        = 'No budget'; | ||||
|         $accounts = $this->query->getAllAccounts($date, $end, $shared); | ||||
|         $start    = 0; | ||||
|         $end      = 0; | ||||
|         $diff     = 0; | ||||
|  | ||||
|         // find transactions to shared asset accounts, which are without a budget by default: | ||||
|         // which is only relevant when shared asset accounts are hidden. | ||||
|         if ($showSharedReports === false) { | ||||
|             $transfers = $query->sharedExpenses($start, $end)->sum('queryAmount'); | ||||
|             $budgets[0]['spent'] += floatval($transfers) * -1; | ||||
|         // remove cash account, if any: | ||||
|         $accounts  =$accounts->filter(function(Account $account) { | ||||
|             if($account->accountType->type != 'Cash account') { | ||||
|                 return $account; | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         // summarize: | ||||
|         foreach ($accounts as $account) { | ||||
|             $start += $account->startBalance; | ||||
|             $end += $account->endBalance; | ||||
|             $diff += ($account->endBalance - $account->startBalance); | ||||
|         } | ||||
|  | ||||
|         return $budgets; | ||||
|         $object = new AccountCollection; | ||||
|         $object->setStart($start); | ||||
|         $object->setEnd($end); | ||||
|         $object->setDifference($diff); | ||||
|         $object->setAccounts($accounts); | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * The balance report contains a Balance object which in turn contains: | ||||
|      * | ||||
|      * A BalanceHeader object which contains all relevant user asset accounts for the report. | ||||
|      * | ||||
|      * A number of BalanceLine objects, which hold: | ||||
|      * - A budget | ||||
|      * - A number of BalanceEntry objects. | ||||
|      * | ||||
|      * The BalanceEntry object holds: | ||||
|      *   - The same budget (again) | ||||
|      *   - A user asset account as mentioned in the BalanceHeader | ||||
|      *   - The amount of money spent on the budget by the user asset account | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return Balance | ||||
|      */ | ||||
|     public function getBalanceReport(Carbon $start, Carbon $end, $shared) | ||||
|     { | ||||
|         $repository    = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|         $tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface'); | ||||
|         $balance       = new Balance; | ||||
|  | ||||
|         // build a balance header: | ||||
|         $header = new BalanceHeader; | ||||
|  | ||||
|         $accounts = $this->query->getAllAccounts($start, $end, $shared); | ||||
|         $budgets  = $repository->getBudgets(); | ||||
|         foreach ($accounts as $account) { | ||||
|             $header->addAccount($account); | ||||
|         } | ||||
|  | ||||
|         /** @var BudgetModel $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             $line = new BalanceLine; | ||||
|             $line->setBudget($budget); | ||||
|  | ||||
|             // get budget amount for current period: | ||||
|             $rep = $repository->getCurrentRepetition($budget, $start); | ||||
|             $line->setRepetition($rep); | ||||
|  | ||||
|             // loop accounts: | ||||
|             foreach ($accounts as $account) { | ||||
|                 $balanceEntry = new BalanceEntry; | ||||
|                 $balanceEntry->setAccount($account); | ||||
|  | ||||
|                 // get spent: | ||||
|                 $spent = $this->query->spentInBudgetCorrected($account, $budget, $start, $end); // I think shared is irrelevant. | ||||
|  | ||||
|                 $balanceEntry->setSpent($spent); | ||||
|                 $line->addBalanceEntry($balanceEntry); | ||||
|             } | ||||
|             // add line to balance: | ||||
|             $balance->addBalanceLine($line); | ||||
|         } | ||||
|  | ||||
|         // then a new line for without budget. | ||||
|         // and one for the tags: | ||||
|         $empty    = new BalanceLine; | ||||
|         $tags     = new BalanceLine; | ||||
|         $diffLine = new BalanceLine; | ||||
|  | ||||
|         $tags->setRole(BalanceLine::ROLE_TAGROLE); | ||||
|         $diffLine->setRole(BalanceLine::ROLE_DIFFROLE); | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             $spent = $this->query->spentNoBudget($account, $start, $end); | ||||
|             $left  = $tagRepository->coveredByBalancingActs($account, $start, $end); | ||||
|             $diff  = $spent + $left; | ||||
|  | ||||
|             // budget | ||||
|             $budgetEntry = new BalanceEntry; | ||||
|             $budgetEntry->setAccount($account); | ||||
|             $budgetEntry->setSpent($spent); | ||||
|             $empty->addBalanceEntry($budgetEntry); | ||||
|  | ||||
|             // balanced by tags | ||||
|             $tagEntry = new BalanceEntry; | ||||
|             $tagEntry->setAccount($account); | ||||
|             $tagEntry->setLeft($left); | ||||
|             $tags->addBalanceEntry($tagEntry); | ||||
|  | ||||
|             // difference: | ||||
|             $diffEntry = new BalanceEntry; | ||||
|             $diffEntry->setAccount($account); | ||||
|             $diffEntry->setSpent($diff); | ||||
|             $diffLine->addBalanceEntry($diffEntry); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         $balance->addBalanceLine($empty); | ||||
|         $balance->addBalanceLine($tags); | ||||
|         $balance->addBalanceLine($diffLine); | ||||
|  | ||||
|         $balance->setBalanceHeader($header); | ||||
|  | ||||
|         return $balance; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method generates a full report for the given period on all | ||||
|      * the users bills and their payments. | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return BillCollection | ||||
|      */ | ||||
|     public function getBillReport(Carbon $start, Carbon $end, $shared) | ||||
|     { | ||||
|         /** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */ | ||||
|         $repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface'); | ||||
|         $bills      = $repository->getBills(); | ||||
|         $collection = new BillCollection; | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $billLine = new BillLine; | ||||
|             $billLine->setBill($bill); | ||||
|             $billLine->setActive(intval($bill->active) == 1); | ||||
|             $billLine->setMin(floatval($bill->amount_min)); | ||||
|             $billLine->setMax(floatval($bill->amount_max)); | ||||
|  | ||||
|             // is hit in period? | ||||
|             $set = $repository->getJournalsInRange($bill, $start, $end); | ||||
|             if ($set->count() == 0) { | ||||
|                 $billLine->setHit(false); | ||||
|             } else { | ||||
|                 $billLine->setHit(true); | ||||
|                 $amount = 0; | ||||
|                 foreach ($set as $entry) { | ||||
|                     $amount += $entry->amount; | ||||
|                 } | ||||
|                 $billLine->setAmount($amount); | ||||
|             } | ||||
|  | ||||
|             $collection->addBill($billLine); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $collection; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return BudgetCollection | ||||
|      */ | ||||
|     public function getBudgetReport(Carbon $start, Carbon $end, $shared) | ||||
|     { | ||||
|         $object = new BudgetCollection; | ||||
|         /** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */ | ||||
|         $repository = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); | ||||
|         $set        = $repository->getBudgets(); | ||||
|  | ||||
|         foreach ($set as $budget) { | ||||
|  | ||||
|             $repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end); | ||||
|  | ||||
|             // no repetition(s) for this budget: | ||||
|             if ($repetitions->count() == 0) { | ||||
|                 $spent      = $repository->spentInPeriodCorrected($budget, $start, $end, $shared); | ||||
|                 $budgetLine = new BudgetLine; | ||||
|                 $budgetLine->setBudget($budget); | ||||
|                 $budgetLine->setOverspent($spent); | ||||
|                 $object->addOverspent($spent); | ||||
|                 $object->addBudgetLine($budgetLine); | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // one or more repetitions for budget: | ||||
|             /** @var LimitRepetition $repetition */ | ||||
|             foreach ($repetitions as $repetition) { | ||||
|                 $budgetLine = new BudgetLine; | ||||
|                 $budgetLine->setBudget($budget); | ||||
|                 $budgetLine->setRepetition($repetition); | ||||
|                 $expenses  = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, $shared); | ||||
|                 $left      = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0; | ||||
|                 $spent     = $expenses > floatval($repetition->amount) ? 0 : $expenses; | ||||
|                 $overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0; | ||||
|  | ||||
|                 $budgetLine->setLeft($left); | ||||
|                 $budgetLine->setSpent($spent); | ||||
|                 $budgetLine->setOverspent($overspent); | ||||
|                 $budgetLine->setBudgeted($repetition->amount); | ||||
|  | ||||
|                 $object->addBudgeted($repetition->amount); | ||||
|                 $object->addSpent($spent); | ||||
|                 $object->addLeft($left); | ||||
|                 $object->addOverspent($overspent); | ||||
|                 $object->addBudgetLine($budgetLine); | ||||
|  | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         // stuff outside of budgets: | ||||
|         $noBudget   = $repository->getWithoutBudgetSum($start, $end); | ||||
|         $budgetLine = new BudgetLine; | ||||
|         $budgetLine->setOverspent($noBudget); | ||||
|         $object->addOverspent($noBudget); | ||||
|         $object->addBudgetLine($budgetLine); | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return CategoryCollection | ||||
|      */ | ||||
|     public function getCategoryReport(Carbon $start, Carbon $end, $shared) | ||||
|     { | ||||
|         $object = new CategoryCollection; | ||||
|  | ||||
|  | ||||
|         /** | ||||
|          * GET CATEGORIES: | ||||
|          */ | ||||
|         /** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */ | ||||
|         $repository = App::make('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); | ||||
|         $set        = $repository->getCategories(); | ||||
|         foreach ($set as $category) { | ||||
|             $spent           = $repository->spentInPeriodCorrected($category, $start, $end, $shared); | ||||
|             $category->spent = $spent; | ||||
|             $object->addCategory($category); | ||||
|             $object->addTotal($spent); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a full report on the users expenses during the period. | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return Expense | ||||
|      */ | ||||
|     public function getExpenseReport($start, $end, $shared) | ||||
|     { | ||||
|         $object = new Expense; | ||||
|         $set    = $this->query->expenseInPeriodCorrected($start, $end, $shared); | ||||
|         foreach ($set as $entry) { | ||||
|             $object->addToTotal($entry->amount); | ||||
|             $object->addOrCreateExpense($entry); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a full report on the users incomes during the period. | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return Income | ||||
|      */ | ||||
|     public function getIncomeReport($start, $end, $shared) | ||||
|     { | ||||
|         $object = new Income; | ||||
|         $set    = $this->query->incomeInPeriodCorrected($start, $end, $shared); | ||||
|         foreach ($set as $entry) { | ||||
|             $object->addToTotal($entry->amount); | ||||
|             $object->addOrCreateIncome($entry); | ||||
|         } | ||||
|  | ||||
|         return $object; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -68,13 +377,14 @@ class ReportHelper implements ReportHelperInterface | ||||
|      */ | ||||
|     public function listOfMonths(Carbon $date) | ||||
|     { | ||||
|  | ||||
|         $start  = clone $date; | ||||
|         $end    = Carbon::now(); | ||||
|         $months = []; | ||||
|         while ($start <= $end) { | ||||
|             $year            = $start->year; | ||||
|             $months[$year][] = [ | ||||
|                 'formatted' => $start->format('F Y'), | ||||
|                 'formatted' => $start->formatLocalized('%B %Y'), | ||||
|                 'month'     => $start->month, | ||||
|                 'year'      => $year, | ||||
|             ]; | ||||
| @@ -83,77 +393,4 @@ class ReportHelper implements ReportHelperInterface | ||||
|  | ||||
|         return $months; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listOfYears(Carbon $date) | ||||
|     { | ||||
|         $start = clone $date; | ||||
|         $end   = Carbon::now(); | ||||
|         $years = []; | ||||
|         while ($start <= $end) { | ||||
|             $years[] = $start->year; | ||||
|             $start->addYear(); | ||||
|         } | ||||
|         $years[] = Carbon::now()->year; | ||||
|         // force the current year. | ||||
|         $years = array_unique($years); | ||||
|  | ||||
|         return $years; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearBalanceReport(Carbon $date, $showSharedReports = false) | ||||
|     { | ||||
|         $start          = clone $date; | ||||
|         $end            = clone $date; | ||||
|         $sharedAccounts = []; | ||||
|         if ($showSharedReports === false) { | ||||
|             $sharedCollection = Auth::user()->accounts() | ||||
|                                      ->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id') | ||||
|                                      ->where('account_meta.name', '=', 'accountRole') | ||||
|                                      ->where('account_meta.data', '=', json_encode('sharedAsset')) | ||||
|                                      ->get(['accounts.id']); | ||||
|  | ||||
|             foreach ($sharedCollection as $account) { | ||||
|                 $sharedAccounts[] = $account->id; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']) | ||||
|                         ->filter( | ||||
|                             function (Account $account) use ($sharedAccounts) { | ||||
|                                 if (!in_array($account->id, $sharedAccounts)) { | ||||
|                                     return $account; | ||||
|                                 } | ||||
|  | ||||
|                                 return null; | ||||
|                             } | ||||
|                         ); | ||||
|         $report   = []; | ||||
|         $start->startOfYear()->subDay(); | ||||
|         $end->endOfYear(); | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|             $startBalance = Steam::balance($account, $start); | ||||
|             $endBalance   = Steam::balance($account, $end); | ||||
|             $report[]     = [ | ||||
|                 'start'   => $startBalance, | ||||
|                 'end'     => $endBalance, | ||||
|                 'hide'    => ($startBalance == 0 && $endBalance == 0), | ||||
|                 'account' => $account, | ||||
|                 'shared'  => $account->accountRole == 'sharedAsset' | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $report; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -3,7 +3,12 @@ | ||||
| namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Illuminate\Support\Collection; | ||||
| use FireflyIII\Helpers\Collection\Account; | ||||
| use FireflyIII\Helpers\Collection\Balance; | ||||
| use FireflyIII\Helpers\Collection\Budget as BudgetCollection; | ||||
| use FireflyIII\Helpers\Collection\Category as CategoryCollection; | ||||
| use FireflyIII\Helpers\Collection\Expense; | ||||
| use FireflyIII\Helpers\Collection\Income; | ||||
|  | ||||
| /** | ||||
|  * Interface ReportHelperInterface | ||||
| @@ -14,13 +19,77 @@ interface ReportHelperInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * This method gets some kind of list for a monthly overview. | ||||
|      * This method generates a full report for the given period on all | ||||
|      * the users asset and cash accounts. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * @param Carbon  $date | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return Collection | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function getBudgetsForMonth(Carbon $date); | ||||
|     public function getAccountReport(Carbon $date, Carbon $end, $shared); | ||||
|  | ||||
|     /** | ||||
|      * This method generates a full report for the given period on all | ||||
|      * the users bills and their payments. | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function getBillReport(Carbon $start, Carbon $end, $shared); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return Balance | ||||
|      */ | ||||
|     public function getBalanceReport(Carbon $start, Carbon $end, $shared); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return BudgetCollection | ||||
|      */ | ||||
|     public function getBudgetReport(Carbon $start, Carbon $end, $shared); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return CategoryCollection | ||||
|      */ | ||||
|     public function getCategoryReport(Carbon $start, Carbon $end, $shared); | ||||
|  | ||||
|     /** | ||||
|      * Get a full report on the users expenses during the period. | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return Expense | ||||
|      */ | ||||
|     public function getExpenseReport($start, $end, $shared); | ||||
|  | ||||
|     /** | ||||
|      * Get a full report on the users incomes during the period. | ||||
|      * | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return Income | ||||
|      */ | ||||
|     public function getIncomeReport($start, $end, $shared); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
| @@ -29,18 +98,4 @@ interface ReportHelperInterface | ||||
|      */ | ||||
|     public function listOfMonths(Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function listOfYears(Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * @param Carbon $date | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function yearBalanceReport(Carbon $date, $showSharedReports = false); | ||||
| } | ||||
|   | ||||
| @@ -7,6 +7,7 @@ use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use DB; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Database\Eloquent\Builder; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| @@ -21,101 +22,62 @@ use Steam; | ||||
|  */ | ||||
| class ReportQuery implements ReportQueryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * This query retrieves a list of accounts that are active and not shared. | ||||
|      * See ReportQueryInterface::incomeInPeriodCorrected | ||||
|      * | ||||
|      * @param bool $showSharedReports | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $includeShared | ||||
|      * | ||||
|      * @return Collection | ||||
|      * | ||||
|      */ | ||||
|     public function accountList($showSharedReports = false) | ||||
|     public function expenseInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false) | ||||
|     { | ||||
|         $query = Auth::user()->accounts(); | ||||
|         if ($showSharedReports === false) { | ||||
|  | ||||
|             $query->leftJoin( | ||||
|                 'account_meta', function (JoinClause $join) { | ||||
|                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', "accountRole"); | ||||
|             } | ||||
|             )->where( | ||||
|         $query = $this->queryJournalsWithTransactions($start, $end); | ||||
|         if ($includeShared === false) { | ||||
|             $query->where( | ||||
|                 function (Builder $query) { | ||||
|                     $query->where('account_meta.data', '!=', '"sharedAsset"'); | ||||
|                     $query->orWhereNull('account_meta.data'); | ||||
|                     $query->where( | ||||
|                         function (Builder $q) { // only get withdrawals not from a shared account | ||||
|                             $q->where('transaction_types.type', 'Withdrawal'); | ||||
|                             $q->where('acm_from.data', '!=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                     $query->orWhere( | ||||
|                         function (Builder $q) { // and transfers from a shared account. | ||||
|                             $q->where('transaction_types.type', 'Transfer'); | ||||
|                             $q->where('acm_to.data', '=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|             ); | ||||
|  | ||||
|         } else { | ||||
|             $query->where('transaction_types.type', 'Withdrawal'); // any withdrawal is fine. | ||||
|         } | ||||
|         $query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') | ||||
|               ->whereIn('account_types.type', ['Default account', 'Cash account', 'Asset account']) | ||||
|               ->where('active', 1) | ||||
|               ->orderBy('accounts.name', 'ASC'); | ||||
|         $query->orderBy('transaction_journals.date'); | ||||
|  | ||||
|         return $query->get(['accounts.*']); | ||||
|     } | ||||
|         // get everything | ||||
|         $data = $query->get( | ||||
|             ['transaction_journals.*', 'transaction_types.type', 'ac_to.name as name', 'ac_to.id as account_id', 'ac_to.encrypted as account_encrypted'] | ||||
|         ); | ||||
|  | ||||
|     /** | ||||
|      * This method will get a list of all expenses in a certain time period that have no budget | ||||
|      * and are balanced by a transfer to make up for it. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $data->each( | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if (intval($journal->account_encrypted) == 1) { | ||||
|                     $journal->name = Crypt::decrypt($journal->name); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|         $data = $data->filter( | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if ($journal->amount != 0) { | ||||
|                     return $journal; | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         $set = TransactionJournal:: | ||||
|         leftJoin('transaction_group_transaction_journal', 'transaction_group_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transaction_group_transaction_journal as otherFromGroup', function (JoinClause $join) { | ||||
|                                      $join->on('otherFromGroup.transaction_group_id', '=', 'transaction_group_transaction_journal.transaction_group_id') | ||||
|                                           ->on('otherFromGroup.transaction_journal_id', '!=', 'transaction_journals.id'); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('transaction_journals as otherJournals', 'otherJournals.id', '=', 'otherFromGroup.transaction_journal_id') | ||||
|                                  ->leftJoin('transaction_types', 'transaction_types.id', '=', 'otherJournals.transaction_type_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', function (JoinClause $join) { | ||||
|                                      $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'otherJournals.id') | ||||
|                                  ->before($end)->after($start) | ||||
|                                  ->where('transaction_types.type', 'Withdrawal') | ||||
|                                  ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|                                  ->whereNull('budget_transaction_journal.budget_id')->whereNull('transaction_journals.deleted_at') | ||||
|                                  ->whereNull('otherJournals.deleted_at') | ||||
|                                  ->where('transactions.account_id', $account->id) | ||||
|                                  ->orderBy('transaction_journals.date', 'DESC') | ||||
|                                  ->orderBy('transaction_journals.order', 'ASC') | ||||
|                                  ->orderBy('transaction_journals.id', 'DESC') | ||||
|                                  ->whereNotNull('transaction_group_transaction_journal.transaction_group_id') | ||||
|                                  ->get( | ||||
|                                      [ | ||||
|                                          'transaction_journals.*', | ||||
|                                          'transactions.amount as queryAmount' | ||||
|                                      ] | ||||
|                                  ); | ||||
|  | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method will get the sum of all expenses in a certain time period that have no budget | ||||
|      * and are balanced by a transfer to make up for it. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return floatval($this->balancedTransactionsList($account, $start, $end)->sum('queryAmount')); | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -123,15 +85,15 @@ class ReportQuery implements ReportQueryInterface | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * @param bool   $includeShared | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAllAccounts(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = false) | ||||
|     { | ||||
|         $query = Auth::user()->accounts()->orderBy('accounts.name', 'ASC') | ||||
|                      ->accountTypeIn(['Default account', 'Asset account', 'Cash account']); | ||||
|         if ($showSharedReports === false) { | ||||
|         if ($includeShared === false) { | ||||
|             $query->leftJoin( | ||||
|                 'account_meta', function (JoinClause $join) { | ||||
|                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
| @@ -167,55 +129,27 @@ class ReportQuery implements ReportQueryInterface | ||||
|         return $set; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Grabs a summary of all expenses grouped by budget, related to the account. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function getBudgetSummary(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $query = $this->queryJournalsNoBudget($account, $start, $end); | ||||
|  | ||||
|         return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `queryAmount`')]); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get a list of transaction journals that have no budget, filtered for the specified account | ||||
|      * and the specified date range. | ||||
|      * This method works the same way as ReportQueryInterface::incomeInPeriod does, but instead of returning results | ||||
|      * will simply list the transaction journals only. This should allow any follow up counting to be accurate with | ||||
|      * regards to tags. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getTransactionsWithoutBudget(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $query = $this->queryJournalsNoBudget($account, $start, $end); | ||||
|  | ||||
|         return $query->get(['budgets.name', 'transactions.amount as queryAmount', 'transaction_journals.*']); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method returns all "income" journals in a certain period, which are both transfers from a shared account | ||||
|      * and "ordinary" deposits. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does | ||||
|      * not group and returns different fields. | ||||
|  | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * @param bool   $includeShared | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function incomeByPeriod(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     public function incomeInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false) | ||||
|     { | ||||
|         $query = $this->queryJournalsWithTransactions($start, $end); | ||||
|         if ($showSharedReports === false) { | ||||
|         if ($includeShared === false) { | ||||
|             // only get deposits not to a shared account | ||||
|             // and transfers to a shared account. | ||||
|             $query->where( | ||||
| @@ -238,219 +172,25 @@ class ReportQuery implements ReportQueryInterface | ||||
|             // any deposit is fine. | ||||
|             $query->where('transaction_types.type', 'Deposit'); | ||||
|         } | ||||
|         $query->groupBy('transaction_journals.id')->orderBy('transaction_journals.date'); | ||||
|         $query->orderBy('transaction_journals.date'); | ||||
|  | ||||
|         // get everything, decrypt and return | ||||
|         // get everything | ||||
|         $data = $query->get( | ||||
|             ['transaction_journals.id', | ||||
|              'transaction_journals.description', | ||||
|              'transaction_journals.encrypted', | ||||
|              'transaction_types.type', | ||||
|              DB::Raw('SUM(`t_to`.`amount`) as `queryAmount`'), | ||||
|              'transaction_journals.date', | ||||
|              't_from.account_id as account_id', | ||||
|              'ac_from.name as name', | ||||
|              'ac_from.encrypted as account_encrypted' | ||||
|             ] | ||||
|             ['transaction_journals.*', 'transaction_types.type', 'ac_from.name as name', 'ac_from.id as account_id', 'ac_from.encrypted as account_encrypted'] | ||||
|         ); | ||||
|  | ||||
|         $data->each( | ||||
|             function (Model $object) { | ||||
|                 $object->name = intval($object->account_encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of expenses grouped by the budget they were filed under. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByBudget(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     { | ||||
|         $query = Auth::user()->transactionjournals() | ||||
|                      ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                      ->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id') | ||||
|                      ->leftJoin( | ||||
|                          'transactions', function (JoinClause $join) { | ||||
|                          $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); | ||||
|                      } | ||||
|                      ) | ||||
|                      ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id'); | ||||
|         if ($showSharedReports === false) { | ||||
|  | ||||
|             $query->leftJoin( | ||||
|                 'account_meta', function (JoinClause $join) { | ||||
|                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|             } | ||||
|             )->where('account_meta.data', '!=', '"sharedAsset"'); | ||||
|         } | ||||
|         $query->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id') | ||||
|               ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|               ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|               ->where('transaction_types.type', 'Withdrawal') | ||||
|               ->groupBy('budgets.id') | ||||
|               ->orderBy('budgets.name', 'ASC'); | ||||
|  | ||||
|         return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) AS `spent`')]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of categories and the expenses therein, grouped by the relevant category. | ||||
|      * This result excludes transfers to shared accounts which are expenses, technically. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByCategory(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     { | ||||
|         $query = Auth::user()->transactionjournals() | ||||
|                      ->leftJoin( | ||||
|                          'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|                      ) | ||||
|                      ->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id') | ||||
|                      ->leftJoin( | ||||
|                          'transactions', function (JoinClause $join) { | ||||
|                          $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); | ||||
|                      } | ||||
|                      ) | ||||
|                      ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id'); | ||||
|         if ($showSharedReports === false) { | ||||
|             $query->leftJoin( | ||||
|                 'account_meta', function (JoinClause $join) { | ||||
|                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|             } | ||||
|             )->where('account_meta.data', '!=', '"sharedAsset"'); | ||||
|         } | ||||
|         $query->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id') | ||||
|               ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) | ||||
|               ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) | ||||
|               ->where('transaction_types.type', 'Withdrawal') | ||||
|               ->groupBy('categories.id') | ||||
|               ->orderBy('queryAmount'); | ||||
|  | ||||
|         $data = $query->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `queryAmount`')]); | ||||
|         // decrypt data: | ||||
|         $data->each( | ||||
|             function (Model $object) { | ||||
|                 $object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $data; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of expense accounts and the expenses therein, grouped by that expense account. | ||||
|      * This result excludes transfers to shared accounts which are expenses, technically. | ||||
|      * | ||||
|      * So now it will include them! | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByExpenseAccount(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     { | ||||
|         $query = $this->queryJournalsWithTransactions($start, $end); | ||||
|         if ($showSharedReports === false) { | ||||
|             // get all withdrawals not from a shared accounts | ||||
|             // and all transfers to a shared account | ||||
|             $query->where( | ||||
|                 function (Builder $query) { | ||||
|                     $query->where( | ||||
|                         function (Builder $q) { | ||||
|                             $q->where('transaction_types.type', 'Withdrawal'); | ||||
|                             $q->where('acm_from.data', '!=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                     $query->orWhere( | ||||
|                         function (Builder $q) { | ||||
|                             $q->where('transaction_types.type', 'Transfer'); | ||||
|                             $q->where('acm_to.data', '=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if (intval($journal->account_encrypted) == 1) { | ||||
|                     $journal->name = Crypt::decrypt($journal->name); | ||||
|                 } | ||||
|             ); | ||||
|         } else { | ||||
|             // any withdrawal goes: | ||||
|             $query->where('transaction_types.type', 'Withdrawal'); | ||||
|         } | ||||
|         $query->before($end)->after($start) | ||||
|               ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|               ->groupBy('t_to.account_id') | ||||
|               ->orderBy('queryAmount', 'DESC'); | ||||
|  | ||||
|         $data = $query->get(['t_to.account_id as id', 'ac_to.name as name', 'ac_to.encrypted', DB::Raw('SUM(t_to.amount) as `queryAmount`')]); | ||||
|  | ||||
|         // decrypt | ||||
|         $data->each( | ||||
|             function (Model $object) { | ||||
|                 $object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method returns all deposits into asset accounts, grouped by the revenue account, | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByRevenueAccount(Carbon $start, Carbon $end, $showSharedReports = false) | ||||
|     { | ||||
|         $query = $this->queryJournalsWithTransactions($start, $end); | ||||
|         if ($showSharedReports === false) { | ||||
|  | ||||
|             // show queries where transfer type is deposit, and its not to a shared account | ||||
|             // or where its a transfer and its from a shared account (both count as incomes) | ||||
|             $query->where( | ||||
|                 function (Builder $query) { | ||||
|                     $query->where( | ||||
|                         function (Builder $q) { | ||||
|                             $q->where('transaction_types.type', 'Deposit'); | ||||
|                             $q->where('acm_to.data', '!=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|                     $query->orWhere( | ||||
|                         function (Builder $q) { | ||||
|                             $q->where('transaction_types.type', 'Transfer'); | ||||
|                             $q->where('acm_from.data', '=', '"sharedAsset"'); | ||||
|                         } | ||||
|                     ); | ||||
|         $data = $data->filter( | ||||
|             function (TransactionJournal $journal) { | ||||
|                 if ($journal->amount != 0) { | ||||
|                     return $journal; | ||||
|                 } | ||||
|             ); | ||||
|         } else { | ||||
|             // any deposit goes: | ||||
|             $query->where('transaction_types.type', 'Deposit'); | ||||
|         } | ||||
|  | ||||
|         $query->groupBy('t_from.account_id')->orderBy('queryAmount'); | ||||
|  | ||||
|         $data = $query->get( | ||||
|             ['t_from.account_id as account_id', 'ac_from.name as name', 'ac_from.encrypted as encrypted', DB::Raw('SUM(t_from.amount) as `queryAmount`')] | ||||
|         ); | ||||
|         // decrypt | ||||
|         $data->each( | ||||
|             function (Model $object) { | ||||
|                 $object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
| @@ -458,119 +198,53 @@ class ReportQuery implements ReportQueryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * With an equally misleading name, this query returns are transfers to shared accounts. These are considered | ||||
|      * expenses. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function sharedExpenses(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return TransactionJournal:: | ||||
|         leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', function (JoinClause $join) { | ||||
|                                      $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where( | ||||
|                                          'transactions.amount', '>', 0 | ||||
|                                      ); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'account_meta', function (JoinClause $join) { | ||||
|                                      $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->where('account_meta.data', '"sharedAsset"') | ||||
|                                  ->after($start) | ||||
|                                  ->before($end) | ||||
|                                  ->where('transaction_types.type', 'Transfer') | ||||
|                                  ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|                                  ->get( | ||||
|                                      ['transaction_journals.id', 'transaction_journals.description', 'transactions.account_id', 'accounts.name', | ||||
|                                       'transactions.amount as queryAmount'] | ||||
|                                  ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * With a slightly misleading name, this query returns all transfers to shared accounts | ||||
|      * which are technically expenses, since it won't be just your money that gets spend. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function sharedExpensesByCategory(Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return TransactionJournal:: | ||||
|         leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', function (JoinClause $join) { | ||||
|                                      $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where( | ||||
|                                          'transactions.amount', '>', 0 | ||||
|                                      ); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'account_meta', function (JoinClause $join) { | ||||
|                                      $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin( | ||||
|                                      'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|                                  ) | ||||
|                                  ->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id') | ||||
|                                  ->where('account_meta.data', '"sharedAsset"') | ||||
|                                  ->after($start) | ||||
|                                  ->before($end) | ||||
|                                  ->where('transaction_types.type', 'Transfer') | ||||
|                                  ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|                                  ->groupBy('categories.name') | ||||
|                                  ->get( | ||||
|                                      [ | ||||
|                                          'categories.id', | ||||
|                                          'categories.name as name', | ||||
|                                          DB::Raw('SUM(`transactions`.`amount`) * -1 AS `queryAmount`') | ||||
|                                      ] | ||||
|                                  ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * This query will get all transaction journals and budget information for a specified account | ||||
|      * in a certain date range, where the transaction journal does not have a budget. | ||||
|      * There is no get() specified, this is up to the method itself. | ||||
|      * Covers tags | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Budget  $budget | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Builder | ||||
|      * @return float | ||||
|      */ | ||||
|     protected function queryJournalsNoBudget(Account $account, Carbon $start, Carbon $end) | ||||
|     public function spentInBudgetCorrected(Account $account, Budget $budget, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         return TransactionJournal:: | ||||
|         leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                                  ->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id') | ||||
|                                  ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', function (JoinClause $join) { | ||||
|                                      $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); | ||||
|                                  } | ||||
|                                  ) | ||||
|                                  ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|                                  ->before($end) | ||||
|                                  ->after($start) | ||||
|                                  ->where('accounts.id', $account->id) | ||||
|                                  ->where('transaction_journals.user_id', Auth::user()->id) | ||||
|                                  ->where('transaction_types.type', 'Withdrawal') | ||||
|                                  ->groupBy('budgets.id') | ||||
|                                  ->orderBy('budgets.name', 'ASC'); | ||||
|  | ||||
|         return floatval( | ||||
|                    Auth::user()->transactionjournals() | ||||
|                        ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                        ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                        ->transactionTypes(['Withdrawal']) | ||||
|                        ->where('transactions.account_id', $account->id) | ||||
|                        ->before($end) | ||||
|                        ->after($start) | ||||
|                        ->where('budget_transaction_journal.budget_id', $budget->id) | ||||
|                        ->get(['transaction_journals.*'])->sum('amount') | ||||
|                ) * -1; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param bool    $shared | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false) | ||||
|     { | ||||
|         return floatval( | ||||
|             Auth::user()->transactionjournals() | ||||
|                 ->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                 ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                 ->where('transactions.amount', '<', 0) | ||||
|                 ->transactionTypes(['Withdrawal']) | ||||
|                 ->where('transactions.account_id', $account->id) | ||||
|                 ->before($end) | ||||
|                 ->after($start) | ||||
|                 ->whereNull('budget_transaction_journal.budget_id') | ||||
|                 ->sum('transactions.amount') | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -609,5 +283,4 @@ class ReportQuery implements ReportQueryInterface | ||||
|  | ||||
|         return $query; | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -4,6 +4,7 @@ namespace FireflyIII\Helpers\Report; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Budget; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
| @@ -15,152 +16,66 @@ interface ReportQueryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * This query retrieves a list of accounts that are active and not shared. | ||||
|      * See ReportQueryInterface::incomeInPeriodCorrected | ||||
|      * | ||||
|      * @param bool $showSharedReports | ||||
|      * This method returns all "expense" journals in a certain period, which are both transfers to a shared account | ||||
|      * and "ordinary" withdrawals. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does | ||||
|      * not group and returns different fields. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $includeShared | ||||
|      * | ||||
|      * @return Collection | ||||
|      * | ||||
|      */ | ||||
|     public function accountList($showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * This method will get a list of all expenses in a certain time period that have no budget | ||||
|      * and are balanced by a transfer to make up for it. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * This method will get the sum of all expenses in a certain time period that have no budget | ||||
|      * and are balanced by a transfer to make up for it. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end); | ||||
|     public function expenseInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false); | ||||
|  | ||||
|     /** | ||||
|      * Get a users accounts combined with various meta-data related to the start and end date. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * @param bool   $includeShared | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getAllAccounts(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|     public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = false); | ||||
|  | ||||
|     /** | ||||
|      * Grabs a summary of all expenses grouped by budget, related to the account. | ||||
|      * This method works the same way as ReportQueryInterface::incomeInPeriod does, but instead of returning results | ||||
|      * will simply list the transaction journals only. This should allow any follow up counting to be accurate with | ||||
|      * regards to tags. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $includeShared | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function incomeInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false); | ||||
|  | ||||
|     /** | ||||
|      * Covers tags as well. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Budget  $budget | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getBudgetSummary(Account $account, Carbon $start, Carbon $end); | ||||
|     public function spentInBudgetCorrected(Account $account, Budget $budget, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Get a list of transaction journals that have no budget, filtered for the specified account | ||||
|      * and the specified date range. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param bool    $shared | ||||
|      * | ||||
|      * @return Collection | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getTransactionsWithoutBudget(Account $account, Carbon $start, Carbon $end); | ||||
|     public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false); | ||||
|  | ||||
|     /** | ||||
|      * This method returns all "income" journals in a certain period, which are both transfers from a shared account | ||||
|      * and "ordinary" deposits. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does | ||||
|      * not group and returns different fields. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function incomeByPeriod(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of expenses grouped by the budget they were filed under. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByBudget(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of categories and the expenses therein, grouped by the relevant category. | ||||
|      * This result excludes transfers to shared accounts which are expenses, technically. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByCategory(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * Gets a list of expense accounts and the expenses therein, grouped by that expense account. | ||||
|      * This result excludes transfers to shared accounts which are expenses, technically. | ||||
|      * | ||||
|      * So now it will include them! | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByExpenseAccount(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * This method returns all deposits into asset accounts, grouped by the revenue account, | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $showSharedReports | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function journalsByRevenueAccount(Carbon $start, Carbon $end, $showSharedReports = false); | ||||
|  | ||||
|     /** | ||||
|      * With an equally misleading name, this query returns are transfers to shared accounts. These are considered | ||||
|      * expenses. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function sharedExpenses(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * With a slightly misleading name, this query returns all transfers to shared accounts | ||||
|      * which are technically expenses, since it won't be just your money that gets spend. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function sharedExpensesByCategory(Carbon $start, Carbon $end); | ||||
| } | ||||
|   | ||||
| @@ -28,7 +28,7 @@ class AccountController extends Controller | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         View::share('mainTitleIcon', 'fa-credit-card'); | ||||
|         View::share('title', 'Accounts'); | ||||
|         View::share('title', trans('firefly.accounts')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -96,7 +96,7 @@ class AccountController extends Controller | ||||
|     { | ||||
|  | ||||
|         $what           = Config::get('firefly.shortNamesByFullName')[$account->accountType->type]; | ||||
|         $subTitle       = 'Edit ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; | ||||
|         $subTitle       = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]); | ||||
|         $subTitleIcon   = Config::get('firefly.subIconsByIdentifier.' . $what); | ||||
|         $openingBalance = $repository->openingBalanceTransaction($account); | ||||
|  | ||||
| @@ -137,7 +137,7 @@ class AccountController extends Controller | ||||
|      */ | ||||
|     public function index(AccountRepositoryInterface $repository, $what) | ||||
|     { | ||||
|         $subTitle     = Config::get('firefly.subTitlesByIdentifier.' . $what); | ||||
|         $subTitle     = trans('firefly.' . $what . '_accounts'); | ||||
|         $subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what); | ||||
|         $types        = Config::get('firefly.accountTypesByIdentifier.' . $what); | ||||
|         $accounts     = $repository->getAccounts($types); | ||||
| @@ -170,7 +170,7 @@ class AccountController extends Controller | ||||
|         $subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type); | ||||
|         $what         = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|         $journals     = $repository->getJournals($account, $page); | ||||
|         $subTitle     = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; | ||||
|         $subTitle     = trans('firefly.details_for_' . $what, ['name' => $account->name]); | ||||
|         $journals->setPath('accounts/show/' . $account->id); | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -38,6 +38,7 @@ class AuthController extends Controller | ||||
|      * | ||||
|      * @param  \Illuminate\Contracts\Auth\Guard     $auth | ||||
|      * @param  \Illuminate\Contracts\Auth\Registrar $registrar | ||||
|      * | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      */ | ||||
|   | ||||
| @@ -7,6 +7,7 @@ use Illuminate\Foundation\Auth\ResetsPasswords; | ||||
|  | ||||
| /** | ||||
|  * Class PasswordController | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @package FireflyIII\Http\Controllers\Auth | ||||
|  */ | ||||
|   | ||||
| @@ -7,7 +7,6 @@ use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use Input; | ||||
| use Redirect; | ||||
| @@ -29,54 +28,10 @@ class BillController extends Controller | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         View::share('title', 'Bills'); | ||||
|         View::share('title', trans('firefly.bills')); | ||||
|         View::share('mainTitleIcon', 'fa-calendar-o'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * @param Bill                       $bill | ||||
|      * | ||||
|      * @return \Illuminate\Http\RedirectResponse | ||||
|      */ | ||||
|     public function add(AccountRepositoryInterface $repository, Bill $bill) | ||||
|     { | ||||
|         $matches     = explode(',', $bill->match); | ||||
|         $description = []; | ||||
|         $expense     = null; | ||||
|  | ||||
|         // get users expense accounts: | ||||
|         $accounts = $repository->getAccounts(Config::get('firefly.accountTypesByIdentifier.expense')); | ||||
|  | ||||
|         foreach ($matches as $match) { | ||||
|             $match = strtolower($match); | ||||
|             // find expense account for each word if not found already: | ||||
|             if (is_null($expense)) { | ||||
|                 /** @var Account $account */ | ||||
|                 foreach ($accounts as $account) { | ||||
|                     $name = strtolower($account->name); | ||||
|                     if (!(strpos($name, $match) === false)) { | ||||
|                         $expense = $account; | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|  | ||||
|             } | ||||
|             if (is_null($expense)) { | ||||
|                 $description[] = $match; | ||||
|             } | ||||
|         } | ||||
|         $parameters = [ | ||||
|             'description'     => ucfirst(join(' ', $description)), | ||||
|             'expense_account' => is_null($expense) ? '' : $expense->name, | ||||
|             'amount'          => round(($bill->amount_min + $bill->amount_max), 2), | ||||
|         ]; | ||||
|         Session::put('preFilled', $parameters); | ||||
|  | ||||
|         return Redirect::to(route('transactions.create', 'withdrawal')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return $this | ||||
|      */ | ||||
|   | ||||
| @@ -29,7 +29,7 @@ class BudgetController extends Controller | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         View::share('title', 'Budgets'); | ||||
|         View::share('title', trans('firefly.budgets')); | ||||
|         View::share('mainTitleIcon', 'fa-tasks'); | ||||
|         View::share('hideBudgets', true); | ||||
|     } | ||||
| @@ -60,7 +60,7 @@ class BudgetController extends Controller | ||||
|             Session::put('budgets.create.url', URL::previous()); | ||||
|         } | ||||
|         Session::forget('budgets.create.fromStore'); | ||||
|         $subTitle = 'Create a new budget'; | ||||
|         $subTitle = trans('firefly.create_new_budget'); | ||||
|  | ||||
|         return view('budgets.create', compact('subTitle')); | ||||
|     } | ||||
| @@ -137,7 +137,8 @@ class BudgetController extends Controller | ||||
|         $budgets->each( | ||||
|             function (Budget $budget) use ($repository) { | ||||
|                 $date               = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|                 $budget->spent      = $repository->spentInMonth($budget, $date); | ||||
|                 $end                = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|                 $budget->spent      = $repository->spentInPeriodCorrected($budget, $date, $end); | ||||
|                 $budget->currentRep = $repository->getCurrentRepetition($budget, $date); | ||||
|             } | ||||
|         ); | ||||
|   | ||||
| @@ -26,7 +26,7 @@ class CategoryController extends Controller | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         View::share('title', 'Categories'); | ||||
|         View::share('title', trans('firefly.categories')); | ||||
|         View::share('mainTitleIcon', 'fa-bar-chart'); | ||||
|     } | ||||
|  | ||||
|   | ||||
							
								
								
									
										150
									
								
								app/Http/Controllers/Chart/AccountController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								app/Http/Controllers/Chart/AccountController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers\Chart; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class AccountController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers\Chart | ||||
|  */ | ||||
| class AccountController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Shows the balances for all the user's accounts. | ||||
|      * | ||||
|      * @param GChart                     $chart | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function all(GChart $chart, AccountRepositoryInterface $repository, $year, $month, $shared = false) | ||||
|     { | ||||
|         $start = new Carbon($year . '-' . $month . '-01'); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfMonth(); | ||||
|         $chart->addColumn(trans('firefly.dayOfMonth'), 'date'); | ||||
|  | ||||
|         /** @var Collection $accounts */ | ||||
|         $accounts = $repository->getAccounts(['Default account', 'Asset account']); | ||||
|         if ($shared === false) { | ||||
|             // remove the shared accounts from the collection: | ||||
|             /** @var Account $account */ | ||||
|             foreach ($accounts as $index => $account) { | ||||
|                 if ($account->getMeta('accountRole') == 'sharedAsset') { | ||||
|                     $accounts->forget($index); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $index = 1; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number'); | ||||
|             $chart->addCertainty($index); | ||||
|             $index++; | ||||
|         } | ||||
|         $current = clone $start; | ||||
|         $current->subDay(); | ||||
|         $today = Carbon::now(); | ||||
|         while ($end >= $current) { | ||||
|             $row     = [clone $current]; | ||||
|             $certain = $current < $today; | ||||
|             foreach ($accounts as $account) { | ||||
|                 $row[] = Steam::balance($account, $current); | ||||
|                 $row[] = $certain; | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the balances for all the user's frontpage accounts. | ||||
|      * | ||||
|      * @param GChart                     $chart | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(GChart $chart, AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.dayOfMonth'), 'date'); | ||||
|  | ||||
|         $frontPage = Preferences::get('frontPageAccounts', []); | ||||
|         $start     = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end       = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $accounts  = $repository->getFrontpageAccounts($frontPage); | ||||
|  | ||||
|         $index = 1; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number'); | ||||
|             $chart->addCertainty($index); | ||||
|             $index++; | ||||
|         } | ||||
|         $current = clone $start; | ||||
|         $current->subDay(); | ||||
|         $today = Carbon::now(); | ||||
|         while ($end >= $current) { | ||||
|             $row     = [clone $current]; | ||||
|             $certain = $current < $today; | ||||
|             foreach ($accounts as $account) { | ||||
|                 $row[] = Steam::balance($account, $current); | ||||
|                 $row[] = $certain; | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows an account's balance for a single month. | ||||
|      * | ||||
|      * @param GChart  $chart | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function single(GChart $chart, Account $account) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.dayOfMonth'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number'); | ||||
|         $chart->addCertainty(1); | ||||
|  | ||||
|         $start   = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end     = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $current = clone $start; | ||||
|         $today   = new Carbon; | ||||
|  | ||||
|         while ($end >= $current) { | ||||
|             $certain = $current < $today; | ||||
|             $chart->addRow(clone $current, Steam::balance($account, $current), $certain); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										141
									
								
								app/Http/Controllers/Chart/BillController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										141
									
								
								app/Http/Controllers/Chart/BillController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,141 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers\Chart; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
| use Response; | ||||
| use Session; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class BillController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers\Chart | ||||
|  */ | ||||
| class BillController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Shows the overview for a bill. The min/max amount and matched journals. | ||||
|      * | ||||
|      * @param GChart                  $chart | ||||
|      * @param BillRepositoryInterface $repository | ||||
|      * @param Bill                    $bill | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function single(GChart $chart, BillRepositoryInterface $repository, Bill $bill) | ||||
|     { | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.date'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.maxAmount'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.minAmount'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.billEntry'), 'number'); | ||||
|  | ||||
|         // get first transaction or today for start: | ||||
|         $results = $repository->getJournals($bill); | ||||
|         /** @var TransactionJournal $result */ | ||||
|         foreach ($results as $result) { | ||||
|             $chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount)); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows all bills and whether or not theyve been paid this month (pie chart). | ||||
|      * | ||||
|      * @param GChart                     $chart | ||||
|      * | ||||
|      * @param BillRepositoryInterface    $repository | ||||
|      * @param AccountRepositoryInterface $accounts | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.name'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.amount'), 'number'); | ||||
|  | ||||
|         $start  = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end    = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $bills  = $repository->getActiveBills(); | ||||
|         $paid   = new Collection; // journals. | ||||
|         $unpaid = new Collection; // bills | ||||
|         // loop paid and create single entry: | ||||
|         $paidDescriptions   = []; | ||||
|         $paidAmount         = 0; | ||||
|         $unpaidDescriptions = []; | ||||
|         $unpaidAmount       = 0; | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $ranges = $repository->getRanges($bill, $start, $end); | ||||
|  | ||||
|             foreach ($ranges as $range) { | ||||
|                 // paid a bill in this range? | ||||
|                 $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); | ||||
|                 if ($journals->count() == 0) { | ||||
|                     $unpaid->push([$bill, $range['start']]); | ||||
|                 } else { | ||||
|                     $paid = $paid->merge($journals); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $creditCards = $accounts->getCreditCards(); | ||||
|         foreach ($creditCards as $creditCard) { | ||||
|             $balance = Steam::balance($creditCard, $end, true); | ||||
|             $date    = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate')); | ||||
|             if ($balance < 0) { | ||||
|                 // unpaid! create a fake bill that matches the amount. | ||||
|                 $description = $creditCard->name; | ||||
|                 $amount      = $balance * -1; | ||||
|                 $fakeBill    = $repository->createFakeBill($description, $date, $amount); | ||||
|                 unset($description, $amount); | ||||
|                 $unpaid->push([$fakeBill, $date]); | ||||
|             } | ||||
|             if ($balance == 0) { | ||||
|                 // find transfer(s) TO the credit card which should account for | ||||
|                 // anything paid. If not, the CC is not yet used. | ||||
|                 $journals = $accounts->getTransfersInRange($creditCard, $start, $end); | ||||
|                 $paid     = $paid->merge($journals); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         /** @var TransactionJournal $entry */ | ||||
|         foreach ($paid as $entry) { | ||||
|  | ||||
|             $paidDescriptions[] = $entry->description; | ||||
|             $paidAmount += floatval($entry->amount); | ||||
|         } | ||||
|  | ||||
|         // loop unpaid: | ||||
|         /** @var Bill $entry */ | ||||
|         foreach ($unpaid as $entry) { | ||||
|             $description          = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; | ||||
|             $amount               = ($entry[0]->amount_max + $entry[0]->amount_min) / 2; | ||||
|             $unpaidDescriptions[] = $description; | ||||
|             $unpaidAmount += $amount; | ||||
|             unset($amount, $description); | ||||
|         } | ||||
|  | ||||
|         $chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount); | ||||
|         $chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount); | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										195
									
								
								app/Http/Controllers/Chart/BudgetController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								app/Http/Controllers/Chart/BudgetController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,195 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers\Chart; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers\Chart | ||||
|  */ | ||||
| class BudgetController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param Budget                    $budget | ||||
|      */ | ||||
|     public function budget(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.period'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|  | ||||
|  | ||||
|         $first = $repository->getFirstBudgetLimitDate($budget); | ||||
|         $range = $viewRange = Preferences::get('viewRange', '1M')->data; | ||||
|         $last  = Session::get('end', new Carbon); | ||||
|         $final = clone $last; | ||||
|         $final->addYears(2); | ||||
|         $last = Navigation::endOfX($last, $range, $final); | ||||
|  | ||||
|         while ($first < $last) { | ||||
|             $end = Navigation::addPeriod($first, $range, 0); | ||||
|  | ||||
|             $spent = $repository->spentInPeriodCorrected($budget, $first, $end); | ||||
|             $chart->addRow($end, $spent); | ||||
|  | ||||
|  | ||||
|             $first = Navigation::addPeriod($first, $range, 0); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows the amount left in a specific budget limit. | ||||
|      * | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param Budget                    $budget | ||||
|      * @param LimitRepetition           $repetition | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function budgetLimit(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition) | ||||
|     { | ||||
|         $start = clone $repetition->startdate; | ||||
|         $end   = $repetition->enddate; | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.day'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.left'), 'number'); | ||||
|  | ||||
|  | ||||
|         $amount = $repetition->amount; | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             /* | ||||
|              * Sum of expenses on this day: | ||||
|              */ | ||||
|             $sum = $repository->expensesOnDayCorrected($budget, $start); | ||||
|             $amount += $sum; | ||||
|             $chart->addRow(clone $start, $amount); | ||||
|             $start->addDay(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Shows a budget list with spent/left/overspent. | ||||
|      * | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(GChart $chart, BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.budget'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.left'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.overspent'), 'number'); | ||||
|  | ||||
|         $budgets    = $repository->getBudgets(); | ||||
|         $start      = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end        = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $allEntries = new Collection; | ||||
|  | ||||
|         foreach ($budgets as $budget) { | ||||
|             $repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end); | ||||
|             if ($repetitions->count() == 0) { | ||||
|                 $expenses = $repository->spentInPeriodCorrected($budget, $start, $end, true); | ||||
|                 $allEntries->push([$budget->name, 0, 0, $expenses]); | ||||
|                 continue; | ||||
|             } | ||||
|             /** @var LimitRepetition $repetition */ | ||||
|             foreach ($repetitions as $repetition) { | ||||
|                 $expenses  = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true); | ||||
|                 $left      = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0; | ||||
|                 $spent     = $expenses > floatval($repetition->amount) ? floatval($repetition->amount) : $expenses; | ||||
|                 $overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0; | ||||
|                 $allEntries->push( | ||||
|                     [$budget->name . ' (' . $repetition->startdate->formatLocalized($this->monthAndDayFormat) . ')', | ||||
|                      $left, | ||||
|                      $spent, | ||||
|                      $overspent | ||||
|                     ] | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end); | ||||
|         $allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses]); | ||||
|  | ||||
|         foreach ($allEntries as $entry) { | ||||
|             if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) { | ||||
|                 $chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a yearly overview for a budget. | ||||
|      * | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param                           $year | ||||
|      * @param bool                      $shared | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function year(GChart $chart, BudgetRepositoryInterface $repository, $year, $shared = false) | ||||
|     { | ||||
|         $start   = new Carbon($year . '-01-01'); | ||||
|         $end     = new Carbon($year . '-12-31'); | ||||
|         $shared  = $shared == 'shared' ? true : false; | ||||
|         $budgets = $repository->getBudgets(); | ||||
|  | ||||
|         // add columns: | ||||
|         $chart->addColumn(trans('firefly.month'), 'date'); | ||||
|         foreach ($budgets as $budget) { | ||||
|             $chart->addColumn($budget->name, 'number'); | ||||
|         } | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             // month is the current end of the period: | ||||
|             $month = clone $start; | ||||
|             $month->endOfMonth(); | ||||
|             // make a row: | ||||
|             $row = [clone $start]; | ||||
|  | ||||
|             // each budget, fill the row: | ||||
|             foreach ($budgets as $budget) { | ||||
|                 $spent = $repository->spentInPeriodCorrected($budget, $start, $month, $shared); | ||||
|                 $row[] = $spent; | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|  | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										180
									
								
								app/Http/Controllers/Chart/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								app/Http/Controllers/Chart/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers\Chart; | ||||
|  | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers\Chart | ||||
|  */ | ||||
| class CategoryController extends Controller | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Show an overview for a category for all time, per month/week/year. | ||||
|      * | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function all(GChart $chart, CategoryRepositoryInterface $repository, Category $category) | ||||
|     { | ||||
|         // oldest transaction in category: | ||||
|         $start = $repository->getFirstActivityDate($category); | ||||
|         $range = Preferences::get('viewRange', '1M')->data; | ||||
|         // jump to start of week / month / year / etc | ||||
|         $start = Navigation::startOfPeriod($start, $range); | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.period'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|  | ||||
|  | ||||
|         $end = new Carbon; | ||||
|         while ($start <= $end) { | ||||
|  | ||||
|             $currentEnd = Navigation::endOfPeriod($start, $range); | ||||
|             $spent      = $repository->spentInPeriodCorrected($category, $start, $currentEnd); | ||||
|             $chart->addRow(clone $start, $spent); | ||||
|  | ||||
|             $start = Navigation::addPeriod($start, $range, 0); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show this month's category overview. | ||||
|      * | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function frontpage(GChart $chart, CategoryRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.category'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|  | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $set   = $repository->getCategoriesAndExpensesCorrected($start, $end); | ||||
|  | ||||
|         // sort by callback: | ||||
|         uasort( | ||||
|             $set, | ||||
|             function ($left, $right) { | ||||
|                 if ($left['sum'] == $right['sum']) { | ||||
|                     return 0; | ||||
|                 } | ||||
|  | ||||
|                 return ($left['sum'] < $right['sum']) ? 1 : -1; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $sum = floatval($entry['sum']); | ||||
|             if ($sum != 0) { | ||||
|                 $chart->addRow($entry['name'], $sum); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function month(GChart $chart, CategoryRepositoryInterface $repository, Category $category) | ||||
|     { | ||||
|         $start = clone Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.period'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.spent'), 'number'); | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             $spent = $repository->spentOnDaySumCorrected($category, $start); | ||||
|             $chart->addRow(clone $start, $spent); | ||||
|             $start->addDay(); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This chart will only show expenses. | ||||
|      * | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param                             $year | ||||
|      * @param bool                        $shared | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function year(GChart $chart, CategoryRepositoryInterface $repository, $year, $shared = false) | ||||
|     { | ||||
|         $start      = new Carbon($year . '-01-01'); | ||||
|         $end        = new Carbon($year . '-12-31'); | ||||
|         $shared     = $shared == 'shared' ? true : false; | ||||
|         $categories = $repository->getCategories(); | ||||
|  | ||||
|         // add columns: | ||||
|         $chart->addColumn(trans('firefly.month'), 'date'); | ||||
|         foreach ($categories as $category) { | ||||
|             $chart->addColumn($category->name, 'number'); | ||||
|         } | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             // month is the current end of the period: | ||||
|             $month = clone $start; | ||||
|             $month->endOfMonth(); | ||||
|             // make a row: | ||||
|             $row = [clone $start]; | ||||
|  | ||||
|             // each budget, fill the row: | ||||
|             foreach ($categories as $category) { | ||||
|                 $spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared); | ||||
|                 $row[] = $spent; | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|  | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										58
									
								
								app/Http/Controllers/Chart/PiggyBankController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								app/Http/Controllers/Chart/PiggyBankController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Created by PhpStorm. | ||||
|  * User: sander | ||||
|  * Date: 16/05/15 | ||||
|  * Time: 09:36 | ||||
|  */ | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers\Chart; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
| use Response; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers\Chart | ||||
|  */ | ||||
| class PiggyBankController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Shows the piggy bank history. | ||||
|      * | ||||
|      * @param GChart                       $chart | ||||
|      * @param PiggyBankRepositoryInterface $repository | ||||
|      * @param PiggyBank                    $piggyBank | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function history(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank) | ||||
|     { | ||||
|         $chart->addColumn(trans('firefly.date'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.balance'), 'number'); | ||||
|  | ||||
|         /** @var Collection $set */ | ||||
|         $set = $repository->getEventSummarySet($piggyBank); | ||||
|         $sum = 0; | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $sum += floatval($entry->sum); | ||||
|             $chart->addRow(new Carbon($entry->date), $sum); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										101
									
								
								app/Http/Controllers/Chart/ReportController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								app/Http/Controllers/Chart/ReportController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Http\Controllers\Chart; | ||||
|  | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Report\ReportQueryInterface; | ||||
| use FireflyIII\Http\Controllers\Controller; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Response; | ||||
|  | ||||
| /** | ||||
|  * Class ReportController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers\Chart | ||||
|  */ | ||||
| class ReportController extends Controller | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Summarizes all income and expenses, per month, for a given year. | ||||
|      * | ||||
|      * @param GChart               $chart | ||||
|      * @param ReportQueryInterface $query | ||||
|      * @param                      $year | ||||
|      * @param bool                 $shared | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function yearInOut(GChart $chart, ReportQueryInterface $query, $year, $shared = false) | ||||
|     { | ||||
|         // get start and end of year | ||||
|         $start  = new Carbon($year . '-01-01'); | ||||
|         $end    = new Carbon($year . '-12-31'); | ||||
|         $shared = $shared == 'shared' ? true : false; | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.month'), 'date'); | ||||
|         $chart->addColumn(trans('firefly.income'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.expenses'), 'number'); | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             $month = clone $start; | ||||
|             $month->endOfMonth(); | ||||
|             // total income and total expenses: | ||||
|             $incomeSum  = floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $expenseSum = floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|  | ||||
|             $chart->addRow(clone $start, $incomeSum, $expenseSum); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Summarizes all income and expenses for a given year. Gives a total and an average. | ||||
|      * | ||||
|      * @param GChart               $chart | ||||
|      * @param ReportQueryInterface $query | ||||
|      * @param                      $year | ||||
|      * @param bool                 $shared | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function yearInOutSummarized(GChart $chart, ReportQueryInterface $query, $year, $shared = false) | ||||
|     { | ||||
|         $start   = new Carbon($year . '-01-01'); | ||||
|         $end     = new Carbon($year . '-12-31'); | ||||
|         $shared  = $shared == 'shared' ? true : false; | ||||
|         $income  = 0; | ||||
|         $expense = 0; | ||||
|         $count   = 0; | ||||
|  | ||||
|         $chart->addColumn(trans('firefly.summary'), 'string'); | ||||
|         $chart->addColumn(trans('firefly.income'), 'number'); | ||||
|         $chart->addColumn(trans('firefly.expenses'), 'number'); | ||||
|  | ||||
|         while ($start < $end) { | ||||
|             $month = clone $start; | ||||
|             $month->endOfMonth(); | ||||
|             // total income and total expenses: | ||||
|             $income += floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $expense += floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount')); | ||||
|             $count++; | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         // add total + average: | ||||
|         $chart->addRow(trans('firefly.sum'), $income, $expense); | ||||
|         $count = $count > 0 ? $count : 1; | ||||
|         $chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count)); | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
| } | ||||
| @@ -1,8 +1,11 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Auth; | ||||
| use Config; | ||||
| use Illuminate\Foundation\Bus\DispatchesCommands; | ||||
| use Illuminate\Foundation\Validation\ValidatesRequests; | ||||
| use Illuminate\Routing\Controller as BaseController; | ||||
| use Preferences; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
| @@ -15,6 +18,11 @@ abstract class Controller extends BaseController | ||||
|  | ||||
|     use DispatchesCommands, ValidatesRequests; | ||||
|  | ||||
|     /** @var string */ | ||||
|     protected $monthAndDayFormat; | ||||
|     /** @var string */ | ||||
|     protected $monthFormat; | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
| @@ -24,5 +32,16 @@ abstract class Controller extends BaseController | ||||
|         View::share('hideCategories', false); | ||||
|         View::share('hideBills', false); | ||||
|         View::share('hideTags', false); | ||||
|  | ||||
|         if (Auth::check()) { | ||||
|             $pref                    = Preferences::get('language', 'en'); | ||||
|             $lang                    = $pref->data; | ||||
|             $this->monthFormat       = Config::get('firefly.month.' . $lang); | ||||
|             $this->monthAndDayFormat = Config::get('firefly.monthAndDay.' . $lang); | ||||
|  | ||||
|             View::share('monthFormat', $this->monthFormat); | ||||
|             View::share('monthAndDayFormat', $this->monthAndDayFormat); | ||||
|             View::share('language', $lang); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -28,7 +28,7 @@ class CurrencyController extends Controller | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         View::share('title', 'Currencies'); | ||||
|         View::share('title', trans('firefly.currencies')); | ||||
|         View::share('mainTitleIcon', 'fa-usd'); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,590 +0,0 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use FireflyIII\Helpers\Report\ReportQueryInterface; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use Grumpydictator\Gchart\GChart; | ||||
| use Illuminate\Support\Collection; | ||||
| use Navigation; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
| use Steam; | ||||
|  | ||||
| /** | ||||
|  * Class GoogleChartController | ||||
|  * | ||||
|  * @package FireflyIII\Http\Controllers | ||||
|  */ | ||||
| class GoogleChartController extends Controller | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param GChart  $chart | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function accountBalanceChart(GChart $chart, Account $account) | ||||
|     { | ||||
|         $chart->addColumn('Day of month', 'date'); | ||||
|         $chart->addColumn('Balance for ' . $account->name, 'number'); | ||||
|         $chart->addCertainty(1); | ||||
|  | ||||
|         $start   = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end     = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $current = clone $start; | ||||
|         $today   = new Carbon; | ||||
|  | ||||
|         while ($end >= $current) { | ||||
|             $certain = $current < $today; | ||||
|             $chart->addRow(clone $current, Steam::balance($account, $current), $certain); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                     $chart | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function allAccountsBalanceChart(GChart $chart, AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn('Day of the month', 'date'); | ||||
|  | ||||
|         $frontPage = Preferences::get('frontPageAccounts', []); | ||||
|         $start     = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end       = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $accounts  = $repository->getFrontpageAccounts($frontPage); | ||||
|  | ||||
|         $index = 1; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             $chart->addColumn('Balance for ' . $account->name, 'number'); | ||||
|             $chart->addCertainty($index); | ||||
|             $index++; | ||||
|         } | ||||
|         $current = clone $start; | ||||
|         $current->subDay(); | ||||
|         $today = Carbon::now(); | ||||
|         while ($end >= $current) { | ||||
|             $row     = [clone $current]; | ||||
|             $certain = $current < $today; | ||||
|             foreach ($accounts as $account) { | ||||
|                 $row[] = Steam::balance($account, $current); | ||||
|                 $row[] = $certain; | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|             $current->addDay(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param                           $year | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function allBudgetsAndSpending(GChart $chart, BudgetRepositoryInterface $repository, $year) | ||||
|     { | ||||
|         $budgets = $repository->getBudgets(); | ||||
|         $chart->addColumn('Month', 'date'); | ||||
|         foreach ($budgets as $budget) { | ||||
|             $chart->addColumn($budget->name, 'number'); | ||||
|         } | ||||
|  | ||||
|         $start = Carbon::createFromDate(intval($year), 1, 1); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfYear(); | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             $row = [clone $start]; | ||||
|             foreach ($budgets as $budget) { | ||||
|                 $spent = $repository->spentInMonth($budget, $start); | ||||
|                 $row[] = $spent; | ||||
|             } | ||||
|             $chart->addRowArray($row); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function allBudgetsHomeChart(GChart $chart, BudgetRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn('Budget', 'string'); | ||||
|         $chart->addColumn('Left', 'number'); | ||||
|         $chart->addColumn('Spent', 'number'); | ||||
|         $chart->addColumn('Overspent', 'number'); | ||||
|  | ||||
|         $budgets    = $repository->getBudgets(); | ||||
|         $start      = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end        = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $allEntries = new Collection; | ||||
|  | ||||
|         foreach ($budgets as $budget) { | ||||
|             $repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end); | ||||
|             if ($repetitions->count() == 0) { | ||||
|                 $expenses = $repository->sumBudgetExpensesInPeriod($budget, $start, $end); | ||||
|                 $allEntries->push([$budget->name, 0, 0, $expenses]); | ||||
|                 continue; | ||||
|             } | ||||
|             /** @var LimitRepetition $repetition */ | ||||
|             foreach ($repetitions as $repetition) { | ||||
|                 $expenses  = $repository->sumBudgetExpensesInPeriod($budget, $repetition->startdate, $repetition->enddate); | ||||
|                 $left      = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0; | ||||
|                 $spent     = $expenses > floatval($repetition->amount) ? 0 : $expenses; | ||||
|                 $overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0; | ||||
|                 $allEntries->push( | ||||
|                     [$budget->name . ' (' . $repetition->startdate->format('j M Y') . ')', | ||||
|                      $left, | ||||
|                      $spent, | ||||
|                      $overspent | ||||
|                     ] | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end); | ||||
|         $allEntries->push(['(no budget)', 0, 0, $noBudgetExpenses]); | ||||
|  | ||||
|         foreach ($allEntries as $entry) { | ||||
|             if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) { | ||||
|                 $chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function allCategoriesHomeChart(GChart $chart, CategoryRepositoryInterface $repository) | ||||
|     { | ||||
|         $chart->addColumn('Category', 'string'); | ||||
|         $chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         $start = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end   = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $set   = $repository->getCategoriesAndExpenses($start, $end); | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $isEncrypted = intval($entry->encrypted) == 1 ? true : false; | ||||
|             $name        = strlen($entry->name) == 0 ? '(no category)' : $entry->name; | ||||
|             $name        = $isEncrypted ? Crypt::decrypt($name) : $name; | ||||
|             $chart->addRow($name, floatval($entry->sum)); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                  $chart | ||||
|      * @param BillRepositoryInterface $repository | ||||
|      * @param Bill                    $bill | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function billOverview(GChart $chart, BillRepositoryInterface $repository, Bill $bill) | ||||
|     { | ||||
|  | ||||
|         $chart->addColumn('Date', 'date'); | ||||
|         $chart->addColumn('Max amount', 'number'); | ||||
|         $chart->addColumn('Min amount', 'number'); | ||||
|         $chart->addColumn('Recorded bill entry', 'number'); | ||||
|  | ||||
|         // get first transaction or today for start: | ||||
|         $results = $repository->getJournals($bill); | ||||
|         /** @var TransactionJournal $result */ | ||||
|         foreach ($results as $result) { | ||||
|             $chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount)); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                     $chart | ||||
|      * | ||||
|      * @param BillRepositoryInterface    $repository | ||||
|      * @param AccountRepositoryInterface $accounts | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function billsOverview(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts) | ||||
|     { | ||||
|         $chart->addColumn('Name', 'string'); | ||||
|         $chart->addColumn('Amount', 'number'); | ||||
|  | ||||
|         $start  = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end    = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $bills  = $repository->getActiveBills(); | ||||
|         $paid   = new Collection; // journals. | ||||
|         $unpaid = new Collection; // bills | ||||
|         // loop paid and create single entry: | ||||
|         $paidDescriptions   = []; | ||||
|         $paidAmount         = 0; | ||||
|         $unpaidDescriptions = []; | ||||
|         $unpaidAmount       = 0; | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $ranges = $repository->getRanges($bill, $start, $end); | ||||
|  | ||||
|             foreach ($ranges as $range) { | ||||
|                 // paid a bill in this range? | ||||
|                 $journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']); | ||||
|                 if ($journals->count() == 0) { | ||||
|                     $unpaid->push([$bill, $range['start']]); | ||||
|                 } else { | ||||
|                     $paid = $paid->merge($journals); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $creditCards = $accounts->getCreditCards(); | ||||
|         foreach ($creditCards as $creditCard) { | ||||
|             $balance = Steam::balance($creditCard, null, true); | ||||
|             $date    = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate')); | ||||
|             if ($balance < 0) { | ||||
|                 // unpaid! create a fake bill that matches the amount. | ||||
|                 $description = $creditCard->name; | ||||
|                 $amount      = $balance * -1; | ||||
|                 $fakeBill    = $repository->createFakeBill($description, $date, $amount); | ||||
|                 unset($description, $amount); | ||||
|                 $unpaid->push([$fakeBill, $date]); | ||||
|             } | ||||
|             if ($balance == 0) { | ||||
|                 // find transfer(s) TO the credit card which should account for | ||||
|                 // anything paid. If not, the CC is not yet used. | ||||
|                 $journals = $accounts->getTransfersInRange($creditCard, $start, $end); | ||||
|                 $paid     = $paid->merge($journals); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|         /** @var TransactionJournal $entry */ | ||||
|         foreach ($paid as $entry) { | ||||
|  | ||||
|             $paidDescriptions[] = $entry->description; | ||||
|             $paidAmount += floatval($entry->amount); | ||||
|         } | ||||
|  | ||||
|         // loop unpaid: | ||||
|         /** @var Bill $entry */ | ||||
|         foreach ($unpaid as $entry) { | ||||
|             $description          = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')'; | ||||
|             $amount               = ($entry[0]->amount_max + $entry[0]->amount_min) / 2; | ||||
|             $unpaidDescriptions[] = $description; | ||||
|             $unpaidAmount += $amount; | ||||
|             unset($amount, $description); | ||||
|         } | ||||
|  | ||||
|         $chart->addRow('Unpaid: ' . join(', ', $unpaidDescriptions), $unpaidAmount); | ||||
|         $chart->addRow('Paid: ' . join(', ', $paidDescriptions), $paidAmount); | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param Budget                    $budget | ||||
|      * @param LimitRepetition           $repetition | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function budgetLimitSpending(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition) | ||||
|     { | ||||
|         $start = clone $repetition->startdate; | ||||
|         $end   = $repetition->enddate; | ||||
|  | ||||
|         $chart->addColumn('Day', 'date'); | ||||
|         $chart->addColumn('Left', 'number'); | ||||
|  | ||||
|  | ||||
|         $amount = $repetition->amount; | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             /* | ||||
|              * Sum of expenses on this day: | ||||
|              */ | ||||
|             $sum = $repository->expensesOnDay($budget, $start); | ||||
|             $amount += $sum; | ||||
|             $chart->addRow(clone $start, $amount); | ||||
|             $start->addDay(); | ||||
|         } | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                    $chart | ||||
|      * @param BudgetRepositoryInterface $repository | ||||
|      * @param Budget                    $budget | ||||
|      * @param int                       $year | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function budgetsAndSpending(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, $year = 0) | ||||
|     { | ||||
|         $chart->addColumn('Month', 'date'); | ||||
|         $chart->addColumn('Budgeted', 'number'); | ||||
|         $chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         if ($year == 0) { | ||||
|             $start = $repository->getFirstBudgetLimitDate($budget); | ||||
|             $end   = $repository->getLastBudgetLimitDate($budget); | ||||
|         } else { | ||||
|             $start = Carbon::createFromDate(intval($year), 1, 1); | ||||
|             $end   = clone $start; | ||||
|             $end->endOfYear(); | ||||
|         } | ||||
|  | ||||
|         while ($start <= $end) { | ||||
|             $spent    = $repository->spentInMonth($budget, $start); | ||||
|             $budgeted = $repository->getLimitAmountOnDate($budget, $start); | ||||
|             $chart->addRow(clone $start, $budgeted, $spent); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function categoryOverviewChart(GChart $chart, CategoryRepositoryInterface $repository, Category $category) | ||||
|     { | ||||
|         // oldest transaction in category: | ||||
|         $start = $repository->getFirstActivityDate($category); | ||||
|  | ||||
|         /** @var Preference $range */ | ||||
|         $range = Preferences::get('viewRange', '1M'); | ||||
|         // jump to start of week / month / year / etc (TODO). | ||||
|         $start = Navigation::startOfPeriod($start, $range->data); | ||||
|  | ||||
|         $chart->addColumn('Period', 'date'); | ||||
|         $chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         $end = new Carbon; | ||||
|         while ($start <= $end) { | ||||
|  | ||||
|             $currentEnd = Navigation::endOfPeriod($start, $range->data); | ||||
|             $spent      = $repository->spentInPeriodSum($category, $start, $currentEnd); | ||||
|             $chart->addRow(clone $start, $spent); | ||||
|  | ||||
|             $start = Navigation::addPeriod($start, $range->data, 0); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                      $chart | ||||
|      * @param CategoryRepositoryInterface $repository | ||||
|      * @param Category                    $category | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function categoryPeriodChart(GChart $chart, CategoryRepositoryInterface $repository, Category $category) | ||||
|     { | ||||
|         $start = clone Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $chart->addColumn('Period', 'date'); | ||||
|         $chart->addColumn('Spent', 'number'); | ||||
|  | ||||
|         $end = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         while ($start <= $end) { | ||||
|             $spent = $repository->spentOnDaySum($category, $start); | ||||
|             $chart->addRow(clone $start, $spent); | ||||
|             $start->addDay(); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param GChart                       $chart | ||||
|      * @param PiggyBankRepositoryInterface $repository | ||||
|      * @param PiggyBank                    $piggyBank | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function piggyBankHistory(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank) | ||||
|     { | ||||
|         $chart->addColumn('Date', 'date'); | ||||
|         $chart->addColumn('Balance', 'number'); | ||||
|  | ||||
|         /** @var Collection $set */ | ||||
|         $set = $repository->getEventSummarySet($piggyBank); | ||||
|         $sum = 0; | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $sum += floatval($entry->sum); | ||||
|             $chart->addRow(new Carbon($entry->date), $sum); | ||||
|         } | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart               $chart | ||||
|      * @param ReportQueryInterface $query | ||||
|      * @param                      $year | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function yearInExp(GChart $chart, ReportQueryInterface $query, $year) | ||||
|     { | ||||
|         $start = new Carbon('01-01-' . $year); | ||||
|         $chart->addColumn('Month', 'date'); | ||||
|         $chart->addColumn('Income', 'number'); | ||||
|         $chart->addColumn('Expenses', 'number'); | ||||
|  | ||||
|         $pref              = Preferences::get('showSharedReports', false); | ||||
|         $showSharedReports = $pref->data; | ||||
|  | ||||
|         // get report query interface. | ||||
|  | ||||
|         $end = clone $start; | ||||
|         $end->endOfYear(); | ||||
|         while ($start < $end) { | ||||
|             $currentEnd = clone $start; | ||||
|             $currentEnd->endOfMonth(); | ||||
|             // total income && total expenses: | ||||
|             $incomeSum  = floatval($query->incomeByPeriod($start, $currentEnd, $showSharedReports)->sum('queryAmount')); | ||||
|             $expenseSum = floatval($query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports)->sum('queryAmount')); | ||||
|  | ||||
|             $chart->addRow(clone $start, $incomeSum, $expenseSum); | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param GChart               $chart | ||||
|      * @param ReportQueryInterface $query | ||||
|      * @param                      $year | ||||
|      * | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function yearInExpSum(GChart $chart, ReportQueryInterface $query, $year) | ||||
|     { | ||||
|         $start = new Carbon('01-01-' . $year); | ||||
|         $chart->addColumn('Summary', 'string'); | ||||
|         $chart->addColumn('Income', 'number'); | ||||
|         $chart->addColumn('Expenses', 'number'); | ||||
|  | ||||
|         $pref              = Preferences::get('showSharedReports', false); | ||||
|         $showSharedReports = $pref->data; | ||||
|  | ||||
|         $income  = 0; | ||||
|         $expense = 0; | ||||
|         $count   = 0; | ||||
|  | ||||
|         $end = clone $start; | ||||
|         $end->endOfYear(); | ||||
|         while ($start < $end) { | ||||
|             $currentEnd = clone $start; | ||||
|             $currentEnd->endOfMonth(); | ||||
|             // total income: | ||||
|             $incomeSum = floatval($query->incomeByPeriod($start, $currentEnd, $showSharedReports)->sum('queryAmount')); | ||||
|             // total expenses: | ||||
|             $expenseSum = floatval($query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports)->sum('queryAmount')); | ||||
|  | ||||
|             $income += $incomeSum; | ||||
|             $expense += $expenseSum; | ||||
|             $count++; | ||||
|             $start->addMonth(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $chart->addRow('Sum', $income, $expense); | ||||
|         $count = $count > 0 ? $count : 1; | ||||
|         $chart->addRow('Average', ($income / $count), ($expense / $count)); | ||||
|  | ||||
|         $chart->generate(); | ||||
|  | ||||
|         return Response::json($chart->getData()); | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -53,7 +53,7 @@ class HomeController extends Controller | ||||
|         $types             = Config::get('firefly.accountTypesByIdentifier.asset'); | ||||
|         $count             = $repository->countAccounts($types); | ||||
|         $title             = 'Firefly'; | ||||
|         $subTitle          = 'What\'s playing?'; | ||||
|         $subTitle          = trans('firefly.welcomeBack'); | ||||
|         $mainTitleIcon     = 'fa-fire'; | ||||
|         $transactions      = []; | ||||
|         $frontPage         = Preferences::get('frontPageAccounts', []); | ||||
| @@ -63,13 +63,11 @@ class HomeController extends Controller | ||||
|         $savings           = $repository->getSavingsAccounts(); | ||||
|         $piggyBankAccounts = $repository->getPiggyBankAccounts(); | ||||
|  | ||||
|  | ||||
|         $savingsTotal = 0; | ||||
|         foreach ($savings as $savingAccount) { | ||||
|             $savingsTotal += Steam::balance($savingAccount, $end); | ||||
|         } | ||||
|  | ||||
|         // check if all books are correct. | ||||
|         $sum = $repository->sumOfEverything(); | ||||
|         if ($sum != 0) { | ||||
|             Session::flash( | ||||
|   | ||||
| @@ -12,7 +12,6 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\Tag\TagRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Preferences; | ||||
| use Response; | ||||
| use Session; | ||||
| use Steam; | ||||
| @@ -39,19 +38,14 @@ class JsonController extends Controller | ||||
|         $end    = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $amount = 0; | ||||
|  | ||||
|         // these two functions are the same as the chart TODO | ||||
|         // these two functions are the same as the chart | ||||
|         $bills = $repository->getActiveBills(); | ||||
|  | ||||
|         /** @var Bill $bill */ | ||||
|         foreach ($bills as $bill) { | ||||
|             $ranges = $repository->getRanges($bill, $start, $end); | ||||
|  | ||||
|             foreach ($ranges as $range) { | ||||
|                 // paid a bill in this range? | ||||
|                 $amount += $repository->getJournalsInRange($bill, $range['start'], $range['end'])->sum('amount'); | ||||
|             } | ||||
|             $amount += $repository->billPaymentsInRange($bill, $start, $end); | ||||
|         } | ||||
|         unset($ranges, $bill, $range, $bills); | ||||
|         unset($bill, $bills); | ||||
|  | ||||
|         /** | ||||
|          * Find credit card accounts and possibly unpaid credit card bills. | ||||
| @@ -60,7 +54,7 @@ class JsonController extends Controller | ||||
|         // if the balance is not zero, the monthly payment is still underway. | ||||
|         /** @var Account $creditCard */ | ||||
|         foreach ($creditCards as $creditCard) { | ||||
|             $balance = Steam::balance($creditCard, null, true); | ||||
|             $balance = Steam::balance($creditCard, $end, true); | ||||
|             if ($balance == 0) { | ||||
|                 // find a transfer TO the credit card which should account for | ||||
|                 // anything paid. If not, the CC is not yet used. | ||||
| @@ -100,7 +94,7 @@ class JsonController extends Controller | ||||
|  | ||||
|         $creditCards = $accountRepository->getCreditCards(); | ||||
|         foreach ($creditCards as $creditCard) { | ||||
|             $balance = Steam::balance($creditCard, null, true); | ||||
|             $balance = Steam::balance($creditCard, $end, true); | ||||
|             $date    = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate')); | ||||
|             if ($balance < 0) { | ||||
|                 // unpaid! create a fake bill that matches the amount. | ||||
| @@ -128,7 +122,12 @@ class JsonController extends Controller | ||||
|     { | ||||
|         $start  = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end    = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $amount = $reportQuery->incomeByPeriod($start, $end, true)->sum('queryAmount'); | ||||
|         $amount = $reportQuery->incomeInPeriodCorrected($start, $end, true)->sum('amount'); | ||||
|         //        $amount = 0; | ||||
|         //        foreach($set as $entry) { | ||||
|         //            //echo $entry->description.' ('.$entry->tags->count().'): ' . $entry->amount."\n"; | ||||
|         //            $amount += $entry->amount; | ||||
|         //        } | ||||
|  | ||||
|         return Response::json(['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); | ||||
|     } | ||||
| @@ -142,7 +141,7 @@ class JsonController extends Controller | ||||
|     { | ||||
|         $start  = Session::get('start', Carbon::now()->startOfMonth()); | ||||
|         $end    = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $amount = $reportQuery->journalsByExpenseAccount($start, $end, true)->sum('queryAmount'); | ||||
|         $amount = $reportQuery->expenseInPeriodCorrected($start, $end, true)->sum('amount'); | ||||
|  | ||||
|         return Response::json(['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]); | ||||
|     } | ||||
| @@ -202,30 +201,6 @@ class JsonController extends Controller | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function setSharedReports() | ||||
|     { | ||||
|         /** @var Preference $pref */ | ||||
|         $pref = Preferences::get('showSharedReports', false); | ||||
|         $new  = !$pref->data; | ||||
|         Preferences::set('showSharedReports', $new); | ||||
|  | ||||
|  | ||||
|         return Response::json(['value' => $new]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return \Symfony\Component\HttpFoundation\Response | ||||
|      */ | ||||
|     public function showSharedReports() | ||||
|     { | ||||
|         $pref = Preferences::get('showSharedReports', false); | ||||
|  | ||||
|         return Response::json(['value' => $pref->data]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a JSON list of all beneficiaries. | ||||
|      * | ||||
|   | ||||
| @@ -31,7 +31,7 @@ class PiggyBankController extends Controller | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         View::share('title', 'Piggy banks'); | ||||
|         View::share('title', trans('firefly.piggyBanks')); | ||||
|         View::share('mainTitleIcon', 'fa-sort-amount-asc'); | ||||
|     } | ||||
|  | ||||
| @@ -45,7 +45,8 @@ class PiggyBankController extends Controller | ||||
|      */ | ||||
|     public function add(AccountRepositoryInterface $repository, PiggyBank $piggyBank) | ||||
|     { | ||||
|         $leftOnAccount = $repository->leftOnAccount($piggyBank->account); | ||||
|         $date          = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $leftOnAccount = $repository->leftOnAccount($piggyBank->account, $date); | ||||
|         $savedSoFar    = $piggyBank->currentRelevantRep()->currentamount; | ||||
|         $leftToSave    = $piggyBank->targetamount - $savedSoFar; | ||||
|         $maxAmount     = min($leftOnAccount, $leftToSave); | ||||
| @@ -157,6 +158,7 @@ class PiggyBankController extends Controller | ||||
|     { | ||||
|         /** @var Collection $piggyBanks */ | ||||
|         $piggyBanks = $piggyRepository->getPiggyBanks(); | ||||
|         $end        = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|         $accounts = []; | ||||
|         /** @var PiggyBank $piggyBank */ | ||||
| @@ -172,8 +174,8 @@ class PiggyBankController extends Controller | ||||
|             if (!isset($accounts[$account->id])) { | ||||
|                 $accounts[$account->id] = [ | ||||
|                     'name'              => $account->name, | ||||
|                     'balance'           => Steam::balance($account, null, true), | ||||
|                     'leftForPiggyBanks' => $repository->leftOnAccount($account), | ||||
|                     'balance'           => Steam::balance($account, $end, true), | ||||
|                     'leftForPiggyBanks' => $repository->leftOnAccount($account, $end), | ||||
|                     'sumOfSaved'        => $piggyBank->savedSoFar, | ||||
|                     'sumOfTargets'      => floatval($piggyBank->targetamount), | ||||
|                     'leftToSave'        => $piggyBank->leftToSave | ||||
| @@ -215,7 +217,8 @@ class PiggyBankController extends Controller | ||||
|     public function postAdd(PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts, PiggyBank $piggyBank) | ||||
|     { | ||||
|         $amount        = round(floatval(Input::get('amount')), 2); | ||||
|         $leftOnAccount = $accounts->leftOnAccount($piggyBank->account); | ||||
|         $date          = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|         $leftOnAccount = $accounts->leftOnAccount($piggyBank->account, $date); | ||||
|         $savedSoFar    = $piggyBank->currentRelevantRep()->currentamount; | ||||
|         $leftToSave    = $piggyBank->targetamount - $savedSoFar; | ||||
|         $maxAmount     = round(min($leftOnAccount, $leftToSave), 2); | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| <?php namespace FireflyIII\Http\Controllers; | ||||
|  | ||||
| use Config; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Input; | ||||
| use Preferences; | ||||
| @@ -21,7 +22,7 @@ class PreferencesController extends Controller | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         View::share('title', 'Preferences'); | ||||
|         View::share('title', trans('firefly.preferences')); | ||||
|         View::share('mainTitleIcon', 'fa-gear'); | ||||
|     } | ||||
|  | ||||
| @@ -37,9 +38,11 @@ class PreferencesController extends Controller | ||||
|         $viewRange         = $viewRangePref->data; | ||||
|         $frontPageAccounts = Preferences::get('frontPageAccounts', []); | ||||
|         $budgetMax         = Preferences::get('budgetMaximum', 1000); | ||||
|         $languagePref      = Preferences::get('language', 'en'); | ||||
|         $language          = $languagePref->data; | ||||
|         $budgetMaximum     = $budgetMax->data; | ||||
|  | ||||
|         return view('preferences.index', compact('budgetMaximum', 'accounts', 'frontPageAccounts', 'viewRange')); | ||||
|         return view('preferences.index', compact('budgetMaximum', 'language', 'accounts', 'frontPageAccounts', 'viewRange')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -49,10 +52,12 @@ class PreferencesController extends Controller | ||||
|     { | ||||
|         // front page accounts | ||||
|         $frontPageAccounts = []; | ||||
|         foreach (Input::get('frontPageAccounts') as $id) { | ||||
|             $frontPageAccounts[] = intval($id); | ||||
|         if (is_array(Input::get('frontPageAccounts'))) { | ||||
|             foreach (Input::get('frontPageAccounts') as $id) { | ||||
|                 $frontPageAccounts[] = intval($id); | ||||
|             } | ||||
|             Preferences::set('frontPageAccounts', $frontPageAccounts); | ||||
|         } | ||||
|         Preferences::set('frontPageAccounts', $frontPageAccounts); | ||||
|  | ||||
|         // view range: | ||||
|         Preferences::set('viewRange', Input::get('viewRange')); | ||||
| @@ -65,6 +70,12 @@ class PreferencesController extends Controller | ||||
|         $budgetMaximum = intval(Input::get('budgetMaximum')); | ||||
|         Preferences::set('budgetMaximum', $budgetMaximum); | ||||
|  | ||||
|         // language: | ||||
|         $lang = Input::get('language'); | ||||
|         if (in_array($lang, array_keys(Config::get('firefly.lang')))) { | ||||
|             Preferences::set('language', $lang); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         Session::flash('success', 'Preferences saved!'); | ||||
|  | ||||
|   | ||||
| @@ -2,13 +2,13 @@ | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Report\ReportHelperInterface; | ||||
| use FireflyIII\Helpers\Report\ReportQueryInterface; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Preferences; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use Session; | ||||
| use Steam; | ||||
| use View; | ||||
|  | ||||
| /** | ||||
| @@ -21,311 +21,132 @@ class ReportController extends Controller | ||||
|  | ||||
|     /** @var ReportHelperInterface */ | ||||
|     protected $helper; | ||||
|     /** @var ReportQueryInterface */ | ||||
|     protected $query; | ||||
|  | ||||
|     /** | ||||
|      * @param ReportHelperInterface $helper | ||||
|      * @param ReportQueryInterface  $query | ||||
|      */ | ||||
|     public function __construct(ReportHelperInterface $helper, ReportQueryInterface $query) | ||||
|     public function __construct(ReportHelperInterface $helper) | ||||
|     { | ||||
|         $this->query  = $query; | ||||
|         parent::__construct(); | ||||
|         $this->helper = $helper; | ||||
|  | ||||
|         View::share('title', 'Reports'); | ||||
|         View::share('title', trans('firefly.reports')); | ||||
|         View::share('mainTitleIcon', 'fa-line-chart'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $year | ||||
|      * @param string $month | ||||
|      * @param AccountRepositoryInterface $repository | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function budget($year = '2014', $month = '1') | ||||
|     { | ||||
|         $date         = new Carbon($year . '-' . $month . '-01'); | ||||
|         $subTitle     = 'Budget report for ' . $date->format('F Y'); | ||||
|         $subTitleIcon = 'fa-calendar'; | ||||
|         $start        = clone $date; | ||||
|  | ||||
|  | ||||
|         $start->startOfMonth(); | ||||
|         $end = clone $date; | ||||
|         $end->endOfMonth(); | ||||
|  | ||||
|         // should show shared reports? | ||||
|         /** @var Preference $pref */ | ||||
|         $pref              = Preferences::get('showSharedReports', false); | ||||
|         $showSharedReports = $pref->data; | ||||
|         $accountAmounts    = []; // array with sums of spent amounts on each account. | ||||
|         $accounts          = $this->query->getAllAccounts($start, $end, $showSharedReports); // all accounts and some data. | ||||
|  | ||||
|         foreach ($accounts as $account) { | ||||
|  | ||||
|             $budgets                      = $this->query->getBudgetSummary($account, $start, $end);// get budget summary for this account: | ||||
|             $balancedAmount               = $this->query->balancedTransactionsSum($account, $start, $end); | ||||
|             $accountAmounts[$account->id] = $balancedAmount; | ||||
|             // balance out the transactions (see transaction groups & tags) ^^ | ||||
|  | ||||
|             // array with budget information for each account: | ||||
|             $array = []; | ||||
|             // should always hide account | ||||
|             $hide = true; | ||||
|             // loop all budgets | ||||
|             /** @var \FireflyIII\Models\Budget $budget */ | ||||
|             foreach ($budgets as $budget) { | ||||
|                 $id         = intval($budget->id); | ||||
|                 $data       = $budget->toArray(); | ||||
|                 $array[$id] = $data; | ||||
|  | ||||
|                 // no longer hide account if any budget has money in it. | ||||
|                 if (floatval($data['queryAmount']) != 0) { | ||||
|                     $hide = false; | ||||
|                 } | ||||
|                 $accountAmounts[$account->id] += $data['queryAmount']; | ||||
|             } | ||||
|             $account->hide              = $hide; | ||||
|             $account->budgetInformation = $array; | ||||
|             $account->balancedAmount    = $balancedAmount; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Start getBudgetsForMonth DONE | ||||
|          */ | ||||
|         $budgets = $this->helper->getBudgetsForMonth($date, $showSharedReports); | ||||
|  | ||||
|         /** | ||||
|          * End getBudgetsForMonth DONE | ||||
|          */ | ||||
|  | ||||
|         return view('reports.budget', compact('subTitle', 'accountAmounts', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets')); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return View | ||||
|      * @internal param ReportHelperInterface $helper | ||||
|      * | ||||
|      */ | ||||
|     public function index() | ||||
|     public function index(AccountRepositoryInterface $repository) | ||||
|     { | ||||
|         $start         = Session::get('first'); | ||||
|         $months        = $this->helper->listOfMonths($start); | ||||
|         $years         = $this->helper->listOfYears($start); | ||||
|         $title         = 'Reports'; | ||||
|         $mainTitleIcon = 'fa-line-chart'; | ||||
|         $start  = Session::get('first'); | ||||
|         $months = $this->helper->listOfMonths($start); | ||||
|  | ||||
|         return view('reports.index', compact('years', 'months', 'title', 'mainTitleIcon')); | ||||
|     } | ||||
|         // does the user have shared accounts? | ||||
|         $accounts  = $repository->getAccounts(['Default account', 'Asset account']); | ||||
|         $hasShared = false; | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param string  $year | ||||
|      * @param string  $month | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function modalBalancedTransfers(Account $account, $year = '2014', $month = '1') | ||||
|     { | ||||
|  | ||||
|         $start = new Carbon($year . '-' . $month . '-01'); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfMonth(); | ||||
|  | ||||
|         $journals = $this->query->balancedTransactionsList($account, $start, $end); | ||||
|  | ||||
|         return view('reports.modal-journal-list', compact('journals')); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param string  $year | ||||
|      * @param string  $month | ||||
|      * | ||||
|      * @return View | ||||
|      * @internal param ReportQueryInterface $query | ||||
|      * | ||||
|      */ | ||||
|     public function modalLeftUnbalanced(Account $account, $year = '2014', $month = '1') | ||||
|     { | ||||
|         $start = new Carbon($year . '-' . $month . '-01'); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfMonth(); | ||||
|         $set = $this->query->getTransactionsWithoutBudget($account, $start, $end); | ||||
|  | ||||
|         $journals = $set->filter( | ||||
|             function (TransactionJournal $journal) { | ||||
|                 $count = $journal->transactiongroups()->where('relation', 'balance')->count(); | ||||
|                 if ($count == 0) { | ||||
|                     return $journal; | ||||
|                 } | ||||
|  | ||||
|                 return null; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($accounts as $account) { | ||||
|             if ($account->getMeta('accountRole') == 'sharedAsset') { | ||||
|                 $hasShared = true; | ||||
|             } | ||||
|         ); | ||||
|         } | ||||
|  | ||||
|         return view('reports.modal-journal-list', compact('journals')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param string  $year | ||||
|      * @param string  $month | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function modalNoBudget(Account $account, $year = '2014', $month = '1') | ||||
|     { | ||||
|         $start = new Carbon($year . '-' . $month . '-01'); | ||||
|         $end   = clone $start; | ||||
|         $end->endOfMonth(); | ||||
|         $journals = $this->query->getTransactionsWithoutBudget($account, $start, $end); | ||||
|  | ||||
|         return view('reports.modal-journal-list', compact('journals')); | ||||
|  | ||||
|         return view('reports.index', compact('months', 'hasShared')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $year | ||||
|      * @param string $month | ||||
|      * | ||||
|      * @param bool   $shared | ||||
|      * | ||||
|      * @return \Illuminate\View\View | ||||
|      */ | ||||
|     public function month($year = '2014', $month = '1') | ||||
|     public function month($year = '2014', $month = '1', $shared = false) | ||||
|     { | ||||
|         $date         = new Carbon($year . '-' . $month . '-01'); | ||||
|         $subTitle     = 'Report for ' . $date->format('F Y'); | ||||
|         $subTitleIcon = 'fa-calendar'; | ||||
|         $displaySum   = true; // to show sums in report. | ||||
|         /** @var Preference $pref */ | ||||
|         $pref              = Preferences::get('showSharedReports', false); | ||||
|         $showSharedReports = $pref->data; | ||||
|         $start            = new Carbon($year . '-' . $month . '-01'); | ||||
|         $subTitle         = trans('firefly.reportForMonth', ['date' => $start->formatLocalized($this->monthFormat)]); | ||||
|         $subTitleIcon     = 'fa-calendar'; | ||||
|         $end              = clone $start; | ||||
|         $incomeTopLength  = 8; | ||||
|         $expenseTopLength = 8; | ||||
|         if ($shared == 'shared') { | ||||
|             $shared   = true; | ||||
|             $subTitle = trans('firefly.reportForMonthShared', ['date' => $start->formatLocalized($this->monthFormat)]); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         /** | ||||
|          * | ||||
|          * get income for month (date) | ||||
|          * | ||||
|          */ | ||||
|  | ||||
|         $start = clone $date; | ||||
|         $start->startOfMonth(); | ||||
|         $end = clone $date; | ||||
|         $end->endOfMonth(); | ||||
|  | ||||
|         /** | ||||
|          * Start getIncomeForMonth DONE | ||||
|          */ | ||||
|         $income = $this->query->incomeByPeriod($start, $end, $showSharedReports); | ||||
|         /** | ||||
|          * End getIncomeForMonth DONE | ||||
|          */ | ||||
|         /** | ||||
|          * Start getExpenseGroupedForMonth DONE | ||||
|          */ | ||||
|         $set = $this->query->journalsByExpenseAccount($start, $end, $showSharedReports); | ||||
|  | ||||
|         $expenses = Steam::makeArray($set); | ||||
|         $expenses = Steam::sortArray($expenses); | ||||
|         $expenses = Steam::limitArray($expenses, 10); | ||||
|         /** | ||||
|          * End getExpenseGroupedForMonth DONE | ||||
|          */ | ||||
|         /** | ||||
|          * Start getBudgetsForMonth DONE | ||||
|          */ | ||||
|         $budgets = $this->helper->getBudgetsForMonth($date, $showSharedReports); | ||||
|  | ||||
|         /** | ||||
|          * End getBudgetsForMonth DONE | ||||
|          */ | ||||
|         /** | ||||
|          * Start getCategoriesForMonth DONE | ||||
|          */ | ||||
|         // all categories. | ||||
|         $result     = $this->query->journalsByCategory($start, $end); | ||||
|         $categories = Steam::makeArray($result); | ||||
|  | ||||
|  | ||||
|         // all transfers | ||||
|         if ($showSharedReports === false) { | ||||
|             $result    = $this->query->sharedExpensesByCategory($start, $end); | ||||
|             $transfers = Steam::makeArray($result); | ||||
|             $merged    = Steam::mergeArrays($categories, $transfers); | ||||
|         } else { | ||||
|             $merged = $categories; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         // sort. | ||||
|         $sorted = Steam::sortNegativeArray($merged); | ||||
|  | ||||
|         // limit to $limit: | ||||
|         $categories = Steam::limitArray($sorted, 10); | ||||
|         /** | ||||
|          * End getCategoriesForMonth DONE | ||||
|          */ | ||||
|         /** | ||||
|          * Start getAccountsForMonth | ||||
|          */ | ||||
|         $list     = $this->query->accountList($showSharedReports); | ||||
|         $accounts = []; | ||||
|         /** @var Account $account */ | ||||
|         foreach ($list as $account) { | ||||
|             $id = intval($account->id); | ||||
|             /** @noinspection PhpParamsInspection */ | ||||
|             $accounts[$id] = [ | ||||
|                 'name'         => $account->name, | ||||
|                 'startBalance' => Steam::balance($account, $start), | ||||
|                 'endBalance'   => Steam::balance($account, $end) | ||||
|             ]; | ||||
|  | ||||
|             $accounts[$id]['difference'] = $accounts[$id]['endBalance'] - $accounts[$id]['startBalance']; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * End getAccountsForMonth | ||||
|          */ | ||||
|         $accounts   = $this->helper->getAccountReport($start, $end, $shared); | ||||
|         $incomes    = $this->helper->getIncomeReport($start, $end, $shared); | ||||
|         $expenses   = $this->helper->getExpenseReport($start, $end, $shared); | ||||
|         $budgets    = $this->helper->getBudgetReport($start, $end, $shared); | ||||
|         $categories = $this->helper->getCategoryReport($start, $end, $shared); | ||||
|         $balance    = $this->helper->getBalanceReport($start, $end, $shared); | ||||
|         $bills      = $this->helper->getBillReport($start, $end, $shared); | ||||
|  | ||||
|  | ||||
|         return view( | ||||
|             'reports.month', | ||||
|             compact( | ||||
|                 'income', 'expenses', 'budgets', 'accounts', 'categories', | ||||
|                 'date', 'subTitle', 'displaySum', 'subTitleIcon' | ||||
|                 'start', 'shared', | ||||
|                 'subTitle', 'subTitleIcon', | ||||
|                 'accounts', | ||||
|                 'incomes', 'incomeTopLength', | ||||
|                 'expenses', 'expenseTopLength', | ||||
|                 'budgets', 'balance', | ||||
|                 'categories', | ||||
|                 'bills' | ||||
|             ) | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param $year | ||||
|      * @param      $year | ||||
|      * | ||||
|      * @param bool $shared | ||||
|      * | ||||
|      * @return $this | ||||
|      */ | ||||
|     public function year($year) | ||||
|     public function year($year, $shared = false) | ||||
|     { | ||||
|         /** @var Preference $pref */ | ||||
|         $pref              = Preferences::get('showSharedReports', false); | ||||
|         $showSharedReports = $pref->data; | ||||
|         $date              = new Carbon('01-01-' . $year); | ||||
|         $end               = clone $date; | ||||
|         $start            = new Carbon('01-01-' . $year); | ||||
|         $end              = clone $start; | ||||
|         $subTitle         = trans('firefly.reportForYear', ['year' => $year]); | ||||
|         $subTitleIcon     = 'fa-bar-chart'; | ||||
|         $incomeTopLength  = 8; | ||||
|         $expenseTopLength = 8; | ||||
|  | ||||
|         if ($shared == 'shared') { | ||||
|             $shared   = true; | ||||
|             $subTitle = trans('firefly.reportForYearShared', ['year' => $year]); | ||||
|         } | ||||
|         $end->endOfYear(); | ||||
|         $title           = 'Reports'; | ||||
|         $subTitle        = $year; | ||||
|         $subTitleIcon    = 'fa-bar-chart'; | ||||
|         $mainTitleIcon   = 'fa-line-chart'; | ||||
|         $balances        = $this->helper->yearBalanceReport($date, $showSharedReports); | ||||
|         $groupedIncomes  = $this->query->journalsByRevenueAccount($date, $end, $showSharedReports); | ||||
|         $groupedExpenses = $this->query->journalsByExpenseAccount($date, $end, $showSharedReports); | ||||
|  | ||||
|         $accounts = $this->helper->getAccountReport($start, $end, $shared); | ||||
|         $incomes  = $this->helper->getIncomeReport($start, $end, $shared); | ||||
|         $expenses = $this->helper->getExpenseReport($start, $end, $shared); | ||||
|  | ||||
|  | ||||
|         return view( | ||||
|             'reports.year', compact('date', 'groupedIncomes', 'groupedExpenses', 'year', 'balances', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon') | ||||
|             'reports.year', | ||||
|             compact( | ||||
|                 'start', // the date for this report. | ||||
|                 'shared', // is a shared report? | ||||
|                 'accounts', // all accounts | ||||
|                 'incomes', 'expenses', // expenses and incomes. | ||||
|                 'subTitle', 'subTitleIcon', // subtitle and subtitle icon. | ||||
|                 'incomeTopLength', // length of income top X | ||||
|                 'expenseTopLength' // length of expense top X. | ||||
|             ) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -133,7 +133,7 @@ class TagController extends Controller | ||||
|          * changes to an advancePayment. | ||||
|          */ | ||||
|  | ||||
|         if ($tag->tagMode == 'balancingAct') { | ||||
|         if ($tag->tagMode == 'balancingAct' || $tag->tagMode == 'nothing') { | ||||
|             foreach ($tag->transactionjournals as $journal) { | ||||
|                 if ($journal->transactionType->type == 'Transfer') { | ||||
|                     $allowToAdvancePayment = false; | ||||
| @@ -289,9 +289,9 @@ class TagController extends Controller | ||||
|     public function update(TagFormRequest $request, TagRepositoryInterface $repository, Tag $tag) | ||||
|     { | ||||
|         if (Input::get('setTag') == 'true') { | ||||
|             $latitude  = strlen($request->get('latitude')) > 0 ? $request->get('latitude') : null; | ||||
|             $longitude = strlen($request->get('longitude')) > 0 ? $request->get('longitude') : null; | ||||
|             $zoomLevel = strlen($request->get('zoomLevel')) > 0 ? $request->get('zoomLevel') : null; | ||||
|             $latitude  = $request->get('latitude'); | ||||
|             $longitude = $request->get('longitude'); | ||||
|             $zoomLevel = $request->get('zoomLevel'); | ||||
|         } else { | ||||
|             $latitude  = null; | ||||
|             $longitude = null; | ||||
|   | ||||
| @@ -30,7 +30,7 @@ class TransactionController extends Controller | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         View::share('title', 'Transactions'); | ||||
|         View::share('title', trans('firefly.transactions')); | ||||
|         View::share('mainTitleIcon', 'fa-repeat'); | ||||
|     } | ||||
|  | ||||
| @@ -44,17 +44,15 @@ class TransactionController extends Controller | ||||
|     { | ||||
|         $accounts   = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account'])); | ||||
|         $budgets    = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); | ||||
|         $budgets[0] = '(no budget)'; | ||||
|         $budgets[0] = trans('form.noBudget'); | ||||
|         $piggies    = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get()); | ||||
|         $piggies[0] = '(no piggy bank)'; | ||||
|         $piggies[0] = trans('form.noPiggybank'); | ||||
|         $preFilled  = Session::has('preFilled') ? Session::get('preFilled') : []; | ||||
|         $respondTo  = ['account_id', 'account_from_id']; | ||||
|         $subTitle   = 'Add a new ' . e($what); | ||||
|         $subTitle   = trans('form.add_new_' . $what); | ||||
|  | ||||
|         foreach ($respondTo as $r) { | ||||
|             if (!is_null(Input::get($r))) { | ||||
|                 $preFilled[$r] = Input::get($r); | ||||
|             } | ||||
|             $preFilled[$r] = Input::get($r); | ||||
|         } | ||||
|         Session::put('preFilled', $preFilled); | ||||
|  | ||||
| @@ -119,10 +117,11 @@ class TransactionController extends Controller | ||||
|         $what         = strtolower($journal->transactiontype->type); | ||||
|         $accounts     = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account'])); | ||||
|         $budgets      = ExpandedForm::makeSelectList(Auth::user()->budgets()->get()); | ||||
|         $budgets[0]   = '(no budget)'; | ||||
|         $budgets[0]   = trans('form.noBudget'); | ||||
|         $transactions = $journal->transactions()->orderBy('amount', 'DESC')->get(); | ||||
|         $piggies      = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get()); | ||||
|         $piggies[0]   = '(no piggy bank)'; | ||||
|         $piggies[0]   = trans('form.noPiggybank'); | ||||
|         $subTitle     = trans('breadcrumbs.edit_journal', ['description' => $journal->description]); | ||||
|         $preFilled    = [ | ||||
|             'date'          => $journal->date->format('Y-m-d'), | ||||
|             'category'      => '', | ||||
| @@ -150,7 +149,7 @@ class TransactionController extends Controller | ||||
|             $preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id; | ||||
|         } | ||||
|  | ||||
|         $preFilled['amount']          = $journal->amount; | ||||
|         $preFilled['amount']          = $journal->actualAmount; | ||||
|         $preFilled['account_id']      = $journal->assetAccount->id; | ||||
|         $preFilled['expense_account'] = $transactions[0]->account->name; | ||||
|         $preFilled['revenue_account'] = $transactions[1]->account->name; | ||||
| @@ -182,19 +181,19 @@ class TransactionController extends Controller | ||||
|             case 'expenses': | ||||
|             case 'withdrawal': | ||||
|                 $subTitleIcon = 'fa-long-arrow-left'; | ||||
|                 $subTitle     = 'Expenses'; | ||||
|                 $subTitle     = trans('firefly.expenses'); | ||||
|                 $types        = ['Withdrawal']; | ||||
|                 break; | ||||
|             case 'revenue': | ||||
|             case 'deposit': | ||||
|                 $subTitleIcon = 'fa-long-arrow-right'; | ||||
|                 $subTitle     = 'Revenue, income and deposits'; | ||||
|                 $subTitle     = trans('firefly.income'); | ||||
|                 $types        = ['Deposit']; | ||||
|                 break; | ||||
|             case 'transfer': | ||||
|             case 'transfers': | ||||
|                 $subTitleIcon = 'fa-exchange'; | ||||
|                 $subTitle     = 'Transfers'; | ||||
|                 $subTitle     = trans('firefly.transfers'); | ||||
|                 $types        = ['Transfer']; | ||||
|                 break; | ||||
|         } | ||||
| @@ -249,7 +248,7 @@ class TransactionController extends Controller | ||||
|                 $t->after  = $t->before + $t->amount; | ||||
|             } | ||||
|         ); | ||||
|         $subTitle = e($journal->transactiontype->type) . ' "' . e($journal->description) . '"'; | ||||
|         $subTitle = trans('firefly.' . $journal->transactiontype->type) . ' "' . e($journal->description) . '"'; | ||||
|  | ||||
|         return view('transactions.show', compact('journal', 'subTitle')); | ||||
|     } | ||||
| @@ -269,7 +268,9 @@ class TransactionController extends Controller | ||||
|         // rescan journal, UpdateJournalConnection | ||||
|         event(new JournalSaved($journal)); | ||||
|         // ConnectJournalToPiggyBank | ||||
|         event(new JournalCreated($journal, intval($request->get('piggy_bank_id')))); | ||||
|         if ($journal->transactionType->type == 'Transfer' && intval($request->get('piggy_bank_id')) > 0) { | ||||
|             event(new JournalCreated($journal, intval($request->get('piggy_bank_id')))); | ||||
|         } | ||||
|  | ||||
|         $repository->deactivateReminder($request->get('reminder_id')); | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,12 @@ | ||||
| <?php namespace FireflyIII\Http\Middleware; | ||||
|  | ||||
| use App; | ||||
| use Closure; | ||||
| use Config; | ||||
| use FireflyIII\Models\Preference; | ||||
| use Illuminate\Contracts\Auth\Guard; | ||||
| use Illuminate\Http\Request; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class Authenticate | ||||
| @@ -48,6 +52,11 @@ class Authenticate | ||||
|                 return redirect()->guest('auth/login'); | ||||
|             } | ||||
|         } | ||||
|         // if logged in, set user language: | ||||
|         $pref = Preferences::get('language', 'en'); | ||||
|         App::setLocale($pref->data); | ||||
|  | ||||
|         setlocale(LC_TIME, Config::get('firefly.locales.' . $pref->data)); | ||||
|  | ||||
|         return $next($request); | ||||
|     } | ||||
|   | ||||
| @@ -3,7 +3,6 @@ | ||||
| namespace FireflyIII\Http\Middleware; | ||||
|  | ||||
|  | ||||
| use App; | ||||
| use Closure; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\PiggyBankRepetition; | ||||
| @@ -53,16 +52,15 @@ class PiggyBanks | ||||
|                               ->leftJoin('piggy_bank_repetitions', 'piggy_banks.id', '=', 'piggy_bank_repetitions.piggy_bank_id') | ||||
|                               ->whereNull('piggy_bank_repetitions.id') | ||||
|                               ->get(['piggy_banks.id', 'piggy_banks.startdate', 'piggy_banks.targetdate']); | ||||
|             if ($set->count() > 0) { | ||||
|                 /** @var PiggyBank $partialPiggy */ | ||||
|                 foreach ($set as $partialPiggy) { | ||||
|                     $repetition = new PiggyBankRepetition; | ||||
|                     $repetition->piggyBank()->associate($partialPiggy); | ||||
|                     $repetition->startdate     = is_null($partialPiggy->startdate) ? null : $partialPiggy->startdate; | ||||
|                     $repetition->targetdate    = is_null($partialPiggy->targetdate) ? null : $partialPiggy->targetdate; | ||||
|                     $repetition->currentamount = 0; | ||||
|                     $repetition->save(); | ||||
|                 } | ||||
|  | ||||
|             /** @var PiggyBank $partialPiggy */ | ||||
|             foreach ($set as $partialPiggy) { | ||||
|                 $repetition = new PiggyBankRepetition; | ||||
|                 $repetition->piggyBank()->associate($partialPiggy); | ||||
|                 $repetition->startdate     = $partialPiggy->startdate; | ||||
|                 $repetition->targetdate    = $partialPiggy->targetdate; | ||||
|                 $repetition->currentamount = 0; | ||||
|                 $repetition->save(); | ||||
|             } | ||||
|             unset($partialPiggy, $set, $repetition); | ||||
|         } | ||||
|   | ||||
| @@ -43,6 +43,7 @@ class Range | ||||
|      * | ||||
|      * @param  \Illuminate\Http\Request $request | ||||
|      * @param  \Closure                 $theNext | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
| @@ -54,18 +55,15 @@ class Range | ||||
|             if (!Session::has('start') && !Session::has('end')) { | ||||
|  | ||||
|                 /** @var \FireflyIII\Models\Preference $viewRange */ | ||||
|                 $viewRange = Preferences::get('viewRange', '1M'); | ||||
|                 $viewRange = Preferences::get('viewRange', '1M')->data; | ||||
|                 $start     = new Carbon; | ||||
|                 $start     = Navigation::updateStartDate($viewRange->data, $start); | ||||
|                 $end       = Navigation::updateEndDate($viewRange->data, $start); | ||||
|                 $start     = Navigation::updateStartDate($viewRange, $start); | ||||
|                 $end       = Navigation::updateEndDate($viewRange, $start); | ||||
|  | ||||
|                 Session::put('start', $start); | ||||
|                 Session::put('end', $end); | ||||
|             } | ||||
|             if (!Session::has('first')) { | ||||
|                 /** | ||||
|                  * Get helper thing. | ||||
|                  */ | ||||
|                 /** @var \FireflyIII\Repositories\Journal\JournalRepositoryInterface $repository */ | ||||
|                 $repository = App::make('FireflyIII\Repositories\Journal\JournalRepositoryInterface'); | ||||
|                 $journal    = $repository->first(); | ||||
| @@ -75,16 +73,12 @@ class Range | ||||
|                     Session::put('first', Carbon::now()->startOfYear()); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // set current / next / prev month. | ||||
|             $current = Carbon::now()->format('F Y'); | ||||
|             $next    = Carbon::now()->endOfMonth()->addDay()->format('F Y'); | ||||
|             $prev    = Carbon::now()->startOfMonth()->subDay()->format('F Y'); | ||||
|             $current = Carbon::now()->formatLocalized('%B %Y'); | ||||
|             $next    = Carbon::now()->endOfMonth()->addDay()->formatLocalized('%B %Y'); | ||||
|             $prev    = Carbon::now()->startOfMonth()->subDay()->formatLocalized('%B %Y'); | ||||
|             View::share('currentMonthName', $current); | ||||
|             View::share('previousMonthName', $prev); | ||||
|             View::share('nextMonthName', $next); | ||||
|  | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $theNext($request); | ||||
|   | ||||
| @@ -49,33 +49,22 @@ class Reminders | ||||
|         if ($this->auth->check() && !$request->isXmlHttpRequest()) { | ||||
|             // do reminders stuff. | ||||
|             $piggyBanks = $this->auth->user()->piggyBanks()->where('remind_me', 1)->get(); | ||||
|             $today      = new Carbon; | ||||
|             /** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface $helper */ | ||||
|             $helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface'); | ||||
|  | ||||
|             /** @var PiggyBank $piggyBank */ | ||||
|             foreach ($piggyBanks as $piggyBank) { | ||||
|                 $ranges = $helper->getReminderRanges($piggyBank); | ||||
|  | ||||
|                 foreach ($ranges as $range) { | ||||
|                     if ($today < $range['end'] && $today > $range['start']) { | ||||
|                         // create a reminder here! | ||||
|                         $helper->createReminder($piggyBank, $range['start'], $range['end']); | ||||
|                         // stop looping, we're done. | ||||
|                         break; | ||||
|                     } | ||||
|  | ||||
|                 } | ||||
|                 $helper->createReminders($piggyBank, new Carbon); | ||||
|             } | ||||
|             // delete invalid reminders | ||||
|             $set = $this->auth->user()->reminders()->leftJoin('piggy_banks', 'piggy_banks.id', '=', 'remindersable_id')->whereNull('piggy_banks.id')->get( | ||||
|                 ['reminders.id'] | ||||
|             ); | ||||
|             foreach ($set as $reminder) { | ||||
|                 $reminder->delete(); | ||||
|             // this is a construction SQLITE cannot handle :( | ||||
|             if (env('DB_CONNECTION') != 'sqlite') { | ||||
|                 Reminder::whereUserId($this->auth->user()->id) | ||||
|                         ->leftJoin('piggy_banks', 'piggy_banks.id', '=', 'remindersable_id') | ||||
|                         ->whereNull('piggy_banks.id') | ||||
|                         ->delete(); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             // get and list active reminders: | ||||
|             $reminders = $this->auth->user()->reminders()->today()->get(); | ||||
|             $reminders->each( | ||||
|   | ||||
| @@ -50,12 +50,11 @@ class JournalFormRequest extends Request | ||||
|     /** | ||||
|      * @return array | ||||
|      * @throws Exception | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     public function rules() | ||||
|     { | ||||
|         // can we switch on the "what"? | ||||
|         $what = Input::get('what'); | ||||
|  | ||||
|         $what  = Input::get('what'); | ||||
|         $rules = [ | ||||
|             'description'        => 'required|min:1,max:255', | ||||
|             'what'               => 'required|in:withdrawal,deposit,transfer', | ||||
| @@ -74,8 +73,6 @@ class JournalFormRequest extends Request | ||||
|                 if (intval(Input::get('budget_id')) != 0) { | ||||
|                     $rules['budget_id'] = 'exists:budgets,id|belongsToUser:budgets'; | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 break; | ||||
|             case 'deposit': | ||||
|                 $rules['category']        = 'between:1,255'; | ||||
| @@ -93,7 +90,5 @@ class JournalFormRequest extends Request | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|  | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -48,6 +48,7 @@ class TagFormRequest extends Request | ||||
|             'date'        => 'date', | ||||
|             'latitude'    => 'numeric|min:-90|max:90', | ||||
|             'longitude'   => 'numeric|min:-90|max:90', | ||||
|             'zoomLevel'   => 'numeric|min:0|max:80', | ||||
|             'tagMode'     => 'required|in:nothing,balancingAct,advancePayment' | ||||
|         ]; | ||||
|     } | ||||
|   | ||||
| @@ -20,7 +20,7 @@ Breadcrumbs::register( | ||||
|     'home', | ||||
|     function (Generator $breadcrumbs) { | ||||
|  | ||||
|         $breadcrumbs->push('Home', route('index')); | ||||
|         $breadcrumbs->push(trans('breadcrumbs.home'), route('index')); | ||||
|     } | ||||
| ); | ||||
|  | ||||
| @@ -28,38 +28,32 @@ Breadcrumbs::register( | ||||
|     'index', | ||||
|     function (Generator $breadcrumbs) { | ||||
|  | ||||
|         $breadcrumbs->push('Home', route('index')); | ||||
|         $breadcrumbs->push(trans('breadcrumbs.home'), route('index')); | ||||
|     } | ||||
| ); | ||||
| //trans('breadcrumbs.') | ||||
|  | ||||
| // accounts | ||||
| Breadcrumbs::register( | ||||
|     'accounts.index', function (Generator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push(ucfirst(e($what)) . ' accounts', route('accounts.index', $what)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.' . strtolower(e($what)) . '_accounts'), route('accounts.index', $what)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'accounts.create', function (Generator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('accounts.index', $what); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.new_' . strtolower(e($what)) . '_account'), route('accounts.create', $what)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'accounts.show', function (Generator $breadcrumbs, Account $account) { | ||||
|     switch ($account->accountType->type) { | ||||
|         default: | ||||
|             throw new FireflyException('Cannot handle account type "' . e($account->accountType->type) . '"'); | ||||
|             break; | ||||
|         case 'Default account': | ||||
|         case 'Asset account': | ||||
|             $what = 'asset'; | ||||
|             break; | ||||
|         case 'Cash account': | ||||
|             $what = 'cash'; | ||||
|             break; | ||||
|         case 'Expense account': | ||||
|         case 'Beneficiary account': | ||||
|             $what = 'expense'; | ||||
|             break; | ||||
|         case 'Revenue account': | ||||
|             $what = 'revenue'; | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     $what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|  | ||||
|  | ||||
|     $breadcrumbs->parent('accounts.index', $what); | ||||
|     $breadcrumbs->push(e($account->name), route('accounts.show', $account->id)); | ||||
| } | ||||
| @@ -67,14 +61,17 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'accounts.delete', function (Generator $breadcrumbs, Account $account) { | ||||
|     $breadcrumbs->parent('accounts.show', $account); | ||||
|     $breadcrumbs->push('Delete ' . e($account->name), route('accounts.delete', $account->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_account', ['name' => e($account->name)]), route('accounts.delete', $account->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'accounts.edit', function (Generator $breadcrumbs, Account $account) { | ||||
|     $breadcrumbs->parent('accounts.show', $account); | ||||
|     $breadcrumbs->push('Edit ' . e($account->name), route('accounts.edit', $account->id)); | ||||
|     $what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|  | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_'.$what.'_account', ['name' => e($account->name)]), route('accounts.edit', $account->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| @@ -82,26 +79,26 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'budgets.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Budgets', route('budgets.index')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.budgets'), route('budgets.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'budgets.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('budgets.index'); | ||||
|     $breadcrumbs->push('Create new budget', route('budgets.create')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.newBudget'), route('budgets.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'budgets.edit', function (Generator $breadcrumbs, Budget $budget) { | ||||
|     $breadcrumbs->parent('budgets.show', $budget); | ||||
|     $breadcrumbs->push('Edit ' . e($budget->name), route('budgets.edit', $budget->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_budget', ['name' => e($budget->name)]), route('budgets.edit', $budget->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'budgets.delete', function (Generator $breadcrumbs, Budget $budget) { | ||||
|     $breadcrumbs->parent('budgets.show', $budget); | ||||
|     $breadcrumbs->push('Delete ' . e($budget->name), route('budgets.delete', $budget->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_budget', ['name' => e($budget->name)]), route('budgets.delete', $budget->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| @@ -128,26 +125,26 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'categories.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Categories', route('categories.index')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.categories'), route('categories.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'categories.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('categories.index'); | ||||
|     $breadcrumbs->push('Create new category', route('categories.create')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.newCategory'), route('categories.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'categories.edit', function (Generator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.show', $category); | ||||
|     $breadcrumbs->push('Edit ' . e($category->name), route('categories.edit', $category->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_category', ['name' => e($category->name)]), route('categories.edit', $category->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'categories.delete', function (Generator $breadcrumbs, Category $category) { | ||||
|     $breadcrumbs->parent('categories.show', $category); | ||||
|     $breadcrumbs->push('Delete ' . e($category->name), route('categories.delete', $category->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_category', ['name' => e($category->name)]), route('categories.delete', $category->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| @@ -170,20 +167,20 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'currency.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Currencies', route('currency.index')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.currencies'), route('currency.index')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'currency.edit', function (Generator $breadcrumbs, TransactionCurrency $currency) { | ||||
|     $breadcrumbs->parent('currency.index'); | ||||
|     $breadcrumbs->push('Edit ' . $currency->name, route('currency.edit', $currency->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_currency', ['name' => e($currency->name)]), route('currency.edit', $currency->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'currency.delete', function (Generator $breadcrumbs, TransactionCurrency $currency) { | ||||
|     $breadcrumbs->parent('currency.index'); | ||||
|     $breadcrumbs->push('Delete ' . $currency->name, route('currency.delete', $currency->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_currency', ['name' => e($currency->name)]), route('currency.delete', $currency->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| @@ -192,26 +189,26 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Piggy banks', route('piggy-banks.index')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.piggyBanks'), route('piggy-banks.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('piggy-banks.index'); | ||||
|     $breadcrumbs->push('Create new piggy bank', route('piggy-banks.create')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.newPiggyBank'), route('piggy-banks.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggy-banks.show', $piggyBank); | ||||
|     $breadcrumbs->push('Edit ' . e($piggyBank->name), route('piggy-banks.edit', $piggyBank->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_piggyBank', ['name' => e($piggyBank->name)]), route('piggy-banks.edit', $piggyBank->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'piggy-banks.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) { | ||||
|     $breadcrumbs->parent('piggy-banks.show', $piggyBank); | ||||
|     $breadcrumbs->push('Delete ' . e($piggyBank->name), route('piggy-banks.delete', $piggyBank->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_piggyBank', ['name' => e($piggyBank->name)]), route('piggy-banks.delete', $piggyBank->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| @@ -227,7 +224,7 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'preferences', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Preferences', route('preferences')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.preferences'), route('preferences')); | ||||
|  | ||||
| } | ||||
| ); | ||||
| @@ -236,14 +233,14 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'profile', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Profile', route('profile')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.profile'), route('profile')); | ||||
|  | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'change-password', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('profile'); | ||||
|     $breadcrumbs->push('Change your password', route('change-password')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.changePassword'), route('change-password')); | ||||
|  | ||||
| } | ||||
| ); | ||||
| @@ -252,26 +249,26 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'bills.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Bills', route('bills.index')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.bills'), route('bills.index')); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'bills.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('bills.index'); | ||||
|     $breadcrumbs->push('Create new bill', route('bills.create')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.newBill'), route('bills.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'bills.edit', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.show', $bill); | ||||
|     $breadcrumbs->push('Edit ' . e($bill->name), route('bills.edit', $bill->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_bill', ['name' => e($bill->name)]), route('bills.edit', $bill->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'bills.delete', function (Generator $breadcrumbs, Bill $bill) { | ||||
|     $breadcrumbs->parent('bills.show', $bill); | ||||
|     $breadcrumbs->push('Delete ' . e($bill->name), route('bills.delete', $bill->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_bill', ['name' => e($bill->name)]), route('bills.delete', $bill->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| @@ -287,7 +284,7 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'reminders.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Reminders', route('reminders.index')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.reminders'), route('reminders.index')); | ||||
|  | ||||
| } | ||||
| ); | ||||
| @@ -296,7 +293,7 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) { | ||||
|     $breadcrumbs->parent('reminders.index'); | ||||
|     $breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.reminder', ['id' => e($reminder->id)]), route('reminders.show', $reminder->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
| @@ -306,28 +303,33 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'reports.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Reports', route('reports.index')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.reports'), route('reports.index')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.year', function (Generator $breadcrumbs, Carbon $date) { | ||||
|     'reports.year', function (Generator $breadcrumbs, Carbon $date, $shared) { | ||||
|     $breadcrumbs->parent('reports.index'); | ||||
|     $breadcrumbs->push($date->year, route('reports.year', $date->year)); | ||||
|     if ($shared) { | ||||
|         $title = trans('breadcrumbs.yearly_report_shared', ['date' => $date->year]); | ||||
|     } else { | ||||
|         $title = trans('breadcrumbs.yearly_report', ['date' => $date->year]); | ||||
|     } | ||||
|     $breadcrumbs->push($title, route('reports.year', $date->year)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.month', function (Generator $breadcrumbs, Carbon $date) { | ||||
|     $breadcrumbs->parent('reports.year', $date); | ||||
|     $breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', [$date->year, $date->month])); | ||||
| } | ||||
| ); | ||||
|     'reports.month', function (Generator $breadcrumbs, Carbon $date, $shared) { | ||||
|     $breadcrumbs->parent('reports.year', $date, $shared); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'reports.budget', function (Generator $breadcrumbs, Carbon $date) { | ||||
|     $breadcrumbs->parent('reports.index'); | ||||
|     $breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', [$date->year, $date->month])); | ||||
|     if ($shared) { | ||||
|         $title = trans('breadcrumbs.monthly_report_shared', ['date' => $date->year]); | ||||
|     } else { | ||||
|         $title = trans('breadcrumbs.monthly_report', ['date' => $date->year]); | ||||
|     } | ||||
|  | ||||
|     $breadcrumbs->push($title, route('reports.month', [$date->year, $date->month])); | ||||
| } | ||||
| ); | ||||
|  | ||||
| @@ -335,7 +337,7 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'search', function (Generator $breadcrumbs, $query) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Search for "' . e($query) . '"', route('search')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.searchResult', ['query' => e($query)]), route('search')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| @@ -343,47 +345,26 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'transactions.index', function (Generator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|  | ||||
|     switch ($what) { | ||||
|         case 'expenses': | ||||
|         case 'withdrawal': | ||||
|             $subTitle = 'Expenses'; | ||||
|             break; | ||||
|         case 'revenue': | ||||
|         case 'deposit': | ||||
|             $subTitle = 'Revenue, income and deposits'; | ||||
|             break; | ||||
|         case 'transfer': | ||||
|         case 'transfers': | ||||
|             $subTitle = 'Transfers'; | ||||
|             break; | ||||
|         case 'opening balance': | ||||
|             $subTitle = 'Opening balances'; | ||||
|             break; | ||||
|         default: | ||||
|             throw new FireflyException('Cannot handle $what "' . e($what) . '" in bread crumbs'); | ||||
|     } | ||||
|  | ||||
|     $breadcrumbs->push($subTitle, route('transactions.index', $what)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.' . $what . '_list'), route('transactions.index', $what)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'transactions.create', function (Generator $breadcrumbs, $what) { | ||||
|     $breadcrumbs->parent('transactions.index', $what); | ||||
|     $breadcrumbs->push('Create new ' . e($what), route('transactions.create', $what)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.create_' . e($what)), route('transactions.create', $what)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'transactions.edit', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|     $breadcrumbs->parent('transactions.show', $journal); | ||||
|     $breadcrumbs->push('Edit ' . e($journal->description), route('transactions.edit', $journal->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_journal', ['description' => $journal->description]), route('transactions.edit', $journal->id)); | ||||
| } | ||||
| ); | ||||
| Breadcrumbs::register( | ||||
|     'transactions.delete', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|     $breadcrumbs->parent('transactions.show', $journal); | ||||
|     $breadcrumbs->push('Delete ' . e($journal->description), route('transactions.delete', $journal->id)); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_journal', ['description' => e($journal->description)]), route('transactions.delete', $journal->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| @@ -391,7 +372,7 @@ Breadcrumbs::register( | ||||
|     'transactions.show', function (Generator $breadcrumbs, TransactionJournal $journal) { | ||||
|  | ||||
|     $breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type)); | ||||
|     $breadcrumbs->push(e($journal->description), route('transactions.show', $journal->id)); | ||||
|     $breadcrumbs->push($journal->description, route('transactions.show', $journal->id)); | ||||
|  | ||||
| } | ||||
| ); | ||||
| @@ -400,16 +381,32 @@ Breadcrumbs::register( | ||||
| Breadcrumbs::register( | ||||
|     'tags.index', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('home'); | ||||
|     $breadcrumbs->push('Tags', route('tags.index')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.tags'), route('tags.index')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'tags.create', function (Generator $breadcrumbs) { | ||||
|     $breadcrumbs->parent('tags.index'); | ||||
|     $breadcrumbs->push('Create tag', route('tags.create')); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.createTag'), route('tags.create')); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'tags.edit', function (Generator $breadcrumbs, Tag $tag) { | ||||
|     $breadcrumbs->parent('tags.show', $tag); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.edit_tag', ['tag' => e($tag->tag)]), route('tags.edit', $tag->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'tags.delete', function (Generator $breadcrumbs, Tag $tag) { | ||||
|     $breadcrumbs->parent('tags.show', $tag); | ||||
|     $breadcrumbs->push(trans('breadcrumbs.delete_tag', ['tag' => e($tag->tag)]), route('tags.delete', $tag->id)); | ||||
| } | ||||
| ); | ||||
|  | ||||
|  | ||||
| Breadcrumbs::register( | ||||
|     'tags.show', function (Generator $breadcrumbs, Tag $tag) { | ||||
|     $breadcrumbs->parent('tags.index'); | ||||
|   | ||||
| @@ -223,7 +223,6 @@ Route::group( | ||||
|     Route::get('/bills/rescan/{bill}', ['uses' => 'BillController@rescan', 'as' => 'bills.rescan']); # rescan for matching. | ||||
|     Route::get('/bills/create', ['uses' => 'BillController@create', 'as' => 'bills.create']); | ||||
|     Route::get('/bills/edit/{bill}', ['uses' => 'BillController@edit', 'as' => 'bills.edit']); | ||||
|     Route::get('/bills/add/{bill}', ['uses' => 'BillController@add', 'as' => 'bills.add']); | ||||
|     Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']); | ||||
|     Route::get('/bills/show/{bill}', ['uses' => 'BillController@show', 'as' => 'bills.show']); | ||||
|     Route::post('/bills/store', ['uses' => 'BillController@store', 'as' => 'bills.store']); | ||||
| @@ -273,22 +272,41 @@ Route::group( | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Google Chart Controller | ||||
|      * ALL CHART Controllers | ||||
|      */ | ||||
|     Route::get('/chart/home/account', ['uses' => 'GoogleChartController@allAccountsBalanceChart']); | ||||
|     Route::get('/chart/home/budgets', ['uses' => 'GoogleChartController@allBudgetsHomeChart']); | ||||
|     Route::get('/chart/home/categories', ['uses' => 'GoogleChartController@allCategoriesHomeChart']); | ||||
|     Route::get('/chart/home/bills', ['uses' => 'GoogleChartController@billsOverview']); | ||||
|     Route::get('/chart/account/{account}/{view?}', ['uses' => 'GoogleChartController@accountBalanceChart']); | ||||
|     Route::get('/chart/budget/{budget}/spending/{year?}', ['uses' => 'GoogleChartController@budgetsAndSpending']); | ||||
|     Route::get('/chart/budgets/spending/{year?}', ['uses' => 'GoogleChartController@allBudgetsAndSpending'])->where(['year' => '[0-9]+']); | ||||
|     Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'GoogleChartController@budgetLimitSpending']); | ||||
|     Route::get('/chart/reports/income-expenses/{year}', ['uses' => 'GoogleChartController@yearInExp']); | ||||
|     Route::get('/chart/reports/income-expenses-sum/{year}', ['uses' => 'GoogleChartController@yearInExpSum']); | ||||
|     Route::get('/chart/bills/{bill}', ['uses' => 'GoogleChartController@billOverview']); | ||||
|     Route::get('/chart/piggy-history/{piggyBank}', ['uses' => 'GoogleChartController@piggyBankHistory']); | ||||
|     Route::get('/chart/category/{category}/period', ['uses' => 'GoogleChartController@categoryPeriodChart']); | ||||
|     Route::get('/chart/category/{category}/overview', ['uses' => 'GoogleChartController@categoryOverviewChart']); | ||||
|     // accounts: | ||||
|     Route::get('/chart/account/frontpage', ['uses' => 'Chart\AccountController@frontpage']); | ||||
|     Route::get('/chart/account/month/{year}/{month}/{shared?}', ['uses' => 'Chart\AccountController@all'])->where( | ||||
|         ['year' => '[0-9]{4}', 'month' => '[0-9]{1,2}', 'shared' => 'shared'] | ||||
|     ); | ||||
|     Route::get('/chart/account/{account}', ['uses' => 'Chart\AccountController@single']); | ||||
|  | ||||
|  | ||||
|     // bills: | ||||
|     Route::get('/chart/bill/frontpage', ['uses' => 'Chart\BillController@frontpage']); | ||||
|     Route::get('/chart/bill/{bill}', ['uses' => 'Chart\BillController@single']); | ||||
|  | ||||
|     // budgets: | ||||
|     Route::get('/chart/budget/frontpage', ['uses' => 'Chart\BudgetController@frontpage']); | ||||
|     Route::get('/chart/budget/year/{year}/{shared?}', ['uses' => 'Chart\BudgetController@year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']); | ||||
|     Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'Chart\BudgetController@budgetLimit']); | ||||
|     Route::get('/chart/budget/{budget}', ['uses' => 'Chart\BudgetController@budget']); | ||||
|  | ||||
|     // categories: | ||||
|     Route::get('/chart/category/frontpage', ['uses' => 'Chart\CategoryController@frontpage']); | ||||
|     Route::get('/chart/category/year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']); | ||||
|     Route::get('/chart/category/{category}/month', ['uses' => 'Chart\CategoryController@month']); // should be period. | ||||
|     Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']); | ||||
|  | ||||
|     // piggy banks: | ||||
|     Route::get('/chart/piggyBank/{piggyBank}', ['uses' => 'Chart\PiggyBankController@history']); | ||||
|  | ||||
|     // reports: | ||||
|     Route::get('/chart/report/in-out/{year}/{shared?}', ['uses' => 'Chart\ReportController@yearInOut'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']); | ||||
|     Route::get('/chart/report/in-out-sum/{year}/{shared?}', ['uses' => 'Chart\ReportController@yearInOutSummarized'])->where( | ||||
|         ['year' => '[0-9]{4}', 'shared' => 'shared'] | ||||
|     ); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Help Controller | ||||
| @@ -306,10 +324,7 @@ Route::group( | ||||
|     Route::get('/json/box/out', ['uses' => 'JsonController@boxOut', 'as' => 'json.box.out']); | ||||
|     Route::get('/json/box/bills-unpaid', ['uses' => 'JsonController@boxBillsUnpaid', 'as' => 'json.box.paid']); | ||||
|     Route::get('/json/box/bills-paid', ['uses' => 'JsonController@boxBillsPaid', 'as' => 'json.box.unpaid']); | ||||
|     Route::get('/json/show-shared-reports', 'JsonController@showSharedReports'); | ||||
|     Route::get('/json/transaction-journals/{what}', 'JsonController@transactionJournals'); | ||||
|     Route::get('/json/show-shared-reports/set', 'JsonController@setSharedReports'); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Piggy Bank Controller | ||||
| @@ -355,19 +370,13 @@ Route::group( | ||||
|      * Report Controller | ||||
|      */ | ||||
|     Route::get('/reports', ['uses' => 'ReportController@index', 'as' => 'reports.index']); | ||||
|     Route::get('/reports/{year}', ['uses' => 'ReportController@year', 'as' => 'reports.year']); | ||||
|     Route::get('/reports/{year}/{month}', ['uses' => 'ReportController@month', 'as' => 'reports.month']); | ||||
|     Route::get('/reports/budget/{year}/{month}', ['uses' => 'ReportController@budget', 'as' => 'reports.budget']); | ||||
|     //Route::get('/reports/{year}', ['uses' => 'ReportController@year', 'as' => 'reports.year'])->where(['year' => '[0-9]{4}']); | ||||
|     Route::get('/reports/{year}/{shared?}', ['uses' => 'ReportController@year', 'as' => 'reports.year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']); | ||||
|     Route::get('/reports/{year}/{month}/{shared?}', ['uses' => 'ReportController@month', 'as' => 'reports.month'])->where( | ||||
|         ['year' => '[0-9]{4}', 'month' => '[0-9]{1,2}', 'shared' => 'shared'] | ||||
|     ); | ||||
|  | ||||
|     // pop ups for budget report: | ||||
|     Route::get('/reports/modal/{account}/{year}/{month}/no-budget', ['uses' => 'ReportController@modalNoBudget', 'as' => 'reports.no-budget']); | ||||
|     Route::get( | ||||
|         '/reports/modal/{account}/{year}/{month}/balanced-transfers', | ||||
|         ['uses' => 'ReportController@modalBalancedTransfers', 'as' => 'reports.balanced-transfers'] | ||||
|     ); | ||||
|     Route::get( | ||||
|         '/reports/modal/{account}/{year}/{month}/left-unbalanced', ['uses' => 'ReportController@modalLeftUnbalanced', 'as' => 'reports.left-unbalanced'] | ||||
|     ); | ||||
|  | ||||
|     /** | ||||
|      * Search Controller | ||||
|   | ||||
| @@ -28,7 +28,7 @@ class Account extends Model | ||||
|  | ||||
|     /** | ||||
|      * @param array $fields | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * | ||||
|      * @return Account|null | ||||
|      */ | ||||
| @@ -133,6 +133,7 @@ class Account extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return string | ||||
| @@ -160,6 +161,7 @@ class Account extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param array           $types | ||||
|      */ | ||||
| @@ -174,6 +176,7 @@ class Account extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param string          $name | ||||
|      * @param string          $value | ||||
| @@ -191,6 +194,7 @@ class Account extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setNameAttribute($value) | ||||
|   | ||||
| @@ -37,6 +37,7 @@ class Category extends Model | ||||
|  | ||||
|     /** | ||||
|      * @param array $fields | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * | ||||
|      * @return Account|null | ||||
|      */ | ||||
| @@ -79,6 +80,7 @@ class Category extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setNameAttribute($value) | ||||
| @@ -89,6 +91,7 @@ class Category extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return string | ||||
|   | ||||
| @@ -64,6 +64,7 @@ class PiggyBank extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return int | ||||
| @@ -93,6 +94,7 @@ class PiggyBank extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setNameAttribute($value) | ||||
| @@ -103,6 +105,7 @@ class PiggyBank extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return string | ||||
|   | ||||
| @@ -18,6 +18,7 @@ class Reminder extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return int | ||||
| @@ -38,6 +39,7 @@ class Reminder extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return mixed | ||||
| @@ -53,6 +55,7 @@ class Reminder extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return bool | ||||
| @@ -73,6 +76,7 @@ class Reminder extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Carbon          $start | ||||
|      * @param Carbon          $end | ||||
| @@ -86,6 +90,7 @@ class Reminder extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * | ||||
|      * @return $this | ||||
| @@ -100,6 +105,7 @@ class Reminder extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setMetadataAttribute($value) | ||||
|   | ||||
| @@ -29,6 +29,8 @@ class Tag extends Model | ||||
|  | ||||
|     /** | ||||
|      * @param array $fields | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.NPathComplexity) | ||||
|      * | ||||
|      * @return Tag|null | ||||
|      */ | ||||
| @@ -77,6 +79,7 @@ class Tag extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return string | ||||
| @@ -88,6 +91,7 @@ class Tag extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return string | ||||
| @@ -99,6 +103,7 @@ class Tag extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setDescriptionAttribute($value) | ||||
| @@ -108,6 +113,7 @@ class Tag extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setTagAttribute($value) | ||||
|   | ||||
| @@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Builder as EloquentBuilder; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Database\Eloquent\Relations\HasMany; | ||||
| use Illuminate\Database\Eloquent\SoftDeletes; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Watson\Validating\ValidatingTrait; | ||||
|  | ||||
| /** | ||||
| @@ -61,20 +62,90 @@ class TransactionJournal extends Model | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getAmountAttribute() | ||||
|     public function getActualAmountAttribute() | ||||
|     { | ||||
|         $amount = 0; | ||||
|         /** @var Transaction $t */ | ||||
|         foreach ($this->transactions as $t) { | ||||
|             if ($t->amount > 0) { | ||||
|                 return floatval($t->amount); | ||||
|                 $amount = floatval($t->amount); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return 0; | ||||
|         return $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account|mixed | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getAmountAttribute() | ||||
|     { | ||||
|         $amount = 0; | ||||
|         /** @var Transaction $t */ | ||||
|         foreach ($this->transactions as $t) { | ||||
|             if ($t->amount > 0) { | ||||
|                 $amount = floatval($t->amount); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * If the journal has tags, it gets complicated. | ||||
|          */ | ||||
|         if ($this->tags->count() == 0) { | ||||
|             return $amount; | ||||
|         } | ||||
|         // if journal is part of advancePayment AND journal is a withdrawal, | ||||
|         // then journal is being repaid by other journals, so the actual amount will lower: | ||||
|         /** @var Tag $advancePayment */ | ||||
|         $advancePayment = $this->tags()->where('tagMode', 'advancePayment')->first(); | ||||
|         if ($advancePayment && $this->transactionType->type == 'Withdrawal') { | ||||
|  | ||||
|             // loop other deposits, remove from our amount. | ||||
|             $others = $advancePayment->transactionJournals()->transactionTypes(['Deposit'])->get(); | ||||
|             foreach ($others as $other) { | ||||
|                 $amount -= $other->actualAmount; | ||||
|             } | ||||
|  | ||||
|             return $amount; | ||||
|         } | ||||
|  | ||||
|         // if this journal is part of an advancePayment AND the journal is a deposit, | ||||
|         // then the journal amount is correcting a withdrawal, and the amount is zero: | ||||
|         if ($advancePayment && $this->transactionType->type == 'Deposit') { | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         // is balancing act? | ||||
|         $balancingAct = $this->tags()->where('tagMode', 'balancingAct')->first(); | ||||
|         if ($balancingAct) { | ||||
|             // this is the transfer | ||||
|  | ||||
|             // this is the expense: | ||||
|             if ($this->transactionType->type == 'Withdrawal') { | ||||
|                 $transfer = $balancingAct->transactionJournals()->transactionTypes(['Transfer'])->first(); | ||||
|                 if ($transfer) { | ||||
|                     $amount -= $transfer->actualAmount; | ||||
|  | ||||
|                     return $amount; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | ||||
|      */ | ||||
|     public function tags() | ||||
|     { | ||||
|         return $this->belongsToMany('FireflyIII\Models\Tag'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return Account | ||||
|      */ | ||||
|     public function getAssetAccountAttribute() | ||||
|     { | ||||
| @@ -93,7 +164,7 @@ class TransactionJournal extends Model | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return $this->transactions()->first(); | ||||
|         return $this->transactions()->first()->account; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -105,6 +176,28 @@ class TransactionJournal extends Model | ||||
|         return $this->hasMany('FireflyIII\Models\Transaction'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return float | ||||
|      */ | ||||
|     public function getCorrectedActualAmountAttribute() | ||||
|     { | ||||
|         $amount = 0; | ||||
|         $type   = $this->transactionType->type; | ||||
|         /** @var Transaction $t */ | ||||
|         foreach ($this->transactions as $t) { | ||||
|             if ($t->amount > 0 && $type != 'Withdrawal') { | ||||
|                 $amount = floatval($t->amount); | ||||
|                 break; | ||||
|             } | ||||
|             if ($t->amount < 0 && $type == 'Withdrawal') { | ||||
|                 $amount = floatval($t->amount); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return array | ||||
| @@ -116,6 +209,7 @@ class TransactionJournal extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      * | ||||
|      * @return string | ||||
| @@ -140,6 +234,7 @@ class TransactionJournal extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Account         $account | ||||
|      */ | ||||
| @@ -154,6 +249,7 @@ class TransactionJournal extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Carbon          $date | ||||
|      * | ||||
| @@ -166,6 +262,7 @@ class TransactionJournal extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Carbon          $date | ||||
|      * | ||||
| @@ -178,6 +275,7 @@ class TransactionJournal extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param                 $amount | ||||
|      */ | ||||
| @@ -195,6 +293,7 @@ class TransactionJournal extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Carbon          $date | ||||
|      * | ||||
| @@ -206,7 +305,26 @@ class TransactionJournal extends Model | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the account to which the money was moved. | ||||
|      * | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param Account         $account | ||||
|      */ | ||||
|     public function scopeToAccountIs(EloquentBuilder $query, Account $account) | ||||
|     { | ||||
|         $query->leftJoin( | ||||
|             'transactions', function (JoinClause $join) { | ||||
|             $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '>', 0); | ||||
|         } | ||||
|         ); | ||||
|         $query->where('transactions.account_id', $account->id); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param EloquentBuilder $query | ||||
|      * @param array           $types | ||||
|      */ | ||||
| @@ -239,6 +357,7 @@ class TransactionJournal extends Model | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * | ||||
|      * @param $value | ||||
|      */ | ||||
|     public function setDescriptionAttribute($value) | ||||
| @@ -247,15 +366,6 @@ class TransactionJournal extends Model | ||||
|         $this->attributes['encrypted']   = true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany | ||||
|      */ | ||||
|     public function tags() | ||||
|     { | ||||
|         return $this->belongsToMany('FireflyIII\Models\Tag'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @codeCoverageIgnore | ||||
|      * @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||||
|   | ||||
| @@ -17,6 +17,8 @@ class ConfigServiceProvider extends ServiceProvider | ||||
|      * to overwrite any "vendor" or package configuration that you may want to | ||||
|      * modify before the application handles the incoming request / command. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function register() | ||||
| @@ -163,6 +165,7 @@ class ConfigServiceProvider extends ServiceProvider | ||||
|                             'Session', | ||||
|                             'Route', | ||||
|                             'Auth', | ||||
|                             'Lang', | ||||
|                             'URL', | ||||
|                             'Config', | ||||
|                             'ExpandedForm' => [ | ||||
|   | ||||
| @@ -49,7 +49,47 @@ class EventServiceProvider extends ServiceProvider | ||||
|     public function boot(DispatcherContract $events) | ||||
|     { | ||||
|         parent::boot($events); | ||||
|         $this->registerDeleteEvents(); | ||||
|         $this->registerCreateEvents(); | ||||
|         BudgetLimit::saved( | ||||
|             function (BudgetLimit $budgetLimit) { | ||||
|  | ||||
|                 $end = Navigation::addPeriod(clone $budgetLimit->startdate, $budgetLimit->repeat_freq, 0); | ||||
|                 $end->subDay(); | ||||
|                 $set = $budgetLimit->limitrepetitions()->where('startdate', $budgetLimit->startdate->format('Y-m-d'))->where('enddate', $end->format('Y-m-d')) | ||||
|                                    ->get(); | ||||
|                 if ($set->count() == 0) { | ||||
|                     $repetition            = new LimitRepetition; | ||||
|                     $repetition->startdate = $budgetLimit->startdate; | ||||
|                     $repetition->enddate   = $end; | ||||
|                     $repetition->amount    = $budgetLimit->amount; | ||||
|                     $repetition->budgetLimit()->associate($budgetLimit); | ||||
|  | ||||
|                     try { | ||||
|                         $repetition->save(); | ||||
|                     } catch (QueryException $e) { | ||||
|                         Log::error('Trying to save new LimitRepetition failed!'); | ||||
|                         Log::error($e->getMessage()); | ||||
|                     } | ||||
|                 } else { | ||||
|                     if ($set->count() == 1) { | ||||
|                         $repetition         = $set->first(); | ||||
|                         $repetition->amount = $budgetLimit->amount; | ||||
|                         $repetition->save(); | ||||
|  | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     protected function registerDeleteEvents() | ||||
|     { | ||||
|         TransactionJournal::deleted( | ||||
|             function (TransactionJournal $journal) { | ||||
|  | ||||
| @@ -59,8 +99,6 @@ class EventServiceProvider extends ServiceProvider | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|         PiggyBank::deleting( | ||||
|             function (PiggyBank $piggyBank) { | ||||
|                 $reminders = $piggyBank->reminders()->get(); | ||||
| @@ -82,6 +120,14 @@ class EventServiceProvider extends ServiceProvider | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     protected function registerCreateEvents() | ||||
|     { | ||||
|  | ||||
|         // move this routine to a filter | ||||
|         // in case of repeated piggy banks and/or other problems. | ||||
|         PiggyBank::created( | ||||
| @@ -94,47 +140,6 @@ class EventServiceProvider extends ServiceProvider | ||||
|                 $repetition->save(); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         BudgetLimit::saved( | ||||
|             function (BudgetLimit $budgetLimit) { | ||||
|  | ||||
|                 $end = Navigation::addPeriod(clone $budgetLimit->startdate, $budgetLimit->repeat_freq, 0); | ||||
|                 $end->subDay(); | ||||
|  | ||||
|                 $set = $budgetLimit->limitrepetitions()->where('startdate', $budgetLimit->startdate->format('Y-m-d'))->where('enddate', $end->format('Y-m-d')) | ||||
|                                    ->get(); | ||||
|                 /* | ||||
|                  * Create new LimitRepetition: | ||||
|                  */ | ||||
|                 if ($set->count() == 0) { | ||||
|  | ||||
|                     $repetition            = new LimitRepetition; | ||||
|                     $repetition->startdate = $budgetLimit->startdate; | ||||
|                     $repetition->enddate   = $end; | ||||
|                     $repetition->amount    = $budgetLimit->amount; | ||||
|                     $repetition->budgetLimit()->associate($budgetLimit); | ||||
|  | ||||
|                     try { | ||||
|                         $repetition->save(); | ||||
|                     } catch (QueryException $e) { | ||||
|                         Log::error('Trying to save new LimitRepetition failed!'); | ||||
|                         Log::error($e->getMessage()); | ||||
|                     } | ||||
|                 } else { | ||||
|                     if ($set->count() == 1) { | ||||
|                         /* | ||||
|                          * Update existing one. | ||||
|                          */ | ||||
|                         $repetition         = $set->first(); | ||||
|                         $repetition->amount = $budgetLimit->amount; | ||||
|                         $repetition->save(); | ||||
|  | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -10,9 +10,9 @@ use FireflyIII\Support\Preferences; | ||||
| use FireflyIII\Support\Steam; | ||||
| use FireflyIII\Support\Twig\Budget; | ||||
| use FireflyIII\Support\Twig\General; | ||||
| use FireflyIII\Support\Twig\Translation; | ||||
| use FireflyIII\Support\Twig\Journal; | ||||
| use FireflyIII\Support\Twig\PiggyBank; | ||||
| use FireflyIII\Support\Twig\Translation; | ||||
| use FireflyIII\Validation\FireflyValidator; | ||||
| use Illuminate\Support\ServiceProvider; | ||||
| use Twig; | ||||
| @@ -46,6 +46,9 @@ class FireflyServiceProvider extends ServiceProvider | ||||
|         Twig::addExtension(new Translation); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      */ | ||||
|     public function register() | ||||
|     { | ||||
|  | ||||
|   | ||||
| @@ -162,8 +162,6 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|                       ->orderBy('transaction_journals.order', 'ASC') | ||||
|                       ->orderBy('transaction_journals.id', 'DESC'); | ||||
|  | ||||
|         $query->before(Session::get('end', Carbon::now()->endOfMonth())); | ||||
|         $query->after(Session::get('start', Carbon::now()->startOfMonth())); | ||||
|         $count     = $query->count(); | ||||
|         $set       = $query->take(50)->offset($offset)->get(['transaction_journals.*']); | ||||
|         $paginator = new LengthAwarePaginator($set, $count, 50, $page); | ||||
| @@ -308,12 +306,14 @@ class AccountRepository implements AccountRepositoryInterface | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $date | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function leftOnAccount(Account $account) | ||||
|     public function leftOnAccount(Account $account, Carbon $date) | ||||
|     { | ||||
|         $balance = Steam::balance($account, null, true); | ||||
|  | ||||
|         $balance = Steam::balance($account, $date, true); | ||||
|         /** @var PiggyBank $p */ | ||||
|         foreach ($account->piggybanks()->get() as $p) { | ||||
|             $balance -= $p->currentRelevantRep()->currentamount; | ||||
|   | ||||
| @@ -115,10 +115,11 @@ interface AccountRepositoryInterface | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $date | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function leftOnAccount(Account $account); | ||||
|     public function leftOnAccount(Account $account, Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * @param Account $account | ||||
|   | ||||
| @@ -22,6 +22,27 @@ use Navigation; | ||||
|  */ | ||||
| class BillRepository implements BillRepositoryInterface | ||||
| { | ||||
|     /** | ||||
|      * Returns the sum of all payments connected to this bill between the dates. | ||||
|      * | ||||
|      * @param Bill   $bill | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function billPaymentsInRange(Bill $bill, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $amount   = 0; | ||||
|         $journals = $bill->transactionjournals()->before($end)->after($start)->get(); | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         foreach ($journals as $journal) { | ||||
|             $amount += $journal->amount; | ||||
|         } | ||||
|  | ||||
|         return $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create a fake bill to help the chart controller. | ||||
|      * | ||||
| @@ -251,13 +272,10 @@ class BillRepository implements BillRepositoryInterface | ||||
|      */ | ||||
|     public function scan(Bill $bill, TransactionJournal $journal) | ||||
|     { | ||||
|         /* | ||||
|          * Match words. | ||||
|          */ | ||||
|         $amountMatch = false; | ||||
|         $wordMatch   = false; | ||||
|         $matches     = explode(',', $bill->match); | ||||
|         $description = strtolower($journal->description); | ||||
|         Log::debug('Now scanning ' . $description); | ||||
|  | ||||
|         /* | ||||
|          * Attach expense account to description for more narrow matching. | ||||
| @@ -295,7 +313,6 @@ class BillRepository implements BillRepositoryInterface | ||||
|          * Match amount. | ||||
|          */ | ||||
|  | ||||
|         $amountMatch = false; | ||||
|         if (count($transactions) > 1) { | ||||
|  | ||||
|             $amount = max(floatval($transactions[0]->amount), floatval($transactions[1]->amount)); | ||||
|   | ||||
| @@ -15,6 +15,17 @@ use Illuminate\Support\Collection; | ||||
| interface BillRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Returns the sum of all payments connected to this bill between the dates. | ||||
|      * | ||||
|      * @param Bill   $bill | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function billPaymentsInRange(Bill $bill, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Create a fake bill to help the chart controller. | ||||
|      * | ||||
|   | ||||
| @@ -8,6 +8,7 @@ use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Models\LimitRepetition; | ||||
| use Illuminate\Database\Query\Builder as QueryBuilder; | ||||
| use Illuminate\Database\Query\JoinClause; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use Input; | ||||
| @@ -48,9 +49,11 @@ class BudgetRepository implements BudgetRepositoryInterface | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function expensesOnDay(Budget $budget, Carbon $date) | ||||
|     public function expensesOnDayCorrected(Budget $budget, Carbon $date) | ||||
|     { | ||||
|         return floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($date)->sum('amount')); | ||||
|         $sum = floatval($budget->transactionjournals()->transactionTypes(['Withdrawal'])->onDate($date)->get(['transaction_journals.*'])->sum('amount')); | ||||
|  | ||||
|         return $sum * -1; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -98,7 +101,6 @@ class BudgetRepository implements BudgetRepositoryInterface | ||||
|     public function getBudgets() | ||||
|     { | ||||
|         $budgets = Auth::user()->budgets()->get(); | ||||
|         $budgets->sortBy('name'); | ||||
|  | ||||
|         return $budgets; | ||||
|     } | ||||
| @@ -250,22 +252,41 @@ class BudgetRepository implements BudgetRepositoryInterface | ||||
|                            ->before($end) | ||||
|                            ->lessThan(0) | ||||
|                            ->transactionTypes(['Withdrawal']) | ||||
|             ->sum('transactions.amount'); | ||||
|                            ->sum('transactions.amount'); | ||||
|  | ||||
|         return floatval($noBudgetSet) * -1; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $date | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * @param bool   $shared | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentInMonth(Budget $budget, Carbon $date) | ||||
|     public function spentInPeriodCorrected(Budget $budget, Carbon $start, Carbon $end, $shared = true) | ||||
|     { | ||||
|         $end = clone $date; | ||||
|         $date->startOfMonth(); | ||||
|         $end->endOfMonth(); | ||||
|         $sum = floatval($budget->transactionjournals()->before($end)->after($date)->lessThan(0)->sum('amount')) * -1; | ||||
|         if ($shared === true) { | ||||
|             // get everything: | ||||
|             $sum = floatval($budget->transactionjournals()->before($end)->after($start)->lessThan(0)->get(['transaction_journals.*'])->sum('amount')); | ||||
|         } else { | ||||
|             // get all journals in this month where the asset account is NOT shared. | ||||
|             $sum = $budget->transactionjournals() | ||||
|                           ->before($end) | ||||
|                           ->after($start) | ||||
|                           ->lessThan(0) | ||||
|                           ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|                           ->leftJoin( | ||||
|                               'account_meta', function (JoinClause $join) { | ||||
|                               $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|                           } | ||||
|                           ) | ||||
|                           ->where('account_meta.data', '!=', '"sharedAsset"') | ||||
|                           ->get(['transaction_journals.*']) | ||||
|                           ->sum('amount'); | ||||
|             $sum = floatval($sum); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
| @@ -288,17 +309,7 @@ class BudgetRepository implements BudgetRepositoryInterface | ||||
|         return $newBudget; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function sumBudgetExpensesInPeriod(Budget $budget, $start, $end) | ||||
|     { | ||||
|         return floatval($budget->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|   | ||||
| @@ -27,12 +27,14 @@ interface BudgetRepositoryInterface | ||||
|     public function destroy(Budget $budget); | ||||
|  | ||||
|     /** | ||||
|      * Takes tags into account. | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function expensesOnDay(Budget $budget, Carbon $date); | ||||
|     public function expensesOnDayCorrected(Budget $budget, Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
| @@ -123,12 +125,17 @@ interface BudgetRepositoryInterface | ||||
|     public function getWithoutBudgetSum(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * Same as ::spentInPeriod but corrects journals for their amount (tags). | ||||
|      * | ||||
|      * @param Budget  $budget | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * @param boolean $shared | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentInMonth(Budget $budget, Carbon $date); | ||||
|     public function spentInPeriodCorrected(Budget $budget, Carbon $start, Carbon $end, $shared = true); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
| @@ -137,15 +144,6 @@ interface BudgetRepositoryInterface | ||||
|      */ | ||||
|     public function store(array $data); | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function sumBudgetExpensesInPeriod(Budget $budget, $start, $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Budget $budget | ||||
|      * @param array  $data | ||||
|   | ||||
| @@ -4,6 +4,7 @@ namespace FireflyIII\Repositories\Category; | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use Crypt; | ||||
| use DB; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| @@ -58,33 +59,44 @@ class CategoryRepository implements CategoryRepositoryInterface | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getCategoriesAndExpenses($start, $end) | ||||
|     public function getCategoriesAndExpensesCorrected($start, $end) | ||||
|     { | ||||
|         return TransactionJournal:: | ||||
|         where('transaction_journals.user_id', Auth::user()->id) | ||||
|                                  ->leftJoin( | ||||
|                                      'transactions', | ||||
|                                      function (JoinClause $join) { | ||||
|                                          $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0); | ||||
|                                      } | ||||
|                                  ) | ||||
|                                  ->leftJoin( | ||||
|                                      'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|                                  ) | ||||
|                                  ->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id') | ||||
|                                  ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|                                  ->before($end) | ||||
|                                  ->where('categories.user_id', Auth::user()->id) | ||||
|                                  ->after($start) | ||||
|                                  ->where('transaction_types.type', 'Withdrawal') | ||||
|                                  ->groupBy('categories.id') | ||||
|                                  ->orderBy('sum', 'DESC') | ||||
|                                  ->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]); | ||||
|         $set = Auth::user()->transactionjournals() | ||||
|                    ->leftJoin( | ||||
|                        'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' | ||||
|                    ) | ||||
|                    ->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id') | ||||
|                    ->before($end) | ||||
|                    ->where('categories.user_id', Auth::user()->id) | ||||
|                    ->after($start) | ||||
|                    ->transactionTypes(['Withdrawal']) | ||||
|                    ->groupBy('categories.id') | ||||
|                    ->get(['categories.id as category_id', 'categories.encrypted as category_encrypted', 'categories.name', 'transaction_journals.*']); | ||||
|  | ||||
|         $result = []; | ||||
|         foreach ($set as $entry) { | ||||
|             $categoryId = intval($entry->category_id); | ||||
|             if (isset($result[$categoryId])) { | ||||
|                 $result[$categoryId]['sum'] += floatval($entry->amount); | ||||
|             } else { | ||||
|                 $isEncrypted         = intval($entry->category_encrypted) == 1 ? true : false; | ||||
|                 $name                = strlen($entry->name) == 0 ? trans('firefly.noCategory') : $entry->name; | ||||
|                 $name                = $isEncrypted ? Crypt::decrypt($name) : $name; | ||||
|                 $result[$categoryId] = [ | ||||
|                     'name' => $name, | ||||
|                     'sum'  => floatval($entry->amount), | ||||
|                 ]; | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -168,22 +180,54 @@ class CategoryRepository implements CategoryRepositoryInterface | ||||
|      * @param Carbon   $start | ||||
|      * @param Carbon   $end | ||||
|      * | ||||
|      * @param bool     $shared | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentInPeriodSum(Category $category, Carbon $start, Carbon $end) | ||||
|     public function spentInPeriodCorrected(Category $category, Carbon $start, Carbon $end, $shared = false) | ||||
|     { | ||||
|         return floatval($category->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1; | ||||
|         if ($shared === true) { | ||||
|             // shared is true. | ||||
|             // always ignore transfers between accounts! | ||||
|             $sum = floatval( | ||||
|                 $category->transactionjournals() | ||||
|                          ->transactionTypes(['Withdrawal']) | ||||
|                          ->before($end)->after($start)->get(['transaction_journals.*'])->sum('amount') | ||||
|             ); | ||||
|  | ||||
|         } else { | ||||
|             // do something else, SEE budgets. | ||||
|             // get all journals in this month where the asset account is NOT shared. | ||||
|             $sum = $category->transactionjournals() | ||||
|                             ->before($end) | ||||
|                             ->after($start) | ||||
|                             ->transactionTypes(['Withdrawal']) | ||||
|                             ->lessThan(0) | ||||
|                             ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') | ||||
|                             ->leftJoin( | ||||
|                                 'account_meta', function (JoinClause $join) { | ||||
|                                 $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); | ||||
|                             } | ||||
|                             ) | ||||
|                             ->where('account_meta.data', '!=', '"sharedAsset"') | ||||
|                             ->get(['transaction_journals.*'])->sum('amount'); | ||||
|             $sum = floatval($sum); | ||||
|         } | ||||
|  | ||||
|         return $sum; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Corrected for tags | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $date | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentOnDaySum(Category $category, Carbon $date) | ||||
|     public function spentOnDaySumCorrected(Category $category, Carbon $date) | ||||
|     { | ||||
|         return floatval($category->transactionjournals()->onDate($date)->lessThan(0)->sum('amount')) * -1; | ||||
|         return floatval($category->transactionjournals()->onDate($date)->get(['transaction_journals.*'])->sum('amount')); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -33,12 +33,14 @@ interface CategoryRepositoryInterface | ||||
|     public function getCategories(); | ||||
|  | ||||
|     /** | ||||
|      * Corrected for tags. | ||||
|      * | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function getCategoriesAndExpenses($start, $end); | ||||
|     public function getCategoriesAndExpensesCorrected($start, $end); | ||||
|  | ||||
|     /** | ||||
|      * @param Category $category | ||||
| @@ -71,21 +73,28 @@ interface CategoryRepositoryInterface | ||||
|     public function getWithoutCategory(Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * Corrected for tags. | ||||
|      * | ||||
|      * @param Category       $category | ||||
|      * @param \Carbon\Carbon $start | ||||
|      * @param \Carbon\Carbon $end | ||||
|      * | ||||
|      * @param bool           $shared | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentInPeriodSum(Category $category, Carbon $start, Carbon $end); | ||||
|     public function spentInPeriodCorrected(Category $category, Carbon $start, Carbon $end, $shared = false); | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * Corrected for tags. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * @param Carbon   $date | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function spentOnDaySum(Category $category, Carbon $date); | ||||
|     public function spentOnDaySumCorrected(Category $category, Carbon $date); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|   | ||||
| @@ -338,61 +338,86 @@ class JournalRepository implements JournalRepositoryInterface | ||||
|      */ | ||||
|     protected function storeAccounts(TransactionType $type, array $data) | ||||
|     { | ||||
|         $from = null; | ||||
|         $to   = null; | ||||
|         $fromAccount = null; | ||||
|         $toAccount   = null; | ||||
|         switch ($type->type) { | ||||
|             case 'Withdrawal': | ||||
|  | ||||
|                 $from = Account::find($data['account_id']); | ||||
|  | ||||
|                 if (strlen($data['expense_account']) > 0) { | ||||
|                     $toType = AccountType::where('type', 'Expense account')->first(); | ||||
|                     $to     = Account::firstOrCreateEncrypted( | ||||
|                         ['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => $data['expense_account'], 'active' => 1] | ||||
|                     ); | ||||
|                 } else { | ||||
|                     $toType = AccountType::where('type', 'Cash account')->first(); | ||||
|                     $to     = Account::firstOrCreateEncrypted( | ||||
|                         ['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1] | ||||
|                     ); | ||||
|                 } | ||||
|                 list($fromAccount, $toAccount) = $this->storeWithdrawalAccounts($data); | ||||
|                 break; | ||||
|  | ||||
|             case 'Deposit': | ||||
|                 $to = Account::find($data['account_id']); | ||||
|  | ||||
|                 if (strlen($data['revenue_account']) > 0) { | ||||
|                     $fromType = AccountType::where('type', 'Revenue account')->first(); | ||||
|                     $from     = Account::firstOrCreateEncrypted( | ||||
|                         ['user_id' => $data['user'], 'account_type_id' => $fromType->id, 'name' => $data['revenue_account'], 'active' => 1] | ||||
|                     ); | ||||
|                 } else { | ||||
|                     $toType = AccountType::where('type', 'Cash account')->first(); | ||||
|                     $from   = Account::firstOrCreateEncrypted( | ||||
|                         ['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1] | ||||
|                     ); | ||||
|                 } | ||||
|                 list($fromAccount, $toAccount) = $this->storeDepositAccounts($data); | ||||
|  | ||||
|                 break; | ||||
|             case 'Transfer': | ||||
|                 $from = Account::find($data['account_from_id']); | ||||
|                 $to   = Account::find($data['account_to_id']); | ||||
|                 $fromAccount = Account::find($data['account_from_id']); | ||||
|                 $toAccount   = Account::find($data['account_to_id']); | ||||
|                 break; | ||||
|         } | ||||
|         if (is_null($to) || (!is_null($to) && is_null($to->id))) { | ||||
|  | ||||
|         if (is_null($toAccount)) { | ||||
|             Log::error('"to"-account is null, so we cannot continue!'); | ||||
|             App::abort(500, '"to"-account is null, so we cannot continue!'); | ||||
|             // @codeCoverageIgnoreStart | ||||
|         } | ||||
|         // @codeCoverageIgnoreEnd | ||||
|  | ||||
|         if (is_null($from) || (!is_null($from) && is_null($from->id))) { | ||||
|         if (is_null($fromAccount)) { | ||||
|             Log::error('"from"-account is null, so we cannot continue!'); | ||||
|             App::abort(500, '"from"-account is null, so we cannot continue!'); | ||||
|             // @codeCoverageIgnoreStart | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreEnd | ||||
|  | ||||
|         return [$from, $to]; | ||||
|         return [$fromAccount, $toAccount]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function storeWithdrawalAccounts(array $data) | ||||
|     { | ||||
|         $fromAccount = Account::find($data['account_id']); | ||||
|  | ||||
|         if (strlen($data['expense_account']) > 0) { | ||||
|             $toType    = AccountType::where('type', 'Expense account')->first(); | ||||
|             $toAccount = Account::firstOrCreateEncrypted( | ||||
|                 ['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => $data['expense_account'], 'active' => 1] | ||||
|             ); | ||||
|         } else { | ||||
|             $toType    = AccountType::where('type', 'Cash account')->first(); | ||||
|             $toAccount = Account::firstOrCreateEncrypted( | ||||
|                 ['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return [$fromAccount, $toAccount]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     protected function storeDepositAccounts(array $data) | ||||
|     { | ||||
|         $toAccount = Account::find($data['account_id']); | ||||
|  | ||||
|         if (strlen($data['revenue_account']) > 0) { | ||||
|             $fromType    = AccountType::where('type', 'Revenue account')->first(); | ||||
|             $fromAccount = Account::firstOrCreateEncrypted( | ||||
|                 ['user_id' => $data['user'], 'account_type_id' => $fromType->id, 'name' => $data['revenue_account'], 'active' => 1] | ||||
|             ); | ||||
|         } else { | ||||
|             $toType      = AccountType::where('type', 'Cash account')->first(); | ||||
|             $fromAccount = Account::firstOrCreateEncrypted( | ||||
|                 ['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1] | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         return [$fromAccount, $toAccount]; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -9,7 +9,6 @@ use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Models\PiggyBankRepetition; | ||||
| use Illuminate\Support\Collection; | ||||
| use Navigation; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankRepository | ||||
| @@ -19,57 +18,6 @@ use Navigation; | ||||
| class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * Based on the piggy bank, the reminder-setting and | ||||
|      * other variables this method tries to divide the piggy bank into equal parts. Each is | ||||
|      * accommodated by a reminder (if everything goes to plan). | ||||
|      * | ||||
|      * @param PiggyBankRepetition $repetition | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function calculateParts(PiggyBankRepetition $repetition) | ||||
|     { | ||||
|         /** @var PiggyBank $piggyBank */ | ||||
|         $piggyBank    = $repetition->piggyBank()->first(); | ||||
|         $bars         = new Collection; | ||||
|         $currentStart = clone $repetition->startdate; | ||||
|  | ||||
|         if (is_null($piggyBank->reminder)) { | ||||
|             $entry = ['repetition'    => $repetition, 'amountPerBar' => floatval($piggyBank->targetamount), | ||||
|                       'currentAmount' => floatval($repetition->currentamount), 'cumulativeAmount' => floatval($piggyBank->targetamount), | ||||
|                       'startDate'     => clone $repetition->startdate, 'targetDate' => clone $repetition->targetdate]; | ||||
|             $bars->push($this->createPiggyBankPart($entry)); | ||||
|  | ||||
|             return $bars; | ||||
|         } | ||||
|  | ||||
|         while ($currentStart < $repetition->targetdate) { | ||||
|             $currentTarget = Navigation::endOfX($currentStart, $piggyBank->reminder, $repetition->targetdate); | ||||
|             $entry         = ['repetition'       => $repetition, 'amountPerBar' => null, 'currentAmount' => floatval($repetition->currentamount), | ||||
|                               'cumulativeAmount' => null, 'startDate' => $currentStart, 'targetDate' => $currentTarget]; | ||||
|             $bars->push($this->createPiggyBankPart($entry)); | ||||
|             $currentStart = clone $currentTarget; | ||||
|             $currentStart->addDay(); | ||||
|  | ||||
|         } | ||||
|         $amountPerBar = floatval($piggyBank->targetamount) / $bars->count(); | ||||
|         $cumulative   = $amountPerBar; | ||||
|         /** @var PiggyBankPart $bar */ | ||||
|         foreach ($bars as $index => $bar) { | ||||
|             $bar->setAmountPerBar($amountPerBar); | ||||
|             $bar->setCumulativeAmount($cumulative); | ||||
|             if ($bars->count() - 1 == $index) { | ||||
|                 $bar->setCumulativeAmount($piggyBank->targetamount); | ||||
|             } | ||||
|             $cumulative += $amountPerBar; | ||||
|         } | ||||
|  | ||||
|         return $bars; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param           $amount | ||||
| @@ -83,24 +31,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return PiggyBankPart | ||||
|      */ | ||||
|     public function createPiggyBankPart(array $data) | ||||
|     { | ||||
|         $part = new PiggyBankPart; | ||||
|         $part->setRepetition($data['repetition']); | ||||
|         $part->setAmountPerBar($data['amountPerBar']); | ||||
|         $part->setCurrentamount($data['currentAmount']); | ||||
|         $part->setCumulativeAmount($data['cumulativeAmount']); | ||||
|         $part->setStartdate($data['startDate']); | ||||
|         $part->setTargetdate($data['targetDate']); | ||||
|  | ||||
|         return $part; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
| @@ -151,8 +81,8 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|     { | ||||
|         // split query to make it work in sqlite: | ||||
|         $set = PiggyBank:: | ||||
|                  leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.id') | ||||
|                  ->where('accounts.user_id', Auth::user()->id)->get(['piggy_banks.*']); | ||||
|         leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.id') | ||||
|                         ->where('accounts.user_id', Auth::user()->id)->get(['piggy_banks.*']); | ||||
|         foreach ($set as $e) { | ||||
|             $e->order = 0; | ||||
|             $e->save(); | ||||
| @@ -198,7 +128,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface | ||||
|      * @param array     $data | ||||
|      * | ||||
|      * @return PiggyBank | ||||
|      * @internal param PiggyBank $account | ||||
|      */ | ||||
|     public function update(PiggyBank $piggyBank, array $data) | ||||
|     { | ||||
|   | ||||
| @@ -14,18 +14,6 @@ use Illuminate\Support\Collection; | ||||
| interface PiggyBankRepositoryInterface | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * Based on the piggy bank, the reminder-setting and | ||||
|      * other variables this method tries to divide the piggy bank into equal parts. Each is | ||||
|      * accommodated by a reminder (if everything goes to plan). | ||||
|      * | ||||
|      * @param PiggyBankRepetition $repetition | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function calculateParts(PiggyBankRepetition $repetition); | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
|      */ | ||||
| @@ -38,13 +26,6 @@ interface PiggyBankRepositoryInterface | ||||
|      */ | ||||
|     public function getEvents(PiggyBank $piggyBank); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return PiggyBankPart | ||||
|      */ | ||||
|     public function createPiggyBankPart(array $data); | ||||
|  | ||||
|     /** | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * @param           $amount | ||||
|   | ||||
| @@ -4,6 +4,8 @@ namespace FireflyIII\Repositories\Tag; | ||||
|  | ||||
|  | ||||
| use Auth; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Tag; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| @@ -17,7 +19,10 @@ use Illuminate\Support\Collection; | ||||
| class TagRepository implements TagRepositoryInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five. | ||||
|      * | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param Tag                $tag | ||||
|      * | ||||
| @@ -33,88 +38,54 @@ class TagRepository implements TagRepositoryInterface | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if ($tag->tagMode == 'nothing') { | ||||
|             // save it, no problem: | ||||
|             $journal->tags()->save($tag); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * get some withdrawal types: | ||||
|          */ | ||||
|         /** @var TransactionType $withdrawal */ | ||||
|         $withdrawal = TransactionType::whereType('Withdrawal')->first(); | ||||
|         /** @var TransactionType $deposit */ | ||||
|         $deposit = TransactionType::whereType('Deposit')->first(); | ||||
|         /** @var TransactionType $transfer */ | ||||
|         $transfer = TransactionType::whereType('Transfer')->first(); | ||||
|  | ||||
|         $withdrawals = $tag->transactionjournals()->where('transaction_type_id', $withdrawal->id)->count(); | ||||
|         $transfers   = $tag->transactionjournals()->where('transaction_type_id', $transfer->id)->count(); | ||||
|         $deposits    = $tag->transactionjournals()->where('transaction_type_id', $deposit->id)->count(); | ||||
|  | ||||
|         if ($tag->tagMode == 'balancingAct') { | ||||
|  | ||||
|             // only if this is the only withdrawal. | ||||
|             if ($journal->transaction_type_id == $withdrawal->id && $withdrawals < 1) { | ||||
|         switch ($tag->tagMode) { | ||||
|             case 'nothing': | ||||
|                 $journal->tags()->save($tag); | ||||
|  | ||||
|                 return true; | ||||
|             } | ||||
|             // and only if this is the only transfer | ||||
|             if ($journal->transaction_type_id == $transfer->id && $transfers < 1) { | ||||
|                 $journal->tags()->save($tag); | ||||
|  | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // ignore expense | ||||
|             return false; | ||||
|                 break; | ||||
|             case 'balancingAct': | ||||
|                 return $this->connectBalancingAct($journal, $tag); | ||||
|                 break; | ||||
|             case 'advancePayment': | ||||
|                 return $this->connectAdvancePayment($journal, $tag); | ||||
|                 break; | ||||
|         } | ||||
|         if ($tag->tagMode == 'advancePayment') { | ||||
|  | ||||
|             // advance payments cannot accept transfers: | ||||
|             if ($journal->transaction_type_id == $transfer->id) { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             // the first transaction to be attached to this | ||||
|             // tag is attached just like that: | ||||
|             if ($withdrawals < 1 && $deposits < 1) { | ||||
|                 $journal->tags()->save($tag); | ||||
|  | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // if withdrawal and already has a withdrawal, return false: | ||||
|             if ($journal->transaction_type_id == $withdrawal->id && $withdrawals == 1) { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             // if already has transaction journals, must match ALL asset account id's: | ||||
|             if ($deposits > 0 || $withdrawals == 1) { | ||||
|                 $match = true; | ||||
|                 /** @var TransactionJournal $check */ | ||||
|                 foreach ($tag->transactionjournals as $check) { | ||||
|                     if ($check->assetAccount->id != $journal->assetAccount->id) { | ||||
|                         $match = false; | ||||
|                     } | ||||
|                 } | ||||
|                 if ($match) { | ||||
|                     $journal->tags()->save($tag); | ||||
|  | ||||
|                     return true; | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|         // @codeCoverageIgnoreStart | ||||
|         return false; | ||||
|     } | ||||
|     // @codeCoverageIgnoreEnd | ||||
|  | ||||
|     /** | ||||
|      * This method scans the transaction journals from or to the given asset account | ||||
|      * and checks if these are part of a balancing act. If so, it will sum up the amounts | ||||
|      * transferred into the balancing act (if any) and return this amount. | ||||
|      * | ||||
|      * This method effectively tells you the amount of money that has been balanced out | ||||
|      * correctly in the given period for the given account. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function coveredByBalancingActs(Account $account, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         // the quickest way to do this is by scanning all balancingAct tags | ||||
|         // because there will be less of them any way. | ||||
|         $tags   = Auth::user()->tags()->where('tagMode', 'balancingAct')->get(); | ||||
|         $amount = 0; | ||||
|  | ||||
|         /** @var Tag $tag */ | ||||
|         foreach ($tags as $tag) { | ||||
|             $transfer = $tag->transactionjournals()->after($start)->before($end)->toAccountIs($account)->transactionTypes(['Transfer'])->first(); | ||||
|             if ($transfer) { | ||||
|                 $amount += $transfer->amount; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $amount; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Tag $tag | ||||
| @@ -127,6 +98,7 @@ class TagRepository implements TagRepositoryInterface | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|     // @codeCoverageIgnoreEnd | ||||
|  | ||||
|     /** | ||||
|      * @return Collection | ||||
| @@ -186,4 +158,107 @@ class TagRepository implements TagRepositoryInterface | ||||
|  | ||||
|         return $tag; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param Tag                $tag | ||||
|      * | ||||
|      * @return boolean | ||||
|      */ | ||||
|     protected function connectBalancingAct(TransactionJournal $journal, Tag $tag) | ||||
|     { | ||||
|         /** @var TransactionType $withdrawal */ | ||||
|         $withdrawal  = TransactionType::whereType('Withdrawal')->first(); | ||||
|         $withdrawals = $tag->transactionjournals()->where('transaction_type_id', $withdrawal->id)->count(); | ||||
|         /** @var TransactionType $transfer */ | ||||
|         $transfer  = TransactionType::whereType('Transfer')->first(); | ||||
|         $transfers = $tag->transactionjournals()->where('transaction_type_id', $transfer->id)->count(); | ||||
|  | ||||
|  | ||||
|         // only if this is the only withdrawal. | ||||
|         if ($journal->transaction_type_id == $withdrawal->id && $withdrawals < 1) { | ||||
|             $journal->tags()->save($tag); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|         // and only if this is the only transfer | ||||
|         if ($journal->transaction_type_id == $transfer->id && $transfers < 1) { | ||||
|             $journal->tags()->save($tag); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         // ignore expense | ||||
|         return false; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param Tag                $tag | ||||
|      * | ||||
|      * @return boolean | ||||
|      */ | ||||
|     protected function connectAdvancePayment(TransactionJournal $journal, Tag $tag) | ||||
|     { | ||||
|         /** @var TransactionType $transfer */ | ||||
|         $transfer = TransactionType::whereType('Transfer')->first(); | ||||
|         /** @var TransactionType $withdrawal */ | ||||
|         $withdrawal = TransactionType::whereType('Withdrawal')->first(); | ||||
|         /** @var TransactionType $deposit */ | ||||
|         $deposit = TransactionType::whereType('Deposit')->first(); | ||||
|  | ||||
|         $withdrawals = $tag->transactionjournals()->where('transaction_type_id', $withdrawal->id)->count(); | ||||
|         $deposits    = $tag->transactionjournals()->where('transaction_type_id', $deposit->id)->count(); | ||||
|  | ||||
|         // advance payments cannot accept transfers: | ||||
|         if ($journal->transaction_type_id == $transfer->id) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         // the first transaction to be attached to this | ||||
|         // tag is attached just like that: | ||||
|         if ($withdrawals < 1 && $deposits < 1) { | ||||
|             $journal->tags()->save($tag); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         // if withdrawal and already has a withdrawal, return false: | ||||
|         if ($journal->transaction_type_id == $withdrawal->id && $withdrawals == 1) { | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         // if already has transaction journals, must match ALL asset account id's: | ||||
|         if ($deposits > 0 || $withdrawals == 1) { | ||||
|             return $this->matchAll($journal, $tag); | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param TransactionJournal $journal | ||||
|      * @param Tag                $tag | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     protected function matchAll(TransactionJournal $journal, Tag $tag) | ||||
|     { | ||||
|         $match = true; | ||||
|         /** @var TransactionJournal $check */ | ||||
|         foreach ($tag->transactionjournals as $check) { | ||||
|             if ($check->assetAccount->id != $journal->assetAccount->id) { | ||||
|                 $match = false; | ||||
|             } | ||||
|         } | ||||
|         if ($match) { | ||||
|             $journal->tags()->save($tag); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -2,6 +2,8 @@ | ||||
|  | ||||
| namespace FireflyIII\Repositories\Tag; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Tag; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use Illuminate\Support\Collection; | ||||
| @@ -15,6 +17,23 @@ use Illuminate\Support\Collection; | ||||
| interface TagRepositoryInterface | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * This method scans the transaction journals from or to the given asset account | ||||
|      * and checks if these are part of a balancing act. If so, it will sum up the amounts | ||||
|      * transferred into the balancing act (if any) and return this amount. | ||||
|      * | ||||
|      * This method effectively tells you the amount of money that has been balanced out | ||||
|      * correctly in the given period for the given account. | ||||
|      * | ||||
|      * @param Account $account | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function coveredByBalancingActs(Account $account, Carbon $start, Carbon $end); | ||||
|  | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|   | ||||
| @@ -84,32 +84,20 @@ class Amount | ||||
|      */ | ||||
|     public function formatJournal(TransactionJournal $journal, $coloured = true) | ||||
|     { | ||||
|         $showPositive = true; | ||||
|         if (is_null($journal->symbol)) { | ||||
|             $symbol = $journal->transactionCurrency->symbol; | ||||
|         } else { | ||||
|             $symbol = $journal->symbol; | ||||
|         } | ||||
|         $amount = 0; | ||||
|  | ||||
|         if (is_null($journal->type)) { | ||||
|             $type = $journal->transactionType->type; | ||||
|         } else { | ||||
|             $type = $journal->type; | ||||
|         $amount = $journal->amount; | ||||
|         if ($journal->transactionType->type == 'Withdrawal') { | ||||
|             $amount = $amount * -1; | ||||
|         } | ||||
|  | ||||
|         if ($type == 'Withdrawal') { | ||||
|             $showPositive = false; | ||||
|         if ($journal->transactionType->type == 'Transfer' && $coloured) { | ||||
|             return '<span class="text-info">' . $this->formatWithSymbol($symbol, $amount, false) . '</span>'; | ||||
|         } | ||||
|  | ||||
|         foreach ($journal->transactions as $t) { | ||||
|             if (floatval($t->amount) > 0 && $showPositive === true) { | ||||
|                 $amount = floatval($t->amount); | ||||
|                 break; | ||||
|             } | ||||
|             if (floatval($t->amount) < 0 && $showPositive === false) { | ||||
|                 $amount = floatval($t->amount); | ||||
|             } | ||||
|         if ($journal->transactionType->type == 'Transfer' && !$coloured) { | ||||
|             return $this->formatWithSymbol($symbol, $amount, false); | ||||
|         } | ||||
|  | ||||
|         return $this->formatWithSymbol($symbol, $amount, $coloured); | ||||
|   | ||||
| @@ -51,29 +51,8 @@ class ExpandedForm | ||||
|         if (isset($options['label'])) { | ||||
|             return $options['label']; | ||||
|         } | ||||
|         $labels = [ | ||||
|             'amount_min'           => 'Amount (min)', | ||||
|             'amount_max'           => 'Amount (max)', | ||||
|             'match'                => 'Matches on', | ||||
|             'repeat_freq'          => 'Repetition', | ||||
|             'account_from_id'      => 'Account from', | ||||
|             'account_to_id'        => 'Account to', | ||||
|             'account_id'           => 'Asset account', | ||||
|             'budget_id'            => 'Budget', | ||||
|             'openingBalance'       => 'Opening balance', | ||||
|             'tagMode'              => 'Tag mode', | ||||
|             'tagPosition'          => 'Tag location', | ||||
|             'virtualBalance'       => 'Virtual balance', | ||||
|             'longitude_latitude'   => 'Location', | ||||
|             'targetamount'         => 'Target amount', | ||||
|             'accountRole'          => 'Account role', | ||||
|             'openingBalanceDate'   => 'Opening balance date', | ||||
|             'ccType'               => 'Credit card payment plan', | ||||
|             'ccMonthlyPaymentDate' => 'Credit card monthly payment date', | ||||
|             'piggy_bank_id'        => 'Piggy bank']; | ||||
|  | ||||
|  | ||||
|         return isset($labels[$name]) ? $labels[$name] : str_replace('_', ' ', ucfirst($name)); | ||||
|         return trans('form.' . $name); | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -28,21 +28,11 @@ class Navigation | ||||
|         $add  = ($skip + 1); | ||||
|  | ||||
|         $functionMap = [ | ||||
|             '1D'        => 'addDays', | ||||
|             'daily'     => 'addDays', | ||||
|             '1W'        => 'addWeeks', | ||||
|             'weekly'    => 'addWeeks', | ||||
|             'week'      => 'addWeeks', | ||||
|             '1M'        => 'addMonths', | ||||
|             'month'     => 'addMonths', | ||||
|             'monthly'   => 'addMonths', | ||||
|             '3M'        => 'addMonths', | ||||
|             'quarter'   => 'addMonths', | ||||
|             'quarterly' => 'addMonths', | ||||
|             '6M'        => 'addMonths', | ||||
|             'half-year' => 'addMonths', | ||||
|             'year'      => 'addYears', | ||||
|             'yearly'    => 'addYears', | ||||
|             '1D'      => 'addDays', 'daily' => 'addDays', | ||||
|             '1W'      => 'addWeeks', 'weekly' => 'addWeeks', 'week' => 'addWeeks', | ||||
|             '1M'      => 'addMonths', 'month' => 'addMonths', 'monthly' => 'addMonths', '3M' => 'addMonths', | ||||
|             'quarter' => 'addMonths', 'quarterly' => 'addMonths', '6M' => 'addMonths', 'half-year' => 'addMonths', | ||||
|             'year'    => 'addYears', 'yearly' => 'addYears', | ||||
|         ]; | ||||
|         $modifierMap = [ | ||||
|             'quarter'   => 3, | ||||
| @@ -75,21 +65,11 @@ class Navigation | ||||
|         $currentEnd = clone $theCurrentEnd; | ||||
|  | ||||
|         $functionMap = [ | ||||
|             '1D'        => 'addDay', | ||||
|             'daily'     => 'addDay', | ||||
|             '1W'        => 'addWeek', | ||||
|             'week'      => 'addWeek', | ||||
|             'weekly'    => 'addWeek', | ||||
|             '1M'        => 'addMonth', | ||||
|             'month'     => 'addMonth', | ||||
|             'monthly'   => 'addMonth', | ||||
|             '3M'        => 'addMonths', | ||||
|             'quarter'   => 'addMonths', | ||||
|             'quarterly' => 'addMonths', | ||||
|             '6M'        => 'addMonths', | ||||
|             'half-year' => 'addMonths', | ||||
|             'year'      => 'addYear', | ||||
|             'yearly'    => 'addYear', | ||||
|             '1D'   => 'addDay', 'daily' => 'addDay', | ||||
|             '1W'   => 'addWeek', 'week' => 'addWeek', 'weekly' => 'addWeek', | ||||
|             '1M'   => 'addMonth', 'month' => 'addMonth', 'monthly' => 'addMonth', | ||||
|             '3M'   => 'addMonths', 'quarter' => 'addMonths', 'quarterly' => 'addMonths', '6M' => 'addMonths', 'half-year' => 'addMonths', | ||||
|             'year' => 'addYear', 'yearly' => 'addYear', | ||||
|         ]; | ||||
|         $modifierMap = [ | ||||
|             'quarter'   => 3, | ||||
|   | ||||
| @@ -23,12 +23,9 @@ class Steam | ||||
|      * | ||||
|      * @return float | ||||
|      */ | ||||
|     public function balance(Account $account, Carbon $date = null, $ignoreVirtualBalance = false) | ||||
|     public function balance(Account $account, Carbon $date, $ignoreVirtualBalance = false) | ||||
|     { | ||||
|         $date = is_null($date) ? Carbon::now() : $date; | ||||
|  | ||||
|         // find the first known transaction on this account: | ||||
|         // | ||||
|         $firstDateObject = $account | ||||
|             ->transactions() | ||||
|             ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
| @@ -37,12 +34,6 @@ class Steam | ||||
|         $firstDate = is_null($firstDateObject) ? clone $date : new Carbon($firstDateObject->date); | ||||
|         $date      = $date < $firstDate ? $firstDate : $date; | ||||
|  | ||||
|         /** | ||||
|          *select * from transactions | ||||
|          * left join transaction_journals ON transaction_journals.id = transactions.transaction_journal_id | ||||
|          * order by date ASC | ||||
|          */ | ||||
|  | ||||
|         $balance = floatval( | ||||
|             $account->transactions()->leftJoin( | ||||
|                 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' | ||||
|   | ||||
| @@ -39,6 +39,22 @@ class Budget extends Twig_Extension | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         $functions[] = new Twig_SimpleFunction( | ||||
|             'spentInRepetitionCorrected', function (LimitRepetition $repetition) { | ||||
|             $sum | ||||
|                 = Auth::user()->transactionjournals() | ||||
|                       ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                       ->leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budget_transaction_journal.budget_id') | ||||
|                       ->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id') | ||||
|                       ->before($repetition->enddate) | ||||
|                       ->after($repetition->startdate) | ||||
|                       ->where('limit_repetitions.id', '=', $repetition->id) | ||||
|                       ->get(['transaction_journals.*'])->sum('amount'); | ||||
|  | ||||
|             return floatval($sum); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|         return $functions; | ||||
|  | ||||
|     } | ||||
|   | ||||
| @@ -3,10 +3,12 @@ | ||||
| namespace FireflyIII\Support\Twig; | ||||
|  | ||||
| use App; | ||||
| use Carbon\Carbon; | ||||
| use Config; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use Route; | ||||
| use Session; | ||||
| use Twig_Extension; | ||||
| use Twig_SimpleFilter; | ||||
| use Twig_SimpleFunction; | ||||
| @@ -21,6 +23,7 @@ class General extends Twig_Extension | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getFilters() | ||||
| @@ -56,8 +59,9 @@ class General extends Twig_Extension | ||||
|             if (is_null($account)) { | ||||
|                 return 'NULL'; | ||||
|             } | ||||
|             $date = Session::get('end', Carbon::now()->endOfMonth()); | ||||
|  | ||||
|             return App::make('steam')->balance($account); | ||||
|             return App::make('steam')->balance($account, $date); | ||||
|         } | ||||
|         ); | ||||
|  | ||||
|   | ||||
| @@ -18,6 +18,7 @@ class Journal extends Twig_Extension | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getFilters() | ||||
| @@ -27,20 +28,25 @@ class Journal extends Twig_Extension | ||||
|         $filters[] = new Twig_SimpleFilter( | ||||
|             'typeIcon', function (TransactionJournal $journal) { | ||||
|             $type = $journal->transactionType->type; | ||||
|             if ($type == 'Withdrawal') { | ||||
|                 return '<span class="glyphicon glyphicon-arrow-left" title="Withdrawal"></span>'; | ||||
|             } | ||||
|             if ($type == 'Deposit') { | ||||
|                 return '<span class="glyphicon glyphicon-arrow-right" title="Deposit"></span>'; | ||||
|             } | ||||
|             if ($type == 'Transfer') { | ||||
|                 return '<i class="fa fa-fw fa-exchange" title="Transfer"></i>'; | ||||
|             } | ||||
|             if ($type == 'Opening balance') { | ||||
|                 return '<span class="glyphicon glyphicon-ban-circle" title="Opening balance"></span>'; | ||||
|  | ||||
|             switch ($type) { | ||||
|                 case 'Withdrawal': | ||||
|                     return '<span class="glyphicon glyphicon-arrow-left" title="' . trans('firefly.withdrawal') . '"></span>'; | ||||
|                     break; | ||||
|                 case 'Deposit': | ||||
|                     return '<span class="glyphicon glyphicon-arrow-right" title="' . trans('firefly.deposit') . '"></span>'; | ||||
|                     break; | ||||
|                 case 'Transfer': | ||||
|                     return '<i class="fa fa-fw fa-exchange" title="' . trans('firefly.transfer') . '"></i>'; | ||||
|                     break; | ||||
|                 case 'Opening balance': | ||||
|                     return '<span class="glyphicon glyphicon-ban-circle" title="' . trans('firefly.openingBalance') . '"></span>'; | ||||
|                     break; | ||||
|                 default: | ||||
|                     return ''; | ||||
|                     break; | ||||
|             } | ||||
|  | ||||
|             return ''; | ||||
|  | ||||
|         }, ['is_safe' => ['html']] | ||||
|         ); | ||||
| @@ -49,6 +55,8 @@ class Journal extends Twig_Extension | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getFunctions() | ||||
| @@ -70,13 +78,41 @@ class Journal extends Twig_Extension | ||||
|             if ($journal->tags->count() == 0) { | ||||
|                 return App::make('amount')->formatJournal($journal); | ||||
|             } | ||||
|  | ||||
|  | ||||
|             foreach ($journal->tags as $tag) { | ||||
|                 if ($tag->tagMode == 'balancingAct') { | ||||
|                     // return tag formatted for a "balancing act". | ||||
|                     // return tag formatted for a "balancing act", even if other | ||||
|                     // tags are present. | ||||
|                     $amount = App::make('amount')->formatJournal($journal, false); | ||||
|  | ||||
|                     return '<a href="' . route('tags.show', $tag->id) . '" class="label label-success" title="' . $amount | ||||
|                            . '"><i class="fa fa-fw fa-refresh"></i> ' . $tag->tag . '</span>'; | ||||
|                            . '"><i class="fa fa-fw fa-refresh"></i> ' . $tag->tag . '</a>'; | ||||
|                 } | ||||
|  | ||||
|                 /* | ||||
|                  * AdvancePayment with a deposit will show the tag instead of the amount: | ||||
|                  */ | ||||
|                 if ($tag->tagMode == 'advancePayment' && $journal->transactionType->type == 'Deposit') { | ||||
|                     $amount = App::make('amount')->formatJournal($journal, false); | ||||
|  | ||||
|                     return '<a href="' . route('tags.show', $tag->id) . '" class="label label-success" title="' . $amount | ||||
|                            . '"><i class="fa fa-fw fa-sort-numeric-desc"></i> ' . $tag->tag . '</a>'; | ||||
|                 } | ||||
|                 /* | ||||
|                  * AdvancePayment with a withdrawal will show the amount with a link to | ||||
|                  * the tag. The TransactionJournal should properly calculate the amount. | ||||
|                  */ | ||||
|                 if ($tag->tagMode == 'advancePayment' && $journal->transactionType->type == 'Withdrawal') { | ||||
|                     $amount = App::make('amount')->formatJournal($journal); | ||||
|  | ||||
|                     return '<a href="' . route('tags.show', $tag->id) . '">' . $amount . '</a>'; | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 if ($tag->tagMode == 'nothing') { | ||||
|                     // return the amount: | ||||
|                     return App::make('amount')->formatJournal($journal); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -24,7 +24,7 @@ class Translation extends Twig_Extension | ||||
|         $filters[] = new Twig_SimpleFilter( | ||||
|             '_', function ($name) { | ||||
|  | ||||
|             return trans('firefly.'.$name); | ||||
|             return trans('firefly.' . $name); | ||||
|  | ||||
|         }, ['is_safe' => ['html']] | ||||
|         ); | ||||
|   | ||||
| @@ -29,10 +29,11 @@ class FireflyValidator extends Validator | ||||
|      * @param array               $rules | ||||
|      * @param array               $messages | ||||
|      * @param array               $customAttributes | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveParameterList) | ||||
|      */ | ||||
|     public function __construct(TranslatorInterface $translator, array $data, array $rules, array $messages = [], array $customAttributes = []) | ||||
|     { | ||||
|         parent::__construct($translator, $data, $rules, $messages); | ||||
|         parent::__construct($translator, $data, $rules, $messages, $customAttributes); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -21,7 +21,7 @@ return [ | ||||
|         'defaultAsset' => 'Default asset account', | ||||
|         'sharedAsset'  => 'Shared asset account', | ||||
|         'savingAsset'  => 'Savings account', | ||||
|         'ccAsset'  => 'Credit card', | ||||
|         'ccAsset'      => 'Credit card', | ||||
|     ], | ||||
|  | ||||
|     'range_to_text'            => [ | ||||
| @@ -32,7 +32,7 @@ return [ | ||||
|         '6M'     => 'half year', | ||||
|         'custom' => '(custom)' | ||||
|     ], | ||||
|     'ccTypes' => [ | ||||
|     'ccTypes'                  => [ | ||||
|         'monthlyFull' => 'Full payment every month' | ||||
|     ], | ||||
|     'range_to_name'            => [ | ||||
| @@ -56,6 +56,7 @@ return [ | ||||
|             'asset'   => 'Asset accounts', | ||||
|             'expense' => 'Expense accounts', | ||||
|             'revenue' => 'Revenue accounts', | ||||
|             'cash' => 'Cash accounts', | ||||
|         ], | ||||
|     'subIconsByIdentifier'     => | ||||
|         [ | ||||
| @@ -77,9 +78,9 @@ return [ | ||||
|         ], | ||||
|     'accountTypeByIdentifier'  => | ||||
|         [ | ||||
|             'asset'      => 'Asset account', | ||||
|             'expense'    => 'Expense account', | ||||
|             'revenue'    => 'Revenue account' | ||||
|             'asset'   => 'Asset account', | ||||
|             'expense' => 'Expense account', | ||||
|             'revenue' => 'Revenue account' | ||||
|         ], | ||||
|     'shortNamesByFullName'     => | ||||
|         [ | ||||
| @@ -89,6 +90,22 @@ return [ | ||||
|             'Beneficiary account' => 'expense', | ||||
|             'Revenue account'     => 'revenue', | ||||
|             'Cash account'        => 'cash', | ||||
|         ] | ||||
|         ], | ||||
|     'lang'                     => [ | ||||
|         'en' => 'English', | ||||
|         'nl' => 'Nederlands' | ||||
|     ], | ||||
|     'locales'                  => [ | ||||
|         'en' => ['en', 'English', 'en_US', 'en_US.utf8'], | ||||
|         'nl' => ['nl', 'Dutch', 'nl_NL', 'nl_NL.utf8'], | ||||
|     ], | ||||
|     'month'                    => [ | ||||
|         'en' => '%B %Y', | ||||
|         'nl' => '%B %Y', | ||||
|     ], | ||||
|     'monthAndDay'              => [ | ||||
|         'en' => '%B %e, %Y', | ||||
|         'nl' => '%e %B %Y', | ||||
|     ], | ||||
|  | ||||
| ]; | ||||
|   | ||||
							
								
								
									
										2
									
								
								database/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								database/.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +1 @@ | ||||
| *.sqlite | ||||
|  | ||||
|   | ||||
							
								
								
									
										2
									
								
								pu.sh
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								pu.sh
									
									
									
									
									
								
							| @@ -11,7 +11,7 @@ fi | ||||
|  | ||||
| if [ ! -z "$1" ] | ||||
| then | ||||
|     phpunit --verbose tests/repositories/$1.php | ||||
|     phpunit --verbose tests/helpers/$1.php | ||||
| fi | ||||
|  | ||||
| # restore .env file | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| $(document).ready(function () { | ||||
|  | ||||
|         if (typeof(googleComboChart) === 'function' && typeof(billID) !== 'undefined') { | ||||
|             googleComboChart('chart/bills/' + billID, 'bill-overview'); | ||||
|             googleComboChart('chart/bill/' + billID, 'bill-overview'); | ||||
|         } | ||||
|     } | ||||
| ); | ||||
| @@ -8,7 +8,7 @@ $(function () { | ||||
|  | ||||
|  | ||||
|     if (typeof budgetID !== 'undefined' && typeof repetitionID === 'undefined') { | ||||
|         googleColumnChart('chart/budget/' + budgetID + '/spending', 'budgetOverview'); | ||||
|         googleColumnChart('chart/budget/' + budgetID, 'budgetOverview'); | ||||
|     } | ||||
|     if (typeof budgetID !== 'undefined' && typeof repetitionID !== 'undefined') { | ||||
|         googleLineChart('chart/budget/' + budgetID + '/' + repetitionID, 'budgetOverview'); | ||||
| @@ -20,7 +20,7 @@ $(function () { | ||||
| function updateSingleRange(e) { | ||||
|     // get some values: | ||||
|     var input = $(e.target); | ||||
|     var id    = input.data('id'); | ||||
|     var id = input.data('id'); | ||||
|     var value = parseInt(input.val()); | ||||
|     var spent = parseFloat($('#spent-' + id).data('value')); | ||||
|  | ||||
| @@ -95,7 +95,9 @@ function updateTotal() { | ||||
| } | ||||
|  | ||||
| function updateIncome(e) { | ||||
|     $('#monthlyBudgetModal').empty().load('budgets/income').modal('show'); | ||||
|     $('#monthlyBudgetModal').empty().load('budgets/income', function () { | ||||
|         $('#monthlyBudgetModal').modal('show'); | ||||
|     }); | ||||
|  | ||||
|     return false; | ||||
| } | ||||
| @@ -112,7 +114,7 @@ function updateRanges() { | ||||
|         var value = parseInt(input.val()); | ||||
|  | ||||
|         // calculate sum: | ||||
|         sum += value | ||||
|         sum += value; | ||||
|  | ||||
|         // update small display: | ||||
|         $('#budget-range-display-' + id).text('\u20AC ' + value.toFixed(2)); | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| $(function () { | ||||
|  | ||||
|     if (typeof categoryID !== 'undefined') { | ||||
|         googleColumnChart('chart/category/' + categoryID + '/overview', 'componentOverview'); | ||||
|         googleColumnChart('chart/category/' + categoryID + '/period', 'periodOverview'); | ||||
|         googleColumnChart('chart/category/' + categoryID + '/all', 'all'); | ||||
|         googleColumnChart('chart/category/' + categoryID + '/month', 'month'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -6,7 +6,7 @@ $(function () { | ||||
|     ranges[currentMonthName] = [moment().startOf('month'), moment().endOf('month')]; | ||||
|     ranges[previousMonthName] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]; | ||||
|     ranges[nextMonthName] = [moment().add(1, 'month').startOf('month'), moment().add(1, 'month').endOf('month')]; | ||||
|     ranges['Everything'] = [firstDate, moment()]; | ||||
|     ranges[everything] = [firstDate, moment()]; | ||||
|  | ||||
|     $('#daterange').daterangepicker( | ||||
|         { | ||||
| @@ -15,10 +15,19 @@ $(function () { | ||||
|             //View::share('nextMonthName', $next); | ||||
|  | ||||
|  | ||||
|             ranges: ranges | ||||
|             , | ||||
|             ranges: ranges, | ||||
|             opens: 'left', | ||||
|  | ||||
|             locale: { | ||||
|                 applyLabel: applyLabel, | ||||
|                 cancelLabel: cancelLabel, | ||||
|                 fromLabel: fromLabel, | ||||
|                 toLabel: toLabel, | ||||
|                 weekLabel: 'W', | ||||
|                 customRangeLabel: customRangeLabel, | ||||
|                 daysOfWeek: moment.weekdaysMin(), | ||||
|                 monthNames: moment.monthsShort(), | ||||
|                 firstDay: moment.localeData()._week.dow | ||||
|             }, | ||||
|             format: 'DD-MM-YYYY', | ||||
|             startDate: start, | ||||
|             endDate: end | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| var google = google || {}; | ||||
| google.load('visualization', '1.1', {'packages': ['corechart', 'bar', 'line', 'sankey', 'table']}); | ||||
| google.load('visualization', '1.1', {'packages': ['corechart', 'bar', 'line'],'language': language  }); | ||||
|  | ||||
| function googleChart(chartType, URL, container, options) { | ||||
|     if ($('#' + container).length === 1) { | ||||
|   | ||||
| @@ -2,11 +2,12 @@ google.setOnLoadCallback(drawChart); | ||||
|  | ||||
|  | ||||
| function drawChart() { | ||||
|     googleLineChart('chart/home/account', 'accounts-chart'); | ||||
|     //googleColumnChart('chart/home/budgets', 'budgets-chart'); | ||||
|     googleStackedColumnChart('chart/home/budgets', 'budgets-chart'); | ||||
|     googleColumnChart('chart/home/categories', 'categories-chart'); | ||||
|     googlePieChart('chart/home/bills', 'bills-chart'); | ||||
|     googleLineChart('chart/account/frontpage', 'accounts-chart'); | ||||
|     googlePieChart('chart/bill/frontpage', 'bills-chart'); | ||||
|     googleStackedColumnChart('chart/budget/frontpage', 'budgets-chart'); | ||||
|     googleColumnChart('chart/category/frontpage', 'categories-chart'); | ||||
|  | ||||
|  | ||||
|     getBoxAmounts(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,7 @@ $(function () { | ||||
|     $('.removeMoney').on('click', removeMoney); | ||||
|  | ||||
|     if (typeof(googleLineChart) === 'function' && typeof(piggyBankID) !== 'undefined') { | ||||
|         googleLineChart('chart/piggy-history/' + piggyBankID, 'piggy-bank-history'); | ||||
|         googleLineChart('chart/piggyBank/' + piggyBankID, 'piggy-bank-history'); | ||||
|     } | ||||
|  | ||||
|     $('#sortable tbody').sortable( | ||||
|   | ||||
| @@ -1,20 +1,26 @@ | ||||
| if (typeof(google) != 'undefined') { | ||||
|     google.setOnLoadCallback(drawChart); | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| function drawChart() { | ||||
|     googleColumnChart('chart/reports/income-expenses/' + year, 'income-expenses-chart'); | ||||
|     googleColumnChart('chart/reports/income-expenses-sum/' + year, 'income-expenses-sum-chart') | ||||
|     googleColumnChart('chart/report/in-out/' + year + shared, 'income-expenses-chart'); | ||||
|     googleColumnChart('chart/report/in-out-sum/' + year + shared, 'income-expenses-sum-chart'); | ||||
|  | ||||
|     googleStackedColumnChart('chart/budgets/spending/' + year, 'budgets'); | ||||
|     googleStackedColumnChart('chart/budget/year/' + year + shared, 'budgets'); | ||||
|     googleStackedColumnChart('chart/category/year/' + year + shared, 'categories'); | ||||
|  | ||||
|     googleLineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart'); | ||||
| } | ||||
|  | ||||
| $(function () { | ||||
|     $('.openModal').on('click', openModal); | ||||
|     includeSharedToggle(); | ||||
|     $('#includeShared').click(includeSharedSet); | ||||
|  | ||||
|  | ||||
|     // click open the top X income list: | ||||
|     $('#showIncomes').click(showIncomes); | ||||
|     // click open the top X expense list: | ||||
|     $('#showExpenses').click(showExpenses); | ||||
| }); | ||||
|  | ||||
| function openModal(e) { | ||||
| @@ -32,31 +38,44 @@ function openModal(e) { | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| function includeSharedToggle() { | ||||
|     // get setting from JSON. | ||||
|     $.getJSON('json/show-shared-reports').success(function (data) { | ||||
|         console.log('GO'); | ||||
|         if (data.value == true) { | ||||
|             // show shared data, update button: | ||||
|             //<i class="state-icon glyphicon glyphicon-check"></i> | ||||
|             $('#includeShared').empty().addClass('btn-info').append($('<i>').addClass('state-icon glyphicon glyphicon-check')).append(' Include shared asset accounts').show(); | ||||
|             console.log('true'); | ||||
|         } else { | ||||
|             $('#includeShared').empty().removeClass('btn-info').append($('<i>').addClass('state-icon glyphicon glyphicon-unchecked')).append(' Include shared asset accounts').show(); | ||||
|             console.log('false'); | ||||
|         } | ||||
|     }).fail(function () { | ||||
|         console.log('fail'); | ||||
|     }); | ||||
|  | ||||
| function showIncomes() { | ||||
|     "use strict"; | ||||
|     if (incomeRestShow) { | ||||
|         // hide everything, make button say "show" | ||||
|         $('#showIncomes').text(showTheRest); | ||||
|         $('.incomesCollapsed').removeClass('in').addClass('out'); | ||||
|  | ||||
|         // toggle: | ||||
|         incomeRestShow = false; | ||||
|     } else { | ||||
|         // show everything, make button say "hide". | ||||
|         $('#showIncomes').text(hideTheRest); | ||||
|         $('.incomesCollapsed').removeClass('out').addClass('in'); | ||||
|  | ||||
|         // toggle: | ||||
|         incomeRestShow = true; | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| function includeSharedSet() { | ||||
|     // get setting from JSON. | ||||
|     $.getJSON('json/show-shared-reports/set').success(function (data) { | ||||
|         console.log('Value is now: ' + data.value); | ||||
|         includeSharedToggle(); | ||||
|     }).fail(function () { | ||||
|         console.log('fail'); | ||||
|     }); | ||||
| function showExpenses() { | ||||
|     if (expenseRestShow) { | ||||
|         // hide everything, make button say "show" | ||||
|         $('#showExpenses').text(showTheRestExpense); | ||||
|         $('.expenseCollapsed').removeClass('in').addClass('out'); | ||||
|  | ||||
|         // toggle: | ||||
|         expenseRestShow = false; | ||||
|     } else { | ||||
|         // show everything, make button say "hide". | ||||
|         $('#showExpenses').text(hideTheRestExpense); | ||||
|         $('.expenseCollapsed').removeClass('out').addClass('in'); | ||||
|  | ||||
|         // toggle: | ||||
|         expenseRestShow = true; | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
							
								
								
									
										89
									
								
								resources/lang/en/breadcrumbs.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								resources/lang/en/breadcrumbs.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| <?php | ||||
| return [ | ||||
|     'home'                  => 'Home', | ||||
|  | ||||
|     // accounts | ||||
|     'asset_accounts'        => 'Asset accounts', | ||||
|     'expense_accounts'      => 'Expense accounts', | ||||
|     'revenue_accounts'      => 'Revenue accounts', | ||||
|     'cash_accounts'         => 'Cash accounts', | ||||
|     'new_asset_account'     => 'New asset accounts', | ||||
|     'new_expense_account'   => 'New expense account', | ||||
|     'new_revenue_account'   => 'New revenue account', | ||||
|     'delete_account'        => 'Delete account ":name"', | ||||
|     'edit_account'          => 'Edit account ":name"', | ||||
|     'edit_asset_account'    => 'Edit asset account ":name"', | ||||
|     'edit_expense_account'  => 'Edit expense account ":name"', | ||||
|     'edit_revenue_account'  => 'Edit revenue account ":name"', | ||||
|  | ||||
|     // budgets | ||||
|     'budgets'               => 'Budgets', | ||||
|     'newBudget'             => 'Create a new budget', | ||||
|     'delete_budget'         => 'Delete budget ":name"', | ||||
|     'edit_budget'           => 'Edit budget ":name"', | ||||
|  | ||||
|     // categories | ||||
|     'categories'            => 'Categories', | ||||
|     'newCategory'           => 'Create a new categori', | ||||
|     'delete_category'       => 'Delete category ":name"', | ||||
|     'edit_category'         => 'Edit category ":name"', | ||||
|  | ||||
|     // currencies | ||||
|     'currencies'            => 'Currencies', | ||||
|     'edit_currency'         => 'Edit currencies ":name"', | ||||
|     'delete_currency'       => 'Delete currencies ":name"', | ||||
|  | ||||
|     // piggy banks | ||||
|     'piggyBanks'            => 'Piggy banks', | ||||
|     'newPiggyBank'          => 'Create a new piggy bank', | ||||
|     'edit_piggyBank'        => 'Edit piggy bank ":name"', | ||||
|     'delete_piggyBank'      => 'Delete piggy bank ":name"', | ||||
|  | ||||
|     // top menu | ||||
|     'preferences'           => 'Preferences', | ||||
|     'profile'               => 'Profile', | ||||
|     'changePassword'        => 'Change your password', | ||||
|  | ||||
|     // bills | ||||
|     'bills'                 => 'Bills', | ||||
|     'newBill'               => 'New bill', | ||||
|     'edit_bill'             => 'Edit bill ":name"', | ||||
|     'delete_bill'           => 'Delete bill ":name"', | ||||
|  | ||||
|     // reminders | ||||
|     'reminders'             => 'Reminders', | ||||
|     'reminder'              => 'Reminder #:id', | ||||
|  | ||||
|     // reports | ||||
|     'reports'               => 'Reports', | ||||
|     'monthly_report'        => 'Montly report for :date', | ||||
|     'monthly_report_shared' => 'Montly report for :date (including shared accounts)', | ||||
|     'yearly_report'         => 'Yearly report for :date', | ||||
|     'yearly_report_shared'  => 'Yearly report for :date (including shared accounts)', | ||||
|     'budget_report'         => 'Budget report for :date', | ||||
|  | ||||
|     // search | ||||
|     'searchResult'          => 'Search for ":query"', | ||||
|  | ||||
|     // transaction lists. | ||||
|     'withdrawal_list'       => 'Expenses', | ||||
|     'deposit_list'          => 'Revenue, income and deposits', | ||||
|     'transfer_list'         => 'Transfers', | ||||
|     'transfers_list'        => 'Transfers', | ||||
|  | ||||
|     // create transactions | ||||
|     'create_withdrawal'     => 'Create new withdrawal', | ||||
|     'create_deposit'        => 'Create new deposit', | ||||
|     'create_transfer'       => 'Create new transfer', | ||||
|  | ||||
|     // edit transactions | ||||
|     'edit_journal'          => 'Edit transaction ":description"', | ||||
|     'delete_journal'        => 'Delete transaction ":description"', | ||||
|  | ||||
|     // tags | ||||
|     'tags'                  => 'Tags', | ||||
|     'createTag'             => 'Create new tag', | ||||
|     'edit_tag'              => 'Edit tag ":tag"', | ||||
|     'delete_tag'            => 'Delete tag ":tag"', | ||||
|  | ||||
| ]; | ||||
| @@ -1,12 +1,201 @@ | ||||
| <?php | ||||
| return [ | ||||
|     'welcome'         => 'Welcome to Firefly!', | ||||
|     'mainTitle'       => 'What\'s playing?', | ||||
|     'close'           => 'Clone', | ||||
|     'pleaseHold'      => 'Please hold...', | ||||
|     'mandatoryFields' => 'Mandatory fields', | ||||
|     'optionalFields'  => 'Optional fields', | ||||
|     'options'         => 'Options', | ||||
|     'something'       => 'Something!' | ||||
|  | ||||
| return [ | ||||
|     'test'                          => 'You have selected English.', | ||||
|     'close'                         => 'Close', | ||||
|     'pleaseHold'                    => 'Please hold...', | ||||
|     'mandatoryFields'               => 'Mandatory fields', | ||||
|     'optionalFields'                => 'Optional fields', | ||||
|     'options'                       => 'Options', | ||||
|     'something'                     => 'Something!', | ||||
|     'actions'                       => 'Actions', | ||||
|     'edit'                          => 'Edit', | ||||
|     'delete'                        => 'Delete', | ||||
|     'welcomeBack'                   => 'What\'s playing?', | ||||
|  | ||||
|     'everything'                    => 'Everything', | ||||
|     'customRange'                   => 'Custom range', | ||||
|     'apply'                         => 'Apply', | ||||
|     'cancel'                        => 'Cancel', | ||||
|     'from'                          => 'From', | ||||
|     'to'                            => 'To', | ||||
|  | ||||
|     'showEverything'                => 'Show everything', | ||||
|     'create_new_budget'             => 'Create a new budget', | ||||
|     'store_new_budget'              => ' Store new budget', | ||||
|  | ||||
|     'availableIn'                   => 'Available in :date', | ||||
|     'transactionsWithoutBudget'     => 'Expenses without budget', | ||||
|     'transactionsWithoutBudgetDate' => 'Expenses without budget in :date', | ||||
|     'createBudget'                  => 'New budget', | ||||
|     'inactiveBudgets'               => 'Inactive budgets', | ||||
|     'newCategory'                   => 'New category', | ||||
|     'withoutCategory'               => 'Without a category', | ||||
|  | ||||
|     'details_for_asset'             => 'Details for asset account ":name"', | ||||
|     'details_for_expense'           => 'Details for expense account ":name"', | ||||
|     'details_for_revenue'           => 'Details for revenue account ":name"', | ||||
|     'details_for_cash'              => 'Details for cash account ":name"', | ||||
|  | ||||
|     'store_new_asset_account'       => 'Store new asset account', | ||||
|     'store_new_expense_account'     => 'Store new expense account', | ||||
|     'store_new_revenue_account'     => 'Store new revenue account', | ||||
|  | ||||
|     'edit_asset_account'            => 'Edit asset account ":name"', | ||||
|     'edit_expense_account'          => 'Edit expense account ":name"', | ||||
|     'edit_revenue_account'          => 'Edit revenue account ":name"', | ||||
|  | ||||
|     'update_asset_account'          => 'Update asset account', | ||||
|     'update_expense_account'        => 'Update expense account', | ||||
|     'update_revenue_account'        => 'Update revenue account', | ||||
|  | ||||
|     'make_new_asset_account'        => 'New asset account', | ||||
|     'make_new_expense_account'      => 'New expense account', | ||||
|     'make_new_revenue_account'      => 'New revenue account', | ||||
|  | ||||
|     // new user: | ||||
|     'welcome'                       => 'Welcome to Firefly!', | ||||
|     'createNewAsset'                => 'Create a new asset account to get started. This will allow you to create transactions and start your financial management', | ||||
|     'createNewAssetButton'          => 'Create new asset account', | ||||
|  | ||||
|     // home page: | ||||
|     'yourAccounts'                  => 'Your accounts', | ||||
|     'budgetsAndSpending'            => 'Budgets and spending', | ||||
|     'savings'                       => 'Savings', | ||||
|     'markAsSavingsToContinue'       => 'Mark your asset accounts as "Savings account" to fill this panel', | ||||
|     'createPiggyToContinue'         => 'Create piggy banks to fill this panel.', | ||||
|     'newWithdrawal'                 => 'New expense', | ||||
|     'newDeposit'                    => 'New deposit', | ||||
|     'newTransfer'                   => 'New transfer', | ||||
|     'moneyIn'                       => 'Money in', | ||||
|     'moneyOut'                      => 'Money out', | ||||
|     'billsToPay'                    => 'Bills to pay', | ||||
|     'billsPaid'                     => 'Bills paid', | ||||
|     'viewDetails'                   => 'View details', | ||||
|     'divided'                       => 'divided', | ||||
|     'toDivide'                      => 'left to divide', | ||||
|  | ||||
|     // menu and titles, should be recycled as often as possible: | ||||
|     'toggleNavigation'              => 'Toggle navigation', | ||||
|     'seeAllReminders'               => 'See all reminders', | ||||
|     'reminders'                     => 'Reminders', | ||||
|     'currency'                      => 'Currency', | ||||
|     'preferences'                   => 'Preferences', | ||||
|     'logout'                        => 'Logout', | ||||
|     'searchPlaceholder'             => 'Search...', | ||||
|     'dashboard'                     => 'Dashboard', | ||||
|     'currencies'                    => 'Currencies', | ||||
|     'accounts'                      => 'Accounts', | ||||
|     'assetAccounts'                 => 'Asset accounts', | ||||
|     'expenseAccounts'               => 'Expense accounts', | ||||
|     'revenueAccounts'               => 'Revenue accounts', | ||||
|     'Asset account'                 => 'Asset account', | ||||
|     'Default account'               => 'Asset account', | ||||
|     'Expense account'               => 'Expense account', | ||||
|     'Revenue account'               => 'Revenue account', | ||||
|     'budgets'                       => 'Budgets', | ||||
|     'categories'                    => 'Categories', | ||||
|     'tags'                          => 'Tags', | ||||
|     'reports'                       => 'Reports', | ||||
|     'transactions'                  => 'Transactions', | ||||
|     'expenses'                      => 'Expenses', | ||||
|     'income'                        => 'Revenue / income', | ||||
|     'transfers'                     => 'Transfer', | ||||
|     'moneyManagement'               => 'Money management', | ||||
|     'piggyBanks'                    => 'Piggy banks', | ||||
|     'bills'                         => 'Bills', | ||||
|     'createNew'                     => 'Create new', | ||||
|     'withdrawal'                    => 'Withdrawal', | ||||
|     'deposit'                       => 'Deposit', | ||||
|     'transfer'                      => 'Transfer', | ||||
|     'Withdrawal'                    => 'Withdrawal', | ||||
|     'Deposit'                       => 'Deposit', | ||||
|     'Transfer'                      => 'Transfer', | ||||
|     'bill'                          => 'Rekening', | ||||
|     'yes'                           => 'Yes', | ||||
|     'no'                            => 'No', | ||||
|     'amount'                        => 'Amount', | ||||
|     'newBalance'                    => 'New balance', | ||||
|     'overview'                      => 'Overview', | ||||
|     'saveOnAccount'                 => 'Save on account', | ||||
|     'unknown'                       => 'Unknown', | ||||
|     'daily'                         => 'Daily', | ||||
|     'weekly'                        => 'Weekly', | ||||
|     'monthly'                       => 'Monthly', | ||||
|     'quarterly'                     => 'Quarterly', | ||||
|     'half-year'                     => 'Every six months', | ||||
|     'yearly'                        => 'Yearly', | ||||
|  | ||||
|     'reportForYear'                 => 'Yearly report for :year', | ||||
|     'reportForYearShared'           => 'Yearly report for :year (including shared accounts)', | ||||
|     'reportForMonth'                => 'Montly report for :year', | ||||
|     'reportForMonthShared'          => 'Montly report for :year (including shared accounts)', | ||||
|     'incomeVsExpenses'              => 'Income vs. expenses', | ||||
|     'accountBalances'               => 'Account balances', | ||||
|     'balanceStartOfYear'            => 'Balance at start of year', | ||||
|     'balanceEndOfYear'              => 'Balance at end of year', | ||||
|     'balanceStartOfMonth'           => 'Balance at end of month', | ||||
|     'balanceEndOfMonth'             => 'Balance at end of month', | ||||
|  | ||||
|     'balanceStart'                  => 'Balance at end of period', | ||||
|     'balanceEnd'                    => 'Balance at end of period', | ||||
|  | ||||
|     'reportsOwnAccounts'            => 'Reports for your own accounts', | ||||
|     'reportsOwnAccountsAndShared'   => 'Reports for your own accounts and shared accounts', | ||||
|  | ||||
|     'account'                       => 'Account', | ||||
|  | ||||
|     'splitByAccount'                => 'Split by account', | ||||
|     'balancedByTransfersAndTags'    => 'Balanced by transfers and tags', | ||||
|     'coveredWithTags'               => 'Covered with tags', | ||||
|     'leftUnbalanced'                => 'Left unbalanced', | ||||
|     'expectedBalance'               => 'Expected balance', | ||||
|     'outsideOfBudgets'              => 'Outside of budgets', | ||||
|     'leftInBudget'                  => 'Left in budget', | ||||
|  | ||||
|     'sumOfSums'                     => 'Sum of sums', | ||||
|     'notCharged'                    => 'Not charged (yet)', | ||||
|     'inactive'                      => 'Inactive', | ||||
|  | ||||
|     'difference'                    => 'Difference', | ||||
|     'in'                            => 'In', | ||||
|     'out'                           => 'Out', | ||||
|     'topX'                          => 'top :number', | ||||
|     'showTheRest'                   => 'Show everything', | ||||
|     'hideTheRest'                   => 'Show only the top :number', | ||||
|  | ||||
|     // charts: | ||||
|     'dayOfMonth'                    => 'Day of the month', | ||||
|     'month'                         => 'Month', | ||||
|     'budget'                        => 'Budget', | ||||
|     'spent'                         => 'Spent', | ||||
|     'overspent'                     => 'Overspent', | ||||
|     'left'                          => 'Left', | ||||
|     'noCategory'                    => '(no category)', | ||||
|     'noBudget'                      => '(no budget)', | ||||
|     'category'                      => 'Category', | ||||
|     'maxAmount'                     => 'Maximum amount', | ||||
|     'minAmount'                     => 'Minumum amount', | ||||
|     'billEntry'                     => 'Current bill entry', | ||||
|     'name'                          => 'Name', | ||||
|     'date'                          => 'Date', | ||||
|     'paid'                          => 'Paid', | ||||
|     'unpaid'                        => 'Unpaid', | ||||
|     'day'                           => 'Day', | ||||
|     'budgeted'                      => 'Budgeted', | ||||
|     'period'                        => 'Period', | ||||
|     'balance'                       => 'Balance', | ||||
|     'summary'                       => 'Summary', | ||||
|     'sum'                           => 'Sum', | ||||
|     'average'                       => 'Average', | ||||
|     'balanceFor'                    => 'Balance for :name', | ||||
|  | ||||
|     'asset_accounts'                => 'Asset accounts', | ||||
|     'expense_accounts'              => 'Expense accounts', | ||||
|     'revenue_accounts'              => 'Revenue accounts', | ||||
|  | ||||
|     // some extra help: | ||||
|     'accountExtraHelp_asset'        => '', | ||||
|     'accountExtraHelp_expense'      => '', | ||||
|     'accountExtraHelp_revenue'      => '', | ||||
| ]; | ||||
|   | ||||
							
								
								
									
										78
									
								
								resources/lang/en/form.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								resources/lang/en/form.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| <?php | ||||
| return [ | ||||
|     'name'                        => 'Name', | ||||
|     'active'                      => 'Active', | ||||
|     'amount_min'                  => 'Minimum amount', | ||||
|     'amount_max'                  => 'Maximum amount', | ||||
|     'match'                       => 'Matches on', | ||||
|     'repeat_freq'                 => 'Repeats', | ||||
|     'account_from_id'             => 'From account', | ||||
|     'account_to_id'               => 'To account', | ||||
|     'account_id'                  => 'Asset account', | ||||
|     'budget_id'                   => 'Budget', | ||||
|     'openingBalance'              => 'Opening balance', | ||||
|     'tagMode'                     => 'Tag mode', | ||||
|     'tagPosition'                 => 'Tag location', | ||||
|     'virtualBalance'              => 'Virtual balance', | ||||
|     'longitude_latitude'          => 'Location', | ||||
|     'targetamount'                => 'Target amount', | ||||
|     'accountRole'                 => 'Account role', | ||||
|     'openingBalanceDate'          => 'Opening balance date', | ||||
|     'ccType'                      => 'Credit card payment plan', | ||||
|     'ccMonthlyPaymentDate'        => 'Credit card monthly payment date', | ||||
|     'piggy_bank_id'               => 'Piggy bank', | ||||
|     'returnHere'                  => 'Return here', | ||||
|     'returnHereExplanation'       => 'After storing, return here to create another one.', | ||||
|     'returnHereUpdateExplanation' => 'After updating, return here.', | ||||
|     'description'                 => 'Description', | ||||
|     'expense_account'             => 'Expense account', | ||||
|     'revenue_account'             => 'Revenue account', | ||||
|     'amount'                      => 'Amount', | ||||
|     'date'                        => 'Date', | ||||
|     'category'                    => 'Category', | ||||
|     'tags'                        => 'Tags', | ||||
|     'deletePermanently'           => 'Delete permanently', | ||||
|     'cancel'                      => 'Cancel', | ||||
|     'targetdate'                  => 'Target date', | ||||
|     'remind_me'                   => 'Remind me', | ||||
|     'tag'                         => 'Tag', | ||||
|     'reminder'                    => 'Remind me every', | ||||
|     'under'                       => 'Under', | ||||
|  | ||||
|     'store_new_withdrawal'        => 'Store new withdrawal', | ||||
|     'store_new_deposit'           => 'Store new deposit', | ||||
|     'store_new_transfer'          => 'Store new transfer', | ||||
|     'add_new_withdrawal'          => 'Add a new withdrawal', | ||||
|     'add_new_deposit'             => 'Add a new deposit', | ||||
|     'add_new_transfer'            => 'Add a new transfer', | ||||
|     'noPiggybank'                 => '(no piggy bank)', | ||||
|     'noBudget'                    => '(no budget)', | ||||
|  | ||||
|     'delete_account'              => 'Delete account ":name"', | ||||
|     'delete_bill'                 => 'Delete bill ":name"', | ||||
|     'delete_budget'               => 'Delete budget ":name"', | ||||
|     'delete_category'             => 'Delete category ":name"', | ||||
|     'delete_currency'             => 'Delete currency ":name"', | ||||
|     'delete_piggyBank'            => 'Delete piggy banl ":name"', | ||||
|     'delete_journal'              => 'Delete transaction with description ":description"', | ||||
|  | ||||
|     'account_areYouSure'          => 'Are you sure you want to delete the account named ":name"?', | ||||
|     'bill_areYouSure'             => 'Are you sure you want to delete the bill named ":name"?', | ||||
|     'budget_areYouSure'           => 'Are you sure you want to delete the budget named ":name"?', | ||||
|     'category_areYouSure'         => 'Are you sure you want to delete the category named ":name"?', | ||||
|     'currency_areYouSure'         => 'Are you sure you want to delete the currency named ":name"?', | ||||
|     'piggyBank_areYouSure'        => 'Are you sure you want to delete the piggy bank named ":name"?', | ||||
|     'journal_areYouSure'          => 'Are you sure you want to delete the transaction described ":description"?', | ||||
|  | ||||
|     'permDeleteWarning'           => 'Deleting stuff from Firely is permanent and cannot be undone.', | ||||
|     'also_delete_transactions'    => 'The only transaction connected to this account will be deleted as well.' . | ||||
|                                      '|All :count transactions connected to this account will be deleted as well.', | ||||
|     'also_delete_piggyBanks'      => 'The only piggy bank connected to this account will be deleted as well.' . | ||||
|                                      '|All :count piggy bank connected to this account will be deleted as well.', | ||||
|     'bill_keep_transactions'      => 'The only transaction connected to this bill will not be deleted.' . | ||||
|                                      '|All :count transactions connected to this bill will spared deletion.', | ||||
|     'budget_keep_transactions'    => 'The only transaction connected to this budget will not be deleted.' . | ||||
|                                      '|All :count transactions connected to this budget will spared deletion.', | ||||
|     'category_keep_transactions'  => 'The only transaction connected to this category will not be deleted.' . | ||||
|                                      '|All :count transactions connected to this category will spared deletion.', | ||||
| ]; | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user