mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Cleaned up the chart controller.
This commit is contained in:
parent
77f4111b09
commit
71b11e26d2
@ -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
|
* @param Budget $budget
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function budgetSession(\Budget $budget)
|
public function budgetSession(\Budget $budget)
|
||||||
{
|
{
|
||||||
$expense = [];
|
$series = [];
|
||||||
$repetitionSeries = [];
|
$end = clone Session::get('end');
|
||||||
$current = clone Session::get('start');
|
$start = clone Session::get('start');
|
||||||
$end = clone Session::get('end');
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Expenses per day in the session's period. That's easy.
|
||||||
|
*/
|
||||||
|
$expense = [];
|
||||||
|
$current = clone Session::get('start');
|
||||||
while ($current <= $end) {
|
while ($current <= $end) {
|
||||||
$spent = $this->_chart->spentOnDay($budget, $current);
|
$spent = $this->_chart->spentOnDay($budget, $current);
|
||||||
$spent = floatval($spent) == 0 ? null : floatval($spent);
|
$spent = floatval($spent) == 0 ? null : floatval($spent);
|
||||||
@ -203,89 +213,66 @@ class ChartController extends BaseController
|
|||||||
$current->addDay();
|
$current->addDay();
|
||||||
}
|
}
|
||||||
|
|
||||||
// find all limit repetitions (for this budget) between start and end.
|
$series[] = [
|
||||||
$start = clone Session::get('start');
|
|
||||||
$repetitionSeries[] = [
|
|
||||||
'type' => 'column',
|
'type' => 'column',
|
||||||
'name' => 'Expenses per day',
|
'name' => 'Expenses per day',
|
||||||
'data' => $expense
|
'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) {
|
* For each limitrepetition we create a serie that contains the amount left in
|
||||||
$reps = $limit->limitrepetitions()->where(
|
* the limitrepetition for its entire date-range. Entries are only actually included when they
|
||||||
function ($q) use ($start, $end) {
|
* fall into the charts date range.
|
||||||
// startdate is between range
|
*
|
||||||
$q->where(
|
* So example: we have a session date from Jan 15 to Jan 30. The limitrepetition starts at 1 Jan until 1 Feb.
|
||||||
function ($q) use ($start, $end) {
|
*
|
||||||
$q->where('startdate', '>=', $start->format('Y-m-d'));
|
* We loop from 1 Jan to 1 Feb but only include Jan 15 / Jan 30. But we do keep count of the amount outside
|
||||||
$q->where('startdate', '<=', $end->format('Y-m-d'));
|
* 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.
|
$currentSerie['data'][] = [$current->timestamp * 1000, $leftInLimit];
|
||||||
$q->orWhere(
|
|
||||||
function ($q) use ($start, $end) {
|
|
||||||
$q->where('enddate', '>=', $start->format('Y-m-d'));
|
|
||||||
$q->where('enddate', '<=', $end->format('Y-m-d'));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
)->get();
|
$current->addDay();
|
||||||
$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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do something here.
|
||||||
|
$series[] = $currentSerie;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$return = [
|
$return = [
|
||||||
'chart_title' => 'Overview for budget ' . $budget->name,
|
'chart_title' => 'Overview for budget ' . $budget->name,
|
||||||
'subtitle' =>
|
'subtitle' =>
|
||||||
'Between ' . Session::get('start')->format('M jS, Y') . ' and ' . Session::get('end')->format(
|
'Between ' . Session::get('start')->format('M jS, Y') . ' and ' . Session::get('end')->format(
|
||||||
'M jS, Y'
|
'M jS, Y'
|
||||||
),
|
),
|
||||||
'series' => $repetitionSeries
|
'series' => $series
|
||||||
];
|
];
|
||||||
|
|
||||||
return Response::json($return);
|
return Response::json($return);
|
||||||
|
@ -4,6 +4,7 @@ namespace Firefly\Helper\Controllers;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Firefly\Exception\FireflyException;
|
use Firefly\Exception\FireflyException;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Chart
|
* Class Chart
|
||||||
@ -117,6 +118,7 @@ class Chart implements ChartInterface
|
|||||||
$limitInPeriod = '';
|
$limitInPeriod = '';
|
||||||
$spentInPeriod = '';
|
$spentInPeriod = '';
|
||||||
|
|
||||||
|
/** @var \Budget $budget */
|
||||||
foreach ($budgets as $budget) {
|
foreach ($budgets as $budget) {
|
||||||
$budget->count = 0;
|
$budget->count = 0;
|
||||||
foreach ($budget->limits as $limit) {
|
foreach ($budget->limits as $limit) {
|
||||||
@ -144,6 +146,23 @@ class Chart implements ChartInterface
|
|||||||
}
|
}
|
||||||
$budget->count += count($limit->limitrepetitions);
|
$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) {
|
foreach ($budgets as $budget) {
|
||||||
if ($budget->count > 0) {
|
if ($budget->count > 0) {
|
||||||
$data['labels'][] = wordwrap($budget->name, 12, "<br>");
|
$data['labels'][] = wordwrap($budget->name, 12, "<br>");
|
||||||
}
|
foreach ($budget->limits as $limit) {
|
||||||
foreach ($budget->limits as $limit) {
|
foreach ($limit->limitrepetitions as $rep) {
|
||||||
foreach ($limit->limitrepetitions as $rep) {
|
//0: envelope for period:
|
||||||
//0: envelope for period:
|
$amount = floatval($rep->amount);
|
||||||
$amount = floatval($rep->amount);
|
$spent = $rep->spent;
|
||||||
$spent = $rep->spent;
|
$color = $spent > $amount ? '#FF0000' : null;
|
||||||
$color = $spent > $amount ? '#FF0000' : null;
|
$data['series'][0]['data'][] = ['y' => $amount, 'id' => 'amount-' . $rep->id];
|
||||||
$data['series'][0]['data'][] = ['y' => $amount, 'id' => 'amount-' . $rep->id];
|
$data['series'][1]['data'][] = ['y' => $rep->spent, 'color' => $color,
|
||||||
$data['series'][1]['data'][] = ['y' => $rep->spent, 'color' => $color, 'id' => 'spent-' . $rep->id];
|
'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;
|
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);
|
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);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user