diff --git a/app/Generator/Chart/Account/AccountChartGenerator.php b/app/Generator/Chart/Account/AccountChartGenerator.php
index 8a019d155e..d64876c7d6 100644
--- a/app/Generator/Chart/Account/AccountChartGenerator.php
+++ b/app/Generator/Chart/Account/AccountChartGenerator.php
@@ -40,4 +40,13 @@ interface AccountChartGenerator
* @return array
*/
public function single(Account $account, Carbon $start, Carbon $end);
+
+ /**
+ * @param Collection $accounts
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return array
+ */
+ public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end);
}
diff --git a/app/Generator/Chart/Account/ChartJsAccountChartGenerator.php b/app/Generator/Chart/Account/ChartJsAccountChartGenerator.php
index a6ab113571..92abc7bb90 100644
--- a/app/Generator/Chart/Account/ChartJsAccountChartGenerator.php
+++ b/app/Generator/Chart/Account/ChartJsAccountChartGenerator.php
@@ -32,6 +32,65 @@ class ChartJsAccountChartGenerator implements AccountChartGenerator
return $this->frontpage($accounts, $start, $end);
}
+ /**
+ * @param Collection $accounts
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return array
+ */
+ public function expenseAccounts(Collection $accounts, Carbon $start, Carbon $end)
+ {
+ // language:
+
+ $data = [
+ 'count' => 1,
+ 'labels' => [],
+ 'datasets' => [
+ [
+ 'label' => trans('firefly.spent'),
+ 'data' => []
+ ]
+ ],
+ ];
+ $ids = [];
+
+ foreach ($accounts as $account) {
+ $ids[] = $account->id;
+ }
+ $start->subDay();
+
+ $startBalances = Steam::balancesById($ids, $start);
+ $endBalances = Steam::balancesById($ids, $end);
+
+ $accounts->each(
+ function (Account $account) use ($startBalances, $endBalances) {
+ $id = $account->id;
+ $startBalance = isset($startBalances[$id]) ? $startBalances[$id] : 0;
+ $endBalance = isset($endBalances[$id]) ? $endBalances[$id] : 0;
+ $diff = $endBalance - $startBalance;
+ $account->difference = round($diff, 2);
+ }
+ );
+
+ $accounts = $accounts->sortByDesc(
+ function (Account $account) {
+ return $account->difference;
+ }
+ );
+
+ foreach ($accounts as $account) {
+ if ($account->difference > 0) {
+ $data['labels'][] = $account->name;
+ $data['datasets'][0]['data'][] = $account->difference;
+ }
+ }
+
+
+ return $data;
+ }
+
+
/**
* @param Collection $accounts
* @param Carbon $start
diff --git a/app/Generator/Chart/Account/GoogleAccountChartGenerator.php b/app/Generator/Chart/Account/GoogleAccountChartGenerator.php
deleted file mode 100644
index ab84e168ce..0000000000
--- a/app/Generator/Chart/Account/GoogleAccountChartGenerator.php
+++ /dev/null
@@ -1,97 +0,0 @@
-addColumn(trans('firefly.dayOfMonth'), 'date');
- $index = 1;
- /** @var Account $account */
- foreach ($accounts as $account) {
- $chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
- $chart->addCertainty($index);
- $index++;
- }
- $current = clone $start;
- $current->subDay();
- $today = Carbon::now();
- while ($end >= $current) {
- $row = [clone $current];
- $certain = $current < $today;
- foreach ($accounts as $account) {
- $row[] = Steam::balance($account, $current);
- $row[] = $certain;
- }
- $chart->addRowArray($row);
- $current->addDay();
- }
- $chart->generate();
-
- return $chart->getData();
- }
-
- /**
- * @param Collection $accounts
- * @param Carbon $start
- * @param Carbon $end
- *
- * @return array
- */
- public function frontpage(Collection $accounts, Carbon $start, Carbon $end)
- {
- return $this->all($accounts, $start, $end);
- }
-
- /**
- * @param Account $account
- * @param Carbon $start
- * @param Carbon $end
- *
- * @return array
- */
- public function single(Account $account, Carbon $start, Carbon $end)
- {
- $current = clone $start;
- $today = new Carbon;
- $chart = new GChart;
- $chart->addColumn(trans('firefly.dayOfMonth'), 'date');
- $chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
- $chart->addCertainty(1);
-
- while ($end >= $current) {
- $certain = $current < $today;
- $chart->addRow(clone $current, Steam::balance($account, $current), $certain);
- $current->addDay();
- }
-
-
- $chart->generate();
-
- return $chart->getData();
- }
-}
diff --git a/app/Generator/Chart/Bill/GoogleBillChartGenerator.php b/app/Generator/Chart/Bill/GoogleBillChartGenerator.php
deleted file mode 100644
index 3ccf83d7d5..0000000000
--- a/app/Generator/Chart/Bill/GoogleBillChartGenerator.php
+++ /dev/null
@@ -1,94 +0,0 @@
-description;
- $paidAmount = bcadd($paidAmount, $entry->amount);
- }
-
- // loop unpaid:
- /** @var Bill $entry */
- foreach ($unpaid as $entry) {
- $description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
- $amount = bcdiv(bcadd($entry[0]->amount_max, $entry[0]->amount_min), 2);
- $unpaidDescriptions[] = $description;
- $unpaidAmount = bcadd($unpaidAmount, $amount);
- unset($amount, $description);
- }
-
- $chart = new GChart;
- $chart->addColumn(trans('firefly.name'), 'string');
- $chart->addColumn(trans('firefly.amount'), 'number');
-
- $chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount);
- $chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount);
-
- $chart->generate();
-
- return $chart->getData();
- }
-
- /**
- * @param Bill $bill
- * @param Collection $entries
- *
- * @return mixed
- */
- public function single(Bill $bill, Collection $entries)
- {
- // make chart:
- $chart = new GChart;
- $chart->addColumn(trans('firefly.date'), 'date');
- $chart->addColumn(trans('firefly.maxAmount'), 'number');
- $chart->addColumn(trans('firefly.minAmount'), 'number');
- $chart->addColumn(trans('firefly.billEntry'), 'number');
-
- /** @var TransactionJournal $result */
- foreach ($entries as $result) {
- $chart->addRow(
- clone $result->date,
- round($bill->amount_max, 2),
- round($bill->amount_min, 2),
- round($result->amount, 2)
- );
- }
-
- $chart->generate();
-
- return $chart->getData();
- }
-}
diff --git a/app/Generator/Chart/Budget/GoogleBudgetChartGenerator.php b/app/Generator/Chart/Budget/GoogleBudgetChartGenerator.php
deleted file mode 100644
index 848c493b68..0000000000
--- a/app/Generator/Chart/Budget/GoogleBudgetChartGenerator.php
+++ /dev/null
@@ -1,102 +0,0 @@
-addColumn(trans('firefly.period'), 'date');
- $chart->addColumn(trans('firefly.spent'), 'number');
-
- /** @var array $entry */
- foreach ($entries as $entry) {
- $chart->addRow($entry[0], $entry[1]);
- }
-
- $chart->generate();
-
- return $chart->getData();
- }
-
- /**
- * @codeCoverageIgnore
- *
- * @param Collection $entries
- *
- * @return array
- */
- public function budgetLimit(Collection $entries)
- {
- return $this->budget($entries);
- }
-
- /**
- * @param Collection $entries
- *
- * @return array
- */
- public function frontpage(Collection $entries)
- {
- $chart = new GChart;
- $chart->addColumn(trans('firefly.budget'), 'string');
- $chart->addColumn(trans('firefly.left'), 'number');
- $chart->addColumn(trans('firefly.spent'), 'number');
- $chart->addColumn(trans('firefly.overspent'), 'number');
-
- /** @var array $entry */
- foreach ($entries as $entry) {
- if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
- $chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]);
- }
- }
-
-
- $chart->generate();
-
- return $chart->getData();
-
- }
-
- /**
- * @param Collection $budgets
- * @param Collection $entries
- *
- * @return array
- */
- public function year(Collection $budgets, Collection $entries)
- {
- $chart = new GChart;
- // add columns:
- $chart->addColumn(trans('firefly.month'), 'date');
- foreach ($budgets as $budget) {
- $chart->addColumn($budget->name, 'number');
- }
-
- /** @var array $entry */
- foreach ($entries as $entry) {
-
- $chart->addRowArray($entry);
- }
-
- $chart->generate();
-
- return $chart->getData();
- }
-}
diff --git a/app/Generator/Chart/Category/CategoryChartGenerator.php b/app/Generator/Chart/Category/CategoryChartGenerator.php
index 16c04a48bd..3c2698c5b7 100644
--- a/app/Generator/Chart/Category/CategoryChartGenerator.php
+++ b/app/Generator/Chart/Category/CategoryChartGenerator.php
@@ -40,5 +40,13 @@ interface CategoryChartGenerator
*
* @return array
*/
- public function year(Collection $categories, Collection $entries);
+ public function spentInYear(Collection $categories, Collection $entries);
+
+ /**
+ * @param Collection $categories
+ * @param Collection $entries
+ *
+ * @return array
+ */
+ public function earnedInYear(Collection $categories, Collection $entries);
}
diff --git a/app/Generator/Chart/Category/ChartJsCategoryChartGenerator.php b/app/Generator/Chart/Category/ChartJsCategoryChartGenerator.php
index 42e17d875c..621a51ee13 100644
--- a/app/Generator/Chart/Category/ChartJsCategoryChartGenerator.php
+++ b/app/Generator/Chart/Category/ChartJsCategoryChartGenerator.php
@@ -29,19 +29,30 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
$format = Config::get('firefly.' . $dateFormat . '.' . $language);
$data = [
- 'count' => 1,
+ 'count' => 2,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.spent'),
'data' => []
+ ],
+ [
+ 'label' => trans('firefly.earned'),
+ 'data' => []
]
],
];
foreach ($entries as $entry) {
- $data['labels'][] = $entry[0]->formatLocalized($format);
- $data['datasets'][0]['data'][] = round($entry[1], 2);
+ $data['labels'][] = $entry[0]->formatLocalized($format);
+ $amount = round($entry[1], 2);
+ if ($amount > 0) {
+ $data['datasets'][0]['data'][] = null;
+ $data['datasets'][1]['data'][] = $amount;
+ } else {
+ $data['datasets'][0]['data'][] = $amount * -1;
+ $data['datasets'][1]['data'][] = null;
+ }
}
return $data;
@@ -93,7 +104,41 @@ class ChartJsCategoryChartGenerator implements CategoryChartGenerator
*
* @return array
*/
- public function year(Collection $categories, Collection $entries)
+ public function spentInYear(Collection $categories, Collection $entries)
+ {
+
+ // language:
+ $language = Preferences::get('language', 'en')->data;
+ $format = Config::get('firefly.month.' . $language);
+
+ $data = [
+ 'count' => 0,
+ 'labels' => [],
+ 'datasets' => [],
+ ];
+
+ foreach ($categories as $category) {
+ $data['labels'][] = $category->name;
+ }
+
+ foreach ($entries as $entry) {
+ $date = $entry[0]->formatLocalized($format);
+ array_shift($entry);
+ $data['count']++;
+ $data['datasets'][] = ['label' => $date, 'data' => $entry];
+ }
+
+ return $data;
+
+ }
+
+ /**
+ * @param Collection $categories
+ * @param Collection $entries
+ *
+ * @return array
+ */
+ public function earnedInYear(Collection $categories, Collection $entries)
{
// language:
diff --git a/app/Generator/Chart/Category/GoogleCategoryChartGenerator.php b/app/Generator/Chart/Category/GoogleCategoryChartGenerator.php
deleted file mode 100644
index 476f90c998..0000000000
--- a/app/Generator/Chart/Category/GoogleCategoryChartGenerator.php
+++ /dev/null
@@ -1,106 +0,0 @@
-addColumn(trans('firefly.period'), 'date');
- $chart->addColumn(trans('firefly.spent'), 'number');
-
- /** @var array $entry */
- foreach ($entries as $entry) {
- $chart->addRow($entry[0], $entry[1]);
- }
-
- $chart->generate();
-
- return $chart->getData();
- }
-
- /**
- * @param Collection $entries
- *
- * @return array
- */
- public function frontpage(Collection $entries)
- {
- $chart = new GChart;
- $chart->addColumn(trans('firefly.category'), 'string');
- $chart->addColumn(trans('firefly.spent'), 'number');
-
-
- /** @var array $entry */
- foreach ($entries as $entry) {
- $sum = $entry['sum'];
- if ($sum != 0) {
- $chart->addRow($entry['name'], $sum);
- }
- }
-
- $chart->generate();
-
- return $chart->getData();
- }
-
- /**
- * @param Collection $entries
- *
- * @return array
- */
- public function month(Collection $entries)
- {
- $chart = new GChart;
-
- $chart->addColumn(trans('firefly.period'), 'date');
- $chart->addColumn(trans('firefly.spent'), 'number');
-
- /** @var array $entry */
- foreach ($entries as $entry) {
- $chart->addRow($entry[0], $entry[1]);
- }
- $chart->generate();
-
- return $chart->getData();
- }
-
- /**
- * @param Collection $categories
- * @param Collection $entries
- *
- * @return array
- */
- public function year(Collection $categories, Collection $entries)
- {
- $chart = new GChart;
-
- $chart->addColumn(trans('firefly.month'), 'date');
- foreach ($categories as $category) {
- $chart->addColumn($category->name, 'number');
- }
- /** @var array $entry */
- foreach ($entries as $entry) {
- $chart->addRowArray($entry);
- }
- $chart->generate();
-
- return $chart->getData();
-
- }
-}
diff --git a/app/Generator/Chart/PiggyBank/ChartJsPiggyBankChartGenerator.php b/app/Generator/Chart/PiggyBank/ChartJsPiggyBankChartGenerator.php
index 0bd146b737..8927d1bb91 100644
--- a/app/Generator/Chart/PiggyBank/ChartJsPiggyBankChartGenerator.php
+++ b/app/Generator/Chart/PiggyBank/ChartJsPiggyBankChartGenerator.php
@@ -9,7 +9,7 @@ use Preferences;
/**
- * Class GooglePiggyBankChartGenerator
+ * Class ChartJsPiggyBankChartGenerator
*
* @package FireflyIII\Generator\Chart\PiggyBank
*/
diff --git a/app/Generator/Chart/PiggyBank/GooglePiggyBankChartGenerator.php b/app/Generator/Chart/PiggyBank/GooglePiggyBankChartGenerator.php
deleted file mode 100644
index 15d6eb9931..0000000000
--- a/app/Generator/Chart/PiggyBank/GooglePiggyBankChartGenerator.php
+++ /dev/null
@@ -1,41 +0,0 @@
-addColumn(trans('firefly.date'), 'date');
- $chart->addColumn(trans('firefly.balance'), 'number');
-
- $sum = '0';
- bcscale(2);
-
- foreach ($set as $entry) {
- $sum = bcadd($sum, $entry->sum);
- $chart->addRow(new Carbon($entry->date), $sum);
- }
-
- $chart->generate();
-
- return $chart->getData();
- }
-}
diff --git a/app/Generator/Chart/Report/ChartJsReportChartGenerator.php b/app/Generator/Chart/Report/ChartJsReportChartGenerator.php
index ef9a921ef1..ef9611ff31 100644
--- a/app/Generator/Chart/Report/ChartJsReportChartGenerator.php
+++ b/app/Generator/Chart/Report/ChartJsReportChartGenerator.php
@@ -7,7 +7,7 @@ use Illuminate\Support\Collection;
use Preferences;
/**
- * Class GoogleReportChartGenerator
+ * Class ChartJsReportChartGenerator
*
* @package FireflyIII\Generator\Chart\Report
*/
diff --git a/app/Generator/Chart/Report/GoogleReportChartGenerator.php b/app/Generator/Chart/Report/GoogleReportChartGenerator.php
deleted file mode 100644
index f995596687..0000000000
--- a/app/Generator/Chart/Report/GoogleReportChartGenerator.php
+++ /dev/null
@@ -1,58 +0,0 @@
-addColumn(trans('firefly.month'), 'date');
- $chart->addColumn(trans('firefly.income'), 'number');
- $chart->addColumn(trans('firefly.expenses'), 'number');
-
- /** @var array $entry */
- foreach ($entries as $entry) {
- $chart->addRowArray($entry);
- }
- $chart->generate();
-
- return $chart->getData();
- }
-
- /**
- * @param string $income
- * @param string $expense
- * @param int $count
- *
- * @return array
- */
- public function yearInOutSummarized($income, $expense, $count)
- {
- $chart = new GChart;
-
- $chart->addColumn(trans('firefly.summary'), 'string');
- $chart->addColumn(trans('firefly.income'), 'number');
- $chart->addColumn(trans('firefly.expenses'), 'number');
- $chart->addRow(trans('firefly.sum'), $income, $expense);
- $chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count));
-
- $chart->generate();
-
- return $chart->getData();
- }
-}
diff --git a/app/Helpers/Collection/Category.php b/app/Helpers/Collection/Category.php
index 76ed0f05de..e365d2c27d 100644
--- a/app/Helpers/Collection/Category.php
+++ b/app/Helpers/Collection/Category.php
@@ -34,7 +34,8 @@ class Category
*/
public function addCategory(CategoryModel $category)
{
- if ($category->spent > 0) {
+ // spent is minus zero for an expense report:
+ if ($category->spent < 0) {
$this->categories->push($category);
}
}
diff --git a/app/Helpers/Csv/Converter/Date.php b/app/Helpers/Csv/Converter/Date.php
index c92de17921..d43a961ac1 100644
--- a/app/Helpers/Csv/Converter/Date.php
+++ b/app/Helpers/Csv/Converter/Date.php
@@ -3,6 +3,9 @@
namespace FireflyIII\Helpers\Csv\Converter;
use Carbon\Carbon;
+use FireflyIII\Exceptions\FireflyException;
+use InvalidArgumentException;
+use Log;
use Session;
/**
@@ -19,8 +22,16 @@ class Date extends BasicConverter implements ConverterInterface
public function convert()
{
$format = Session::get('csv-date-format');
+ try {
+ $date = Carbon::createFromFormat($format, $this->value);
+ } catch (InvalidArgumentException $e) {
+ Log::error('Date conversion error: ' . $e->getMessage() . '. Value was "' . $this->value . '", format was "' . $format . '".');
+
+ $message = trans('firefly.csv_date_parse_error', ['format' => $format, 'value' => $this->value]);
+
+ throw new FireflyException($message);
+ }
- $date = Carbon::createFromFormat($format, $this->value);
return $date;
}
diff --git a/app/Helpers/Csv/Importer.php b/app/Helpers/Csv/Importer.php
index aa6b32334c..73286efa38 100644
--- a/app/Helpers/Csv/Importer.php
+++ b/app/Helpers/Csv/Importer.php
@@ -124,7 +124,7 @@ class Importer
*/
protected function parseRow($index)
{
- return (($this->data->hasHeaders() && $index > 1) || !$this->data->hasHeaders());
+ return (($this->data->hasHeaders() && $index >= 1) || !$this->data->hasHeaders());
}
/**
diff --git a/app/Helpers/Report/ReportHelper.php b/app/Helpers/Report/ReportHelper.php
index 095d68ae53..bccc191c87 100644
--- a/app/Helpers/Report/ReportHelper.php
+++ b/app/Helpers/Report/ReportHelper.php
@@ -263,7 +263,7 @@ class ReportHelper implements ReportHelperInterface
// no repetition(s) for this budget:
if ($repetitions->count() == 0) {
- $spent = $repository->spentInPeriodCorrected($budget, $start, $end, $shared);
+ $spent = $repository->balanceInPeriod($budget, $start, $end, $shared);
$budgetLine = new BudgetLine;
$budgetLine->setBudget($budget);
$budgetLine->setOverspent($spent);
@@ -278,7 +278,7 @@ class ReportHelper implements ReportHelperInterface
$budgetLine = new BudgetLine;
$budgetLine->setBudget($budget);
$budgetLine->setRepetition($repetition);
- $expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, $shared);
+ $expenses = $repository->balanceInPeriod($budget, $repetition->startdate, $repetition->enddate, $shared);
$left = $expenses < $repetition->amount ? bcsub($repetition->amount, $expenses) : 0;
$spent = $expenses > $repetition->amount ? 0 : $expenses;
$overspent = $expenses > $repetition->amount ? bcsub($expenses, $repetition->amount) : 0;
@@ -327,7 +327,7 @@ class ReportHelper implements ReportHelperInterface
$repository = app('FireflyIII\Repositories\Category\CategoryRepositoryInterface');
$set = $repository->getCategories();
foreach ($set as $category) {
- $spent = $repository->spentInPeriodCorrected($category, $start, $end, $shared);
+ $spent = $repository->balanceInPeriod($category, $start, $end, $shared);
$category->spent = $spent;
$object->addCategory($category);
$object->addTotal($spent);
diff --git a/app/Http/Controllers/BudgetController.php b/app/Http/Controllers/BudgetController.php
index 5e698ee423..02ef9eaece 100644
--- a/app/Http/Controllers/BudgetController.php
+++ b/app/Http/Controllers/BudgetController.php
@@ -152,7 +152,7 @@ class BudgetController extends Controller
foreach ($budgets as $budget) {
$date = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
- $budget->spent = $repository->spentInPeriodCorrected($budget, $date, $end);
+ $budget->spent = $repository->balanceInPeriod($budget, $date, $end);
$budget->currentRep = $repository->getCurrentRepetition($budget, $date);
if ($budget->currentRep) {
$budgeted = bcadd($budgeted, $budget->currentRep->amount);
diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php
index 790d2fd822..7580f30a78 100644
--- a/app/Http/Controllers/CategoryController.php
+++ b/app/Http/Controllers/CategoryController.php
@@ -151,10 +151,12 @@ class CategoryController extends Controller
$page = intval(Input::get('page'));
$set = $repository->getJournals($category, $page);
$count = $repository->countJournals($category);
+ $totalSum = $repository->journalsSum($category);
+ $periodSum = $repository->journalsSum($category, Session::get('start'), Session::get('end'));
$journals = new LengthAwarePaginator($set, $count, 50, $page);
$journals->setPath('categories/show/' . $category->id);
- return view('categories.show', compact('category', 'journals', 'hideCategory'));
+ return view('categories.show', compact('category', 'journals', 'hideCategory', 'totalSum', 'periodSum'));
}
/**
diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php
index e1447488e9..116e2c00aa 100644
--- a/app/Http/Controllers/Chart/AccountController.php
+++ b/app/Http/Controllers/Chart/AccountController.php
@@ -79,6 +79,36 @@ class AccountController extends Controller
return Response::json($data);
}
+ /**
+ * Shows the balances for all the user's expense accounts.
+ *
+ * @param AccountRepositoryInterface $repository
+ *
+ * @return \Symfony\Component\HttpFoundation\Response
+ */
+ public function expenseAccounts(AccountRepositoryInterface $repository)
+ {
+ $start = clone Session::get('start', Carbon::now()->startOfMonth());
+ $end = clone Session::get('end', Carbon::now()->endOfMonth());
+ $accounts = $repository->getAccounts(['Expense account', 'Beneficiary account']);
+
+ // chart properties for cache:
+ $cache = new CacheProperties();
+ $cache->addProperty($start);
+ $cache->addProperty($end);
+ $cache->addProperty('expenseAccounts');
+ $cache->addProperty('accounts');
+ if ($cache->has()) {
+ return Response::json($cache->get()); // @codeCoverageIgnore
+ }
+
+ $data = $this->generator->expenseAccounts($accounts, $start, $end);
+ $cache->store($data);
+
+ return Response::json($data);
+
+ }
+
/**
* Shows the balances for all the user's frontpage accounts.
*
diff --git a/app/Http/Controllers/Chart/BudgetController.php b/app/Http/Controllers/Chart/BudgetController.php
index 039d04308d..d5036356d8 100644
--- a/app/Http/Controllers/Chart/BudgetController.php
+++ b/app/Http/Controllers/Chart/BudgetController.php
@@ -68,7 +68,7 @@ class BudgetController extends Controller
$end->subDay();
$chartDate = clone $end;
$chartDate->startOfMonth();
- $spent = $repository->spentInPeriodCorrected($budget, $first, $end);
+ $spent = $repository->balanceInPeriod($budget, $first, $end);
$entries->push([$chartDate, $spent]);
$first = Navigation::addPeriod($first, $range, 0);
}
@@ -156,13 +156,13 @@ class BudgetController extends Controller
foreach ($budgets as $budget) {
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
if ($repetitions->count() == 0) {
- $expenses = $repository->spentInPeriodCorrected($budget, $start, $end, true);
+ $expenses = $repository->balanceInPeriod($budget, $start, $end, true);
$allEntries->push([$budget->name, 0, 0, $expenses, 0, 0]);
continue;
}
/** @var LimitRepetition $repetition */
foreach ($repetitions as $repetition) {
- $expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true);
+ $expenses = $repository->balanceInPeriod($budget, $repetition->startdate, $repetition->enddate, true);
// $left can be less than zero.
// $overspent can be more than zero ( = overspending)
@@ -199,10 +199,11 @@ class BudgetController extends Controller
*/
public function year(BudgetRepositoryInterface $repository, $year, $shared = false)
{
- $start = new Carbon($year . '-01-01');
- $end = new Carbon($year . '-12-31');
- $shared = $shared == 'shared' ? true : false;
- $budgets = $repository->getBudgets();
+ $start = new Carbon($year . '-01-01');
+ $end = new Carbon($year . '-12-31');
+ $shared = $shared == 'shared' ? true : false;
+ $allBudgets = $repository->getBudgets();
+ $budgets = new Collection;
// chart properties for cache:
$cache = new CacheProperties();
@@ -214,6 +215,15 @@ class BudgetController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore
}
+ // filter empty budgets:
+
+ foreach ($allBudgets as $budget) {
+ $spent = $repository->balanceInPeriod($budget, $start, $end, $shared);
+ if ($spent != 0) {
+ $budgets->push($budget);
+ }
+ }
+
$entries = new Collection;
while ($start < $end) {
@@ -224,14 +234,14 @@ class BudgetController extends Controller
// each budget, fill the row:
foreach ($budgets as $budget) {
- $spent = $repository->spentInPeriodCorrected($budget, $start, $month, $shared);
- $row[] = $spent;
+ $spent = $repository->balanceInPeriod($budget, $start, $month, $shared);
+ $row[] = $spent * -1;
}
$entries->push($row);
$start->endOfMonth()->addDay();
}
- $data = $this->generator->year($budgets, $entries);
+ $data = $this->generator->year($allBudgets, $entries);
$cache->store($data);
return Response::json($data);
diff --git a/app/Http/Controllers/Chart/CategoryController.php b/app/Http/Controllers/Chart/CategoryController.php
index f1fde920dc..840bc68aed 100644
--- a/app/Http/Controllers/Chart/CategoryController.php
+++ b/app/Http/Controllers/Chart/CategoryController.php
@@ -46,11 +46,10 @@ class CategoryController extends Controller
public function all(CategoryRepositoryInterface $repository, Category $category)
{
// oldest transaction in category:
- $start = $repository->getFirstActivityDate($category);
- $range = Preferences::get('viewRange', '1M')->data;
- $start = Navigation::startOfPeriod($start, $range);
- $end = new Carbon;
-
+ $start = $repository->getFirstActivityDate($category);
+ $range = Preferences::get('viewRange', '1M')->data;
+ $start = Navigation::startOfPeriod($start, $range);
+ $end = new Carbon;
$entries = new Collection;
@@ -66,7 +65,7 @@ class CategoryController extends Controller
while ($start <= $end) {
$currentEnd = Navigation::endOfPeriod($start, $range);
- $spent = $repository->spentInPeriodCorrected($category, $start, $currentEnd);
+ $spent = $repository->balanceInPeriod($category, $start, $currentEnd);
$entries->push([clone $start, $spent]);
$start = Navigation::addPeriod($start, $range, 0);
@@ -170,7 +169,7 @@ class CategoryController extends Controller
*
* @return \Symfony\Component\HttpFoundation\Response
*/
- public function year(CategoryRepositoryInterface $repository, $year, $shared = false)
+ public function spentInYear(CategoryRepositoryInterface $repository, $year, $shared = false)
{
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
@@ -179,14 +178,24 @@ class CategoryController extends Controller
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('category');
- $cache->addProperty('year');
+ $cache->addProperty('spent-in-year');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
- $shared = $shared == 'shared' ? true : false;
- $categories = $repository->getCategories();
- $entries = new Collection;
+ $shared = $shared == 'shared' ? true : false;
+ $allCategories = $repository->getCategories();
+ $entries = new Collection;
+ $categories = $allCategories->filter(
+ function (Category $category) use ($repository, $start, $end, $shared) {
+ $spent = $repository->balanceInPeriod($category, $start, $end, $shared);
+ if ($spent < 0) {
+ return $category;
+ }
+
+ return null;
+ }
+ );
while ($start < $end) {
$month = clone $start; // month is the current end of the period
@@ -194,15 +203,76 @@ class CategoryController extends Controller
$row = [clone $start]; // make a row:
foreach ($categories as $category) { // each budget, fill the row
- $spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
- $row[] = $spent;
+ $spent = $repository->balanceInPeriod($category, $start, $month, $shared);
+ if ($spent < 0) {
+ $row[] = $spent * -1;
+ } else {
+ $row[] = 0;
+ }
}
$entries->push($row);
-
$start->addMonth();
}
+ $data = $this->generator->spentInYear($categories, $entries);
+ $cache->store($data);
- $data = $this->generator->year($categories, $entries);
+ return Response::json($data);
+ }
+
+ /**
+ * This chart will only show income.
+ *
+ * @param CategoryRepositoryInterface $repository
+ * @param $year
+ * @param bool $shared
+ *
+ * @return \Symfony\Component\HttpFoundation\Response
+ */
+ public function earnedInYear(CategoryRepositoryInterface $repository, $year, $shared = false)
+ {
+ $start = new Carbon($year . '-01-01');
+ $end = new Carbon($year . '-12-31');
+
+ $cache = new CacheProperties; // chart properties for cache:
+ $cache->addProperty($start);
+ $cache->addProperty($end);
+ $cache->addProperty('category');
+ $cache->addProperty('earned-in-year');
+ if ($cache->has()) {
+ return Response::json($cache->get()); // @codeCoverageIgnore
+ }
+
+ $shared = $shared == 'shared' ? true : false;
+ $allCategories = $repository->getCategories();
+ $allEntries = new Collection;
+ $categories = $allCategories->filter(
+ function (Category $category) use ($repository, $start, $end, $shared) {
+ $spent = $repository->balanceInPeriod($category, $start, $end, $shared);
+ if ($spent > 0) {
+ return $category;
+ }
+
+ return null;
+ }
+ );
+
+ while ($start < $end) {
+ $month = clone $start; // month is the current end of the period
+ $month->endOfMonth();
+ $row = [clone $start]; // make a row:
+
+ foreach ($categories as $category) { // each budget, fill the row
+ $spent = $repository->balanceInPeriod($category, $start, $month, $shared);
+ if ($spent > 0) {
+ $row[] = $spent;
+ } else {
+ $row[] = 0;
+ }
+ }
+ $allEntries->push($row);
+ $start->addMonth();
+ }
+ $data = $this->generator->earnedInYear($categories, $allEntries);
$cache->store($data);
return Response::json($data);
diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php
index 9b9c5bef5e..5613809750 100644
--- a/app/Http/Controllers/HomeController.php
+++ b/app/Http/Controllers/HomeController.php
@@ -79,18 +79,16 @@ class HomeController extends Controller
return redirect(route('new-user.index'));
}
- $title = 'Firefly';
- $subTitle = trans('firefly.welcomeBack');
- $mainTitleIcon = 'fa-fire';
- $transactions = [];
- $frontPage = Preferences::get('frontPageAccounts', []);
- $start = Session::get('start', Carbon::now()->startOfMonth());
- $end = Session::get('end', Carbon::now()->endOfMonth());
- $showTour = Preferences::get('tour', true)->data;
-
- $accounts = $repository->getFrontpageAccounts($frontPage);
- $savings = $repository->getSavingsAccounts();
-
+ $title = 'Firefly';
+ $subTitle = trans('firefly.welcomeBack');
+ $mainTitleIcon = 'fa-fire';
+ $transactions = [];
+ $frontPage = Preferences::get('frontPageAccounts', []);
+ $start = Session::get('start', Carbon::now()->startOfMonth());
+ $end = Session::get('end', Carbon::now()->endOfMonth());
+ $showTour = Preferences::get('tour', true)->data;
+ $accounts = $repository->getFrontpageAccounts($frontPage);
+ $savings = $repository->getSavingsAccounts();
$piggyBankAccounts = $repository->getPiggyBankAccounts();
diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php
index cf79dd47e1..2c06b6b475 100644
--- a/app/Http/Controllers/TagController.php
+++ b/app/Http/Controllers/TagController.php
@@ -190,7 +190,8 @@ class TagController extends Controller
$tags = Auth::user()->tags()->where('tagMode', $type)->orderBy('date', 'ASC')->get();
$tags = $tags->sortBy(
function (Tag $tag) {
- $date = $tag->date->format('Ymd');
+ $date = !is_null($tag->date) ? $tag->date->format('Ymd') : '000000';
+
return strtolower($date . $tag->tag);
}
diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php
index d88c7f7d3c..b7093dea48 100644
--- a/app/Http/Controllers/TransactionController.php
+++ b/app/Http/Controllers/TransactionController.php
@@ -1,5 +1,6 @@
getAccounts(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = trans('form.noBudget');
- $piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
- $piggies[0] = trans('form.noPiggybank');
- $preFilled = Session::has('preFilled') ? Session::get('preFilled') : [];
- $respondTo = ['account_id', 'account_from_id'];
- $subTitle = trans('form.add_new_' . $what);
+
+ // piggy bank list:
+ $piggyBanks = Auth::user()->piggyBanks()->orderBy('order', 'ASC')->get();
+ /** @var PiggyBank $piggy */
+ foreach ($piggyBanks as $piggy) {
+ $piggy->name = $piggy->name . ' (' . Amount::format($piggy->currentRelevantRep()->currentamount, false) . ')';
+ }
+
+ $piggies = ExpandedForm::makeSelectList($piggyBanks);
+ $piggies[0] = trans('form.noPiggybank');
+ $preFilled = Session::has('preFilled') ? Session::get('preFilled') : [];
+ $respondTo = ['account_id', 'account_from_id'];
+ $subTitle = trans('form.add_new_' . $what);
foreach ($respondTo as $r) {
$preFilled[$r] = Input::get($r);
diff --git a/app/Http/routes.php b/app/Http/routes.php
index 17307916dc..0471e559b9 100644
--- a/app/Http/routes.php
+++ b/app/Http/routes.php
@@ -162,7 +162,7 @@ Route::get('/cron/sendgrid', ['uses' => 'CronController@sendgrid']);
Route::controllers(
[
- 'auth' => 'Auth\AuthController',
+ 'auth' => 'Auth\AuthController',
'password' => 'Auth\PasswordController',
]
);
@@ -282,6 +282,7 @@ Route::group(
*/
// accounts:
Route::get('/chart/account/frontpage', ['uses' => 'Chart\AccountController@frontpage']);
+ Route::get('/chart/account/expense', ['uses' => 'Chart\AccountController@expenseAccounts']);
Route::get('/chart/account/month/{year}/{month}/{shared?}', ['uses' => 'Chart\AccountController@all'])->where(
['year' => '[0-9]{4}', 'month' => '[0-9]{1,2}', 'shared' => 'shared']
);
@@ -300,7 +301,12 @@ Route::group(
// categories:
Route::get('/chart/category/frontpage', ['uses' => 'Chart\CategoryController@frontpage']);
- Route::get('/chart/category/year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
+ Route::get('/chart/category/spent-in-year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@spentInYear'])->where(
+ ['year' => '[0-9]{4}', 'shared' => 'shared']
+ );
+ Route::get('/chart/category/earned-in-year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@earnedInYear'])->where(
+ ['year' => '[0-9]{4}', 'shared' => 'shared']
+ );
Route::get('/chart/category/{category}/month', ['uses' => 'Chart\CategoryController@month']); // should be period.
Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']);
diff --git a/app/Models/Category.php b/app/Models/Category.php
index 7792eba5f0..a1c65c4667 100644
--- a/app/Models/Category.php
+++ b/app/Models/Category.php
@@ -25,7 +25,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Category whereEncrypted($value)
* @property-read float $spent
- * @property-read \Carbon\Carbon $lastActivity
+ * @property \Carbon\Carbon $lastActivity
*/
class Category extends Model
{
diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php
index 45e2d5bb62..6f5643752d 100644
--- a/app/Providers/FireflyServiceProvider.php
+++ b/app/Providers/FireflyServiceProvider.php
@@ -98,7 +98,6 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind('FireflyIII\Helpers\Attachments\AttachmentHelperInterface', 'FireflyIII\Helpers\Attachments\AttachmentHelper');
// make charts:
- // alternative is Google instead of ChartJs
$this->app->bind('FireflyIII\Generator\Chart\Account\AccountChartGenerator', 'FireflyIII\Generator\Chart\Account\ChartJsAccountChartGenerator');
$this->app->bind('FireflyIII\Generator\Chart\Bill\BillChartGenerator', 'FireflyIII\Generator\Chart\Bill\ChartJsBillChartGenerator');
$this->app->bind('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator', 'FireflyIII\Generator\Chart\Budget\ChartJsBudgetChartGenerator');
diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php
index c60864d473..7096306b67 100644
--- a/app/Repositories/Budget/BudgetRepository.php
+++ b/app/Repositories/Budget/BudgetRepository.php
@@ -313,9 +313,9 @@ class BudgetRepository extends ComponentRepository implements BudgetRepositoryIn
*
* @return string
*/
- public function spentInPeriodCorrected(Budget $budget, Carbon $start, Carbon $end, $shared = true)
+ public function balanceInPeriod(Budget $budget, Carbon $start, Carbon $end, $shared = true)
{
- return $this->spentInPeriod($budget, $start, $end, $shared);
+ return $this->commonBalanceInPeriod($budget, $start, $end, $shared);
}
/**
diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php
index 12d3d01b93..6ba34a6e66 100644
--- a/app/Repositories/Budget/BudgetRepositoryInterface.php
+++ b/app/Repositories/Budget/BudgetRepositoryInterface.php
@@ -136,7 +136,7 @@ interface BudgetRepositoryInterface
*
* @return string
*/
- public function spentInPeriodCorrected(Budget $budget, Carbon $start, Carbon $end, $shared = true);
+ public function balanceInPeriod(Budget $budget, Carbon $start, Carbon $end, $shared = true);
/**
* @param array $data
diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php
index 3686fbc581..5e8a4be655 100644
--- a/app/Repositories/Category/CategoryRepository.php
+++ b/app/Repositories/Category/CategoryRepository.php
@@ -57,6 +57,7 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
return $set;
}
+
/**
*
* @param Carbon $start
@@ -64,7 +65,7 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
*
* @return array
*/
- public function getCategoriesAndExpensesCorrected($start, $end)
+ public function getCategoriesAndExpensesCorrected(Carbon $start, Carbon $end)
{
$set = Auth::user()->transactionjournals()
->leftJoin(
@@ -183,9 +184,9 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
*
* @return string
*/
- public function spentInPeriodCorrected(Category $category, Carbon $start, Carbon $end, $shared = false)
+ public function balanceInPeriod(Category $category, Carbon $start, Carbon $end, $shared = false)
{
- return $this->spentInPeriod($category, $start, $end, $shared);
+ return $this->commonBalanceInPeriod($category, $start, $end, $shared);
}
/**
@@ -198,7 +199,7 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
*/
public function spentOnDaySumCorrected(Category $category, Carbon $date)
{
- return $category->transactionjournals()->onDate($date)->get(['transaction_journals.*'])->sum('amount');
+ return $category->transactionjournals()->onDate($date)->get(['transaction_journals.*'])->sum('correct_amount');
}
/**
@@ -233,4 +234,32 @@ class CategoryRepository extends ComponentRepository implements CategoryReposito
return $category;
}
+
+ /**
+ * This method returns the sum of the journals in the category, optionally
+ * limited by a start or end date.
+ *
+ * @param Category $category
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return string
+ */
+ public function journalsSum(Category $category, Carbon $start = null, Carbon $end = null)
+ {
+ $query = $category->transactionJournals()
+ ->orderBy('transaction_journals.date', 'DESC')
+ ->orderBy('transaction_journals.order', 'ASC')
+ ->orderBy('transaction_journals.id', 'DESC');
+ if (!is_null($start)) {
+ $query->after($start);
+ }
+
+ if (!is_null($end)) {
+ $query->before($end);
+ }
+
+ return $query->get(['transaction_journals.*'])->sum('correct_amount');
+
+ }
}
diff --git a/app/Repositories/Category/CategoryRepositoryInterface.php b/app/Repositories/Category/CategoryRepositoryInterface.php
index a24dfb6efe..b7364e518b 100644
--- a/app/Repositories/Category/CategoryRepositoryInterface.php
+++ b/app/Repositories/Category/CategoryRepositoryInterface.php
@@ -40,7 +40,7 @@ interface CategoryRepositoryInterface
*
* @return array
*/
- public function getCategoriesAndExpensesCorrected($start, $end);
+ public function getCategoriesAndExpensesCorrected(Carbon $start, Carbon $end);
/**
* @param Category $category
@@ -57,6 +57,18 @@ interface CategoryRepositoryInterface
*/
public function getJournals(Category $category, $page);
+ /**
+ * This method returns the sum of the journals in the category, optionally
+ * limited by a start or end date.
+ *
+ * @param Category $category
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return string
+ */
+ public function journalsSum(Category $category, Carbon $start = null, Carbon $end = null);
+
/**
* @param Category $category
*
@@ -83,7 +95,7 @@ interface CategoryRepositoryInterface
*
* @return string
*/
- public function spentInPeriodCorrected(Category $category, Carbon $start, Carbon $end, $shared = false);
+ public function balanceInPeriod(Category $category, Carbon $start, Carbon $end, $shared = false);
/**
*
diff --git a/app/Repositories/Shared/ComponentRepository.php b/app/Repositories/Shared/ComponentRepository.php
index c97019880a..584856fa3d 100644
--- a/app/Repositories/Shared/ComponentRepository.php
+++ b/app/Repositories/Shared/ComponentRepository.php
@@ -24,7 +24,7 @@ class ComponentRepository
*
* @return string
*/
- protected function spentInPeriod($object, Carbon $start, Carbon $end, $shared = false)
+ protected function commonBalanceInPeriod($object, Carbon $start, Carbon $end, $shared = false)
{
$cache = new CacheProperties; // we must cache this.
$cache->addProperty($object->id);
@@ -32,7 +32,7 @@ class ComponentRepository
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty($shared);
- $cache->addProperty('spentInPeriod');
+ $cache->addProperty('balanceInPeriod');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
@@ -45,14 +45,14 @@ class ComponentRepository
// do something else, SEE budgets.
// get all journals in this month where the asset account is NOT shared.
$sum = $object->transactionjournals()->before($end)->after($start)
- ->transactionTypes(['Withdrawal'])
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
+ ->transactionTypes(['Withdrawal', 'Deposit', 'Opening balance'])
->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
- )->where('account_meta.data', '!=', '"sharedAsset"')->get(['transaction_journals.*'])->sum('amount');
+ )->where('account_meta.data', '!=', '"sharedAsset"')->get(['transaction_journals.*'])->sum('correct_amount');
}
$cache->store($sum);
diff --git a/composer.lock b/composer.lock
index 3f0c144b82..6b58906c1b 100644
--- a/composer.lock
+++ b/composer.lock
@@ -1488,16 +1488,16 @@
},
{
"name": "league/flysystem",
- "version": "1.0.10",
+ "version": "1.0.11",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem.git",
- "reference": "3475ce0b1b5cab41f012905c4c58ad645088f7c9"
+ "reference": "c16222fdc02467eaa12cb6d6d0e65527741f6040"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/3475ce0b1b5cab41f012905c4c58ad645088f7c9",
- "reference": "3475ce0b1b5cab41f012905c4c58ad645088f7c9",
+ "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/c16222fdc02467eaa12cb6d6d0e65527741f6040",
+ "reference": "c16222fdc02467eaa12cb6d6d0e65527741f6040",
"shasum": ""
},
"require": {
@@ -1565,7 +1565,7 @@
"sftp",
"storage"
],
- "time": "2015-07-21 19:35:53"
+ "time": "2015-07-28 20:41:58"
},
{
"name": "monolog/monolog",
diff --git a/config/firefly.php b/config/firefly.php
index 20d51d6d8f..8cc76952ee 100644
--- a/config/firefly.php
+++ b/config/firefly.php
@@ -2,7 +2,7 @@
return [
'chart' => 'chartjs',
- 'version' => '3.4.10',
+ 'version' => '3.4.11',
'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'],
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'csv_import_enabled' => true,
diff --git a/pu.sh b/pu.sh
deleted file mode 100755
index 5daa2f6f0d..0000000000
--- a/pu.sh
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-
-# set testing environment
-cp .env.testing .env
-
-# test!
-if [ -z "$1" ]
-then
- phpunit --verbose
-fi
-
-# directories to look in:
-dirs=("controllers" "database" "factories" "generators" "helpers" "models" "middleware" "repositories" "support")
-
-if [ ! -z "$1" ]
-then
- for i in "${dirs[@]}"
- do
- firstFile="./tests/$i/$1.php"
- secondFile="./tests/$i/$1Test.php"
- if [ -f "$firstFile" ]
- then
- # run it!
- phpunit --verbose $firstFile
- exit $?
- fi
- if [ -f "$secondFile" ]
- then
- # run it!
- phpunit --verbose $secondFile
- exit $?
- fi
-
-
- done
-
-fi
-
-# restore .env file
-cp .env.local .env
diff --git a/public/css/firefly.css b/public/css/firefly.css
index 147bcec4f0..f60f7b03c6 100644
--- a/public/css/firefly.css
+++ b/public/css/firefly.css
@@ -1,5 +1,5 @@
#daterange {cursor:pointer;}
-.google-chart-error {height:30px;background:url('/images/error.png') no-repeat center center;}
+.general-chart-error {height:30px;background:url('/images/error.png') no-repeat center center;}
.handle {cursor:move;}
.ui-sortable-placeholder {
diff --git a/public/js/charts.js b/public/js/charts.js
index 447186790b..e3c1429ecf 100644
--- a/public/js/charts.js
+++ b/public/js/charts.js
@@ -3,18 +3,6 @@
/*
Make some colours:
*/
-/*
- #555299
- #4285f4
- #
- #
- #
- #
- #
- #
- #
- #", "#", "#", "#"],
- */
var colourSet = [
[53, 124, 165],
[0, 141, 76],
@@ -54,6 +42,7 @@ var defaultAreaOptions = {
datasetStrokeWidth: 1,
pointHitDetectionRadius: 5,
datasetFill: true,
+ animation: false,
scaleFontSize: 10,
responsive: false,
scaleLabel: " <%= '" + currencySymbol + " ' + Number(value).toFixed(0).replace('.', ',') %>",
@@ -68,6 +57,7 @@ var defaultPieOptions = {
datasetStrokeWidth: 1,
pointHitDetectionRadius: 5,
datasetFill: false,
+ animation: false,
scaleFontSize: 10,
responsive: false,
tooltipFillColor: "rgba(0,0,0,0.5)",
@@ -81,6 +71,7 @@ var defaultLineOptions = {
pointDotRadius: 2,
datasetStrokeWidth: 1,
pointHitDetectionRadius: 5,
+ animation: false,
datasetFill: false,
scaleFontSize: 10,
responsive: false,
@@ -98,6 +89,7 @@ var defaultColumnOptions = {
datasetFill: false,
scaleFontSize: 10,
responsive: false,
+ animation: false,
scaleLabel: "<%= '" + currencySymbol + " ' + Number(value).toFixed(0).replace('.', ',') %>",
tooltipFillColor: "rgba(0,0,0,0.5)",
tooltipTemplate: "<%if (label){%><%=label%>: <%}%>" + currencySymbol + " <%= value %>",
@@ -110,6 +102,7 @@ var defaultStackedColumnOptions = {
barStrokeWidth: 1,
pointHitDetectionRadius: 5,
datasetFill: false,
+ animation: false,
scaleFontSize: 10,
responsive: false,
scaleLabel: "<%= '" + currencySymbol + " ' + Number(value).toFixed(0).replace('.', ',') %>",
@@ -147,7 +140,7 @@ function lineChart(URL, container, options) {
new Chart(ctx).Line(newData, options);
}).fail(function () {
- $('#' + container).addClass('google-chart-error');
+ $('#' + container).addClass('general-chart-error');
});
console.log('URL for line chart : ' + URL);
}
@@ -182,7 +175,7 @@ function areaChart(URL, container, options) {
new Chart(ctx).Line(newData, options);
}).fail(function () {
- $('#' + container).addClass('google-chart-error');
+ $('#' + container).addClass('general-chart-error');
});
console.log('URL for area chart: ' + URL);
@@ -218,7 +211,7 @@ function columnChart(URL, container, options) {
new Chart(ctx).Bar(newData, options);
}).fail(function () {
- $('#' + container).addClass('google-chart-error');
+ $('#' + container).addClass('general-chart-error');
});
console.log('URL for column chart : ' + URL);
}
@@ -253,7 +246,7 @@ function stackedColumnChart(URL, container, options) {
new Chart(ctx).StackedBar(newData, options);
}).fail(function () {
- $('#' + container).addClass('google-chart-error');
+ $('#' + container).addClass('general-chart-error');
});
console.log('URL for stacked column chart : ' + URL);
}
@@ -286,7 +279,7 @@ function pieChart(URL, container, options) {
new Chart(ctx).Pie(data, options);
}).fail(function () {
- $('#' + container).addClass('google-chart-error');
+ $('#' + container).addClass('general-chart-error');
});
diff --git a/public/js/gcharts.js b/public/js/gcharts.js
deleted file mode 100644
index 64c1431dba..0000000000
--- a/public/js/gcharts.js
+++ /dev/null
@@ -1,319 +0,0 @@
-/* globals currencyCode, language */
-/* exported lineChart, googleColumnChart, stackedColumnChart, comboChart, pieChart, defaultLineChartOptions, defaultAreaChartOptions, defaultBarChartOptions, defaultComboChartOptions, defaultColumnChartOptions, defaultStackedColumnChartOptions, defaultPieChartOptions */
-var google = google || {};
-google.load('visualization', '1.1', {'packages': ['corechart', 'bar', 'line'], 'language': language});
-
-
-/* exported */
-
-var defaultLineChartOptions = {
- curveType: 'function',
- legend: {
- position: 'none'
- },
- interpolateNulls: true,
- lineWidth: 1,
- chartArea: {
- left: 50,
- top: 10,
- width: '95%',
- height: '90%'
- },
- height: 400,
- colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
- hAxis: {
- textStyle: {
- color: '#838383',
- },
- baselineColor: '#aaaaaa',
- gridlines: {
- color: 'transparent'
- }
- },
- fontSize: 11,
- vAxis: {
- textStyle: {
- color: '#838383',
- },
- baselineColor: '#aaaaaa',
- format: '\u20AC #'
- }
-
-
-};
-
-var defaultAreaChartOptions = {
- curveType: 'function',
- legend: {
- position: 'none'
- },
- interpolateNulls: true,
- lineWidth: 1,
- chartArea: {
- left: 50,
- top: 10,
- width: '95%',
- height: '90%'
- },
- height: 400,
- colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
- hAxis: {
- textStyle: {
- color: '#838383',
- },
- baselineColor: '#aaaaaa',
- gridlines: {
- color: 'transparent'
- }
- },
- fontSize: 11,
- vAxis: {
- textStyle: {
- color: '#838383',
- },
- baselineColor: '#aaaaaa',
- format: '\u20AC #'
- }
-
-
-};
-
-var defaultBarChartOptions = {
- height: 400,
- bars: 'horizontal',
- hAxis: {
- textStyle: {
- color: '#838383',
- },
- baselineColor: '#aaaaaa',
- format: '\u20AC #'
-
- },
- fontSize: 11,
- colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
- vAxis: {
- textStyle: {
- color: '#838383'
- },
- textPosition: 'in',
- gridlines: {
-
- color: 'transparent'
- },
- baselineColor: '#aaaaaa'
- },
- chartArea: {
- left: 15,
- top: 10,
- width: '100%',
- height: '90%'
- },
-
- legend: {
- position: 'none'
- }
-};
-
-var defaultComboChartOptions = {
- height: 300,
- chartArea: {
- left: 75,
- top: 10,
- width: '100%',
- height: '90%'
- },
- vAxis: {
- minValue: 0,
- format: '\u20AC #'
- },
- colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
- fontSize: 11,
- legend: {
- position: 'none'
- },
- series: {
- 0: {type: 'line'},
- 1: {type: 'line'},
- 2: {type: 'bars'}
- },
- bar: {groupWidth: 20}
-};
-
-var defaultColumnChartOptions = {
- height: 400,
- chartArea: {
- left: 50,
- top: 10,
- width: '85%',
- height: '80%'
- },
- fontSize: 11,
- hAxis: {
- textStyle: {
- color: '#838383'
- },
- gridlines: {
- color: 'transparent'
- },
- baselineColor: '#aaaaaa'
-
- },
- colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
- vAxis: {
- textStyle: {
- color: '#838383'
- },
- baselineColor: '#aaaaaa',
- format: '\u20AC #'
- },
- legend: {
- position: 'none'
- }
-};
-
-var defaultStackedColumnChartOptions = {
- height: 400,
- chartArea: {
- left: 50,
- top: 10,
- width: '85%',
- height: '80%'
- },
- legend: {
- position: 'none'
- },
- fontSize: 11,
- isStacked: true,
- colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
- hAxis: {
- textStyle: {
- color: '#838383',
- },
- gridlines: {
- color: 'transparent'
- }
- },
- vAxis: {
- textStyle: {
- color: '#838383',
- },
- format: '\u20AC #'
- }
-};
-
-var defaultPieChartOptions = {
- chartArea: {
- left: 0,
- top: 0,
- width: '100%',
- height: '100%'
- },
- fontSize: 11,
- height: 200,
- legend: {
- position: 'none'
- },
- colors: ["#357ca5", "#008d4c", "#db8b0b", "#ca195a", "#555299", "#4285f4", "#db4437", "#f4b400", "#0f9d58", "#ab47bc", "#00acc1", "#ff7043", "#9e9d24", "#5c6bc0", "#f06292", "#00796b", "#c2185b"],
-};
-
-
-function googleChart(chartType, URL, container, options) {
- "use strict";
- if ($('#' + container).length === 1) {
- $.getJSON(URL).success(function (data) {
- /*
- Get the data from the JSON
- */
- var gdata = new google.visualization.DataTable(data);
-
- /*
- Format as money
- */
- var money = new google.visualization.NumberFormat({
- decimalSymbol: ',',
- groupingSymbol: '.',
- prefix: currencyCode + ' '
- });
- for (var i = 1; i < gdata.getNumberOfColumns(); i++) {
- money.format(gdata, i);
- }
-
- /*
- Create a new google charts object.
- */
- var chart = false;
- var options = false;
- if (chartType === 'line') {
- chart = new google.visualization.LineChart(document.getElementById(container));
- options = options || defaultLineChartOptions;
- }
- if (chartType === 'area') {
- chart = new google.visualization.AreaChart(document.getElementById(container));
- options = options || defaultAreaChartOptions;
- }
-
- if (chartType === 'column') {
- chart = new google.visualization.ColumnChart(document.getElementById(container));
- options = options || defaultColumnChartOptions;
- }
- if (chartType === 'pie') {
- chart = new google.visualization.PieChart(document.getElementById(container));
- options = options || defaultPieChartOptions;
- }
- if (chartType === 'bar') {
- chart = new google.visualization.BarChart(document.getElementById(container));
- options = options || defaultBarChartOptions;
- }
- if (chartType === 'stackedColumn') {
- chart = new google.visualization.ColumnChart(document.getElementById(container));
- options = options || defaultStackedColumnChartOptions;
- }
- if (chartType === 'combo') {
- chart = new google.visualization.ComboChart(document.getElementById(container));
- options = options || defaultComboChartOptions;
- }
-
- if (chart === false) {
- alert('Cannot draw chart of type "' + chartType + '".');
- } else {
- chart.draw(gdata, options);
- }
-
- }).fail(function () {
- $('#' + container).addClass('google-chart-error');
- });
- } else {
- console.log('No container found called "' + container + '"');
- }
-}
-
-
-function lineChart(URL, container, options) {
- "use strict";
- return googleChart('line', URL, container, options);
-}
-
-function areaChart(URL, container, options) {
- "use strict";
- return googleChart('area', URL, container, options);
-}
-
-function columnChart(URL, container, options) {
- "use strict";
- return googleChart('column', URL, container, options);
-}
-
-function stackedColumnChart(URL, container, options) {
- "use strict";
- return googleChart('stackedColumn', URL, container, options);
-}
-
-function comboChart(URL, container, options) {
- "use strict";
- return googleChart('combo', URL, container, options);
-}
-
-function pieChart(URL, container, options) {
- "use strict";
- return googleChart('pie', URL, container, options);
-}
diff --git a/public/js/index.js b/public/js/index.js
index a7542a40ca..597233fb72 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -2,13 +2,8 @@
$(function () {
"use strict";
- if (typeof google !== 'undefined') {
- // do google charts:
- google.setOnLoadCallback(drawChart);
- } else {
- // do chart JS stuff.
- drawChart();
- }
+ // do chart JS stuff.
+ drawChart();
if (showTour) {
$.getJSON('json/tour').success(function (data) {
var tour = new Tour(
@@ -41,6 +36,7 @@ function drawChart() {
pieChart('chart/bill/frontpage', 'bills-chart');
stackedColumnChart('chart/budget/frontpage', 'budgets-chart');
columnChart('chart/category/frontpage', 'categories-chart');
+ columnChart('chart/account/expense', 'expense-accounts-chart');
getBoxAmounts();
diff --git a/public/js/reports.js b/public/js/reports.js
index 0c63642830..b123497481 100644
--- a/public/js/reports.js
+++ b/public/js/reports.js
@@ -2,11 +2,7 @@
$(function () {
"use strict";
- if (typeof(google) !== 'undefined') {
- google.setOnLoadCallback(drawChart);
- } else {
- drawChart();
- }
+ drawChart();
});
@@ -18,7 +14,8 @@ function drawChart() {
}
if (typeof stackedColumnChart !== 'undefined' && typeof year !== 'undefined' && typeof month === 'undefined') {
stackedColumnChart('chart/budget/year/' + year + shared, 'budgets');
- stackedColumnChart('chart/category/year/' + year + shared, 'categories');
+ stackedColumnChart('chart/category/spent-in-year/' + year + shared, 'categories-spent-in-year');
+ stackedColumnChart('chart/category/earned-in-year/' + year + shared, 'categories-earned-in-year');
}
if (typeof lineChart !== 'undefined' && typeof month !== 'undefined') {
lineChart('/chart/account/month/' + year + '/' + month + shared, 'account-balances-chart');
diff --git a/resources/lang/en/firefly.php b/resources/lang/en/firefly.php
index 26a67e6de9..456e0ef9a1 100644
--- a/resources/lang/en/firefly.php
+++ b/resources/lang/en/firefly.php
@@ -15,6 +15,8 @@ return [
'cancel' => 'Cancel',
'from' => 'From',
'to' => 'To',
+ 'total_sum' => 'Total sum',
+ 'period_sum' => 'Sum for period',
'showEverything' => 'Show everything',
'never' => 'Never',
'search_results_for' => 'Search results for ":query"',
@@ -117,16 +119,16 @@ return [
'onto existing data in Firefly, use the checkbox. The next step will show you what this button does.',
'csv_column_roles_table' => 'Column roles',
'csv_column' => 'CSV column',
- 'cvs_column_name' => 'CSV column name',
- 'cvs_column_example' => 'Column example data',
- 'cvs_column_role' => 'Column contains?',
+ 'csv_column_name' => 'CSV column name',
+ 'csv_column_example' => 'Column example data',
+ 'csv_column_role' => 'Column contains?',
'csv_do_map_value' => 'Map value?',
'csv_continue' => 'Continue to the next step',
'csv_go_back' => 'Go back to the previous step',
'csv_map_title' => 'Map found values to existing values',
'csv_map_text' => 'This page allows you to map the values from the CSV file to existing entries in your ' .
'database. This ensures that accounts and other things won\'t be created twice.',
- 'cvs_field_value' => 'Field value from CSV',
+ 'csv_field_value' => 'Field value from CSV',
'csv_field_mapped_to' => 'Must be mapped to...',
'csv_do_not_map' => 'Do not map this value',
'csv_download_config_title' => 'Download CSV configuration',
@@ -140,8 +142,8 @@ return [
'csv_unsupported_map' => 'The importer cannot map the column ":columnRole" to existing values in the database.',
'csv_unsupported_value' => 'The importer does not know how to handle values in columns marked as ":columnRole".',
'csv_cannot_store_value' => 'The importer has not reserved space for columns marked ":columnRole" and will be incapable of processing them.',
- 'csv_process_title' => 'CVS import finished!',
- 'csv_process_text' => 'The CVS importer has finished and has processed :rows rows',
+ 'csv_process_title' => 'CSV import finished!',
+ 'csv_process_text' => 'The CSV importer has finished and has processed :rows rows',
'csv_row' => 'Row',
'csv_import_with_errors' => 'There was one error.|There were :errors errors.',
'csv_error_see_logs' => 'Check the log files to see details.',
@@ -180,6 +182,7 @@ return [
'csv_specifix_Dummy' => 'Checking this has no effect whatsoever.',
'csv_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which'
. ' account the transactions in the CSV belong to.',
+ 'csv_date_parse_error' => 'Could not parse a valid date from ":value", using the format ":format". Are you sure your CSV is correct?',
// create new stuff:
@@ -396,12 +399,15 @@ return [
'hideTheRest' => 'Show only the top :number',
'sum_of_year' => 'Sum of year',
'average_of_year' => 'Average of year',
+ 'categories_earned_in_year' => 'Categories (by earnings)',
+ 'categories_spent_in_year' => 'Categories (by spendings)',
// charts:
'dayOfMonth' => 'Day of the month',
'month' => 'Month',
'budget' => 'Budget',
'spent' => 'Spent',
+ 'earned' => 'Earned',
'overspent' => 'Overspent',
'left' => 'Left',
'noBudget' => '(no budget)',
diff --git a/resources/lang/nl/firefly.php b/resources/lang/nl/firefly.php
index 82f115da14..1a1836f8da 100644
--- a/resources/lang/nl/firefly.php
+++ b/resources/lang/nl/firefly.php
@@ -15,6 +15,8 @@ return [
'cancel' => 'Annuleren',
'from' => 'Van',
'to' => 'Tot',
+ 'total_sum' => 'Totale som',
+ 'period_sum' => 'Som van periode',
'showEverything' => 'Laat alles zien',
'never' => 'Nooit',
'search_results_for' => 'Zoekresultaten voor ":query"',
@@ -116,24 +118,24 @@ return [
. ' die al in Firefly staan, gebruik dan het vinkje. Tijdens de volgende stap komt Firefly hier dan op terug.',
'csv_column_roles_table' => 'Kolominhoud',
'csv_column' => 'CSV-kolom',
- 'cvs_column_name' => 'CSV-kolomnaam',
- 'cvs_column_example' => 'Voorbeeldgegevens',
- 'cvs_column_role' => 'Kolom bevat?',
+ 'csv_column_name' => 'CSV-kolomnaam',
+ 'csv_column_example' => 'Voorbeeldgegevens',
+ 'csv_column_role' => 'Kolom bevat?',
'csv_do_map_value' => 'Directe relatie?',
'csv_continue' => 'Naar de volgende stap',
'csv_go_back' => 'Terug naar de vorige stap',
'csv_map_title' => 'Leg relaties met kolomwaardes',
'csv_map_text' => 'Sommige kolommen bevatten waardes die misschien al in Firefly bestaan. Selecteer hier de juiste combinaties'
. 'zodat het importeren netjes aansluit bij je huidige gegevens.',
- 'cvs_field_value' => 'Veldwaarde',
+ 'csv_field_value' => 'Veldwaarde',
'csv_field_mapped_to' => 'Is gelijk aan',
'csv_do_not_map' => 'Geen relatie',
'csv_download_config_title' => 'Download importconfiguratie',
- 'csv_download_config_text' => 'Firefly is klaar om je bestand te importeren. De instellingen en selecties die je zojuist hebt gemaakt kan je downloaden'
- . ' en opslaan. Bij de volgende keer kan je dit bestand ook uploaden. Als je kommagescheiden bestand dezelfde indeling'
- . ' heeft, zullen alle selecties goed staan. Dat scheelt weer!',
- 'csv_more_information_text' => 'Ook als het importeren fout gaat is dit bestand handig. Na het importeren krijg je nogmaals de gelegenheid dit bestand'
- . 'te downloaden.',
+ 'csv_download_config_text' => 'Firefly is klaar om je bestand te importeren. De instellingen en selecties die je zojuist hebt gemaakt' .
+ ' kan je downloaden en opslaan. Bij de volgende keer kan je dit bestand ook uploaden. Als je' .
+ ' kommagescheiden bestand dezelfde indeling heeft, zullen alle selecties goed staan. Dat scheelt weer!',
+ 'csv_more_information_text' => 'Ook als het importeren fout gaat is dit bestand handig. Na het importeren krijg je nogmaals' .
+ ' de gelegenheid dit bestand te downloaden.',
'csv_do_download_config' => 'Download het configuratiebestand',
'csv_empty_description' => '(geen beschrijving)',
'csv_upload_form' => 'CSV upload formulier',
@@ -181,6 +183,8 @@ return [
'csv_specifix_RabobankDescription' => 'Vink dit aan als je Rabobank bestanden importeert.',
'csv_specifix_Dummy' => 'Dit vinkje doet niks (dummy).',
'csv_import_account_help' => 'Als jouw CSV bestand geen referenties bevat naar jouw rekening(en), geef dan hier aan om welke rekening het gaat.',
+ 'csv_date_parse_error' => 'Kan geen chocola maken van ":value" (met hulp van configuratie ":format").' .
+ ' Weet je zeker dat je CSV bestand geen fouten bevat?',
// create new stuff:
'create_new_withdrawal' => 'Nieuwe uitgave',
@@ -376,8 +380,8 @@ return [
// reports:
'reportForYear' => 'Jaaroverzicht :year',
'reportForYearShared' => 'Jaaroverzicht :year (inclusief gedeelde rekeningen)',
- 'reportForMonth' => 'Maandoverzicht van :date',
- 'reportForMonthShared' => 'Maandoverzicht van :date (inclusief gedeelde rekeningen)',
+ 'reportForMonth' => 'Maandoverzicht voor :month',
+ 'reportForMonthShared' => 'Maandoverzicht voor :month (inclusief gedeelde rekeningen)',
'incomeVsExpenses' => 'Inkomsten tegenover uitgaven',
'accountBalances' => 'Rekeningsaldi',
'balanceStartOfYear' => 'Saldo aan het begin van het jaar',
@@ -404,12 +408,15 @@ return [
'topX' => 'top :number',
'showTheRest' => 'Laat alles zien',
'hideTheRest' => 'Laat alleen de top :number zien',
+ 'categories_earned_in_year' => 'Categorieën (inkomsten)',
+ 'categories_spent_in_year' => 'Categorieën (uitgaven)',
// charts:
'dayOfMonth' => 'Dag vd maand',
'month' => 'Maand',
'budget' => 'Budget',
'spent' => 'Uitgegeven',
+ 'earned' => 'Verdiend',
'overspent' => 'Teveel uitgegeven',
'left' => 'Over',
'noBudget' => '(geen budget)',
diff --git a/resources/twig/categories/show.twig b/resources/twig/categories/show.twig
index 771c5d56b8..38e95fee51 100644
--- a/resources/twig/categories/show.twig
+++ b/resources/twig/categories/show.twig
@@ -45,7 +45,7 @@
{{ 'transactions'|_ }}
- {% include 'list/journals' %}
+ {% include 'list/journals' with {showPageSum: true, showTotalSum: true, showPeriodSum: true} %}
diff --git a/resources/twig/csv/column-roles.twig b/resources/twig/csv/column-roles.twig
index 3f186e89ff..b8a46bd96b 100644
--- a/resources/twig/csv/column-roles.twig
+++ b/resources/twig/csv/column-roles.twig
@@ -45,9 +45,9 @@
- | {{ 'cvs_column_name'|_ }} |
- {{ 'cvs_column_example'|_ }} |
- {{ 'cvs_column_role'|_ }} |
+ {{ 'csv_column_name'|_ }} |
+ {{ 'csv_column_example'|_ }} |
+ {{ 'csv_column_role'|_ }} |
{{ 'csv_do_map_value'|_ }} |
{% for index,header in headers %}
diff --git a/resources/twig/csv/map.twig b/resources/twig/csv/map.twig
index ccd26c0e50..b5e321df14 100644
--- a/resources/twig/csv/map.twig
+++ b/resources/twig/csv/map.twig
@@ -48,7 +48,7 @@
- | {{ 'cvs_field_value'|_ }} |
+ {{ 'csv_field_value'|_ }} |
{{ 'csv_field_mapped_to'|_ }} |
diff --git a/resources/twig/index.twig b/resources/twig/index.twig
index c0808e413f..b37d7ff2b0 100644
--- a/resources/twig/index.twig
+++ b/resources/twig/index.twig
@@ -67,7 +67,87 @@
{% endif %}
+
+
+
+
+
+
+ {% if Config.get('firefly.chart') == 'google' %}
+
+ {% endif %}
+ {% if Config.get('firefly.chart') == 'chartjs' %}
+
+ {% endif %}
+
+
+
+
+ {% for data in transactions %}
+
+
+
+ {% include 'list/journals-tiny.twig' with {'transactions': data[0],'account': data[1]} %}
+
+
+
+ {% endfor %}
+
+
+
+
+
+
+
+
+ {% if Config.get('firefly.chart') == 'google' %}
+
+ {% endif %}
+ {% if Config.get('firefly.chart') == 'chartjs' %}
+
+ {% endif %}
+
+
+
+
+
+
+
-
-
-
-
-
-
- {% if Config.get('firefly.chart') == 'google' %}
-
- {% endif %}
- {% if Config.get('firefly.chart') == 'chartjs' %}
-
- {% endif %}
-
-
-
-
- {% for data in transactions %}
-
-
-
- {% include 'list/journals-tiny.twig' with {'transactions': data[0],'account': data[1]} %}
-
-
-
- {% endfor %}
diff --git a/resources/twig/list/journals.twig b/resources/twig/list/journals.twig
index f517ecec8c..aa739484bb 100644
--- a/resources/twig/list/journals.twig
+++ b/resources/twig/list/journals.twig
@@ -1,6 +1,7 @@
{{ journals.render|raw }}
-
+
+
| |
{{ trans('list.description') }} |
@@ -23,6 +24,9 @@
|
{% endif %}
+
+
+ {% set _sum = 0 %}
{% for journal in journals %}
{% if invalidJournal(journal) %}
@@ -36,6 +40,7 @@
| Invalid journal: Found {{ journal.transactions|length }} transaction(s) |
{% else %}
+ {% set _sum = _sum + journal.correct_amount %}
|
@@ -111,8 +116,28 @@
{% endif %}
|
{% endif %}
-
{% endfor %}
+
+
+ {% if showPageSum %}
+
+ | {{ 'sum'|_ }} |
+ {{ _sum|formatAmount }} |
+
+ {% endif %}
+ {% if showPeriodSum %}
+
+ | {{ 'period_sum'|_ }} |
+ {{ periodSum|formatAmount }} |
+
+ {% endif %}
+ {% if showTotalSum %}
+
+ | {{ 'total_sum'|_ }} |
+ {{ totalSum|formatAmount }} |
+
+ {% endif %}
+
{{ journals.render|raw }}
diff --git a/resources/twig/partials/reports/categories.twig b/resources/twig/partials/reports/categories.twig
index 66b7491081..88aee1a0b9 100644
--- a/resources/twig/partials/reports/categories.twig
+++ b/resources/twig/partials/reports/categories.twig
@@ -16,14 +16,14 @@
{{ cat.name }}
|
- {{ (cat.spent)|formatAmountPlain }} |
+ {{ (cat.spent * -1)|formatAmountPlain }} |
{% endfor %}
| {{ 'sum'|_ }} |
- {{ categories.getTotal|formatAmountPlain }} |
+ {{ (categories.getTotal * -1)|formatAmountPlain }} |
diff --git a/resources/twig/reports/year.twig b/resources/twig/reports/year.twig
index 28f8371b6b..0d543bc54a 100644
--- a/resources/twig/reports/year.twig
+++ b/resources/twig/reports/year.twig
@@ -56,19 +56,38 @@
{% if Config.get('firefly.chart') == 'google' %}
-
+
{% endif %}
{% if Config.get('firefly.chart') == 'chartjs' %}
-
+
{% endif %}
+
+
+
+
+
+
+ {% if Config.get('firefly.chart') == 'google' %}
+
+ {% endif %}
+ {% if Config.get('firefly.chart') == 'chartjs' %}
+
+ {% endif %}
+
+
+
+
+