mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-19 02:45: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
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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:
|
||||
|
@@ -86,7 +86,31 @@ class GoogleCategoryChartGenerator implements CategoryChartGenerator
|
||||
*
|
||||
* @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;
|
||||
|
||||
|
@@ -46,11 +46,10 @@ class CategoryController extends Controller
|
||||
public function all(CategoryRepositoryInterface $repository, Category $category)
|
||||
{
|
||||
// oldest transaction in category:
|
||||
$start = $repository->getFirstActivityDate($category);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = new Carbon;
|
||||
|
||||
$start = $repository->getFirstActivityDate($category);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = new Carbon;
|
||||
$entries = new Collection;
|
||||
|
||||
|
||||
@@ -170,7 +169,7 @@ class CategoryController extends Controller
|
||||
*
|
||||
* @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');
|
||||
$end = new Carbon($year . '-12-31');
|
||||
@@ -179,14 +178,23 @@ class CategoryController extends Controller
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('category');
|
||||
$cache->addProperty('year');
|
||||
$cache->addProperty('spent-in-year');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$shared = $shared == 'shared' ? true : false;
|
||||
$categories = $repository->getCategories();
|
||||
$entries = new Collection;
|
||||
$shared = $shared == 'shared' ? true : false;
|
||||
$allCategories = $repository->getCategories();
|
||||
$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) {
|
||||
$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
|
||||
$spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
|
||||
$row[] = $spent;
|
||||
if ($spent < 0) {
|
||||
$spent = $spent * -1;
|
||||
$row[] = $spent;
|
||||
} else {
|
||||
$row[] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
$entries->push($row);
|
||||
|
||||
$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);
|
||||
|
||||
return Response::json($data);
|
||||
|
@@ -300,7 +300,8 @@ Route::group(
|
||||
|
||||
// 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/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}/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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return $this->spentInPeriod($category, $start, $end, $shared);
|
||||
return $this->balanceInPeriod($category, $start, $end, $shared);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -24,7 +24,7 @@ class ComponentRepository
|
||||
*
|
||||
* @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->addProperty($object->id);
|
||||
@@ -45,14 +45,13 @@ class ComponentRepository
|
||||
// do something else, SEE budgets.
|
||||
// get all journals in this month where the asset account is NOT shared.
|
||||
$sum = $object->transactionjournals()->before($end)->after($start)
|
||||
->transactionTypes(['Withdrawal'])
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->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');
|
||||
)->where('account_meta.data', '!=', '"sharedAsset"')->get(['transaction_journals.*'])->sum('correct_amount');
|
||||
}
|
||||
|
||||
$cache->store($sum);
|
||||
|
@@ -18,7 +18,8 @@ function drawChart() {
|
||||
}
|
||||
if (typeof stackedColumnChart !== 'undefined' && typeof year !== 'undefined' && typeof month === 'undefined') {
|
||||
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') {
|
||||
lineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart');
|
||||
|
@@ -396,6 +396,8 @@ return [
|
||||
'hideTheRest' => 'Show only the top :number',
|
||||
'sum_of_year' => 'Sum of year',
|
||||
'average_of_year' => 'Average of year',
|
||||
'categories_earned_in_year' => 'Categories (by earnings)',
|
||||
'categories_spent_in_year' => 'Categories (by spendings)',
|
||||
|
||||
// charts:
|
||||
'dayOfMonth' => 'Day of the month',
|
||||
|
@@ -404,6 +404,8 @@ return [
|
||||
'topX' => 'top :number',
|
||||
'showTheRest' => 'Laat alles zien',
|
||||
'hideTheRest' => 'Laat alleen de top :number zien',
|
||||
'categories_earned_in_year' => 'Categorieën (inkomsten)',
|
||||
'categories_spent_in_year' => 'Categorieën (uitgaven)',
|
||||
|
||||
// charts:
|
||||
'dayOfMonth' => 'Dag vd maand',
|
||||
|
@@ -56,19 +56,38 @@
|
||||
<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'|_ }}</h3>
|
||||
<h3 class="box-title">{{ 'categories_spent_in_year'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
{% if Config.get('firefly.chart') == 'google' %}
|
||||
<div id="categories"></div>
|
||||
<div id="categories-spent-in-year"></div>
|
||||
{% endif %}
|
||||
{% 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 %}
|
||||
</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="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="box">
|
||||
|
Reference in New Issue
Block a user