Merge branch 'release/3.4.6'

This commit is contained in:
James Cole 2015-06-29 09:53:25 +02:00
commit f15932b2ac
223 changed files with 7174 additions and 4483 deletions

View File

@ -1,4 +1,4 @@
# Firefly III (v3.4.5) # Firefly III (v3.4.6)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
[![Code Coverage](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master) [![Code Coverage](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
@ -82,11 +82,25 @@ and the **[first use guide](https://github.com/JC5/firefly-iii/wiki/First-use)**
If you want to try out Firefly III, you can do so on [this dedicated website](https://geld.nder.be/). If you want to try out Firefly III, you can do so on [this dedicated website](https://geld.nder.be/).
This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site. This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site.
## Credits
Firefly III uses the following libraries and tools:
* The AdminLTE template by [Almsaseed Studio](https://almsaeedstudio.com/)
* The [Google charts](https://developers.google.com/chart/) library.
* [Bootstrap](http://getbootstrap.com/)
* [Laravel](http://laravel.com/)
* [Twig](http://twig.sensiolabs.org/)
* For development, some of the excellent tools made by [Barry van den Heuvel](https://github.com/barryvdh)
* [Bootstrap sortable](https://github.com/drvic10k/bootstrap-sortable) by [Matúš Brliť](https://github.com/drvic10k).
* [Date range picker](https://github.com/dangrossman/bootstrap-daterangepicker/) by [Dan Grossman](https://github.com/dangrossman)
* The [real favicon generator](http://realfavicongenerator.net/)
* Various other open source components (see [composer.json](https://github.com/JC5/firefly-iii/blob/master/composer.json))
## Current state ## Current state
Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. One of the things on the todo-list Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. Translations are a work in progress.
is adding translations.
Questions, ideas, bugs or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)! Questions, ideas, bugs or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)!

View File

@ -0,0 +1,43 @@
<?php
namespace FireflyIII\Generator\Chart\Account;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use Illuminate\Support\Collection;
/**
* Interface AccountChartGenerator
*
* @package FireflyIII\Generator\Chart\Account
*/
interface AccountChartGenerator
{
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function all(Collection $accounts, Carbon $start, Carbon $end);
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function frontpage(Collection $accounts, Carbon $start, Carbon $end);
/**
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function single(Account $account, Carbon $start, Carbon $end);
}

View File

@ -0,0 +1,114 @@
<?php
namespace FireflyIII\Generator\Chart\Account;
use Carbon\Carbon;
use Config;
use FireflyIII\Models\Account;
use Illuminate\Support\Collection;
use Preferences;
use Steam;
/**
* Class ChartJsAccountChartGenerator
*
* @package FireflyIII\Generator\Chart\Account
*/
class ChartJsAccountChartGenerator implements AccountChartGenerator
{
/**
* @codeCoverageIgnore
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function all(Collection $accounts, Carbon $start, Carbon $end)
{
return $this->frontpage($accounts, $start, $end);
}
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function frontpage(Collection $accounts, Carbon $start, Carbon $end)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.monthAndDay.' . $language);
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
$current = clone $start;
while ($current <= $end) {
$data['labels'][] = $current->formatLocalized($format);
$current->addDay();
}
foreach ($accounts as $account) {
$set = [
'label' => $account->name,
'fillColor' => 'rgba(220,220,220,0.2)',
'strokeColor' => 'rgba(220,220,220,1)',
'pointColor' => 'rgba(220,220,220,1)',
'pointStrokeColor' => '#fff',
'pointHighlightFill' => '#fff',
'pointHighlightStroke' => 'rgba(220,220,220,1)',
'data' => [],
];
$current = clone $start;
while ($current <= $end) {
$set['data'][] = Steam::balance($account, $current);
$current->addDay();
}
$data['datasets'][] = $set;
}
$data['count'] = count($data['datasets']);
return $data;
}
/**
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function single(Account $account, Carbon $start, Carbon $end)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.monthAndDay.' . $language);
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => $account->name,
'data' => []
]
],
];
$current = clone $start;
while ($end >= $current) {
$data['labels'][] = $current->formatLocalized($format);
$data['datasets'][0]['data'][] = Steam::balance($account, $current);
$current->addDay();
}
return $data;
}
}

View File

@ -0,0 +1,122 @@
<?php
namespace FireflyIII\Generator\Chart\Account;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Steam;
/**
* Class GoogleAccountChartGenerator
*
* @package FireflyIII\Generator\Chart\Account
*/
class GoogleAccountChartGenerator implements AccountChartGenerator
{
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
public function all(Collection $accounts, Carbon $start, Carbon $end)
{
// make chart (original code):
$chart = new GChart;
$chart->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)
{
$chart = new GChart;
$chart->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 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();
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace FireflyIII\Generator\Chart\Bill;
use FireflyIII\Models\Bill;
use Illuminate\Support\Collection;
/**
* Interface BillChartGenerator
*
* @package FireflyIII\Generator\Chart\Bill
*/
interface BillChartGenerator
{
/**
* @param Collection $paid
* @param Collection $unpaid
*
* @return array
*/
public function frontpage(Collection $paid, Collection $unpaid);
/**
* @param Bill $bill
* @param Collection $entries
*
* @return array
*/
public function single(Bill $bill, Collection $entries);
}

View File

@ -0,0 +1,125 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 27/06/15
* Time: 17:21
*/
namespace FireflyIII\Generator\Chart\Bill;
use Config;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
use Preferences;
/**
* Class ChartJsBillChartGenerator
*
* @package FireflyIII\Generator\Chart\Bill
*/
class ChartJsBillChartGenerator implements BillChartGenerator
{
/**
* @param Collection $paid
* @param Collection $unpaid
*
* @return array
*/
public function frontpage(Collection $paid, Collection $unpaid)
{
// loop paid and create single entry:
$paidDescriptions = [];
$paidAmount = 0;
$unpaidDescriptions = [];
$unpaidAmount = 0;
/** @var TransactionJournal $entry */
foreach ($paid as $entry) {
$paidDescriptions[] = $entry->description;
$paidAmount += floatval($entry->amount);
}
// loop unpaid:
/** @var Bill $entry */
foreach ($unpaid as $entry) {
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
$unpaidDescriptions[] = $description;
$unpaidAmount += $amount;
unset($amount, $description);
}
$data = [
[
'value' => $unpaidAmount,
'color' => 'rgba(53, 124, 165,0.7)',
'highlight' => 'rgba(53, 124, 165,0.9)',
'label' => trans('firefly.unpaid'),
],
[
'value' => $paidAmount,
'color' => 'rgba(0, 141, 76, 0.7)',
'highlight' => 'rgba(0, 141, 76, 0.9)',
'label' => trans('firefly.paid'),
]
];
return $data;
}
/**
* @param Bill $bill
* @param Collection $entries
*
* @return array
*/
public function single(Bill $bill, Collection $entries)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.month.' . $language);
$data = [
'count' => 3,
'labels' => [],
'datasets' => [],
];
// dataset: max amount
// dataset: min amount
// dataset: actual amount
$minAmount = [];
$maxAmount = [];
$actualAmount = [];
foreach ($entries as $entry) {
$data['labels'][] = $entry->date->formatLocalized($format);
$minAmount[] = round($bill->amount_min, 2);
$maxAmount[] = round($bill->amount_max, 2);
$actualAmount[] = round($entry->amount, 2);
}
$data['datasets'][] = [
'label' => trans('firefly.minAmount'),
'data' => $minAmount,
];
$data['datasets'][] = [
'label' => trans('firefly.billEntry'),
'data' => $actualAmount,
];
$data['datasets'][] = [
'label' => trans('firefly.maxAmount'),
'data' => $maxAmount,
];
$data['count'] = count($data['datasets']);
return $data;
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace FireflyIII\Generator\Chart\Bill;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
/**
* Class GoogleBillChartGenerator
*
* @package FireflyIII\Generator\Chart\Bill
*/
class GoogleBillChartGenerator implements BillChartGenerator
{
/**
* @param Collection $paid
* @param Collection $unpaid
*
* @return array
*/
public function frontpage(Collection $paid, Collection $unpaid)
{
// loop paid and create single entry:
$paidDescriptions = [];
$paidAmount = 0;
$unpaidDescriptions = [];
$unpaidAmount = 0;
/** @var TransactionJournal $entry */
foreach ($paid as $entry) {
$paidDescriptions[] = $entry->description;
$paidAmount += floatval($entry->amount);
}
// loop unpaid:
/** @var Bill $entry */
foreach ($unpaid as $entry) {
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
$unpaidDescriptions[] = $description;
$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, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
}
$chart->generate();
return $chart->getData();
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace FireflyIII\Generator\Chart\Budget;
use Illuminate\Support\Collection;
/**
* Interface BudgetChartGenerator
*
* @package FireflyIII\Generator\Chart\Budget
*/
interface BudgetChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function budget(Collection $entries);
/**
* @param Collection $entries
*
* @return array
*/
public function budgetLimit(Collection $entries);
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries);
/**
* @param Collection $budgets
* @param Collection $entries
*
* @return array
*/
public function year(Collection $budgets, Collection $entries);
}

View File

@ -0,0 +1,139 @@
<?php
namespace FireflyIII\Generator\Chart\Budget;
use Config;
use Illuminate\Support\Collection;
use Preferences;
/**
* Class ChartJsBudgetChartGenerator
*
* @package FireflyIII\Generator\Chart\Budget
*/
class ChartJsBudgetChartGenerator implements BudgetChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function budget(Collection $entries)
{
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => 'Amount',
'data' => [],
]
],
];
/** @var array $entry */
foreach ($entries as $entry) {
$data['labels'][] = trans('firefly.spent');
$data['datasets'][0]['data'][] = $entry[1];
}
return $data;
}
/**
* @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)
{
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
// dataset: left
// dataset: spent
// dataset: overspent
$left = [];
$spent = [];
$overspent = [];
foreach ($entries as $entry) {
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
$data['labels'][] = $entry[0];
$left[] = round($entry[1], 2);
$spent[] = round($entry[2], 2);
$overspent[] = round($entry[3], 2);
}
}
$data['datasets'][] = [
'label' => trans('firefly.left'),
'data' => $left,
];
$data['datasets'][] = [
'label' => trans('firefly.spent'),
'data' => $spent,
];
$data['datasets'][] = [
'label' => trans('firefly.overspent'),
'data' => $overspent,
];
$data['count'] = count($data['datasets']);
return $data;
}
/**
* @param Collection $budgets
* @param Collection $entries
*
* @return array
*/
public function year(Collection $budgets, Collection $entries)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.month.' . $language);
$data = [
'count' => 0,
'labels' => [],
'datasets' => [],
];
foreach ($budgets as $budget) {
$data['labels'][] = $budget->name;
}
/** @var array $entry */
foreach ($entries as $entry) {
$array = [
'label' => $entry[0]->formatLocalized($format),
'data' => [],
];
array_shift($entry);
$array['data'] = $entry;
$data['datasets'][] = $array;
}
$data['count'] = count($data['datasets']);
return $data;
}
}

View File

@ -0,0 +1,101 @@
<?php
namespace FireflyIII\Generator\Chart\Budget;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
/**
* Class GoogleBudgetChartGenerator
*
* @package FireflyIII\Generator\Chart\Budget
*/
class GoogleBudgetChartGenerator implements BudgetChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function budget(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();
}
/**
* @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();
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace FireflyIII\Generator\Chart\Category;
use Illuminate\Support\Collection;
/**
* Interface CategoryChartGenerator
*
* @package FireflyIII\Generator\Chart\Category
*/
interface CategoryChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function all(Collection $entries);
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries);
/**
* @param Collection $entries
*
* @return array
*/
public function month(Collection $entries);
/**
* @param Collection $categories
* @param Collection $entries
*
* @return array
*/
public function year(Collection $categories, Collection $entries);
}

View File

@ -0,0 +1,116 @@
<?php
namespace FireflyIII\Generator\Chart\Category;
use Config;
use Illuminate\Support\Collection;
use Preferences;
/**
* Class ChartJsCategoryChartGenerator
*
* @package FireflyIII\Generator\Chart\Category
*/
class ChartJsCategoryChartGenerator implements CategoryChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function all(Collection $entries)
{
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.spent'),
'data' => []
]
],
];
foreach ($entries as $entry) {
$data['labels'][] = trans('firefly.spent');
$data['datasets'][0]['data'][] = round($entry[1], 2);
}
return $data;
}
/**
* @param Collection $entries
*
* @return array
*/
public function frontpage(Collection $entries)
{
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.spent'),
'data' => []
]
],
];
foreach ($entries as $entry) {
if ($entry['sum'] != 0) {
$data['labels'][] = $entry['name'];
$data['datasets'][0]['data'][] = round($entry['sum'], 2);
}
}
return $data;
}
/**
* @codeCoverageIgnore
* @param Collection $entries
*
* @return array
*/
public function month(Collection $entries)
{
return $this->all($entries);
}
/**
* @param Collection $categories
* @param Collection $entries
*
* @return array
*/
public function year(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;
}
}

View File

@ -0,0 +1,105 @@
<?php
namespace FireflyIII\Generator\Chart\Category;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
/**
* Class GoogleCategoryChartGenerator
*
* @package FireflyIII\Generator\Chart\Category
*/
class GoogleCategoryChartGenerator implements CategoryChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function all(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 $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();
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace FireflyIII\Generator\Chart\PiggyBank;
use Carbon\Carbon;
use Config;
use Illuminate\Support\Collection;
use Preferences;
/**
* Class GooglePiggyBankChartGenerator
*
* @package FireflyIII\Generator\Chart\PiggyBank
*/
class ChartJsPiggyBankChartGenerator implements PiggyBankChartGenerator
{
/**
* @param Collection $set
*
* @return array
*/
public function history(Collection $set)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.month.' . $language);
$data = [
'count' => 1,
'labels' => [],
'datasets' => [
[
'label' => 'Diff',
'data' => []
]
],
];
$sum = '0';
bcscale(2);
foreach ($set as $entry) {
$date = new Carbon($entry->date);
$sum = bcadd($sum, $entry->sum);
$data['labels'][] = $date->formatLocalized($format);
$data['datasets'][0]['data'][] = round($sum, 2);
}
return $data;
}
}

View File

@ -0,0 +1,41 @@
<?php
namespace FireflyIII\Generator\Chart\PiggyBank;
use Carbon\Carbon;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
/**
* Class GooglePiggyBankChartGenerator
*
* @package FireflyIII\Generator\Chart\PiggyBank
*/
class GooglePiggyBankChartGenerator implements PiggyBankChartGenerator
{
/**
* @param Collection $set
*
* @return array
*/
public function history(Collection $set)
{
$chart = new GChart;
$chart->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();
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace FireflyIII\Generator\Chart\PiggyBank;
use Illuminate\Support\Collection;
/**
* Interface PiggyBankChartGenerator
*
* @package FireflyIII\Generator\Chart\PiggyBank
*/
interface PiggyBankChartGenerator
{
/**
* @param Collection $set
*
* @return array
*/
public function history(Collection $set);
}

View File

@ -0,0 +1,83 @@
<?php
namespace FireflyIII\Generator\Chart\Report;
use Config;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Preferences;
/**
* Class GoogleReportChartGenerator
*
* @package FireflyIII\Generator\Chart\Report
*/
class ChartJsReportChartGenerator implements ReportChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function yearInOut(Collection $entries)
{
// language:
$language = Preferences::get('language', 'en')->data;
$format = Config::get('firefly.month.' . $language);
$data = [
'count' => 2,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.income'),
'data' => []
],
[
'label' => trans('firefly.expenses'),
'data' => []
]
],
];
foreach ($entries as $entry) {
$data['labels'][] = $entry[0]->formatLocalized($format);
$data['datasets'][0]['data'][] = round($entry[1], 2);
$data['datasets'][1]['data'][] = round($entry[2], 2);
}
return $data;
}
/**
* @param string $income
* @param string $expense
* @param int $count
*
* @return array
*/
public function yearInOutSummarized($income, $expense, $count)
{
$data = [
'count' => 2,
'labels' => [],
'datasets' => [
[
'label' => trans('firefly.income'),
'data' => []
],
[
'label' => trans('firefly.expenses'),
'data' => []
]
],
];
$data['datasets'][0]['data'][] = round($income, 2);
$data['datasets'][1]['data'][] = round($expense, 2);
$data['datasets'][0]['data'][] = round(($income / $count), 2);
$data['datasets'][1]['data'][] = round(($expense / $count), 2);
return $data;
}
}

View File

@ -0,0 +1,58 @@
<?php
namespace FireflyIII\Generator\Chart\Report;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
/**
* Class GoogleReportChartGenerator
*
* @package FireflyIII\Generator\Chart\Report
*/
class GoogleReportChartGenerator implements ReportChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function yearInOut(Collection $entries)
{
$chart = new GChart;
$chart->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();
}
}

View File

@ -0,0 +1,31 @@
<?php
namespace FireflyIII\Generator\Chart\Report;
use Illuminate\Support\Collection;
/**
* Interface ReportChartGenerator
*
* @package FireflyIII\Generator\Chart\Report
*/
interface ReportChartGenerator
{
/**
* @param Collection $entries
*
* @return array
*/
public function yearInOut(Collection $entries);
/**
* @param string $income
* @param string $expense
* @param int $count
*
* @return array
*/
public function yearInOutSummarized($income, $expense, $count);
}

View File

@ -51,9 +51,15 @@ class ConnectJournalToPiggyBank
if (is_null($repetition)) { if (is_null($repetition)) {
return false; return false;
} }
$amount = $journal->correct_amount;
bcscale(2); bcscale(2);
$amount = $journal->actual_amount;
// if piggy account matches source account, the amount is positive
if ($piggyBank->account_id == $journal->source_account->id) {
$amount = $amount * -1;
}
$repetition->currentamount = bcadd($repetition->currentamount, $amount); $repetition->currentamount = bcadd($repetition->currentamount, $amount);
$repetition->save(); $repetition->save();

View File

@ -1,176 +0,0 @@
<?php
namespace FireflyIII\Helpers\Reminders;
use Amount;
use Auth;
use Carbon\Carbon;
use Config;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder;
use Navigation;
use Preferences;
/**
* Class ReminderHelper
*
* @package FireflyIII\Helpers\Reminders
*/
class ReminderHelper implements ReminderHelperInterface
{
/**
* @param PiggyBank $piggyBank
* @param Carbon $start
* @param Carbon $end
*
* @return Reminder
*/
public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end)
{
$reminder = Auth::user()->reminders()->where('remindersable_id', $piggyBank->id)->onDates($start, $end)->first();
if (is_null($reminder)) {
if (!is_null($piggyBank->targetdate)) {
// get ranges again, but now for the start date
$ranges = $this->getReminderRanges($piggyBank, $start);
$currentRep = $piggyBank->currentRelevantRep();
$left = $piggyBank->targetamount - $currentRep->currentamount;
$perReminder = count($ranges) == 0 ? $left : $left / count($ranges);
} else {
$perReminder = null;
$ranges = [];
$left = 0;
}
$metaData = [
'perReminder' => $perReminder,
'rangesCount' => count($ranges),
'ranges' => $ranges,
'leftToSave' => $left,
];
$reminder = new Reminder;
$reminder->user()->associate(Auth::user());
$reminder->startdate = $start;
$reminder->enddate = $end;
$reminder->active = true;
$reminder->metadata = $metaData;
$reminder->notnow = false;
$reminder->remindersable()->associate($piggyBank);
$reminder->save();
return $reminder;
} else {
return $reminder;
}
}
/**
* Create all reminders for a piggy bank for a given date.
*
* @param PiggyBank $piggyBank
*
* @param Carbon $date
*
* @return mixed
*/
public function createReminders(PiggyBank $piggyBank, Carbon $date)
{
$ranges = $this->getReminderRanges($piggyBank);
foreach ($ranges as $range) {
if ($date < $range['end'] && $date > $range['start']) {
// create a reminder here!
$this->createReminder($piggyBank, $range['start'], $range['end']);
// stop looping, we're done.
break;
}
}
}
/**
* This routine will return an array consisting of two dates which indicate the start
* and end date for each reminder that this piggy bank will have, if the piggy bank has
* any reminders. For example:
*
* [12 mar - 15 mar]
* [15 mar - 18 mar]
*
* etcetera.
*
* Array is filled with tiny arrays with Carbon objects in them.
*
* @param PiggyBank $piggyBank
* @param Carbon $date ;
*
* @return array
*/
public function getReminderRanges(PiggyBank $piggyBank, Carbon $date = null)
{
$ranges = [];
if (is_null($date)) {
$date = new Carbon;
}
if ($piggyBank->remind_me === false) {
return $ranges;
}
if (!is_null($piggyBank->targetdate)) {
// count back until now.
$start = $piggyBank->targetdate;
$end = $piggyBank->startdate;
while ($start > $end) {
$currentEnd = clone $start;
$start = Navigation::subtractPeriod($start, $piggyBank->reminder, 1);
$currentStart = clone $start;
$ranges[] = ['start' => clone $currentStart, 'end' => clone $currentEnd];
}
} else {
$start = clone $piggyBank->startdate;
while ($start < $date) {
$currentStart = clone $start;
$start = Navigation::addPeriod($start, $piggyBank->reminder, 0);
$currentEnd = clone $start;
$ranges[] = ['start' => clone $currentStart, 'end' => clone $currentEnd];
}
}
return $ranges;
}
/**
* Takes a reminder, finds the piggy bank and tells you what to do now.
* Aka how much money to put in.
*
*
* @param Reminder $reminder
*
* @return string
*/
public function getReminderText(Reminder $reminder)
{
/** @var PiggyBank $piggyBank */
$piggyBank = $reminder->remindersable;
if (is_null($piggyBank)) {
return trans('firefly.piggy_bank_not_exists');
}
if (is_null($piggyBank->targetdate)) {
return trans('firefly.add_any_amount_to_piggy', ['amount' => Amount::format($piggyBank->targetamount)]);
}
$lang = Preferences::get('language', 'en')->data;
return trans(
'firefly.add_set_amount_to_piggy',
[
'amount' => Amount::format($reminder->metadata->perReminder),
'date' => $piggyBank->targetdate->formatLocalized(Config::get('firefly.monthAndDay.' . $lang))
]
);
}
}

View File

@ -1,63 +0,0 @@
<?php
namespace FireflyIII\Helpers\Reminders;
use Carbon\Carbon;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder;
/**
* Interface ReminderHelperInterface
*
* @package FireflyIII\Helpers\Reminders
*/
interface ReminderHelperInterface
{
/**
* Takes a reminder, finds the piggy bank and tells you what to do now.
* Aka how much money to put in.
*
* @param Reminder $reminder
*
* @return string
*/
public function getReminderText(Reminder $reminder);
/**
* This routine will return an array consisting of two dates which indicate the start
* and end date for each reminder that this piggy bank will have, if the piggy bank has
* any reminders. For example:
*
* [12 mar - 15 mar]
* [15 mar - 18 mar]
*
* etcetera.
*
* Array is filled with tiny arrays with Carbon objects in them.
*
* @param PiggyBank $piggyBank
*
* @return array
*/
public function getReminderRanges(PiggyBank $piggyBank);
/**
* @param PiggyBank $piggyBank
* @param Carbon $start
* @param Carbon $end
*
* @return Reminder
*/
public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end);
/**
* Create all reminders for a piggy bank for a given date.
*
* @param PiggyBank $piggyBank
*
* @param Carbon $date
*
* @return mixed
*/
public function createReminders(PiggyBank $piggyBank, Carbon $date);
}

View File

@ -2,17 +2,16 @@
namespace FireflyIII\Http\Controllers\Chart; namespace FireflyIII\Http\Controllers\Chart;
use App;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Preferences; use Preferences;
use Response; use Response;
use Session; use Session;
use Steam;
/** /**
* Class AccountController * Class AccountController
@ -21,10 +20,24 @@ use Steam;
*/ */
class AccountController extends Controller class AccountController extends Controller
{ {
/** @var \FireflyIII\Generator\Chart\Account\AccountChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\Account\AccountChartGenerator');
}
/** /**
* Shows the balances for all the user's accounts. * Shows the balances for all the user's accounts.
* *
* @param GChart $chart
* @param AccountRepositoryInterface $repository * @param AccountRepositoryInterface $repository
* *
* @param $year * @param $year
@ -33,7 +46,7 @@ class AccountController extends Controller
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function all(GChart $chart, AccountRepositoryInterface $repository, $year, $month, $shared = false) public function all(AccountRepositoryInterface $repository, $year, $month, $shared = false)
{ {
$start = new Carbon($year . '-' . $month . '-01'); $start = new Carbon($year . '-' . $month . '-01');
$end = clone $start; $end = clone $start;
@ -49,9 +62,6 @@ class AccountController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
/** @var Collection $accounts */ /** @var Collection $accounts */
$accounts = $repository->getAccounts(['Default account', 'Asset account']); $accounts = $repository->getAccounts(['Default account', 'Asset account']);
if ($shared === false) { if ($shared === false) {
@ -63,31 +73,8 @@ class AccountController extends Controller
} }
} }
// // make chart:
$data = $this->generator->all($accounts, $start, $end);
$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();
$data = $chart->getData();
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);
@ -96,18 +83,15 @@ class AccountController extends Controller
/** /**
* Shows the balances for all the user's frontpage accounts. * Shows the balances for all the user's frontpage accounts.
* *
* @param GChart $chart
* @param AccountRepositoryInterface $repository * @param AccountRepositoryInterface $repository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function frontpage(GChart $chart, AccountRepositoryInterface $repository) public function frontpage(AccountRepositoryInterface $repository)
{ {
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
$frontPage = Preferences::get('frontPageAccounts', []); $frontPage = Preferences::get('frontPageAccounts', []);
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = clone Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $end = clone Session::get('end', Carbon::now()->endOfMonth());
$accounts = $repository->getFrontpageAccounts($frontPage); $accounts = $repository->getFrontpageAccounts($frontPage);
// chart properties for cache: // chart properties for cache:
@ -120,30 +104,7 @@ class AccountController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$data = $this->generator->frontpage($accounts, $start, $end);
$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();
$data = $chart->getData();
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);
@ -153,21 +114,16 @@ class AccountController extends Controller
/** /**
* Shows an account's balance for a single month. * Shows an account's balance for a single month.
* *
* @param GChart $chart
* @param Account $account * @param Account $account
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function single(GChart $chart, Account $account) public function single(Account $account)
{ {
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
$chart->addCertainty(1);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
$current = clone $start; $end = Session::get('end', Carbon::now()->endOfMonth());
$today = new Carbon;
// chart properties for cache: // chart properties for cache:
$cache = new CacheProperties(); $cache = new CacheProperties();
@ -180,16 +136,7 @@ class AccountController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
while ($end >= $current) { $data = $this->generator->single($account, $start, $end);
$certain = $current < $today;
$chart->addRow(clone $current, Steam::balance($account, $current), $certain);
$current->addDay();
}
$chart->generate();
$data = $chart->getData();
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);

View File

@ -2,14 +2,13 @@
namespace FireflyIII\Http\Controllers\Chart; namespace FireflyIII\Http\Controllers\Chart;
use App;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Response; use Response;
use Session; use Session;
@ -22,60 +21,30 @@ use Steam;
*/ */
class BillController extends Controller class BillController extends Controller
{ {
/** @var \FireflyIII\Generator\Chart\Bill\BillChartGenerator */
protected $generator;
/** /**
* Shows the overview for a bill. The min/max amount and matched journals. * @codeCoverageIgnore
*
* @param GChart $chart
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return \Symfony\Component\HttpFoundation\Response
*/ */
public function single(GChart $chart, BillRepositoryInterface $repository, Bill $bill) public function __construct()
{ {
parent::__construct();
$chart->addColumn(trans('firefly.date'), 'date'); // create chart generator:
$chart->addColumn(trans('firefly.maxAmount'), 'number'); $this->generator = App::make('FireflyIII\Generator\Chart\Bill\BillChartGenerator');
$chart->addColumn(trans('firefly.minAmount'), 'number');
$chart->addColumn(trans('firefly.billEntry'), 'number');
$cache = new CacheProperties;
$cache->addProperty('single');
$cache->addProperty('bill');
$cache->addProperty($bill->id);
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
// get first transaction or today for start:
$results = $repository->getJournals($bill);
/** @var TransactionJournal $result */
foreach ($results as $result) {
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
}
$chart->generate();
$data = $chart->getData();
$cache->store($data);
return Response::json($data);
} }
/** /**
* Shows all bills and whether or not theyve been paid this month (pie chart). * Shows all bills and whether or not theyve been paid this month (pie chart).
* *
* @param GChart $chart
*
* @param BillRepositoryInterface $repository * @param BillRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts * @param AccountRepositoryInterface $accounts
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function frontpage(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts) public function frontpage(BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
{ {
$chart->addColumn(trans('firefly.name'), 'string');
$chart->addColumn(trans('firefly.amount'), 'number');
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth());
@ -88,17 +57,13 @@ class BillController extends Controller
$cache->addProperty('bills'); $cache->addProperty('bills');
$cache->addProperty('frontpage'); $cache->addProperty('frontpage');
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$bills = $repository->getActiveBills(); $bills = $repository->getActiveBills();
$paid = new Collection; // journals. $paid = new Collection; // journals.
$unpaid = new Collection; // bills $unpaid = new Collection; // bills
// loop paid and create single entry:
$paidDescriptions = [];
$paidAmount = 0;
$unpaidDescriptions = [];
$unpaidAmount = 0;
/** @var Bill $bill */ /** @var Bill $bill */
foreach ($bills as $bill) { foreach ($bills as $bill) {
@ -136,30 +101,35 @@ class BillController extends Controller
} }
} }
// build chart:
$data = $this->generator->frontpage($paid, $unpaid);
$cache->store($data);
/** @var TransactionJournal $entry */ return Response::json($data);
foreach ($paid as $entry) { }
$paidDescriptions[] = $entry->description; /**
$paidAmount += floatval($entry->amount); * Shows the overview for a bill. The min/max amount and matched journals.
*
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function single(BillRepositoryInterface $repository, Bill $bill)
{
$cache = new CacheProperties;
$cache->addProperty('single');
$cache->addProperty('bill');
$cache->addProperty($bill->id);
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
} }
// loop unpaid: // get first transaction or today for start:
/** @var Bill $entry */ $results = $repository->getJournals($bill);
foreach ($unpaid as $entry) {
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
$unpaidDescriptions[] = $description;
$unpaidAmount += $amount;
unset($amount, $description);
}
$chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount); $data = $this->generator->single($bill, $results);
$chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount);
$chart->generate();
$data = $chart->getData();
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);

