From 5d4f1bc76d8e44dd2ab4ca323be433337759a13e Mon Sep 17 00:00:00 2001 From: James Cole Date: Thu, 10 Nov 2016 06:23:21 +0100 Subject: [PATCH] First working example of category report. No content, just place holders. #396 --- .../Report/Audit/MonthReportGenerator.php | 9 ++ .../Report/Category/MonthReportGenerator.php | 99 ++++++++++++++++ .../Category/MultiYearReportGenerator.php | 27 +++++ .../Report/Category/YearReportGenerator.php | 28 +++++ .../Report/ReportGeneratorFactory.php | 2 +- .../Report/ReportGeneratorInterface.php | 7 ++ .../Report/Standard/MonthReportGenerator.php | 9 ++ .../Standard/MultiYearReportGenerator.php | 10 +- .../Report/Standard/YearReportGenerator.php | 10 +- app/Helpers/Report/ReportHelper.php | 84 +------------- app/Helpers/Report/ReportHelperInterface.php | 11 -- app/Http/Controllers/ReportController.php | 72 +++++++----- resources/lang/en_US/firefly.php | 2 + resources/views/reports/category/month.twig | 65 +++++++++++ resources/views/reports/index.twig | 106 ++++++------------ 15 files changed, 345 insertions(+), 196 deletions(-) create mode 100644 app/Generator/Report/Category/MonthReportGenerator.php create mode 100644 app/Generator/Report/Category/MultiYearReportGenerator.php create mode 100644 app/Generator/Report/Category/YearReportGenerator.php create mode 100644 resources/views/reports/category/month.twig diff --git a/app/Generator/Report/Audit/MonthReportGenerator.php b/app/Generator/Report/Audit/MonthReportGenerator.php index 27398a2fab..3ad211f952 100644 --- a/app/Generator/Report/Audit/MonthReportGenerator.php +++ b/app/Generator/Report/Audit/MonthReportGenerator.php @@ -111,6 +111,15 @@ class MonthReportGenerator implements ReportGeneratorInterface return $this; } + /** + * @param Collection $categories + * + * @return ReportGeneratorInterface + */ + public function setCategories(Collection $categories): ReportGeneratorInterface + { + } + /** * @param Carbon $date * diff --git a/app/Generator/Report/Category/MonthReportGenerator.php b/app/Generator/Report/Category/MonthReportGenerator.php new file mode 100644 index 0000000000..d2bd5ec3c2 --- /dev/null +++ b/app/Generator/Report/Category/MonthReportGenerator.php @@ -0,0 +1,99 @@ +accounts->pluck('id')->toArray()); + $reportType = 'category'; + + // render! + return view('reports.category.month', compact('accountIds', 'reportType')) + ->with('start', $this->start)->with('end', $this->end) + ->with('categories', $this->categories) + ->render(); + } + + /** + * @param Collection $accounts + * + * @return ReportGeneratorInterface + */ + public function setAccounts(Collection $accounts): ReportGeneratorInterface + { + $this->accounts = $accounts; + + return $this; + } + + /** + * @param Collection $categories + * + * @return ReportGeneratorInterface + */ + public function setCategories(Collection $categories): ReportGeneratorInterface + { + $this->categories = $categories; + + return $this; + } + + /** + * @param Carbon $date + * + * @return ReportGeneratorInterface + */ + public function setEndDate(Carbon $date): ReportGeneratorInterface + { + $this->end = $date; + + return $this; + } + + /** + * @param Carbon $date + * + * @return ReportGeneratorInterface + */ + public function setStartDate(Carbon $date): ReportGeneratorInterface + { + $this->start = $date; + + return $this; + } +} \ No newline at end of file diff --git a/app/Generator/Report/Category/MultiYearReportGenerator.php b/app/Generator/Report/Category/MultiYearReportGenerator.php new file mode 100644 index 0000000000..2f663c3925 --- /dev/null +++ b/app/Generator/Report/Category/MultiYearReportGenerator.php @@ -0,0 +1,27 @@ +budgetRepository = $budgetRepository; - $this->tagRepository = $tagRepository; } /** @@ -234,78 +226,4 @@ class ReportHelper implements ReportHelperInterface return $months; } - /** - * Returns an array of tags and their comparitive size with amounts bla bla. - * - * @param Carbon $start - * @param Carbon $end - * @param Collection $accounts - * - * @return array - */ - public function tagReport(Carbon $start, Carbon $end, Collection $accounts): array - { - $ids = $accounts->pluck('id')->toArray(); - $set = Tag:: - leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id') - ->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') - ->leftJoin( - 'transactions AS source', function (JoinClause $join) { - $join->on('source.transaction_journal_id', '=', 'transaction_journals.id')->where('source.amount', '<', '0'); - } - ) - ->leftJoin( - 'transactions AS destination', function (JoinClause $join) { - $join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')->where('destination.amount', '>', '0'); - } - ) - ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) - ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) - ->where( - // source.account_id in accountIds XOR destination.account_id in accountIds - function (Builder $query) use ($ids) { - $query->where( - function (Builder $q1) use ($ids) { - $q1->whereIn('source.account_id', $ids) - ->whereNotIn('destination.account_id', $ids); - } - )->orWhere( - function (Builder $q2) use ($ids) { - $q2->whereIn('destination.account_id', $ids) - ->whereNotIn('source.account_id', $ids); - } - ); - } - ) - ->get(['tags.id', 'tags.tag', 'transaction_journals.id as journal_id', 'destination.amount']); - $collection = []; - if ($set->count() === 0) { - return $collection; - } - /** @var Tag $entry */ - foreach ($set as $entry) { - // less than zero? multiply to be above zero. - $amount = $entry->amount; - $id = intval($entry->id); - $previousAmount = $collection[$id]['amount'] ?? '0'; - $collection[$id] = [ - 'id' => $id, - 'tag' => $entry->tag, - 'amount' => bcadd($previousAmount, $amount), - ]; - } - - // cleanup collection (match "fonts") - $max = strval(max(array_column($collection, 'amount'))); - foreach ($collection as $id => $entry) { - $size = bcdiv($entry['amount'], $max, 4); - if (bccomp($size, '0.25') === -1) { - $size = '0.5'; - } - $collection[$id]['fontsize'] = $size; - } - - return $collection; - } - } diff --git a/app/Helpers/Report/ReportHelperInterface.php b/app/Helpers/Report/ReportHelperInterface.php index 34ffcc9e7b..47af08976b 100644 --- a/app/Helpers/Report/ReportHelperInterface.php +++ b/app/Helpers/Report/ReportHelperInterface.php @@ -80,15 +80,4 @@ interface ReportHelperInterface */ public function listOfMonths(Carbon $date): array; - /** - * Returns an array of tags and their comparitive size with amounts bla bla. - * - * @param Carbon $start - * @param Carbon $end - * @param Collection $accounts - * - * @return array - */ - public function tagReport(Carbon $start, Carbon $end, Collection $accounts): array; - } diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index 2a24548513..8d29ba1edf 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -16,22 +16,15 @@ namespace FireflyIII\Http\Controllers; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Generator\Report\ReportGeneratorFactory; -use FireflyIII\Generator\Report\Standard\MonthReportGenerator; -use FireflyIII\Generator\Report\StandardReportGenerator; -use FireflyIII\Helpers\Collector\JournalCollector; use FireflyIII\Helpers\Report\ReportHelperInterface; use FireflyIII\Http\Requests\ReportFormRequest; -use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; -use FireflyIII\Models\Transaction; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use Illuminate\Http\RedirectResponse; use Illuminate\Support\Collection; use Preferences; use Response; -use Session; -use Steam; use View; /** @@ -56,6 +49,7 @@ class ReportController extends Controller function ($request, $next) { View::share('title', trans('firefly.reports')); View::share('mainTitleIcon', 'fa-line-chart'); + View::share('subTitleIcon', 'fa-calendar'); $this->helper = app(ReportHelperInterface::class); @@ -75,12 +69,9 @@ class ReportController extends Controller */ public function auditReport(Carbon $start, Carbon $end, Collection $accounts) { - // throw an error if necessary. if ($end < $start) { - throw new FireflyException('End date cannot be before start date, silly!'); + return view('error')->with('message', trans('firefly.end_after_start_date')); } - - // lower threshold if ($start < session('first')) { $start = session('first'); } @@ -94,7 +85,7 @@ class ReportController extends Controller ] ) ); - View::share('subTitleIcon', 'fa-calendar'); + $generator = ReportGeneratorFactory::reportGenerator('Audit', $start, $end); $generator->setAccounts($accounts); @@ -112,14 +103,47 @@ class ReportController extends Controller * @return string * @throws FireflyException */ - public function defaultReport(Carbon $start, Carbon $end, Collection $accounts) + public function categoryReport(Carbon $start, Carbon $end, Collection $accounts, Collection $categories) { - // throw an error if necessary. if ($end < $start) { - throw new FireflyException('End date cannot be before start date, silly!'); + return view('error')->with('message', trans('firefly.end_after_start_date')); + } + if ($start < session('first')) { + $start = session('first'); } - // lower threshold + View::share( + 'subTitle', trans( + 'firefly.report_category', + [ + 'start' => $start->formatLocalized($this->monthFormat), + 'end' => $end->formatLocalized($this->monthFormat), + ] + ) + ); + + $generator = ReportGeneratorFactory::reportGenerator('Category', $start, $end); + $generator->setAccounts($accounts); + $generator->setCategories($categories); + $result = $generator->generate(); + + return $result; + + } + + /** + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts + * + * @return string + * @throws FireflyException + */ + public function defaultReport(Carbon $start, Carbon $end, Collection $accounts) + { + if ($end < $start) { + return view('error')->with('message', trans('firefly.end_after_start_date')); + } if ($start < session('first')) { $start = session('first'); } @@ -133,7 +157,6 @@ class ReportController extends Controller ] ) ); - View::share('subTitleIcon', 'fa-calendar'); $generator = ReportGeneratorFactory::reportGenerator('Standard', $start, $end); $generator->setAccounts($accounts); @@ -155,16 +178,8 @@ class ReportController extends Controller $start = clone session('first'); $months = $this->helper->listOfMonths($start); $customFiscalYear = Preferences::get('customFiscalYear', 0)->data; - - // does the user have shared accounts? - $accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); - // get id's for quick links: - $accountIds = []; - /** @var Account $account */ - foreach ($accounts as $account) { - $accountIds [] = $account->id; - } - $accountList = join(',', $accountIds); + $accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); + $accountList = join(',', $accounts->pluck('id')->toArray()); return view('reports.index', compact('months', 'accounts', 'start', 'accountList', 'customFiscalYear')); @@ -177,7 +192,6 @@ class ReportController extends Controller */ public function options(string $reportType) { - $result = ''; switch ($reportType) { default: $result = $this->noReportOptions(); @@ -206,7 +220,7 @@ class ReportController extends Controller $categories = join(',', $request->getCategoryList()->pluck('id')->toArray()); if ($end < $start) { - throw new FireflyException('End date cannot be before start date, silly!'); + return view('error')->with('message', trans('firefly.end_after_start_date')); } // lower threshold diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 57e2e48caf..0700a0f643 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -686,6 +686,8 @@ return [ 'reports_extra_options' => 'Extra options', 'report_has_no_extra_options' => 'This report has no extra options', 'reports_submit' => 'View report', + 'end_after_start_date' => 'End date of report must be after start date.', + 'select_category' => 'Select one or more categories.', // charts: 'chart' => 'Chart', diff --git a/resources/views/reports/category/month.twig b/resources/views/reports/category/month.twig new file mode 100644 index 0000000000..4864dc3ca6 --- /dev/null +++ b/resources/views/reports/category/month.twig @@ -0,0 +1,65 @@ +{% extends "./layout/default" %} + +{% block breadcrumbs %} + {{ Breadcrumbs.renderIfExists(Route.getCurrentRoute.getName) }} +{% endblock %} + +{% block content %} + +
+
+ Summary here. Accounts and categories involved. Summary of in/out +
+
+ Pie chart with spending (aka all withdrawals in category). Optional checkbox to include all other transactions. +
+
+ Pie chart with income (aka all deposits in category). Optional checkbox to include all other transactions (for comparison). +
+
+ +
+
+ big chart here + + Show income / expenses per period. Differs per report: month = per day, year = per month, multi-year = per year. + In a bar chart, possibly grouped by expense/revenue account. + +
+
+ +
+
+ List of spending (withdrawals) by account, if relevant. Grouped:
+ + BC: 456 + AH: 123 + + order by size + + linked to chart + + use reset button to reset after chart was clicked. +
+
+ List of spending (withdrawals) by transaction, if relevant. Not grouped
+ + more groceries: 456 + groceries: 123 + + ordered by size. top x list? +
+ +
+ Same but for income +
+ +
+ +{% endblock %} + +{% block scripts %} +{% endblock %} + +{% block styles %} +{% endblock %} \ No newline at end of file diff --git a/resources/views/reports/index.twig b/resources/views/reports/index.twig index 886deb0477..eec3c8c134 100644 --- a/resources/views/reports/index.twig +++ b/resources/views/reports/index.twig @@ -113,81 +113,47 @@

{{ 'quick_link_reports'|_ }}

-

{{ 'quick_link_default_report'|_ }}

- -

{{ 'quick_link_audit_report'|_ }}

- + {% endfor %}

{{ 'reports_can_bookmark'|_ }}