From cdeac2c6db20bf4a8ea771d044f3b43f0e5fe42b Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 16 May 2015 14:51:23 +0200 Subject: [PATCH] Should simplify reports. --- app/Helpers/Collection/Balance.php | 53 +++++++ app/Helpers/Collection/BalanceEntry.php | 56 ++++++++ app/Helpers/Collection/BalanceHeader.php | 45 ++++++ app/Helpers/Collection/BalanceLine.php | 67 +++++++++ app/Helpers/Collection/Category.php | 66 ++++++++- app/Helpers/Report/ReportHelper.php | 78 ++++++++++- app/Helpers/Report/ReportHelperInterface.php | 14 +- app/Helpers/Report/ReportQuery.php | 127 ++++++++--------- app/Helpers/Report/ReportQueryInterface.php | 1 + app/Http/Controllers/ReportController.php | 3 +- resources/lang/en/firefly.php | 1 + resources/lang/nl/firefly.php | 1 + .../partials/reports/budgets-vs-accounts.twig | 122 ++++++++++++++++ .../twig/partials/reports/categories.twig | 24 ++++ resources/twig/reports/month.twig | 132 +----------------- 15 files changed, 593 insertions(+), 197 deletions(-) create mode 100644 app/Helpers/Collection/Balance.php create mode 100644 app/Helpers/Collection/BalanceEntry.php create mode 100644 app/Helpers/Collection/BalanceHeader.php create mode 100644 app/Helpers/Collection/BalanceLine.php create mode 100644 resources/twig/partials/reports/budgets-vs-accounts.twig create mode 100644 resources/twig/partials/reports/categories.twig diff --git a/app/Helpers/Collection/Balance.php b/app/Helpers/Collection/Balance.php new file mode 100644 index 0000000000..d6eabf1192 --- /dev/null +++ b/app/Helpers/Collection/Balance.php @@ -0,0 +1,53 @@ +balanceLines = new Collection; + } + + /** + * @param BalanceLine $line + */ + public function addBalanceLine(BalanceLine $line) + { + $this->balanceLines->push($line); + } + + /** + * @return BalanceHeader + */ + public function getBalanceHeader() + { + return $this->balanceHeader; + } + + /** + * @param BalanceHeader $balanceHeader + */ + public function setBalanceHeader($balanceHeader) + { + $this->balanceHeader = $balanceHeader; + } + + +} \ No newline at end of file diff --git a/app/Helpers/Collection/BalanceEntry.php b/app/Helpers/Collection/BalanceEntry.php new file mode 100644 index 0000000000..f1362ca35d --- /dev/null +++ b/app/Helpers/Collection/BalanceEntry.php @@ -0,0 +1,56 @@ +account; + } + + /** + * @param AccountModel $account + */ + public function setAccount($account) + { + $this->account = $account; + } + + /** + * @return float + */ + public function getSpent() + { + return $this->spent; + } + + /** + * @param float $spent + */ + public function setSpent($spent) + { + $this->spent = $spent; + } + + +} \ No newline at end of file diff --git a/app/Helpers/Collection/BalanceHeader.php b/app/Helpers/Collection/BalanceHeader.php new file mode 100644 index 0000000000..252adf43ec --- /dev/null +++ b/app/Helpers/Collection/BalanceHeader.php @@ -0,0 +1,45 @@ +accounts = new Collection; + } + + /** + * @param AccountModel $account + */ + public function addAccount(AccountModel $account) + { + $this->accounts->push($account); + } + + /** + * @return Collection + */ + public function getAccounts() + { + return $this->accounts; + } + + + +} \ No newline at end of file diff --git a/app/Helpers/Collection/BalanceLine.php b/app/Helpers/Collection/BalanceLine.php new file mode 100644 index 0000000000..f4473513e2 --- /dev/null +++ b/app/Helpers/Collection/BalanceLine.php @@ -0,0 +1,67 @@ +balanceEntries = new Collection; + } + + public function addBalanceEntry(BalanceEntry $balanceEntry) + { + $this->balanceEntries->push($balanceEntry); + } + + /** + * @return Collection + */ + public function getBalanceEntries() + { + return $this->balanceEntries; + } + + /** + * @param Collection $balanceEntries + */ + public function setBalanceEntries($balanceEntries) + { + $this->balanceEntries = $balanceEntries; + } + + /** + * @return BudgetModel + */ + public function getBudget() + { + return $this->budget; + } + + /** + * @param BudgetModel $budget + */ + public function setBudget($budget) + { + $this->budget = $budget; + } + + +} \ No newline at end of file diff --git a/app/Helpers/Collection/Category.php b/app/Helpers/Collection/Category.php index bbce06ace3..5865f12676 100644 --- a/app/Helpers/Collection/Category.php +++ b/app/Helpers/Collection/Category.php @@ -8,7 +8,71 @@ namespace FireflyIII\Helpers\Collection; +use FireflyIII\Models\Category as CategoryModel; +use Illuminate\Support\Collection; + + +/** + * Class Category + * + * @package FireflyIII\Helpers\Collection + */ +class Category +{ + + /** @var Collection */ + protected $categories; + /** @var float */ + protected $total = 0; + + /** + * + */ + public function __construct() + { + $this->categories = new Collection; + } + + /** + * @param CategoryModel $category + */ + public function addCategory(CategoryModel $category) + { + if ($category->spent > 0) { + $this->categories->push($category); + } + } + + /** + * @param float $add + */ + public function addTotal($add) + { + $this->total += floatval($add); + } + + /** + * @return Collection + */ + public function getCategories() + { + $this->categories->sortByDesc( + function (CategoryModel $category) { + return $category->spent; + } + ); + + + return $this->categories; + } + + /** + * @return float + */ + public function getTotal() + { + return $this->total; + } -class Category { } \ No newline at end of file diff --git a/app/Helpers/Report/ReportHelper.php b/app/Helpers/Report/ReportHelper.php index 347380408c..fbc2464e11 100644 --- a/app/Helpers/Report/ReportHelper.php +++ b/app/Helpers/Report/ReportHelper.php @@ -5,12 +5,17 @@ namespace FireflyIII\Helpers\Report; use App; use Carbon\Carbon; use FireflyIII\Helpers\Collection\Account as AccountCollection; +use FireflyIII\Helpers\Collection\Balance; +use FireflyIII\Helpers\Collection\BalanceEntry; +use FireflyIII\Helpers\Collection\BalanceHeader; +use FireflyIII\Helpers\Collection\BalanceLine; use FireflyIII\Helpers\Collection\Budget as BudgetCollection; use FireflyIII\Helpers\Collection\BudgetLine; use FireflyIII\Helpers\Collection\Category as CategoryCollection; use FireflyIII\Helpers\Collection\Expense; use FireflyIII\Helpers\Collection\Income; use FireflyIII\Models\Account; +use FireflyIII\Models\Budget as BudgetModel; use FireflyIII\Models\LimitRepetition; /** @@ -69,6 +74,61 @@ class ReportHelper implements ReportHelperInterface return $object; } + /** + * + * The balance report contains a Balance object which in turn contains: + * + * A BalanceHeader object which contains all relevant user asset accounts for the report. + * + * A number of BalanceLine objects, which hold: + * - A budget + * - A number of BalanceEntry objects. + * + * The BalanceEntry object holds: + * - The same budget (again) + * - A user asset account as mentioned in the BalanceHeader + * - The amount of money spent on the budget by the user asset account + * + * @param Carbon $start + * @param Carbon $end + * @param boolean $shared + * + * @return Balance + */ + public function getBalanceReport(Carbon $start, Carbon $end, $shared) + { + $repository = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $balance = new Balance; + + // build a balance header: + $header = new BalanceHeader; + + $accounts = $this->query->getAllAccounts($start, $end, $shared); + $budgets = $repository->getBudgets(); + foreach ($accounts as $account) { + $header->addAccount($account); + } + + foreach ($budgets as $budget) { + $line = new BalanceLine; + $line->setBudget($budget); + + // loop accounts: + foreach ($accounts as $account) { + $balanceEntry = new BalanceEntry; + $balanceEntry->setAccount($account); + $balanceEntry->setSpent(rand(1, 100)); + $line->addBalanceEntry($balanceEntry); + } + // add line to balance: + $balance->addBalanceLine($line); + } + + $balance->setBalanceHeader($header); + + return $balance; + } + /** * @param Carbon $start * @param Carbon $end @@ -143,7 +203,23 @@ class ReportHelper implements ReportHelperInterface */ public function getCategoryReport(Carbon $start, Carbon $end, $shared) { - return null; + $object = new CategoryCollection; + + + /** + * GET CATEGORIES: + */ + /** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */ + $repository = App::make('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $set = $repository->getCategories(); + foreach ($set as $category) { + $spent = $repository->spentInPeriod($category, $start, $end, $shared); + $category->spent = $spent; + $object->addCategory($category); + $object->addTotal($spent); + } + + return $object; } /** diff --git a/app/Helpers/Report/ReportHelperInterface.php b/app/Helpers/Report/ReportHelperInterface.php index 66af64da7e..863a386d6a 100644 --- a/app/Helpers/Report/ReportHelperInterface.php +++ b/app/Helpers/Report/ReportHelperInterface.php @@ -4,10 +4,11 @@ namespace FireflyIII\Helpers\Report; use Carbon\Carbon; use FireflyIII\Helpers\Collection\Account; -use FireflyIII\Helpers\Collection\Expense; -use FireflyIII\Helpers\Collection\Income; +use FireflyIII\Helpers\Collection\Balance; use FireflyIII\Helpers\Collection\Budget as BudgetCollection; use FireflyIII\Helpers\Collection\Category as CategoryCollection; +use FireflyIII\Helpers\Collection\Expense; +use FireflyIII\Helpers\Collection\Income; /** * Interface ReportHelperInterface @@ -29,6 +30,15 @@ interface ReportHelperInterface */ public function getAccountReport(Carbon $date, Carbon $end, $shared); + /** + * @param Carbon $start + * @param Carbon $end + * @param boolean $shared + * + * @return Balance + */ + public function getBalanceReport(Carbon $start, Carbon $end, $shared); + /** * @param Carbon $start * @param Carbon $end diff --git a/app/Helpers/Report/ReportQuery.php b/app/Helpers/Report/ReportQuery.php index 68f5fc8e80..a4b673f410 100644 --- a/app/Helpers/Report/ReportQuery.php +++ b/app/Helpers/Report/ReportQuery.php @@ -86,6 +86,70 @@ class ReportQuery implements ReportQueryInterface return floatval($this->balancedTransactionsList($account, $start, $end)->sum('queryAmount')); } + /** + * This method returns all "expense" journals in a certain period, which are both transfers to a shared account + * and "ordinary" withdrawals. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does + * not group and returns different fields. + * + * @param Carbon $start + * @param Carbon $end + * @param bool $includeShared + * + * @return Collection + * + */ + public function expenseInPeriod(Carbon $start, Carbon $end, $includeShared = false) + { + $query = $this->queryJournalsWithTransactions($start, $end); + if ($includeShared === false) { + // only get withdrawals not from a shared account + // and transfers from a shared account. + $query->where( + function (Builder $query) { + $query->where( + function (Builder $q) { + $q->where('transaction_types.type', 'Withdrawal'); + $q->where('acm_from.data', '!=', '"sharedAsset"'); + } + ); + $query->orWhere( + function (Builder $q) { + $q->where('transaction_types.type', 'Transfer'); + $q->where('acm_to.data', '=', '"sharedAsset"'); + } + ); + } + ); + } else { + // any withdrawal is fine. + $query->where('transaction_types.type', 'Withdrawal'); + } + $query->groupBy('transaction_journals.id')->orderBy('transaction_journals.date'); + + // get everything, decrypt and return + $data = $query->get( + ['transaction_journals.id', + 'transaction_journals.description', + 'transaction_journals.encrypted', + 'transaction_types.type', + DB::Raw('SUM(`t_from`.`amount`) as `queryAmount`'), + 'transaction_journals.date', + 't_to.account_id as account_id', + 'ac_to.name as name', + 'ac_to.encrypted as account_encrypted' + ] + ); + + $data->each( + function (Model $object) { + $object->name = intval($object->account_encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name; + } + ); + $data->sortByDesc('queryAmount'); + + return $data; + } + /** * Get a users accounts combined with various meta-data related to the start and end date. * @@ -232,69 +296,6 @@ class ReportQuery implements ReportQueryInterface return $data; } - /** - * This method returns all "expense" journals in a certain period, which are both transfers to a shared account - * and "ordinary" withdrawals. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does - * not group and returns different fields. - * - * @param Carbon $start - * @param Carbon $end - * @param bool $includeShared - * - * @return Collection - * - */ - public function expenseInPeriod(Carbon $start, Carbon $end, $includeShared = false) { - $query = $this->queryJournalsWithTransactions($start, $end); - if ($includeShared === false) { - // only get withdrawals not from a shared account - // and transfers from a shared account. - $query->where( - function (Builder $query) { - $query->where( - function (Builder $q) { - $q->where('transaction_types.type', 'Withdrawal'); - $q->where('acm_from.data', '!=', '"sharedAsset"'); - } - ); - $query->orWhere( - function (Builder $q) { - $q->where('transaction_types.type', 'Transfer'); - $q->where('acm_to.data', '=', '"sharedAsset"'); - } - ); - } - ); - } else { - // any withdrawal is fine. - $query->where('transaction_types.type', 'Withdrawal'); - } - $query->groupBy('transaction_journals.id')->orderBy('transaction_journals.date'); - - // get everything, decrypt and return - $data = $query->get( - ['transaction_journals.id', - 'transaction_journals.description', - 'transaction_journals.encrypted', - 'transaction_types.type', - DB::Raw('SUM(`t_from`.`amount`) as `queryAmount`'), - 'transaction_journals.date', - 't_to.account_id as account_id', - 'ac_to.name as name', - 'ac_to.encrypted as account_encrypted' - ] - ); - - $data->each( - function (Model $object) { - $object->name = intval($object->account_encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name; - } - ); - $data->sortByDesc('queryAmount'); - - return $data; - } - /** * Gets a list of expenses grouped by the budget they were filed under. * diff --git a/app/Helpers/Report/ReportQueryInterface.php b/app/Helpers/Report/ReportQueryInterface.php index 7b700d8d9a..7ffcb0b6ad 100644 --- a/app/Helpers/Report/ReportQueryInterface.php +++ b/app/Helpers/Report/ReportQueryInterface.php @@ -123,6 +123,7 @@ interface ReportQueryInterface */ public function journalsByCategory(Carbon $start, Carbon $end, $includeShared = false); + /** * Gets a list of expense accounts and the expenses therein, grouped by that expense account. * This result excludes transfers to shared accounts which are expenses, technically. diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index 3b69b1280c..42a8033f69 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -160,6 +160,7 @@ class ReportController extends Controller $expenses = $this->helper->getExpenseReport($start, $end, $shared); $budgets = $this->helper->getBudgetReport($start, $end, $shared); $categories = $this->helper->getCategoryReport($start, $end, $shared); + $balance = $this->helper->getBalanceReport($start, $end, $shared); // /** // * DO BUDGETS. @@ -234,7 +235,7 @@ class ReportController extends Controller 'accounts', 'incomes', 'incomeTopLength', 'expenses', 'expenseTopLength', - 'budgets', + 'budgets','balance', 'categories' ) ); diff --git a/resources/lang/en/firefly.php b/resources/lang/en/firefly.php index fd1845cfa2..2b61e405a5 100644 --- a/resources/lang/en/firefly.php +++ b/resources/lang/en/firefly.php @@ -103,6 +103,7 @@ return [ 'leftUnbalanced' => 'Left unbalanced', 'expectedBalance' => 'Expected balance', 'outsideOfBudgets' => 'Outside of budgets', + 'leftInBudget' => 'Left in budget', 'difference' => 'Difference', 'in' => 'In', diff --git a/resources/lang/nl/firefly.php b/resources/lang/nl/firefly.php index 12217c916b..0bf6d0ba85 100644 --- a/resources/lang/nl/firefly.php +++ b/resources/lang/nl/firefly.php @@ -103,6 +103,7 @@ return [ 'leftUnbalanced' => 'Ongecorrigeerd', 'expectedBalance' => 'Verwacht saldo', 'outsideOfBudgets' => 'Buiten budgetten', + 'leftInBudget' => 'Over van budget', 'difference' => 'Verschil', 'in' => 'In', diff --git a/resources/twig/partials/reports/budgets-vs-accounts.twig b/resources/twig/partials/reports/budgets-vs-accounts.twig new file mode 100644 index 0000000000..471c8b001d --- /dev/null +++ b/resources/twig/partials/reports/budgets-vs-accounts.twig @@ -0,0 +1,122 @@ +
+
+ + {{ 'budgets'|_ }} ({{ 'splitByAccount'|_|lower }}) +
+ + + + + {% for account in balance.getBalanceHeader.getAccounts %} + + {% endfor %} + + + +
{{ 'budgets'|_ }}{{ account.name }} + {{ 'leftInBudget'|_ }} +
+ + +
\ No newline at end of file diff --git a/resources/twig/partials/reports/categories.twig b/resources/twig/partials/reports/categories.twig new file mode 100644 index 0000000000..c55a176209 --- /dev/null +++ b/resources/twig/partials/reports/categories.twig @@ -0,0 +1,24 @@ +
+
+ + {{ 'categories'|_ }} +
+ + + + + + {% for cat in categories.getCategories %} + + + + + {% endfor %} + + + + +
{{ 'categories'|_ }}{{ 'spent'|_ }}
+ {{ cat.name }} + {{ (cat.spent)|formatAmountPlain }}
{{ 'sum'|_ }}{{ categories.getTotal|formatAmountPlain }}
+
\ No newline at end of file diff --git a/resources/twig/reports/month.twig b/resources/twig/reports/month.twig index f2f9e79d4b..249cbc4bf4 100644 --- a/resources/twig/reports/month.twig +++ b/resources/twig/reports/month.twig @@ -36,29 +36,8 @@ {% include 'partials/reports/budgets.twig' %}
-
-
- - {{ 'categories'|_ }} -
- - - - - - {% set sum = 0 %} - {% for data in categories %} - {% if data[1] > 0 %} - - - - - {% endif %} - {% endfor %} -
{{ 'categories'|_ }}{{ 'spent'|_ }}
- {{ data[0].name }} - {{ (data[1])|formatAmountPlain }}
-
+ + {% include 'partials/reports/categories.twig' %}
@@ -68,112 +47,7 @@
-
-
- - {{ 'budgets'|_ }} ({{ 'splitByAccount'|_|lower }}) -
- - - - {% for account in accounts %} - - {% endfor %} - - - {% for data in budgets %} - {% if data[0] %} - - - - {% set spent = 0 %} - {% for account in accounts %} - {% if account.budgetInformation[id] %} - - {% set spent = spent + account.budgetInformation[id].queryAmount %} - {% else %} - - {% endif %} - {% endfor %} - - - - {% endif %} - {% endfor %} - - - {% for account in accounts %} - {% if not account.hide %} - - {% endif %} - {% endfor %} - - - - - {% for account in accounts %} - - {% if not account.hide %} - {% if account.budgetInformation[0] %} - - {% else %} - - {% endif %} - {% endif %} - {% endfor %} - - - - - {% for account in accounts %} - {% if not account.hide %} - - {% endif %} - {% endfor %} - - - - - {% for account in accounts %} - {% if not account.hide %} - - {% endif %} - {% endfor %} - - - -
{{ 'budgets'|_ }}{{ account.name }} - {{ 'leftInBudget'|_ }} -
{{ data[0].name }} - {% if data[1] %} - {{ data[1].amount|formatAmount }} - {% else %} - {{ 0|formatAmount }} - {% endif %} - - {% if id == 0 %} - - {{ account.budgetInformation[id].queryAmount|formatAmount }} - - {% else %} - {{ account.budgetInformation[id].queryAmount|formatAmount }} - {% endif %} - {{ 0|formatAmount }} - {% if data[1] %} - {{ (data[1].amount - data[3])|formatAmount }} - {% else %} - {{ (0 - data[3])|formatAmount }} - {% endif %} - {{ data[2]|formatAmount }}
{{ 'balancedByTransfersAndTags'|_ }} - {{ account.balancedAmount|formatAmount }} -  
{{ 'leftUnbalanced'|_ }} - {% if account.budgetInformation[0].queryAmount + account.balancedAmount != 0.0 %} - {{ (account.budgetInformation[0].queryAmount + account.balancedAmount)|formatAmount }} - {% else %} - {{ (account.budgetInformation[0].queryAmount + account.balancedAmount)|formatAmount }} - {% endif %} - {{ 0|formatAmount }} 
{{ 'sum'|_ }}{{ accountAmounts[account.id]|formatAmount }} 
{{ 'expectedBalance'|_ }}{{ (account.startBalance + accountAmounts[account.id])|formatAmount }} 
-
+ {% include 'partials/reports/budgets-vs-accounts.twig' %}