mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Code for #385
This commit is contained in:
parent
c56f937521
commit
8baea2feb9
@ -24,6 +24,15 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface AccountChartGeneratorInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param array $values
|
||||
* @param array $names
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function pieChart(array $values, array $names): array;
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
|
@ -14,6 +14,7 @@ namespace FireflyIII\Generator\Chart\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Support\ChartColour;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
@ -83,6 +84,37 @@ class ChartJsAccountChartGenerator implements AccountChartGeneratorInterface
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $values
|
||||
* @param array $names
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function pieChart(array $values, array $names): array
|
||||
{
|
||||
$data = [
|
||||
'datasets' => [
|
||||
0 => [],
|
||||
],
|
||||
'labels' => [],
|
||||
];
|
||||
$index = 0;
|
||||
foreach ($values as $categoryId => $value) {
|
||||
|
||||
// make larger than 0
|
||||
if (bccomp($value, '0') === -1) {
|
||||
$value = bcmul($value, '-1');
|
||||
}
|
||||
|
||||
$data['datasets'][0]['data'][] = round($value, 2);
|
||||
$data['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index);
|
||||
$data['labels'][] = $names[$categoryId];
|
||||
$index++;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
|
@ -259,8 +259,10 @@ class JournalCollector implements JournalCollectorInterface
|
||||
|
||||
$this->query->where(
|
||||
function (EloquentBuilder $q) use ($categoryIds) {
|
||||
$q->whereIn('category_transaction.category_id', $categoryIds);
|
||||
$q->orWhereIn('category_transaction_journal.category_id', $categoryIds);
|
||||
if (count($categoryIds) > 0) {
|
||||
$q->whereIn('category_transaction.category_id', $categoryIds);
|
||||
$q->orWhereIn('category_transaction_journal.category_id', $categoryIds);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@ -383,6 +385,27 @@ class JournalCollector implements JournalCollectorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function withBudgetInformation(): JournalCollectorInterface
|
||||
{
|
||||
$this->joinBudgetTables();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function withCategoryInformation(): JournalCollectorInterface
|
||||
{
|
||||
|
||||
$this->joinCategoryTables();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
@ -516,6 +539,8 @@ class JournalCollector implements JournalCollectorInterface
|
||||
$this->joinedBudget = true;
|
||||
$this->query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
$this->query->leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id');
|
||||
$this->fields[] = 'budget_transaction_journal.budget_id as transaction_journal_budget_id';
|
||||
$this->fields[] = 'budget_transaction.budget_id as transaction_budget_id';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,6 +131,16 @@ interface JournalCollectorInterface
|
||||
*/
|
||||
public function setTypes(array $types): JournalCollectorInterface;
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function withBudgetInformation(): JournalCollectorInterface;
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function withCategoryInformation(): JournalCollectorInterface;
|
||||
|
||||
/**
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
|
@ -17,6 +17,7 @@ use Carbon\Carbon;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\JournalCollector;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Requests\AccountFormRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
@ -209,7 +210,7 @@ class AccountController extends Controller
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function show(AccountTaskerInterface $tasker, ARI $repository, Account $account)
|
||||
public function show(JournalCollectorInterface $collector, Account $account)
|
||||
{
|
||||
if ($account->accountType->type === AccountType::INITIAL_BALANCE) {
|
||||
return $this->redirectToOriginalAccount($account);
|
||||
@ -218,62 +219,20 @@ class AccountController extends Controller
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||
$subTitle = $account->name;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
/** @var Carbon $start */
|
||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
|
||||
// replace with journal collector:
|
||||
$collector = new JournalCollector(auth()->user());
|
||||
// grab those journals:
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->setLimit($pageSize)->setPage($page);
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('accounts/show/' . $account->id);
|
||||
|
||||
// grouped other months thing:
|
||||
// oldest transaction in account:
|
||||
$start = $repository->oldestJournalDate($account);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfX(new Carbon, $range);
|
||||
$entries = new Collection;
|
||||
// generate entries for each period (and cache those)
|
||||
$entries = $this->periodEntries($account);
|
||||
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('account-show');
|
||||
$cache->addProperty($account->id);
|
||||
|
||||
|
||||
if ($cache->has()) {
|
||||
$entries = $cache->get();
|
||||
Log::debug('Entries are cached, return cache.');
|
||||
|
||||
return view('accounts.show', compact('account', 'what', 'entries', 'subTitleIcon', 'journals', 'subTitle'));
|
||||
}
|
||||
|
||||
// only include asset accounts when this account is an asset:
|
||||
$assets = new Collection;
|
||||
if (in_array($account->accountType->type, [AccountType::ASSET, AccountType::DEFAULT])) {
|
||||
$assets = $repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]);
|
||||
}
|
||||
Log::debug('Going to get period expenses and incomes.');
|
||||
while ($end >= $start) {
|
||||
$end = Navigation::startOfPeriod($end, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||
$spent = $tasker->amountOutInPeriod(new Collection([$account]), $assets, $end, $currentEnd);
|
||||
$earned = $tasker->amountInInPeriod(new Collection([$account]), $assets, $end, $currentEnd);
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$entries->push([$dateStr, $dateName, $spent, $earned]);
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
||||
return view('accounts.show', compact('account', 'what', 'entries', 'subTitleIcon', 'journals', 'subTitle'));
|
||||
return view('accounts.show', compact('account', 'what', 'entries', 'subTitleIcon', 'journals', 'subTitle', 'start', 'end'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -318,7 +277,7 @@ class AccountController extends Controller
|
||||
$journals = $collector->getPaginatedJournals();
|
||||
$journals->setPath('accounts/show/' . $account->id . '/' . $date);
|
||||
|
||||
return view('accounts.show_with_date', compact('category', 'date', 'account', 'journals', 'subTitle', 'carbon'));
|
||||
return view('accounts.show_with_date', compact('category', 'date', 'account', 'journals', 'subTitle', 'carbon', 'start', 'end'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -397,6 +356,63 @@ class AccountController extends Controller
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns "period entries", so nov-2015, dec-2015, etc etc (this depends on the users session range)
|
||||
* and for each period, the amount of money spent and earned. This is a complex operation which is cached for
|
||||
* performance reasons.
|
||||
*
|
||||
* @param Account $account The account involved.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function periodEntries(Account $account): Collection
|
||||
{
|
||||
/** @var ARI $repository */
|
||||
$repository = app(ARI::class);
|
||||
/** @var AccountTaskerInterface $tasker */
|
||||
$tasker = app(AccountTaskerInterface::class);
|
||||
|
||||
$start = $repository->oldestJournalDate($account);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfX(new Carbon, $range);
|
||||
$entries = new Collection;
|
||||
|
||||
// properties for cache
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('account-show-period-entries');
|
||||
$cache->addProperty($account->id);
|
||||
|
||||
if ($cache->has()) {
|
||||
Log::debug('Entries are cached, return cache.');
|
||||
|
||||
return $cache->get();
|
||||
}
|
||||
|
||||
// only include asset accounts when this account is an asset:
|
||||
$assets = new Collection;
|
||||
if (in_array($account->accountType->type, [AccountType::ASSET, AccountType::DEFAULT])) {
|
||||
$assets = $repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]);
|
||||
}
|
||||
Log::debug('Going to get period expenses and incomes.');
|
||||
while ($end >= $start) {
|
||||
$end = Navigation::startOfPeriod($end, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||
$spent = $tasker->amountOutInPeriod(new Collection([$account]), $assets, $end, $currentEnd);
|
||||
$earned = $tasker->amountInInPeriod(new Collection([$account]), $assets, $end, $currentEnd);
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$entries->push([$dateStr, $dateName, $spent, $earned]);
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
||||
return $entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
|
@ -17,10 +17,15 @@ use Carbon\Carbon;
|
||||
use Exception;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Generator\Chart\Account\AccountChartGeneratorInterface;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
@ -99,6 +104,87 @@ class AccountController extends Controller
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JournalCollectorInterface $collector
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function expenseByBudget(JournalCollectorInterface $collector, Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($account->id);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('expenseByBudget');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
|
||||
|
||||
// grab all journals:
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->withBudgetInformation()->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$transactions = $collector->getJournals();
|
||||
|
||||
$result = [];
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$jrnlBudgetId = intval($transaction->transaction_journal_budget_id);
|
||||
$transBudgetId = intval($transaction->transaction_budget_id);
|
||||
$budgetId = max($jrnlBudgetId, $transBudgetId);
|
||||
|
||||
$result[$budgetId] = $result[$budgetId] ?? '0';
|
||||
$result[$budgetId] = bcadd($transaction->transaction_amount, $result[$budgetId]);
|
||||
}
|
||||
$names = $this->getBudgetNames(array_keys($result));
|
||||
$data = $this->generator->pieChart($result, $names);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JournalCollectorInterface $collector
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function expenseByCategory(JournalCollectorInterface $collector, Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($account->id);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('expenseByCategory');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
|
||||
// grab all journals:
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->withCategoryInformation()->setTypes([TransactionType::WITHDRAWAL]);
|
||||
$transactions = $collector->getJournals();
|
||||
$result = [];
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$jrnlCatId = intval($transaction->transaction_journal_category_id);
|
||||
$transCatId = intval($transaction->transaction_category_id);
|
||||
$categoryId = max($jrnlCatId, $transCatId);
|
||||
|
||||
$result[$categoryId] = $result[$categoryId] ?? '0';
|
||||
$result[$categoryId] = bcadd($transaction->transaction_amount, $result[$categoryId]);
|
||||
}
|
||||
$names = $this->getCategoryNames(array_keys($result));
|
||||
$data = $this->generator->pieChart($result, $names);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the balances for all the user's frontpage accounts.
|
||||
*
|
||||
@ -116,6 +202,43 @@ class AccountController extends Controller
|
||||
return Response::json($this->accountBalanceChart($start, $end, $accounts));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*/
|
||||
public function incomeByCategory(JournalCollectorInterface $collector, Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($account->id);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('incomeByCategory');
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get());
|
||||
}
|
||||
|
||||
// grab all journals:
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->withCategoryInformation()->setTypes([TransactionType::DEPOSIT]);
|
||||
$transactions = $collector->getJournals();
|
||||
$result = [];
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$jrnlCatId = intval($transaction->transaction_journal_category_id);
|
||||
$transCatId = intval($transaction->transaction_category_id);
|
||||
$categoryId = max($jrnlCatId, $transCatId);
|
||||
|
||||
$result[$categoryId] = $result[$categoryId] ?? '0';
|
||||
$result[$categoryId] = bcadd($transaction->transaction_amount, $result[$categoryId]);
|
||||
}
|
||||
$names = $this->getCategoryNames(array_keys($result));
|
||||
$data = $this->generator->pieChart($result, $names);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the balances for a given set of dates and accounts.
|
||||
*
|
||||
@ -227,7 +350,6 @@ class AccountController extends Controller
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param string $date
|
||||
@ -319,4 +441,51 @@ class AccountController extends Controller
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $budgetIds
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getBudgetNames(array $budgetIds): array
|
||||
{
|
||||
|
||||
/** @var BudgetRepositoryInterface $repository */
|
||||
$repository = app(BudgetRepositoryInterface::class);
|
||||
$budgets = $repository->getBudgets();
|
||||
$grouped = $budgets->groupBy('id')->toArray();
|
||||
$return = [];
|
||||
foreach ($budgetIds as $budgetId) {
|
||||
if (isset($grouped[$budgetId])) {
|
||||
$return[$budgetId] = $grouped[$budgetId][0]['name'];
|
||||
}
|
||||
}
|
||||
$return[0] = trans('firefly.no_budget');
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Small helper function for some of the charts.
|
||||
*
|
||||
* @param array $categoryIds
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getCategoryNames(array $categoryIds): array
|
||||
{
|
||||
/** @var CategoryRepositoryInterface $repository */
|
||||
$repository = app(CategoryRepositoryInterface::class);
|
||||
$categories = $repository->getCategories();
|
||||
$grouped = $categories->groupBy('id')->toArray();
|
||||
$return = [];
|
||||
foreach ($categoryIds as $categoryId) {
|
||||
if (isset($grouped[$categoryId])) {
|
||||
$return[$categoryId] = $grouped[$categoryId][0]['name'];
|
||||
}
|
||||
}
|
||||
$return[0] = trans('firefly.noCategory');
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* global $, lineChart, accountID, token */
|
||||
/* global $, lineChart, accountID, token, incomeByCategoryUri, expenseByCategoryUri, expenseByBudgetUri */
|
||||
|
||||
|
||||
// Return a helper with preserved width of cells
|
||||
@ -15,10 +15,11 @@ var fixHelper = function (e, tr) {
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(lineChart) === "function" && typeof accountID !== 'undefined') {
|
||||
|
||||
lineChart('chart/account/' + accountID, 'overview-chart');
|
||||
}
|
||||
pieChart(incomeByCategoryUri, 'account-cat-in');
|
||||
pieChart(expenseByCategoryUri, 'account-cat-out');
|
||||
pieChart(expenseByBudgetUri, 'account-budget-out');
|
||||
|
||||
|
||||
// sortable!
|
||||
if (typeof $(".sortable-table tbody").sortable !== "undefined") {
|
||||
|
@ -6,7 +6,7 @@
|
||||
* of the MIT license. See the LICENSE file for details.
|
||||
*/
|
||||
|
||||
/* global $, lineChart, dateString, accountID, token */
|
||||
/* global $, lineChart, dateString, accountID, token, incomeByCategoryUri, expenseByCategoryUri, expenseByBudgetUri */
|
||||
|
||||
|
||||
// Return a helper with preserved width of cells
|
||||
@ -23,13 +23,13 @@ var fixHelper = function (e, tr) {
|
||||
|
||||
$(function () {
|
||||
"use strict";
|
||||
if (typeof(lineChart) === "function" &&
|
||||
typeof accountID !== 'undefined' &&
|
||||
typeof dateString !== 'undefined'
|
||||
) {
|
||||
|
||||
lineChart('chart/account/' + accountID + '/' + dateString, 'period-specific-account');
|
||||
}
|
||||
lineChart('chart/account/' + accountID + '/' + dateString, 'period-specific-account');
|
||||
|
||||
pieChart(incomeByCategoryUri, 'account-cat-in');
|
||||
pieChart(expenseByCategoryUri, 'account-cat-out');
|
||||
pieChart(expenseByBudgetUri, 'account-budget-out');
|
||||
|
||||
|
||||
// sortable!
|
||||
if (typeof $(".sortable-table tbody").sortable !== "undefined") {
|
||||
|
@ -87,6 +87,9 @@ return [
|
||||
'need_more_help' => 'If you need more help using Firefly III, please <a href="https://github.com/JC5/firefly-iii/issues">open a ticker on Github</a>.',
|
||||
'nothing_to_display' => 'There are no transactions to show you',
|
||||
'show_all_no_filter' => 'Show all transactions without grouping them by date.',
|
||||
'expenses_by_category' => 'Expenses by category',
|
||||
'expenses_by_budget' => 'Expenses by budget',
|
||||
'income_by_category' => 'Income by category',
|
||||
|
||||
// repeat frequencies:
|
||||
'repeat_freq_yearly' => 'yearly',
|
||||
|
@ -28,7 +28,44 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'expenses_by_category'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div style="width:60%;margin:0 auto;">
|
||||
<canvas id="account-cat-out" style="margin:0 auto;" height="150" width="150"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'expenses_by_budget'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div style="width:60%;margin:0 auto;">
|
||||
<canvas id="account-budget-out" style="margin:0 auto;" height="150" width="150"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'income_by_category'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div style="width:60%;margin:0 auto;">
|
||||
<canvas id="account-cat-in" style="margin:0 auto;" height="150" width="150"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-10 col-md-10 col-sm-12">
|
||||
@ -85,7 +122,13 @@
|
||||
{% block scripts %}
|
||||
<script type="text/javascript">
|
||||
var accountID = {{ account.id }};
|
||||
// uri's for charts:
|
||||
var incomeByCategoryUri = '{{ route('chart.account.incomeByCategory', [account.id, start.format('Ymd'), end.format('Ymd')]) }}';
|
||||
var expenseByCategoryUri = '{{ route('chart.account.expenseByCategory', [account.id, start.format('Ymd'), end.format('Ymd')]) }}';
|
||||
var expenseByBudgetUri = '{{ route('chart.account.expenseByBudget', [account.id, start.format('Ymd'), end.format('Ymd')]) }}';
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="js/lib/Chart.bundle.min.js"></script>
|
||||
<script type="text/javascript" src="js/ff/charts.defaults.js"></script>
|
||||
<script type="text/javascript" src="js/ff/charts.js"></script>
|
||||
|
@ -32,6 +32,45 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'expenses_by_category'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div style="width:60%;margin:0 auto;">
|
||||
<canvas id="account-cat-out" style="margin:0 auto;" height="150" width="150"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'expenses_by_budget'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div style="width:60%;margin:0 auto;">
|
||||
<canvas id="account-budget-out" style="margin:0 auto;" height="150" width="150"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ 'income_by_category'|_ }}</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div style="width:60%;margin:0 auto;">
|
||||
<canvas id="account-cat-in" style="margin:0 auto;" height="150" width="150"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<div class="box">
|
||||
@ -53,6 +92,12 @@
|
||||
<script type="text/javascript">
|
||||
var accountID = {{ account.id }};
|
||||
var dateString = "{{ date }}";
|
||||
|
||||
// uri's for charts:
|
||||
var incomeByCategoryUri = '{{ route('chart.account.incomeByCategory', [account.id, start.format('Ymd'), end.format('Ymd')]) }}';
|
||||
var expenseByCategoryUri = '{{ route('chart.account.expenseByCategory', [account.id, start.format('Ymd'), end.format('Ymd')]) }}';
|
||||
var expenseByBudgetUri = '{{ route('chart.account.expenseByBudget', [account.id, start.format('Ymd'), end.format('Ymd')]) }}';
|
||||
|
||||
</script>
|
||||
<script type="text/javascript" src="js/lib/Chart.bundle.min.js"></script>
|
||||
<script type="text/javascript" src="js/ff/charts.defaults.js"></script>
|
||||
|
@ -190,6 +190,19 @@ Route::group(
|
||||
Route::get('/chart/account/{account}', ['uses' => 'Chart\AccountController@single']);
|
||||
Route::get('/chart/account/{account}/{date}', ['uses' => 'Chart\AccountController@specificPeriod']);
|
||||
|
||||
Route::get(
|
||||
'/chart/account/income-by-category/{account}/{start_date}/{end_date}',
|
||||
['uses' => 'Chart\AccountController@incomeByCategory', 'as' => 'chart.account.incomeByCategory']
|
||||
);
|
||||
Route::get(
|
||||
'/chart/account/expense-by-category/{account}/{start_date}/{end_date}',
|
||||
['uses' => 'Chart\AccountController@expenseByCategory', 'as' => 'chart.account.expenseByCategory']
|
||||
);
|
||||
Route::get(
|
||||
'/chart/account/expense-by-budget/{account}/{start_date}/{end_date}',
|
||||
['uses' => 'Chart\AccountController@expenseByBudget', 'as' => 'chart.account.expenseByBudget']
|
||||
);
|
||||
|
||||
|
||||
// bills:
|
||||
Route::get('/chart/bill/frontpage', ['uses' => 'Chart\BillController@frontpage']);
|
||||
|
Loading…
Reference in New Issue
Block a user