View File

@ -2,13 +2,13 @@
namespace FireflyIII\Http\Controllers\Chart; namespace FireflyIII\Http\Controllers\Chart;
use App;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Navigation; use Navigation;
use Preferences; use Preferences;
@ -22,19 +22,30 @@ use Session;
*/ */
class BudgetController extends Controller class BudgetController extends Controller
{ {
/** @var \FireflyIII\Generator\Chart\Budget\BudgetChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\Budget\BudgetChartGenerator');
}
/** /**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* @param Budget $budget * @param Budget $budget
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function budget(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget) public function budget(BudgetRepositoryInterface $repository, Budget $budget)
{ {
$chart->addColumn(trans('firefly.period'), 'date');
$chart->addColumn(trans('firefly.spent'), 'number');
// dates and times
$first = $repository->getFirstBudgetLimitDate($budget); $first = $repository->getFirstBudgetLimitDate($budget);
$range = Preferences::get('viewRange', '1M')->data; $range = Preferences::get('viewRange', '1M')->data;
$last = Session::get('end', new Carbon); $last = Session::get('end', new Carbon);
@ -47,33 +58,23 @@ class BudgetController extends Controller
$cache->addProperty($first); $cache->addProperty($first);
$cache->addProperty($last); $cache->addProperty($last);
$cache->addProperty('budget'); $cache->addProperty('budget');
$cache->addProperty('budget');
if ($cache->has()) { if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$entries = new Collection;
while ($first < $last) { while ($first < $last) {
$end = Navigation::addPeriod($first, $range, 0); $end = Navigation::addPeriod($first, $range, 0);
$end->subDay(); $end->subDay();
// start date for chart.
$chartDate = clone $end; $chartDate = clone $end;
$chartDate->startOfMonth(); $chartDate->startOfMonth();
$spent = $repository->spentInPeriodCorrected($budget, $first, $end); $spent = $repository->spentInPeriodCorrected($budget, $first, $end);
$chart->addRow($chartDate, $spent); $entries->push([$chartDate, $spent]);
$first = Navigation::addPeriod($first, $range, 0); $first = Navigation::addPeriod($first, $range, 0);
} }
$chart->generate(); $data = $this->generator->budget($entries);
$data = $chart->getData();
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);
@ -82,14 +83,13 @@ class BudgetController extends Controller
/** /**
* Shows the amount left in a specific budget limit. * Shows the amount left in a specific budget limit.
* *
* @param GChart $chart
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* @param Budget $budget * @param Budget $budget
* @param LimitRepetition $repetition * @param LimitRepetition $repetition
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function budgetLimit(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition) public function budgetLimit(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
{ {
$start = clone $repetition->startdate; $start = clone $repetition->startdate;
$end = $repetition->enddate; $end = $repetition->enddate;
@ -106,11 +106,8 @@ class BudgetController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$chart->addColumn(trans('firefly.day'), 'date'); $entries = new Collection;
$chart->addColumn(trans('firefly.left'), 'number'); $amount = $repetition->amount;
$amount = $repetition->amount;
while ($start <= $end) { while ($start <= $end) {
/* /*
@ -118,12 +115,11 @@ class BudgetController extends Controller
*/ */
$sum = $repository->expensesOnDayCorrected($budget, $start); $sum = $repository->expensesOnDayCorrected($budget, $start);
$amount += $sum; $amount += $sum;
$chart->addRow(clone $start, $amount); $entries->push([clone $start, $amount]);
$start->addDay(); $start->addDay();
} }
$chart->generate();
$data = $chart->getData(); $data = $this->generator->budgetLimit($entries);
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);
@ -133,18 +129,12 @@ class BudgetController extends Controller
/** /**
* Shows a budget list with spent/left/overspent. * Shows a budget list with spent/left/overspent.
* *
* @param GChart $chart
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function frontpage(GChart $chart, BudgetRepositoryInterface $repository) public function frontpage(BudgetRepositoryInterface $repository)
{ {
$chart->addColumn(trans('firefly.budget'), 'string');
$chart->addColumn(trans('firefly.left'), 'number');
$chart->addColumn(trans('firefly.spent'), 'number');
$chart->addColumn(trans('firefly.overspent'), 'number');
$budgets = $repository->getBudgets(); $budgets = $repository->getBudgets();
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth());
@ -160,43 +150,38 @@ class BudgetController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
bcscale(2);
/** @var Budget $budget */ /** @var Budget $budget */
foreach ($budgets as $budget) { foreach ($budgets as $budget) {
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end); $repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
if ($repetitions->count() == 0) { if ($repetitions->count() == 0) {
$expenses = $repository->spentInPeriodCorrected($budget, $start, $end, true); $expenses = $repository->spentInPeriodCorrected($budget, $start, $end, true);
$allEntries->push([$budget->name, 0, 0, $expenses]); $allEntries->push([$budget->name, 0, 0, $expenses, 0, 0]);
continue; continue;
} }
/** @var LimitRepetition $repetition */ /** @var LimitRepetition $repetition */
foreach ($repetitions as $repetition) { foreach ($repetitions as $repetition) {
$expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true); $expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true);
$left = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0; // $left can be less than zero.
$spent = $expenses > floatval($repetition->amount) ? floatval($repetition->amount) : $expenses; // $overspent can be more than zero ( = overspending)
$overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0;
$allEntries->push( $left = max(bcsub($repetition->amount, $expenses), 0); // limited at zero.
[$budget->name . ' (' . $repetition->startdate->formatLocalized($this->monthAndDayFormat) . ')', $overspent = max(bcsub($expenses, $repetition->amount), 0); // limited at zero.
$left, $name = $budget->name;
$spent,
$overspent // $spent is maxed to the repetition amount:
] $spent = $expenses > $repetition->amount ? $repetition->amount : $expenses;
);
$allEntries->push([$name, $left, $spent, $overspent, $repetition->amount, $expenses]);
} }
} }
$noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end) * -1; $noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end) * -1;
$allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses]); $allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses, 0, 0]);
foreach ($allEntries as $entry) { $data = $this->generator->frontpage($allEntries);
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
$chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]);
}
}
$chart->generate();
$data = $chart->getData();
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);
@ -206,14 +191,13 @@ class BudgetController extends Controller
/** /**
* Show a yearly overview for a budget. * Show a yearly overview for a budget.
* *
* @param GChart $chart
* @param BudgetRepositoryInterface $repository * @param BudgetRepositoryInterface $repository
* @param $year * @param $year
* @param bool $shared * @param bool $shared
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function year(GChart $chart, BudgetRepositoryInterface $repository, $year, $shared = false) public function year(BudgetRepositoryInterface $repository, $year, $shared = false)
{ {
$start = new Carbon($year . '-01-01'); $start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31'); $end = new Carbon($year . '-12-31');
@ -230,17 +214,12 @@ class BudgetController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
// add columns: $entries = new Collection;
$chart->addColumn(trans('firefly.month'), 'date');
foreach ($budgets as $budget) {
$chart->addColumn($budget->name, 'number');
}
while ($start < $end) { while ($start < $end) {
// month is the current end of the period: // month is the current end of the period:
$month = clone $start; $month = clone $start;
$month->endOfMonth(); $month->endOfMonth();
// make a row:
$row = [clone $start]; $row = [clone $start];
// each budget, fill the row: // each budget, fill the row:
@ -248,14 +227,11 @@ class BudgetController extends Controller
$spent = $repository->spentInPeriodCorrected($budget, $start, $month, $shared); $spent = $repository->spentInPeriodCorrected($budget, $start, $month, $shared);
$row[] = $spent; $row[] = $spent;
} }
$chart->addRowArray($row); $entries->push($row);
$start->endOfMonth()->addDay(); $start->endOfMonth()->addDay();
} }
$chart->generate(); $data = $this->generator->year($budgets, $entries);
$data = $chart->getData();
$cache->store($data); $cache->store($data);
return Response::json($data); return Response::json($data);

View File

@ -3,12 +3,13 @@
namespace FireflyIII\Http\Controllers\Chart; namespace FireflyIII\Http\Controllers\Chart;
use App;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use Grumpydictator\Gchart\GChart; use Illuminate\Support\Collection;
use Navigation; use Navigation;
use Preferences; use Preferences;
use Response; use Response;
@ -21,42 +22,61 @@ use Session;
*/ */
class CategoryController extends Controller class CategoryController extends Controller
{ {
/** @var \FireflyIII\Generator\Chart\Category\CategoryChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\Category\CategoryChartGenerator');
}
/** /**
* Show an overview for a category for all time, per month/week/year. * Show an overview for a category for all time, per month/week/year.
* *
* @param GChart $chart
* @param CategoryRepositoryInterface $repository * @param CategoryRepositoryInterface $repository
* @param Category $category * @param Category $category
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function all(GChart $chart, CategoryRepositoryInterface $repository, Category $category) public function all(CategoryRepositoryInterface $repository, Category $category)
{ {
// oldest transaction in category: // oldest transaction in category:
$start = $repository->getFirstActivityDate($category); $start = $repository->getFirstActivityDate($category);
$range = Preferences::get('viewRange', '1M')->data; $range = Preferences::get('viewRange', '1M')->data;
// jump to start of week / month / year / etc
$start = Navigation::startOfPeriod($start, $range); $start = Navigation::startOfPeriod($start, $range);
$end = new Carbon;
$chart->addColumn(trans('firefly.period'), 'date'); $entries = new Collection;
$chart->addColumn(trans('firefly.spent'), 'number');
$end = new Carbon; // chart properties for cache:
while ($start <= $end) { $cache = new CacheProperties();
$cache->addProperty($start);
$currentEnd = Navigation::endOfPeriod($start, $range); $cache->addProperty($end);
$spent = $repository->spentInPeriodCorrected($category, $start, $currentEnd); $cache->addProperty('all');
$chart->addRow(clone $start, $spent); $cache->addProperty('categories');
if ($cache->has()) {
$start = Navigation::addPeriod($start, $range, 0); return Response::json($cache->get()); // @codeCoverageIgnore
} }
$chart->generate(); while ($start <= $end) {
$currentEnd = Navigation::endOfPeriod($start, $range);
$spent = $repository->spentInPeriodCorrected($category, $start, $currentEnd);
$entries->push([clone $start, $spent]);
$start = Navigation::addPeriod($start, $range, 0);
return Response::json($chart->getData()); }
$data = $this->generator->all($entries);
$cache->store($data);
return Response::json($data);
} }
@ -64,15 +84,12 @@ class CategoryController extends Controller
/** /**
* Show this month's category overview. * Show this month's category overview.
* *
* @param GChart $chart
* @param CategoryRepositoryInterface $repository * @param CategoryRepositoryInterface $repository
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function frontpage(GChart $chart, CategoryRepositoryInterface $repository) public function frontpage(CategoryRepositoryInterface $repository)
{ {
$chart->addColumn(trans('firefly.category'), 'string');
$chart->addColumn(trans('firefly.spent'), 'number');
$start = Session::get('start', Carbon::now()->startOfMonth()); $start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth());
@ -87,11 +104,10 @@ class CategoryController extends Controller
return Response::json($cache->get()); // @codeCoverageIgnore return Response::json($cache->get()); // @codeCoverageIgnore
} }
$set = $repository->getCategoriesAndExpensesCorrected($start, $end); $array = $repository->getCategoriesAndExpensesCorrected($start, $end);
// sort by callback: // sort by callback:
uasort( uasort(
$set, $array,
function ($left, $right) { function ($left, $right) {
if ($left['sum'] == $right['sum']) { if ($left['sum'] == $right['sum']) {
return 0; return 0;
@ -100,48 +116,48 @@ class CategoryController extends Controller
return ($left['sum'] < $right['sum']) ? 1 : -1; return ($left['sum'] < $right['sum']) ? 1 : -1;
} }
); );
$set = new Collection($array);
$data = $this->generator->frontpage($set);
foreach ($set as $entry) {
$sum = floatval($entry['sum']);
if ($sum != 0) {
$chart->addRow($entry['name'], $sum);
}
}
$chart->generate();
$data = $chart->getData();
$cache->store($data);
return Response::json($data); return Response::json($data);
} }
/** /**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository * @param CategoryRepositoryInterface $repository
* @param Category $category * @param Category $category
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function month(GChart $chart, CategoryRepositoryInterface $repository, Category $category) public function month(CategoryRepositoryInterface $repository, Category $category)
{ {
$start = clone Session::get('start', Carbon::now()->startOfMonth()); $start = clone Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth()); $end = Session::get('end', Carbon::now()->endOfMonth());
$chart->addColumn(trans('firefly.period'), 'date'); // chart properties for cache:
$chart->addColumn(trans('firefly.spent'), 'number'); $cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty($category->id);
$cache->addProperty('category');
$cache->addProperty('month');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$entries = new Collection;
while ($start <= $end) { while ($start <= $end) {
$spent = $repository->spentOnDaySumCorrected($category, $start); $spent = $repository->spentOnDaySumCorrected($category, $start);
$chart->addRow(clone $start, $spent);
$entries->push([clone $start, $spent]);
$start->addDay(); $start->addDay();
} }
$chart->generate(); $data = $this->generator->month($entries);
$cache->store($data);
return Response::json($chart->getData()); return Response::json($data);
} }
@ -149,25 +165,31 @@ class CategoryController extends Controller
/** /**
* This chart will only show expenses. * This chart will only show expenses.
* *
* @param GChart $chart
* @param CategoryRepositoryInterface $repository * @param CategoryRepositoryInterface $repository
* @param $year * @param $year
* @param bool $shared * @param bool $shared
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function year(GChart $chart, CategoryRepositoryInterface $repository, $year, $shared = false) public function year(CategoryRepositoryInterface $repository, $year, $shared = false)
{ {
$start = new Carbon($year . '-01-01'); $start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31'); $end = new Carbon($year . '-12-31');
// chart properties for cache:
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('category');
$cache->addProperty('year');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$shared = $shared == 'shared' ? true : false; $shared = $shared == 'shared' ? true : false;
$categories = $repository->getCategories(); $categories = $repository->getCategories();
$entries = new Collection;
// add columns:
$chart->addColumn(trans('firefly.month'), 'date');
foreach ($categories as $category) {
$chart->addColumn($category->name, 'number');
}
while ($start < $end) { while ($start < $end) {
// month is the current end of the period: // month is the current end of the period:
@ -181,13 +203,14 @@ class CategoryController extends Controller
$spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared); $spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
$row[] = $spent; $row[] = $spent;
} }
$chart->addRowArray($row); $entries->push($row);
$start->addMonth(); $start->addMonth();
} }
$chart->generate(); $data = $this->generator->year($categories, $entries);
$cache->store($data);
return Response::json($chart->getData()); return Response::json($data);
} }
} }

View File

@ -2,11 +2,11 @@
namespace FireflyIII\Http\Controllers\Chart; namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon; use App;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Grumpydictator\Gchart\GChart; use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Response; use Response;
@ -18,32 +18,44 @@ use Response;
*/ */
class PiggyBankController extends Controller class PiggyBankController extends Controller
{ {
/** @var \FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator');
}
/** /**
* Shows the piggy bank history. * Shows the piggy bank history.
* *
* @param GChart $chart
* @param PiggyBankRepositoryInterface $repository * @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank * @param PiggyBank $piggyBank
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function history(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank) public function history(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{ {
$chart->addColumn(trans('firefly.date'), 'date'); // chart properties for cache:
$chart->addColumn(trans('firefly.balance'), 'number'); $cache = new CacheProperties;
$cache->addProperty('piggy-history');
/** @var Collection $set */ $cache->addProperty($piggyBank->id);
$set = $repository->getEventSummarySet($piggyBank); if ($cache->has()) {
$sum = 0; return Response::json($cache->get()); // @codeCoverageIgnore
foreach ($set as $entry) {
$sum += floatval($entry->sum);
$chart->addRow(new Carbon($entry->date), $sum);
} }
$chart->generate(); /** @var Collection $set */
$set = new Collection($repository->getEventSummarySet($piggyBank));
$data = $this->generator->history($set);
$cache->store($data);
return Response::json($chart->getData()); return Response::json($data);
} }
} }

