mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-16 01:06:46 +00:00
Initial code base for tag report.
This commit is contained in:
@@ -331,22 +331,4 @@ class CategoryReportController extends Controller
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function groupByOpposingAccount(Collection $set): array
|
||||
{
|
||||
$grouped = [];
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($set as $transaction) {
|
||||
$accountId = $transaction->opposing_account_id;
|
||||
$grouped[$accountId] = $grouped[$accountId] ?? '0';
|
||||
$grouped[$accountId] = bcadd($transaction->transaction_amount, $grouped[$accountId]);
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
}
|
||||
|
216
app/Http/Controllers/Chart/TagReportController.php
Normal file
216
app/Http/Controllers/Chart/TagReportController.php
Normal file
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
/**
|
||||
* TagReportController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||
*
|
||||
* See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
|
||||
use FireflyIII\Generator\Report\Tag\MonthReportGenerator;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Response;
|
||||
|
||||
class TagReportController extends Controller
|
||||
{
|
||||
/** @var GeneratorInterface */
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
// create chart generator:
|
||||
$this->generator = app(GeneratorInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $tags
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function mainChart(Collection $accounts, Collection $tags, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('chart.category.report.main');
|
||||
$cache->addProperty($accounts);
|
||||
$cache->addProperty($tags);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
|
||||
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
|
||||
$function = Navigation::preferredEndOfPeriod($start, $end);
|
||||
$chartData = [];
|
||||
$currentStart = clone $start;
|
||||
|
||||
// prep chart data:
|
||||
foreach ($tags as $tag) {
|
||||
$chartData[$tag->id . '-in'] = [
|
||||
'label' => $tag->tag . ' (' . strtolower(strval(trans('firefly.income'))) . ')',
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 'y-axis-0',
|
||||
'entries' => [],
|
||||
];
|
||||
$chartData[$tag->id . '-out'] = [
|
||||
'label' => $tag->tag . ' (' . strtolower(strval(trans('firefly.expenses'))) . ')',
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 'y-axis-0',
|
||||
'entries' => [],
|
||||
];
|
||||
// total in, total out:
|
||||
$chartData[$tag->id . '-total-in'] = [
|
||||
'label' => $tag->tag . ' (' . strtolower(strval(trans('firefly.sum_of_income'))) . ')',
|
||||
'type' => 'line',
|
||||
'fill' => false,
|
||||
'yAxisID' => 'y-axis-1',
|
||||
'entries' => [],
|
||||
];
|
||||
$chartData[$tag->id . '-total-out'] = [
|
||||
'label' => $tag->tag . ' (' . strtolower(strval(trans('firefly.sum_of_expenses'))) . ')',
|
||||
'type' => 'line',
|
||||
'fill' => false,
|
||||
'yAxisID' => 'y-axis-1',
|
||||
'entries' => [],
|
||||
];
|
||||
}
|
||||
$sumOfIncome = [];
|
||||
$sumOfExpense = [];
|
||||
|
||||
while ($currentStart < $end) {
|
||||
$currentEnd = clone $currentStart;
|
||||
$currentEnd = $currentEnd->$function();
|
||||
$expenses = $this->groupByTag($this->getExpenses($accounts, $tags, $currentStart, $currentEnd));
|
||||
$income = $this->groupByTag($this->getIncome($accounts, $tags, $currentStart, $currentEnd));
|
||||
$label = $currentStart->formatLocalized($format);
|
||||
|
||||
/** @var Tag $tag */
|
||||
foreach ($tags as $tag) {
|
||||
$labelIn = $tag->id . '-in';
|
||||
$labelOut = $tag->id . '-out';
|
||||
$labelSumIn = $tag->id . '-total-in';
|
||||
$labelSumOut = $tag->id . '-total-out';
|
||||
$currentIncome = $income[$tag->id] ?? '0';
|
||||
$currentExpense = $expenses[$tag->id] ?? '0';
|
||||
|
||||
|
||||
// add to sum:
|
||||
$sumOfIncome[$tag->id] = $sumOfIncome[$tag->id] ?? '0';
|
||||
$sumOfExpense[$tag->id] = $sumOfExpense[$tag->id] ?? '0';
|
||||
$sumOfIncome[$tag->id] = bcadd($sumOfIncome[$tag->id], $currentIncome);
|
||||
$sumOfExpense[$tag->id] = bcadd($sumOfExpense[$tag->id], $currentExpense);
|
||||
|
||||
// add to chart:
|
||||
$chartData[$labelIn]['entries'][$label] = $currentIncome;
|
||||
$chartData[$labelOut]['entries'][$label] = $currentExpense;
|
||||
$chartData[$labelSumIn]['entries'][$label] = $sumOfIncome[$tag->id];
|
||||
$chartData[$labelSumOut]['entries'][$label] = $sumOfExpense[$tag->id];
|
||||
}
|
||||
$currentStart = clone $currentEnd;
|
||||
$currentStart->addDay();
|
||||
}
|
||||
// remove all empty entries to prevent cluttering:
|
||||
$newSet = [];
|
||||
foreach ($chartData as $key => $entry) {
|
||||
if (!array_sum($entry['entries']) == 0) {
|
||||
$newSet[$key] = $chartData[$key];
|
||||
}
|
||||
}
|
||||
if (count($newSet) === 0) {
|
||||
$newSet = $chartData;
|
||||
}
|
||||
$data = $this->generator->multiSet($newSet);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $tags
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function getExpenses(Collection $accounts, Collection $tags, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
|
||||
->setTags($tags)->withOpposingAccount()->disableFilter();
|
||||
$accountIds = $accounts->pluck('id')->toArray();
|
||||
$transactions = $collector->getJournals();
|
||||
$set = MonthReportGenerator::filterExpenses($transactions, $accountIds);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $tags
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function getIncome(Collection $accounts, Collection $tags, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
|
||||
->setTags($tags)->withOpposingAccount();
|
||||
$accountIds = $accounts->pluck('id')->toArray();
|
||||
$transactions = $collector->getJournals();
|
||||
$set = MonthReportGenerator::filterIncome($transactions, $accountIds);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function groupByTag(Collection $set): array
|
||||
{
|
||||
// group by category ID:
|
||||
$grouped = [];
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($set as $transaction) {
|
||||
$journal = $transaction->transactionJournal;
|
||||
$journalTags = $journal->tags;
|
||||
/** @var Tag $journalTag */
|
||||
foreach ($journalTags as $journalTag) {
|
||||
$journalTagId = $journalTag->id;
|
||||
$grouped[$journalTagId] = $grouped[$journalTagId] ?? '0';
|
||||
$grouped[$journalTagId] = bcadd($transaction->transaction_amount, $grouped[$journalTagId]);
|
||||
}
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
|
||||
}
|
@@ -556,6 +556,19 @@ Breadcrumbs::register(
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'reports.report.tag', function (BreadCrumbGenerator $breadcrumbs, string $accountIds, string $tagTags, Carbon $start, Carbon $end) {
|
||||
$breadcrumbs->parent('reports.index');
|
||||
|
||||
$monthFormat = (string)trans('config.month_and_day');
|
||||
$startString = $start->formatLocalized($monthFormat);
|
||||
$endString = $end->formatLocalized($monthFormat);
|
||||
$title = (string)trans('firefly.report_tag', ['start' => $startString, 'end' => $endString]);
|
||||
|
||||
$breadcrumbs->push($title, route('reports.report.tag', [$accountIds, $tagTags, $start->format('Ymd'), $end->format('Ymd')]));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'reports.report.category', function (BreadCrumbGenerator $breadcrumbs, string $accountIds, string $categoryIds, Carbon $start, Carbon $end) {
|
||||
$breadcrumbs->parent('reports.index');
|
||||
|
Reference in New Issue
Block a user