mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 02:36:28 +00:00 
			
		
		
		
	Cleaned up the chart controller.
This commit is contained in:
		| @@ -186,16 +186,26 @@ class ChartController extends BaseController | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method gets all transactions within a budget within the period set by the current session | ||||
|      * start and end date. It also includes any envelopes which might exist within this period. | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function budgetSession(\Budget $budget) | ||||
|     { | ||||
|         $expense          = []; | ||||
|         $repetitionSeries = []; | ||||
|         $current          = clone Session::get('start'); | ||||
|         $end              = clone Session::get('end'); | ||||
|         $series = []; | ||||
|         $end    = clone Session::get('end'); | ||||
|         $start  = clone Session::get('start'); | ||||
|  | ||||
|  | ||||
|  | ||||
|         /* | ||||
|          * Expenses per day in the session's period. That's easy. | ||||
|          */ | ||||
|         $expense = []; | ||||
|         $current = clone Session::get('start'); | ||||
|         while ($current <= $end) { | ||||
|             $spent     = $this->_chart->spentOnDay($budget, $current); | ||||
|             $spent     = floatval($spent) == 0 ? null : floatval($spent); | ||||
| @@ -203,89 +213,66 @@ class ChartController extends BaseController | ||||
|             $current->addDay(); | ||||
|         } | ||||
|  | ||||
|         // find all limit repetitions (for this budget) between start and end. | ||||
|         $start              = clone Session::get('start'); | ||||
|         $repetitionSeries[] = [ | ||||
|         $series[] = [ | ||||
|             'type' => 'column', | ||||
|             'name' => 'Expenses per day', | ||||
|             'data' => $expense | ||||
|         ]; | ||||
|         unset($expense, $spent, $current); | ||||
|  | ||||
|         /* | ||||
|          * Find all limit repetitions (for this budget) between start and end. This is | ||||
|          * quite a complex query. | ||||
|          */ | ||||
|         $reps = $this->_chart->limitsInRange($budget, $start, $end); | ||||
|  | ||||
|         /** @var \Limit $limit */ | ||||
|         foreach ($budget->limits as $limit) { | ||||
|             $reps               = $limit->limitrepetitions()->where( | ||||
|                 function ($q) use ($start, $end) { | ||||
|                     // startdate is between range | ||||
|                     $q->where( | ||||
|                         function ($q) use ($start, $end) { | ||||
|                             $q->where('startdate', '>=', $start->format('Y-m-d')); | ||||
|                             $q->where('startdate', '<=', $end->format('Y-m-d')); | ||||
|                         } | ||||
|         /* | ||||
|          * For each limitrepetition we create a serie that contains the amount left in | ||||
|          * the limitrepetition for its entire date-range. Entries are only actually included when they | ||||
|          * fall into the charts date range. | ||||
|          * | ||||
|          * So example: we have a session date from Jan 15 to Jan 30. The limitrepetition starts at 1 Jan until 1 Feb. | ||||
|          * | ||||
|          * We loop from 1 Jan to 1 Feb but only include Jan 15 / Jan 30. But we do keep count of the amount outside | ||||
|          * of these dates because otherwise the line might be wrong. | ||||
|          */ | ||||
|         /** @var \LimitRepetition $repetition */ | ||||
|         foreach ($reps as $repetition) { | ||||
|             $limitAmount = $repetition->limit->amount; | ||||
|  | ||||
|             // create a serie for the repetition. | ||||
|             $currentSerie = [ | ||||
|                 'type'  => 'spline', | ||||
|                 'id'    => 'rep-' . $repetition->id, | ||||
|                 'yAxis' => 1, | ||||
|                 'name'  => 'Envelope #'.$repetition->id.' in ' . $repetition->periodShow(), | ||||
|                 'data'  => [] | ||||
|             ]; | ||||
|             $current      = clone $repetition->startdate; | ||||
|             while ($current <= $repetition->enddate) { | ||||
|                 if ($current >= $start && $current <= $end) { | ||||
|                     // spent on limit: | ||||
|                     $spentSoFar  = $this->_chart->spentOnLimitRepetitionBetweenDates( | ||||
|                         $repetition, $repetition->startdate, $current | ||||
|                     ); | ||||
|                     $leftInLimit = floatval($limitAmount) - floatval($spentSoFar); | ||||
|  | ||||
|                     // or enddate is between range. | ||||
|                     $q->orWhere( | ||||
|                         function ($q) use ($start, $end) { | ||||
|                             $q->where('enddate', '>=', $start->format('Y-m-d')); | ||||
|                             $q->where('enddate', '<=', $end->format('Y-m-d')); | ||||
|                         } | ||||
|                     ); | ||||
|                     $currentSerie['data'][] = [$current->timestamp * 1000, $leftInLimit]; | ||||
|                 } | ||||
|             )->get(); | ||||
|             $currentLeftInLimit = floatval($limit->amount); | ||||
|             /** @var \LimitRepetition $repetition */ | ||||
|             foreach ($reps as $repetition) { | ||||
|                 // create a serie for the repetition. | ||||
|                 $currentSerie = [ | ||||
|                     'type'  => 'spline', | ||||
|                     'id'    => 'rep-' . $repetition->id, | ||||
|                     'yAxis' => 1, | ||||
|                     'name'  => 'Envelope in ' . $repetition->periodShow(), | ||||
|                     'data'  => [] | ||||
|                 ]; | ||||
|                 $current      = clone $repetition->startdate; | ||||
|                 while ($current <= $repetition->enddate) { | ||||
|                     if ($current >= Session::get('start') && $current <= Session::get('end')) { | ||||
|                         // spent on limit: | ||||
|  | ||||
|                         $spentSoFar         = \Transaction:: | ||||
|                             leftJoin( | ||||
|                                 'transaction_journals', 'transaction_journals.id', '=', | ||||
|                                 'transactions.transaction_journal_id' | ||||
|                             ) | ||||
|                             ->leftJoin( | ||||
|                                 'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', | ||||
|                                 '=', | ||||
|                                 'transaction_journals.id' | ||||
|                             )->where('component_transaction_journal.component_id', '=', $budget->id)->where( | ||||
|                                 'transaction_journals.date', '>=', $repetition->startdate->format('Y-m-d') | ||||
|                             )->where('transaction_journals.date', '<=', $current->format('Y-m-d'))->where( | ||||
|                                 'amount', '>', 0 | ||||
|                             )->sum('amount'); | ||||
|                         $spent              = floatval($spent) == 0 ? null : floatval($spent); | ||||
|                         $currentLeftInLimit = floatval($limit->amount) - floatval($spentSoFar); | ||||
|  | ||||
|                         $currentSerie['data'][] = [$current->timestamp * 1000, $currentLeftInLimit]; | ||||
|                     } | ||||
|                     $current->addDay(); | ||||
|                 } | ||||
|  | ||||
|                 // do something here. | ||||
|                 $repetitionSeries[] = $currentSerie; | ||||
|  | ||||
|                 $current->addDay(); | ||||
|             } | ||||
|  | ||||
|             // do something here. | ||||
|             $series[] = $currentSerie; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         $return = [ | ||||
|             'chart_title' => 'Overview for budget ' . $budget->name, | ||||
|             'subtitle'    => | ||||
|                 'Between ' . Session::get('start')->format('M jS, Y') . ' and ' . Session::get('end')->format( | ||||
|                     'M jS, Y' | ||||
|                 ), | ||||
|             'series'      => $repetitionSeries | ||||
|             'series'      => $series | ||||
|         ]; | ||||
|  | ||||
|         return Response::json($return); | ||||
|   | ||||
| @@ -4,6 +4,7 @@ namespace Firefly\Helper\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Firefly\Exception\FireflyException; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class Chart | ||||
| @@ -117,6 +118,7 @@ class Chart implements ChartInterface | ||||
|         $limitInPeriod = ''; | ||||
|         $spentInPeriod = ''; | ||||
|  | ||||
|         /** @var \Budget $budget */ | ||||
|         foreach ($budgets as $budget) { | ||||
|             $budget->count = 0; | ||||
|             foreach ($budget->limits as $limit) { | ||||
| @@ -144,6 +146,23 @@ class Chart implements ChartInterface | ||||
|                 } | ||||
|                 $budget->count += count($limit->limitrepetitions); | ||||
|             } | ||||
|             if ($budget->count == 0) { | ||||
|                 // get expenses in period until today, starting at $start. | ||||
|                 $end                   = \Session::get('end'); | ||||
|                 $expenses              = $budget->transactionjournals()->after($start)->before($end) | ||||
|                     ->transactionTypes( | ||||
|                         ['Withdrawal'] | ||||
|                     )->get(); | ||||
|                 $budget->spentInPeriod = 0; | ||||
|                 /** @var \TransactionJournal $expense */ | ||||
|                 foreach ($expenses as $expense) { | ||||
|                     $transaction = $expense->transactions[1]; | ||||
|                     if (!is_null($transaction)) { | ||||
|                         $budget->spentInPeriod += floatval($transaction->amount); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
| @@ -162,15 +181,24 @@ class Chart implements ChartInterface | ||||
|         foreach ($budgets as $budget) { | ||||
|             if ($budget->count > 0) { | ||||
|                 $data['labels'][] = wordwrap($budget->name, 12, "<br>"); | ||||
|             } | ||||
|             foreach ($budget->limits as $limit) { | ||||
|                 foreach ($limit->limitrepetitions as $rep) { | ||||
|                     //0: envelope for period: | ||||
|                     $amount                      = floatval($rep->amount); | ||||
|                     $spent                       = $rep->spent; | ||||
|                     $color                       = $spent > $amount ? '#FF0000' : null; | ||||
|                     $data['series'][0]['data'][] = ['y' => $amount, 'id' => 'amount-' . $rep->id]; | ||||
|                     $data['series'][1]['data'][] = ['y' => $rep->spent, 'color' => $color, 'id' => 'spent-' . $rep->id]; | ||||
|                 foreach ($budget->limits as $limit) { | ||||
|                     foreach ($limit->limitrepetitions as $rep) { | ||||
|                         //0: envelope for period: | ||||
|                         $amount                      = floatval($rep->amount); | ||||
|                         $spent                       = $rep->spent; | ||||
|                         $color                       = $spent > $amount ? '#FF0000' : null; | ||||
|                         $data['series'][0]['data'][] = ['y' => $amount, 'id' => 'amount-' . $rep->id]; | ||||
|                         $data['series'][1]['data'][] = ['y'  => $rep->spent, 'color' => $color, | ||||
|                                                         'id' => 'spent-' . $rep->id]; | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 // add for "empty" budget: | ||||
|                 if ($budget->spentInPeriod > 0) { | ||||
|                     $data['labels'][]            = wordwrap($budget->name, 12, "<br>"); | ||||
|                     $data['series'][0]['data'][] = ['y' => null, 'id' => 'amount-norep-' . $budget->id]; | ||||
|                     $data['series'][1]['data'][] = ['y'  => $budget->spentInPeriod, | ||||
|                                                     'id' => 'spent-norep-' . $budget->id]; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
| @@ -482,5 +510,69 @@ class Chart implements ChartInterface | ||||
|         return $transactions; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all limit (LimitRepetitions) for a budget falling in a certain date range. | ||||
|      * | ||||
|      * @param \Budget $budget | ||||
|      * @param Carbon  $start | ||||
|      * @param Carbon  $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function limitsInRange(\Budget $budget, Carbon $start, Carbon $end) | ||||
|     { | ||||
|         $reps = new Collection; | ||||
|         /** @var \Limit $limit */ | ||||
|         foreach ($budget->limits as $limit) { | ||||
|             $set = $limit->limitrepetitions()->where( | ||||
|                 function ($q) use ($start, $end) { | ||||
|                     // startdate is between range | ||||
|                     $q->where( | ||||
|                         function ($q) use ($start, $end) { | ||||
|                             $q->where('startdate', '>=', $start->format('Y-m-d')); | ||||
|                             $q->where('startdate', '<=', $end->format('Y-m-d')); | ||||
|                         } | ||||
|                     ); | ||||
|  | ||||
|                     // or enddate is between range. | ||||
|                     $q->orWhere( | ||||
|                         function ($q) use ($start, $end) { | ||||
|                             $q->where('enddate', '>=', $start->format('Y-m-d')); | ||||
|                             $q->where('enddate', '<=', $end->format('Y-m-d')); | ||||
|                         } | ||||
|                     ); | ||||
|                 } | ||||
|             )->get(); | ||||
|  | ||||
|             $reps = $reps->merge($set); | ||||
|         } | ||||
|         return $reps; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * We check how much money has been spend on the limitrepetition (aka: the current envelope) in the period denoted. | ||||
|      * Aka, we have a certain amount of money in an envelope and we wish to know how much we've spent between the dates | ||||
|      * entered. This can be a partial match with the date range of the envelope or no match at all. | ||||
|      * | ||||
|      * @param \LimitRepetition $repetition | ||||
|      * @param Carbon           $start | ||||
|      * @param Carbon           $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function spentOnLimitRepetitionBetweenDates(\LimitRepetition $repetition, Carbon $start, Carbon $end) { | ||||
|         return floatval( | ||||
|             \Transaction:: | ||||
|             leftJoin('transaction_journals', 'transaction_journals.id', '=','transactions.transaction_journal_id') | ||||
|             ->leftJoin('component_transaction_journal', 'component_transaction_journal.transaction_journal_id','=', | ||||
|                 'transaction_journals.id' | ||||
|             )->where('component_transaction_journal.component_id', '=', $repetition->limit->budget->id)->where( | ||||
|                 'transaction_journals.date', '>=', $start->format('Y-m-d') | ||||
|             )->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->where( | ||||
|                 'amount', '>', 0 | ||||
|             )->sum('amount')) ; | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -85,7 +85,30 @@ interface ChartInterface | ||||
|      */ | ||||
|     public function transactionsByJournals(array $set); | ||||
|  | ||||
|     /** | ||||
|      * Get all limit (LimitRepetitions) for a budget falling in a certain date range. | ||||
|      * | ||||
|      * @param \Budget $budget | ||||
|      * @param Carbon $start | ||||
|      * @param Carbon $end | ||||
|      * | ||||
|      * @return Collection | ||||
|      */ | ||||
|     public function limitsInRange(\Budget $budget, Carbon $start, Carbon $end); | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * We check how much money has been spend on the limitrepetition (aka: the current envelope) in the period denoted. | ||||
|      * Aka, we have a certain amount of money in an envelope and we wish to know how much we've spent between the dates | ||||
|      * entered. This can be a partial match with the date range of the envelope or no match at all. | ||||
|      * | ||||
|      * @param \LimitRepetition $repetition | ||||
|      * @param Carbon           $start | ||||
|      * @param Carbon           $end | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function spentOnLimitRepetitionBetweenDates(\LimitRepetition $repetition, Carbon $start, Carbon $end); | ||||
|  | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user