View File

@ -3,10 +3,12 @@
namespace FireflyIII\Http\Controllers\Chart; namespace FireflyIII\Http\Controllers\Chart;
use App;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportQueryInterface; use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use Grumpydictator\Gchart\GChart; use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Response; use Response;
/** /**
@ -17,85 +19,108 @@ use Response;
class ReportController extends Controller class ReportController extends Controller
{ {
/** @var \FireflyIII\Generator\Chart\Report\ReportChartGenerator */
protected $generator;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
parent::__construct();
// create chart generator:
$this->generator = App::make('FireflyIII\Generator\Chart\Report\ReportChartGenerator');
}
/** /**
* Summarizes all income and expenses, per month, for a given year. * Summarizes all income and expenses, per month, for a given year.
* *
* @param GChart $chart
* @param ReportQueryInterface $query * @param ReportQueryInterface $query
* @param $year * @param $year
* @param bool $shared * @param bool $shared
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function yearInOut(GChart $chart, ReportQueryInterface $query, $year, $shared = false) public function yearInOut(ReportQueryInterface $query, $year, $shared = false)
{ {
// get start and end of year // get start and end of year
$start = new Carbon($year . '-01-01'); $start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31'); $end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false; $shared = $shared == 'shared' ? true : false;
$chart->addColumn(trans('firefly.month'), 'date'); // chart properties for cache:
$chart->addColumn(trans('firefly.income'), 'number'); $cache = new CacheProperties;
$chart->addColumn(trans('firefly.expenses'), 'number'); $cache->addProperty('yearInOut');
$cache->addProperty($year);
$cache->addProperty($shared);
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$entries = new Collection;
while ($start < $end) { while ($start < $end) {
$month = clone $start; $month = clone $start;
$month->endOfMonth(); $month->endOfMonth();
// total income and total expenses: // total income and total expenses:
$incomeSum = floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount')); $incomeSum = $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount');
$expenseSum = floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount')); $expenseSum = $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount');
$chart->addRow(clone $start, $incomeSum, $expenseSum); $entries->push([clone $start, $incomeSum, $expenseSum]);
$start->addMonth(); $start->addMonth();
} }
$chart->generate();
return Response::json($chart->getData()); $data = $this->generator->yearInOut($entries);
$cache->store($data);
return Response::json($data);
} }
/** /**
* Summarizes all income and expenses for a given year. Gives a total and an average. * Summarizes all income and expenses for a given year. Gives a total and an average.
* *
* @param GChart $chart
* @param ReportQueryInterface $query * @param ReportQueryInterface $query
* @param $year * @param $year
* @param bool $shared * @param bool $shared
* *
* @return \Symfony\Component\HttpFoundation\Response * @return \Symfony\Component\HttpFoundation\Response
*/ */
public function yearInOutSummarized(GChart $chart, ReportQueryInterface $query, $year, $shared = false) public function yearInOutSummarized(ReportQueryInterface $query, $year, $shared = false)
{ {
// chart properties for cache:
$cache = new CacheProperties;
$cache->addProperty('yearInOutSummarized');
$cache->addProperty($year);
$cache->addProperty($shared);
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$start = new Carbon($year . '-01-01'); $start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31'); $end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false; $shared = $shared == 'shared' ? true : false;
$income = 0; $income = '0';
$expense = 0; $expense = '0';
$count = 0; $count = 0;
$chart->addColumn(trans('firefly.summary'), 'string'); bcscale(2);
$chart->addColumn(trans('firefly.income'), 'number');
$chart->addColumn(trans('firefly.expenses'), 'number');
while ($start < $end) { while ($start < $end) {
$month = clone $start; $month = clone $start;
$month->endOfMonth(); $month->endOfMonth();
// total income and total expenses: // total income and total expenses:
$income += floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount')); $income = bcadd($income, $query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'));
$expense += floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount')); $expense = bcadd($expense, $query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'));
$count++; $count++;
$start->addMonth(); $start->addMonth();
} }
// add total + average: $data = $this->generator->yearInOutSummarized($income, $expense, $count);
$chart->addRow(trans('firefly.sum'), $income, $expense); $cache->store($data);
$count = $count > 0 ? $count : 1;
$chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count));
$chart->generate(); return Response::json($data);
return Response::json($chart->getData());
} }
} }

View File

