mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-19 19:01:58 +00:00
Reorganized the category charts in the year report to properly reflect income and expenses. Necessary to facilitate the changes needed for bug #99
This commit is contained in:
@@ -40,5 +40,13 @@ interface CategoryChartGenerator
|
|||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function year(Collection $categories, Collection $entries);
|
public function spentInYear(Collection $categories, Collection $entries);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $categories
|
||||||
|
* @param Collection $entries
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function earnedInYear(Collection $categories, Collection $entries);
|
||||||
}
|
}
|
||||||
|
@@ -93,7 +93,41 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
|
|||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function year(Collection $categories, Collection $entries)
|
public function spentInYear(Collection $categories, Collection $entries)
|
||||||
|
{
|
||||||
|
|
||||||
|
// language:
|
||||||
|
$language = Preferences::get('language', 'en')->data;
|
||||||
|
$format = Config::get('firefly.month.' . $language);
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'count' => 0,
|
||||||
|
'labels' => [],
|
||||||
|
'datasets' => [],
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($categories as $category) {
|
||||||
|
$data['labels'][] = $category->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
$date = $entry[0]->formatLocalized($format);
|
||||||
|
array_shift($entry);
|
||||||
|
$data['count']++;
|
||||||
|
$data['datasets'][] = ['label' => $date, 'data' => $entry];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $categories
|
||||||
|
* @param Collection $entries
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function earnedInYear(Collection $categories, Collection $entries)
|
||||||
{
|
{
|
||||||
|
|
||||||
// language:
|
// language:
|
||||||
|
@@ -86,7 +86,31 @@ class GoogleCategoryChartGenerator implements CategoryChartGenerator
|
|||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function year(Collection $categories, Collection $entries)
|
public function spentInYear(Collection $categories, Collection $entries)
|
||||||
|
{
|
||||||
|
$chart = new GChart;
|
||||||
|
|
||||||
|
$chart->addColumn(trans('firefly.month'), 'date');
|
||||||
|
foreach ($categories as $category) {
|
||||||
|
$chart->addColumn($category->name, 'number');
|
||||||
|
}
|
||||||
|
/** @var array $entry */
|
||||||
|
foreach ($entries as $entry) {
|
||||||
|
$chart->addRowArray($entry);
|
||||||
|
}
|
||||||
|
$chart->generate();
|
||||||
|
|
||||||
|
return $chart->getData();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Collection $categories
|
||||||
|
* @param Collection $entries
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function earnedInYear(Collection $categories, Collection $entries)
|
||||||
{
|
{
|
||||||
$chart = new GChart;
|
$chart = new GChart;
|
||||||
|
|
||||||
|
@@ -50,7 +50,6 @@ class CategoryController extends Controller
|
|||||||
$range = Preferences::get('viewRange', '1M')->data;
|
$range = Preferences::get('viewRange', '1M')->data;
|
||||||
$start = Navigation::startOfPeriod($start, $range);
|
$start = Navigation::startOfPeriod($start, $range);
|
||||||
$end = new Carbon;
|
$end = new Carbon;
|
||||||
|
|
||||||
$entries = new Collection;
|
$entries = new Collection;
|
||||||
|
|
||||||
|
|
||||||
@@ -170,7 +169,7 @@ class CategoryController extends Controller
|
|||||||
*
|
*
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
*/
|
*/
|
||||||
public function year(CategoryRepositoryInterface $repository, $year, $shared = false)
|
public function spentInYear(CategoryRepositoryInterface $repository, $year, $shared = false)
|
||||||
{
|
{
|
||||||
$start = new Carbon($year . '-01-01');
|
$start = new Carbon($year . '-01-01');
|
||||||
$end = new Carbon($year . '-12-31');
|
$end = new Carbon($year . '-12-31');
|
||||||
@@ -179,14 +178,23 @@ class CategoryController extends Controller
|
|||||||
$cache->addProperty($start);
|
$cache->addProperty($start);
|
||||||
$cache->addProperty($end);
|
$cache->addProperty($end);
|
||||||
$cache->addProperty('category');
|
$cache->addProperty('category');
|
||||||
$cache->addProperty('year');
|
$cache->addProperty('spent-in-year');
|
||||||
if ($cache->has()) {
|
if ($cache->has()) {
|
||||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||||
}
|
}
|
||||||
|
|
||||||
$shared = $shared == 'shared' ? true : false;
|
$shared = $shared == 'shared' ? true : false;
|
||||||
$categories = $repository->getCategories();
|
$allCategories = $repository->getCategories();
|
||||||
$entries = new Collection;
|
$entries = new Collection;
|
||||||
|
$categories = new Collection;
|
||||||
|
|
||||||
|
// filter by checking the entire year first:
|
||||||
|
foreach ($allCategories as $category) {
|
||||||
|
$spent = $repository->spentInPeriodCorrected($category, $start, $end, $shared);
|
||||||
|
if ($spent < 0) {
|
||||||
|
$categories->push($category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while ($start < $end) {
|
while ($start < $end) {
|
||||||
$month = clone $start; // month is the current end of the period
|
$month = clone $start; // month is the current end of the period
|
||||||
@@ -195,14 +203,83 @@ class CategoryController extends Controller
|
|||||||
|
|
||||||
foreach ($categories as $category) { // each budget, fill the row
|
foreach ($categories as $category) { // each budget, fill the row
|
||||||
$spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
|
$spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
|
||||||
|
if ($spent < 0) {
|
||||||
|
$spent = $spent * -1;
|
||||||
$row[] = $spent;
|
$row[] = $spent;
|
||||||
|
} else {
|
||||||
|
$row[] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
$entries->push($row);
|
$entries->push($row);
|
||||||
|
|
||||||
$start->addMonth();
|
$start->addMonth();
|
||||||
}
|
}
|
||||||
|
|
||||||
$data = $this->generator->year($categories, $entries);
|
$data = $this->generator->spentInYear($categories, $entries);
|
||||||
|
$cache->store($data);
|
||||||
|
|
||||||
|
return Response::json($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This chart will only show income.
|
||||||
|
*
|
||||||
|
* @param CategoryRepositoryInterface $repository
|
||||||
|
* @param $year
|
||||||
|
* @param bool $shared
|
||||||
|
*
|
||||||
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
|
*/
|
||||||
|
public function earnedInYear(CategoryRepositoryInterface $repository, $year, $shared = false)
|
||||||
|
{
|
||||||
|
$start = new Carbon($year . '-01-01');
|
||||||
|
$end = new Carbon($year . '-12-31');
|
||||||
|
|
||||||
|
$cache = new CacheProperties; // chart properties for cache:
|
||||||
|
$cache->addProperty($start);
|
||||||
|
$cache->addProperty($end);
|
||||||
|
$cache->addProperty('category');
|
||||||
|
$cache->addProperty('earned-in-year');
|
||||||
|
if ($cache->has()) {
|
||||||
|
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
|
||||||
|
$shared = $shared == 'shared' ? true : false;
|
||||||
|
$allCategories = $repository->getCategories();
|
||||||
|
$allEntries = new Collection;
|
||||||
|
$categories = new Collection;
|
||||||
|
|
||||||
|
// filter by checking the entire year first:
|
||||||
|
foreach ($allCategories as $category) {
|
||||||
|
$spent = $repository->spentInPeriodCorrected($category, $start, $end, $shared);
|
||||||
|
if ($spent > 0) {
|
||||||
|
$categories->push($category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while ($start < $end) {
|
||||||
|
$month = clone $start; // month is the current end of the period
|
||||||
|
$month->endOfMonth();
|
||||||
|
$row = [clone $start]; // make a row:
|
||||||
|
|
||||||
|
foreach ($categories as $category) { // each budget, fill the row
|
||||||
|
$spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
|
||||||
|
if ($spent > 0) {
|
||||||
|
$row[] = $spent;
|
||||||
|
} else {
|
||||||
|
$row[] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
$allEntries->push($row);
|
||||||
|
|
||||||
|
$start->addMonth();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$data = $this->generator->earnedInYear($categories, $allEntries);
|
||||||
$cache->store($data);
|
$cache->store($data);
|
||||||
|
|
||||||
return Response::json($data);
|
return Response::json($data);
|
||||||
|
@@ -300,7 +300,8 @@ Route::group(
|
|||||||
|
|
||||||
// categories:
|
// categories:
|
||||||
Route::get('/chart/category/frontpage', ['uses' => 'Chart\CategoryController@frontpage']);
|
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/spent-in-year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@spentInYear'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
|
||||||
|
Route::get('/chart/category/earned-in-year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@earnedInYear'])->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}/month', ['uses' => 'Chart\CategoryController@month']); // should be period.
|
||||||
Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']);
|
Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']);
|
||||||
|
|
||||||
|
@@ -315,7 +315,7 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
|
|||||||
*/
|
*/
|
||||||
public function spentInPeriodCorrected(Budget $budget, Carbon $start, Carbon $end, $shared = true)
|
public function spentInPeriodCorrected(Budget $budget, Carbon $start, Carbon $end, $shared = true)
|
||||||
{
|
{
|
||||||
return $this->spentInPeriod($budget, $start, $end, $shared);
|
return $this->balanceInPeriod($budget, $start, $end, $shared);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -185,7 +185,7 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
|
|||||||
*/
|
*/
|
||||||
public function spentInPeriodCorrected(Category $category, Carbon $start, Carbon $end, $shared = false)
|
public function spentInPeriodCorrected(Category $category, Carbon $start, Carbon $end, $shared = false)
|
||||||
{
|
{
|
||||||
return $this->spentInPeriod($category, $start, $end, $shared);
|
return $this->balanceInPeriod($category, $start, $end, $shared);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -24,7 +24,7 @@ class ComponentRepository
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
protected function spentInPeriod($object, Carbon $start, Carbon $end, $shared = false)
|
protected function balanceInPeriod($object, Carbon $start, Carbon $end, $shared = false)
|
||||||
{
|
{
|
||||||
$cache = new CacheProperties; // we must cache this.
|
$cache = new CacheProperties; // we must cache this.
|
||||||
$cache->addProperty($object->id);
|
$cache->addProperty($object->id);
|
||||||
@@ -45,14 +45,13 @@ class ComponentRepository
|
|||||||
// do something else, SEE budgets.
|
// do something else, SEE budgets.
|
||||||
// get all journals in this month where the asset account is NOT shared.
|
// get all journals in this month where the asset account is NOT shared.
|
||||||
$sum = $object->transactionjournals()->before($end)->after($start)
|
$sum = $object->transactionjournals()->before($end)->after($start)
|
||||||
->transactionTypes(['Withdrawal'])
|
|
||||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||||
->leftJoin(
|
->leftJoin(
|
||||||
'account_meta', function (JoinClause $join) {
|
'account_meta', function (JoinClause $join) {
|
||||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||||
}
|
}
|
||||||
)->where('account_meta.data', '!=', '"sharedAsset"')->get(['transaction_journals.*'])->sum('amount');
|
)->where('account_meta.data', '!=', '"sharedAsset"')->get(['transaction_journals.*'])->sum('correct_amount');
|
||||||
}
|
}
|
||||||
|
|
||||||
$cache->store($sum);
|
$cache->store($sum);
|
||||||
|
@@ -18,7 +18,8 @@ function drawChart() {
|
|||||||
}
|
}
|
||||||
if (typeof stackedColumnChart !== 'undefined' && typeof year !== 'undefined' && typeof month === 'undefined') {
|
if (typeof stackedColumnChart !== 'undefined' && typeof year !== 'undefined' && typeof month === 'undefined') {
|
||||||
stackedColumnChart('chart/budget/year/' + year + shared, 'budgets');
|
stackedColumnChart('chart/budget/year/' + year + shared, 'budgets');
|
||||||
stackedColumnChart('chart/category/year/' + year + shared, 'categories');
|
stackedColumnChart('chart/category/spent-in-year/' + year + shared, 'categories-spent-in-year');
|
||||||
|
stackedColumnChart('chart/category/earned-in-year/' + year + shared, 'categories-earned-in-year');
|
||||||
}
|
}
|
||||||
if (typeof lineChart !== 'undefined' && typeof month !== 'undefined') {
|
if (typeof lineChart !== 'undefined' && typeof month !== 'undefined') {
|
||||||
lineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart');
|
lineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart');
|
||||||
|
@@ -396,6 +396,8 @@ return [
|
|||||||
'hideTheRest' => 'Show only the top :number',
|
'hideTheRest' => 'Show only the top :number',
|
||||||
'sum_of_year' => 'Sum of year',
|
'sum_of_year' => 'Sum of year',
|
||||||
'average_of_year' => 'Average of year',
|
'average_of_year' => 'Average of year',
|
||||||
|
'categories_earned_in_year' => 'Categories (by earnings)',
|
||||||
|
'categories_spent_in_year' => 'Categories (by spendings)',
|
||||||
|
|
||||||
// charts:
|
// charts:
|
||||||
'dayOfMonth' => 'Day of the month',
|
'dayOfMonth' => 'Day of the month',
|
||||||
|
@@ -404,6 +404,8 @@ return [
|
|||||||
'topX' => 'top :number',
|
'topX' => 'top :number',
|
||||||
'showTheRest' => 'Laat alles zien',
|
'showTheRest' => 'Laat alles zien',
|
||||||
'hideTheRest' => 'Laat alleen de top :number zien',
|
'hideTheRest' => 'Laat alleen de top :number zien',
|
||||||
|
'categories_earned_in_year' => 'Categorieën (inkomsten)',
|
||||||
|
'categories_spent_in_year' => 'Categorieën (uitgaven)',
|
||||||
|
|
||||||
// charts:
|
// charts:
|
||||||
'dayOfMonth' => 'Dag vd maand',
|
'dayOfMonth' => 'Dag vd maand',
|
||||||
|
@@ -56,19 +56,38 @@
|
|||||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">{{ 'categories'|_ }}</h3>
|
<h3 class="box-title">{{ 'categories_spent_in_year'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
{% if Config.get('firefly.chart') == 'google' %}
|
{% if Config.get('firefly.chart') == 'google' %}
|
||||||
<div id="categories"></div>
|
<div id="categories-spent-in-year"></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if Config.get('firefly.chart') == 'chartjs' %}
|
{% if Config.get('firefly.chart') == 'chartjs' %}
|
||||||
<canvas id="categories" style="width:100%;height:400px;"></canvas>
|
<canvas id="categories-spent-in-year" style="width:100%;height:400px;"></canvas>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'categories_earned_in_year'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
{% if Config.get('firefly.chart') == 'google' %}
|
||||||
|
<div id="categories-earned-in-year"></div>
|
||||||
|
{% endif %}
|
||||||
|
{% if Config.get('firefly.chart') == 'chartjs' %}
|
||||||
|
<canvas id="categories-earned-in-year" style="width:100%;height:400px;"></canvas>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
|
Reference in New Issue
Block a user