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 }})
+
+
+
+
+ {{ 'budgets'|_ }} |
+ {% for account in balance.getBalanceHeader.getAccounts %}
+ {{ account.name }} |
+ {% endfor %}
+
+ {{ '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'|_ }}
+
+
+
+ {{ 'categories'|_ }} |
+ {{ 'spent'|_ }} |
+
+ {% for cat in categories.getCategories %}
+
+
+ {{ cat.name }}
+ |
+ {{ (cat.spent)|formatAmountPlain }} |
+
+ {% endfor %}
+
+ {{ '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'|_ }}
-
-
-
- {{ 'categories'|_ }} |
- {{ 'spent'|_ }} |
-
- {% set sum = 0 %}
- {% for data in categories %}
- {% if data[1] > 0 %}
-
-
- {{ data[0].name }}
- |
- {{ (data[1])|formatAmountPlain }} |
-
- {% endif %}
- {% endfor %}
-
-
+
+ {% include 'partials/reports/categories.twig' %}
@@ -68,112 +47,7 @@
-
-
-
- {{ 'budgets'|_ }} ({{ 'splitByAccount'|_|lower }})
-
-
-
- {{ 'budgets'|_ }} |
- {% for account in accounts %}
- {{ account.name }} |
- {% endfor %}
-
- {{ 'leftInBudget'|_ }}
- |
-
- {% for data in budgets %}
- {% if data[0] %}
-
- {{ data[0].name }} |
-
- {% if data[1] %}
- {{ data[1].amount|formatAmount }}
- {% else %}
- {{ 0|formatAmount }}
- {% endif %}
- |
- {% set spent = 0 %}
- {% for account in accounts %}
- {% if account.budgetInformation[id] %}
-
- {% if id == 0 %}
-
- {{ account.budgetInformation[id].queryAmount|formatAmount }}
-
- {% else %}
- {{ account.budgetInformation[id].queryAmount|formatAmount }}
- {% endif %}
- |
- {% set spent = spent + account.budgetInformation[id].queryAmount %}
- {% else %}
- {{ 0|formatAmount }} |
- {% endif %}
- {% endfor %}
-
- {% if data[1] %}
- {{ (data[1].amount - data[3])|formatAmount }}
- {% else %}
- {{ (0 - data[3])|formatAmount }}
- {% endif %}
- |
- {{ data[2]|formatAmount }} |
-
- {% endif %}
- {% endfor %}
-
- {{ 'balancedByTransfersAndTags'|_ }} |
- {% for account in accounts %}
- {% if not account.hide %}
-
- {{ account.balancedAmount|formatAmount }}
- |
- {% endif %}
- {% endfor %}
- |
-
-
- {{ 'leftUnbalanced'|_ }} |
- {% for account in accounts %}
-
- {% if not account.hide %}
- {% if account.budgetInformation[0] %}
-
- {% 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 %}
- |
- {% else %}
- {{ 0|formatAmount }} |
- {% endif %}
- {% endif %}
- {% endfor %}
- |
-
-
- {{ 'sum'|_ }} |
- {% for account in accounts %}
- {% if not account.hide %}
- {{ accountAmounts[account.id]|formatAmount }} |
- {% endif %}
- {% endfor %}
- |
-
-
- {{ 'expectedBalance'|_ }} |
- {% for account in accounts %}
- {% if not account.hide %}
- {{ (account.startBalance + accountAmounts[account.id])|formatAmount }} |
- {% endif %}
- {% endfor %}
- |
-
-
-
-
+ {% include 'partials/reports/budgets-vs-accounts.twig' %}