@ -142,8 +142,6 @@ class PiggyBankController extends Controller
'account_id' => $piggyBank->account_id, 'account_id' => $piggyBank->account_id,
'targetamount' => $piggyBank->targetamount, 'targetamount' => $piggyBank->targetamount,
'targetdate' => $targetDate, 'targetdate' => $targetDate,
'reminder' => $piggyBank->reminder,
'remind_me' => intval($piggyBank->remind_me) == 1 && !is_null($piggyBank->reminder) ? true : false
]; ];
Session::flash('preFilled', $preFilled); Session::flash('preFilled', $preFilled);
Session::flash('gaEventCategory', 'piggy-banks'); Session::flash('gaEventCategory', 'piggy-banks');
@ -299,12 +297,7 @@ class PiggyBankController extends Controller
*/ */
public function show(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank) public function show(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{ {
$events = $repository->getEvents($piggyBank); $events = $repository->getEvents($piggyBank);
/*
* Number of reminders:
*/
$subTitle = e($piggyBank->name); $subTitle = e($piggyBank->name);
return view('piggy-banks.show', compact('piggyBank', 'events', 'subTitle')); return view('piggy-banks.show', compact('piggyBank', 'events', 'subTitle'));
@ -321,13 +314,13 @@ class PiggyBankController extends Controller
{ {
$piggyBankData = [ $piggyBankData = [
'name' => $request->get('name'), 'name' => $request->get('name'),
'startdate' => new Carbon, 'startdate' => new Carbon,
'account_id' => intval($request->get('account_id')), 'account_id' => intval($request->get('account_id')),
'targetamount' => floatval($request->get('targetamount')), 'targetamount' => floatval($request->get('targetamount')),
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null, 'remind_me' => false,
'reminder' => $request->get('reminder'), 'reminder_skip' => 0,
'remind_me' => $request->get('remind_me'), 'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
]; ];
$piggyBank = $repository->store($piggyBankData); $piggyBank = $repository->store($piggyBankData);
@ -356,13 +349,13 @@ class PiggyBankController extends Controller
public function update(PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request, PiggyBank $piggyBank) public function update(PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request, PiggyBank $piggyBank)
{ {
$piggyBankData = [ $piggyBankData = [
'name' => $request->get('name'), 'name' => $request->get('name'),
'startdate' => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate, 'startdate' => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate,
'account_id' => intval($request->get('account_id')), 'account_id' => intval($request->get('account_id')),
'targetamount' => floatval($request->get('targetamount')), 'targetamount' => floatval($request->get('targetamount')),
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null, 'remind_me' => false,
'reminder' => $request->get('reminder'), 'reminder_skip' => 0,
'remind_me' => $request->get('remind_me') 'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
]; ];
$piggyBank = $repository->update($piggyBank, $piggyBankData); $piggyBank = $repository->update($piggyBank, $piggyBankData);

View File

@ -1,92 +0,0 @@
<?php namespace FireflyIII\Http\Controllers;
use FireflyIII\Models\Reminder;
use FireflyIII\Repositories\Reminder\ReminderRepositoryInterface;
use Redirect;
use Session;
use URL;
/**
* Class ReminderController
*
* @package FireflyIII\Http\Controllers
*/
class ReminderController extends Controller
{
/**
* @param Reminder $reminder
*
* @return \Illuminate\Http\RedirectResponse
*/
public function act(Reminder $reminder)
{
$data = [
'description' => 'Money for piggy bank "' . $reminder->remindersable->name . '"',
'amount' => round($reminder->metadata->perReminder, 2),
'account_to_id' => $reminder->remindersable->account_id,
'piggy_bank_id' => $reminder->remindersable_id,
'reminder_id' => $reminder->id,
];
Session::flash('_old_input', $data);
return Redirect::route('transactions.create', ['transfer']);
}
/**
* @param Reminder $reminder
*
* @return \Illuminate\Http\RedirectResponse
*/
public function dismiss(Reminder $reminder)
{
$reminder->notnow = true;
$reminder->save();
return Redirect::to(URL::previous());
}
/**
* @param ReminderRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function index(ReminderRepositoryInterface $repository)
{
$active = $repository->getActiveReminders();
$expired = $repository->getExpiredReminders();
$inactive = $repository->getInactiveReminders();
$dismissed = $repository->getDismissedReminders();
$title = 'Reminders';
$mainTitleIcon = 'fa-clock-o';
return view('reminders.index', compact('dismissed', 'expired', 'inactive', 'active', 'title', 'mainTitleIcon'));
}
/**
* @param Reminder $reminder
*
* @return \Illuminate\View\View
*/
public function show(Reminder $reminder)
{
$title = trans('firefly.reminder');
$mainTitleIcon = 'fa-clock-o';
if ($reminder->notnow === true) {
$subTitle = trans('firefly.dismissed_reminder_for_piggy', ['name' => $reminder->remindersable->name]);
} else {
$subTitle = trans('firefly.reminder_for_piggy', ['name' => $reminder->remindersable->name]);
}
return view('reminders.show', compact('reminder', 'title', 'subTitle', 'mainTitleIcon'));
}
}

View File

@ -180,12 +180,12 @@ class TagController extends Controller
$helpHidden = $helpHiddenPref->data; $helpHidden = $helpHiddenPref->data;
// group years. // group years.
$types = ['nothing','balancingAct', 'advancePayment']; $types = ['nothing', 'balancingAct', 'advancePayment'];
// loop each types and get the tags, group them by year. // loop each types and get the tags, group them by year.
$collection = []; $collection = [];
foreach ($types as $type) { foreach ($types as $type) {
$tags = Auth::user()->tags()->where('tagMode', $type)->orderBy('date','ASC')->get(); $tags = Auth::user()->tags()->where('tagMode', $type)->orderBy('date', 'ASC')->get();
/** @var Tag $tag */ /** @var Tag $tag */
foreach ($tags as $tag) { foreach ($tags as $tag) {
$year = is_null($tag->date) ? trans('firefly.no_year') : $tag->date->year; $year = is_null($tag->date) ? trans('firefly.no_year') : $tag->date->year;
@ -195,7 +195,7 @@ class TagController extends Controller
} }
return view('tags.index', compact('title', 'mainTitleIcon','types', 'helpHidden', 'collection')); return view('tags.index', compact('title', 'mainTitleIcon', 'types', 'helpHidden', 'collection'));
} }
/** /**
@ -208,7 +208,7 @@ class TagController extends Controller
$subTitle = $tag->tag; $subTitle = $tag->tag;
$subTitleIcon = 'fa-tag'; $subTitleIcon = 'fa-tag';
return view('tags.show', compact('tag', 'subTitle','types', 'subTitleIcon')); return view('tags.show', compact('tag', 'subTitle', 'subTitleIcon'));
} }
/** /**

View File

@ -159,20 +159,12 @@ class TransactionController extends Controller
if ($journal->transactionType->type == 'Withdrawal') { if ($journal->transactionType->type == 'Withdrawal') {
$preFilled['account_id'] = $journal->source_account->id; $preFilled['account_id'] = $journal->source_account->id;
$preFilled['expense_account'] = $journal->destination_account->name; $preFilled['expense_account'] = $journal->destination_account->name_for_editform;
} else { } else {
$preFilled['account_id'] = $journal->destination_account->id; $preFilled['account_id'] = $journal->destination_account->id;
$preFilled['revenue_account'] = $journal->source_account->name; $preFilled['revenue_account'] = $journal->source_account->name_for_editform;
} }
if ($journal->destination_account->accountType->type == 'Cash account') {
$preFilled['expense_account'] = '';
}
if ($journal->source_account->accountType->type == 'Cash account') {
$preFilled['revenue_account'] = '';
}
$preFilled['account_from_id'] = $journal->source_account->id; $preFilled['account_from_id'] = $journal->source_account->id;
$preFilled['account_to_id'] = $journal->destination_account->id; $preFilled['account_to_id'] = $journal->destination_account->id;
@ -296,8 +288,6 @@ class TransactionController extends Controller
event(new JournalCreated($journal, intval($request->get('piggy_bank_id')))); event(new JournalCreated($journal, intval($request->get('piggy_bank_id'))));
} }
$repository->deactivateReminder($request->get('reminder_id'));
Session::flash('success', 'New transaction "' . $journal->description . '" stored!'); Session::flash('success', 'New transaction "' . $journal->description . '" stored!');
Preferences::mark(); Preferences::mark();

View File

@ -37,7 +37,6 @@ class Kernel extends HttpKernel
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth', 'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
'guest' => 'FireflyIII\Http\Middleware\RedirectIfAuthenticated', 'guest' => 'FireflyIII\Http\Middleware\RedirectIfAuthenticated',
'range' => 'FireflyIII\Http\Middleware\Range', 'range' => 'FireflyIII\Http\Middleware\Range',
'reminders' => 'FireflyIII\Http\Middleware\Reminders',
]; ];

View File

@ -1,96 +0,0 @@
<?php
namespace FireflyIII\Http\Middleware;
use App;
use Carbon\Carbon;
use Closure;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder;
use FireflyIII\Support\CacheProperties;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use View;
/**
* Class Reminders
*
* @package FireflyIII\Http\Middleware
*/
class Reminders
{
/**
* The Guard implementation.
*
* @var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* @param Guard $auth
*
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
*
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$user = $this->auth->user();
if ($this->auth->check() && !$request->isXmlHttpRequest() && $user instanceof User) {
// do reminders stuff.
// abuse CacheProperties to find out if we need to do this:
$cache = new CacheProperties;
$cache->addProperty('reminders');
if ($cache->has()) {
$reminders = $cache->get();
View::share('reminders', $reminders);
return $next($request);
}
$piggyBanks = $user->piggyBanks()->where('remind_me', 1)->get();
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface $helper */
$helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface');
/** @var PiggyBank $piggyBank */
foreach ($piggyBanks as $piggyBank) {
$helper->createReminders($piggyBank, new Carbon);
}
// delete invalid reminders
// this is a construction SQLITE cannot handle :(
if (env('DB_CONNECTION') != 'sqlite') {
Reminder::whereUserId($user->id)->leftJoin('piggy_banks', 'piggy_banks.id', '=', 'remindersable_id')->whereNull('piggy_banks.id')->delete();
}
// get and list active reminders:
$reminders = $user->reminders()->today()->get();
$reminders->each(
function (Reminder $reminder) use ($helper) {
$reminder->description = $helper->getReminderText($reminder);
}
);
$cache->store($reminders);
View::share('reminders', $reminders);
}
return $next($request);
}
}

View File

@ -61,7 +61,6 @@ class JournalFormRequest extends Request
'what' => 'required|in:withdrawal,deposit,transfer', 'what' => 'required|in:withdrawal,deposit,transfer',
'amount' => 'numeric|required|min:0.01', 'amount' => 'numeric|required|min:0.01',
'date' => 'required|date', 'date' => 'required|date',
'reminder_id' => 'numeric|exists:reminders,id',
'amount_currency_id' => 'required|exists:transaction_currencies,id', 'amount_currency_id' => 'required|exists:transaction_currencies,id',
]; ];

View File

@ -42,9 +42,6 @@ class PiggyBankFormRequest extends Request
'amount_currency_id' => 'exists:transaction_currencies,id', 'amount_currency_id' => 'exists:transaction_currencies,id',
'startdate' => 'date', 'startdate' => 'date',
'targetdate' => $targetDateRule, 'targetdate' => $targetDateRule,
'reminder' => 'in:day,week,quarter,month,year',
'reminder_skip' => 'integer|min:0|max:99',
'remind_me' => 'boolean|piggyBankReminder',
'order' => 'integer|min:1', 'order' => 'integer|min:1',
]; ];

View File

@ -7,7 +7,6 @@ use FireflyIII\Models\Budget;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
@ -286,25 +285,6 @@ Breadcrumbs::register(
} }
); );
// reminders
Breadcrumbs::register(
'reminders.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push(trans('breadcrumbs.reminders'), route('reminders.index'));
}
);
// reminders
Breadcrumbs::register(
'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) {
$breadcrumbs->parent('reminders.index');
$breadcrumbs->push(trans('breadcrumbs.reminder', ['id' => e($reminder->id)]), route('reminders.show', [$reminder->id]));
}
);
// reports // reports
Breadcrumbs::register( Breadcrumbs::register(
'reports.index', function (Generator $breadcrumbs) { 'reports.index', function (Generator $breadcrumbs) {

View File

@ -5,7 +5,6 @@ use FireflyIII\Models\Budget;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder;
use FireflyIII\Models\Tag; use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
@ -81,19 +80,6 @@ Route::bind(
} }
); );
Route::bind(
'reminder', function ($value) {
if (Auth::check()) {
$object = Reminder::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
}
throw new NotFoundHttpException;
}
);
Route::bind( Route::bind(
'limitrepetition', function ($value) { 'limitrepetition', function ($value) {
if (Auth::check()) { if (Auth::check()) {
@ -140,23 +126,6 @@ Route::bind(
} }
); );
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'reminder', function ($value) {
if (Auth::check()) {
/** @var \FireflyIII\Models\Reminder $object */
$object = Reminder::find($value);
if ($object) {
if ($object->remindersable->account->user_id == Auth::user()->id) {
return $object;
}
}
}
throw new NotFoundHttpException;
}
);
Route::bind( Route::bind(
'tag', function ($value) { 'tag', function ($value) {
if (Auth::check()) { if (Auth::check()) {
@ -185,7 +154,7 @@ Route::controllers(
Route::group( Route::group(
['middleware' => ['auth', 'range', 'reminders']], function () { ['middleware' => ['auth', 'range']], function () {
/** /**
* Home Controller * Home Controller
@ -355,14 +324,6 @@ Route::group(
Route::post('/profile/delete-account', ['uses' => 'ProfileController@postDeleteAccount', 'as' => 'delete-account-post']); Route::post('/profile/delete-account', ['uses' => 'ProfileController@postDeleteAccount', 'as' => 'delete-account-post']);
Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword', 'as' => 'change-password-post']); Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword', 'as' => 'change-password-post']);
/**
* Reminder Controller
*/
Route::get('/reminders', ['uses' => 'ReminderController@index', 'as' => 'reminders.index']);
Route::get('/reminder/dismiss/{reminder}', ['uses' => 'ReminderController@dismiss', 'as' => 'reminders.dismiss']);
Route::get('/reminder/act/{reminder}', ['uses' => 'ReminderController@act', 'as' => 'reminders.act']);
Route::get('/reminder/{reminder}', ['uses' => 'ReminderController@show', 'as' => 'reminders.show']);
/** /**
* Report Controller * Report Controller
*/ */

View File

@ -180,6 +180,20 @@ class Account extends Model
return $value; return $value;
} }
/**
*
* @return string
*/
public function getNameForEditformAttribute()
{
$name = $this->name;
if ($this->accountType->type == 'Cash account') {
$name = '';
}
return $name;
}
/** /**
* @codeCoverageIgnore * @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany * @return \Illuminate\Database\Eloquent\Relations\HasMany

View File

@ -6,7 +6,7 @@ use Watson\Validating\ValidatingTrait;
/** /**
* Class AccountMeta * Class AccountMeta
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/** /**
* Class AccountType * Class AccountType
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Model;
* FireflyIII\Models\Bill * FireflyIII\Models\Bill
* *
* @codeCoverageIgnore Class Bill * @codeCoverageIgnore Class Bill
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at

View File

@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class Budget * Class Budget
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/** /**
* Class BudgetLimit * Class BudgetLimit
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class Component * Class Component
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/** /**
* Class LimitRepetition * Class LimitRepetition
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class PiggyBank * Class PiggyBank
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
@ -19,15 +19,11 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @property string $targetamount_encrypted * @property string $targetamount_encrypted
* @property \Carbon\Carbon $startdate * @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $targetdate * @property \Carbon\Carbon $targetdate
* @property string $reminder
* @property integer $reminder_skip
* @property boolean $remind_me
* @property integer $order * @property integer $order
* @property boolean $encrypted * @property boolean $encrypted
* @property-read \FireflyIII\Models\Account $account * @property-read \FireflyIII\Models\Account $account
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankRepetition[] $piggyBankRepetitions * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankRepetition[] $piggyBankRepetitions
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Reminder[] $reminders
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereId($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereUpdatedAt($value)
@ -38,9 +34,6 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetamountEncrypted($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetamountEncrypted($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereStartdate($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetdate($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereTargetdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminder($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereReminderSkip($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereRemindMe($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereOrder($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereOrder($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\PiggyBank whereEncrypted($value)
* @property PiggyBankRepetition currentRep * @property PiggyBankRepetition currentRep
@ -50,7 +43,7 @@ class PiggyBank extends Model
use SoftDeletes; use SoftDeletes;
protected $fillable protected $fillable
= ['name', 'account_id', 'order', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me']; = ['name', 'account_id', 'order', 'targetamount', 'startdate', 'targetdate', 'remind_me', 'reminder_skip'];
protected $hidden = ['targetamount_encrypted', 'encrypted']; protected $hidden = ['targetamount_encrypted', 'encrypted'];
/** /**
@ -112,17 +105,6 @@ class PiggyBank extends Model
return $value; return $value;
} }
/**
*
* @param $value
*
* @return boolean
*/
public function getRemindMeAttribute($value)
{
return intval($value) == 1;
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\HasMany * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/ */
@ -131,14 +113,6 @@ class PiggyBank extends Model
return $this->hasMany('FireflyIII\Models\PiggyBankEvent'); return $this->hasMany('FireflyIII\Models\PiggyBankEvent');
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function reminders()
{
return $this->morphMany('FireflyIII\Models\Reminder', 'remindersable');
}
/** /**
* *
* @param $value * @param $value

View File

@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/** /**
* Class PiggyBankEvent * Class PiggyBankEvent
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -7,7 +7,7 @@ use Illuminate\Database\Eloquent\Model;
/** /**
* Class PiggyBankRepetition * Class PiggyBankRepetition
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Model;
/** /**
* Class Preference * Class Preference
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -1,148 +0,0 @@
<?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Crypt;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model;
/**
* Class Reminder
*
* @codeCoverageIgnore
* @package FireflyIII\Models
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $enddate
* @property boolean $active
* @property boolean $notnow
* @property integer $remindersable_id
* @property string $remindersable_type
* @property string $metadata
* @property boolean $encrypted
* @property-read \ $remindersable
* @property-read \FireflyIII\User $user
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereActive($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereNotnow($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereRemindersableId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereRemindersableType($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereMetadata($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Reminder whereEncrypted($value)
* @method static \FireflyIII\Models\Reminder onDates($start, $end)
* @method static \FireflyIII\Models\Reminder today()
* @property string description
*/
class Reminder extends Model
{
protected $fillable = ['user_id', 'startdate', 'metadata', 'enddate', 'active', 'notnow', 'remindersable_id', 'remindersable_type',];
protected $hidden = ['encrypted'];
/**
*
* @param $value
*
* @return int
*/
public function getActiveAttribute($value)
{
return intval($value) == 1;
}
/**
* @return array
*/
public function getDates()
{
return ['created_at', 'updated_at', 'startdate', 'enddate'];
}
/**
*
* @param $value
*
* @return mixed
*/
public function getMetadataAttribute($value)
{
if (intval($this->encrypted) == 1) {
return json_decode(Crypt::decrypt($value));
}
return json_decode($value);
}
/**
*
* @param $value
*
* @return bool
*/
public function getNotnowAttribute($value)
{
return intval($value) == 1;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function remindersable()
{
return $this->morphTo();
}
/**
*
* @param EloquentBuilder $query
* @param Carbon $start
* @param Carbon $end
*
* @return $this
*/
public function scopeOnDates(EloquentBuilder $query, Carbon $start, Carbon $end)
{
return $query->where('reminders.startdate', '=', $start->format('Y-m-d 00:00:00'))->where('reminders.enddate', '=', $end->format('Y-m-d 00:00:00'));
}
/**
*
* @param EloquentBuilder $query
*
* @return $this
*/
public function scopeToday(EloquentBuilder $query)
{
$today = new Carbon;
return $query->where('startdate', '<=', $today->format('Y-m-d 00:00:00'))->where('enddate', '>=', $today->format('Y-m-d 00:00:00'))->where('active', 1)
->where('notnow', 0);
}
/**
*
* @param $value
*/
public function setMetadataAttribute($value)
{
$this->attributes['encrypted'] = true;
$this->attributes['metadata'] = Crypt::encrypt(json_encode($value));
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('FireflyIII\User');
}
}

View File

@ -9,7 +9,7 @@ use Watson\Validating\ValidatingTrait;
/** /**
* Class Transaction * Class Transaction
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class TransactionCurrency * Class TransactionCurrency
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class TransactionGroup * Class TransactionGroup
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -159,12 +159,12 @@ class TransactionJournal extends Model
} }
} }
if ($this->tag_count === 1) { if (intval($this->tag_count) === 1) {
// get amount for single tag: // get amount for single tag:
$amount = $this->amountByTag($this->tags()->first(), $amount); $amount = $this->amountByTag($this->tags()->first(), $amount);
} }
if ($this->tag_count > 1) { if (intval($this->tag_count) > 1) {
// get amount for either tag. // get amount for either tag.
$amount = $this->amountByTags($amount); $amount = $this->amountByTags($amount);

View File

@ -5,7 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/** /**
* Class TransactionRelation * Class TransactionRelation
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
*/ */
class TransactionRelation extends Model class TransactionRelation extends Model

View File

@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/** /**
* Class TransactionType * Class TransactionType
* *
* @codeCoverageIgnore * @codeCoverageIgnore
* @package FireflyIII\Models * @package FireflyIII\Models
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at

View File

@ -5,7 +5,6 @@ use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\LimitRepetition; use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition; use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\Reminder;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Support\Facades\Navigation; use FireflyIII\Support\Facades\Navigation;
@ -53,8 +52,6 @@ class EventServiceProvider extends ServiceProvider
$this->registerCreateEvents(); $this->registerCreateEvents();
BudgetLimit::saved( BudgetLimit::saved(
function (BudgetLimit $budgetLimit) { function (BudgetLimit $budgetLimit) {
Log::debug('Saved!');
$end = Navigation::addPeriod(clone $budgetLimit->startdate, $budgetLimit->repeat_freq, 0); $end = Navigation::addPeriod(clone $budgetLimit->startdate, $budgetLimit->repeat_freq, 0);
$end->subDay(); $end->subDay();
$set = $budgetLimit->limitrepetitions() $set = $budgetLimit->limitrepetitions()
@ -101,15 +98,6 @@ class EventServiceProvider extends ServiceProvider
} }
} }
); );
PiggyBank::deleting(
function (PiggyBank $piggyBank) {
$reminders = $piggyBank->reminders()->get();
/** @var Reminder $reminder */
foreach ($reminders as $reminder) {
$reminder->delete();
}
}
);
Account::deleted( Account::deleted(
function (Account $account) { function (Account $account) {

View File

@ -89,12 +89,19 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository'); $this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository');
$this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository'); $this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository');
$this->app->bind('FireflyIII\Repositories\Tag\TagRepositoryInterface', 'FireflyIII\Repositories\Tag\TagRepository'); $this->app->bind('FireflyIII\Repositories\Tag\TagRepositoryInterface', 'FireflyIII\Repositories\Tag\TagRepository');
$this->app->bind('FireflyIII\Repositories\Reminder\ReminderRepositoryInterface', 'FireflyIII\Repositories\Reminder\ReminderRepository');
$this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search'); $this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search');
// 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');
$this->app->bind('FireflyIII\Generator\Chart\Category\CategoryChartGenerator', 'FireflyIII\Generator\Chart\Category\ChartJsCategoryChartGenerator');
$this->app->bind('FireflyIII\Generator\Chart\PiggyBank\PiggyBankChartGenerator', 'FireflyIII\Generator\Chart\PiggyBank\ChartJsPiggyBankChartGenerator');
$this->app->bind('FireflyIII\Generator\Chart\Report\ReportChartGenerator', 'FireflyIII\Generator\Chart\Report\ChartJsReportChartGenerator');
$this->app->bind('FireflyIII\Helpers\Help\HelpInterface', 'FireflyIII\Helpers\Help\Help'); $this->app->bind('FireflyIII\Helpers\Help\HelpInterface', 'FireflyIII\Helpers\Help\Help');
$this->app->bind('FireflyIII\Helpers\Reminders\ReminderHelperInterface', 'FireflyIII\Helpers\Reminders\ReminderHelper');
$this->app->bind('FireflyIII\Helpers\Report\ReportHelperInterface', 'FireflyIII\Helpers\Report\ReportHelper'); $this->app->bind('FireflyIII\Helpers\Report\ReportHelperInterface', 'FireflyIII\Helpers\Report\ReportHelper');
$this->app->bind('FireflyIII\Helpers\Report\ReportQueryInterface', 'FireflyIII\Helpers\Report\ReportQuery'); $this->app->bind('FireflyIII\Helpers\Report\ReportQueryInterface', 'FireflyIII\Helpers\Report\ReportQuery');

View File

@ -225,6 +225,7 @@ class AccountRepository implements AccountRepositoryInterface
$accountIds = DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id']); $accountIds = DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id']);
$accounts = new Collection; $accounts = new Collection;
/** @var PiggyBank $id */
foreach ($accountIds as $id) { foreach ($accountIds as $id) {
$ids[] = intval($id->account_id); $ids[] = intval($id->account_id);
} }
@ -432,7 +433,6 @@ class AccountRepository implements AccountRepositoryInterface
$account->virtual_balance = $data['virtualBalance']; $account->virtual_balance = $data['virtualBalance'];
$account->save(); $account->save();
// update meta data:
$this->updateMetadata($account, $data); $this->updateMetadata($account, $data);
$openingBalance = $this->openingBalanceTransaction($account); $openingBalance = $this->openingBalanceTransaction($account);

View File

@ -26,21 +26,6 @@ use Log;
class JournalRepository implements JournalRepositoryInterface class JournalRepository implements JournalRepositoryInterface
{ {
/**
* @param int $reminderId
*
* @return boolean|null
*/
public function deactivateReminder($reminderId)
{
$reminder = Auth::user()->reminders()->find($reminderId);
if ($reminder) {
$reminder->active = 0;
$reminder->save();
}
}
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal
* *

View File

@ -16,13 +16,6 @@ use Illuminate\Support\Collection;
*/ */
interface JournalRepositoryInterface interface JournalRepositoryInterface
{ {
/**
* @param int $reminderId
*
* @return bool
*/
public function deactivateReminder($reminderId);
/** /**
* @param TransactionJournal $journal * @param TransactionJournal $journal
* *

View File

@ -116,8 +116,10 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
*/ */
public function store(array $data) public function store(array $data)
{ {
$data['remind_me'] = isset($data['remind_me']) && $data['remind_me'] == '1' ? true : false; $data['remind_me'] = false;
$piggyBank = PiggyBank::create($data); $data['reminder_skip'] = 0;
$piggyBank = PiggyBank::create($data);
return $piggyBank; return $piggyBank;
} }
@ -130,21 +132,12 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
*/ */
public function update(PiggyBank $piggyBank, array $data) public function update(PiggyBank $piggyBank, array $data)
{ {
/**
* 'rep_length' => $request->get('rep_length'),
* 'rep_every' => intval($request->get('rep_every')),
* 'rep_times' => intval($request->get('rep_times')),
* 'remind_me' => intval($request->get('remind_me')) == 1 ? true : false ,
* 'reminder' => $request->get('reminder'),
*/
$piggyBank->name = $data['name']; $piggyBank->name = $data['name'];
$piggyBank->account_id = intval($data['account_id']); $piggyBank->account_id = intval($data['account_id']);
$piggyBank->targetamount = floatval($data['targetamount']); $piggyBank->targetamount = floatval($data['targetamount']);
$piggyBank->targetdate = $data['targetdate']; $piggyBank->targetdate = $data['targetdate'];
$piggyBank->reminder = $data['reminder'];
$piggyBank->startdate = $data['startdate']; $piggyBank->startdate = $data['startdate'];
$piggyBank->remind_me = isset($data['remind_me']) && $data['remind_me'] == '1' ? 1 : 0;
$piggyBank->save(); $piggyBank->save();

View File

@ -4,7 +4,6 @@ namespace FireflyIII\Repositories\PiggyBank;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Models\PiggyBankRepetition; use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\Reminder;
/** /**
* Class PiggyBankPart * Class PiggyBankPart
@ -20,8 +19,6 @@ class PiggyBankPart
public $cumulativeAmount; public $cumulativeAmount;
/** @var float */ /** @var float */
public $currentamount; public $currentamount;
/** @var Reminder */
public $reminder;
/** @var PiggyBankRepetition */ /** @var PiggyBankRepetition */
public $repetition; public $repetition;
@ -33,25 +30,19 @@ class PiggyBankPart
public $targetdate; public $targetdate;
/** /**
* @return Reminder * @return PiggyBankRepetition
*/ */
public function getReminder() public function getRepetition()
{ {
if (is_null($this->reminder)) { return $this->repetition;
$this->reminder = $this->repetition->piggyBank->reminders()->where('startdate', $this->getStartdate()->format('Y-m-d'))->where(
'enddate', $this->getTargetdate()->format('Y-m-d')
)->first();
}
return $this->reminder;
} }
/** /**
* @param Reminder $reminder * @param PiggyBankRepetition $repetition
*/ */
public function setReminder($reminder) public function setRepetition($repetition)
{ {
$this->reminder = $reminder; $this->repetition = $repetition;
} }
/** /**
@ -86,30 +77,6 @@ class PiggyBankPart
$this->targetdate = $targetdate; $this->targetdate = $targetdate;
} }
/**
* @return PiggyBankRepetition
*/
public function getRepetition()
{
return $this->repetition;
}
/**
* @param PiggyBankRepetition $repetition
*/
public function setRepetition($repetition)
{
$this->repetition = $repetition;
}
/**
* @return bool
*/
public function hasReminder()
{
return !is_null($this->reminder);
}
/** /**
* @return float|int * @return float|int
*/ */

View File

@ -1,116 +0,0 @@
<?php
namespace FireflyIII\Repositories\Reminder;
use App;
use Auth;
use Carbon\Carbon;
use FireflyIII\Models\Reminder;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
/**
* Class ReminderRepository
*
* @package FireflyIII\Repositories\Reminder
*/
class ReminderRepository implements ReminderRepositoryInterface
{
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface */
protected $helper;
/**
* @codeCoverageIgnore
*/
public function __construct()
{
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface helper */
$this->helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface');
}
/**
* @return Collection
*/
public function getActiveReminders()
{
$today = new Carbon;
// active reminders:
$active = Auth::user()->reminders()
->where('notnow', 0)
->where('active', 1)
->where('startdate', '<=', $today->format('Y-m-d 00:00:00'))
->where('enddate', '>=', $today->format('Y-m-d 00:00:00'))
->get();
$active->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $active;
}
/**
* @return Collection
*/
public function getDismissedReminders()
{
$dismissed = Auth::user()->reminders()
->where('notnow', 1)
->get();
$dismissed->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $dismissed;
}
/**
* @return Collection
*/
public function getExpiredReminders()
{
$expired = Auth::user()->reminders()
->where('notnow', 0)
->where('active', 1)
->where(
function (Builder $q) {
$today = new Carbon;
$q->where('startdate', '>', $today->format('Y-m-d 00:00:00'));
$q->orWhere('enddate', '<', $today->format('Y-m-d 00:00:00'));
}
)->get();
$expired->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $expired;
}
/**
* @return Collection
*/
public function getInactiveReminders()
{
$inactive = Auth::user()->reminders()
->where('active', 0)
->get();
$inactive->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $inactive;
}
}

View File

@ -1,35 +0,0 @@
<?php
namespace FireflyIII\Repositories\Reminder;
use Illuminate\Support\Collection;
/**
* Interface ReminderRepositoryInterface
*
* @package FireflyIII\Repositories\Reminder
*/
interface ReminderRepositoryInterface
{
/**
* @return Collection
*/
public function getActiveReminders();
/**
* @return Collection
*/
public function getDismissedReminders();
/**
* @return Collection
*/
public function getExpiredReminders();
/**
* @return Collection
*/
public function getInactiveReminders();
}

View File

@ -40,7 +40,7 @@ class ExpandedForm
$currencies = Amt::getAllCurrencies(); $currencies = Amt::getAllCurrencies();
unset($options['currency']); unset($options['currency']);
unset($options['placeholder']); unset($options['placeholder']);
$html = View::make('form.amount', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render(); $html = View::make('form.amount', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
return $html; return $html;
@ -144,7 +144,7 @@ class ExpandedForm
$currencies = Amt::getAllCurrencies(); $currencies = Amt::getAllCurrencies();
unset($options['currency']); unset($options['currency']);
unset($options['placeholder']); unset($options['placeholder']);
$html = View::make('form.balance', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render(); $html = View::make('form.balance', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
return $html; return $html;
} }
@ -186,7 +186,7 @@ class ExpandedForm
$classes = $this->getHolderClasses($name); $classes = $this->getHolderClasses($name);
$value = $this->fillFieldValue($name, $value); $value = $this->fillFieldValue($name, $value);
unset($options['placeholder']); unset($options['placeholder']);
$html = View::make('form.date', compact('classes', 'name', 'label', 'value', 'options'))->render(); $html = View::make('form.date', compact('classes', 'name', 'label', 'value', 'options'))->render();
return $html; return $html;
} }
@ -323,7 +323,7 @@ class ExpandedForm
$selected = $this->fillFieldValue($name, $selected); $selected = $this->fillFieldValue($name, $selected);
unset($options['autocomplete']); unset($options['autocomplete']);
unset($options['placeholder']); unset($options['placeholder']);
$html = View::make('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render(); $html = View::make('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
return $html; return $html;
} }

View File

@ -83,7 +83,7 @@ class Navigation
$subDay = ['week', 'weekly', '1W', 'month', 'monthly', '1M', '3M', 'quarter', 'quarterly', '6M', 'half-year', 'year', 'yearly']; $subDay = ['week', 'weekly', '1W', 'month', 'monthly', '1M', '3M', 'quarter', 'quarterly', '6M', 'half-year', 'year', 'yearly'];
if (!isset($functionMap[$repeatFreq])) { if (!isset($functionMap[$repeatFreq])) {
throw new FireflyException('Cannot do endOfPeriod for $repeat_freq ' . $repeatFreq); throw new FireflyException('Cannot do endOfPeriod for $repeat_freq "' . $repeatFreq.'"');
} }
$function = $functionMap[$repeatFreq]; $function = $functionMap[$repeatFreq];
if (isset($modifierMap[$repeatFreq])) { if (isset($modifierMap[$repeatFreq])) {
@ -119,7 +119,6 @@ class Navigation
'year' => 'endOfYear', 'year' => 'endOfYear',
'yearly' => 'endOfYear', 'yearly' => 'endOfYear',
]; ];
$specials = ['mont', 'monthly'];
$currentEnd = clone $theCurrentEnd; $currentEnd = clone $theCurrentEnd;
@ -128,12 +127,7 @@ class Navigation
$currentEnd->$function(); $currentEnd->$function();
} }
if (isset($specials[$repeatFreq])) {
$currentEnd->endOfYear();
if ($theCurrentEnd->month <= 6) {
$currentEnd->subMonths(6);
}
}
if ($currentEnd > $maxDate) { if ($currentEnd > $maxDate) {
return clone $maxDate; return clone $maxDate;
} }
@ -142,7 +136,7 @@ class Navigation
} }
/** /**
* @param Carbon $date * @param \Carbon\Carbon $date
* @param $repeatFrequency * @param $repeatFrequency
* *
* @return string * @return string
@ -210,7 +204,7 @@ class Navigation
return $date; return $date;
} }
throw new FireflyException('Cannot do startOfPeriod for $repeat_freq ' . $repeatFreq); throw new FireflyException('Cannot do startOfPeriod for $repeat_freq "' . $repeatFreq.'"');
} }
/** /**
@ -252,7 +246,7 @@ class Navigation
return $date; return $date;
} }
throw new FireflyException('Cannot do subtractPeriod for $repeat_freq ' . $repeatFreq); throw new FireflyException('Cannot do subtractPeriod for $repeat_freq "' . $repeatFreq.'"');
} }
/** /**
@ -288,7 +282,7 @@ class Navigation
return $end; return $end;
} }
throw new FireflyException('updateEndDate cannot handle $range ' . $range); throw new FireflyException('updateEndDate cannot handle $range "' . $range.'"');
} }
/** /**
@ -322,7 +316,7 @@ class Navigation
return $start; return $start;
} }
throw new FireflyException('updateStartDate cannot handle $range ' . $range); throw new FireflyException('updateStartDate cannot handle $range "' . $range.'"');
} }

View File

@ -35,7 +35,7 @@ class Steam
bcscale(2); bcscale(2);
$balance = $account->transactions()->leftJoin( $balance = $account->transactions()->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount'); )->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount');

View File

@ -9,6 +9,7 @@ use Twig_Extension;
use Twig_SimpleFunction; use Twig_SimpleFunction;
/** /**
* @codeCoverageIgnore
* Class Budget * Class Budget
* *
* @package FireflyIII\Support\Twig * @package FireflyIII\Support\Twig

View File

@ -14,6 +14,8 @@ use Twig_SimpleFilter;
use Twig_SimpleFunction; use Twig_SimpleFunction;
/** /**
* @codeCoverageIgnore
*
* Class TwigSupport * Class TwigSupport
* *
* @package FireflyIII\Support * @package FireflyIII\Support
@ -204,10 +206,10 @@ class General extends Twig_Extension
$route = $args[0]; // name of the route. $route = $args[0]; // name of the route.
if (Route::getCurrentRoute()->getName() == $route) { if (Route::getCurrentRoute()->getName() == $route) {
return 'active because-route-matches-strict'; return 'active';
} }
return 'not-xxx-at-all'; return '';
} }
); );
} }
@ -225,10 +227,10 @@ class General extends Twig_Extension
$args = func_get_args(); $args = func_get_args();
$route = $args[0]; // name of the route. $route = $args[0]; // name of the route.
if (!(strpos(Route::getCurrentRoute()->getName(), $route) === false)) { if (!(strpos(Route::getCurrentRoute()->getName(), $route) === false)) {
return 'active because-route-matches-non-strict'; return 'active';
} }
return 'not-xxx-at-all'; return '';
} }
); );
} }
@ -249,10 +251,10 @@ class General extends Twig_Extension
$activeWhat = isset($context['what']) ? $context['what'] : false; $activeWhat = isset($context['what']) ? $context['what'] : false;
if ($what == $activeWhat && !(strpos(Route::getCurrentRoute()->getName(), $route) === false)) { if ($what == $activeWhat && !(strpos(Route::getCurrentRoute()->getName(), $route) === false)) {
return 'active because-route-matches-non-strict-what'; return 'active';
} }
return 'not-xxx-at-all'; return '';
}, ['needs_context' => true] }, ['needs_context' => true]
); );
} }

View File

@ -12,6 +12,8 @@ use Twig_SimpleFilter;
use Twig_SimpleFunction; use Twig_SimpleFunction;
/** /**
* @codeCoverageIgnore
*
* Class Journal * Class Journal
* *
* @package FireflyIII\Support\Twig * @package FireflyIII\Support\Twig
@ -71,16 +73,16 @@ class Journal extends Twig_Extension
switch ($type) { switch ($type) {
case 'Withdrawal': case 'Withdrawal':
$txt = '<span class="glyphicon glyphicon-arrow-left" title="' . trans('firefly.withdrawal') . '"></span>'; $txt = '<i class="fa fa-long-arrow-left fa-fw" title="' . trans('firefly.withdrawal') . '"></i>';
break; break;
case 'Deposit': case 'Deposit':
$txt = '<span class="glyphicon glyphicon-arrow-right" title="' . trans('firefly.deposit') . '"></span>'; $txt = '<i class="fa fa-long-arrow-right fa-fw" title="' . trans('firefly.deposit') . '"></i>';
break; break;
case 'Transfer': case 'Transfer':
$txt = '<i class="fa fa-fw fa-exchange" title="' . trans('firefly.transfer') . '"></i>'; $txt = '<i class="fa fa-fw fa-exchange" title="' . trans('firefly.transfer') . '"></i>';
break; break;
case 'Opening balance': case 'Opening balance':
$txt = '<span class="glyphicon glyphicon-ban-circle" title="' . trans('firefly.openingBalance') . '"></span>'; $txt = '<i class="fa-fw fa fa-ban" title="' . trans('firefly.openingBalance') . '"></i>';
break; break;
default: default:
$txt = ''; $txt = '';

View File

@ -7,6 +7,8 @@ use Twig_Extension;
use Twig_SimpleFunction; use Twig_SimpleFunction;
/** /**
* @codeCoverageIgnore
*
* Class PiggyBank * Class PiggyBank
* *
* @package FireflyIII\Support\Twig * @package FireflyIII\Support\Twig

View File

@ -6,6 +6,8 @@ use Twig_Extension;
use Twig_SimpleFilter; use Twig_SimpleFilter;
/** /**
* @codeCoverageIgnore
*
* Class Budget * Class Budget
* *
* @package FireflyIII\Support\Twig * @package FireflyIII\Support\Twig

View File

@ -10,6 +10,8 @@ use Zizaco\Entrust\Traits\EntrustUserTrait;
/** /**
* Class User * Class User
* *
* @codeCoverageIgnore
*
* @package FireflyIII * @package FireflyIII
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
@ -24,7 +26,6 @@ use Zizaco\Entrust\Traits\EntrustUserTrait;
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Budget[] $budgets * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[] $categories * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Preference[] $preferences * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Preference[] $preferences
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Reminder[] $reminders
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournal[] $transactionjournals
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereId($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\FireflyIII\User whereCreatedAt($value)
@ -123,14 +124,6 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return $this->hasMany('FireflyIII\Models\Preference'); return $this->hasMany('FireflyIII\Models\Preference');
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function reminders()
{
return $this->hasMany('FireflyIII\Models\Reminder');
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\HasMany * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/ */

View File

@ -3,16 +3,15 @@
namespace FireflyIII\Validation; namespace FireflyIII\Validation;
use Auth; use Auth;
use Carbon\Carbon;
use Config; use Config;
use Crypt; use Crypt;
use DB; use DB;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Models\PiggyBank;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Validation\Validator; use Illuminate\Validation\Validator;
use Navigation;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
/** /**
@ -55,35 +54,6 @@ class FireflyValidator extends Validator
} }
/**
* @return bool
*/
public function validatePiggyBankReminder()
{
$array = $this->data;
// no reminder? dont care.
if (!isset($array['remind_me'])) {
return true;
}
// get or set start date & target date:
$startDate = isset($array['startdate']) ? new Carbon($array['startdate']) : new Carbon;
$targetDate = isset($array['targetdate']) && strlen($array['targetdate']) > 0 ? new Carbon($array['targetdate']) : null;
// target date is null? reminder period is always good.
if ($array['remind_me'] == '1' && is_null($targetDate)) {
return true;
}
$nextReminder = Navigation::addPeriod($startDate, $array['reminder'], 0);
// reminder is beyond target?
if ($nextReminder > $targetDate) {
return false;
}
return true;
}
/** /**
* @param $attribute * @param $attribute
* @param $value * @param $value
@ -105,6 +75,10 @@ class FireflyValidator extends Validator
if (isset($this->data['account_type_id'])) { if (isset($this->data['account_type_id'])) {
return $this->validateByAccountTypeId($value, $parameters); return $this->validateByAccountTypeId($value, $parameters);
} }
if (isset($this->data['id'])) {
return $this->validateByAccountId($value);
}
return false; return false;
} }
@ -197,6 +171,33 @@ class FireflyValidator extends Validator
} }
/**
* @param $value
* @param $parameters
*
* @return bool
*/
protected function validateByAccountId($value)
{
/** @var Account $existingAccount */
$existingAccount = Account::find($this->data['id']);
$type = $existingAccount->accountType;
$ignore = $existingAccount->id;
$value = $this->tryDecrypt($value);
$set = Auth::user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get();
/** @var Account $entry */
foreach ($set as $entry) {
if ($entry->name == $value) {
return false;
}
}
return true;
}
/** /**
* @param $attribute * @param $attribute
* @param $value * @param $value
@ -273,6 +274,7 @@ class FireflyValidator extends Validator
} }
$set = $query->get(['piggy_banks.*']); $set = $query->get(['piggy_banks.*']);
/** @var PiggyBank $entry */
foreach ($set as $entry) { foreach ($set as $entry) {
$fieldValue = $this->tryDecrypt($entry->name); $fieldValue = $this->tryDecrypt($entry->name);
if ($fieldValue == $value) { if ($fieldValue == $value) {

View File

@ -28,7 +28,6 @@ $app = new Illuminate\Foundation\Application(
*/ */
$app->singleton( $app->singleton(
'Illuminate\Contracts\Http\Kernel', 'Illuminate\Contracts\Http\Kernel',
'FireflyIII\Http\Kernel' 'FireflyIII\Http\Kernel'
@ -45,8 +44,6 @@ $app->singleton(
); );
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Return The Application | Return The Application

View File

@ -14,7 +14,7 @@ define('LARAVEL_START', microtime(true));
| |
*/ */
require __DIR__.'/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -27,9 +27,8 @@ require __DIR__.'/../vendor/autoload.php';
| |
*/ */
$compiledPath = __DIR__.'/cache/compiled.php'; $compiledPath = __DIR__ . '/cache/compiled.php';
if (file_exists($compiledPath)) if (file_exists($compiledPath)) {
{ require $compiledPath;
require $compiledPath;
} }

View File

@ -2,67 +2,67 @@
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Default Authentication Driver | Default Authentication Driver
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| This option controls the authentication driver that will be utilized. | This option controls the authentication driver that will be utilized.
| This driver manages the retrieval and authentication of the users | This driver manages the retrieval and authentication of the users
| attempting to get access to protected areas of your application. | attempting to get access to protected areas of your application.
| |
| Supported: "database", "eloquent" | Supported: "database", "eloquent"
| |
*/ */
'driver' => 'eloquent', 'driver' => 'eloquent',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Authentication Model | Authentication Model
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| When using the "Eloquent" authentication driver, we need to know which | When using the "Eloquent" authentication driver, we need to know which
| Eloquent model should be used to retrieve your users. Of course, it | Eloquent model should be used to retrieve your users. Of course, it
| is often just the "User" model but you may use whatever you like. | is often just the "User" model but you may use whatever you like.
| |
*/ */
'model' => 'FireflyIII\User', 'model' => 'FireflyIII\User',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Authentication Table | Authentication Table
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| When using the "Database" authentication driver, we need to know which | When using the "Database" authentication driver, we need to know which
| table should be used to retrieve your users. We have chosen a basic | table should be used to retrieve your users. We have chosen a basic
| default value but you may easily change it to any table you like. | default value but you may easily change it to any table you like.
| |
*/ */
'table' => 'users', 'table' => 'users',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Password Reset Settings | Password Reset Settings
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may set the options for resetting passwords including the view | Here you may set the options for resetting passwords including the view
| that is your password reset e-mail. You can also set the name of the | that is your password reset e-mail. You can also set the name of the
| table that maintains all of the reset tokens for your application. | table that maintains all of the reset tokens for your application.
| |
| The expire time is the number of minutes that the reset token should be | The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so | considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed. | they have less time to be guessed. You may change this as needed.
| |
*/ */
'password' => [ 'password' => [
'email' => 'emails.password', 'email' => 'emails.password',
'table' => 'password_resets', 'table' => 'password_resets',
'expire' => 60, 'expire' => 60,
], ],
'allow_register' => true 'allow_register' => true
]; ];

View File

@ -2,6 +2,6 @@
return [ return [
'view' => 'breadcrumbs::bootstrap3', 'view' => 'breadcrumbs::bootstrap3',
]; ];

View File

@ -2,78 +2,78 @@
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Default Cache Store | Default Cache Store
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| This option controls the default cache connection that gets used while | This option controls the default cache connection that gets used while
| using this caching library. This connection is used when another is | using this caching library. This connection is used when another is
| not explicitly specified when executing a given caching function. | not explicitly specified when executing a given caching function.
| |
*/ */
'default' => env('CACHE_DRIVER', 'file'), 'default' => env('CACHE_DRIVER', 'file'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Cache Stores | Cache Stores
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may define all of the cache "stores" for your application as | Here you may define all of the cache "stores" for your application as
| well as their drivers. You may even define multiple stores for the | well as their drivers. You may even define multiple stores for the
| same cache driver to group types of items stored in your caches. | same cache driver to group types of items stored in your caches.
| |
*/ */
'stores' => [ 'stores' => [
'apc' => [ 'apc' => [
'driver' => 'apc' 'driver' => 'apc'
], ],
'array' => [ 'array' => [
'driver' => 'array' 'driver' => 'array'
], ],
'database' => [ 'database' => [
'driver' => 'database', 'driver' => 'database',
'table' => 'cache', 'table' => 'cache',
'connection' => null, 'connection' => null,
], ],
'file' => [ 'file' => [
'driver' => 'file', 'driver' => 'file',
'path' => storage_path().'/framework/cache', 'path' => storage_path() . '/framework/cache',
], ],
'memcached' => [ 'memcached' => [
'driver' => 'memcached', 'driver' => 'memcached',
'servers' => [ 'servers' => [
[ [
'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100 'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100
], ],
], ],
], ],
'redis' => [ 'redis' => [
'driver' => 'redis', 'driver' => 'redis',
'connection' => 'default', 'connection' => 'default',
], ],
], ],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Cache Key Prefix | Cache Key Prefix
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| When utilizing a RAM based store such as APC or Memcached, there might | When utilizing a RAM based store such as APC or Memcached, there might
| be other applications utilizing the same cache. So, we'll specify a | be other applications utilizing the same cache. So, we'll specify a
| value to get prefixed to all our keys so we can avoid collisions. | value to get prefixed to all our keys so we can avoid collisions.
| |
*/ */
'prefix' => 'laravel', 'prefix' => 'laravel',
]; ];

View File

@ -2,40 +2,40 @@
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Additional Compiled Classes | Additional Compiled Classes
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may specify additional classes to include in the compiled file | Here you may specify additional classes to include in the compiled file
| generated by the `artisan optimize` command. These should be classes | generated by the `artisan optimize` command. These should be classes
| that are included on basically every request into the application. | that are included on basically every request into the application.
| |
*/ */
'files' => [ 'files' => [
realpath(__DIR__.'/../app/Providers/AppServiceProvider.php'), realpath(__DIR__ . '/../app/Providers/AppServiceProvider.php'),
realpath(__DIR__.'/../app/Providers/BusServiceProvider.php'), realpath(__DIR__ . '/../app/Providers/BusServiceProvider.php'),
realpath(__DIR__.'/../app/Providers/ConfigServiceProvider.php'), realpath(__DIR__ . '/../app/Providers/ConfigServiceProvider.php'),
realpath(__DIR__.'/../app/Providers/EventServiceProvider.php'), realpath(__DIR__ . '/../app/Providers/EventServiceProvider.php'),
realpath(__DIR__.'/../app/Providers/RouteServiceProvider.php'), realpath(__DIR__ . '/../app/Providers/RouteServiceProvider.php'),
], ],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Compiled File Providers | Compiled File Providers
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may list service providers which define a "compiles" function | Here you may list service providers which define a "compiles" function
| that returns additional files that should be compiled, providing an | that returns additional files that should be compiled, providing an
| easy way to get common files from any packages you are utilizing. | easy way to get common files from any packages you are utilizing.
| |
*/ */
'providers' => [ 'providers' => [
// //
], ],
]; ];

View File

@ -48,7 +48,7 @@ return [
'sqlite' => [ 'sqlite' => [
'driver' => 'sqlite', 'driver' => 'sqlite',
'database' => __DIR__.'/../storage/database/testing.db', 'database' => __DIR__ . '/../storage/database/testing.db',
'prefix' => '', 'prefix' => '',
], ],

View File

@ -19,7 +19,7 @@ return [
| the role if it is in a different namespace. | the role if it is in a different namespace.
| |
*/ */
'role' => 'FireflyIII\Models\Role', 'role' => 'FireflyIII\Models\Role',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -29,7 +29,7 @@ return [
| This is the roles table used by Entrust to save roles to the database. | This is the roles table used by Entrust to save roles to the database.
| |
*/ */
'roles_table' => 'roles', 'roles_table' => 'roles',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -40,7 +40,7 @@ return [
| Update the permission if it is in a different namespace. | Update the permission if it is in a different namespace.
| |
*/ */
'permission' => 'FireflyIII\Models\Permission', 'permission' => 'FireflyIII\Models\Permission',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -51,7 +51,7 @@ return [
| database. | database.
| |
*/ */
'permissions_table' => 'permissions', 'permissions_table' => 'permissions',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -73,6 +73,6 @@ return [
| database. | database.
| |
*/ */
'role_user_table' => 'role_user', 'role_user_table' => 'role_user',
]; ];

View File

@ -2,69 +2,69 @@
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Default Filesystem Disk | Default Filesystem Disk
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may specify the default filesystem disk that should be used | Here you may specify the default filesystem disk that should be used
| by the framework. A "local" driver, as well as a variety of cloud | by the framework. A "local" driver, as well as a variety of cloud
| based drivers are available for your choosing. Just store away! | based drivers are available for your choosing. Just store away!
| |
| Supported: "local", "s3", "rackspace" | Supported: "local", "s3", "rackspace"
| |
*/ */
'default' => 'local', 'default' => 'local',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Default Cloud Filesystem Disk | Default Cloud Filesystem Disk
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Many applications store files both locally and in the cloud. For this | Many applications store files both locally and in the cloud. For this
| reason, you may specify a default "cloud" driver here. This driver | reason, you may specify a default "cloud" driver here. This driver
| will be bound as the Cloud disk implementation in the container. | will be bound as the Cloud disk implementation in the container.
| |
*/ */
'cloud' => 's3', 'cloud' => 's3',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Filesystem Disks | Filesystem Disks
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may configure as many filesystem "disks" as you wish, and you | Here you may configure as many filesystem "disks" as you wish, and you
| may even configure multiple disks of the same driver. Defaults have | may even configure multiple disks of the same driver. Defaults have
| been setup for each driver as an example of the required options. | been setup for each driver as an example of the required options.
| |
*/ */
'disks' => [ 'disks' => [
'local' => [ 'local' => [
'driver' => 'local', 'driver' => 'local',
'root' => storage_path().'/app', 'root' => storage_path() . '/app',
], ],
's3' => [ 's3' => [
'driver' => 's3', 'driver' => 's3',
'key' => 'your-key', 'key' => 'your-key',
'secret' => 'your-secret', 'secret' => 'your-secret',
'region' => 'your-region', 'region' => 'your-region',
'bucket' => 'your-bucket', 'bucket' => 'your-bucket',
], ],
'rackspace' => [ 'rackspace' => [
'driver' => 'rackspace', 'driver' => 'rackspace',
'username' => 'your-username', 'username' => 'your-username',
'key' => 'your-key', 'key' => 'your-key',
'container' => 'your-container', 'container' => 'your-container',
'endpoint' => 'https://identity.api.rackspacecloud.com/v2.0/', 'endpoint' => 'https://identity.api.rackspacecloud.com/v2.0/',
'region' => 'IAD', 'region' => 'IAD',
], ],
], ],
]; ];

View File

@ -1,7 +1,8 @@
<?php <?php
return [ return [
'version' => '3.4.5', 'chart' => 'chartjs', // or 'chartjs'
'version' => '3.4.6',
'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'], 'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'],
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'], 'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'piggy_bank_periods' => [ 'piggy_bank_periods' => [
@ -57,7 +58,7 @@ return [
'asset' => 'Asset accounts', 'asset' => 'Asset accounts',
'expense' => 'Expense accounts', 'expense' => 'Expense accounts',
'revenue' => 'Revenue accounts', 'revenue' => 'Revenue accounts',
'cash' => 'Cash accounts', 'cash' => 'Cash accounts',
], ],
'subIconsByIdentifier' => 'subIconsByIdentifier' =>
[ [

View File

@ -2,91 +2,91 @@
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Default Queue Driver | Default Queue Driver
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The Laravel queue API supports a variety of back-ends via an unified | The Laravel queue API supports a variety of back-ends via an unified
| API, giving you convenient access to each back-end using the same | API, giving you convenient access to each back-end using the same
| syntax for each one. Here you may set the default queue driver. | syntax for each one. Here you may set the default queue driver.
| |
| Supported: "null", "sync", "database", "beanstalkd", | Supported: "null", "sync", "database", "beanstalkd",
| "sqs", "iron", "redis" | "sqs", "iron", "redis"
| |
*/ */
'default' => env('QUEUE_DRIVER', 'sync'), 'default' => env('QUEUE_DRIVER', 'sync'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Queue Connections | Queue Connections
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may configure the connection information for each server that | Here you may configure the connection information for each server that
| is used by your application. A default configuration has been added | is used by your application. A default configuration has been added
| for each back-end shipped with Laravel. You are free to add more. | for each back-end shipped with Laravel. You are free to add more.
| |
*/ */
'connections' => [ 'connections' => [
'sync' => [ 'sync' => [
'driver' => 'sync', 'driver' => 'sync',
], ],
'database' => [ 'database' => [
'driver' => 'database', 'driver' => 'database',
'table' => 'jobs', 'table' => 'jobs',
'queue' => 'default', 'queue' => 'default',
'expire' => 60, 'expire' => 60,
], ],
'beanstalkd' => [ 'beanstalkd' => [
'driver' => 'beanstalkd', 'driver' => 'beanstalkd',
'host' => 'localhost', 'host' => 'localhost',
'queue' => 'default', 'queue' => 'default',
'ttr' => 60, 'ttr' => 60,
], ],
'sqs' => [ 'sqs' => [
'driver' => 'sqs', 'driver' => 'sqs',
'key' => 'your-public-key', 'key' => 'your-public-key',
'secret' => 'your-secret-key', 'secret' => 'your-secret-key',
'queue' => 'your-queue-url', 'queue' => 'your-queue-url',
'region' => 'us-east-1', 'region' => 'us-east-1',
], ],
'iron' => [ 'iron' => [
'driver' => 'iron', 'driver' => 'iron',
'host' => 'mq-aws-us-east-1.iron.io', 'host' => 'mq-aws-us-east-1.iron.io',
'token' => 'your-token', 'token' => 'your-token',
'project' => 'your-project-id', 'project' => 'your-project-id',
'queue' => 'your-queue-name', 'queue' => 'your-queue-name',
'encrypt' => true, 'encrypt' => true,
], ],
'redis' => [ 'redis' => [
'driver' => 'redis', 'driver' => 'redis',
'queue' => 'default', 'queue' => 'default',
'expire' => 60, 'expire' => 60,
], ],
], ],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Failed Queue Jobs | Failed Queue Jobs
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| These options configure the behavior of failed queue job logging so you | These options configure the behavior of failed queue job logging so you
| can control which database and table are used to store the jobs that | can control which database and table are used to store the jobs that
| have failed. You may change them to any database / table you wish. | have failed. You may change them to any database / table you wish.
| |
*/ */
'failed' => [ 'failed' => [
'database' => 'mysql', 'table' => 'failed_jobs', 'database' => 'mysql', 'table' => 'failed_jobs',
], ],
]; ];

View File

@ -2,36 +2,36 @@
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Third Party Services | Third Party Services
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| This file is for storing the credentials for third party services such | This file is for storing the credentials for third party services such
| as Stripe, Mailgun, Mandrill, and others. This file provides a sane | as Stripe, Mailgun, Mandrill, and others. This file provides a sane
| default location for this type of information, allowing packages | default location for this type of information, allowing packages
| to have a conventional place to find your various credentials. | to have a conventional place to find your various credentials.
| |
*/ */
'mailgun' => [ 'mailgun' => [
'domain' => '', 'domain' => '',
'secret' => '', 'secret' => '',
], ],
'mandrill' => [ 'mandrill' => [
'secret' => '', 'secret' => '',
], ],
'ses' => [ 'ses' => [
'key' => '', 'key' => '',
'secret' => '', 'secret' => '',
'region' => 'us-east-1', 'region' => 'us-east-1',
], ],
'stripe' => [ 'stripe' => [
'model' => 'User', 'model' => 'User',
'secret' => '', 'secret' => '',
], ],
]; ];

View File

@ -2,152 +2,152 @@
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Default Session Driver | Default Session Driver
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| This option controls the default session "driver" that will be used on | This option controls the default session "driver" that will be used on
| requests. By default, we will use the lightweight native driver but | requests. By default, we will use the lightweight native driver but
| you may specify any of the other wonderful drivers provided here. | you may specify any of the other wonderful drivers provided here.
| |
| Supported: "file", "cookie", "database", "apc", | Supported: "file", "cookie", "database", "apc",
| "memcached", "redis", "array" | "memcached", "redis", "array"
| |
*/ */
'driver' => env('SESSION_DRIVER', 'file'), 'driver' => env('SESSION_DRIVER', 'file'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Session Lifetime | Session Lifetime
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may specify the number of minutes that you wish the session | Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them | to be allowed to remain idle before it expires. If you want them
| to immediately expire on the browser closing, set that option. | to immediately expire on the browser closing, set that option.
| |
*/ */
'lifetime' => 120, 'lifetime' => 120,
'expire_on_close' => false, 'expire_on_close' => false,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Session Encryption | Session Encryption
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| This option allows you to easily specify that all of your session data | This option allows you to easily specify that all of your session data
| should be encrypted before it is stored. All encryption will be run | should be encrypted before it is stored. All encryption will be run
| automatically by Laravel and you can use the Session like normal. | automatically by Laravel and you can use the Session like normal.
| |
*/ */
'encrypt' => false, 'encrypt' => false,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Session File Location | Session File Location
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| When using the native session driver, we need a location where session | When using the native session driver, we need a location where session
| files may be stored. A default has been set for you but a different | files may be stored. A default has been set for you but a different
| location may be specified. This is only needed for file sessions. | location may be specified. This is only needed for file sessions.
| |
*/ */
'files' => storage_path().'/framework/sessions', 'files' => storage_path() . '/framework/sessions',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Session Database Connection | Session Database Connection
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| When using the "database" or "redis" session drivers, you may specify a | When using the "database" or "redis" session drivers, you may specify a
| connection that should be used to manage these sessions. This should | connection that should be used to manage these sessions. This should
| correspond to a connection in your database configuration options. | correspond to a connection in your database configuration options.
| |
*/ */
'connection' => null, 'connection' => null,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Session Database Table | Session Database Table
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| When using the "database" session driver, you may specify the table we | When using the "database" session driver, you may specify the table we
| should use to manage the sessions. Of course, a sensible default is | should use to manage the sessions. Of course, a sensible default is
| provided for you; however, you are free to change this as needed. | provided for you; however, you are free to change this as needed.
| |
*/ */
'table' => 'sessions', 'table' => 'sessions',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Session Sweeping Lottery | Session Sweeping Lottery
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Some session drivers must manually sweep their storage location to get | Some session drivers must manually sweep their storage location to get
| rid of old sessions from storage. Here are the chances that it will | rid of old sessions from storage. Here are the chances that it will
| happen on a given request. By default, the odds are 2 out of 100. | happen on a given request. By default, the odds are 2 out of 100.
| |
*/ */
'lottery' => [2, 100], 'lottery' => [2, 100],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Session Cookie Name | Session Cookie Name
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may change the name of the cookie used to identify a session | Here you may change the name of the cookie used to identify a session
| instance by ID. The name specified here will get used every time a | instance by ID. The name specified here will get used every time a
| new session cookie is created by the framework for every driver. | new session cookie is created by the framework for every driver.
| |
*/ */
'cookie' => 'laravel_session', 'cookie' => 'laravel_session',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Session Cookie Path | Session Cookie Path
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The session cookie path determines the path for which the cookie will | The session cookie path determines the path for which the cookie will
| be regarded as available. Typically, this will be the root path of | be regarded as available. Typically, this will be the root path of
| your application but you are free to change this when necessary. | your application but you are free to change this when necessary.
| |
*/ */
'path' => '/', 'path' => '/',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Session Cookie Domain | Session Cookie Domain
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may change the domain of the cookie used to identify a session | Here you may change the domain of the cookie used to identify a session
| in your application. This will determine which domains the cookie is | in your application. This will determine which domains the cookie is
| available to in your application. A sensible default has been set. | available to in your application. A sensible default has been set.
| |
*/ */
'domain' => null, 'domain' => null,
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| HTTPS Only Cookies | HTTPS Only Cookies
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| By setting this option to true, session cookies will only be sent back | By setting this option to true, session cookies will only be sent back
| to the server if the browser has a HTTPS connection. This will keep | to the server if the browser has a HTTPS connection. This will keep
| the cookie from being sent to you if it can not be done securely. | the cookie from being sent to you if it can not be done securely.
| |
*/ */
'secure' => false, 'secure' => false,
]; ];

View File

@ -2,32 +2,32 @@
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| View Storage Paths | View Storage Paths
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Most templating systems load templates from disk. Here you may specify | Most templating systems load templates from disk. Here you may specify
| an array of paths that should be checked for your views. Of course | an array of paths that should be checked for your views. Of course
| the usual Laravel view path has already been registered for you. | the usual Laravel view path has already been registered for you.
| |
*/ */
'paths' => [ 'paths' => [
realpath(base_path('resources/twig')) realpath(base_path('resources/twig'))
], ],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Compiled View Path | Compiled View Path
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| This option determines where all the compiled Blade templates will be | This option determines where all the compiled Blade templates will be
| stored for your application. Typically, this is within the storage | stored for your application. Typically, this is within the storage
| directory. However, as usual, you are free to change this value. | directory. However, as usual, you are free to change this value.
| |
*/ */
'compiled' => realpath(storage_path().'/framework/views'), 'compiled' => realpath(storage_path() . '/framework/views'),
]; ];

View File

@ -37,7 +37,7 @@ class CreateTransactionGroupsTable extends Migration
$table->integer('user_id')->unsigned(); $table->integer('user_id')->unsigned();
$table->enum('relation', ['balance']); $table->enum('relation', ['balance']);
// connect reminders to users // connect groups to users
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
} }
); );

View File

@ -57,7 +57,7 @@ class ChangesForV3310 extends Migration
$table->decimal('longitude', 18, 12)->nullable(); $table->decimal('longitude', 18, 12)->nullable();
$table->smallInteger('zoomLevel', false, true)->nullable(); $table->smallInteger('zoomLevel', false, true)->nullable();
// connect reminders to users // connect tags to users
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
} }
); );

View File

@ -7,58 +7,6 @@ use Illuminate\Database\Schema\Blueprint;
*/ */
class EntrustSetupTables extends Migration class EntrustSetupTables extends Migration
{ {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// Create table for storing roles
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->string('display_name')->nullable();
$table->string('description')->nullable();
$table->timestamps();
});
// Create table for associating roles to users (Many-to-Many)
Schema::create('role_user', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('roles')
->onUpdate('cascade')->onDelete('cascade');
$table->primary(['user_id', 'role_id']);
});
// Create table for storing permissions
Schema::create('permissions', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->string('display_name')->nullable();
$table->string('description')->nullable();
$table->timestamps();
});
// Create table for associating permissions to roles (Many-to-Many)
Schema::create('permission_role', function (Blueprint $table) {
$table->integer('permission_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->foreign('permission_id')->references('id')->on('permissions')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('roles')
->onUpdate('cascade')->onDelete('cascade');
$table->primary(['permission_id', 'role_id']);
});
}
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
@ -71,4 +19,64 @@ class EntrustSetupTables extends Migration
Schema::drop('role_user'); Schema::drop('role_user');
Schema::drop('roles'); Schema::drop('roles');
} }
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// Create table for storing roles
Schema::create(
'roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->string('display_name')->nullable();
$table->string('description')->nullable();
$table->timestamps();
}
);
// Create table for associating roles to users (Many-to-Many)
Schema::create(
'role_user', function (Blueprint $table) {
$table->integer('user_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('roles')
->onUpdate('cascade')->onDelete('cascade');
$table->primary(['user_id', 'role_id']);
}
);
// Create table for storing permissions
Schema::create(
'permissions', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
$table->string('display_name')->nullable();
$table->string('description')->nullable();
$table->timestamps();
}
);
// Create table for associating permissions to roles (Many-to-Many)
Schema::create(
'permission_role', function (Blueprint $table) {
$table->integer('permission_id')->unsigned();
$table->integer('role_id')->unsigned();
$table->foreign('permission_id')->references('id')->on('permissions')
->onUpdate('cascade')->onDelete('cascade');
$table->foreign('role_id')->references('id')->on('roles')
->onUpdate('cascade')->onDelete('cascade');
$table->primary(['permission_id', 'role_id']);
}
);
}
} }

View File

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
/**
* Class ChangesForV3451
*/
class ChangesForV3451 extends Migration
{
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
}
//$table->smallInteger('reminder_skip')->unsigned();
//$table->boolean('remind_me');
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
}
}

View File

@ -10,7 +10,7 @@ class PermissionSeeder extends Seeder
{ {
public function run() public function run()
{ {
$owner = new Role; $owner = new Role;
$owner->name = 'owner'; $owner->name = 'owner';
$owner->display_name = 'Site Owner'; $owner->display_name = 'Site Owner';
$owner->description = 'User runs this instance of FF3'; // optional $owner->description = 'User runs this instance of FF3'; // optional

View File

@ -88,7 +88,6 @@ class TestDataSeeder extends Seeder
$this->createBudgets(); $this->createBudgets();
$this->createCategories(); $this->createCategories();
$this->createPiggyBanks(); $this->createPiggyBanks();
$this->createReminders();
$this->createBills(); $this->createBills();
$this->createExpenseAccounts(); $this->createExpenseAccounts();
$this->createRevenueAccounts(); $this->createRevenueAccounts();
@ -264,7 +263,6 @@ class TestDataSeeder extends Seeder
'targetamount' => 2000, 'targetamount' => 2000,
'startdate' => $this->som, 'startdate' => $this->som,
'targetdate' => null, 'targetdate' => null,
'reminder' => null,
'reminder_skip' => 0, 'reminder_skip' => 0,
'remind_me' => 0, 'remind_me' => 0,
'order' => 0, 'order' => 0,
@ -281,7 +279,6 @@ class TestDataSeeder extends Seeder
'targetamount' => 2000, 'targetamount' => 2000,
'startdate' => $this->som, 'startdate' => $this->som,
'targetdate' => $end, 'targetdate' => $end,
'reminder' => null,
'reminder_skip' => 0, 'reminder_skip' => 0,
'remind_me' => 0, 'remind_me' => 0,
'order' => 0, 'order' => 0,
@ -292,7 +289,6 @@ class TestDataSeeder extends Seeder
/* /*
* New: create no less than eight piggy banks that * New: create no less than eight piggy banks that
* create all sorts of reminders
*/ */
$list = ['week', 'quarter', 'month', 'year']; $list = ['week', 'quarter', 'month', 'year'];
$nextYear = clone $this->_startOfMonth; $nextYear = clone $this->_startOfMonth;
@ -306,9 +302,8 @@ class TestDataSeeder extends Seeder
'targetamount' => 1000, 'targetamount' => 1000,
'startdate' => $this->som, 'startdate' => $this->som,
'targetdate' => $nextYear, 'targetdate' => $nextYear,
'reminder' => $entry,
'reminder_skip' => 0, 'reminder_skip' => 0,
'remind_me' => 1, 'remind_me' => 0,
'order' => 0, 'order' => 0,
] ]
); );
@ -319,9 +314,8 @@ class TestDataSeeder extends Seeder
'targetamount' => 1000, 'targetamount' => 1000,
'startdate' => $this->som, 'startdate' => $this->som,
'targetdate' => null, 'targetdate' => null,
'reminder' => $entry,
'reminder_skip' => 0, 'reminder_skip' => 0,
'remind_me' => 1, 'remind_me' => 0,
'order' => 0, 'order' => 0,
] ]
); );
@ -348,14 +342,6 @@ class TestDataSeeder extends Seeder
return null; return null;
} }
/**
*
*/
public function createReminders()
{
}
/** /**
* *
*/ */
@ -444,7 +430,8 @@ class TestDataSeeder extends Seeder
$user = User::whereEmail('thegrumpydictator@gmail.com')->first(); $user = User::whereEmail('thegrumpydictator@gmail.com')->first();
Tag::create( Tag::create(
['tag' => 'TagOne', 'tagMode' => 'nothing', 'user_id' => $user->id]); ['tag' => 'TagOne', 'tagMode' => 'nothing', 'user_id' => $user->id]
);
Tag::create(['tag' => 'TagTwo', 'tagMode' => 'nothing', 'user_id' => $user->id]); Tag::create(['tag' => 'TagTwo', 'tagMode' => 'nothing', 'user_id' => $user->id]);
Tag::create(['tag' => 'TagThree', 'tagMode' => 'nothing', 'user_id' => $user->id]); Tag::create(['tag' => 'TagThree', 'tagMode' => 'nothing', 'user_id' => $user->id]);
@ -541,9 +528,10 @@ class TestDataSeeder extends Seeder
} }
/** /**
* @param $tag * @param $tagName
* *
* @return Tag|null * @return Tag|null
* @internal param $tag
*/ */
protected function findTag($tagName) protected function findTag($tagName)
{ {

2
pu.sh
View File

@ -10,7 +10,7 @@ then
fi fi
# directories to look in: # directories to look in:
dirs=("controllers" "database" "factories" "helpers" "models" "middleware" "repositories" "support") dirs=("controllers" "database" "factories" "generators" "helpers" "models" "middleware" "repositories" "support")
if [ ! -z "$1" ] if [ ! -z "$1" ]
then then

13
public/bootstrap/css/bootstrap.min.css vendored Normal file → Executable file

File diff suppressed because one or more lines are too long

11
public/bootstrap/js/bootstrap.min.js vendored Normal file → Executable file

File diff suppressed because one or more lines are too long

View File

@ -7,42 +7,42 @@
* Built for http://www.improvely.com * Built for http://www.improvely.com
*/ */
.daterangepicker.dropdown-menu { .daterangepicker.dropdown-menu {
max-width: none; max-width: none;
z-index: 3000; z-index: 3000;
} }
.daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar { .daterangepicker.opensleft .ranges, .daterangepicker.opensleft .calendar {
float: left; float: left;
margin: 4px; margin: 4px;
} }
.daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar, .daterangepicker.opensright .ranges, .daterangepicker.opensright .calendar,
.daterangepicker.openscenter .ranges, .daterangepicker.openscenter .calendar { .daterangepicker.openscenter .ranges, .daterangepicker.openscenter .calendar {
float: right; float: right;
margin: 4px; margin: 4px;
} }
.daterangepicker.single .ranges, .daterangepicker.single .calendar { .daterangepicker.single .ranges, .daterangepicker.single .calendar {
float: none; float: none;
} }
.daterangepicker .ranges { .daterangepicker .ranges {
width: 160px; width: 160px;
text-align: left; text-align: left;
} }
.daterangepicker .ranges .range_inputs>div { .daterangepicker .ranges .range_inputs>div {
float: left; float: left;
} }
.daterangepicker .ranges .range_inputs>div:nth-child(2) { .daterangepicker .ranges .range_inputs>div:nth-child(2) {
padding-left: 11px; padding-left: 11px;
} }
.daterangepicker .calendar { .daterangepicker .calendar {
display: none; display: none;
max-width: 270px; max-width: 270px;
} }
.daterangepicker.show-calendar .calendar { .daterangepicker.show-calendar .calendar {
@ -50,270 +50,286 @@
} }
.daterangepicker .calendar.single .calendar-date { .daterangepicker .calendar.single .calendar-date {
border: none; border: none;
} }
.daterangepicker .calendar th, .daterangepicker .calendar td { .daterangepicker .calendar th, .daterangepicker .calendar td {
font-family: Roboto, 'Helvetica Neue', Helvetica, Arial, sans-serif; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
white-space: nowrap; white-space: nowrap;
text-align: center; text-align: center;
min-width: 32px; min-width: 32px;
} }
.daterangepicker .daterangepicker_start_input label, .daterangepicker .daterangepicker_start_input label,
.daterangepicker .daterangepicker_end_input label { .daterangepicker .daterangepicker_end_input label {
color: #333; color: #333;
display: block; display: block;
font-size: 11px; font-size: 11px;
font-weight: normal; font-weight: normal;
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
margin-bottom: 2px; margin-bottom: 2px;
text-shadow: #fff 1px 1px 0px; text-shadow: #fff 1px 1px 0px;
text-transform: uppercase; text-transform: uppercase;
width: 74px; width: 74px;
} }
.daterangepicker .ranges input { .daterangepicker .ranges input {
font-size: 11px; font-size: 11px;
} }
.daterangepicker .ranges .input-mini { .daterangepicker .ranges .input-mini {
border: 1px solid #ccc; border: 1px solid #ccc;
border-radius: 4px; border-radius: 4px;
color: #555; color: #555;
display: block; display: block;
font-size: 11px; font-size: 11px;
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
vertical-align: middle; vertical-align: middle;
margin: 0 0 10px 0; margin: 0 0 10px 0;
padding: 0 6px; padding: 0 6px;
width: 74px; width: 74px;
} }
.daterangepicker .ranges ul { .daterangepicker .ranges ul {
list-style: none; list-style: none;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }
.daterangepicker .ranges li { .daterangepicker .ranges li {
font-size: 13px; font-size: 13px;
background: #f5f5f5; background: #f5f5f5;
border: 1px solid #f5f5f5; border: 1px solid #f5f5f5;
color: #08c; color: #08c;
padding: 3px 12px; padding: 3px 12px;
margin-bottom: 8px; margin-bottom: 8px;
-webkit-border-radius: 5px; -webkit-border-radius: 5px;
-moz-border-radius: 5px; -moz-border-radius: 5px;
border-radius: 5px; border-radius: 5px;
cursor: pointer; cursor: pointer;
} }
.daterangepicker .ranges li.active, .daterangepicker .ranges li:hover { .daterangepicker .ranges li.active, .daterangepicker .ranges li:hover {
background: #08c; background: #08c;
border: 1px solid #08c; border: 1px solid #08c;
color: #fff; color: #fff;
} }
.daterangepicker .calendar-date { .daterangepicker .calendar-date {
border: 1px solid #ddd; border: 1px solid #ddd;
padding: 4px; padding: 4px;
border-radius: 4px; border-radius: 4px;
background: #fff; background: #fff;
} }
.daterangepicker .calendar-time { .daterangepicker .calendar-time {
text-align: center; text-align: center;
margin: 8px auto 0 auto; margin: 8px auto 0 auto;
line-height: 30px; line-height: 30px;
} }
.daterangepicker { .daterangepicker {
position: absolute; position: absolute;
background: #fff; background: #fff;
top: 100px; top: 100px;
left: 20px; left: 20px;
padding: 4px; padding: 4px;
margin-top: 1px; margin-top: 1px;
-webkit-border-radius: 4px; -webkit-border-radius: 4px;
-moz-border-radius: 4px; -moz-border-radius: 4px;
border-radius: 4px; border-radius: 4px;
} }
.daterangepicker.opensleft:before { .daterangepicker.opensleft:before {
position: absolute; position: absolute;
top: -7px; top: -7px;
right: 9px; right: 9px;
display: inline-block; display: inline-block;
border-right: 7px solid transparent; border-right: 7px solid transparent;
border-bottom: 7px solid #ccc; border-bottom: 7px solid #ccc;
border-left: 7px solid transparent; border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2); border-bottom-color: rgba(0, 0, 0, 0.2);
content: ''; content: '';
} }
.daterangepicker.opensleft:after { .daterangepicker.opensleft:after {
position: absolute; position: absolute;
top: -6px; top: -6px;
right: 10px; right: 10px;
display: inline-block; display: inline-block;
border-right: 6px solid transparent; border-right: 6px solid transparent;
border-bottom: 6px solid #fff; border-bottom: 6px solid #fff;
border-left: 6px solid transparent; border-left: 6px solid transparent;
content: ''; content: '';
} }
.daterangepicker.openscenter:before { .daterangepicker.openscenter:before {
position: absolute; position: absolute;
top: -7px; top: -7px;
left: 0; left: 0;
right: 0; right: 0;
width: 0; width: 0;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
display: inline-block; display: inline-block;
border-right: 7px solid transparent; border-right: 7px solid transparent;
border-bottom: 7px solid #ccc; border-bottom: 7px solid #ccc;
border-left: 7px solid transparent; border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2); border-bottom-color: rgba(0, 0, 0, 0.2);
content: ''; content: '';
} }
.daterangepicker.openscenter:after { .daterangepicker.openscenter:after {
position: absolute; position: absolute;
top: -6px; top: -6px;
left: 0; left: 0;
right: 0; right: 0;
width: 0; width: 0;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
display: inline-block; display: inline-block;
border-right: 6px solid transparent; border-right: 6px solid transparent;
border-bottom: 6px solid #fff; border-bottom: 6px solid #fff;
border-left: 6px solid transparent; border-left: 6px solid transparent;
content: ''; content: '';
} }
.daterangepicker.opensright:before { .daterangepicker.opensright:before {
position: absolute; position: absolute;
top: -7px; top: -7px;
left: 9px; left: 9px;
display: inline-block; display: inline-block;
border-right: 7px solid transparent; border-right: 7px solid transparent;
border-bottom: 7px solid #ccc; border-bottom: 7px solid #ccc;
border-left: 7px solid transparent; border-left: 7px solid transparent;
border-bottom-color: rgba(0, 0, 0, 0.2); border-bottom-color: rgba(0, 0, 0, 0.2);
content: ''; content: '';
} }
.daterangepicker.opensright:after { .daterangepicker.opensright:after {
position: absolute; position: absolute;
top: -6px; top: -6px;
left: 10px; left: 10px;
display: inline-block; display: inline-block;
border-right: 6px solid transparent; border-right: 6px solid transparent;
border-bottom: 6px solid #fff; border-bottom: 6px solid #fff;
border-left: 6px solid transparent; border-left: 6px solid transparent;
content: ''; content: '';
}
.daterangepicker.dropup{
margin-top: -5px;
}
.daterangepicker.dropup:before{
top: initial;
bottom:-7px;
border-bottom: initial;
border-top: 7px solid #ccc;
}
.daterangepicker.dropup:after{
top: initial;
bottom:-6px;
border-bottom: initial;
border-top: 6px solid #fff;
} }
.daterangepicker table { .daterangepicker table {
width: 100%; width: 100%;
margin: 0; margin: 0;
} }
.daterangepicker td, .daterangepicker th { .daterangepicker td, .daterangepicker th {
text-align: center; text-align: center;
width: 20px; width: 20px;
height: 20px; height: 20px;
-webkit-border-radius: 4px; -webkit-border-radius: 4px;
-moz-border-radius: 4px; -moz-border-radius: 4px;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
white-space: nowrap; white-space: nowrap;
} }
.daterangepicker td.off { .daterangepicker td.off {
color: #999; color: #999;
} }
.daterangepicker td.disabled, .daterangepicker option.disabled { .daterangepicker td.disabled, .daterangepicker option.disabled {
color: #999; color: #999;
} }
.daterangepicker td.available:hover, .daterangepicker th.available:hover { .daterangepicker td.available:hover, .daterangepicker th.available:hover {
background: #eee; background: #eee;
} }
.daterangepicker td.in-range { .daterangepicker td.in-range {
background: #ebf4f8; background: #ebf4f8;
-webkit-border-radius: 0; -webkit-border-radius: 0;
-moz-border-radius: 0; -moz-border-radius: 0;
border-radius: 0; border-radius: 0;
} }
.daterangepicker td.start-date { .daterangepicker td.start-date {
-webkit-border-radius: 4px 0 0 4px; -webkit-border-radius: 4px 0 0 4px;
-moz-border-radius: 4px 0 0 4px; -moz-border-radius: 4px 0 0 4px;
border-radius: 4px 0 0 4px; border-radius: 4px 0 0 4px;
} }
.daterangepicker td.end-date { .daterangepicker td.end-date {
-webkit-border-radius: 0 4px 4px 0; -webkit-border-radius: 0 4px 4px 0;
-moz-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0;
border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0;
} }
.daterangepicker td.start-date.end-date { .daterangepicker td.start-date.end-date {
-webkit-border-radius: 4px; -webkit-border-radius: 4px;
-moz-border-radius: 4px; -moz-border-radius: 4px;
border-radius: 4px; border-radius: 4px;
} }
.daterangepicker td.active, .daterangepicker td.active:hover { .daterangepicker td.active, .daterangepicker td.active:hover {
background-color: #357ebd; background-color: #357ebd;
border-color: #3071a9; border-color: #3071a9;
color: #fff; color: #fff;
} }
.daterangepicker td.week, .daterangepicker th.week { .daterangepicker td.week, .daterangepicker th.week {
font-size: 80%; font-size: 80%;
color: #ccc; color: #ccc;
} }
.daterangepicker select.monthselect, .daterangepicker select.yearselect { .daterangepicker select.monthselect, .daterangepicker select.yearselect {
font-size: 12px; font-size: 12px;
padding: 1px; padding: 1px;
height: auto; height: auto;
margin: 0; margin: 0;
cursor: default; cursor: default;
} }
.daterangepicker select.monthselect { .daterangepicker select.monthselect {
margin-right: 2%; margin-right: 2%;
width: 56%; width: 56%;
} }
.daterangepicker select.yearselect { .daterangepicker select.yearselect {
width: 40%; width: 40%;
} }
.daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect { .daterangepicker select.hourselect, .daterangepicker select.minuteselect, .daterangepicker select.secondselect, .daterangepicker select.ampmselect {
width: 50px; width: 50px;
margin-bottom: 0; margin-bottom: 0;
} }
.daterangepicker_start_input { .daterangepicker_start_input {
float: left; float: left;
} }
.daterangepicker_end_input { .daterangepicker_end_input {
float: left; float: left;
padding-left: 11px padding-left: 11px
} }
.daterangepicker th.month { .daterangepicker th.month {
width: auto; width: auto;
} }

Some files were not shown because too many files have changed in this diff Show More