diff --git a/.coveralls.yml b/.coveralls.yml
index eb8e63b57e..482521d6ec 100644
--- a/.coveralls.yml
+++ b/.coveralls.yml
@@ -1 +1,2 @@
src_dir: .
+coverage_clover: tests/_output/coverage.xml
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index a6133503cd..7c2baa148d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,7 @@ index.html*
app/storage/firefly-export*
.vagrant
firefly-iii-import-*.json
+
+tests/_output/*
+testing.sqlite
+c3.php
diff --git a/.travis.yml b/.travis.yml
index 48aa3ad7af..835ec484b9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,12 +2,14 @@ language: php
php:
- 5.5
- - 5.4
+ - 5.6
- hhvm
install:
- composer install
-after_script:
- - php vendor/bin/coveralls
+script:
+ - php vendor/bin/codecept run
+after_script:
+ - php vendor/bin/coveralls
\ No newline at end of file
diff --git a/README.md b/README.md
index 2085e155c5..6d44b33cf8 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-firefly-iii
+Firefly III
===========
[](https://travis-ci.org/JC5/firefly-iii)
diff --git a/app/breadcrumbs.php b/app/breadcrumbs.php
index 0aff5d9441..9772319edf 100644
--- a/app/breadcrumbs.php
+++ b/app/breadcrumbs.php
@@ -1,7 +1,363 @@
push('Home', route('index'));
-});
\ No newline at end of file
+Breadcrumbs::register(
+ 'home',
+ function (Generator $breadcrumbs) {
+
+ $breadcrumbs->push('Home', route('index'));
+ }
+);
+
+// accounts
+Breadcrumbs::register(
+ 'accounts.index', function (Generator $breadcrumbs, $what) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push(ucfirst($what) . ' accounts', route('accounts.index', $what));
+ }
+);
+Breadcrumbs::register(
+ 'accounts.show', function (Generator $breadcrumbs, \Account $account) {
+ switch ($account->accountType->type) {
+ default:
+ throw new FireflyException('Cannot handle account type "' . e($account->accountType->type) . '"');
+ break;
+ case 'Default account':
+ case 'Asset account':
+ $what = 'asset';
+ break;
+ case 'Expense account':
+ case 'Beneficiary account':
+ $what = 'expense';
+ break;
+ case 'Revenue account':
+ $what = 'revenue';
+ break;
+ }
+ $breadcrumbs->parent('accounts.index', $what);
+ $breadcrumbs->push($account->name, route('accounts.show', $account->id));
+ }
+);
+Breadcrumbs::register(
+ 'accounts.delete', function (Generator $breadcrumbs, \Account $account) {
+ $breadcrumbs->parent('accounts.show', $account);
+ $breadcrumbs->push('Delete ' . $account->name, route('accounts.delete', $account->id));
+ }
+);
+
+Breadcrumbs::register(
+ 'accounts.edit', function (Generator $breadcrumbs, \Account $account) {
+ $breadcrumbs->parent('accounts.show', $account);
+ $breadcrumbs->push('Edit ' . $account->name, route('accounts.edit', $account->id));
+ }
+);
+
+// budgets.
+Breadcrumbs::register(
+ 'budgets.index', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push('Budgets', route('budgets.index'));
+ }
+);
+Breadcrumbs::register(
+ 'budgets.create', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('budgets.index');
+ $breadcrumbs->push('Create new budget', route('budgets.create'));
+ }
+);
+
+Breadcrumbs::register(
+ 'budgets.edit', function (Generator $breadcrumbs, Budget $budget) {
+ $breadcrumbs->parent('budgets.show', $budget);
+ $breadcrumbs->push('Edit ' . $budget->name, route('budgets.edit', $budget->id));
+ }
+);
+Breadcrumbs::register(
+ 'budgets.delete', function (Generator $breadcrumbs, Budget $budget) {
+ $breadcrumbs->parent('budgets.show', $budget);
+ $breadcrumbs->push('Delete ' . $budget->name, route('budgets.delete', $budget->id));
+ }
+);
+
+Breadcrumbs::register(
+ 'budgets.show', function (Generator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) {
+ $breadcrumbs->parent('budgets.index');
+ $breadcrumbs->push($budget->name, route('budgets.show', $budget->id));
+ if (!is_null($repetition)) {
+ $breadcrumbs->push(
+ DateKit::periodShow($repetition->startdate, $repetition->limit->repeat_freq), route('budgets.show', $budget->id, $repetition->id)
+ );
+ }
+ }
+);
+
+// categories
+Breadcrumbs::register(
+ 'categories.index', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push('Categories', route('categories.index'));
+ }
+);
+Breadcrumbs::register(
+ 'categories.create', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('categories.index');
+ $breadcrumbs->push('Create new category', route('categories.create'));
+ }
+);
+
+Breadcrumbs::register(
+ 'categories.edit', function (Generator $breadcrumbs, Category $category) {
+ $breadcrumbs->parent('categories.show', $category);
+ $breadcrumbs->push('Edit ' . $category->name, route('categories.edit', $category->id));
+ }
+);
+Breadcrumbs::register(
+ 'categories.delete', function (Generator $breadcrumbs, Category $category) {
+ $breadcrumbs->parent('categories.show', $category);
+ $breadcrumbs->push('Delete ' . $category->name, route('categories.delete', $category->id));
+ }
+);
+
+Breadcrumbs::register(
+ 'categories.show', function (Generator $breadcrumbs, Category $category) {
+ $breadcrumbs->parent('categories.index');
+ $breadcrumbs->push($category->name, route('categories.show', $category->id));
+
+ }
+);
+
+
+// piggy banks
+Breadcrumbs::register(
+ 'piggybanks.index', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push('Piggy banks', route('piggybanks.index'));
+ }
+);
+Breadcrumbs::register(
+ 'piggybanks.create', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('piggybanks.index');
+ $breadcrumbs->push('Create new piggy bank', route('piggybanks.create'));
+ }
+);
+
+Breadcrumbs::register(
+ 'piggybanks.edit', function (Generator $breadcrumbs, Piggybank $piggybank) {
+ $breadcrumbs->parent('piggybanks.show', $piggybank);
+ $breadcrumbs->push('Edit ' . $piggybank->name, route('piggybanks.edit', $piggybank->id));
+ }
+);
+Breadcrumbs::register(
+ 'piggybanks.delete', function (Generator $breadcrumbs, Piggybank $piggybank) {
+ $breadcrumbs->parent('piggybanks.show', $piggybank);
+ $breadcrumbs->push('Delete ' . $piggybank->name, route('piggybanks.delete', $piggybank->id));
+ }
+);
+
+Breadcrumbs::register(
+ 'piggybanks.show', function (Generator $breadcrumbs, Piggybank $piggybank) {
+ $breadcrumbs->parent('piggybanks.index');
+ $breadcrumbs->push($piggybank->name, route('piggybanks.show', $piggybank->id));
+
+ }
+);
+
+// preferences
+Breadcrumbs::register(
+ 'preferences', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push('Preferences', route('preferences'));
+
+ }
+);
+
+// profile
+Breadcrumbs::register(
+ 'profile', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push('Profile', route('profile'));
+
+ }
+);
+Breadcrumbs::register(
+ 'change-password', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('profile');
+ $breadcrumbs->push('Change your password', route('change-password'));
+
+ }
+);
+
+// recurring transactions
+Breadcrumbs::register(
+ 'recurring.index', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push('Recurring transactions', route('recurring.index'));
+ }
+);
+Breadcrumbs::register(
+ 'recurring.create', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('recurring.index');
+ $breadcrumbs->push('Create new recurring transaction', route('recurring.create'));
+ }
+);
+
+Breadcrumbs::register(
+ 'recurring.edit', function (Generator $breadcrumbs, RecurringTransaction $recurring) {
+ $breadcrumbs->parent('recurring.show', $recurring);
+ $breadcrumbs->push('Edit ' . $recurring->name, route('recurring.edit', $recurring->id));
+ }
+);
+Breadcrumbs::register(
+ 'recurring.delete', function (Generator $breadcrumbs, RecurringTransaction $recurring) {
+ $breadcrumbs->parent('recurring.show', $recurring);
+ $breadcrumbs->push('Delete ' . $recurring->name, route('recurring.delete', $recurring->id));
+ }
+);
+
+Breadcrumbs::register(
+ 'recurring.show', function (Generator $breadcrumbs, RecurringTransaction $recurring) {
+ $breadcrumbs->parent('recurring.index');
+ $breadcrumbs->push($recurring->name, route('recurring.show', $recurring->id));
+
+ }
+);
+
+// reminders
+Breadcrumbs::register(
+ 'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id));
+
+ }
+);
+
+// repeated expenses
+Breadcrumbs::register(
+ 'repeated.index', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push('Repeated expenses', route('repeated.index'));
+ }
+);
+Breadcrumbs::register(
+ 'repeated.create', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('repeated.index');
+ $breadcrumbs->push('Create new repeated expense', route('repeated.create'));
+ }
+);
+
+Breadcrumbs::register(
+ 'repeated.edit', function (Generator $breadcrumbs, Piggybank $piggybank) {
+ $breadcrumbs->parent('repeated.show', $piggybank);
+ $breadcrumbs->push('Edit ' . $piggybank->name, route('repeated.edit', $piggybank->id));
+ }
+);
+Breadcrumbs::register(
+ 'repeated.delete', function (Generator $breadcrumbs, Piggybank $piggybank) {
+ $breadcrumbs->parent('repeated.show', $piggybank);
+ $breadcrumbs->push('Delete ' . $piggybank->name, route('repeated.delete', $piggybank->id));
+ }
+);
+
+Breadcrumbs::register(
+ 'repeated.show', function (Generator $breadcrumbs, Piggybank $piggybank) {
+ $breadcrumbs->parent('repeated.index');
+ $breadcrumbs->push($piggybank->name, route('repeated.show', $piggybank->id));
+
+ }
+);
+
+// reports
+Breadcrumbs::register(
+ 'reports.index', function (Generator $breadcrumbs) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push('Reports', route('reports.index'));
+ }
+);
+
+Breadcrumbs::register(
+ 'reports.year', function (Generator $breadcrumbs, Carbon $date) {
+ $breadcrumbs->parent('reports.index');
+ $breadcrumbs->push($date->format('Y'), route('reports.year', $date->format('Y')));
+ }
+);
+Breadcrumbs::register(
+ 'reports.budgets', function (Generator $breadcrumbs, Carbon $date) {
+ $breadcrumbs->parent('reports.index');
+ $breadcrumbs->push('Budgets in ' . $date->format('F Y'), route('reports.budgets', $date->format('Y')));
+ }
+);
+Breadcrumbs::register(
+ 'reports.unbalanced', function (Generator $breadcrumbs, Carbon $date) {
+ $breadcrumbs->parent('reports.index');
+ $breadcrumbs->push('Unbalanced transactions in ' . $date->format('F Y'), route('reports.unbalanced', $date->format('Y')));
+ }
+);
+// search
+Breadcrumbs::register(
+ 'search', function (Generator $breadcrumbs, $query) {
+ $breadcrumbs->parent('home');
+ $breadcrumbs->push('Search for "' . e($query) . '"', route('search'));
+ }
+);
+
+// transactions
+Breadcrumbs::register(
+ 'transactions.index', function (Generator $breadcrumbs, $what) {
+ $breadcrumbs->parent('home');
+
+ switch ($what) {
+ case 'expenses':
+ case 'withdrawal':
+ $subTitle = 'Expenses';
+ break;
+ case 'revenue':
+ case 'deposit':
+ $subTitle = 'Revenue, income and deposits';
+ break;
+ case 'transfer':
+ case 'transfers':
+ $subTitle = 'Transfers';
+ break;
+ case 'opening balance':
+ $subTitle = 'Opening balances';
+ break;
+ default:
+ throw new FireflyException('Cannot handle $what "'.e($what).'" in bread crumbs');
+ }
+
+ $breadcrumbs->push($subTitle, route('transactions.index', $what));
+ }
+);
+Breadcrumbs::register(
+ 'transactions.create', function (Generator $breadcrumbs, $what) {
+ $breadcrumbs->parent('transactions.index', $what);
+ $breadcrumbs->push('Create new ' . $what, route('transactions.create', $what));
+ }
+);
+
+Breadcrumbs::register(
+ 'transactions.edit', function (Generator $breadcrumbs, TransactionJournal $journal) {
+ $breadcrumbs->parent('transactions.show', $journal);
+ $breadcrumbs->push('Edit ' . $journal->description, route('transactions.edit', $journal ->id));
+ }
+);
+Breadcrumbs::register(
+ 'transactions.delete', function (Generator $breadcrumbs, TransactionJournal $journal) {
+ $breadcrumbs->parent('transactions.show', $journal);
+ $breadcrumbs->push('Delete ' . $journal->description, route('transactions.delete', $journal->id));
+ }
+);
+
+Breadcrumbs::register(
+ 'transactions.show', function (Generator $breadcrumbs, TransactionJournal $journal) {
+
+ $breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type));
+ $breadcrumbs->push($journal->description, route('transactions.show', $journal->id));
+
+ }
+);
\ No newline at end of file
diff --git a/app/commands/Cleanup.php b/app/commands/Cleanup.php
new file mode 100644
index 0000000000..2e5c889068
--- /dev/null
+++ b/app/commands/Cleanup.php
@@ -0,0 +1,77 @@
+info('Start!');
+ Artisan::call('clear-compiled');
+ $this->info('Cleared compiled...');
+ Artisan::call('ide-helper:generate');
+ $this->info('IDE helper, done...');
+ Artisan::call('ide-helper:models', ['write']);
+ $this->info('IDE models, done...');
+ Artisan::call('optimize');
+ $this->info('Optimized...');
+ Artisan::call('dump-autoload');
+ $this->info('Done!');
+ }
+
+ /**
+ * Get the console command arguments.
+ *
+ * @return array
+ */
+ protected function getArguments()
+ {
+ return [
+ // ['example', InputArgument::REQUIRED, 'An example argument.'],
+ ];
+ }
+
+ /**
+ * Get the console command options.
+ *
+ * @return array
+ */
+ protected function getOptions()
+ {
+ return [
+ // ['example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null],
+ ];
+ }
+
+}
diff --git a/app/config/.gitignore b/app/config/.gitignore
index 3415788027..8205aab29b 100644
--- a/app/config/.gitignore
+++ b/app/config/.gitignore
@@ -1,3 +1,4 @@
local/
laptop/
-vagrant/
\ No newline at end of file
+vagrant/
+production/
\ No newline at end of file
diff --git a/app/config/app.php b/app/config/app.php
index b997979dd7..507426a367 100644
--- a/app/config/app.php
+++ b/app/config/app.php
@@ -39,9 +39,7 @@ return [
'Illuminate\Workbench\WorkbenchServiceProvider',
'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
'Barryvdh\Debugbar\ServiceProvider',
- 'Firefly\Storage\StorageServiceProvider',
- 'Firefly\Helper\HelperServiceProvider',
- 'Firefly\Validation\ValidationServiceProvider',
+ 'FireflyIII\FF3ServiceProvider',
'DaveJamesMiller\Breadcrumbs\ServiceProvider',
'Grumpydictator\Gchart\GchartServiceProvider',
],
@@ -86,8 +84,7 @@ return [
'URL' => 'Illuminate\Support\Facades\URL',
'Validator' => 'Illuminate\Support\Facades\Validator',
'View' => 'Illuminate\Support\Facades\View',
- 'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade',
- 'Twig' => 'TwigBridge\Facade\Twig',
+ 'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade'
],
diff --git a/app/config/firefly.php b/app/config/firefly.php
index bd7db200f6..e259b2c0fa 100644
--- a/app/config/firefly.php
+++ b/app/config/firefly.php
@@ -1,13 +1,13 @@
['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'],
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'piggybank_periods' => [
- 'week' => 'Week',
- 'month' => 'Month',
- 'year' => 'Year'
+ 'week' => 'Week',
+ 'month' => 'Month',
+ 'quarter' => 'Quarter',
+ 'year' => 'Year'
],
'periods_to_text' => [
'weekly' => 'A week',
@@ -17,6 +17,11 @@ return [
'yearly' => 'A year',
],
+ 'accountRoles' => [
+ 'default' => 'Default expense account',
+ 'sharedExpense' => 'Shared expense account'
+ ],
+
'range_to_text' => [
'1D' => 'day',
'1W' => 'week',
diff --git a/app/config/homestead/app.php b/app/config/homestead/app.php
new file mode 100644
index 0000000000..b6d461000d
--- /dev/null
+++ b/app/config/homestead/app.php
@@ -0,0 +1,15 @@
+ true,
+ 'log_level' => 'debug',
+];
\ No newline at end of file
diff --git a/app/config/homestead/cache.php b/app/config/homestead/cache.php
new file mode 100644
index 0000000000..8fa089055b
--- /dev/null
+++ b/app/config/homestead/cache.php
@@ -0,0 +1,12 @@
+ 'file',
+ 'path' => storage_path() . '/cache',
+ 'connection' => null,
+ 'table' => 'cache',
+ 'memcached' => [
+ ['host' => '127.0.0.1', 'port' => 11211, 'weight' => 100],
+ ],
+ 'prefix' => 'laravel',
+];
diff --git a/app/config/homestead/database.php b/app/config/homestead/database.php
new file mode 100644
index 0000000000..de7f714bdf
--- /dev/null
+++ b/app/config/homestead/database.php
@@ -0,0 +1,47 @@
+ [
+
+ 'mysql' => [
+ 'driver' => 'mysql',
+ 'host' => 'localhost',
+ 'database' => 'homestead',
+ 'username' => 'homestead',
+ 'password' => 'secret',
+ 'charset' => 'utf8',
+ 'collation' => 'utf8_unicode_ci',
+ 'prefix' => '',
+ ],
+
+ 'pgsql' => [
+ 'driver' => 'pgsql',
+ 'host' => 'localhost',
+ 'database' => 'homestead',
+ 'username' => 'homestead',
+ 'password' => 'secret',
+ 'charset' => 'utf8',
+ 'prefix' => '',
+ 'schema' => 'public',
+ ],
+
+ ],
+
+];
\ No newline at end of file
diff --git a/app/config/homestead/mail.php b/app/config/homestead/mail.php
new file mode 100644
index 0000000000..79a8bf2536
--- /dev/null
+++ b/app/config/homestead/mail.php
@@ -0,0 +1,13 @@
+ 'smtp',
+ 'host' => 'smtp.gmail.com',
+ 'port' => 587,
+ 'from' => ['address' => '@gmail.com', 'name' => 'Firefly III'],
+ 'encryption' => 'tls',
+ 'username' => '@gmail.com',
+ 'password' => '',
+ 'sendmail' => '/usr/sbin/sendmail -bs',
+ 'pretend' => false,
+];
diff --git a/app/config/packages/barryvdh/laravel-debugbar/config.php b/app/config/packages/barryvdh/laravel-debugbar/config.php
index b4ba5d5c62..3baf4b799a 100644
--- a/app/config/packages/barryvdh/laravel-debugbar/config.php
+++ b/app/config/packages/barryvdh/laravel-debugbar/config.php
@@ -2,14 +2,14 @@
use Illuminate\Support\Facades\Config;
-return array(
+return [
- 'enabled' => Config::get('app.debug'),
+ 'enabled' => Config::get('app.debug'),
- 'storage' => array(
+ 'storage' => [
'enabled' => true,
- 'path' => storage_path() . '/debugbar',
- ),
+ 'path' => storage_path() . '/debugbar',
+ ],
/*
|--------------------------------------------------------------------------
@@ -37,8 +37,8 @@ return array(
|
*/
- 'capture_ajax' => true,
-
+ 'capture_ajax' => true,
+
/*
|--------------------------------------------------------------------------
| Capture Console Commands
@@ -59,7 +59,7 @@ return array(
|
*/
- 'collectors' => array(
+ 'collectors' => [
'phpinfo' => true, // Php version
'messages' => true, // Messages
'time' => true, // Time Datalogger
@@ -78,7 +78,7 @@ return array(
'files' => false, // Show the included files
'config' => false, // Display config settings
'auth' => false, // Display Laravel authentication status
- ),
+ ],
/*
|--------------------------------------------------------------------------
@@ -89,27 +89,27 @@ return array(
|
*/
- 'options' => array(
- 'auth' => array(
+ 'options' => [
+ 'auth' => [
'show_name' => false, // Also show the users name/email in the debugbar
- ),
- 'db' => array(
- 'with_params' => true, // Render SQL with the parameters substituted
- 'timeline' => false, // Add the queries to the timeline
- ),
- 'mail' => array(
+ ],
+ 'db' => [
+ 'with_params' => true, // Render SQL with the parameters substituted
+ 'timeline' => false, // Add the queries to the timeline
+ ],
+ 'mail' => [
'full_log' => false
- ),
- 'views' => array(
+ ],
+ 'views' => [
'data' => false, //Note: Can slow down the application, because the data can be quite large..
- ),
- 'route' => array(
+ ],
+ 'route' => [
'label' => true // show complete route on bar
- ),
- 'logs' => array(
+ ],
+ 'logs' => [
'file' => null
- ),
- ),
+ ],
+ ],
/*
|--------------------------------------------------------------------------
@@ -122,6 +122,6 @@ return array(
|
*/
- 'inject' => true,
+ 'inject' => true,
-);
+];
diff --git a/app/config/packages/barryvdh/laravel-ide-helper/config.php b/app/config/packages/barryvdh/laravel-ide-helper/config.php
index 89b3dada2f..a49a469e62 100644
--- a/app/config/packages/barryvdh/laravel-ide-helper/config.php
+++ b/app/config/packages/barryvdh/laravel-ide-helper/config.php
@@ -1,6 +1,6 @@
'_ide_helper.php',
+ 'filename' => '_ide_helper.php',
/*
|--------------------------------------------------------------------------
@@ -25,9 +25,9 @@ return array(
'include_helpers' => false,
- 'helper_files' => array(
- base_path().'/vendor/laravel/framework/src/Illuminate/Support/helpers.php',
- ),
+ 'helper_files' => [
+ base_path() . '/vendor/laravel/framework/src/Illuminate/Support/helpers.php',
+ ],
/*
|--------------------------------------------------------------------------
@@ -39,9 +39,9 @@ return array(
|
*/
- 'model_locations' => array(
+ 'model_locations' => [
'app/models',
- ),
+ ],
/*
@@ -53,14 +53,14 @@ return array(
|
*/
- 'extra' => array(
- 'Artisan' => array('Illuminate\Foundation\Artisan'),
- 'Eloquent' => array('Illuminate\Database\Eloquent\Builder', 'Illuminate\Database\Query\Builder'),
- 'Session' => array('Illuminate\Session\Store'),
- ),
+ 'extra' => [
+ 'Artisan' => ['Illuminate\Foundation\Artisan'],
+ 'Eloquent' => ['Illuminate\Database\Eloquent\Builder', 'Illuminate\Database\Query\Builder'],
+ 'Session' => ['Illuminate\Session\Store'],
+ ],
- 'magic' => array(
- 'Log' => array(
+ 'magic' => [
+ 'Log' => [
'debug' => 'Monolog\Logger::addDebug',
'info' => 'Monolog\Logger::addInfo',
'notice' => 'Monolog\Logger::addNotice',
@@ -69,7 +69,8 @@ return array(
'critical' => 'Monolog\Logger::addCritical',
'alert' => 'Monolog\Logger::addAlert',
'emergency' => 'Monolog\Logger::addEmergency',
- )
- )
+ ]
+ ]
-);
+
+];
diff --git a/app/config/packages/davejamesmiller/laravel-breadcrumbs/config.php b/app/config/packages/davejamesmiller/laravel-breadcrumbs/config.php
index a46482b491..e58b40faa9 100644
--- a/app/config/packages/davejamesmiller/laravel-breadcrumbs/config.php
+++ b/app/config/packages/davejamesmiller/laravel-breadcrumbs/config.php
@@ -1,5 +1,5 @@
'laravel-breadcrumbs::bootstrap3',
-);
+];
diff --git a/app/config/testing/app.php b/app/config/testing/app.php
new file mode 100644
index 0000000000..e729eb5ab7
--- /dev/null
+++ b/app/config/testing/app.php
@@ -0,0 +1,2 @@
+ 'debug',];
\ No newline at end of file
diff --git a/app/config/testing/cache.php b/app/config/testing/cache.php
index 66a8a39a86..729ae3a825 100644
--- a/app/config/testing/cache.php
+++ b/app/config/testing/cache.php
@@ -1,6 +1,6 @@
'array',
-);
+];
diff --git a/app/config/testing/database.php b/app/config/testing/database.php
index 8448619ce0..dce7200371 100644
--- a/app/config/testing/database.php
+++ b/app/config/testing/database.php
@@ -4,8 +4,9 @@ return [
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
- 'database' => ':memory:',
+ 'database' => 'tests/_data/testing.sqlite',
'prefix' => ''
- ],
+ ]
+
]
];
\ No newline at end of file
diff --git a/app/config/testing/mail.php b/app/config/testing/mail.php
new file mode 100644
index 0000000000..d2df78f4cd
--- /dev/null
+++ b/app/config/testing/mail.php
@@ -0,0 +1,13 @@
+ 'smtp',
+ 'host' => '',
+ 'port' => 587,
+ 'from' => ['address' => '', 'name' => 'Firefly III'],
+ 'encryption' => 'tls',
+ 'username' => '',
+ 'password' => '',
+ 'sendmail' => '/usr/sbin/sendmail -bs',
+ 'pretend' => true,
+];
diff --git a/app/config/testing/session.php b/app/config/testing/session.php
index 0364b63dcc..46bf726a27 100644
--- a/app/config/testing/session.php
+++ b/app/config/testing/session.php
@@ -1,6 +1,6 @@
'array',
-);
+];
diff --git a/app/config/view.php b/app/config/view.php
index e0529fb669..f3b156d455 100644
--- a/app/config/view.php
+++ b/app/config/view.php
@@ -1,6 +1,6 @@
array(__DIR__ . '/../views'),
+ 'paths' => [__DIR__ . '/../views'],
'pagination' => 'pagination::slider-3',
];
diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php
index da88631243..73d8ec9338 100644
--- a/app/controllers/AccountController.php
+++ b/app/controllers/AccountController.php
@@ -1,6 +1,6 @@
with('what', $what)
- ->with(compact('subTitleIcon'))
- ->with(compact('subTitle'));
- }
-
-
- /**
- * @param string $what
- *
- * @return \Illuminate\Http\JsonResponse
- * @throws FireflyException
- */
- public function json($what = 'default')
- {
- /** @var \FireflyIII\Database\Account $acct */
- $acct = App::make('FireflyIII\Database\Account');
-
- /** @var \FireflyIII\Shared\Json\Json $json */
- $json = App::make('FireflyIII\Shared\Json\Json');
-
- $parameters = $json->dataTableParameters();
-
- switch ($what) {
- default:
- throw new FireflyException('Cannot handle account type "' . e($what) . '".');
- break;
- case 'asset':
- $accounts = $acct->getAssetAccounts($parameters);
- $count = $acct->countAssetAccounts();
- break;
- case 'expense':
- $accounts = $acct->getExpenseAccounts($parameters);
- $count = $acct->countExpenseAccounts();
- break;
- case 'revenue':
- $accounts = $acct->getRevenueAccounts($parameters);
- $count = $acct->countRevenueAccounts();
- break;
- }
-
- /*
- * Output the set compatible with data tables:
- */
- $return = [
- 'draw' => intval(Input::get('draw')),
- 'recordsTotal' => $count,
- 'recordsFiltered' => $accounts->count(),
- 'data' => [],
- ];
-
- /*
- * Loop the accounts:
- */
- /** @var \Account $account */
- foreach ($accounts as $account) {
- $entry = [
- 'name' => ['name' => $account->name, 'url' => route('accounts.show', $account->id)],
- 'balance' => $account->balance(),
- 'id' => [
- 'edit' => route('accounts.edit', $account->id),
- 'delete' => route('accounts.delete', $account->id),
- ]
- ];
- $return['data'][] = $entry;
- }
-
-
- return Response::jsoN($return);
- }
-
- /**
* @return \Illuminate\View\View
*/
public function create($what)
@@ -130,11 +36,9 @@ class AccountController extends BaseController
$subTitleIcon = 'fa-download';
break;
}
+ $subTitle = 'Create a new ' . $what . ' account';
- return View::make('accounts.create')
- ->with('subTitle', 'Create a new ' . $what . ' account')
- ->with('what', $what)
- ->with(compact('subTitleIcon'));
+ return View::make('accounts.create', compact('subTitleIcon', 'what', 'subTitle'));
}
/**
@@ -144,10 +48,9 @@ class AccountController extends BaseController
*/
public function delete(Account $account)
{
- return View::make('accounts.delete')->with('account', $account)
- ->with(
- 'subTitle', 'Delete ' . strtolower($account->accountType->type) . ' "' . $account->name . '"'
- );
+ $subTitle = 'Delete ' . strtolower($account->accountType->type) . ' "' . $account->name . '"';
+
+ return View::make('accounts.delete', compact('account', 'subTitle'));
}
/**
@@ -159,69 +62,27 @@ class AccountController extends BaseController
{
$type = $account->accountType->type;
+ $name = $account->name;
/** @var \FireflyIII\Database\Account $acct */
$acct = App::make('FireflyIII\Database\Account');
- /** @var \FireflyIII\Database\TransactionJournal $jrnls */
- $jrnls = App::make('FireflyIII\Database\TransactionJournal');
-
- /*
- * Find the "initial balance account", should it exist:
- */
- $initialBalance = $acct->findInitialBalanceAccount($account);
-
- /*
- * Get all the transaction journals that are part of this/these account(s):
- */
- $journals = [];
- if ($initialBalance) {
- $transactions = $initialBalance->transactions()->get();
- /** @var \Transaction $transaction */
- foreach ($transactions as $transaction) {
- $journals[] = $transaction->transaction_journal_id;
- }
- }
- /** @var \Transaction $transaction */
- foreach ($account->transactions() as $transaction) {
- $journals[] = $transaction->transaction_journal_id;
- }
-
- $journals = array_unique($journals);
-
- /*
- * Delete the journals. Should get rid of the transactions as well.
- */
- foreach ($journals as $id) {
- $journal = $jrnls->find($id);
- $journal->delete();
- }
-
- /*
- * Delete it
- */
- if ($initialBalance) {
- $acct->destroy($initialBalance);
- }
-
$acct->destroy($account);
- Session::flash('success', 'The account was deleted.');
+ $return = 'asset';
switch ($type) {
- case 'Asset account':
- case 'Default account':
- return Redirect::route('accounts.index', 'asset');
- break;
case 'Expense account':
case 'Beneficiary account':
- return Redirect::route('accounts.index', 'expense');
+ $return = 'expense';
break;
case 'Revenue account':
- return Redirect::route('accounts.index', 'revenue');
+ $return = 'revenue';
break;
}
+ Session::flash('success', 'The ' . $return . ' account "' . e($name) . '" was deleted.');
+ return Redirect::route('accounts.index', $return);
}
/**
@@ -231,11 +92,13 @@ class AccountController extends BaseController
*/
public function edit(Account $account)
{
+ $prefilled = [];
switch ($account->accountType->type) {
case 'Asset account':
case 'Default account':
- $subTitleIcon = 'fa-money';
+ $subTitleIcon = 'fa-money';
+ $prefilled['account_role'] = $account->getMeta('accountRole');
break;
case 'Expense account':
case 'Beneficiary account':
@@ -254,46 +117,112 @@ class AccountController extends BaseController
if (!is_null($openingBalance)) {
$prefilled['openingbalancedate'] = $openingBalance->date->format('Y-m-d');
$prefilled['openingbalance'] = floatval($openingBalance->transactions()->where('account_id', $account->id)->first()->amount);
- Session::flash('prefilled', $prefilled);
}
+ Session::flash('prefilled', $prefilled);
- return View::make('accounts.edit')
- ->with('account', $account)
- ->with('openingBalance', $openingBalance)
- ->with(compact('subTitleIcon'))
- ->with('subTitle', 'Edit ' . strtolower(
+ return View::make('accounts.edit', compact('account', 'openingBalance', 'subTitleIcon'))->with(
+ 'subTitle', 'Edit ' . strtolower(
$account->accountType->type
) . ' "' . $account->name . '"'
);
}
+ /**
+ * @param string $what
+ *
+ * @return View
+ * @throws FireflyException
+ */
+ public function index($what = 'default')
+ {
+ /** @var \FireflyIII\Database\Account $acct */
+ $acct = App::make('FireflyIII\Database\Account');
+
+ switch ($what) {
+ default:
+ throw new FireflyException('Cannot handle account type "' . e($what) . '".');
+ break;
+ case 'asset':
+ $subTitleIcon = 'fa-money';
+ $subTitle = 'Asset accounts';
+ $accounts = $acct->getAssetAccounts();
+ break;
+ case 'expense':
+ $subTitleIcon = 'fa-shopping-cart';
+ $subTitle = 'Expense accounts';
+ $accounts = $acct->getExpenseAccounts();
+ break;
+ case 'revenue':
+ $subTitleIcon = 'fa-download';
+ $subTitle = 'Revenue accounts';
+ $accounts = $acct->getRevenueAccounts();
+ break;
+ }
+
+ $accounts->each(
+ function (Account $account) {
+ if (Cache::has('account.' . $account->id . '.lastActivityDate')) {
+ $account->lastActionDate = Cache::get('account.' . $account->id . '.lastActivityDate');
+ } else {
+ $transaction = $account->transactions()->orderBy('updated_at', 'DESC')->first();
+ if (is_null($transaction)) {
+ $account->lastActionDate = null;
+ Cache::forever('account.' . $account->id . '.lastActivityDate', 0);
+ } else {
+ $account->lastActionDate = $transaction->updated_at;
+ Cache::forever('account.' . $account->id . '.lastActivityDate', $transaction->updated_at);
+ }
+ }
+
+ }
+ );
+
+ return View::make('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts'));
+ }
+
/**
* @param Account $account
+ * @param string $view
*
* @return $this
*/
- public function show(Account $account)
+ public function show(Account $account, $view = 'session')
{
switch ($account->accountType->type) {
case 'Asset account':
case 'Default account':
$subTitleIcon = 'fa-money';
+ $what = 'asset';
break;
case 'Expense account':
case 'Beneficiary account':
$subTitleIcon = 'fa-shopping-cart';
+ $what = 'expense';
break;
case 'Revenue account':
$subTitleIcon = 'fa-download';
+ $what = 'revenue';
+ break;
+ }
+
+ // get a paginated view of all transactions for this account:
+ /** @var \FireflyIII\Database\Account $acct */
+ $acct = App::make('FireflyIII\Database\Account');
+ switch ($view) {
+ default:
+ case 'session':
+ $journals = $acct->getTransactionJournals($account, 50);
+ break;
+ case 'all':
+ $journals = $acct->getAllTransactionJournals($account, 50);
+
break;
}
- //$data = $this->_accounts->show($account, 40);
- return View::make('accounts.show')
- ->with('account', $account)
- ->with('subTitle', 'Details for ' . strtolower($account->accountType->type) . ' "' . $account->name . '"')
- ->with(compact('subTitleIcon'));
+ return View::make('accounts.show', compact('account', 'what', 'view', 'subTitleIcon', 'journals'))->with('account', $account)->with(
+ 'subTitle', 'Details for ' . strtolower($account->accountType->type) . ' "' . $account->name . '"'
+ );
}
/**
@@ -312,7 +241,7 @@ class AccountController extends BaseController
default:
throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
break;
- case 'create_another':
+ case 'return_to_edit':
case 'store':
$messages = $acct->validate($data);
/** @var MessageBag $messages ['errors'] */
@@ -320,6 +249,7 @@ class AccountController extends BaseController
Session::flash('warnings', $messages['warnings']);
Session::flash('successes', $messages['successes']);
Session::flash('error', 'Could not save account: ' . $messages['errors']->first());
+
return Redirect::route('accounts.create', $data['what'])->withInput()->withErrors($messages['errors']);
}
// store!
@@ -337,6 +267,7 @@ class AccountController extends BaseController
Session::flash('warnings', $messageBags['warnings']);
Session::flash('successes', $messageBags['successes']);
Session::flash('errors', $messageBags['errors']);
+
return Redirect::route('accounts.create', $data['what'])->withInput();
break;
}
@@ -360,8 +291,10 @@ class AccountController extends BaseController
throw new FireflyException('Cannot handle account type "' . e($account->accountType->type) . '"');
break;
case 'Default account':
+ case 'Asset account':
$data['what'] = 'asset';
break;
+ case 'Expense account':
case 'Beneficiary account':
$data['what'] = 'expense';
break;
@@ -382,6 +315,7 @@ class AccountController extends BaseController
Session::flash('warnings', $messages['warnings']);
Session::flash('successes', $messages['successes']);
Session::flash('error', 'Could not save account: ' . $messages['errors']->first());
+
return Redirect::route('accounts.edit', $account->id)->withInput()->withErrors($messages['errors']);
}
// store!
@@ -391,13 +325,14 @@ class AccountController extends BaseController
if ($data['post_submit_action'] == 'create_another') {
return Redirect::route('accounts.edit', $account->id);
} else {
- return Redirect::route('accounts.index',$data['what']);
+ return Redirect::route('accounts.index', $data['what']);
}
case 'validate_only':
$messageBags = $acct->validate($data);
Session::flash('warnings', $messageBags['warnings']);
Session::flash('successes', $messageBags['successes']);
Session::flash('errors', $messageBags['errors']);
+
return Redirect::route('accounts.edit', $account->id)->withInput();
break;
}
diff --git a/app/controllers/BudgetController.php b/app/controllers/BudgetController.php
index 54e095461d..c2a857fb6d 100644
--- a/app/controllers/BudgetController.php
+++ b/app/controllers/BudgetController.php
@@ -1,6 +1,6 @@
set('budgetIncomeTotal' . $date->format('FY'), $value);
- return Redirect::route('budgets.index');
- }
-
- /**
- * Update the amount for a budget's limitrepetition and/or create it.
- *
* @param Budget $budget
+ *
+ * @return \Illuminate\Http\JsonResponse
+ * @throws Exception
*/
public function amount(Budget $budget)
{
@@ -51,12 +41,18 @@ class BudgetController extends BaseController
$limit->repeat_freq = 'monthly';
$limit->repeats = 0;
$limit->save();
+ /*
+ * A newly stored limit also created a limit repetition.
+ */
Event::fire('limits.store', [$limit]);
} else {
if ($amount > 0) {
$limit->amount = $amount;
$limit->save();
+ /*
+ * An updated limit also updates the associated limit repetitions.
+ */
Event::fire('limits.update', [$limit]);
} else {
$limit->delete();
@@ -72,19 +68,69 @@ class BudgetController extends BaseController
}
+ /**
+ * @return $this
+ */
+ public function create()
+ {
+ return View::make('budgets.create')->with('subTitle', 'Create a new budget');
+ }
+
+ /**
+ * @param Budget $budget
+ *
+ * @return $this
+ */
+ public function delete(Budget $budget)
+ {
+ return View::make('budgets.delete')->with('budget', $budget)->with('subTitle', 'Delete budget "' . $budget->name . '"');
+ }
+
+ /**
+ * @param Budget $budget
+ *
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function destroy(Budget $budget)
+ {
+ /** @var \FireflyIII\Database\Budget $repos */
+ $repos = App::make('FireflyIII\Database\Budget');
+ // remove budget
+ $repos->destroy($budget);
+ Session::flash('success', 'The budget was deleted.');
+
+ return Redirect::route('budgets.index');
+
+ }
+
+ /**
+ * @param Budget $budget
+ *
+ * @return $this
+ */
+ public function edit(Budget $budget)
+ {
+ Session::flash('prefilled', ['name' => $budget->name]);
+
+ return View::make('budgets.edit')->with('budget', $budget)->with('subTitle', 'Edit budget "' . $budget->name . '"');
+
+ }
+
+ /**
+ * @return $this
+ */
public function index()
{
- /** @var \Firefly\Helper\Preferences\PreferencesHelperInterface $preferences */
- $preferences = App::make('Firefly\Helper\Preferences\PreferencesHelperInterface');
- $date = Session::get('start');
+ /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
+ $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
/** @var \FireflyIII\Database\Budget $repos */
$repos = App::make('FireflyIII\Database\Budget');
$budgets = $repos->get();
// get the limits for the current month.
- $date = \Session::get('start');
+ $date = \Session::get('start');
$spent = 0;
/** @var \Budget $budget */
foreach ($budgets as $budget) {
@@ -114,9 +160,9 @@ class BudgetController extends BaseController
}
$budgetAmount = $preferences->get('budgetIncomeTotal' . $date->format('FY'), 1000);
- $amount = floatval($budgetAmount->data);
- $overspent = $spent > $amount;
- if($overspent) {
+ $amount = floatval($budgetAmount->data);
+ $overspent = $spent > $amount;
+ if ($overspent) {
// overspent on total amount
$spentPCT = ceil($amount / $spent * 100);
} else {
@@ -124,19 +170,22 @@ class BudgetController extends BaseController
$spentPCT = ceil($spent / $amount * 100);
}
- return View::make('budgets.index', compact('budgets','spent','spentPCT','overspent'))->with('budgetAmount', $budgetAmount);
+ return View::make('budgets.index', compact('budgets', 'spent', 'spentPCT', 'overspent'))->with('budgetAmount', $budgetAmount);
}
/**
- * @return $this
+ * @return \Illuminate\Http\RedirectResponse
*/
- public function updateIncome()
+ public function postUpdateIncome()
{
- $date = Session::get('start');
- /** @var \Firefly\Helper\Preferences\PreferencesHelperInterface $preferences */
- $preferences = App::make('Firefly\Helper\Preferences\PreferencesHelperInterface');
- $budgetAmount = $preferences->get('budgetIncomeTotal' . $date->format('FY'), 1000);
- return View::make('budgets.income')->with('amount', $budgetAmount)->with('date', $date);
+ /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
+ $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
+ $date = Session::get('start');
+
+ $value = intval(Input::get('amount'));
+ $preferences->set('budgetIncomeTotal' . $date->format('FY'), $value);
+
+ return Redirect::route('budgets.index');
}
/**
@@ -150,62 +199,32 @@ class BudgetController extends BaseController
if (!is_null($repetition) && $repetition->limit->budget->id != $budget->id) {
App::abort(500);
}
+ /** @var \FireflyIII\Database\Budget $repos */
+ $repos = App::make('FireflyIII\Database\Budget');
if (is_null($repetition)) {
// get all other repetitions:
$limits = $budget->limits()->orderBy('startdate', 'DESC')->get();
+ // get all transaction journals for this budget.
+ $journals = $repos->getTransactionJournals($budget, 50);
+ $subTitle = $budget->name;
} else {
// get nothing? i dunno
$limits = [$repetition->limit];
+ // get all transaction journals for this budget and limit repetition.
+ $subTitle = $budget->name . ' in ' . $repetition->startdate->format('F Y');
+ $journals = $repos->getTransactionJournalsInRepetition($budget, $repetition, 50);
}
+ $hideBudget = true;
- return View::make('budgets.show', compact('limits', 'budget', 'repetition'));
+
+ return View::make('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget'));
}
/**
* @return $this
- */
- public function create()
- {
- return View::make('budgets.create')->with('subTitle', 'Create a new budget');
- }
-
- /**
- * @param Budget $budget
- *
- * @return $this
- */
- public function delete(Budget $budget)
- {
- return View::make('budgets.delete')->with('budget', $budget)->with('subTitle', 'Delete budget "' . $budget->name . '"');
- }
-
- public function destroy(Budget $budget)
- {
- /** @var \FireflyIII\Database\Budget $repos */
- $repos = App::make('FireflyIII\Database\Budget');
- // remove budget
- $repos->destroy($budget);
- Session::flash('success', 'The budget was deleted.');
- return Redirect::route('budgets.index');
-
- }
-
- /**
- * @param Budget $budget
- *
- * @return $this
- */
- public function edit(Budget $budget)
- {
- Session::flash('prefilled', ['name' => $budget->name]);
- return View::make('budgets.edit')->with('budget', $budget)->with('subTitle', 'Edit budget "' . $budget->name . '"');
-
- }
-
- /**
- * @return \Illuminate\Http\RedirectResponse
+ * @throws FireflyException
*/
public function store()
{
@@ -225,6 +244,7 @@ class BudgetController extends BaseController
Session::flash('warnings', $messages['warnings']);
Session::flash('successes', $messages['successes']);
Session::flash('error', 'Could not save budget: ' . $messages['errors']->first());
+
return Redirect::route('budgets.create')->withInput()->withErrors($messages['errors']);
}
// store!
@@ -242,6 +262,7 @@ class BudgetController extends BaseController
Session::flash('warnings', $messageBags['warnings']);
Session::flash('successes', $messageBags['successes']);
Session::flash('errors', $messageBags['errors']);
+
return Redirect::route('budgets.create')->withInput();
break;
}
@@ -250,6 +271,7 @@ class BudgetController extends BaseController
/**
* @param Budget $budget
*
+ * @return $this
* @throws FireflyException
*/
public function update(Budget $budget)
@@ -263,7 +285,7 @@ class BudgetController extends BaseController
default:
throw new FireflyException('Cannot handle post_submit_action "' . e(Input::get('post_submit_action')) . '"');
break;
- case 'create_another':
+ case 'return_to_edit':
case 'update':
$messages = $repos->validate($data);
/** @var MessageBag $messages ['errors'] */
@@ -271,13 +293,14 @@ class BudgetController extends BaseController
Session::flash('warnings', $messages['warnings']);
Session::flash('successes', $messages['successes']);
Session::flash('error', 'Could not save budget: ' . $messages['errors']->first());
+
return Redirect::route('budgets.edit', $budget->id)->withInput()->withErrors($messages['errors']);
}
// store!
$repos->update($budget, $data);
Session::flash('success', 'Budget updated!');
- if ($data['post_submit_action'] == 'create_another') {
+ if ($data['post_submit_action'] == 'return_to_edit') {
return Redirect::route('budgets.edit', $budget->id);
} else {
return Redirect::route('budgets.index');
@@ -287,8 +310,22 @@ class BudgetController extends BaseController
Session::flash('warnings', $messageBags['warnings']);
Session::flash('successes', $messageBags['successes']);
Session::flash('errors', $messageBags['errors']);
+
return Redirect::route('budgets.edit', $budget->id)->withInput();
break;
}
}
+
+ /**
+ * @return $this
+ */
+ public function updateIncome()
+ {
+ $date = Session::get('start');
+ /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
+ $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
+ $budgetAmount = $preferences->get('budgetIncomeTotal' . $date->format('FY'), 1000);
+
+ return View::make('budgets.income')->with('amount', $budgetAmount)->with('date', $date);
+ }
}
\ No newline at end of file
diff --git a/app/controllers/CategoryController.php b/app/controllers/CategoryController.php
index 6b1d7a4e44..2093aa54e0 100644
--- a/app/controllers/CategoryController.php
+++ b/app/controllers/CategoryController.php
@@ -1,26 +1,17 @@
_repository = $repository;
- $this->_category = $category;
View::share('title', 'Categories');
View::share('mainTitleIcon', 'fa-bar-chart');
}
@@ -40,8 +31,7 @@ class CategoryController extends BaseController
*/
public function delete(Category $category)
{
- return View::make('categories.delete')->with('category', $category)
- ->with('subTitle', 'Delete category "' . $category->name . '"');
+ return View::make('categories.delete')->with('category', $category)->with('subTitle', 'Delete category "' . $category->name . '"');
}
/**
@@ -51,8 +41,12 @@ class CategoryController extends BaseController
*/
public function destroy(Category $category)
{
- $this->_repository->destroy($category);
+ /** @var \FireflyIII\Database\Category $repos */
+ $repos = App::make('FireflyIII\Database\Category');
+
+ $repos->destroy($category);
Session::flash('success', 'The category was deleted.');
+
return Redirect::route('categories.index');
}
@@ -63,8 +57,7 @@ class CategoryController extends BaseController
*/
public function edit(Category $category)
{
- return View::make('categories.edit')->with('category', $category)
- ->with('subTitle', 'Edit category "' . $category->name . '"');
+ return View::make('categories.edit')->with('category', $category)->with('subTitle', 'Edit category "' . $category->name . '"');
}
/**
@@ -72,10 +65,11 @@ class CategoryController extends BaseController
*/
public function index()
{
- $categories = $this->_repository->get();
+ /** @var \FireflyIII\Database\Category $repos */
+ $repos = App::make('FireflyIII\Database\Category');
+ $categories = $repos->get();
- return View::make('categories.index')->with('categories', $categories)
- ->with('subTitle', 'All your categories');
+ return View::make('categories.index', compact('categories'));
}
/**
@@ -85,54 +79,106 @@ class CategoryController extends BaseController
*/
public function show(Category $category)
{
- $start = \Session::get('start');
- $end = \Session::get('end');
+ $hideCategory = true;
+ /** @var \FireflyIII\Database\Category $repos */
+ $repos = App::make('FireflyIII\Database\Category');
- $journals = $this->_category->journalsInRange($category, $start, $end);
+ $journals = $repos->getTransactionJournals($category, 50);
- return View::make('categories.show')->with('category', $category)->with('journals', $journals)->with(
- 'highlight', Input::get('highlight')
- )->with('subTitle', 'Overview for category "' . $category->name . '"');
+ return View::make('categories.show', compact('category', 'journals', 'hideCategory'));
}
/**
- * @return $this|\Illuminate\Http\RedirectResponse
+ * @return $this
+ * @throws FireflyException
*/
public function store()
{
- $category = $this->_repository->store(Input::all());
- if ($category->validate()) {
- Session::flash('success', 'Category "' . $category->name . '" created!');
+ $data = Input::all();
+ /** @var \FireflyIII\Database\Category $repos */
+ $repos = App::make('FireflyIII\Database\Category');
- if (Input::get('create') == '1') {
- return Redirect::route('categories.create');
- }
+ switch ($data['post_submit_action']) {
+ default:
+ throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
+ break;
+ case 'create_another':
+ case 'store':
+ $messages = $repos->validate($data);
+ /** @var MessageBag $messages ['errors'] */
+ if ($messages['errors']->count() > 0) {
+ Session::flash('warnings', $messages['warnings']);
+ Session::flash('successes', $messages['successes']);
+ Session::flash('error', 'Could not save category: ' . $messages['errors']->first());
- return Redirect::route('categories.index');
- } else {
- Session::flash('error', 'Could not save the new category!');
+ return Redirect::route('categories.create')->withInput()->withErrors($messages['errors']);
+ }
+ // store!
+ $repos->store($data);
+ Session::flash('success', 'New category stored!');
- return Redirect::route('categories.create')->withInput();
+ if ($data['post_submit_action'] == 'create_another') {
+ return Redirect::route('categories.create')->withInput();
+ } else {
+ return Redirect::route('categories.index');
+ }
+ break;
+ case 'validate_only':
+ $messageBags = $repos->validate($data);
+ Session::flash('warnings', $messageBags['warnings']);
+ Session::flash('successes', $messageBags['successes']);
+ Session::flash('errors', $messageBags['errors']);
+
+ return Redirect::route('categories.create')->withInput();
+ break;
}
}
/**
* @param Category $category
*
- * @return $this|\Illuminate\Http\RedirectResponse
+ * @return $this
+ * @throws FireflyException
*/
public function update(Category $category)
{
- $category = $this->_repository->update($category, Input::all());
- if ($category->validate()) {
- Session::flash('success', 'Category "' . $category->name . '" updated.');
+ /** @var \FireflyIII\Database\Category $repos */
+ $repos = App::make('FireflyIII\Database\Category');
+ $data = Input::except('_token');
- return Redirect::route('categories.index');
- } else {
- Session::flash('success', 'Could not update category "' . $category->name . '".');
+ switch (Input::get('post_submit_action')) {
+ default:
+ throw new FireflyException('Cannot handle post_submit_action "' . e(Input::get('post_submit_action')) . '"');
+ break;
+ case 'return_to_edit':
+ case 'update':
+ $messages = $repos->validate($data);
+ /** @var MessageBag $messages ['errors'] */
+ if ($messages['errors']->count() > 0) {
+ Session::flash('warnings', $messages['warnings']);
+ Session::flash('successes', $messages['successes']);
+ Session::flash('error', 'Could not save category: ' . $messages['errors']->first());
- return Redirect::route('categories.edit')->withErrors($category->errors())->withInput();
+ return Redirect::route('categories.edit', $category->id)->withInput()->withErrors($messages['errors']);
+ }
+ // store!
+ $repos->update($category, $data);
+ Session::flash('success', 'Category updated!');
+
+ if ($data['post_submit_action'] == 'return_to_edit') {
+ return Redirect::route('categories.edit', $category->id);
+ } else {
+ return Redirect::route('categories.index');
+ }
+ case 'validate_only':
+ $messageBags = $repos->validate($data);
+ Session::flash('warnings', $messageBags['warnings']);
+ Session::flash('successes', $messageBags['successes']);
+ Session::flash('errors', $messageBags['errors']);
+
+ return Redirect::route('categories.edit', $category->id)->withInput();
+ break;
}
diff --git a/app/controllers/ChartController.php b/app/controllers/ChartController.php
deleted file mode 100644
index 9b104ca379..0000000000
--- a/app/controllers/ChartController.php
+++ /dev/null
@@ -1,603 +0,0 @@
-_chart = $chart;
- $this->_accounts = $accounts;
- }
-
- /**
- * This method takes a budget, all limits and all their repetitions and displays three numbers per repetition:
- * the amount of money in the repetition (represented as "an envelope"), the amount spent and the spent percentage.
- *
- * @param Budget $budget
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function budgetDefault(\Budget $budget)
- {
- $expense = [];
- $left = [];
- $envelope = [];
- // get all limit repetitions for this budget.
- /** @var \Limit $limit */
- foreach ($budget->limits as $limit) {
- /** @var \LimitRepetition $rep */
- foreach ($limit->limitrepetitions as $rep) {
- // get the amount of money spent in this period on this budget.
- $spentInRep = $rep->amount - $rep->leftInRepetition();
- $pct = round((floatval($spentInRep) / floatval($limit->amount)) * 100, 2);
- $name = $rep->periodShow();
- $envelope[] = [$name, floatval($limit->amount)];
- $expense[] = [$name, floatval($spentInRep)];
- $left[] = [$name, $pct];
- }
- }
-
- $return = [
- 'chart_title' => 'Overview for budget ' . $budget->name,
- 'subtitle' => 'All envelopes',
- 'series' => [
- [
- 'type' => 'line',
- 'yAxis' => 1,
- 'name' => 'Amount in envelope',
- 'data' => $envelope
- ],
- [
- 'type' => 'column',
- 'name' => 'Expenses in envelope',
- 'data' => $expense
- ],
- [
- 'type' => 'line',
- 'yAxis' => 1,
- 'name' => 'Spent percentage for envelope',
- 'data' => $left
- ]
-
-
- ]
- ];
-
- return Response::json($return);
- }
-
- /**
- * This method takes a single limit repetition (so a single "envelope") and displays the amount of money spent
- * per day and subsequently how much money is left.
- *
- * @param LimitRepetition $rep
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function budgetLimit(\LimitRepetition $rep)
- {
- $budget = $rep->limit->budget;
- $current = clone $rep->startdate;
- $expense = [];
- $leftInLimit = [];
- $currentLeftInLimit = floatval($rep->limit->amount);
- while ($current <= $rep->enddate) {
- $spent = $this->_chart->spentOnDay($budget, $current);
- $spent = floatval($spent) == 0 ? null : floatval($spent);
- $entry = [$current->timestamp * 1000, $spent];
- $expense[] = $entry;
- $currentLeftInLimit = $currentLeftInLimit - $spent;
- $leftInLimit[] = [$current->timestamp * 1000, $currentLeftInLimit];
- $current->addDay();
- }
-
- $return = [
- 'chart_title' => 'Overview for budget ' . $budget->name,
- 'subtitle' =>
- 'Between ' . $rep->startdate->format('M jS, Y') . ' and ' . $rep->enddate->format('M jS, Y'),
- 'series' => [
- [
- 'type' => 'column',
- 'name' => 'Expenses per day',
- 'yAxis' => 1,
- 'data' => $expense
- ],
- [
- 'type' => 'line',
- 'name' => 'Left in envelope',
- 'data' => $leftInLimit
- ]
-
- ]
- ];
-
- return Response::json($return);
- }
-
- /**
- * This method takes a budget and gets all transactions in it which haven't got an envelope (limit).
- *
- * Usually this means that very old and unorganized or very NEW transactions get displayed; there was never an
- * envelope or it hasn't been created (yet).
- *
- *
- * @param Budget $budget
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function budgetNoLimits(\Budget $budget)
- {
- /*
- * Firefly can go about this two ways. Either it finds all transactions which definitely are IN an envelope
- * and exclude them or it searches for transactions outside of the range of any of the envelopes there are.
- *
- * Since either is kinda shitty Firefly uses the first one because it's easier to build.
- */
- $inRepetitions = $this->_chart->allJournalsInBudgetEnvelope($budget);
-
- /*
- * With this set of id's, Firefly can search for all journals NOT in that set.
- * BUT they have to be in the budget (duh).
- */
- $set = $this->_chart->journalsNotInSet($budget, $inRepetitions);
- /*
- * Next step: get all transactions for those journals.
- */
- $transactions = $this->_chart->transactionsByJournals($set);
-
-
- /*
- * this set builds the chart:
- */
- $expense = [];
-
- foreach ($transactions as $t) {
- $date = new Carbon($t->date);
- $expense[] = [$date->timestamp * 1000, floatval($t->aggregate)];
- }
- $return = [
- 'chart_title' => 'Overview for ' . $budget->name,
- 'subtitle' => 'Not organized by an envelope',
- 'series' => [
- [
- 'type' => 'column',
- 'name' => 'Expenses per day',
- 'data' => $expense
- ]
-
- ]
- ];
- return Response::json($return);
- }
-
- /**
- * This method gets all transactions within a budget within the period set by the current session
- * start and end date. It also includes any envelopes which might exist within this period.
- *
- * @param Budget $budget
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function budgetSession(\Budget $budget)
- {
- $series = [];
- $end = clone Session::get('end');
- $start = clone Session::get('start');
-
-
- /*
- * Expenses per day in the session's period. That's easy.
- */
- $expense = [];
- $current = clone Session::get('start');
- while ($current <= $end) {
- $spent = $this->_chart->spentOnDay($budget, $current);
- $spent = floatval($spent) == 0 ? null : floatval($spent);
- $expense[] = [$current->timestamp * 1000, $spent];
- $current->addDay();
- }
-
- $series[] = [
- 'type' => 'column',
- 'name' => 'Expenses per day',
- 'data' => $expense
- ];
- unset($expense, $spent, $current);
-
- /*
- * Find all limit repetitions (for this budget) between start and end. This is
- * quite a complex query.
- */
- $reps = $this->_chart->limitsInRange($budget, $start, $end);
-
- /*
- * For each limitrepetition Firefly creates a serie that contains the amount left in
- * the limitrepetition for its entire date-range. Entries are only actually included when they
- * fall into the charts date range.
- *
- * So example: the user has a session date from Jan 15 to Jan 30. The limitrepetition
- * starts at 1 Jan until 1 Feb.
- *
- * Firefly loops from 1 Jan to 1 Feb but only includes Jan 15 / Jan 30.
- * But it does keep count of the amount outside of these dates because otherwise the line might be wrong.
- */
- /** @var \LimitRepetition $repetition */
- foreach ($reps as $repetition) {
- $limitAmount = $repetition->limit->amount;
-
- // create a serie for the repetition.
- $currentSerie = [
- 'type' => 'spline',
- 'id' => 'rep-' . $repetition->id,
- 'yAxis' => 1,
- 'name' => 'Envelope #' . $repetition->id . ' in ' . $repetition->periodShow(),
- 'data' => []
- ];
- $current = clone $repetition->startdate;
- while ($current <= $repetition->enddate) {
- if ($current >= $start && $current <= $end) {
- // spent on limit:
- $spentSoFar = $this->_chart->spentOnLimitRepetitionBetweenDates(
- $repetition, $repetition->startdate, $current
- );
- $leftInLimit = floatval($limitAmount) - floatval($spentSoFar);
-
- $currentSerie['data'][] = [$current->timestamp * 1000, $leftInLimit];
- }
- $current->addDay();
- }
-
- // do something here.
- $series[] = $currentSerie;
- }
-
- $return = [
- 'chart_title' => 'Overview for budget ' . $budget->name,
- 'subtitle' =>
- 'Between ' . Session::get('start')->format('M jS, Y') . ' and ' . Session::get('end')->format(
- 'M jS, Y'
- ),
- 'series' => $series
- ];
-
- return Response::json($return);
-
- }
-
- /**
- * @param Category $category
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function categoryShowChart(Category $category)
- {
- $start = Session::get('start');
- $end = Session::get('end');
- $range = Session::get('range');
-
- $serie = $this->_chart->categoryShowChart($category, $range, $start, $end);
- $data = [
- 'chart_title' => $category->name,
- 'subtitle' => 'View more ',
- 'series' => $serie
- ];
-
- return Response::json($data);
-
-
- }
-
- /**
- * @param Account $account
- *
- * @return mixed
- */
- public function homeAccount(Account $account = null)
- {
- // get preferences and accounts (if necessary):
- $start = Session::get('start');
- $end = Session::get('end');
-
- if (is_null($account)) {
- // get, depending on preferences:
- /** @var \Firefly\Helper\Preferences\PreferencesHelperInterface $prefs */
- $prefs = \App::make('Firefly\Helper\Preferences\PreferencesHelperInterface');
- $pref = $prefs->get('frontpageAccounts', []);
-
- /** @var \Firefly\Storage\Account\AccountRepositoryInterface $acct */
- $acct = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
- $accounts = $acct->getByIds($pref->data);
- } else {
- $accounts = [$account];
- }
- // loop and get array data.
-
- $url = count($accounts) == 1 && is_array($accounts)
- ? 'View more '
- :
- 'View more ';
- $data = [
- 'chart_title' => count($accounts) == 1 ? $accounts[0]->name : 'All accounts',
- 'subtitle' => $url,
- 'series' => []
- ];
-
- foreach ($accounts as $account) {
- $data['series'][] = $this->_chart->account($account, $start, $end);
- }
-
- return Response::json($data);
- }
-
- /**
- * @param $name
- * @param $day
- * @param $month
- * @param $year
- *
- * @return $this
- */
- public function homeAccountInfo($name, $day, $month, $year)
- {
- $account = $this->_accounts->findByName($name);
-
- $date = Carbon::createFromDate($year, $month, $day);
- $result = $this->_chart->accountDailySummary($account, $date);
-
- return View::make('charts.info')->with('rows', $result['rows'])->with('sum', $result['sum'])->with(
- 'account', $account
- );
- }
-
- /**
- * @return \Illuminate\Http\JsonResponse
- */
- public function homeBudgets()
- {
- $start = Session::get('start');
- $end = Session::get('end');
- $data = [
- 'labels' => [],
- 'series' => [
- [
- 'name' => 'Limit',
- 'data' => []
- ],
- [
- 'name' => 'Spent',
- 'data' => []
- ],
- ]
- ];
-
- // Get all budgets.
- $budgets = \Auth::user()->budgets()->orderBy('name', 'ASC')->get();
- $budgetIds = [];
- /** @var \Budget $budget */
- foreach ($budgets as $budget) {
- $budgetIds[] = $budget->id;
-
- // Does the budget have a limit starting on $start?
- $rep = \LimitRepetition::
- leftJoin('limits', 'limit_repetitions.limit_id', '=', 'limits.id')->leftJoin(
- 'components', 'limits.component_id', '=', 'components.id'
- )->where('limit_repetitions.startdate', $start->format('Y-m-d'))->where(
- 'components.id', $budget->id
- )->first(['limit_repetitions.*']);
-
- if (is_null($rep)) {
- $limit = 0.0;
- $id = null;
- $parameter = 'useSession=true';
- } else {
- $limit = floatval($rep->amount);
- $id = $rep->id;
- $parameter = '';
- }
-
- // Date range to check for expenses made?
- if (is_null($rep)) {
- // use the session start and end for our search query
- $expenseStart = Session::get('start');
- $expenseEnd = Session::get('end');
-
- } else {
- // use the limit's start and end for our search query
- $expenseStart = $rep->startdate;
- $expenseEnd = $rep->enddate;
- }
- // How much have we spent on this budget?
- $expenses = floatval($budget->transactionjournals()->before($expenseEnd)->after($expenseStart)->lessThan(0)->sum('amount')) * -1;
-
- // Append to chart:
- if ($limit > 0 || $expenses > 0) {
- $data['labels'][] = $budget->name;
- $data['series'][0]['data'][] = [
- 'y' => $limit,
- 'url' => route('budgets.show', [$budget->id, $id]) . '?' . $parameter
- ];
- $data['series'][1]['data'][] = [
- 'y' => $expenses,
- 'url' => route('budgets.show', [$budget->id, $id]) . '?' . $parameter
- ];
- }
- }
- // Add expenses that have no budget:
- $set = \Auth::user()->transactionjournals()->whereNotIn(
- 'transaction_journals.id', function ($query) use ($start, $end) {
- $query->select('transaction_journals.id')->from('transaction_journals')
- ->leftJoin(
- 'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
- 'transaction_journals.id'
- )
- ->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id')
- ->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
- ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
- ->where('components.class', 'Budget');
- }
- )->before($end)->after($start)->lessThan(0)->transactionTypes(['Withdrawal'])->sum('amount');
-
- // This can be debugged by using get(['transaction_journals.*','transactions.amount']);
- $data['labels'][] = 'No budget';
- $data['series'][0]['data'][] = [
- 'y' => 0,
- 'url' => route('budgets.nobudget', 'session')
- ];
- $data['series'][1]['data'][] = [
- 'y' => floatval($set) * -1,
- 'url' => route('budgets.nobudget', 'session')
- ];
-
- return Response::json($data);
-
- }
-
- /**
- * @return \Illuminate\Http\JsonResponse
- */
- public function homeCategories()
- {
- $start = Session::get('start');
- $end = Session::get('end');
-
- return Response::json($this->_chart->categories($start, $end));
-
-
- }
-
- /**
- * This method checks all recurring transactions, calculates the current "moment" and returns
- * a list of yet to be paid (and paid) recurring transactions. This list can be used to show a beautiful chart
- * to the end user who will love it and cherish it.
- *
- * @throws FireflyException
- */
- public function homeRecurring()
- {
- /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */
- $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface');
-
- /*
- * Set of paid transaction journals.
- * Set of unpaid recurring transactions.
- */
- $paid = [];
- $unpaid = [];
-
- /*
- * Loop the recurring transactions.
- */
-
- /** @var \RecurringTransaction $recurring */
- foreach (\Auth::user()->recurringtransactions()->get() as $recurring) {
- /*
- * Start another loop starting at the $date.
- */
- $start = clone $recurring->date;
- $end = Carbon::now();
-
- /*
- * The jump we make depends on the $repeat_freq
- */
- $current = clone $start;
-
- while ($current <= $end) {
- /*
- * Get end of period for $current:
- */
- $currentEnd = clone $current;
- $toolkit->endOfPeriod($currentEnd, $recurring->repeat_freq);
-
- /*
- * In the current session range?
- */
- if (\Session::get('end') >= $current and $currentEnd >= \Session::get('start')) {
- /*
- * Lets see if we've already spent money on this recurring transaction (it hath recurred).
- */
- /** @var TransactionJournal $set */
- $transaction = \Auth::user()->transactionjournals()->where('recurring_transaction_id', $recurring->id)->after($current)->before($currentEnd)->first();
-
- if(is_null($transaction)) {
- $unpaid[] = $recurring;
- } else {
- $paid[] = $transaction;
- }
- }
-
- /*
- * Add some time for the next loop!
- */
- $toolkit->addPeriod($current, $recurring->repeat_freq, intval($recurring->skip));
-
- }
-
- }
- /*
- * Get some colors going.
- */
- $unPaidColours = $toolkit->colorRange('AA4643', 'FFFFFF', count($unpaid) == 0 ? 1 : count($unpaid));
- $paidColours = $toolkit->colorRange('4572A7', 'FFFFFF', count($paid) == 0 ? 1 : count($paid));
-
- /*
- * The chart serie:
- */
- $serie = [
- 'type' => 'pie',
- 'name' => 'Amount',
- 'data' => []
- ];
-
- /*
- * Loop paid and unpaid to make two haves for a pie chart.
- */
- /** @var TransactionJournal $entry */
- foreach ($paid as $index => $entry) {
- $transactions = $entry->transactions()->get();
- $amount = max(floatval($transactions[0]->amount), floatval($transactions[1]->amount));
- $serie['data'][] = [
- 'name' => 'Already paid "'.$entry->description.'"',
- 'y' => $amount,
- 'url' => route('transactions.show',$entry->id),
- 'objType' => 'paid',
- 'color' => $paidColours[$index]
- ];
- }
-
-
- /** @var RecurringTransaction $entry */
- foreach ($unpaid as $index => $entry) {
- $amount = (floatval($entry->amount_max) + floatval($entry->amount_min)) / 2;
- $serie['data'][] = [
- 'name' => 'Still due: '.$entry->name,
- 'y' => $amount,
- 'url' => route('recurring.show',$entry->id),
- 'objType' => 'unpaid',
- 'color' => $unPaidColours[$index]
- ];
- }
-
- return Response::json([$serie]);
-
- }
-}
\ No newline at end of file
diff --git a/app/controllers/GoogleChartController.php b/app/controllers/GoogleChartController.php
index daeedcfddd..0eb2b58396 100644
--- a/app/controllers/GoogleChartController.php
+++ b/app/controllers/GoogleChartController.php
@@ -7,6 +7,209 @@ use Carbon\Carbon;
class GoogleChartController extends BaseController
{
+ /**
+ * @param Account $account
+ * @param string $view
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function accountBalanceChart(Account $account, $view = 'session')
+ {
+ /** @var \Grumpydictator\Gchart\GChart $chart */
+ $chart = App::make('gchart');
+
+ $chart->addColumn('Day of month', 'date');
+ $chart->addColumn('Balance for ' . $account->name, 'number');
+
+ /*
+ * Loop the date, then loop the accounts, then add balance.
+ */
+ switch ($view) {
+ default:
+ case 'session':
+ $start = Session::get('start');
+ $end = Session::get('end');
+ break;
+ case 'all':
+ $first = $account->transactionjournals()->orderBy('date', 'DESC')->first();
+ $last = $account->transactionjournals()->orderBy('date', 'ASC')->first();
+ if (is_null($first)) {
+ $start = Session::get('start');
+ } else {
+ $start = clone $first->date;
+ }
+ if (is_null($last)) {
+ $end = Session::get('end');
+ } else {
+ $end = clone $last->date;
+ }
+ break;
+ }
+
+ $current = clone $start;
+
+ while ($end >= $current) {
+ $row = [clone $current];
+ if ($current > Carbon::now()) {
+ $row[] = null;
+ } else {
+ $row[] = Steam::balance($account, $current);
+ }
+
+ $chart->addRowArray($row);
+ $current->addDay();
+ }
+
+
+ $chart->generate();
+
+ return Response::json($chart->getData());
+ }
+
+ /**
+ * @param Account $account
+ * @param string $view
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function accountSankeyInChart(Account $account, $view = 'session')
+ {
+ // collect all relevant entries.
+ $set = [];
+
+ /** @var \Grumpydictator\Gchart\GChart $chart */
+ $chart = App::make('gchart');
+ $chart->addColumn('From', 'string');
+ $chart->addColumn('To', 'string', 'domain');
+ $chart->addColumn('Weight', 'number');
+
+ switch ($view) {
+ default:
+ case 'session':
+ $start = Session::get('start');
+ $end = Session::get('end');
+ break;
+ case 'all':
+ $first = $account->transactionjournals()->orderBy('date', 'DESC')->first();
+ $last = $account->transactionjournals()->orderBy('date', 'ASC')->first();
+ if (is_null($first)) {
+ $start = Session::get('start');
+ } else {
+ $start = clone $first->date;
+ }
+ if (is_null($last)) {
+ $end = Session::get('end');
+ } else {
+ $end = clone $last->date;
+ }
+ break;
+ }
+
+
+ $transactions = $account->transactions()->with(
+ ['transactionjournal', 'transactionjournal.transactions' => function ($q) {
+ $q->where('amount', '<', 0);
+ }, 'transactionjournal.budgets', 'transactionjournal.transactiontype', 'transactionjournal.categories']
+ )->before($end)->after($start)->get();
+
+ /** @var Transaction $transaction */
+ foreach ($transactions as $transaction) {
+ $amount = floatval($transaction->amount);
+ $type = $transaction->transactionJournal->transactionType->type;
+
+ if ($amount > 0 && $type != 'Transfer') {
+
+ $otherAccount = $transaction->transactionJournal->transactions[0]->account->name;
+ $categoryName = isset($transaction->transactionJournal->categories[0]) ? $transaction->transactionJournal->categories[0]->name : '(no cat)';
+ $set[] = [$otherAccount, $categoryName, $amount];
+ $set[] = [$categoryName, $account->name, $amount];
+ }
+ }
+ // loop the set, group everything together:
+ $grouped = [];
+ foreach ($set as $entry) {
+ $key = $entry[0] . $entry[1];
+ if (isset($grouped[$key])) {
+ $grouped[$key][2] += $entry[2];
+ } else {
+ $grouped[$key] = $entry;
+ }
+ }
+
+ // add rows to the chart:
+ foreach ($grouped as $entry) {
+ $chart->addRow($entry[0], $entry[1], $entry[2]);
+ }
+
+ $chart->generate();
+
+ return Response::json($chart->getData());
+
+ }
+
+ /**
+ * @param Account $account
+ * @param string $view
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function accountSankeyOutChart(Account $account, $view = 'session')
+ {
+ // collect all relevant entries.
+ $set = [];
+
+ /** @var \Grumpydictator\Gchart\GChart $chart */
+ $chart = App::make('gchart');
+ $chart->addColumn('From', 'string');
+ $chart->addColumn('To', 'string', 'domain');
+ $chart->addColumn('Weight', 'number');
+
+ $transactions = $account->transactions()->with(
+ ['transactionjournal', 'transactionjournal.transactions', 'transactionjournal.budgets', 'transactionjournal.transactiontype',
+ 'transactionjournal.categories']
+ )->before(Session::get('end'))->after(
+ Session::get('start')
+ )->get();
+
+ /** @var Transaction $transaction */
+ foreach ($transactions as $transaction) {
+ $amount = floatval($transaction->amount);
+ $type = $transaction->transactionJournal->transactionType->type;
+
+ if ($amount < 0 && $type != 'Transfer') {
+
+ // from account to a budget (if present).
+ $budgetName = isset($transaction->transactionJournal->budgets[0]) ? $transaction->transactionJournal->budgets[0]->name : '(no budget)';
+ $set[] = [$account->name, $budgetName, $amount * -1];
+
+ // from budget to category.
+ $categoryName = isset($transaction->transactionJournal->categories[0]) ? ' ' . $transaction->transactionJournal->categories[0]->name
+ : '(no cat)';
+ $set[] = [$budgetName, $categoryName, $amount * -1];
+ }
+ }
+ // loop the set, group everything together:
+ $grouped = [];
+ foreach ($set as $entry) {
+ $key = $entry[0] . $entry[1];
+ if (isset($grouped[$key])) {
+ $grouped[$key][2] += $entry[2];
+ } else {
+ $grouped[$key] = $entry;
+ }
+ }
+
+ // add rows to the chart:
+ foreach ($grouped as $entry) {
+ $chart->addRow($entry[0], $entry[1], $entry[2]);
+ }
+
+ $chart->generate();
+
+ return Response::json($chart->getData());
+
+ }
+
/**
* This method renders the b
*/
@@ -18,11 +221,15 @@ class GoogleChartController extends BaseController
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
- $pref = $preferences->get('frontpageAccounts');
+ $pref = $preferences->get('frontpageAccounts', []);
/** @var \FireflyIII\Database\Account $acct */
- $acct = App::make('FireflyIII\Database\Account');
- $accounts = $acct->getByIds($pref->data);
+ $acct = App::make('FireflyIII\Database\Account');
+ if (count($pref->data) > 0) {
+ $accounts = $acct->getByIds($pref->data);
+ } else {
+ $accounts = $acct->getAssetAccounts();
+ }
/*
@@ -43,12 +250,7 @@ class GoogleChartController extends BaseController
$row = [clone $current];
foreach ($accounts as $account) {
- //if ($current > Carbon::now()) {
- // $row[] = 0;
- //} else {
- $row[] = $account->balance($current);
- //}
-
+ $row[] = Steam::balance($account, $current);
}
$chart->addRowArray($row);
@@ -56,191 +258,11 @@ class GoogleChartController extends BaseController
}
$chart->generate();
+
return Response::json($chart->getData());
}
- /**
- * @param $year
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function yearInExp($year)
- {
- try {
- $start = new Carbon('01-01-' . $year);
- } catch (Exception $e) {
- App::abort(500);
- }
- /** @var \Grumpydictator\Gchart\GChart $chart */
- $chart = App::make('gchart');
- $chart->addColumn('Month', 'date');
- $chart->addColumn('Income', 'number');
- $chart->addColumn('Expenses', 'number');
-
- /** @var \FireflyIII\Database\TransactionJournal $tj */
- $tj = App::make('FireflyIII\Database\TransactionJournal');
-
- $end = clone $start;
- $end->endOfYear();
- while ($start < $end) {
-
- // total income:
- $income = $tj->getSumOfIncomesByMonth($start);
- $expense = $tj->getSumOfExpensesByMonth($start);
-
- $chart->addRow(clone $start, $income, $expense);
- $start->addMonth();
- }
-
-
- $chart->generate();
- return Response::json($chart->getData());
-
- }
-
- /**
- * @param $year
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function yearInExpSum($year)
- {
- try {
- $start = new Carbon('01-01-' . $year);
- } catch (Exception $e) {
- App::abort(500);
- }
- /** @var \Grumpydictator\Gchart\GChart $chart */
- $chart = App::make('gchart');
- $chart->addColumn('Summary', 'string');
- $chart->addColumn('Income', 'number');
- $chart->addColumn('Expenses', 'number');
-
- /** @var \FireflyIII\Database\TransactionJournal $tj */
- $tj = App::make('FireflyIII\Database\TransactionJournal');
-
- $end = clone $start;
- $end->endOfYear();
- $income = 0;
- $expense = 0;
- $count = 0;
- while ($start < $end) {
-
- // total income:
- $income += $tj->getSumOfIncomesByMonth($start);
- $expense += $tj->getSumOfExpensesByMonth($start);
- $count++;
-
- $start->addMonth();
- }
- $chart->addRow('Sum', $income, $expense);
- $count = $count > 0 ? $count : 1;
- $chart->addRow('Average', ($income / $count), ($expense / $count));
-
-
- $chart->generate();
- return Response::json($chart->getData());
-
- }
-
-
- /**
- * @return \Illuminate\Http\JsonResponse
- */
- public function budgetsReportChart($year)
- {
-
- try {
- $start = new Carbon('01-01-' . $year);
- } catch (Exception $e) {
- App::abort(500);
- }
-
- /** @var \Grumpydictator\Gchart\GChart $chart */
- $chart = App::make('gchart');
-
- /** @var \FireflyIII\Database\Budget $bdt */
- $bdt = App::make('FireflyIII\Database\Budget');
- $budgets = $bdt->get();
-
- $chart->addColumn('Month', 'date');
- /** @var \Budget $budget */
- foreach ($budgets as $budget) {
- $chart->addColumn($budget->name, 'number');
- }
- $chart->addColumn('No budget','number');
-
- /*
- * Loop budgets this year.
- */
- $end = clone $start;
- $end->endOfYear();
- while ($start <= $end) {
- $row = [clone $start];
-
- foreach($budgets as $budget) {
- $row[] = $bdt->spentInMonth($budget, $start);
- }
-
- /*
- * Without a budget:
- */
- $endOfMonth = clone $start;
- $endOfMonth->endOfMonth();
- $set = $bdt->transactionsWithoutBudgetInDateRange($start, $endOfMonth);
- $row[] = floatval($set->sum('amount')) * -1;
-
- $chart->addRowArray($row);
- $start->addMonth();
- }
-
-
- $chart->generate();
- return Response::json($chart->getData());
- }
-
- public function budgetsAndSpending(Budget $budget, $year) {
- try {
- $start = new Carbon('01-01-' . $year);
- } catch (Exception $e) {
- App::abort(500);
- }
-
- /** @var \FireflyIII\Database\Budget $bdt */
- $bdt = App::make('FireflyIII\Database\Budget');
-
- /** @var \Grumpydictator\Gchart\GChart $chart */
- $chart = App::make('gchart');
- $chart->addColumn('Month', 'date');
- $chart->addColumn('Budgeted', 'number');
- $chart->addColumn('Spent', 'number');
-
- $end = clone $start;
- $end->endOfYear();
- while($start <= $end) {
-
- $spent = $bdt->spentInMonth($budget, $start);
- $repetition = $bdt->repetitionOnStartingOnDate($budget, $start);
- if($repetition) {
- $budgeted = floatval($repetition->amount);
- } else {
- $budgeted = 0;
- }
-
- $chart->addRow(clone $start, $budgeted, $spent);
-
- $start->addMonth();
- }
-
-
-
- $chart->generate();
- return Response::json($chart->getData());
-
-
- }
-
/**
* @return \Illuminate\Http\JsonResponse
*/
@@ -306,6 +328,7 @@ class GoogleChartController extends BaseController
$chart->generate();
+
return Response::json($chart->getData());
}
@@ -350,13 +373,224 @@ class GoogleChartController extends BaseController
$chart->generate();
+
+ return Response::json($chart->getData());
+
+ }
+
+ /**
+ * @param Budget $budget
+ * @param LimitRepetition $repetition
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function budgetLimitSpending(\Budget $budget, \LimitRepetition $repetition)
+ {
+ $start = clone $repetition->startdate;
+ $end = $repetition->enddate;
+
+ /** @var \Grumpydictator\Gchart\GChart $chart */
+ $chart = App::make('gchart');
+ $chart->addColumn('Day', 'date');
+ $chart->addColumn('Left', 'number');
+
+
+ $amount = $repetition->amount;
+
+ while ($start <= $end) {
+ /*
+ * Sum of expenses on this day:
+ */
+ $sum = floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($start)->sum('amount'));
+ $amount += $sum;
+ $chart->addRow(clone $start, $amount);
+ $start->addDay();
+ }
+ $chart->generate();
+
+ return Response::json($chart->getData());
+
+ }
+
+ /**
+ * @param $year
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function budgetsReportChart($year)
+ {
+
+ try {
+ $start = new Carbon('01-01-' . $year);
+ } catch (Exception $e) {
+ App::abort(500);
+ }
+
+ /** @var \Grumpydictator\Gchart\GChart $chart */
+ $chart = App::make('gchart');
+
+ /** @var \FireflyIII\Database\Budget $bdt */
+ $bdt = App::make('FireflyIII\Database\Budget');
+ $budgets = $bdt->get();
+
+ $chart->addColumn('Month', 'date');
+ /** @var \Budget $budget */
+ foreach ($budgets as $budget) {
+ $chart->addColumn($budget->name, 'number');
+ }
+ $chart->addColumn('No budget', 'number');
+
+ /*
+ * Loop budgets this year.
+ */
+ $end = clone $start;
+ $end->endOfYear();
+ while ($start <= $end) {
+ $row = [clone $start];
+
+ foreach ($budgets as $budget) {
+ $row[] = $bdt->spentInMonth($budget, $start);
+ }
+
+ /*
+ * Without a budget:
+ */
+ $endOfMonth = clone $start;
+ $endOfMonth->endOfMonth();
+ $set = $bdt->transactionsWithoutBudgetInDateRange($start, $endOfMonth);
+ $row[] = floatval($set->sum('amount')) * -1;
+
+ $chart->addRowArray($row);
+ $start->addMonth();
+ }
+
+
+ $chart->generate();
+
+ return Response::json($chart->getData());
+ }
+
+ /**
+ * @param Component $component
+ * @param $year
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function componentsAndSpending(Component $component, $year)
+ {
+ try {
+ $start = new Carbon('01-01-' . $year);
+ } catch (Exception $e) {
+ App::abort(500);
+ }
+
+ if ($component->class == 'Budget') {
+ /** @var \FireflyIII\Database\Budget $repos */
+ $repos = App::make('FireflyIII\Database\Budget');
+ } else {
+ /** @var \FireflyIII\Database\Category $repos */
+ $repos = App::make('FireflyIII\Database\Category');
+ }
+
+ /** @var \Grumpydictator\Gchart\GChart $chart */
+ $chart = App::make('gchart');
+ $chart->addColumn('Month', 'date');
+ $chart->addColumn('Budgeted', 'number');
+ $chart->addColumn('Spent', 'number');
+
+ $end = clone $start;
+ $end->endOfYear();
+ while ($start <= $end) {
+
+ $spent = $repos->spentInMonth($component, $start);
+ $repetition = $repos->repetitionOnStartingOnDate($component, $start);
+ if ($repetition) {
+ $budgeted = floatval($repetition->amount);
+ } else {
+ $budgeted = null;
+ }
+
+ $chart->addRow(clone $start, $budgeted, $spent);
+
+ $start->addMonth();
+ }
+
+
+ $chart->generate();
+
+ return Response::json($chart->getData());
+
+
+ }
+
+ /**
+ * @param Piggybank $piggybank
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function piggyBankHistory(\Piggybank $piggybank)
+ {
+ /** @var \Grumpydictator\Gchart\GChart $chart */
+ $chart = App::make('gchart');
+ $chart->addColumn('Date', 'date');
+ $chart->addColumn('Balance', 'number');
+
+ $set = \DB::table('piggybank_events')->where('piggybank_id', $piggybank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]);
+
+ foreach ($set as $entry) {
+ $chart->addRow(new Carbon($entry->date), floatval($entry->sum));
+ }
+
+ $chart->generate();
+
+ return Response::json($chart->getData());
+
+ }
+
+ /**
+ * @param RecurringTransaction $recurring
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function recurringOverview(RecurringTransaction $recurring)
+ {
+
+ /** @var \Grumpydictator\Gchart\GChart $chart */
+ $chart = App::make('gchart');
+ $chart->addColumn('Date', 'date');
+ $chart->addColumn('Max amount', 'number');
+ $chart->addColumn('Min amount', 'number');
+ $chart->addColumn('Current entry', 'number');
+
+ // get first transaction or today for start:
+ $first = $recurring->transactionjournals()->orderBy('date', 'ASC')->first();
+ if ($first) {
+ $start = $first->date;
+ } else {
+ $start = new Carbon;
+ }
+ $end = new Carbon;
+ while ($start <= $end) {
+ $result = $recurring->transactionjournals()->before($end)->after($start)->first();
+ if ($result) {
+ $amount = $result->getAmount();
+ } else {
+ $amount = 0;
+ }
+ unset($result);
+ $chart->addRow(clone $start, $recurring->amount_max, $recurring->amount_min, $amount);
+ $start = DateKit::addPeriod($start, $recurring->repeat_freq, 0);
+ }
+
+ $chart->generate();
+
return Response::json($chart->getData());
}
/**
* @return \Illuminate\Http\JsonResponse
- * @throws \Firefly\Exception\FireflyException
+ * @throws \FireflyIII\Exception\FireflyException
*/
public function recurringTransactionsOverview()
{
@@ -365,14 +599,8 @@ class GoogleChartController extends BaseController
* Set of paid transaction journals.
* Set of unpaid recurring transactions.
*/
- $paid = [
- 'items' => [],
- 'amount' => 0
- ];
- $unpaid = [
- 'items' => [],
- 'amount' => 0
- ];
+ $paid = ['items' => [], 'amount' => 0];
+ $unpaid = ['items' => [], 'amount' => 0];
/** @var \Grumpydictator\Gchart\GChart $chart */
$chart = App::make('gchart');
@@ -382,9 +610,6 @@ class GoogleChartController extends BaseController
/** @var \FireflyIII\Database\Recurring $rcr */
$rcr = App::make('FireflyIII\Database\Recurring');
- /** @var \FireflyIII\Shared\Toolkit\Date $dateKit */
- $dateKit = App::make('FireflyIII\Shared\Toolkit\Date');
-
$recurring = $rcr->get();
/** @var \RecurringTransaction $entry */
@@ -404,8 +629,7 @@ class GoogleChartController extends BaseController
/*
* Get end of period for $current:
*/
- $currentEnd = clone $current;
- $dateKit->endOfPeriod($currentEnd, $entry->repeat_freq);
+ $currentEnd = DateKit::endOfPeriod($current, $entry->repeat_freq);
/*
* In the current session range?
@@ -430,7 +654,7 @@ class GoogleChartController extends BaseController
/*
* Add some time for the next loop!
*/
- $dateKit->addPeriod($current, $entry->repeat_freq, intval($entry->skip));
+ $current = DateKit::addPeriod($current, $entry->repeat_freq, intval($entry->skip));
}
@@ -440,160 +664,93 @@ class GoogleChartController extends BaseController
$chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']);
$chart->generate();
+
return Response::json($chart->getData());
}
/**
- * @param Account $account
- */
- public function accountBalanceChart(Account $account)
- {
- /** @var \Grumpydictator\Gchart\GChart $chart */
- $chart = App::make('gchart');
- $chart->addColumn('Day of month', 'date');
- $chart->addColumn('Balance for ' . $account->name, 'number');
-
- /*
- * Loop the date, then loop the accounts, then add balance.
- */
- $start = Session::get('start');
- $end = Session::get('end');
- $current = clone $start;
-
- while ($end >= $current) {
- $row = [clone $current];
- if ($current > Carbon::now()) {
- $row[] = null;
- } else {
- $row[] = $account->balance($current);
- }
-
- $chart->addRowArray($row);
- $current->addDay();
- }
-
-
- $chart->generate();
- return Response::json($chart->getData());
- }
-
- /**
- * @param Account $account
+ * @param $year
*
* @return \Illuminate\Http\JsonResponse
*/
- public function accountSankeyOutChart(Account $account)
+ public function yearInExp($year)
{
- // collect all relevant entries.
- $set = [];
-
+ try {
+ $start = new Carbon('01-01-' . $year);
+ } catch (Exception $e) {
+ App::abort(500);
+ }
/** @var \Grumpydictator\Gchart\GChart $chart */
$chart = App::make('gchart');
- $chart->addColumn('From', 'string');
- $chart->addColumn('To', 'string', 'domain');
- $chart->addColumn('Weight', 'number');
+ $chart->addColumn('Month', 'date');
+ $chart->addColumn('Income', 'number');
+ $chart->addColumn('Expenses', 'number');
- $transactions = $account->transactions()->with(
- ['transactionjournal', 'transactionjournal.transactions', 'transactionjournal.budgets', 'transactionjournal.transactiontype',
- 'transactionjournal.categories']
- )->before(Session::get('end'))->after(
- Session::get('start')
- )->get();
+ /** @var \FireflyIII\Database\TransactionJournal $tj */
+ $tj = App::make('FireflyIII\Database\TransactionJournal');
- /** @var Transaction $transaction */
- foreach ($transactions as $transaction) {
- $amount = floatval($transaction->amount);
- $type = $transaction->transactionJournal->transactionType->type;
+ $end = clone $start;
+ $end->endOfYear();
+ while ($start < $end) {
- if ($amount < 0 && $type != 'Transfer') {
+ // total income:
+ $income = $tj->getSumOfIncomesByMonth($start);
+ $expense = $tj->getSumOfExpensesByMonth($start);
- // from account to a budget (if present).
- $budgetName = isset($transaction->transactionJournal->budgets[0]) ? $transaction->transactionJournal->budgets[0]->name : '(no budget)';
- $set[] = [$account->name, $budgetName, $amount * -1];
-
- // from budget to category.
- $categoryName = isset($transaction->transactionJournal->categories[0]) ? ' ' . $transaction->transactionJournal->categories[0]->name
- : '(no cat)';
- $set[] = [$budgetName, $categoryName, $amount * -1];
- }
- }
- // loop the set, group everything together:
- $grouped = [];
- foreach ($set as $entry) {
- $key = $entry[0] . $entry[1];
- if (isset($grouped[$key])) {
- $grouped[$key][2] += $entry[2];
- } else {
- $grouped[$key] = $entry;
- }
+ $chart->addRow(clone $start, $income, $expense);
+ $start->addMonth();
}
- // add rows to the chart:
- foreach ($grouped as $entry) {
- $chart->addRow($entry[0], $entry[1], $entry[2]);
- }
$chart->generate();
+
return Response::json($chart->getData());
}
/**
- * @param Account $account
+ * @param $year
*
* @return \Illuminate\Http\JsonResponse
*/
- public function accountSankeyInChart(Account $account)
+ public function yearInExpSum($year)
{
- // collect all relevant entries.
- $set = [];
-
+ try {
+ $start = new Carbon('01-01-' . $year);
+ } catch (Exception $e) {
+ App::abort(500);
+ }
/** @var \Grumpydictator\Gchart\GChart $chart */
$chart = App::make('gchart');
- $chart->addColumn('From', 'string');
- $chart->addColumn('To', 'string', 'domain');
- $chart->addColumn('Weight', 'number');
+ $chart->addColumn('Summary', 'string');
+ $chart->addColumn('Income', 'number');
+ $chart->addColumn('Expenses', 'number');
- $transactions = $account->transactions()->with(
- ['transactionjournal', 'transactionjournal.transactions' => function ($q) {
- $q->where('amount', '<', 0);
- }, 'transactionjournal.budgets', 'transactionjournal.transactiontype', 'transactionjournal.categories']
- )->before(Session::get('end'))->after(
- Session::get('start')
- )->get();
+ /** @var \FireflyIII\Database\TransactionJournal $tj */
+ $tj = App::make('FireflyIII\Database\TransactionJournal');
- /** @var Transaction $transaction */
- foreach ($transactions as $transaction) {
- $amount = floatval($transaction->amount);
- $type = $transaction->transactionJournal->transactionType->type;
+ $end = clone $start;
+ $end->endOfYear();
+ $income = 0;
+ $expense = 0;
+ $count = 0;
+ while ($start < $end) {
- if ($amount > 0 && $type != 'Transfer') {
+ // total income:
+ $income += $tj->getSumOfIncomesByMonth($start);
+ $expense += $tj->getSumOfExpensesByMonth($start);
+ $count++;
- $otherAccount = $transaction->transactionJournal->transactions[0]->account->name;
- $categoryName = isset($transaction->transactionJournal->categories[0]) ? $transaction->transactionJournal->categories[0]->name
- : '(no cat)';
- $set[] = [$otherAccount, $categoryName, $amount];
- $set[] = [$categoryName, $account->name, $amount];
- }
- }
- // loop the set, group everything together:
- $grouped = [];
- foreach ($set as $entry) {
- $key = $entry[0] . $entry[1];
- if (isset($grouped[$key])) {
- $grouped[$key][2] += $entry[2];
- } else {
- $grouped[$key] = $entry;
- }
+ $start->addMonth();
}
+ $chart->addRow('Sum', $income, $expense);
+ $count = $count > 0 ? $count : 1;
+ $chart->addRow('Average', ($income / $count), ($expense / $count));
- // add rows to the chart:
- foreach ($grouped as $entry) {
- $chart->addRow($entry[0], $entry[1], $entry[2]);
- }
$chart->generate();
+
return Response::json($chart->getData());
}
diff --git a/app/controllers/GoogleTableController.php b/app/controllers/GoogleTableController.php
deleted file mode 100644
index 8f51270363..0000000000
--- a/app/controllers/GoogleTableController.php
+++ /dev/null
@@ -1,240 +0,0 @@
-getAssetAccounts();
- break;
- case 'expense':
- $list = $acct->getExpenseAccounts();
- break;
- case 'revenue':
- $list = $acct->getRevenueAccounts();
- break;
- }
-
-
- $chart = App::make('gchart');
- $chart->addColumn('ID', 'number');
- $chart->addColumn('ID_Edit', 'string');
- $chart->addColumn('ID_Delete', 'string');
- $chart->addColumn('Name_URL', 'string');
- $chart->addColumn('Name', 'string');
- $chart->addColumn('Balance', 'number');
-
- /** @var \Account $entry */
- foreach ($list as $entry) {
- $edit = route('accounts.edit', $entry->id);
- $delete = route('accounts.delete', $entry->id);
- $show = route('accounts.show', $entry->id);
- $chart->addRow($entry->id, $edit, $delete, $show, $entry->name, $entry->balance());
- }
-
- $chart->generate();
- return Response::json($chart->getData());
-
-
- }
-
- /**
- * @param Budget $budget
- * @param LimitRepetition $repetition
- */
- public function transactionsByBudget(Budget $budget, LimitRepetition $repetition = null)
- {
- /** @var \Grumpydictator\Gchart\GChart $chart */
- $chart = App::make('gchart');
- $chart->addColumn('ID', 'number');
- $chart->addColumn('ID_Edit', 'string');
- $chart->addColumn('ID_Delete', 'string');
- $chart->addColumn('Date', 'date');
- $chart->addColumn('Description_URL', 'string');
- $chart->addColumn('Description', 'string');
- $chart->addColumn('Amount', 'number');
- $chart->addColumn('From_URL', 'string');
- $chart->addColumn('From', 'string');
- $chart->addColumn('To_URL', 'string');
- $chart->addColumn('To', 'string');
- $chart->addColumn('Budget_URL', 'string');
- $chart->addColumn('Budget', 'string');
- $chart->addColumn('Category_URL', 'string');
- $chart->addColumn('Category', 'string');
-
- if (is_null($repetition)) {
- $journals = $budget->transactionjournals()->with(['budgets', 'categories', 'transactions', 'transactions.account'])->orderBy('date', 'DESC')->get();
- } else {
- $journals = $budget->transactionjournals()->with(['budgets', 'categories', 'transactions', 'transactions.account'])->
- after($repetition->startdate)->before($repetition->enddate)->orderBy('date', 'DESC')->get();
- }
- /** @var TransactionJournal $transaction */
- foreach ($journals as $journal) {
- $date = $journal->date;
- $descriptionURL = route('transactions.show', $journal->id);
- $description = $journal->description;
- /** @var Transaction $transaction */
- foreach ($journal->transactions as $transaction) {
- if (floatval($transaction->amount) > 0) {
- $amount = floatval($transaction->amount);
- $to = $transaction->account->name;
- $toURL = route('accounts.show', $transaction->account->id);
- } else {
- $from = $transaction->account->name;
- $fromURL = route('accounts.show', $transaction->account->id);
- }
-
- }
- if (isset($journal->budgets[0])) {
- $budgetURL = route('budgets.show', $journal->budgets[0]->id);
- $budget = $journal->budgets[0]->name;
- } else {
- $budgetURL = '';
- $budget = '';
- }
-
- if (isset($journal->categories[0])) {
- $categoryURL = route('categories.show', $journal->categories[0]->id);
- $category = $journal->categories[0]->name;
- } else {
- $categoryURL = '';
- $category = '';
- }
-
-
- $id = $journal->id;
- $edit = route('transactions.edit', $journal->id);
- $delete = route('transactions.delete', $journal->id);
- $chart->addRow(
- $id, $edit, $delete, $date, $descriptionURL, $description, $amount, $fromURL, $from, $toURL, $to, $budgetURL, $budget, $categoryURL,
- $category
- );
- }
-
-
- $chart->generate();
- return Response::json($chart->getData());
-
- }
-
- /**
- * @param Account $account
- */
- public function transactionsByAccount(Account $account)
- {
- /** @var \Grumpydictator\Gchart\GChart $chart */
- $chart = App::make('gchart');
- $chart->addColumn('ID', 'number');
- $chart->addColumn('ID_Edit', 'string');
- $chart->addColumn('ID_Delete', 'string');
- $chart->addColumn('Date', 'date');
- $chart->addColumn('Description_URL', 'string');
- $chart->addColumn('Description', 'string');
- $chart->addColumn('Amount', 'number');
- $chart->addColumn('From_URL', 'string');
- $chart->addColumn('From', 'string');
- $chart->addColumn('To_URL', 'string');
- $chart->addColumn('To', 'string');
- $chart->addColumn('Budget_URL', 'string');
- $chart->addColumn('Budget', 'string');
- $chart->addColumn('Category_URL', 'string');
- $chart->addColumn('Category', 'string');
-
- /*
- * Find transactions:
- */
- $accountID = $account->id;
- $transactions = $account->transactions()->with(
- ['transactionjournal', 'transactionjournal.transactions' => function ($q) use ($accountID) {
- $q->where('account_id', '!=', $accountID);
- }, 'transactionjournal.budgets', 'transactionjournal.transactiontype',
- 'transactionjournal.categories']
- )->before(Session::get('end'))->after(
- Session::get('start')
- )->orderBy('date', 'DESC')->get();
-
- /** @var Transaction $transaction */
- foreach ($transactions as $transaction) {
- $date = $transaction->transactionJournal->date;
- $descriptionURL = route('transactions.show', $transaction->transaction_journal_id);
- $description = $transaction->transactionJournal->description;
- $amount = floatval($transaction->amount);
-
- if ($transaction->transactionJournal->transactions[0]->account->id == $account->id) {
- $opposingAccountURI = route('accounts.show', $transaction->transactionJournal->transactions[1]->account->id);
- $opposingAccountName = $transaction->transactionJournal->transactions[1]->account->name;
- } else {
- $opposingAccountURI = route('accounts.show', $transaction->transactionJournal->transactions[0]->account->id);
- $opposingAccountName = $transaction->transactionJournal->transactions[0]->account->name;
- }
- if (isset($transaction->transactionJournal->budgets[0])) {
- $budgetURL = route('budgets.show', $transaction->transactionJournal->budgets[0]->id);
- $budget = $transaction->transactionJournal->budgets[0]->name;
- } else {
- $budgetURL = '';
- $budget = '';
- }
-
- if (isset($transaction->transactionJournal->categories[0])) {
- $categoryURL = route('categories.show', $transaction->transactionJournal->categories[0]->id);
- $category = $transaction->transactionJournal->categories[0]->name;
- } else {
- $categoryURL = '';
- $category = '';
- }
-
-
- if ($amount < 0) {
- $from = $account->name;
- $fromURL = route('accounts.show', $account->id);
-
- $to = $opposingAccountName;
- $toURL = $opposingAccountURI;
- } else {
- $to = $account->name;
- $toURL = route('accounts.show', $account->id);
-
- $from = $opposingAccountName;
- $fromURL = $opposingAccountURI;
- }
-
- $id = $transaction->transactionJournal->id;
- $edit = route('transactions.edit', $transaction->transactionJournal->id);
- $delete = route('transactions.delete', $transaction->transactionJournal->id);
- $chart->addRow(
- $id, $edit, $delete, $date, $descriptionURL, $description, $amount, $fromURL, $from, $toURL, $to, $budgetURL, $budget, $categoryURL, $category
- );
- }
-
-//
Date
-// Description
-// Amount (€)
-// From
-// To
-// Budget / category
-// ID
-
-
- $chart->generate();
- return Response::json($chart->getData());
- }
-}
\ No newline at end of file
diff --git a/app/controllers/HelpController.php b/app/controllers/HelpController.php
new file mode 100644
index 0000000000..1424351c40
--- /dev/null
+++ b/app/controllers/HelpController.php
@@ -0,0 +1,54 @@
+There is no help for this route!';
+ $helpTitle = 'Help';
+
+ return Response::json(['title' => $helpTitle, 'text' => $helpText]);
+ }
+
+ // content in cache
+ if (Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text')) {
+ $helpText = Cache::get('help.' . $route . '.text');
+ $helpTitle = Cache::get('help.' . $route . '.title');
+
+ return Response::json(['title' => $helpTitle, 'text' => $helpText]);
+ }
+
+ // get the help-content from Github:
+ $URL = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md';
+ try {
+ $content = file_get_contents($URL);
+ } catch (ErrorException $e) {
+ $content = 'There is no help for this route.
';
+ }
+ if (strlen($content) > 0) {
+ $helpText = \Michelf\Markdown::defaultTransform($content);
+ $helpTitle = $route;
+
+ Cache::put('help.' . $route . '.text', $helpText, 10080); // a week.
+ Cache::put('help.' . $route . '.title', $helpTitle, 10080);
+
+ return Response::json(['title' => $helpTitle, 'text' => $helpText]);
+ }
+
+ $helpText = 'There is no help for this route!
';
+ $helpTitle = 'Help';
+
+ return Response::json(['title' => $helpTitle, 'text' => $helpText]);
+
+ }
+}
\ No newline at end of file
diff --git a/app/controllers/HomeController.php b/app/controllers/HomeController.php
index ffd33b86cd..9617608efc 100644
--- a/app/controllers/HomeController.php
+++ b/app/controllers/HomeController.php
@@ -1,75 +1,11 @@
_accounts = $accounts;
- $this->_preferences = $preferences;
- $this->_journal = $journal;
- }
-
- public function jobDev()
- {
- $fullName = storage_path() . DIRECTORY_SEPARATOR . 'firefly-export-2014-07-23.json';
- \Log::notice('Pushed start job.');
- Queue::push('Firefly\Queue\Import@start', ['file' => $fullName, 'user' => 1]);
-
- }
-
- /*
- *
- */
- public function sessionPrev()
- {
- /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */
- $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface');
- $toolkit->prev();
- return Redirect::back();
- //return Redirect::route('index');
- }
-
- /*
- *
- */
- public function sessionNext()
- {
- /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */
- $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface');
- $toolkit->next();
- return Redirect::back();
- //return Redirect::route('index');
- }
-
- public function rangeJump($range)
- {
-
- $valid = ['1D', '1W', '1M', '3M', '6M', '1Y',];
-
- if (in_array($range, $valid)) {
- $this->_preferences->set('viewRange', $range);
- Session::forget('range');
- }
- return Redirect::back();
- }
-
/**
* @return \Illuminate\Http\RedirectResponse
*/
@@ -85,89 +21,81 @@ class HomeController extends BaseController
*/
public function index()
{
- Event::fire('limits.check');
- Event::fire('piggybanks.check');
- Event::fire('recurring.check');
-
// count, maybe Firefly needs some introducing text to show:
- $count = $this->_accounts->count();
+ /** @var \FireflyIII\Database\Account $acct */
+ $acct = App::make('FireflyIII\Database\Account');
+
+ /** @var \FireflyIII\Database\TransactionJournal $jrnls */
+ $jrnls = App::make('FireflyIII\Database\TransactionJournal');
+
+ /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
+ $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
+
+ $count = $acct->countAssetAccounts();
+
$start = Session::get('start');
$end = Session::get('end');
// get the preference for the home accounts to show:
- $frontpage = $this->_preferences->get('frontpageAccounts', []);
+ $frontpage = $preferences->get('frontpageAccounts', []);
if ($frontpage->data == []) {
- $accounts = $this->_accounts->getActiveDefault();
+ $accounts = $acct->getAssetAccounts();
} else {
- $accounts = $this->_accounts->getByIds($frontpage->data);
+ $accounts = $acct->getByIds($frontpage->data);
}
$transactions = [];
foreach ($accounts as $account) {
- $set = $this->_journal->getByAccountInDateRange($account, 10, $start, $end);
+ $set = $jrnls->getInDateRangeAccount($account, 10, $start, $end);
if (count($set) > 0) {
$transactions[] = [$set, $account];
}
}
// build the home screen:
- return View::make('index')->with('count', $count)->with('transactions', $transactions)->with('title', 'Firefly')
- ->with('subTitle', 'What\'s playing?')->with('mainTitleIcon', 'fa-fire');
+ return View::make('index')->with('count', $count)->with('transactions', $transactions)->with('title', 'Firefly')->with('subTitle', 'What\'s playing?')
+ ->with('mainTitleIcon', 'fa-fire');
}
- public function cleanup()
+ /**
+ * @param $range
+ *
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function rangeJump($range)
{
- /** @var \FireflyIII\Database\TransactionJournal $jrnls */
- $jrnls = App::make('FireflyIII\Database\TransactionJournal');
- /** @var \FireflyIII\Database\Account $acct */
- $acct = \App::make('FireflyIII\Database\Account');
+ $valid = ['1D', '1W', '1M', '3M', '6M', '1Y',];
- /** @var \FireflyIII\Database\AccountType $acctType */
- $acctType = \App::make('FireflyIII\Database\AccountType');
- $rightAcctType = $acctType->findByWhat('revenue');
+ /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
+ $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
- $all = $jrnls->get();
-
- /** @var \TransactionJournal $entry */
- foreach ($all as $entry) {
- $wrongFromType = false;
- $wrongToType = false;
- $transactions = $entry->transactions;
- if (count($transactions) == 2) {
- switch ($entry->transactionType->type) {
- case 'Deposit':
- /** @var \Transaction $transaction */
- foreach ($transactions as $transaction) {
- if (floatval($transaction->amount) < 0) {
- $accountType = $transaction->account->accountType;
- if ($accountType->type == 'Beneficiary account') {
- // should be a Revenue account!
- $name = $transaction->account->name;
- /** @var \Account $account */
- $account = \Auth::user()->accounts()->where('name', $name)->where('account_type_id', $rightAcctType->id)->first();
- if (!$account) {
- $new = [
- 'name' => $name,
- 'what' => 'revenue'
- ];
- $account = $acct->store($new);
- }
- $transaction->account()->associate($account);
- $transaction->save();
- }
-
- echo 'Paid by: ' . $transaction->account->name . ' (' . $transaction->account->accountType->type . ') ';
- }
- }
- break;
- }
-
-
- }
+ if (in_array($range, $valid)) {
+ $preferences->set('viewRange', $range);
+ Session::forget('range');
}
+ return Redirect::back();
+ }
+ /**
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function sessionNext()
+ {
+ Navigation::next();
+
+ return Redirect::back();
+ }
+
+ /**
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function sessionPrev()
+ {
+ Navigation::prev();
+
+ return Redirect::back();
}
}
\ No newline at end of file
diff --git a/app/controllers/JsonController.php b/app/controllers/JsonController.php
index 671e771b95..9f0512572a 100644
--- a/app/controllers/JsonController.php
+++ b/app/controllers/JsonController.php
@@ -1,25 +1,11 @@
helper = $helper;
-
-
- }
/**
* Returns a list of categories.
@@ -28,8 +14,8 @@ class JsonController extends BaseController
*/
public function categories()
{
- /** @var \Firefly\Storage\Category\EloquentCategoryRepository $categories */
- $categories = App::make('Firefly\Storage\Category\CategoryRepositoryInterface');
+ /** @var \FireflyIII\Database\Category $categories */
+ $categories = App::make('FireflyIII\Database\Category');
$list = $categories->get();
$return = [];
foreach ($list as $entry) {
@@ -48,9 +34,9 @@ class JsonController extends BaseController
*/
public function expenseAccounts()
{
- /** @var \Firefly\Storage\Account\EloquentAccountRepository $accounts */
- $accounts = App::make('Firefly\Storage\Account\AccountRepositoryInterface');
- $list = $accounts->getOfTypes(['Expense account', 'Beneficiary account']);
+ /** @var \FireflyIII\Database\Account $accounts */
+ $accounts = App::make('FireflyIII\Database\Account');
+ $list = $accounts->getExpenseAccounts();
$return = [];
foreach ($list as $entry) {
$return[] = $entry->name;
@@ -61,99 +47,13 @@ class JsonController extends BaseController
}
/**
- * Returns a list of transactions, expenses only, using the given parameters.
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function expenses()
- {
-
- /*
- * Gets most parameters from the Input::all() array:
- */
- $parameters = $this->helper->dataTableParameters();
-
- /*
- * Add some more parameters to fine tune the query:
- */
- $parameters['transactionTypes'] = ['Withdrawal'];
- $parameters['amount'] = 'negative';
-
- /*
- * Get the query:
- */
- $query = $this->helper->journalQuery($parameters);
-
- /*
- * Build result set:
- */
- $resultSet = $this->helper->journalDataset($parameters, $query);
-
-
- /*
- * Build return data:
- */
- return Response::json($resultSet);
- }
-
- /**
- *
- */
- public function recurringjournals(RecurringTransaction $recurringTransaction)
- {
- $parameters = $this->helper->dataTableParameters();
- $parameters['transactionTypes'] = ['Withdrawal'];
- $parameters['amount'] = 'negative';
-
- $query = $this->helper->journalQuery($parameters);
-
- $query->where('recurring_transaction_id', $recurringTransaction->id);
- $resultSet = $this->helper->journalDataset($parameters, $query);
-
-
- /*
- * Build return data:
- */
- return Response::json($resultSet);
- }
-
- public function recurring()
- {
- $parameters = $this->helper->dataTableParameters();
- $query = $this->helper->recurringTransactionsQuery($parameters);
- $resultSet = $this->helper->recurringTransactionsDataset($parameters, $query);
- return Response::json($resultSet);
- }
-
- /**
- * @return \Illuminate\Http\JsonResponse|string
- */
- public function revenue()
- {
- $parameters = $this->helper->dataTableParameters();
- $parameters['transactionTypes'] = ['Deposit'];
- $parameters['amount'] = 'positive';
-
- $query = $this->helper->journalQuery($parameters);
- $resultSet = $this->helper->journalDataset($parameters, $query);
-
-
- /*
- * Build return data:
- */
- return Response::json($resultSet);
- }
-
- /**
- * Returns a JSON list of all revenue accounts.
- *
* @return \Illuminate\Http\JsonResponse
*/
public function revenueAccounts()
{
- /** @var \Firefly\Storage\Account\EloquentAccountRepository $accounts */
- $accounts = App::make('Firefly\Storage\Account\AccountRepositoryInterface');
- $list = $accounts->getOfTypes(['Revenue account']);
+ /** @var \FireflyIII\Database\Account $accounts */
+ $accounts = App::make('FireflyIII\Database\Account');
+ $list = $accounts->getRevenueAccounts();
$return = [];
foreach ($list as $entry) {
$return[] = $entry->name;
@@ -162,25 +62,4 @@ class JsonController extends BaseController
return Response::json($return);
}
-
- /**
- * Returns a list of all transfers.
- *
- * @return \Illuminate\Http\JsonResponse
- */
- public function transfers()
- {
- $parameters = $this->helper->dataTableParameters();
- $parameters['transactionTypes'] = ['Transfer'];
- $parameters['amount'] = 'positive';
-
- $query = $this->helper->journalQuery($parameters);
- $resultSet = $this->helper->journalDataset($parameters, $query);
-
-
- /*
- * Build return data:
- */
- return Response::json($resultSet);
- }
-}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/app/controllers/LimitController.php b/app/controllers/LimitController.php
deleted file mode 100644
index f76345a5cf..0000000000
--- a/app/controllers/LimitController.php
+++ /dev/null
@@ -1,162 +0,0 @@
-_budgets = $budgets;
- $this->_limits = $limits;
-
- View::share('title','Envelopes');
- View::share('mainTitleIcon', 'fa-tasks');
- }
-
- /**
- * @param Budget $budget
- *
- * @return $this
- */
- public function create(\Budget $budget = null)
- {
- $periods = \Config::get('firefly.periods_to_text');
- $prefilled = [
- 'startdate' => \Input::get('startdate') ? : date('Y-m-d'),
- 'repeat_freq' => \Input::get('repeat_freq') ? : 'monthly',
- 'budget_id' => $budget ? $budget->id : null
- ];
-
- /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */
- $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit');
- $budgets = $toolkit->makeSelectList($this->_budgets->get());
-
- return View::make('limits.create')->with('budgets', $budgets)->with(
- 'periods', $periods
- )->with('prefilled', $prefilled)->with('subTitle','New envelope');
- }
-
- /**
- * @param Limit $limit
- *
- * @return $this
- */
- public function delete(\Limit $limit)
- {
- return View::make('limits.delete')->with('limit', $limit)->with('subTitle','Delete envelope');
- }
-
- /**
- * @param Limit $limit
- *
- * @return \Illuminate\Http\RedirectResponse
- */
- public function destroy(\Limit $limit)
- {
- Event::fire('limits.destroy', [$limit]); // before
- $success = $this->_limits->destroy($limit);
-
- if ($success) {
- Session::flash('success', 'The envelope was deleted.');
- } else {
- Session::flash('error', 'Could not delete the envelope. Check the logs to be sure.');
- }
- if (Input::get('from') == 'date') {
- return Redirect::route('budgets.index');
- } else {
- return Redirect::route('budgets.index.budget');
- }
- }
-
- /**
- * @param Limit $limit
- *
- * @return $this
- */
- public function edit(Limit $limit)
- {
- /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */
- $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit');
-
- $budgets = $toolkit->makeSelectList($this->_budgets->get());
- $periods = \Config::get('firefly.periods_to_text');
-
- return View::make('limits.edit')->with('limit', $limit)->with('budgets', $budgets)->with(
- 'periods', $periods
- )->with('subTitle','Edit envelope');
- }
-
- /**
- * @param Budget $budget
- *
- * @return $this|\Illuminate\Http\RedirectResponse
- */
- public function store(Budget $budget = null)
- {
-
- // find a limit with these properties, as Firefly might already have one:
- $limit = $this->_limits->store(Input::all());
- if ($limit->validate()) {
- Session::flash('success', 'Envelope created!');
- Event::fire('limits.store', [$limit]);
- if (Input::get('from') == 'date') {
- return Redirect::route('budgets.index');
- } else {
- return Redirect::route('budgets.index.budget');
- }
- } else {
- Session::flash('error', 'Could not save new envelope.');
- $budgetId = $budget ? $budget->id : null;
- $parameters = [$budgetId, 'from' => Input::get('from')];
-
- return Redirect::route('budgets.limits.create', $parameters)->withInput()
- ->withErrors($limit->errors());
- }
- }
-
- /**
- * @param Limit $limit
- *
- * @return $this|\Illuminate\Http\RedirectResponse
- */
- public function update(\Limit $limit)
- {
-
-
- $limit = $this->_limits->update($limit, Input::all());
-
- if ($limit->validate()) {
- Event::fire('limits.update', [$limit]);
- Session::flash('success', 'Limit saved!');
- if (Input::get('from') == 'date') {
- return Redirect::route('budgets.index');
- } else {
- return Redirect::route('budgets.index.budget');
- }
-
-
- } else {
- Session::flash('error', 'Could not save new limit: ' . $limit->errors()->first());
-
- return Redirect::route('budgets.limits.edit', [$limit->id, 'from' => Input::get('from')])->withInput()
- ->withErrors($limit->errors());
- }
-
- }
-
-
-}
\ No newline at end of file
diff --git a/app/controllers/MigrateController.php b/app/controllers/MigrateController.php
deleted file mode 100644
index a9bd16c200..0000000000
--- a/app/controllers/MigrateController.php
+++ /dev/null
@@ -1,52 +0,0 @@
-with('index', 'Migration')->with('title','Migrate')->
- with('subTitle','From Firefly II to Firefly III');
- }
-
- /**
- *
- */
- public function upload()
- {
- if (Input::hasFile('file') && Input::file('file')->isValid()) {
- $path = storage_path();
- $fileName = 'firefly-iii-import-' . date('Y-m-d-H-i') . '.json';
- $fullName = $path . DIRECTORY_SEPARATOR . $fileName;
- if (Input::file('file')->move($path, $fileName)) {
- // so now Firefly pushes something in a queue and does something with it! Yay!
- \Log::debug('Pushed a job to start the import.');
- Queue::push('Firefly\Queue\Import@start', ['file' => $fullName, 'user' => \Auth::user()->id]);
- if (Config::get('queue.default') == 'sync') {
- Session::flash('success', 'Your data has been imported!');
- } else {
- Session::flash(
- 'success',
- 'The import job has been queued. Please be patient. Data will appear slowly. Please be patient.'
- );
- }
-
- return Redirect::route('index');
- }
- Session::flash('error', 'Could not save file to storage.');
- return Redirect::route('migrate.index');
-
- } else {
- Session::flash('error', 'Please upload a file.');
- return Redirect::route('migrate.index');
- }
-
- }
-
-}
\ No newline at end of file
diff --git a/app/controllers/PiggybankController.php b/app/controllers/PiggybankController.php
index fb582a6652..0b4a8a61ab 100644
--- a/app/controllers/PiggybankController.php
+++ b/app/controllers/PiggybankController.php
@@ -1,7 +1,6 @@
makeSelectList($acct->getAssetAccounts());
- return View::make('piggybanks.create', compact('accounts', 'periods'))->with('title', 'Piggy banks')->with('mainTitleIcon', 'fa-sort-amount-asc')
- ->with('subTitle', 'Create new piggy bank')->with('subTitleIcon', 'fa-plus');
- }
-
- /**
- * @param Piggybank $piggyBank
+ * Add money to piggy bank
*
- * @return $this
- */
- public function delete(Piggybank $piggybank)
- {
- return View::make('piggybanks.delete')
- ->with('piggybank', $piggybank)
- ->with('subTitle', 'Delete "' . $piggybank->name . '"')
- ->with('title', 'Piggy banks')
- ->with('mainTitleIcon', 'fa-sort-amount-asc');
- }
-
- /**
- * @param Piggybank $piggyBank
- *
- * @return \Illuminate\Http\RedirectResponse
- */
- public function destroy(Piggybank $piggyBank)
- {
- Event::fire('piggybanks.destroy', [$piggyBank]);
-
- /** @var \FireflyIII\Database\Piggybank $acct */
- $repos = App::make('FireflyIII\Database\Piggybank');
- $repos->destroy($piggyBank);
- Session::flash('success', 'Piggy bank deleted.');
-
- return Redirect::route('piggybanks.index');
- }
-
- /**
- * @param Piggybank $piggyBank
- *
- * @return $this
- */
- public function edit(Piggybank $piggybank)
- {
-
- /** @var \FireflyIII\Database\Account $acct */
- $acct = App::make('FireflyIII\Database\Account');
-
- /** @var \FireflyIII\Shared\Toolkit\Form $toolkit */
- $toolkit = App::make('FireflyIII\Shared\Toolkit\Form');
-
- $periods = Config::get('firefly.piggybank_periods');
-
- $accounts = $toolkit->makeSelectList($acct->getAssetAccounts());
-
- /*
- * Flash some data to fill the form.
- */
- $prefilled = [
- 'name' => $piggybank->name,
- 'account_id' => $piggybank->account_id,
- 'targetamount' => $piggybank->targetamount,
- 'targetdate' => $piggybank->targetdate,
- 'remind_me' => intval($piggybank->remind_me) == 1 ? true : false
- ];
- Session::flash('prefilled', $prefilled);
-
- return View::make('piggybanks.edit', compact('piggybank', 'accounts', 'periods', 'prefilled'))->with('title', 'Piggybanks')->with(
- 'mainTitleIcon', 'fa-sort-amount-asc'
- )
- ->with('subTitle', 'Edit piggy bank "' . e($piggybank->name) . '"')->with('subTitleIcon', 'fa-pencil');
- }
-
- /**
* @param Piggybank $piggybank
*
* @return $this
*/
public function add(Piggybank $piggybank)
{
- /** @var \FireflyIII\Database\Piggybank $acct */
+ /** @var \FireflyIII\Database\Piggybank $repos */
$repos = App::make('FireflyIII\Database\Piggybank');
$leftOnAccount = $repos->leftOnAccount($piggybank->account);
@@ -125,66 +39,87 @@ class PiggybankController extends BaseController
return View::make('piggybanks.add', compact('piggybank'))->with('maxAmount', $amount);
}
+ /**
+ * @return mixed
+ */
+ public function create()
+ {
+
+ /** @var \FireflyIII\Database\Account $acct */
+ $acct = App::make('FireflyIII\Database\Account');
+
+ $periods = Config::get('firefly.piggybank_periods');
+
+
+ $accounts = FFForm::makeSelectList($acct->getAssetAccounts());
+
+ return View::make('piggybanks.create', compact('accounts', 'periods'))->with('title', 'Piggy banks')->with('mainTitleIcon', 'fa-sort-amount-asc')->with(
+ 'subTitle', 'Create new piggy bank'
+ )->with('subTitleIcon', 'fa-plus');
+ }
+
/**
* @param Piggybank $piggybank
*
+ * @return $this
+ */
+ public function delete(Piggybank $piggybank)
+ {
+ return View::make('piggybanks.delete')->with('piggybank', $piggybank)->with('subTitle', 'Delete "' . $piggybank->name . '"')->with(
+ 'title', 'Piggy banks'
+ )->with('mainTitleIcon', 'fa-sort-amount-asc');
+ }
+
+ /**
+ * @param Piggybank $piggyBank
+ *
* @return \Illuminate\Http\RedirectResponse
*/
- public function postAdd(Piggybank $piggybank)
+ public function destroy(Piggybank $piggyBank)
{
- $amount = round(floatval(Input::get('amount')), 2);
-
/** @var \FireflyIII\Database\Piggybank $acct */
$repos = App::make('FireflyIII\Database\Piggybank');
+ $repos->destroy($piggyBank);
+ Session::flash('success', 'Piggy bank deleted.');
- $leftOnAccount = $repos->leftOnAccount($piggybank->account);
- $savedSoFar = $piggybank->currentRelevantRep()->currentamount;
- $leftToSave = $piggybank->targetamount - $savedSoFar;
- $maxAmount = round(min($leftOnAccount, $leftToSave), 2);
-
- if ($amount <= $maxAmount) {
- $repetition = $piggybank->currentRelevantRep();
- $repetition->currentamount += $amount;
- $repetition->save();
- Session::flash('success', 'Added ' . mf($amount, false) . ' to "' . e($piggybank->name) . '".');
- } else {
- Session::flash('error', 'Could not add ' . mf($amount, false) . ' to "' . e($piggybank->name) . '".');
- }
return Redirect::route('piggybanks.index');
}
/**
* @param Piggybank $piggybank
*
- * @return \Illuminate\View\View
+ * @return $this
*/
- public function remove(Piggybank $piggybank)
+ public function edit(Piggybank $piggybank)
{
- return View::make('piggybanks.remove', compact('piggybank'));
+
+ /** @var \FireflyIII\Database\Account $acct */
+ $acct = App::make('FireflyIII\Database\Account');
+
+ $periods = Config::get('firefly.piggybank_periods');
+
+ $accounts = FFForm::makeSelectList($acct->getAssetAccounts());
+
+ /*
+ * Flash some data to fill the form.
+ */
+ $prefilled = ['name' => $piggybank->name,
+ 'account_id' => $piggybank->account_id,
+ 'targetamount' => $piggybank->targetamount,
+ 'targetdate' => !is_null($piggybank->targetdate) ? $piggybank->targetdate->format('Y-m-d') : null,
+ 'reminder' => $piggybank->reminder,
+ 'remind_me' => intval($piggybank->remind_me) == 1 || !is_null($piggybank->reminder) ? true : false
+ ];
+ Session::flash('prefilled', $prefilled);
+
+ return View::make('piggybanks.edit', compact('piggybank', 'accounts', 'periods', 'prefilled'))->with('title', 'Piggybanks')->with(
+ 'mainTitleIcon', 'fa-sort-amount-asc'
+ )->with('subTitle', 'Edit piggy bank "' . e($piggybank->name) . '"')->with('subTitleIcon', 'fa-pencil');
}
/**
- * @param Piggybank $piggybank
- *
- * @return \Illuminate\Http\RedirectResponse
+ * @return $this
*/
- public function postRemove(Piggybank $piggybank)
- {
- $amount = floatval(Input::get('amount'));
-
- $savedSoFar = $piggybank->currentRelevantRep()->currentamount;
-
- if ($amount <= $savedSoFar) {
- $repetition = $piggybank->currentRelevantRep();
- $repetition->currentamount -= $amount;
- $repetition->save();
- Session::flash('success', 'Removed ' . mf($amount, false) . ' from "' . e($piggybank->name) . '".');
- } else {
- Session::flash('error', 'Could not remove ' . mf($amount, false) . ' from "' . e($piggybank->name) . '".');
- }
- return Redirect::route('piggybanks.index');
- }
-
public function index()
{
/** @var \FireflyIII\Database\Piggybank $repos */
@@ -205,27 +140,117 @@ class PiggybankController extends BaseController
*/
$account = $piggybank->account;
if (!isset($accounts[$account->id])) {
- $accounts[$account->id] = [
- 'name' => $account->name,
- 'balance' => $account->balance(),
- 'leftForPiggybanks' => $repos->leftOnAccount($account),
- 'sumOfSaved' => $piggybank->savedSoFar,
- 'sumOfTargets' => floatval($piggybank->targetamount),
- 'leftToSave' => $piggybank->leftToSave
- ];
+ $accounts[$account->id] = ['name' => $account->name, 'balance' => Steam::balance($account),
+ 'leftForPiggybanks' => $repos->leftOnAccount($account), 'sumOfSaved' => $piggybank->savedSoFar,
+ 'sumOfTargets' => floatval($piggybank->targetamount), 'leftToSave' => $piggybank->leftToSave];
} else {
$accounts[$account->id]['sumOfSaved'] += $piggybank->savedSoFar;
$accounts[$account->id]['sumOfTargets'] += floatval($piggybank->targetamount);
$accounts[$account->id]['leftToSave'] += $piggybank->leftToSave;
}
}
+
return View::make('piggybanks.index', compact('piggybanks', 'accounts'))->with('title', 'Piggy banks')->with('mainTitleIcon', 'fa-sort-amount-asc');
}
-
- public function show(Piggybank $piggyBank)
+ /**
+ * POST add money to piggy bank
+ *
+ * @param Piggybank $piggybank
+ *
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function postAdd(Piggybank $piggybank)
{
- throw new NotImplementedException;
+ $amount = round(floatval(Input::get('amount')), 2);
+
+ /** @var \FireflyIII\Database\Piggybank $acct */
+ $repos = App::make('FireflyIII\Database\Piggybank');
+
+ $leftOnAccount = $repos->leftOnAccount($piggybank->account);
+ $savedSoFar = $piggybank->currentRelevantRep()->currentamount;
+ $leftToSave = $piggybank->targetamount - $savedSoFar;
+ $maxAmount = round(min($leftOnAccount, $leftToSave), 2);
+
+ if ($amount <= $maxAmount) {
+ $repetition = $piggybank->currentRelevantRep();
+ $repetition->currentamount += $amount;
+ $repetition->save();
+
+ /*
+ * Create event!
+ */
+ Event::fire('piggybank.addMoney', [$piggybank, $amount]); // new and used.
+
+ Session::flash('success', 'Added ' . mf($amount, false) . ' to "' . e($piggybank->name) . '".');
+ } else {
+ Session::flash('error', 'Could not add ' . mf($amount, false) . ' to "' . e($piggybank->name) . '".');
+ }
+
+ return Redirect::route('piggybanks.index');
+ }
+
+ /**
+ * @param Piggybank $piggybank
+ *
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function postRemove(Piggybank $piggybank)
+ {
+ $amount = floatval(Input::get('amount'));
+
+ $savedSoFar = $piggybank->currentRelevantRep()->currentamount;
+
+ if ($amount <= $savedSoFar) {
+ $repetition = $piggybank->currentRelevantRep();
+ $repetition->currentamount -= $amount;
+ $repetition->save();
+
+ /*
+ * Create event!
+ */
+ Event::fire('piggybank.removeMoney', [$piggybank, $amount]); // new and used.
+
+ Session::flash('success', 'Removed ' . mf($amount, false) . ' from "' . e($piggybank->name) . '".');
+ } else {
+ Session::flash('error', 'Could not remove ' . mf($amount, false) . ' from "' . e($piggybank->name) . '".');
+ }
+
+ return Redirect::route('piggybanks.index');
+ }
+
+ /**
+ * @param Piggybank $piggybank
+ *
+ * @return \Illuminate\View\View
+ */
+ public function remove(Piggybank $piggybank)
+ {
+ return View::make('piggybanks.remove', compact('piggybank'));
+ }
+
+ /**
+ * @param Piggybank $piggybank
+ *
+ * @return $this
+ */
+ public function show(Piggybank $piggybank)
+ {
+
+ $events = $piggybank->piggybankevents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
+
+ /*
+ * Number of reminders:
+ */
+
+ $amountPerReminder = $piggybank->amountPerReminder();
+ $remindersCount = $piggybank->countFutureReminders();
+
+ return View::make('piggybanks.show', compact('amountPerReminder', 'remindersCount', 'piggybank', 'events'))->with('title', 'Piggy banks')->with(
+ 'mainTitleIcon', 'fa-sort-amount-asc'
+ )->with(
+ 'subTitle', $piggybank->name
+ );
}
@@ -251,14 +276,21 @@ class PiggybankController extends BaseController
Session::flash('warnings', $messages['warnings']);
Session::flash('successes', $messages['successes']);
Session::flash('error', 'Could not save piggy bank: ' . $messages['errors']->first());
+
return Redirect::route('piggybanks.create')->withInput()->withErrors($messages['errors']);
}
// store!
- $repos->store($data);
+ $piggyBank = $repos->store($data);
+
+ /*
+ * Create the relevant repetition per Event.
+ */
+ Event::fire('piggybank.store', [$piggyBank]); // new and used.
+
Session::flash('success', 'New piggy bank stored!');
if ($data['post_submit_action'] == 'create_another') {
- return Redirect::route('piggybanks.create');
+ return Redirect::route('piggybanks.create')->withInput();
} else {
return Redirect::route('piggybanks.index');
}
@@ -277,7 +309,8 @@ class PiggybankController extends BaseController
/**
* @param Piggybank $piggyBank
*
- * @return $this|\Illuminate\Http\RedirectResponse
+ * @return $this
+ * @throws FireflyException
*/
public function update(Piggybank $piggyBank)
{
@@ -290,7 +323,7 @@ class PiggybankController extends BaseController
default:
throw new FireflyException('Cannot handle post_submit_action "' . e(Input::get('post_submit_action')) . '"');
break;
- case 'create_another':
+ case 'return_to_edit':
case 'update':
$messages = $repos->validate($data);
/** @var MessageBag $messages ['errors'] */
@@ -298,13 +331,15 @@ class PiggybankController extends BaseController
Session::flash('warnings', $messages['warnings']);
Session::flash('successes', $messages['successes']);
Session::flash('error', 'Could not save piggy bank: ' . $messages['errors']->first());
+
return Redirect::route('piggybanks.edit', $piggyBank->id)->withInput()->withErrors($messages['errors']);
}
// store!
$repos->update($piggyBank, $data);
+ Event::fire('piggybank.update', [$piggyBank]); // new and used.
Session::flash('success', 'Piggy bank updated!');
- if ($data['post_submit_action'] == 'create_another') {
+ if ($data['post_submit_action'] == 'return_to_edit') {
return Redirect::route('piggybanks.edit', $piggyBank->id);
} else {
return Redirect::route('piggybanks.index');
@@ -314,6 +349,7 @@ class PiggybankController extends BaseController
Session::flash('warnings', $messageBags['warnings']);
Session::flash('successes', $messageBags['successes']);
Session::flash('errors', $messageBags['errors']);
+
return Redirect::route('piggybanks.edit', $piggyBank->id)->withInput();
break;
}
diff --git a/app/controllers/PreferencesController.php b/app/controllers/PreferencesController.php
index 2e1d82bcda..0d6a373843 100644
--- a/app/controllers/PreferencesController.php
+++ b/app/controllers/PreferencesController.php
@@ -1,29 +1,19 @@
_accounts = $accounts;
- $this->_preferences = $preferences;
- View::share('title','Preferences');
- View::share('mainTitleIcon','fa-gear');
+ View::share('title', 'Preferences');
+ View::share('mainTitleIcon', 'fa-gear');
}
/**
@@ -31,16 +21,18 @@ class PreferencesController extends BaseController
*/
public function index()
{
- $accounts = $this->_accounts->getDefault();
+ /** @var \FireflyIII\Database\Account $acct */
+ $acct = App::make('FireflyIII\Database\Account');
- $viewRange = $this->_preferences->get('viewRange', '1M');
+ /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
+ $preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
+
+ $accounts = $acct->getAssetAccounts();
+ $viewRange = $preferences->get('viewRange', '1M');
$viewRangeValue = $viewRange->data;
+ $frontpage = $preferences->get('frontpageAccounts', []);
- // pref:
- $frontpage = $this->_preferences->get('frontpageAccounts', []);
-
- return View::make('preferences.index')->with('accounts', $accounts)->with('frontpageAccounts', $frontpage)
- ->with('viewRange', $viewRangeValue);
+ return View::make('preferences.index')->with('accounts', $accounts)->with('frontpageAccounts', $frontpage)->with('viewRange', $viewRangeValue);
}
/**
@@ -49,15 +41,18 @@ class PreferencesController extends BaseController
public function postIndex()
{
+ /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
+ $preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
+
// frontpage accounts
$frontpageAccounts = [];
foreach (Input::get('frontpageAccounts') as $id) {
$frontpageAccounts[] = intval($id);
}
- $this->_preferences->set('frontpageAccounts', $frontpageAccounts);
+ $preferences->set('frontpageAccounts', $frontpageAccounts);
// view range:
- $this->_preferences->set('viewRange', Input::get('viewRange'));
+ $preferences->set('viewRange', Input::get('viewRange'));
// forget session values:
Session::forget('start');
Session::forget('end');
diff --git a/app/controllers/ProfileController.php b/app/controllers/ProfileController.php
index beda24d3cf..938d41f28a 100644
--- a/app/controllers/ProfileController.php
+++ b/app/controllers/ProfileController.php
@@ -1,7 +1,5 @@
user = $user;
+ return View::make('profile.change-password')->with('title', Auth::user()->email)->with('subTitle', 'Change your password')->with(
+ 'mainTitleIcon', 'fa-user'
+ );
}
/**
@@ -22,21 +22,7 @@ class ProfileController extends BaseController
*/
public function index()
{
- return View::make('profile.index')
- ->with('title', 'Profile')
- ->with('subTitle', Auth::user()->email)
- ->with('mainTitleIcon', 'fa-user');
- }
-
- /**
- * @return \Illuminate\View\View
- */
- public function changePassword()
- {
- return View::make('profile.change-password')
- ->with('title', Auth::user()->email)
- ->with('subTitle', 'Change your password')
- ->with('mainTitleIcon', 'fa-user');
+ return View::make('profile.index')->with('title', 'Profile')->with('subTitle', Auth::user()->email)->with('mainTitleIcon', 'fa-user');
}
/**
@@ -70,8 +56,9 @@ class ProfileController extends BaseController
}
// update the user with the new password.
- /** @noinspection PhpParamsInspection */
- $this->user->updatePassword(Auth::user(), Input::get('new1'));
+ /** @var \FireflyIII\Database\User $repository */
+ $repository = \App::make('FireflyIII\Database\User');
+ $repository->updatePassword(Auth::user(), Input::get('new1'));
Session::flash('success', 'Password changed!');
diff --git a/app/controllers/RecurringController.php b/app/controllers/RecurringController.php
index db60b34004..bd3a7faed6 100644
--- a/app/controllers/RecurringController.php
+++ b/app/controllers/RecurringController.php
@@ -1,27 +1,18 @@
_repository = $repository;
- $this->_helper = $helper;
View::share('title', 'Recurring transactions');
View::share('mainTitleIcon', 'fa-rotate-right');
@@ -34,9 +25,7 @@ class RecurringController extends BaseController
{
$periods = \Config::get('firefly.periods_to_text');
- return View::make('recurring.create')
- ->with('periods', $periods)
- ->with('subTitle', 'Create new');
+ return View::make('recurring.create')->with('periods', $periods)->with('subTitle', 'Create new');
}
/**
@@ -46,9 +35,9 @@ class RecurringController extends BaseController
*/
public function delete(RecurringTransaction $recurringTransaction)
{
- return View::make('recurring.delete')
- ->with('recurringTransaction', $recurringTransaction)
- ->with('subTitle', 'Delete "' . $recurringTransaction->name . '"');
+ return View::make('recurring.delete')->with('recurringTransaction', $recurringTransaction)->with(
+ 'subTitle', 'Delete "' . $recurringTransaction->name . '"'
+ );
}
/**
@@ -59,7 +48,11 @@ class RecurringController extends BaseController
public function destroy(RecurringTransaction $recurringTransaction)
{
//Event::fire('recurring.destroy', [$recurringTransaction]);
- $result = $this->_repository->destroy($recurringTransaction);
+
+ /** @var \FireflyIII\Database\Recurring $repository */
+ $repository = App::make('FireflyIII\Database\Recurring');
+
+ $result = $repository->destroy($recurringTransaction);
if ($result === true) {
Session::flash('success', 'The recurring transaction was deleted.');
} else {
@@ -79,10 +72,9 @@ class RecurringController extends BaseController
{
$periods = \Config::get('firefly.periods_to_text');
- return View::make('recurring.edit')
- ->with('periods', $periods)
- ->with('recurringTransaction', $recurringTransaction)
- ->with('subTitle', 'Edit "' . $recurringTransaction->name . '"');
+ return View::make('recurring.edit')->with('periods', $periods)->with('recurringTransaction', $recurringTransaction)->with(
+ 'subTitle', 'Edit "' . $recurringTransaction->name . '"'
+ );
}
/**
@@ -90,150 +82,144 @@ class RecurringController extends BaseController
*/
public function index()
{
- return View::make('recurring.index');
- }
+ /** @var \FireflyIII\Database\Recurring $repos */
+ $repos = App::make('FireflyIII\Database\Recurring');
- /**
- *
- */
- public function show(RecurringTransaction $recurringTransaction)
- {
- return View::make('recurring.show')
- ->with('recurring', $recurringTransaction)
- ->with('subTitle', $recurringTransaction->name);
+ $recurring = $repos->get();
+
+ return View::make('recurring.index', compact('recurring'));
}
/**
* @param RecurringTransaction $recurringTransaction
+ *
* @return mixed
*/
public function rescan(RecurringTransaction $recurringTransaction)
{
if (intval($recurringTransaction->active) == 0) {
Session::flash('warning', 'Inactive recurring transactions cannot be scanned.');
+
return Redirect::back();
}
- // do something!
- /** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $repo */
- $repo = App::make('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
- $set = $repo->get();
- /** @var TransactionJournal $journal */
- foreach ($set as $journal) {
- Event::fire('recurring.rescan', [$recurringTransaction, $journal]);
- }
+ /** @var \FireflyIII\Database\Recurring $repos */
+ $repos = App::make('FireflyIII\Database\Recurring');
+ $repos->scanEverything($recurringTransaction);
+
Session::flash('success', 'Rescanned everything.');
+
return Redirect::back();
-
-
}
+ /**
+ * @param RecurringTransaction $recurringTransaction
+ *
+ * @return mixed
+ */
+ public function show(RecurringTransaction $recurringTransaction)
+ {
+ $journals = $recurringTransaction->transactionjournals()->withRelevantData()->orderBy('date', 'DESC')->get();
+ $hideRecurring = true;
+
+
+ return View::make('recurring.show', compact('journals', 'hideRecurring', 'finalDate'))->with('recurring', $recurringTransaction)->with(
+ 'subTitle', $recurringTransaction->name
+ );
+ }
+
+ /**
+ * @return $this
+ * @throws FireflyException
+ */
public function store()
{
- $data = Input::except(['_token', 'post_submit_action']);
- switch (Input::get('post_submit_action')) {
+ $data = Input::except('_token');
+ /** @var \FireflyIII\Database\Recurring $repos */
+ $repos = App::make('FireflyIII\Database\Recurring');
+
+ switch ($data['post_submit_action']) {
default:
- throw new FireflyException('Method ' . Input::get('post_submit_action') . ' not implemented yet.');
+ throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
break;
- case 'store':
case 'create_another':
- /*
- * Try to store:
- */
- $messageBag = $this->_repository->store($data);
+ case 'store':
+ $messages = $repos->validate($data);
+ /** @var MessageBag $messages ['errors'] */
+ if ($messages['errors']->count() > 0) {
+ Session::flash('warnings', $messages['warnings']);
+ Session::flash('successes', $messages['successes']);
+ Session::flash('error', 'Could not save recurring transaction: ' . $messages['errors']->first());
- /*
- * Failure!
- */
- if ($messageBag->count() > 0) {
- Session::flash('error', 'Could not save recurring transaction: ' . $messageBag->first());
- return Redirect::route('recurring.create')->withInput()->withErrors($messageBag);
+ return Redirect::route('recurring.create')->withInput()->withErrors($messages['errors']);
}
+ // store!
+ $repos->store($data);
+ Session::flash('success', 'New recurring transaction stored!');
- /*
- * Success!
- */
- Session::flash('success', 'Recurring transaction "' . e(Input::get('name')) . '" saved!');
-
- /*
- * Redirect to original location or back to the form.
- */
- if (Input::get('post_submit_action') == 'create_another') {
+ if ($data['post_submit_action'] == 'create_another') {
return Redirect::route('recurring.create')->withInput();
} else {
return Redirect::route('recurring.index');
}
break;
case 'validate_only':
- $messageBags = $this->_helper->validate($data);
-
+ $messageBags = $repos->validate($data);
Session::flash('warnings', $messageBags['warnings']);
Session::flash('successes', $messageBags['successes']);
Session::flash('errors', $messageBags['errors']);
+
return Redirect::route('recurring.create')->withInput();
break;
}
}
+ /**
+ * @param RecurringTransaction $recurringTransaction
+ *
+ * @return $this
+ * @throws FireflyException
+ */
public function update(RecurringTransaction $recurringTransaction)
{
- $data = Input::except(['_token', 'post_submit_action']);
+ /** @var \FireflyIII\Database\Recurring $repos */
+ $repos = App::make('FireflyIII\Database\Recurring');
+ $data = Input::except('_token');
+
switch (Input::get('post_submit_action')) {
- case 'update':
- case 'return_to_edit':
- $messageBag = $this->_repository->update($recurringTransaction, $data);
- if ($messageBag->count() == 0) {
- // has been saved, return to index:
- Session::flash('success', 'Recurring transaction updated!');
-
- if (Input::get('post_submit_action') == 'return_to_edit') {
- return Redirect::route('recurring.edit', $recurringTransaction->id)->withInput();
- } else {
- return Redirect::route('recurring.index');
- }
- } else {
- Session::flash('error', 'Could not update recurring transaction: ' . $messageBag->first());
-
- return Redirect::route('transactions.edit', $recurringTransaction->id)->withInput()
- ->withErrors($messageBag);
- }
-
-
+ default:
+ throw new FireflyException('Cannot handle post_submit_action "' . e(Input::get('post_submit_action')) . '"');
break;
- case 'validate_only':
- $data = Input::all();
- $data['id'] = $recurringTransaction->id;
- $messageBags = $this->_helper->validate($data);
+ case 'create_another':
+ case 'update':
+ $messages = $repos->validate($data);
+ /** @var MessageBag $messages ['errors'] */
+ if ($messages['errors']->count() > 0) {
+ Session::flash('warnings', $messages['warnings']);
+ Session::flash('successes', $messages['successes']);
+ Session::flash('error', 'Could not save recurring transaction: ' . $messages['errors']->first());
+ return Redirect::route('recurring.edit', $recurringTransaction->id)->withInput()->withErrors($messages['errors']);
+ }
+ // store!
+ $repos->update($recurringTransaction, $data);
+ Session::flash('success', 'Recurring transaction updated!');
+
+ if ($data['post_submit_action'] == 'create_another') {
+ return Redirect::route('recurring.edit', $recurringTransaction->id);
+ } else {
+ return Redirect::route('recurring.index');
+ }
+ case 'validate_only':
+ $messageBags = $repos->validate($data);
Session::flash('warnings', $messageBags['warnings']);
Session::flash('successes', $messageBags['successes']);
Session::flash('errors', $messageBags['errors']);
- return Redirect::route('recurring.edit', $recurringTransaction->id)->withInput();
- break;
- // update
- default:
- throw new FireflyException('Method ' . Input::get('post_submit_action') . ' not implemented yet.');
+ return Redirect::route('recurring.edit', $recurringTransaction->id)->withInput();
break;
}
-
-// /** @var \RecurringTransaction $recurringTransaction */
-// $recurringTransaction = $this->_repository->update($recurringTransaction, Input::all());
-// if ($recurringTransaction->errors()->count() == 0) {
-// Session::flash('success', 'The recurring transaction has been updated.');
-// //Event::fire('recurring.update', [$recurringTransaction]);
-//
-// return Redirect::route('recurring.index');
-// } else {
-// Session::flash(
-// 'error', 'Could not update the recurring transaction: ' . $recurringTransaction->errors()->first()
-// );
-//
-// return Redirect::route('recurring.edit', $recurringTransaction->id)->withInput()->withErrors(
-// $recurringTransaction->errors()
-// );
-// }
}
}
\ No newline at end of file
diff --git a/app/controllers/ReminderController.php b/app/controllers/ReminderController.php
index 657f3e8a10..fe8c186e88 100644
--- a/app/controllers/ReminderController.php
+++ b/app/controllers/ReminderController.php
@@ -1,4 +1,5 @@
remindersable)) {
+ default:
+ throw new FireflyException('Cannot act on reminder for ' . get_class($reminder->remindersable));
+ break;
+ break;
+ case 'Piggybank':
+ $amount = Reminders::amountForReminder($reminder);
+ $prefilled = [
+ 'amount' => round($amount, 2),
+ 'description' => 'Money for ' . $reminder->remindersable->name,
+ 'piggybank_id' => $reminder->remindersable_id,
+ 'account_to_id' => $reminder->remindersable->account_id
+ ];
+ Session::flash('prefilled', $prefilled);
+
+ return Redirect::route('transactions.create', 'transfer');
+ break;
+
+ }
+ }
+
+ /**
+ * @param Reminder $reminder
+ *
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function dismiss(Reminder $reminder)
+ {
+ $reminder->active = 0;
+ $reminder->save();
+ Session::flash('success', 'Reminder dismissed');
+
+ return Redirect::route('index');
+ }
+
+ /**
+ * @param Reminder $reminder
+ *
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function notnow(Reminder $reminder)
+ {
+ $reminder->active = 0;
+ $reminder->notnow = 1;
+ $reminder->save();
+ Session::flash('success', 'Reminder dismissed');
+
+ return Redirect::route('index');
+ }
+
+ /**
+ * @param Reminder $reminder
+ *
+ * @return \Illuminate\View\View
+ */
+ public function show(Reminder $reminder)
+ {
+
+ $amount = null;
+ if (get_class($reminder->remindersable) == 'Piggybank') {
+
+ $amount = Reminders::amountForReminder($reminder);
+ }
+
+ return View::make('reminders.show', compact('reminder', 'amount'));
+ }
+
}
\ No newline at end of file
diff --git a/app/controllers/RepeatedExpenseController.php b/app/controllers/RepeatedExpenseController.php
new file mode 100644
index 0000000000..b3bdd762e0
--- /dev/null
+++ b/app/controllers/RepeatedExpenseController.php
@@ -0,0 +1,135 @@
+getAssetAccounts());
+
+ return View::make('repeatedexpense.create', compact('accounts', 'periods'))->with('subTitle', 'Create new repeated expense')->with(
+ 'subTitleIcon', 'fa-plus'
+ );
+ }
+
+ /**
+ * @return \Illuminate\View\View
+ */
+ public function index()
+ {
+
+ $subTitle = 'Overview';
+
+ /** @var \FireflyIII\Database\RepeatedExpense $repository */
+ $repository = App::make('FireflyIII\Database\RepeatedExpense');
+
+ $expenses = $repository->get();
+ $expenses->each(
+ function (Piggybank $piggyBank) use ($repository) {
+ $piggyBank->currentRelevantRep();
+ }
+ );
+
+ return View::make('repeatedexpense.index', compact('expenses', 'subTitle'));
+ }
+
+ /**
+ * @param Piggybank $piggyBank
+ *
+ * @return \Illuminate\View\View
+ */
+ public function show(Piggybank $piggyBank)
+ {
+ $subTitle = $piggyBank->name;
+ $today = Carbon::now();
+
+ /** @var \FireflyIII\Database\RepeatedExpense $repository */
+ $repository = App::make('FireflyIII\Database\RepeatedExpense');
+
+ $repetitions = $piggyBank->piggybankrepetitions()->get();
+ $repetitions->each(
+ function (PiggybankRepetition $repetition) use ($repository) {
+ $repository->calculateParts($repetition);
+ }
+ );
+
+ return View::make('repeatedexpense.show', compact('repetitions', 'piggyBank', 'today', 'subTitle'));
+ }
+
+ /**
+ * @return $this
+ * @throws FireflyException
+ */
+ public function store()
+ {
+ $data = Input::all();
+ $data['repeats'] = 1;
+ /** @var \FireflyIII\Database\RepeatedExpense $repository */
+ $repository = App::make('FireflyIII\Database\RepeatedExpense');
+
+ switch ($data['post_submit_action']) {
+ default:
+ throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
+ break;
+ case 'create_another':
+ case 'store':
+ $messages = $repository->validate($data);
+ /** @var MessageBag $messages ['errors'] */
+ if ($messages['errors']->count() > 0) {
+ Session::flash('warnings', $messages['warnings']);
+ Session::flash('successes', $messages['successes']);
+ Session::flash('error', 'Could not save repeated expense: ' . $messages['errors']->first());
+
+ return Redirect::route('repeated.create')->withInput()->withErrors($messages['errors']);
+ }
+ // store!
+ $repeated = $repository->store($data);
+
+ /*
+ * Create the relevant repetition per Event.
+ */
+ Event::fire('piggybank.store', [$repeated]); // new and used.
+
+ Session::flash('success', 'New repeated expense stored!');
+
+ if ($data['post_submit_action'] == 'create_another') {
+ return Redirect::route('repeated.create')->withInput();
+ } else {
+ return Redirect::route('repeated.index');
+ }
+ break;
+ case 'validate_only':
+ $messageBags = $repository->validate($data);
+ Session::flash('warnings', $messageBags['warnings']);
+ Session::flash('successes', $messageBags['successes']);
+ Session::flash('errors', $messageBags['errors']);
+
+ return Redirect::route('repeated.create')->withInput();
+ break;
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/controllers/ReportController.php b/app/controllers/ReportController.php
index baab2c53a0..ecc45c9649 100644
--- a/app/controllers/ReportController.php
+++ b/app/controllers/ReportController.php
@@ -7,6 +7,108 @@ use Carbon\Carbon;
class ReportController extends BaseController
{
+ /**
+ * @param $year
+ * @param $month
+ *
+ * @return \Illuminate\View\View
+ */
+ public function budgets($year, $month)
+ {
+ try {
+ $start = new Carbon($year . '-' . $month . '-01');
+ } catch (Exception $e) {
+ App::abort(500);
+ }
+ $end = clone $start;
+ $title = 'Reports';
+ $subTitle = 'Budgets in ' . $start->format('F Y');
+ $mainTitleIcon = 'fa-line-chart';
+ $subTitleIcon = 'fa-bar-chart';
+
+ $end->endOfMonth();
+
+
+ // get a list of all budgets and expenses.
+ /** @var \FireflyIII\Database\Budget $budgetRepository */
+ $budgetRepository = App::make('FireflyIII\Database\Budget');
+
+ /** @var \FireflyIII\Database\Account $accountRepository */
+ $accountRepository = App::make('FireflyIII\Database\Account');
+
+
+ $budgets = $budgetRepository->get();
+
+ // calculate some stuff:
+ $budgets->each(
+ function (Budget $budget) use ($start, $end, $budgetRepository) {
+ $limitRepetitions = $budget->limitrepetitions()->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d'))->where(
+ 'enddate', '<=', $end->format(
+ 'Y-m-d'
+ )
+ )->get();
+ $repInfo = [];
+ /** @var LimitRepetition $repetition */
+ foreach ($limitRepetitions as $repetition) {
+ $spent = $budgetRepository->spentInPeriod($budget, $start, $end);
+ if ($spent > floatval($repetition->amount)) {
+ // overspent!
+ $overspent = true;
+ $pct = floatval($repetition->amount) / $spent * 100;
+
+ } else {
+ $overspent = false;
+ $pct = $spent / floatval($repetition->amount) * 100;
+ }
+ $pctDisplay = $spent / floatval($repetition->amount) * 100;
+ $repInfo[] = [
+ 'date' => DateKit::periodShow($repetition->startdate, $repetition->limit->repeat_freq),
+ 'spent' => $spent,
+ 'budgeted' => floatval($repetition->amount),
+ 'left' => floatval($repetition->amount) - $spent,
+ 'pct' => ceil($pct),
+ 'pct_display' => ceil($pctDisplay),
+ 'overspent' => $overspent,
+ ];
+ }
+ $budget->repInfo = $repInfo;
+
+ }
+ );
+
+ $accounts = $accountRepository->getAssetAccounts();
+
+ $accounts->each(
+ function (Account $account) use ($start, $end, $accountRepository) {
+ $journals = $accountRepository->getTransactionJournalsInRange($account, $start, $end);
+ $budgets = [];
+ /** @var TransactionJournal $journal */
+ foreach ($journals as $journal) {
+ $budgetId = isset($journal->budgets[0]) ? $journal->budgets[0]->id : 0;
+ $budgetName = isset($journal->budgets[0]) ? $journal->budgets[0]->name : '(no budget)';
+ if (!isset($budgets[$budgetId])) {
+ $arr = [
+ 'budget_id' => $budgetId,
+ 'budget_name' => $budgetName,
+ 'spent' => floatval($journal->getAmount()),
+ 'budgeted' => 0,
+ ];
+ $budgets[$budgetId] = $arr;
+ } else {
+ $budgets[$budgetId]['spent'] += floatval($journal->getAmount());
+ }
+ }
+ foreach ($budgets as $budgetId => $budget) {
+ $budgets[$budgetId]['left'] = $budget['budgeted'] - $budget['spent'];
+ }
+ $account->budgetInfo = $budgets;
+ }
+ );
+
+
+ return View::make('reports.budgets', compact('start', 'end', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon', 'budgets', 'accounts'));
+
+ }
/**
*
@@ -15,53 +117,194 @@ class ReportController extends BaseController
{
/** @var \FireflyIII\Database\TransactionJournal $journals */
$journals = App::make('FireflyIII\Database\TransactionJournal');
- $journal = $journals->first();
-
- $date = $journal->date;
- $years = [];
+ /** @var TransactionJournal $journal */
+ $journal = $journals->first();
+ if (is_null($journal)) {
+ $date = Carbon::now();
+ } else {
+ $date = clone $journal->date;
+ }
+ $years = [];
+ $months = [];
while ($date <= Carbon::now()) {
$years[] = $date->format('Y');
$date->addYear();
}
+ // months
+ if (is_null($journal)) {
+ $date = Carbon::now();
+ } else {
+ $date = clone $journal->date;
+ }
+ while ($date <= Carbon::now()) {
+ $months[] = [
+ 'formatted' => $date->format('F Y'),
+ 'month' => intval($date->format('m')),
+ 'year' => intval($date->format('Y')),
+ ];
+ $date->addMonth();
+ }
- return View::make('reports.index', compact('years'))->with('title', 'Reports')->with('mainTitleIcon', 'fa-line-chart');
+ return View::make('reports.index', compact('years', 'months'))->with('title', 'Reports')->with('mainTitleIcon', 'fa-line-chart');
}
/**
* @param $year
+ * @param $month
+ *
+ * @return \Illuminate\View\View
+ */
+ public function unbalanced($year, $month)
+ {
+ try {
+ $date = new Carbon($year . '-' . $month . '-01');
+ } catch (Exception $e) {
+ App::abort(500);
+ }
+ $start = new Carbon($year . '-' . $month . '-01');
+ $end = clone $start;
+ $title = 'Reports';
+ $subTitle = 'Unbalanced transactions in ' . $start->format('F Y');
+ $mainTitleIcon = 'fa-line-chart';
+ $subTitleIcon = 'fa-bar-chart';
+ $end->endOfMonth();
+
+ /** @var \FireflyIII\Database\TransactionJournal $journalRepository */
+ $journalRepository = App::make('FireflyIII\Database\TransactionJournal');
+
+ /*
+ * Get all journals from this month:
+ */
+ $journals = $journalRepository->getInDateRange($start, $end);
+
+ /*
+ * Filter withdrawals:
+ */
+ $withdrawals = $journals->filter(
+ function (TransactionJournal $journal) {
+ if ($journal->transactionType->type == 'Withdrawal' && count($journal->budgets) == 0) {
+
+ // count groups related to balance.
+ if ($journal->transactiongroups()->where('relation', 'balance')->count() == 0) {
+ return $journal;
+ }
+ }
+
+ return null;
+ }
+ );
+ /*
+ * Filter deposits.
+ */
+ $deposits = $journals->filter(
+ function (TransactionJournal $journal) {
+ if ($journal->transactionType->type == 'Deposit' && count($journal->budgets) == 0) {
+ // count groups related to balance.
+ if ($journal->transactiongroups()->where('relation', 'balance')->count() == 0) {
+ return $journal;
+ }
+ }
+
+ return null;
+ }
+ );
+
+
+ /*
+ * Filter transfers (not yet used)
+ */
+ // $transfers = $journals->filter(
+ // function (TransactionJournal $journal) {
+ // if ($journal->transactionType->type == 'Transfer') {
+ // return $journal;
+ // }
+ // }
+ // );
+
+ $journals = $withdrawals->merge($deposits);
+
+
+ return View::make('reports.unbalanced', compact('start', 'end', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon', 'journals'));
+ }
+
+ /**
+ * @param $year
+ *
+ * @return $this
*/
public function year($year)
{
+ Config::set('app.debug', false);
try {
$date = new Carbon('01-01-' . $year);
} catch (Exception $e) {
App::abort(500);
}
+ $date = new Carbon('01-01-' . $year);
/** @var \FireflyIII\Database\TransactionJournal $tj */
$tj = App::make('FireflyIII\Database\TransactionJournal');
+ /** @var \FireflyIII\Database\Account $accountRepository */
+ $accountRepository = App::make('FireflyIII\Database\Account');
+
+ /** @var \FireflyIII\Database\Report $reportRepository */
+ $reportRepository = App::make('FireflyIII\Database\Report');
+
+ $accounts = $accountRepository->getAssetAccounts();
+
// get some sums going
$summary = [];
+ /** @var \Account $account */
+ $accounts->each(
+ function (\Account $account) {
+ if ($account->getMeta('accountRole') == 'sharedExpense') {
+ $account->sharedExpense = true;
+ } else {
+ $account->sharedExpense = false;
+ }
+ }
+ );
+
$end = clone $date;
$end->endOfYear();
while ($date < $end) {
+ $month = $date->format('F');
+
+ $income = 0;
+ $incomeShared = 0;
+ $expense = 0;
+ $expenseShared = 0;
+
+ foreach ($accounts as $account) {
+ if ($account->sharedExpense === true) {
+ $incomeShared += $reportRepository->getIncomeByMonth($account, $date);
+ $expenseShared += $reportRepository->getExpenseByMonth($account, $date);
+ } else {
+ $income += $reportRepository->getIncomeByMonth($account, $date);
+ $expense += $reportRepository->getExpenseByMonth($account, $date);
+ }
+ }
+
$summary[] = [
- 'month' => $date->format('F'),
- 'income' => $tj->getSumOfIncomesByMonth($date),
- 'expense' => $tj->getSumOfExpensesByMonth($date),
+ 'month' => $month,
+ 'income' => $income,
+ 'expense' => $expense,
+ 'incomeShared' => $incomeShared,
+ 'expenseShared' => $expenseShared,
];
$date->addMonth();
}
// draw some charts etc.
- return View::make('reports.year', compact('summary'))->with('title', 'Reports')->with('mainTitleIcon', 'fa-line-chart')->with('subTitle', $year)->with(
- 'subTitleIcon', 'fa-bar-chart'
- )->with('year', $year);
+ return View::make('reports.year', compact('summary', 'date'))->with('title', 'Reports')->with('mainTitleIcon', 'fa-line-chart')->with('subTitle', $year)
+ ->with(
+ 'subTitleIcon', 'fa-bar-chart'
+ )->with('year', $year);
}
}
\ No newline at end of file
diff --git a/app/controllers/SearchController.php b/app/controllers/SearchController.php
index 205933400b..e1588d8e3b 100644
--- a/app/controllers/SearchController.php
+++ b/app/controllers/SearchController.php
@@ -1,50 +1,38 @@
_helper = $helper;
-
- }
-
/**
* Results always come in the form of an array [results, count, fullCount]
*/
public function index()
{
+
+ /** @var \FireflyIII\Search\Search $searcher */
+ $searcher = App::make('FireflyIII\Search\Search');
+
$subTitle = null;
$rawQuery = null;
- $result = [];
+ $result = [];
if (!is_null(Input::get('q'))) {
$rawQuery = trim(Input::get('q'));
$words = explode(' ', $rawQuery);
$subTitle = 'Results for "' . e($rawQuery) . '"';
- $transactions = $this->_helper->searchTransactions($words);
- $accounts = $this->_helper->searchAccounts($words);
- $categories = $this->_helper->searchCategories($words);
- $budgets = $this->_helper->searchBudgets($words);
- $tags = $this->_helper->searchTags($words);
- $result = [
- 'transactions' => $transactions,
- 'accounts' => $accounts,
- 'categories' => $categories,
- 'budgets' => $budgets,
- 'tags' => $tags
- ];
+ $transactions = $searcher->searchTransactions($words);
+ $accounts = $searcher->searchAccounts($words);
+ $categories = $searcher->searchCategories($words);
+ $budgets = $searcher->searchBudgets($words);
+ $tags = $searcher->searchTags($words);
+ $result = ['transactions' => $transactions, 'accounts' => $accounts, 'categories' => $categories, 'budgets' => $budgets, 'tags' => $tags];
}
return View::make('search.index')->with('title', 'Search')->with('subTitle', $subTitle)->with(
'mainTitleIcon', 'fa-search'
- )->with('query', $rawQuery)->with('result',$result);
+ )->with('query', $rawQuery)->with('result', $result);
}
}
\ No newline at end of file
diff --git a/app/controllers/TransactionController.php b/app/controllers/TransactionController.php
index e3ed758ed3..69333d6852 100644
--- a/app/controllers/TransactionController.php
+++ b/app/controllers/TransactionController.php
@@ -1,37 +1,67 @@
_repository = $repository;
- $this->_helper = $helper;
View::share('title', 'Transactions');
View::share('mainTitleIcon', 'fa-repeat');
}
+ /**
+ *
+ * TODO this needs cleaning up and thinking over.
+ *
+ * @param TransactionJournal $journal
+ *
+ * @return array|\Illuminate\Http\JsonResponse
+ */
+ public function alreadyRelated(TransactionJournal $journal)
+ {
+
+ $ids = [];
+ /** @var TransactionGroup $group */
+ foreach ($journal->transactiongroups()->get() as $group) {
+ /** @var TransactionJournal $jrnl */
+ foreach ($group->transactionjournals()->get() as $jrnl) {
+ if ($jrnl->id != $journal->id) {
+ $ids[] = $jrnl->id;
+ }
+ }
+ }
+ $unique = array_unique($ids);
+ if (count($ids) > 0) {
+
+ /** @var \FireflyIII\Database\TransactionJournal $repository */
+ $repository = App::make('FireflyIII\Database\TransactionJournal');
+ $set = $repository->getByIds($ids);
+ $set->each(
+ function (TransactionJournal $journal) {
+ $journal->amount = mf($journal->getAmount());
+ }
+ );
+
+ return Response::json($set->toArray());
+ } else {
+ return (new Collection)->toArray();
+ }
+ }
+
/**
* Shows the view helping the user to create a new transaction journal.
*
@@ -44,28 +74,31 @@ class TransactionController extends BaseController
/*
* The repositories we need:
*/
- /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */
- $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit');
- /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */
- $accountRepository = App::make('Firefly\Storage\Account\AccountRepositoryInterface');
+ /** @var \FireflyIII\Database\Account $accountRepository */
+ $accountRepository = App::make('FireflyIII\Database\Account');
- /** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budgetRepository */
- $budgetRepository = App::make('Firefly\Storage\Budget\BudgetRepositoryInterface');
+ /** @var \FireflyIII\Database\Budget $budgetRepository */
+ $budgetRepository = App::make('FireflyIII\Database\Budget');
- /** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $piggyRepository */
- $piggyRepository = App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
+ /** @var \FireflyIII\Database\Piggybank $piggyRepository */
+ $piggyRepository = App::make('FireflyIII\Database\Piggybank');
- // get asset accounts with names and id's.
- $assetAccounts = $toolkit->makeSelectList($accountRepository->getActiveDefault());
+ /** @var \FireflyIII\Database\RepeatedExpense $repRepository */
+ $repRepository = App::make('FireflyIII\Database\RepeatedExpense');
+
+ // get asset accounts with names and id's .
+ $assetAccounts = FFForm::makeSelectList($accountRepository->getAssetAccounts());
// get budgets as a select list.
- $budgets = $toolkit->makeSelectList($budgetRepository->get());
+ $budgets = FFForm::makeSelectList($budgetRepository->get());
$budgets[0] = '(no budget)';
// get the piggy banks.
- $piggies = $toolkit->makeSelectList($piggyRepository->get());
+ $list = $piggyRepository->get()->merge($repRepository->get());
+ $piggies = FFForm::makeSelectList($list);
$piggies[0] = '(no piggy bank)';
+ asort($piggies);
/*
* respond to a possible given values in the URL.
@@ -79,9 +112,8 @@ class TransactionController extends BaseController
}
Session::put('prefilled', $prefilled);
- return View::make('transactions.create')->with('accounts', $assetAccounts)->with('budgets', $budgets)->with(
- 'what', $what
- )->with('piggies', $piggies)->with('subTitle', 'Add a new ' . $what);
+ return View::make('transactions.create')->with('accounts', $assetAccounts)->with('budgets', $budgets)->with('what', $what)->with('piggies', $piggies)
+ ->with('subTitle', 'Add a new ' . $what);
}
/**
@@ -102,7 +134,6 @@ class TransactionController extends BaseController
}
-
/**
* @param TransactionJournal $transactionJournal
*
@@ -111,19 +142,56 @@ class TransactionController extends BaseController
public function destroy(TransactionJournal $transactionJournal)
{
$type = $transactionJournal->transactionType->type;
- $transactionJournal->delete();
+
+ /** @var \FireflyIII\Database\TransactionJournal $repository */
+ $repository = App::make('FireflyIII\Database\TransactionJournal');
+ $repository->destroy($transactionJournal);
+
+ $return = 'withdrawal';
+
switch ($type) {
- case 'Withdrawal':
- return Redirect::route('transactions.expenses');
- break;
case 'Deposit':
- return Redirect::route('transactions.revenue');
+ $return = 'deposit';
break;
case 'Transfer':
- return Redirect::route('transactions.transfers');
+ $return = 'transfers';
break;
}
+
+ return Redirect::route('transactions.index', $return);
+ }
+
+ /**
+ * TODO this needs cleaning up and thinking over.
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function doRelate()
+ {
+ $id = intval(Input::get('id'));
+ $sister = intval(Input::get('relateTo'));
+
+ /** @var \FireflyIII\Database\TransactionJournal $repository */
+ $repository = App::make('FireflyIII\Database\TransactionJournal');
+
+ $journal = $repository->find($id);
+ $sis = $repository->find($sister);
+
+ if ($journal && $sis) {
+ $group = new TransactionGroup;
+ $group->relation = 'balance';
+ $group->user_id = $repository->getUser()->id;
+ $group->save();
+ $group->transactionjournals()->save($journal);
+ $group->transactionjournals()->save($sis);
+
+ return Response::json(true);
+ }
+
+ return Response::json(false);
+
+
}
/**
@@ -138,26 +206,25 @@ class TransactionController extends BaseController
/*
* All the repositories we need:
*/
- /** @var \Firefly\Helper\Toolkit\Toolkit $toolkit */
- $toolkit = App::make('Firefly\Helper\Toolkit\Toolkit');
- /** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */
- $accountRepository = App::make('Firefly\Storage\Account\AccountRepositoryInterface');
+ /** @var \FireflyIII\Database\Account $accountRepository */
+ $accountRepository = App::make('FireflyIII\Database\Account');
- /** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budgetRepository */
- $budgetRepository = App::make('Firefly\Storage\Budget\BudgetRepositoryInterface');
+ /** @var \FireflyIII\Database\Budget $budgetRepository */
+ $budgetRepository = App::make('FireflyIII\Database\Budget');
+
+ /** @var \FireflyIII\Database\Piggybank $piggyRepository */
+ $piggyRepository = App::make('FireflyIII\Database\Piggybank');
- /** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $piggyRepository */
- $piggyRepository = App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
// type is useful for display:
$what = strtolower($journal->transactiontype->type);
// get asset accounts with names and id's.
- $accounts = $toolkit->makeSelectList($accountRepository->getActiveDefault());
+ $accounts = FFForm::makeSelectList($accountRepository->getAssetAccounts());
// get budgets as a select list.
- $budgets = $toolkit->makeSelectList($budgetRepository->get());
+ $budgets = FFForm::makeSelectList($budgetRepository->get());
$budgets[0] = '(no budget)';
/*
@@ -165,8 +232,8 @@ class TransactionController extends BaseController
* of the transactions in the journal has this field, it should all fill in nicely.
*/
// get the piggy banks.
- $piggies = $toolkit->makeSelectList($piggyRepository->get());
- $piggies[0] = '(no piggy bank)';
+ $piggies = FFForm::makeSelectList($piggyRepository->get());
+ $piggies[0] = '(no piggy bank)';
$piggyBankId = 0;
foreach ($journal->transactions as $t) {
if (!is_null($t->piggybank_id)) {
@@ -198,29 +265,61 @@ class TransactionController extends BaseController
*/
switch ($what) {
case 'withdrawal':
- $prefilled['account_id'] = $journal->transactions[0]->account->id;
- $prefilled['expense_account'] = $journal->transactions[1]->account->name;
- $prefilled['amount'] = floatval($journal->transactions[1]->amount);
+ if (floatval($journal->transactions[0]->amount) < 0) {
+ // transactions[0] is the asset account that paid for the withdrawal.
+ $prefilled['account_id'] = $journal->transactions[0]->account->id;
+ $prefilled['expense_account'] = $journal->transactions[1]->account->name;
+ $prefilled['amount'] = floatval($journal->transactions[1]->amount);
+ } else {
+ // transactions[1] is the asset account that paid for the withdrawal.
+ $prefilled['account_id'] = $journal->transactions[1]->account->id;
+ $prefilled['expense_account'] = $journal->transactions[0]->account->name;
+ $prefilled['amount'] = floatval($journal->transactions[0]->amount);
+ }
+
+
$budget = $journal->budgets()->first();
if (!is_null($budget)) {
$prefilled['budget_id'] = $budget->id;
}
break;
case 'deposit':
- $prefilled['account_id'] = $journal->transactions[1]->account->id;
- $prefilled['revenue_account'] = $journal->transactions[0]->account->name;
- $prefilled['amount'] = floatval($journal->transactions[1]->amount);
+ if (floatval($journal->transactions[0]->amount) < 0) {
+ // transactions[0] contains the account the money came from.
+ $prefilled['account_id'] = $journal->transactions[1]->account->id;
+ $prefilled['revenue_account'] = $journal->transactions[0]->account->name;
+ $prefilled['amount'] = floatval($journal->transactions[1]->amount);
+ } else {
+ // transactions[1] contains the account the money came from.
+ $prefilled['account_id'] = $journal->transactions[0]->account->id;
+ $prefilled['revenue_account'] = $journal->transactions[1]->account->name;
+ $prefilled['amount'] = floatval($journal->transactions[0]->amount);
+
+ }
+
break;
case 'transfer':
- $prefilled['account_from_id'] = $journal->transactions[1]->account->id;
- $prefilled['account_to_id'] = $journal->transactions[0]->account->id;
- $prefilled['amount'] = floatval($journal->transactions[1]->amount);
+ if (floatval($journal->transactions[0]->amount) < 0) {
+ // zero = from account.
+ $prefilled['account_from_id'] = $journal->transactions[0]->account->id;
+ $prefilled['account_to_id'] = $journal->transactions[1]->account->id;
+ $prefilled['amount'] = floatval($journal->transactions[1]->amount);
+ } else {
+ // one = from account
+ $prefilled['account_from_id'] = $journal->transactions[1]->account->id;
+ $prefilled['account_to_id'] = $journal->transactions[0]->account->id;
+ $prefilled['amount'] = floatval($journal->transactions[0]->amount);
+ }
+ if ($journal->piggybankevents()->count() > 0) {
+ $prefilled['piggybank_id'] = $journal->piggybankevents()->first()->piggybank_id;
+ }
break;
}
/*
* Show the view.
*/
+
return View::make('transactions.edit')->with('journal', $journal)->with('accounts', $accounts)->with(
'what', $what
)->with('budgets', $budgets)->with('data', $prefilled)->with('piggies', $piggies)->with(
@@ -229,23 +328,85 @@ class TransactionController extends BaseController
}
/**
+ * @param $what
+ *
* @return $this
*/
- public function expenses()
+ public function index($what)
{
- return View::make('transactions.list')->with('subTitle', 'Expenses')->with(
- 'subTitleIcon', 'fa-long-arrow-left'
- )->with('what', 'expenses');
+
+ /** @var \FireflyIII\Database\TransactionJournal $repository */
+ $repository = App::make('FireflyIII\Database\TransactionJournal');
+
+ switch ($what) {
+ case 'expenses':
+ case 'withdrawal':
+ $subTitleIcon = 'fa-long-arrow-left';
+ $subTitle = 'Expenses';
+ $journals = $repository->getWithdrawalsPaginated(50);
+ break;
+ case 'revenue':
+ case 'deposit':
+ $subTitleIcon = 'fa-long-arrow-right';
+ $subTitle = 'Revenue, income and deposits';
+ $journals = $repository->getDepositsPaginated(50);
+ break;
+ case 'transfer':
+ case 'transfers':
+ $subTitleIcon = 'fa-arrows-h';
+ $subTitle = 'Transfers';
+ $journals = $repository->getTransfersPaginated(50);
+ break;
+ }
+
+ return View::make('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals'));
+
}
/**
- * @return $this
+ * @param TransactionJournal $journal
+ *
+ * @return \Illuminate\View\View
*/
- public function revenue()
+ public function relate(TransactionJournal $journal)
{
- return View::make('transactions.list')->with('subTitle', 'Revenue')->with(
- 'subTitleIcon', 'fa-long-arrow-right'
- )->with('what', 'revenue');
+ $groups = $journal->transactiongroups()->get();
+ $members = new Collection;
+ /** @var TransactionGroup $group */
+ foreach ($groups as $group) {
+ /** @var TransactionJournal $jrnl */
+ foreach ($group->transactionjournals()->get() as $jrnl) {
+ if ($jrnl->id != $journal->id) {
+ $members->push($jrnl);
+ }
+ }
+ }
+
+ return View::make('transactions.relate', compact('journal', 'members'));
+ }
+
+ /**
+ * TODO this needs cleaning up and thinking over.
+ *
+ * @param TransactionJournal $journal
+ *
+ * @return \Illuminate\Http\JsonResponse
+ */
+ public function relatedSearch(TransactionJournal $journal)
+ {
+ $search = e(trim(Input::get('searchValue')));
+
+ /** @var \FireflyIII\Database\TransactionJournal $repository */
+ $repository = App::make('FireflyIII\Database\TransactionJournal');
+
+ $result = $repository->searchRelated($search, $journal);
+ $result->each(
+ function (TransactionJournal $j) {
+ $j->amount = mf($j->getAmount());
+ }
+ );
+
+ return Response::json($result->toArray());
}
/**
@@ -255,7 +416,30 @@ class TransactionController extends BaseController
*/
public function show(TransactionJournal $journal)
{
- return View::make('transactions.show')->with('journal', $journal)->with(
+ $journal->transactions->each(
+ function (\Transaction $t) use ($journal) {
+ $t->before = floatval(
+ $t->account->transactions()->leftJoin(
+ 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
+ )->where('transaction_journals.date', '<=', $journal->date->format('Y-m-d'))->where(
+ 'transaction_journals.created_at', '<=', $journal->created_at->format('Y-m-d H:i:s')
+ )->where('transaction_journals.id', '!=', $journal->id)->sum('transactions.amount')
+ );
+ $t->after = $t->before + $t->amount;
+ }
+ );
+ $members = new Collection;
+ /** @var TransactionGroup $group */
+ foreach ($journal->transactiongroups()->get() as $group) {
+ /** @var TransactionJournal $jrnl */
+ foreach ($group->transactionjournals()->get() as $jrnl) {
+ if ($jrnl->id != $journal->id) {
+ $members->push($jrnl);
+ }
+ }
+ }
+
+ return View::make('transactions.show', compact('journal', 'members'))->with(
'subTitle', $journal->transactionType->type . ' "' . $journal->description . '"'
);
}
@@ -268,62 +452,92 @@ class TransactionController extends BaseController
*/
public function store($what)
{
- /*
- * Collect data to process:
- */
- $data = Input::except(['_token']);
- $data['what'] = $what;
+ $data = Input::except('_token');
+ $data['what'] = $what;
+ $data['currency'] = 'EUR';
- switch (Input::get('post_submit_action')) {
- case 'store':
+ /** @var \FireflyIII\Database\TransactionJournal $repository */
+ $repository = App::make('FireflyIII\Database\TransactionJournal');
+
+ switch ($data['post_submit_action']) {
+ default:
+ throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
+ break;
case 'create_another':
- /*
- * Try to store:
- */
- $messageBag = $this->_helper->store($data);
+ case 'store':
+ $messages = $repository->validate($data);
+ /** @var MessageBag $messages ['errors'] */
+ if ($messages['errors']->count() > 0) {
+ Session::flash('warnings', $messages['warnings']);
+ Session::flash('successes', $messages['successes']);
+ Session::flash('error', 'Could not save transaction: ' . $messages['errors']->first());
+
+ return Redirect::route('transactions.create', $what)->withInput()->withErrors($messages['errors']);
+ }
+ // store!
+ $journal = $repository->store($data);
+ Session::flash('success', 'New transaction stored!');
/*
- * Failure!
+ * Trigger a search for the related (if selected)
+ * piggy bank and store an event.
*/
- if ($messageBag->count() > 0) {
- Session::flash('error', 'Could not save transaction: ' . $messageBag->first());
- return Redirect::route('transactions.create', [$what])->withInput()->withErrors($messageBag);
+ $piggyID = null;
+ if (!is_null(Input::get('piggybank_id')) && intval(Input::get('piggybank_id')) > 0) {
+ $piggyID = intval(Input::get('piggybank_id'));
+ }
+ Event::fire('transactionJournal.store', [$journal, $piggyID]); // new and used.
+ /*
+ * Also trigger on both transactions.
+ */
+ /** @var Transaction $transaction */
+ foreach ($journal->transactions as $transaction) {
+ Event::fire('transaction.store', [$transaction]);
}
- /*
- * Success!
- */
- Session::flash('success', 'Transaction "' . e(Input::get('description')) . '" saved!');
-
- /*
- * Redirect to original location or back to the form.
- */
- if (Input::get('post_submit_action') == 'create_another') {
+ if ($data['post_submit_action'] == 'create_another') {
return Redirect::route('transactions.create', $what)->withInput();
} else {
- return Redirect::route('transactions.index.' . $what);
+ return Redirect::route('transactions.index', $what);
}
-
break;
case 'validate_only':
- $messageBags = $this->_helper->validate($data);
-
+ $messageBags = $repository->validate($data);
Session::flash('warnings', $messageBags['warnings']);
Session::flash('successes', $messageBags['successes']);
Session::flash('errors', $messageBags['errors']);
- return Redirect::route('transactions.create', [$what])->withInput();
- break;
- default:
- throw new FireflyException('Method ' . Input::get('post_submit_action') . ' not implemented yet.');
+
+ return Redirect::route('transactions.create', $what)->withInput();
break;
}
}
- public function transfers()
+ /**
+ * TODO this needs cleaning up and thinking over.
+ *
+ * @param TransactionJournal $journal
+ *
+ * @return \Illuminate\Http\JsonResponse
+ * @throws Exception
+ */
+ public function unrelate(TransactionJournal $journal)
{
- return View::make('transactions.list')->with('subTitle', 'Transfers')->with(
- 'subTitleIcon', 'fa-arrows-h'
- )->with('what', 'transfers');
+ $groups = $journal->transactiongroups()->get();
+ $relatedTo = intval(Input::get('relation'));
+ /** @var TransactionGroup $group */
+ foreach ($groups as $group) {
+ foreach ($group->transactionjournals()->get() as $jrnl) {
+ if ($jrnl->id == $relatedTo) {
+ // remove from group:
+ $group->transactionjournals()->detach($relatedTo);
+ }
+ }
+ if ($group->transactionjournals()->count() == 1) {
+ $group->delete();
+ }
+ }
+
+ return Response::json(true);
}
@@ -334,38 +548,52 @@ class TransactionController extends BaseController
*/
public function update(TransactionJournal $journal)
{
+ /** @var \FireflyIII\Database\TransactionJournal $repos */
+ $repos = App::make('FireflyIII\Database\TransactionJournal');
+
+ $data = Input::except('_token');
+ $data['currency'] = 'EUR';
+ $data['what'] = strtolower($journal->transactionType->type);
+
+
switch (Input::get('post_submit_action')) {
case 'update':
case 'return_to_edit':
- $what = strtolower($journal->transactionType->type);
- $messageBag = $this->_helper->update($journal, Input::all());
+ $messageBag = $repos->update($journal, $data);
if ($messageBag->count() == 0) {
// has been saved, return to index:
Session::flash('success', 'Transaction updated!');
- Event::fire('journals.update', [$journal]);
+ Event::fire('transactionJournal.update', [$journal]); // new and used.
+
+ /*
+ * Also trigger on both transactions.
+ */
+ /** @var Transaction $transaction */
+ foreach ($journal->transactions as $transaction) {
+ Event::fire('transaction.update', [$transaction]);
+ }
if (Input::get('post_submit_action') == 'return_to_edit') {
return Redirect::route('transactions.edit', $journal->id)->withInput();
} else {
- return Redirect::route('transactions.index.' . $what);
+ return Redirect::route('transactions.index', $data['what']);
}
} else {
- Session::flash('error', 'Could not update transaction: ' . $journal->errors()->first());
+ Session::flash('error', 'Could not update transaction: ' . $journal->getErrors()->first());
return Redirect::route('transactions.edit', $journal->id)->withInput()->withErrors(
- $journal->errors()
+ $journal->getErrors()
);
}
break;
case 'validate_only':
- $data = Input::all();
- $data['what'] = strtolower($journal->transactionType->type);
- $messageBags = $this->_helper->validate($data);
+ $messageBags = $repos->validate($data);
Session::flash('warnings', $messageBags['warnings']);
Session::flash('successes', $messageBags['successes']);
Session::flash('errors', $messageBags['errors']);
+
return Redirect::route('transactions.edit', $journal->id)->withInput();
break;
default:
@@ -376,4 +604,4 @@ class TransactionController extends BaseController
}
-}
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/app/controllers/UserController.php b/app/controllers/UserController.php
index 834c2bb9cb..5d101c850f 100644
--- a/app/controllers/UserController.php
+++ b/app/controllers/UserController.php
@@ -1,8 +1,5 @@
user = $user;
- $this->email = $email;
-
}
/**
@@ -32,6 +23,18 @@ class UserController extends BaseController
return View::make('user.login');
}
+ /**
+ * Logout user.
+ *
+ * @return \Illuminate\Http\RedirectResponse
+ */
+ public function logout()
+ {
+ Auth::logout();
+ Session::flush();
+
+ return Redirect::route('index');
+ }
/**
* Login.
@@ -41,10 +44,7 @@ class UserController extends BaseController
public function postLogin()
{
$rememberMe = Input::get('remember_me') == '1';
- $data = [
- 'email' => Input::get('email'),
- 'password' => Input::get('password')
- ];
+ $data = ['email' => Input::get('email'), 'password' => Input::get('password')];
$result = Auth::attempt($data, $rememberMe);
if ($result) {
return Redirect::route('index');
@@ -55,20 +55,6 @@ class UserController extends BaseController
return View::make('user.login');
}
- /**
- * If allowed, show the register form.
- *
- * @return $this|\Illuminate\View\View
- */
- public function register()
- {
- if (Config::get('auth.allow_register') !== true) {
- return View::make('error')->with('message', 'Not possible');
- }
-
- return View::make('user.register');
- }
-
/**
* If allowed, register the user.
*
@@ -84,32 +70,77 @@ class UserController extends BaseController
if (Config::get('auth.allow_register') !== true) {
return View::make('error')->with('message', 'Not possible');
}
- $user = $this->user->register(Input::all());
+
+ /** @var \FireflyIII\Database\User $repository */
+ $repository = App::make('FireflyIII\Database\User');
+
+ /** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */
+ $email = App::make('FireflyIII\Shared\Mail\RegistrationInterface');
+
+ $user = $repository->register(Input::all());
+
+
+ //$user = $this->user->register(Input::all());
if ($user) {
if (Config::get('auth.verify_mail') === true) {
- $this->email->sendVerificationMail($user);
+ $email->sendVerificationMail($user);
return View::make('user.verification-pending');
}
- $this->email->sendPasswordMail($user);
+ $email->sendPasswordMail($user);
return View::make('user.registered');
}
+
return View::make('user.register');
}
/**
- * Logout user.
+ * If need to verify, send new reset code.
+ * Otherwise, send new password.
*
- * @return \Illuminate\Http\RedirectResponse
+ * @return \Illuminate\View\View
*/
- public function logout()
+ public function postRemindme()
{
- Auth::logout();
- Session::flush();
- return Redirect::route('index');
+ /** @var \FireflyIII\Database\User $repository */
+ $repository = App::make('FireflyIII\Database\User');
+
+ /** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */
+ $email = App::make('FireflyIII\Shared\Mail\RegistrationInterface');
+
+
+ $user = $repository->findByEmail(Input::get('email'));
+ if (!$user) {
+ Session::flash('error', 'No good!');
+
+ return View::make('user.remindme');
+ }
+ if (Config::get('auth.verify_reset') === true) {
+ $email->sendResetVerification($user);
+
+ return View::make('user.verification-pending');
+ }
+ $email->sendPasswordMail($user);
+
+ return View::make('user.registered');
+
+ }
+
+ /**
+ * If allowed, show the register form.
+ *
+ * @return $this|\Illuminate\View\View
+ */
+ public function register()
+ {
+ if (Config::get('auth.allow_register') !== true) {
+ return View::make('error')->with('message', 'Not possible');
+ }
+
+ return View::make('user.register');
}
/**
@@ -122,31 +153,6 @@ class UserController extends BaseController
return View::make('user.remindme');
}
- /**
- * If need to verify, send new reset code.
- * Otherwise, send new password.
- *
- * @return \Illuminate\View\View
- */
- public function postRemindme()
- {
- $user = $this->user->findByEmail(Input::get('email'));
- if (!$user) {
- Session::flash('error', 'No good!');
-
- return View::make('user.remindme');
- }
- if (Config::get('auth.verify_reset') === true) {
- $this->email->sendResetVerification($user);
-
- return View::make('user.verification-pending');
- }
- $this->email->sendPasswordMail($user);
-
- return View::make('user.registered');
-
- }
-
/**
* Send a user a password based on his reset code.
*
@@ -156,9 +162,16 @@ class UserController extends BaseController
*/
public function reset($reset)
{
- $user = $this->user->findByReset($reset);
+
+ /** @var \FireflyIII\Database\User $repository */
+ $repository = App::make('FireflyIII\Database\User');
+
+ /** @var \FireflyIII\Shared\Mail\RegistrationInterface $email */
+ $email = App::make('FireflyIII\Shared\Mail\RegistrationInterface');
+
+ $user = $repository->findByReset($reset);
if ($user) {
- $this->email->sendPasswordMail($user);
+ $email->sendPasswordMail($user);
return View::make('user.registered');
}
diff --git a/app/database/migrations/2014_06_27_163032_create_users_table.php b/app/database/migrations/2014_06_27_163032_create_users_table.php
index 25cc4349a3..7dce4f47b8 100644
--- a/app/database/migrations/2014_06_27_163032_create_users_table.php
+++ b/app/database/migrations/2014_06_27_163032_create_users_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateUsersTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('users');
+ }
+
/**
* Run the migrations.
*
@@ -33,14 +43,4 @@ class CreateUsersTable extends Migration
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('users');
- }
-
}
diff --git a/app/database/migrations/2014_06_27_163145_create_account_types_table.php b/app/database/migrations/2014_06_27_163145_create_account_types_table.php
index b900c47bed..8a05459eaf 100644
--- a/app/database/migrations/2014_06_27_163145_create_account_types_table.php
+++ b/app/database/migrations/2014_06_27_163145_create_account_types_table.php
@@ -29,14 +29,14 @@ class CreateAccountTypesTable extends Migration
public function up()
{
Schema::create(
- 'account_types', function (Blueprint $table) {
- $table->increments('id');
- $table->timestamps();
- $table->string('type', 50);
- $table->boolean('editable');
+ 'account_types', function (Blueprint $table) {
+ $table->increments('id');
+ $table->timestamps();
+ $table->string('type', 50);
+ $table->boolean('editable');
- $table->unique('type');
- }
+ $table->unique('type');
+ }
);
}
diff --git a/app/database/migrations/2014_06_27_163259_create_accounts_table.php b/app/database/migrations/2014_06_27_163259_create_accounts_table.php
index e98a4d4581..0af5a60455 100644
--- a/app/database/migrations/2014_06_27_163259_create_accounts_table.php
+++ b/app/database/migrations/2014_06_27_163259_create_accounts_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateAccountsTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('accounts');
+ }
+
/**
* Run the migrations.
*
@@ -22,34 +32,21 @@ class CreateAccountsTable extends Migration
'accounts', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
+ $table->softDeletes();
$table->integer('user_id')->unsigned();
$table->integer('account_type_id')->unsigned();
$table->string('name', 100);
$table->boolean('active');
// connect accounts to users
- $table->foreign('user_id')
- ->references('id')->on('users')
- ->onDelete('cascade');
+ $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
// connect accounts to account_types
- $table->foreign('account_type_id')
- ->references('id')->on('account_types')
- ->onDelete('cascade');
+ $table->foreign('account_type_id')->references('id')->on('account_types')->onDelete('cascade');
$table->unique(['user_id', 'account_type_id', 'name']);
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('accounts');
- }
-
}
diff --git a/app/database/migrations/2014_06_27_163817_create_components_table.php b/app/database/migrations/2014_06_27_163817_create_components_table.php
index 998bef4ddf..210773199d 100644
--- a/app/database/migrations/2014_06_27_163817_create_components_table.php
+++ b/app/database/migrations/2014_06_27_163817_create_components_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateComponentsTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('components');
+ }
+
/**
* Run the migrations.
*
@@ -22,14 +32,13 @@ class CreateComponentsTable extends Migration
'components', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
+ $table->softDeletes();
$table->string('name', 50);
$table->integer('user_id')->unsigned();
$table->string('class', 20);
// connect components to users
- $table->foreign('user_id')
- ->references('id')->on('users')
- ->onDelete('cascade');
+ $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->unique(['user_id', 'class', 'name']);
}
@@ -37,14 +46,4 @@ class CreateComponentsTable extends Migration
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('components');
- }
-
}
diff --git a/app/database/migrations/2014_06_27_163818_create_piggybanks_table.php b/app/database/migrations/2014_06_27_163818_create_piggybanks_table.php
index 74ff3e20c8..25efdcf2ef 100644
--- a/app/database/migrations/2014_06_27_163818_create_piggybanks_table.php
+++ b/app/database/migrations/2014_06_27_163818_create_piggybanks_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreatePiggybanksTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('piggybanks');
+ }
+
/**
* Run the migrations.
*
@@ -28,32 +38,20 @@ class CreatePiggybanksTable extends Migration
$table->date('startdate')->nullable();
$table->date('targetdate')->nullable();
$table->boolean('repeats');
- $table->enum('rep_length', ['day', 'week', 'month', 'year'])->nullable();
+ $table->enum('rep_length', ['day', 'week', 'quarter', 'month', 'year'])->nullable();
$table->smallInteger('rep_every')->unsigned();
$table->smallInteger('rep_times')->unsigned()->nullable();
- $table->enum('reminder', ['day', 'week', 'month', 'year'])->nullable();
+ $table->enum('reminder', ['day', 'week', 'quarter', 'month', 'year'])->nullable();
$table->smallInteger('reminder_skip')->unsigned();
$table->boolean('remind_me');
$table->integer('order')->unsigned();
// connect account to piggybank.
- $table->foreign('account_id')
- ->references('id')->on('accounts')
- ->onDelete('cascade');
+ $table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
$table->unique(['account_id', 'name']);
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('piggybanks');
- }
-
}
diff --git a/app/database/migrations/2014_06_27_164042_create_transaction_currencies_table.php b/app/database/migrations/2014_06_27_164042_create_transaction_currencies_table.php
index 64c82f8491..be165577cb 100644
--- a/app/database/migrations/2014_06_27_164042_create_transaction_currencies_table.php
+++ b/app/database/migrations/2014_06_27_164042_create_transaction_currencies_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateTransactionCurrenciesTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('transaction_currencies');
+ }
+
/**
* Run the migrations.
*
@@ -22,19 +32,10 @@ class CreateTransactionCurrenciesTable extends Migration
'transaction_currencies', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
+ $table->softDeletes();
$table->string('code', 3);
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('transaction_currencies');
- }
-
}
diff --git a/app/database/migrations/2014_06_27_164512_create_transaction_types_table.php b/app/database/migrations/2014_06_27_164512_create_transaction_types_table.php
index 6cd34a74c5..40cf43e973 100644
--- a/app/database/migrations/2014_06_27_164512_create_transaction_types_table.php
+++ b/app/database/migrations/2014_06_27_164512_create_transaction_types_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateTransactionTypesTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('transaction_types');
+ }
+
/**
* Run the migrations.
*
@@ -22,19 +32,10 @@ class CreateTransactionTypesTable extends Migration
'transaction_types', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
+ $table->softDeletes();
$table->string('type', 50);
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('transaction_types');
- }
-
}
diff --git a/app/database/migrations/2014_06_27_164619_create_recurring_transactions_table.php b/app/database/migrations/2014_06_27_164619_create_recurring_transactions_table.php
index 46b48bc255..af41979983 100644
--- a/app/database/migrations/2014_06_27_164619_create_recurring_transactions_table.php
+++ b/app/database/migrations/2014_06_27_164619_create_recurring_transactions_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateRecurringTransactionsTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('recurring_transactions');
+ }
+
/**
* Run the migrations.
*
@@ -41,14 +51,4 @@ class CreateRecurringTransactionsTable extends Migration
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('recurring_transactions');
- }
-
}
diff --git a/app/database/migrations/2014_06_27_164620_create_transaction_journals_table.php b/app/database/migrations/2014_06_27_164620_create_transaction_journals_table.php
index 75886fa254..f895bca4d1 100644
--- a/app/database/migrations/2014_06_27_164620_create_transaction_journals_table.php
+++ b/app/database/migrations/2014_06_27_164620_create_transaction_journals_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateTransactionJournalsTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('transaction_journals');
+ }
+
/**
* Run the migrations.
*
@@ -22,6 +32,7 @@ class CreateTransactionJournalsTable extends Migration
'transaction_journals', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
+ $table->softDeletes();
$table->integer('user_id')->unsigned();
$table->integer('transaction_type_id')->unsigned();
$table->integer('recurring_transaction_id')->unsigned()->nullable();
@@ -31,36 +42,18 @@ class CreateTransactionJournalsTable extends Migration
$table->date('date');
// connect transaction journals to transaction types
- $table->foreign('transaction_type_id')
- ->references('id')->on('transaction_types')
- ->onDelete('cascade');
+ $table->foreign('transaction_type_id')->references('id')->on('transaction_types')->onDelete('cascade');
// connect transaction journals to recurring transactions
- $table->foreign('recurring_transaction_id')
- ->references('id')->on('recurring_transactions')
- ->onDelete('set null');
+ $table->foreign('recurring_transaction_id')->references('id')->on('recurring_transactions')->onDelete('set null');
// connect transaction journals to transaction currencies
- $table->foreign('transaction_currency_id')
- ->references('id')->on('transaction_currencies')
- ->onDelete('cascade');
+ $table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
// connect users
- $table->foreign('user_id')
- ->references('id')->on('users')
- ->onDelete('cascade');
+ $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('transaction_journals');
- }
-
}
diff --git a/app/database/migrations/2014_06_27_164836_create_transactions_table.php b/app/database/migrations/2014_06_27_164836_create_transactions_table.php
index 9bd7c6177d..917d65e181 100644
--- a/app/database/migrations/2014_06_27_164836_create_transactions_table.php
+++ b/app/database/migrations/2014_06_27_164836_create_transactions_table.php
@@ -32,6 +32,7 @@ class CreateTransactionsTable extends Migration
'transactions', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
+ $table->softDeletes();
$table->integer('account_id')->unsigned();
$table->integer('piggybank_id')->nullable()->unsigned();
$table->integer('transaction_journal_id')->unsigned();
@@ -39,19 +40,13 @@ class CreateTransactionsTable extends Migration
$table->decimal('amount', 10, 2);
// connect transactions to transaction journals
- $table->foreign('transaction_journal_id')
- ->references('id')->on('transaction_journals')
- ->onDelete('cascade');
+ $table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
// connect piggy banks
- $table->foreign('piggybank_id')
- ->references('id')->on('piggybanks')
- ->onDelete('set null');
+ $table->foreign('piggybank_id')->references('id')->on('piggybanks')->onDelete('set null');
// connect account id:
- $table->foreign('account_id')
- ->references('id')->on('accounts')
- ->onDelete('cascade');
+ $table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
}
);
diff --git a/app/database/migrations/2014_06_27_165344_create_component_transaction_table.php b/app/database/migrations/2014_06_27_165344_create_component_transaction_table.php
index 4c3a2c825a..7cbef507ee 100644
--- a/app/database/migrations/2014_06_27_165344_create_component_transaction_table.php
+++ b/app/database/migrations/2014_06_27_165344_create_component_transaction_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateComponentTransactionTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('component_transaction');
+ }
+
/**
* Run the migrations.
*
@@ -25,26 +35,12 @@ class CreateComponentTransactionTable extends Migration
$table->integer('transaction_id')->unsigned();
// connect to components
- $table->foreign('component_id')
- ->references('id')->on('components')
- ->onDelete('cascade');
+ $table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
// connect to transactions
- $table->foreign('transaction_id')
- ->references('id')->on('transactions')
- ->onDelete('cascade');
+ $table->foreign('transaction_id')->references('id')->on('transactions')->onDelete('cascade');
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('component_transaction');
- }
-
}
diff --git a/app/database/migrations/2014_07_05_171326_create_component_transaction_journal_table.php b/app/database/migrations/2014_07_05_171326_create_component_transaction_journal_table.php
index 1d4b9c5f51..b34fbc1aa2 100644
--- a/app/database/migrations/2014_07_05_171326_create_component_transaction_journal_table.php
+++ b/app/database/migrations/2014_07_05_171326_create_component_transaction_journal_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateComponentTransactionJournalTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('component_transaction_journal');
+ }
+
/**
* Run the migrations.
*
@@ -25,26 +35,12 @@ class CreateComponentTransactionJournalTable extends Migration
$table->integer('transaction_journal_id')->unsigned();
// link components with component_id
- $table->foreign('component_id')
- ->references('id')->on('components')
- ->onDelete('cascade');
+ $table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
// link transaction journals with transaction_journal_id
- $table->foreign('transaction_journal_id')
- ->references('id')->on('transaction_journals')
- ->onDelete('cascade');
+ $table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade');
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('component_transaction_journal');
- }
-
}
diff --git a/app/database/migrations/2014_07_06_123842_create_preferences_table.php b/app/database/migrations/2014_07_06_123842_create_preferences_table.php
index 9aabb3bbcd..fb74ddd1bc 100644
--- a/app/database/migrations/2014_07_06_123842_create_preferences_table.php
+++ b/app/database/migrations/2014_07_06_123842_create_preferences_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreatePreferencesTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('preferences');
+ }
+
/**
* Run the migrations.
*
@@ -27,21 +37,9 @@ class CreatePreferencesTable extends Migration
$table->text('data');
// connect preferences to users
- $table->foreign('user_id')
- ->references('id')->on('users')
- ->onDelete('cascade');
+ $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('preferences');
- }
-
}
diff --git a/app/database/migrations/2014_07_09_204843_create_session_table.php b/app/database/migrations/2014_07_09_204843_create_session_table.php
index 7e29be1cce..c4423f33cf 100644
--- a/app/database/migrations/2014_07_09_204843_create_session_table.php
+++ b/app/database/migrations/2014_07_09_204843_create_session_table.php
@@ -10,6 +10,16 @@ use Illuminate\Database\Migrations\Migration;
class CreateSessionTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('sessions');
+ }
+
/**
* Run the migrations.
*
@@ -26,14 +36,4 @@ class CreateSessionTable extends Migration
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('sessions');
- }
-
}
diff --git a/app/database/migrations/2014_07_17_183717_create_limits_table.php b/app/database/migrations/2014_07_17_183717_create_limits_table.php
index 0edb4a17c8..fb3dbe3660 100644
--- a/app/database/migrations/2014_07_17_183717_create_limits_table.php
+++ b/app/database/migrations/2014_07_17_183717_create_limits_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateLimitsTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('limits');
+ }
+
/**
* Run the migrations.
*
@@ -31,21 +41,9 @@ class CreateLimitsTable extends Migration
$table->unique(['component_id', 'startdate', 'repeat_freq']);
// connect component
- $table->foreign('component_id')
- ->references('id')->on('components')
- ->onDelete('cascade');
+ $table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('limits');
- }
-
}
diff --git a/app/database/migrations/2014_07_19_055011_create_limit_repeat_table.php b/app/database/migrations/2014_07_19_055011_create_limit_repeat_table.php
index f0578b463a..e69902a3eb 100644
--- a/app/database/migrations/2014_07_19_055011_create_limit_repeat_table.php
+++ b/app/database/migrations/2014_07_19_055011_create_limit_repeat_table.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreateLimitRepeatTable extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('limit_repetitions');
+ }
+
/**
* Run the migrations.
*
@@ -30,21 +40,9 @@ class CreateLimitRepeatTable extends Migration
$table->unique(['limit_id', 'startdate', 'enddate']);
// connect limit
- $table->foreign('limit_id')
- ->references('id')->on('limits')
- ->onDelete('cascade');
+ $table->foreign('limit_id')->references('id')->on('limits')->onDelete('cascade');
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('limit_repetitions');
- }
-
}
diff --git a/app/database/migrations/2014_08_06_044416_recurring_transactions_to_components.php b/app/database/migrations/2014_08_06_044416_recurring_transactions_to_components.php
index 18a789b4bd..326228af51 100644
--- a/app/database/migrations/2014_08_06_044416_recurring_transactions_to_components.php
+++ b/app/database/migrations/2014_08_06_044416_recurring_transactions_to_components.php
@@ -11,6 +11,16 @@ use Illuminate\Database\Schema\Blueprint;
class RecurringTransactionsToComponents extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('component_recurring_transaction');
+ }
+
/**
* Run the migrations.
*
@@ -26,26 +36,12 @@ class RecurringTransactionsToComponents extends Migration
$table->boolean('optional');
// link components with component_id
- $table->foreign('component_id')
- ->references('id')->on('components')
- ->onDelete('cascade');
+ $table->foreign('component_id')->references('id')->on('components')->onDelete('cascade');
// link transaction journals with transaction_journal_id
- $table->foreign('recurring_transaction_id')
- ->references('id')->on('recurring_transactions')
- ->onDelete('cascade');
+ $table->foreign('recurring_transaction_id')->references('id')->on('recurring_transactions')->onDelete('cascade');
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('component_recurring_transaction');
- }
-
}
diff --git a/app/database/migrations/2014_08_12_173919_create_piggy_instance.php b/app/database/migrations/2014_08_12_173919_create_piggy_instance.php
index c4a0c0ceeb..96dbb1ec06 100644
--- a/app/database/migrations/2014_08_12_173919_create_piggy_instance.php
+++ b/app/database/migrations/2014_08_12_173919_create_piggy_instance.php
@@ -6,6 +6,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreatePiggyInstance extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('piggybank_repetitions');
+ }
+
/**
* Run the migrations.
*
@@ -25,21 +35,9 @@ class CreatePiggyInstance extends Migration
$table->unique(['piggybank_id', 'startdate', 'targetdate']);
// connect instance to piggybank.
- $table->foreign('piggybank_id')
- ->references('id')->on('piggybanks')
- ->onDelete('cascade');
+ $table->foreign('piggybank_id')->references('id')->on('piggybanks')->onDelete('cascade');
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('piggybank_repetitions');
- }
-
}
diff --git a/app/database/migrations/2014_08_18_100330_create_piggy_events.php b/app/database/migrations/2014_08_18_100330_create_piggy_events.php
index 3551a6b0d9..6abd680a19 100644
--- a/app/database/migrations/2014_08_18_100330_create_piggy_events.php
+++ b/app/database/migrations/2014_08_18_100330_create_piggy_events.php
@@ -6,6 +6,16 @@ use Illuminate\Database\Schema\Blueprint;
class CreatePiggyEvents extends Migration
{
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('piggybank_events');
+ }
+
/**
* Run the migrations.
*
@@ -22,21 +32,9 @@ class CreatePiggyEvents extends Migration
$table->decimal('amount', 10, 2);
// connect instance to piggybank.
- $table->foreign('piggybank_id')
- ->references('id')->on('piggybanks')
- ->onDelete('cascade');
+ $table->foreign('piggybank_id')->references('id')->on('piggybanks')->onDelete('cascade');
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('piggybank_events');
- }
-
}
diff --git a/app/database/migrations/2014_08_23_113221_create_reminders_table.php b/app/database/migrations/2014_08_23_113221_create_reminders_table.php
index 12a04c3b00..bf7ac668b4 100644
--- a/app/database/migrations/2014_08_23_113221_create_reminders_table.php
+++ b/app/database/migrations/2014_08_23_113221_create_reminders_table.php
@@ -33,9 +33,7 @@ class CreateRemindersTable extends Migration
$table->boolean('active');
// connect reminders to users
- $table->foreign('user_id')
- ->references('id')->on('users')
- ->onDelete('cascade');
+ $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
}
);
}
diff --git a/app/database/migrations/2014_08_31_153322_create_importmaps_table.php b/app/database/migrations/2014_08_31_153322_create_importmaps_table.php
index c4b68c7b68..5d7eeefcf9 100644
--- a/app/database/migrations/2014_08_31_153322_create_importmaps_table.php
+++ b/app/database/migrations/2014_08_31_153322_create_importmaps_table.php
@@ -1,41 +1,41 @@
increments('id');
- $table->timestamps();
- $table->integer('user_id')->unsigned();
- $table->string('file',500);
- $table->integer('totaljobs')->unsigned();
- $table->integer('jobsdone')->unsigned();
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::drop('importmaps');
+ }
- // connect maps to users
- $table->foreign('user_id')
- ->references('id')->on('users')
- ->onDelete('cascade');
- });
- }
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::create(
+ 'importmaps', function (Blueprint $table) {
+ $table->increments('id');
+ $table->timestamps();
+ $table->integer('user_id')->unsigned();
+ $table->string('file', 500);
+ $table->integer('totaljobs')->unsigned();
+ $table->integer('jobsdone')->unsigned();
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('importmaps');
- }
+ // connect maps to users
+ $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
+ }
+ );
+ }
}
diff --git a/app/database/migrations/2014_09_01_052816_create_importentries_table.php b/app/database/migrations/2014_09_01_052816_create_importentries_table.php
index 70cd8e862c..5003dfc9d5 100644
--- a/app/database/migrations/2014_09_01_052816_create_importentries_table.php
+++ b/app/database/migrations/2014_09_01_052816_create_importentries_table.php
@@ -1,11 +1,21 @@
integer('new')->unsigned();
// connect import map.
- $table->foreign('importmap_id')
- ->references('id')->on('importmaps')
- ->onDelete('cascade');
+ $table->foreign('importmap_id')->references('id')->on('importmaps')->onDelete('cascade');
}
);
}
- /**
- * Reverse the migrations.
- *
- * @return void
- */
- public function down()
- {
- Schema::drop('importentries');
- }
-
}
diff --git a/app/database/migrations/2014_09_02_103101_create_failed_jobs_table.php b/app/database/migrations/2014_09_02_103101_create_failed_jobs_table.php
index eb0e8e6c12..89cb377e9d 100644
--- a/app/database/migrations/2014_09_02_103101_create_failed_jobs_table.php
+++ b/app/database/migrations/2014_09_02_103101_create_failed_jobs_table.php
@@ -23,13 +23,15 @@ class CreateFailedJobsTable extends Migration
*/
public function up()
{
- Schema::create('failed_jobs', function (Blueprint $table) {
- $table->increments('id');
- $table->text('connection');
- $table->text('queue');
- $table->text('payload');
- $table->timestamp('failed_at');
- });
+ Schema::create(
+ 'failed_jobs', function (Blueprint $table) {
+ $table->increments('id');
+ $table->text('connection');
+ $table->text('queue');
+ $table->text('payload');
+ $table->timestamp('failed_at');
+ }
+ );
}
}
diff --git a/app/database/migrations/2014_11_10_172053_create_account_meta.php b/app/database/migrations/2014_11_10_172053_create_account_meta.php
index 8038f3726f..55281d7748 100644
--- a/app/database/migrations/2014_11_10_172053_create_account_meta.php
+++ b/app/database/migrations/2014_11_10_172053_create_account_meta.php
@@ -1,11 +1,22 @@
integer('transaction_journal_id')->unsigned()->nullable();
+ $table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('set null');
+ }
+ );
+ }
+
+}
diff --git a/app/database/migrations/2014_11_17_194734_event_table_additions_1.php b/app/database/migrations/2014_11_17_194734_event_table_additions_1.php
new file mode 100644
index 0000000000..6ccfb73235
--- /dev/null
+++ b/app/database/migrations/2014_11_17_194734_event_table_additions_1.php
@@ -0,0 +1,36 @@
+boolean('notnow')->default(0);
+ $table->integer('remindersable_id')->unsigned()->nullable();
+ $table->string('remindersable_type')->nullable();
+ }
+ );
+ }
+
+}
diff --git a/app/database/migrations/2014_11_25_204833_cacheTable.php b/app/database/migrations/2014_11_25_204833_cacheTable.php
new file mode 100644
index 0000000000..2ffbce905d
--- /dev/null
+++ b/app/database/migrations/2014_11_25_204833_cacheTable.php
@@ -0,0 +1,34 @@
+string('key')->unique();
+ $table->text('value');
+ $table->integer('expiration');
+ }
+ );
+ }
+
+}
diff --git a/app/database/migrations/2014_11_29_135749_transactiongroups.php b/app/database/migrations/2014_11_29_135749_transactiongroups.php
new file mode 100644
index 0000000000..09fecd7feb
--- /dev/null
+++ b/app/database/migrations/2014_11_29_135749_transactiongroups.php
@@ -0,0 +1,42 @@
+increments('id');
+ $table->timestamps();
+ $table->softDeletes();
+ $table->integer('user_id')->unsigned();
+ $table->enum('relation', ['balance']);
+
+ // connect reminders to users
+ $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
+ }
+ );
+
+
+ }
+
+}
diff --git a/app/database/migrations/2014_11_29_140217_transactiongroupsjoin.php b/app/database/migrations/2014_11_29_140217_transactiongroupsjoin.php
new file mode 100644
index 0000000000..ca3c9c1c6d
--- /dev/null
+++ b/app/database/migrations/2014_11_29_140217_transactiongroupsjoin.php
@@ -0,0 +1,42 @@
+increments('id');
+ $table->integer('transaction_group_id')->unsigned();
+ $table->integer('transaction_journal_id')->unsigned();
+
+ $table->foreign('transaction_group_id', 'tr_grp_id')->references('id')->on('transaction_groups')->onDelete('cascade');
+ $table->foreign('transaction_journal_id', 'tr_trj_id')->references('id')->on('transaction_journals')->onDelete('cascade');
+
+ $table->unique(['transaction_group_id', 'transaction_journal_id'], 'tt_joined');
+ }
+ );
+ }
+
+}
diff --git a/app/database/seeds/DatabaseSeeder.php b/app/database/seeds/DatabaseSeeder.php
index dd35eb592a..29319ca38c 100644
--- a/app/database/seeds/DatabaseSeeder.php
+++ b/app/database/seeds/DatabaseSeeder.php
@@ -19,6 +19,7 @@ class DatabaseSeeder extends Seeder
$this->call('TransactionCurrencySeeder');
$this->call('TransactionTypeSeeder');
$this->call('DefaultUserSeeder');
+ $this->call('TestContentSeeder');
}
}
diff --git a/app/database/seeds/DefaultUserSeeder.php b/app/database/seeds/DefaultUserSeeder.php
index dc7a102cbf..1b484c895c 100644
--- a/app/database/seeds/DefaultUserSeeder.php
+++ b/app/database/seeds/DefaultUserSeeder.php
@@ -8,16 +8,15 @@ class DefaultUserSeeder extends Seeder
public function run()
{
DB::table('users')->delete();
+ if (App::environment() == 'testing') {
- User::create(
- [
- 'email' => 's@nder.be',
- 'password' => 'sander',
- 'reset' => null,
- 'remember_token' => null,
- 'migrated' => 0
- ]
- );
+ User::create(
+ ['email' => 'thegrumpydictator@gmail.com', 'password' => 'james', 'reset' => null, 'remember_token' => null, 'migrated' => 0]
+ );
+ User::create(
+ ['email' => 'acceptance@example.com', 'password' => 'acceptance', 'reset' => null, 'remember_token' => null, 'migrated' => 0]
+ );
+ }
}
diff --git a/app/database/seeds/TestContentSeeder.php b/app/database/seeds/TestContentSeeder.php
new file mode 100644
index 0000000000..202b8ebd11
--- /dev/null
+++ b/app/database/seeds/TestContentSeeder.php
@@ -0,0 +1,176 @@
+first();
+ $expenseType = AccountType::whereType('Expense account')->first();
+ $revenueType = AccountType::whereType('Revenue account')->first();
+ $ibType = AccountType::whereType('Initial balance account')->first();
+
+ $euro = TransactionCurrency::whereCode('EUR')->first();
+
+ $obType = TransactionType::whereType('Opening balance')->first();
+ $withdrawal = TransactionType::whereType('Withdrawal')->first();
+ $transfer = TransactionType::whereType('Transfer')->first();
+ $deposit = TransactionType::whereType('Deposit')->first();
+
+ $user = User::whereEmail('thegrumpydictator@gmail.com')->first();
+
+ if ($user) {
+ // create two asset accounts.
+ $checking = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Checking account', 'active' => 1]);
+ $savings = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Savings account', 'active' => 1]);
+
+ // create two budgets:
+ $groceriesBudget = Budget::create(['user_id' => $user->id, 'name' => 'Groceries']);
+ $billsBudget = Budget::create(['user_id' => $user->id, 'name' => 'Bills']);
+
+ // create two categories:
+ $dailyGroceries = Category::create(['user_id' => $user->id, 'name' => 'Daily groceries']);
+ $lunch = Category::create(['user_id' => $user->id, 'name' => 'Lunch']);
+ $house = Category::create(['user_id' => $user->id, 'name' => 'House']);
+
+ // create some expense accounts.
+ $ah = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Albert Heijn', 'active' => 1]);
+ $plus = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'PLUS', 'active' => 1]);
+ $vitens = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Vitens', 'active' => 1]);
+ $greenchoice = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Greenchoice', 'active' => 1]);
+ $portaal = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Portaal', 'active' => 1]);
+ $store = Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Buy More', 'active' => 1]);
+
+ // create three revenue accounts.
+ $employer = Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'Employer', 'active' => 1]);
+ $taxes = Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'IRS', 'active' => 1]);
+ $job = Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'Job', 'active' => 1]);
+
+ // put money in the two accounts (initial balance)
+ $ibChecking = Account::create(
+ ['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Checking account initial balance', 'active' => 0]
+ );
+ $ibSavings = Account::create(
+ ['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Savings account initial balance', 'active' => 0]
+ );
+
+ $this->createTransaction($ibChecking, $checking, 4000, $obType, 'Initial Balance for Checking account', '2014-01-01');
+ $this->createTransaction($ibSavings, $savings, 10000, $obType, 'Initial Balance for Savings account', '2014-01-01');
+
+
+ // create some expenses and incomes and what-not (for every month):
+ $start = new Carbon('2014-01-01');
+ $end = Carbon::now()->startOfMonth()->subDay();
+ while ($start <= $end) {
+ $this->createTransaction(
+ $checking, $portaal, 500, $withdrawal, 'Rent for ' . $start->format('F Y'), $start->format('Y-m-') . '01', $billsBudget, $house
+ );
+ $this->createTransaction(
+ $checking, $vitens, 12, $withdrawal, 'Water for ' . $start->format('F Y'), $start->format('Y-m-') . '02', $billsBudget, $house
+ );
+ $this->createTransaction(
+ $checking, $greenchoice, 110, $withdrawal, 'Power for ' . $start->format('F Y'), $start->format('Y-m-') . '02', $billsBudget, $house
+ );
+
+ // spend on groceries
+ $groceriesStart = clone $start;
+ for ($i = 0; $i < 13; $i++) {
+ $amt = rand(100, 300) / 10;
+ $lunchAmount = rand(30, 60) / 10;
+ $this->createTransaction(
+ $checking, $plus, $lunchAmount, $withdrawal, 'Lunch', $groceriesStart->format('Y-m-d'), $groceriesBudget, $lunch
+ );
+ $groceriesStart->addDay();
+ if (intval($groceriesStart->format('d')) % 2 == 0) {
+ $this->createTransaction(
+ $checking, $ah, $amt, $withdrawal, 'Groceries', $groceriesStart->format('Y-m-d'), $groceriesBudget, $dailyGroceries
+ );
+ }
+ $groceriesStart->addDay();
+ }
+
+ // get income:
+ $this->createTransaction($employer, $checking, rand(1400, 1600), $deposit, 'Salary', $start->format('Y-m-') . '23');
+
+ // pay taxes:
+ $this->createTransaction($checking, $taxes, rand(50, 70), $withdrawal, 'Taxes in ' . $start->format('F Y'), $start->format('Y-m-') . '27');
+
+ // some other stuff.
+
+
+ $start->addMonth();
+
+ }
+
+ // create some big expenses, move some money around.
+ $this->createTransaction($savings, $checking, 1259, $transfer, 'Money for new PC', $end->format('Y-m') . '-11');
+ $this->createTransaction($checking, $store, 1259, $withdrawal, 'New PC', $end->format('Y-m') . '-12');
+
+ // create two budgets
+
+ // create two categories
+
+ // create
+ }
+
+ }
+ }
+
+ /**
+ * @param Account $from
+ * @param Account $to
+ * @param $amount
+ * @param TransactionType $type
+ * @param $description
+ * @param $date
+ *
+ * @return TransactionJournal
+ */
+ public function createTransaction(
+ Account $from, Account $to, $amount, TransactionType $type, $description, $date, Budget $budget = null, Category $category = null
+ ) {
+ $user = User::whereEmail('thegrumpydictator@gmail.com')->first();
+ $euro = TransactionCurrency::whereCode('EUR')->first();
+
+ /** @var TransactionJournal $journal */
+ $journal = TransactionJournal::create(
+ [
+ 'user_id' => $user->id,
+ 'transaction_type_id' => $type->id,
+ 'transaction_currency_id' => $euro->id,
+ 'description' => $description,
+ 'completed' => 1,
+ 'date' => $date
+ ]
+ );
+
+ Transaction::create(
+ [
+ 'account_id' => $from->id,
+ 'transaction_journal_id' => $journal->id,
+ 'amount' => $amount * -1
+ ]
+
+ );
+ Transaction::create(
+ [
+ 'account_id' => $to->id,
+ 'transaction_journal_id' => $journal->id,
+ 'amount' => $amount
+ ]
+
+ );
+ if (!is_null($budget)) {
+ $journal->budgets()->save($budget);
+ }
+ if (!is_null($category)) {
+ $journal->categories()->save($category);
+ }
+
+ return $journal;
+ }
+}
\ No newline at end of file
diff --git a/app/filters.php b/app/filters.php
index 5b4cf13296..a55467f0e3 100644
--- a/app/filters.php
+++ b/app/filters.php
@@ -4,14 +4,14 @@
App::before(
function ($request) {
+ $reminders = [];
if (Auth::check()) {
- /** @var \Firefly\Helper\Toolkit\ToolkitInterface $toolkit */
- $toolkit = App::make('Firefly\Helper\Toolkit\ToolkitInterface');
- $toolkit->getDateRange();
- $toolkit->checkImportJobs();
- Event::fire('recurring.verify');
+ Filter::setSessionDateRange();
+ Reminders::updateReminders();
+ $reminders = Reminders::getReminders();
}
+ View::share('reminders', $reminders);
}
);
@@ -68,6 +68,7 @@ Route::filter(
if (Auth::check()) {
return Redirect::to('/');
}
+ return null;
}
);
diff --git a/app/lang/en/pagination.php b/app/lang/en/pagination.php
index 6b99ef5fd8..88e22db661 100644
--- a/app/lang/en/pagination.php
+++ b/app/lang/en/pagination.php
@@ -1,6 +1,6 @@
'Next »',
-);
+];
diff --git a/app/lang/en/reminders.php b/app/lang/en/reminders.php
index e42148e9fb..a416c65cb5 100644
--- a/app/lang/en/reminders.php
+++ b/app/lang/en/reminders.php
@@ -1,24 +1,24 @@
"Passwords must be at least six characters and match the confirmation.",
+ "password" => "Passwords must be at least six characters and match the confirmation.",
- "user" => "We can't find a user with that e-mail address.",
+ "user" => "We can't find a user with that e-mail address.",
- "token" => "This password reset token is invalid.",
+ "token" => "This password reset token is invalid.",
- "sent" => "Password reminder sent!",
+ "sent" => "Password reminder sent!",
-);
+];
diff --git a/app/lang/en/validation.php b/app/lang/en/validation.php
index 4c17703856..e6ee8b9253 100644
--- a/app/lang/en/validation.php
+++ b/app/lang/en/validation.php
@@ -21,12 +21,12 @@ return [
"alpha_num" => "The :attribute may only contain letters and numbers.",
"array" => "The :attribute must be an array.",
"before" => "The :attribute must be a date before :date.",
- "between" => array(
+ "between" => [
"numeric" => "The :attribute must be between :min and :max.",
"file" => "The :attribute must be between :min and :max kilobytes.",
"string" => "The :attribute must be between :min and :max characters.",
"array" => "The :attribute must have between :min and :max items.",
- ),
+ ],
"confirmed" => "The :attribute confirmation does not match.",
"date" => "The :attribute is not a valid date.",
"date_format" => "The :attribute does not match the format :format.",
@@ -39,19 +39,19 @@ return [
"in" => "The selected :attribute is invalid.",
"integer" => "The :attribute must be an integer.",
"ip" => "The :attribute must be a valid IP address.",
- "max" => array(
+ "max" => [
"numeric" => "The :attribute may not be greater than :max.",
"file" => "The :attribute may not be greater than :max kilobytes.",
"string" => "The :attribute may not be greater than :max characters.",
"array" => "The :attribute may not have more than :max items.",
- ),
+ ],
"mimes" => "The :attribute must be a file of type: :values.",
- "min" => array(
+ "min" => [
"numeric" => "The :attribute must be at least :min.",
"file" => "The :attribute must be at least :min kilobytes.",
"string" => "The :attribute must be at least :min characters.",
"array" => "The :attribute must have at least :min items.",
- ),
+ ],
"not_in" => "The selected :attribute is invalid.",
"numeric" => "The :attribute must be a number.",
"regex" => "The :attribute format is invalid.",
@@ -62,12 +62,12 @@ return [
"required_without" => "The :attribute field is required when :values is not present.",
"required_without_all" => "The :attribute field is required when none of :values are present.",
"same" => "The :attribute and :other must match.",
- "size" => array(
+ "size" => [
"numeric" => "The :attribute must be :size.",
"file" => "The :attribute must be :size kilobytes.",
"string" => "The :attribute must be :size characters.",
"array" => "The :attribute must contain :size items.",
- ),
+ ],
"unique" => "The :attribute has already been taken.",
"url" => "The :attribute format is invalid.",
@@ -82,11 +82,11 @@ return [
|
*/
- 'custom' => array(
- 'attribute-name' => array(
+ 'custom' => [
+ 'attribute-name' => [
'rule-name' => 'custom-message',
- ),
- ),
+ ],
+ ],
'alphabasic' => 'The :attribute field must consist of basic alphanumeric characters.',
/*
@@ -100,6 +100,6 @@ return [
|
*/
- 'attributes' => array(),
+ 'attributes' => [],
];
diff --git a/app/lib/Firefly/Helper/Toolkit/Toolkit.php b/app/lib/Firefly/Helper/Toolkit/Toolkit.php
index 51941a2508..2e9dbeb725 100644
--- a/app/lib/Firefly/Helper/Toolkit/Toolkit.php
+++ b/app/lib/Firefly/Helper/Toolkit/Toolkit.php
@@ -107,9 +107,6 @@ class Toolkit implements ToolkitInterface
}
}
- /**
- * @return mixed
- */
protected function _getRange()
{
if (!is_null(\Session::get('range'))) {
diff --git a/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php b/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php
index 1d234a5dd9..2bbf39cbfe 100644
--- a/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php
+++ b/app/lib/Firefly/Storage/Account/EloquentAccountRepository.php
@@ -68,7 +68,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
/**
*
- * TODO
+ *
* Also delete: initial balance, initial balance account, and transactions
*/
diff --git a/app/lib/Firefly/Trigger/Budgets/EloquentBudgetTrigger.php b/app/lib/Firefly/Trigger/Budgets/EloquentBudgetTrigger.php
index 54a389c2df..696e039b61 100644
--- a/app/lib/Firefly/Trigger/Budgets/EloquentBudgetTrigger.php
+++ b/app/lib/Firefly/Trigger/Budgets/EloquentBudgetTrigger.php
@@ -46,9 +46,9 @@ class EloquentBudgetTrigger
*/
public function subscribe(Dispatcher $events)
{
- $events->listen('budgets.destroy', 'Firefly\Trigger\Budgets\EloquentBudgetTrigger@destroy');
- $events->listen('budgets.store', 'Firefly\Trigger\Budgets\EloquentBudgetTrigger@store');
- $events->listen('budgets.update', 'Firefly\Trigger\Budgets\EloquentBudgetTrigger@update');
+// $events->listen('budgets.destroy', 'Firefly\Trigger\Budgets\EloquentBudgetTrigger@destroy');
+// $events->listen('budgets.store', 'Firefly\Trigger\Budgets\EloquentBudgetTrigger@store');
+// $events->listen('budgets.update', 'Firefly\Trigger\Budgets\EloquentBudgetTrigger@update');
}
diff --git a/app/lib/Firefly/Trigger/Journals/EloquentJournalTrigger.php b/app/lib/Firefly/Trigger/Journals/EloquentJournalTrigger.php
index b2cdbf9bde..cbb5196fae 100644
--- a/app/lib/Firefly/Trigger/Journals/EloquentJournalTrigger.php
+++ b/app/lib/Firefly/Trigger/Journals/EloquentJournalTrigger.php
@@ -45,8 +45,8 @@ class EloquentJournalTrigger
*/
public function subscribe(Dispatcher $events)
{
- $events->listen('journals.store', 'Firefly\Trigger\Journals\EloquentJournalTrigger@store');
- $events->listen('journals.update', 'Firefly\Trigger\Journals\EloquentJournalTrigger@update');
+// $events->listen('journals.store', 'Firefly\Trigger\Journals\EloquentJournalTrigger@store');
+// $events->listen('journals.update', 'Firefly\Trigger\Journals\EloquentJournalTrigger@update');
}
diff --git a/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php b/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php
index 67f1e4dd03..2633684c14 100644
--- a/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php
+++ b/app/lib/Firefly/Trigger/Limits/EloquentLimitTrigger.php
@@ -107,11 +107,11 @@ class EloquentLimitTrigger
public function subscribe(Dispatcher $events)
{
//$events->listen('budgets.change', 'Firefly\Trigger\Limits\EloquentLimitTrigger@updateLimitRepetitions');
- $events->listen('limits.destroy', 'Firefly\Trigger\Limits\EloquentLimitTrigger@destroy');
- $events->listen('limits.store', 'Firefly\Trigger\Limits\EloquentLimitTrigger@store');
- $events->listen('limits.update', 'Firefly\Trigger\Limits\EloquentLimitTrigger@update');
- $events->listen('limits.check', 'Firefly\Trigger\Limits\EloquentLimitTrigger@checkRepeatingLimits');
- $events->listen('limits.repetition', 'Firefly\Trigger\Limits\EloquentLimitTrigger@madeRepetition');
+// $events->listen('limits.destroy', 'Firefly\Trigger\Limits\EloquentLimitTrigger@destroy');
+// $events->listen('limits.store', 'Firefly\Trigger\Limits\EloquentLimitTrigger@store');
+// $events->listen('limits.update', 'Firefly\Trigger\Limits\EloquentLimitTrigger@update');
+// $events->listen('limits.check', 'Firefly\Trigger\Limits\EloquentLimitTrigger@checkRepeatingLimits');
+// $events->listen('limits.repetition', 'Firefly\Trigger\Limits\EloquentLimitTrigger@madeRepetition');
//\Event::fire('limits.repetition', [$repetition]);
}
diff --git a/app/lib/Firefly/Trigger/Piggybanks/EloquentPiggybankTrigger.php b/app/lib/Firefly/Trigger/Piggybanks/EloquentPiggybankTrigger.php
index 09e3943099..5a51efe653 100644
--- a/app/lib/Firefly/Trigger/Piggybanks/EloquentPiggybankTrigger.php
+++ b/app/lib/Firefly/Trigger/Piggybanks/EloquentPiggybankTrigger.php
@@ -107,16 +107,6 @@ class EloquentPiggybankTrigger
return true;
}
- /**
- * @param \Piggybank $piggyBank
- *
- * @return bool
- */
- public function destroy(\Piggybank $piggyBank)
- {
- return true;
- }
-
/**
* @param \Piggybank $piggyBank
* @param $amount
@@ -175,26 +165,13 @@ class EloquentPiggybankTrigger
*/
public function subscribe(Dispatcher $events)
{
- $events->listen('piggybanks.destroy', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@destroy');
- $events->listen(
- 'piggybanks.modifyAmountAdd', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@modifyAmountAdd'
- );
- $events->listen(
- 'piggybanks.modifyAmountRemove', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@modifyAmountRemove'
- );
- $events->listen('piggybanks.store', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@store');
- $events->listen('piggybanks.update', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@update');
- $events->listen(
- 'piggybanks.createRelatedTransfer',
- 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@createRelatedTransfer'
- );
- $events->listen(
- 'piggybanks.updateRelatedTransfer',
- 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@updateRelatedTransfer'
- );
- $events->listen(
- 'piggybanks.storepiggybanks.check', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@checkRepeatingPiggies'
- );
+// $events->listen('piggybanks.modifyAmountAdd', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@modifyAmountAdd');
+// $events->listen('piggybanks.modifyAmountRemove', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@modifyAmountRemove');
+// $events->listen('piggybanks.store', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@store');
+// $events->listen('piggybanks.update', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@update');
+// $events->listen('piggybanks.createRelatedTransfer', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@createRelatedTransfer');
+// $events->listen('piggybanks.updateRelatedTransfer', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@updateRelatedTransfer');
+// $events->listen('piggybanks.storepiggybanks.check', 'Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger@checkRepeatingPiggies');
}
diff --git a/app/lib/Firefly/Trigger/Recurring/EloquentRecurringTrigger.php b/app/lib/Firefly/Trigger/Recurring/EloquentRecurringTrigger.php
index 1faface9c0..b29167bb48 100644
--- a/app/lib/Firefly/Trigger/Recurring/EloquentRecurringTrigger.php
+++ b/app/lib/Firefly/Trigger/Recurring/EloquentRecurringTrigger.php
@@ -99,7 +99,7 @@ class EloquentRecurringTrigger
*/
public function subscribe(Dispatcher $events)
{
- $events->listen('recurring.rescan', 'Firefly\Trigger\Recurring\EloquentRecurringTrigger@rescan');
+ //$events->listen('recurring.rescan', 'Firefly\Trigger\Recurring\EloquentRecurringTrigger@rescan');
}
/**
diff --git a/app/lib/FireflyIII/Collection/PiggybankPart.php b/app/lib/FireflyIII/Collection/PiggybankPart.php
new file mode 100644
index 0000000000..faf28173b2
--- /dev/null
+++ b/app/lib/FireflyIII/Collection/PiggybankPart.php
@@ -0,0 +1,167 @@
+reminder;
+ }
+
+ /**
+ * @param \Reminder $reminder
+ */
+ public function setReminder($reminder)
+ {
+ $this->reminder = $reminder;
+ }
+
+ /**
+ * @return \PiggybankRepetition
+ */
+ public function getRepetition()
+ {
+ return $this->repetition;
+ }
+
+ /**
+ * @param \PiggybankRepetition $repetition
+ */
+ public function setRepetition($repetition)
+ {
+ $this->repetition = $repetition;
+ }
+
+ /**
+ * @return Carbon
+ */
+ public function getStartdate()
+ {
+ return $this->startdate;
+ }
+
+ /**
+ * @param Carbon $startdate
+ */
+ public function setStartdate($startdate)
+ {
+ $this->startdate = $startdate;
+ }
+
+ /**
+ * @return Carbon
+ */
+ public function getTargetdate()
+ {
+ return $this->targetdate;
+ }
+
+ /**
+ * @param Carbon $targetdate
+ */
+ public function setTargetdate($targetdate)
+ {
+ $this->targetdate = $targetdate;
+ }
+
+ public function hasReminder()
+ {
+ return !is_null($this->reminder);
+ }
+
+ public function percentage()
+ {
+ if ($this->getCurrentamount() < $this->getCumulativeAmount()) {
+ $pct = 0;
+ // calculate halway point?
+ if ($this->getCumulativeAmount() - $this->getCurrentamount() < $this->getAmountPerBar()) {
+ $left = $this->getCurrentamount() % $this->getAmountPerBar();
+ $pct = round($left / $this->getAmountPerBar() * 100);
+ }
+
+ return $pct;
+ } else {
+ return 100;
+ }
+ }
+
+ /**
+ * @return float
+ */
+ public function getCurrentamount()
+ {
+ return $this->currentamount;
+ }
+
+ /**
+ * @param float $currentamount
+ */
+ public function setCurrentamount($currentamount)
+ {
+ $this->currentamount = $currentamount;
+ }
+
+ /**
+ * @return float
+ */
+ public function getAmountPerBar()
+ {
+ return $this->amountPerBar;
+ }
+
+ /**
+ * @param float $amountPerBar
+ */
+ public function setAmountPerBar($amountPerBar)
+ {
+ $this->amountPerBar = $amountPerBar;
+ }
+
+ /**
+ * @return float
+ */
+ public function getCumulativeAmount()
+ {
+ return $this->cumulativeAmount;
+ }
+
+ /**
+ * @param float $cumulativeAmount
+ */
+ public function setCumulativeAmount($cumulativeAmount)
+ {
+ $this->cumulativeAmount = $cumulativeAmount;
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/Account.php b/app/lib/FireflyIII/Database/Account.php
index 60726af53c..6dcd5ae0b3 100644
--- a/app/lib/FireflyIII/Database/Account.php
+++ b/app/lib/FireflyIII/Database/Account.php
@@ -6,9 +6,9 @@ use Carbon\Carbon;
use FireflyIII\Database\Ifaces\AccountInterface;
use FireflyIII\Database\Ifaces\CommonDatabaseCalls;
use FireflyIII\Database\Ifaces\CUD;
-use Illuminate\Support\MessageBag;
-use LaravelBook\Ardent\Ardent;
+use FireflyIII\Exception\NotImplementedException;
use Illuminate\Support\Collection;
+use Illuminate\Support\MessageBag;
/**
* Class Account
@@ -27,122 +27,14 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface
$this->setUser(\Auth::user());
}
- /**
- * @param Ardent $model
- * @param array $data
- *
- * @return bool
- */
- public function update(Ardent $model, array $data)
- {
- $model->name = $data['name'];
- $model->active = isset($data['active']) ? intval($data['active']) : 0;
- $model->save();
-
- if (isset($data['openingbalance']) && isset($data['openingbalancedate'])) {
- $openingBalance = $this->openingBalanceTransaction($model);
-
- $openingBalance->date = new Carbon($data['openingbalancedate']);
- $openingBalance->save();
- $amount = floatval($data['openingbalance']);
- /** @var \Transaction $transaction */
- foreach ($openingBalance->transactions as $transaction) {
- if ($transaction->account_id == $model->id) {
- $transaction->amount = $amount;
- } else {
- $transaction->amount = $amount * -1;
- }
- $transaction->save();
- }
- }
- return true;
- }
-
- /**
- * Get all asset accounts. Optional JSON based parameters.
- *
- * @param array $parameters
- *
- * @return Collection
- */
- public function getAssetAccounts(array $parameters = [])
- {
- return $this->getAccountsByType(['Default account', 'Asset account'], $parameters);
-
- }
-
- /**
- * @param \Account $account
- *
- * @return \Account|null
- */
- public function findInitialBalanceAccount(\Account $account)
- {
- /** @var \FireflyIII\Database\AccountType $acctType */
- $acctType = \App::make('FireflyIII\Database\AccountType');
-
- $accountType = $acctType->findByWhat('initial');
-
- return $this->getUser()->accounts()->where('account_type_id', $accountType->id)->where('name', 'LIKE', $account->name . '%')->first();
- }
-
/**
* @param array $types
- * @param array $parameters
*
- * @return Collection
+ * @return int
*/
- public function getAccountsByType(array $types, array $parameters = [])
+ public function countAccountsByType(array $types)
{
- /*
- * Basic query:
- */
- $query = $this->getUser()->accounts()->accountTypeIn($types);
-
-
- /*
- * Without an opening balance, the rest of these queries will fail.
- */
-
- $query->leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id');
- $query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id');
-
- /*
- * Not used, but useful for the balance within a certain month / year.
- */
- $balanceOnDate = isset($parameters['date']) ? $parameters['date'] : Carbon::now();
- $query->where(
- function ($q) use ($balanceOnDate) {
- $q->where('transaction_journals.date', '<=', $balanceOnDate->format('Y-m-d'));
- $q->orWhereNull('transaction_journals.date');
- }
- );
-
- $query->groupBy('accounts.id');
-
- /*
- * If present, process parameters for sorting:
- */
- $query->orderBy('name', 'ASC');
-
- /*
- * If present, process parameters for searching.
- */
- if (isset($parameters['search'])) {
- $query->where('name', 'LIKE', '%' . e($parameters['search']['value'] . '%'));
- }
-
- /*
- * If present, start at $start:
- */
- if (isset($parameters['start'])) {
- $query->skip(intval($parameters['start']));
- }
- if (isset($parameters['length'])) {
- $query->take(intval($parameters['length']));
- }
-
- return $query->get(['accounts.*', \DB::Raw('SUM(`transactions`.`amount`) as `balance`')]);
+ return $this->getUser()->accounts()->accountTypeIn($types)->count();
}
/**
@@ -161,58 +53,6 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface
return $this->countAccountsByType(['Expense account', 'Beneficiary account']);
}
- /**
- * @param array $types
- *
- * @return int
- */
- public function countAccountsByType(array $types)
- {
- return $this->getUser()->accounts()->accountTypeIn($types)->count();
- }
-
- /**
- * @param array $parameters
- *
- * @return Collection
- */
- public function getExpenseAccounts(array $parameters = [])
- {
- return $this->getAccountsByType(['Expense account', 'Beneficiary account'], $parameters);
- }
-
- /**
- * Get all default accounts.
- *
- * @return Collection
- */
- public function getDefaultAccounts()
- {
- // TODO: Implement getDefaultAccounts() method.
- }
-
- /**
- * Returns an object with id $id.
- *
- * @param int $id
- *
- * @return Ardent
- */
- public function find($id)
- {
- // TODO: Implement find() method.
- }
-
- /**
- * Returns all objects.
- *
- * @return Collection
- */
- public function get()
- {
- // TODO: Implement get() method.
- }
-
/**
* Counts the number of total revenue accounts. Useful for DataTables.
*
@@ -224,27 +64,104 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface
}
/**
- * Get all revenue accounts.
+ * @param \Account $account
+ *
+ * @return \Account|null
+ */
+ public function findInitialBalanceAccount(\Account $account)
+ {
+ /** @var \FireflyIII\Database\AccountType $acctType */
+ $acctType = \App::make('FireflyIII\Database\AccountType');
+
+ $accountType = $acctType->findByWhat('initial');
+
+ return $this->getUser()->accounts()->where('account_type_id', $accountType->id)->where('name', 'LIKE', $account->name . '%')->first();
+ }
+
+ /**
+ * @param array $types
+ *
+ * @return Collection
+ */
+ public function getAccountsByType(array $types)
+ {
+ /*
+ * Basic query:
+ */
+ $query = $this->getUser()->accounts()->accountTypeIn($types)->withMeta();
+
+
+ /*
+ * Without an opening balance, the rest of these queries will fail.
+ */
+
+ $query->leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id');
+ $query->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id');
+
+ /*
+ * Not used, but useful for the balance within a certain month / year.
+ */
+ $query->where(
+ function ($q) {
+ $q->where('transaction_journals.date', '<=', Carbon::now()->format('Y-m-d'));
+ $q->orWhereNull('transaction_journals.date');
+ }
+ );
+
+ $query->groupBy('accounts.id');
+
+ /*
+ * If present, process parameters for sorting:
+ */
+ $query->orderBy('name', 'ASC');
+
+ return $query->get(['accounts.*', \DB::Raw('SUM(`transactions`.`amount`) as `balance`')]);
+ }
+
+ /**
+ * Get all asset accounts. Optional JSON based parameters.
*
* @param array $parameters
*
* @return Collection
*/
- public function getRevenueAccounts(array $parameters = [])
+ public function getAssetAccounts()
{
- return $this->getAccountsByType(['Revenue account'], $parameters);
+ $list = $this->getAccountsByType(['Default account', 'Asset account']);
+ $list->each(
+ function (\Account $account) {
+ /** @var \AccountMeta $entry */
+ foreach ($account->accountmeta as $entry) {
+ if ($entry->name == 'accountRole') {
+ $account->accountRole = \Config::get('firefly.accountRoles.' . $entry->data);
+ }
+ }
+ if (!isset($account->accountRole)) {
+ $account->accountRole = 'Default expense account';
+ }
+ }
+ );
+
+ return $list;
+
}
/**
- * @param Ardent $model
- *
- * @return bool
+ * @return Collection
*/
- public function destroy(Ardent $model)
+ public function getExpenseAccounts()
{
- $model->delete();
- return true;
+ return $this->getAccountsByType(['Expense account', 'Beneficiary account']);
+ }
+ /**
+ * Get all revenue accounts.
+ *
+ * @return Collection
+ */
+ public function getRevenueAccounts()
+ {
+ return $this->getAccountsByType(['Revenue account']);
}
/**
@@ -254,27 +171,208 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface
*/
public function openingBalanceTransaction(\Account $account)
{
- return \TransactionJournal::withRelevantData()
- ->accountIs($account)
- ->leftJoin(
- 'transaction_types', 'transaction_types.id', '=',
- 'transaction_journals.transaction_type_id'
- )
- ->where('transaction_types.type', 'Opening balance')
- ->first(['transaction_journals.*']);
+ return \TransactionJournal::withRelevantData()->accountIs($account)->leftJoin(
+ 'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
+ )->where('transaction_types.type', 'Opening balance')->first(['transaction_journals.*']);
}
/**
- * Validates a model. Returns an array containing MessageBags
- * errors/warnings/successes.
+ * @param \Account $account
+ * @param array $data
*
- * @param Ardent $model
- *
- * @return array
+ * @return bool
*/
- public function validateObject(Ardent $model)
+ public function storeInitialBalance(\Account $account, array $data)
{
- die('No impl');
+ $opposingData = ['name' => $account->name . ' Initial Balance', 'active' => 0, 'what' => 'initial'];
+ $opposingAccount = $this->store($opposingData);
+
+ /*
+ * Create a journal from opposing to account or vice versa.
+ */
+ $balance = floatval($data['openingbalance']);
+ $date = new Carbon($data['openingbalancedate']);
+ /** @var \FireflyIII\Database\TransactionJournal $tj */
+ $tj = \App::make('FireflyIII\Database\TransactionJournal');
+ if ($balance < 0) {
+ // first transaction draws money from the new account to the opposing
+ $from = $account;
+ $to = $opposingAccount;
+ } else {
+ // first transaction puts money into account
+ $from = $opposingAccount;
+ $to = $account;
+ }
+
+ // data for transaction journal:
+ $balance = $balance < 0 ? $balance * -1 : $balance;
+ $opening = ['what' => 'opening', 'currency' => 'EUR', 'amount' => $balance, 'from' => $from, 'to' => $to, 'date' => $date,
+ 'description' => 'Opening balance for new account ' . $account->name,];
+
+
+ $validation = $tj->validate($opening);
+ if ($validation['errors']->count() == 0) {
+ $tj->store($opening);
+
+ return true;
+ } else {
+ var_dump($validation['errors']);
+ exit;
+ }
+
+ }
+
+ /**
+ * @param \Eloquent $model
+ *
+ * @return bool
+ */
+ public function destroy(\Eloquent $model)
+ {
+
+ // delete journals:
+ $journals = \TransactionJournal::whereIn(
+ 'id', function ($query) use ($model) {
+ $query->select('transaction_journal_id')
+ ->from('transactions')->whereIn(
+ 'account_id', function ($query) use ($model) {
+ $query
+ ->select('id')
+ ->from('accounts')
+ ->where(
+ function ($q) use ($model) {
+ $q->where('id', $model->id);
+ $q->orWhere(
+ function ($q) use ($model) {
+ $q->where('accounts.name', 'LIKE', '%' . $model->name . '%');
+ // TODO magic number!
+ $q->where('accounts.account_type_id', 3);
+ $q->where('accounts.active', 0);
+ }
+ );
+ }
+ )->where('accounts.user_id', $this->getUser()->id);
+ }
+ )->get();
+ }
+ )->delete();
+
+ /*
+ * Trigger deletion:
+ */
+ \Event::fire('account.destroy', [$model]);
+
+ // delete accounts:
+ \Account::where(
+ function ($q) use ($model) {
+ $q->where('id', $model->id);
+ $q->orWhere(
+ function ($q) use ($model) {
+ $q->where('accounts.name', 'LIKE', '%' . $model->name . '%');
+ // TODO magic number!
+ $q->where('accounts.account_type_id', 3);
+ $q->where('accounts.active', 0);
+ }
+ );
+ })->delete();
+
+ return true;
+
+ }
+
+ /**
+ * @param array $data
+ *
+ * @return \Eloquent
+ */
+ public function store(array $data)
+ {
+
+ /*
+ * Find account type.
+ */
+ /** @var \FireflyIII\Database\AccountType $acctType */
+ $acctType = \App::make('FireflyIII\Database\AccountType');
+
+ $accountType = $acctType->findByWhat($data['what']);
+
+ $data['user_id'] = $this->getUser()->id;
+ $data['account_type_id'] = $accountType->id;
+ $data['active'] = isset($data['active']) && $data['active'] === '1' ? 1 : 0;
+
+
+ $data = array_except($data, ['_token', 'what']);
+ $account = new \Account($data);
+ if (!$account->isValid()) {
+ var_dump($account->getErrors()->all());
+ exit;
+ }
+ $account->save();
+ if (isset($data['openingbalance']) && floatval($data['openingbalance']) != 0) {
+ $this->storeInitialBalance($account, $data);
+ }
+
+ // TODO this needs cleaning up and thinking over.
+ switch ($account->accountType->type) {
+ case 'Asset account':
+ case 'Default account':
+ $account->updateMeta('accountRole', $data['account_role']);
+ break;
+ }
+
+
+ /* Tell transaction journal to store a new one.*/
+ \Event::fire('account.store', [$account]);
+
+
+ return $account;
+
+ }
+
+ /**
+ * @param \Eloquent $model
+ * @param array $data
+ *
+ * @return bool
+ */
+ public function update(\Eloquent $model, array $data)
+ {
+ $model->name = $data['name'];
+ $model->active = isset($data['active']) ? intval($data['active']) : 0;
+
+ // TODO this needs cleaning up and thinking over.
+ switch ($model->accountType->type) {
+ case 'Asset account':
+ case 'Default account':
+ $model->updateMeta('accountRole', $data['account_role']);
+ break;
+ }
+
+ $model->save();
+
+ if (isset($data['openingbalance']) && isset($data['openingbalancedate']) && strlen($data['openingbalancedate']) > 0) {
+ $openingBalance = $this->openingBalanceTransaction($model);
+ // TODO this needs cleaning up and thinking over.
+ if (is_null($openingBalance)) {
+ $this->storeInitialBalance($model, $data);
+ } else {
+ $openingBalance->date = new Carbon($data['openingbalancedate']);
+ $openingBalance->save();
+ $amount = floatval($data['openingbalance']);
+ /** @var \Transaction $transaction */
+ foreach ($openingBalance->transactions as $transaction) {
+ if ($transaction->account_id == $model->id) {
+ $transaction->amount = $amount;
+ } else {
+ $transaction->amount = $amount * -1;
+ }
+ $transaction->save();
+ }
+ }
+ }
+ \Event::fire('account.update', [$model]);
+
+ return true;
}
/**
@@ -309,6 +407,12 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface
$errors->merge($errors);
}
+ if (isset($model['account_role']) && !in_array($model['account_role'], array_keys(\Config::get('firefly.accountRoles')))) {
+ $errors->add('account_role', 'Invalid account role');
+ } else {
+ $successes->add('account_role', 'OK');
+ }
+
/*
* type validation.
*/
@@ -342,107 +446,20 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface
if (!$errors->has('openingbalancedate')) {
$successes->add('openingbalancedate', 'OK');
}
- return [
- 'errors' => $errors,
- 'warnings' => $warnings,
- 'successes' => $successes
- ];
+
+ return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
}
/**
- * @param array $data
+ * Returns an object with id $id.
*
- * @return Ardent
- */
- public function store(array $data)
- {
-
- /*
- * Find account type.
- */
- /** @var \FireflyIII\Database\AccountType $acctType */
- $acctType = \App::make('FireflyIII\Database\AccountType');
-
- $accountType = $acctType->findByWhat($data['what']);
-
- $data['user_id'] = $this->getUser()->id;
- $data['account_type_id'] = $accountType->id;
- $data['active'] = isset($data['active']) && $data['active'] === '1' ? 1 : 0;
-
-
- $data = array_except($data, array('_token', 'what'));
- $account = new \Account($data);
- if (!$account->validate()) {
- var_dump($account->errors()->all());
- exit;
- }
- $account->save();
- if (isset($data['openingbalance']) && floatval($data['openingbalance']) != 0) {
- $this->storeInitialBalance($account, $data);
- }
-
-
- /* Tell transaction journal to store a new one.*/
-
-
- return $account;
-
- }
-
- /**
- * @param \Account $account
- * @param array $data
+ * @param int $id
*
- * @return bool
+ * @return \Eloquent
*/
- public function storeInitialBalance(\Account $account, array $data)
+ public function find($id)
{
- $opposingData = [
- 'name' => $account->name . ' Initial Balance',
- 'active' => 0,
- 'what' => 'initial'
- ];
- $opposingAccount = $this->store($opposingData);
-
- /*
- * Create a journal from opposing to account or vice versa.
- */
- $balance = floatval($data['openingbalance']);
- $date = new Carbon($data['openingbalancedate']);
- /** @var \FireflyIII\Database\TransactionJournal $tj */
- $tj = \App::make('FireflyIII\Database\TransactionJournal');
- if ($balance < 0) {
- // first transaction draws money from the new account to the opposing
- $from = $account;
- $to = $opposingAccount;
- } else {
- // first transaction puts money into account
- $from = $opposingAccount;
- $to = $account;
- }
-
- // data for transaction journal:
- $balance = $balance < 0 ? $balance * -1 : $balance;
- $opening = [
- 'what' => 'opening',
- 'currency' => 'EUR',
- 'amount' => $balance,
- 'from' => $from,
- 'to' => $to,
- 'date' => $date,
- 'description' => 'Opening balance for new account ' . $account->name,
- ];
-
-
- $validation = $tj->validate($opening);
- if ($validation['errors']->count() == 0) {
- $tj->store($opening);
- return true;
- } else {
- var_dump($validation['errors']);
- exit;
- }
- return false;
+ return $this->getUser()->accounts()->find($id);
}
/**
@@ -455,6 +472,18 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface
public function findByWhat($what)
{
// TODO: Implement findByWhat() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * Returns all objects.
+ *
+ * @return Collection
+ */
+ public function get()
+ {
+ // TODO: Implement get() method.
+ throw new NotImplementedException;
}
/**
@@ -466,4 +495,103 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface
{
return $this->getUser()->accounts()->whereIn('id', $ids)->get();
}
+
+ public function firstExpenseAccountOrCreate($name)
+ {
+ /** @var \FireflyIII\Database\AccountType $accountTypeRepos */
+ $accountTypeRepos = \App::make('FireflyIII\Database\AccountType');
+
+ $accountType = $accountTypeRepos->findByWhat('expense');
+
+ // if name is "", find cash account:
+ if (strlen($name) == 0) {
+ $cashAccountType = $accountTypeRepos->findByWhat('cash');
+
+ // find or create cash account:
+ return \Account::firstOrCreate(
+ ['name' => 'Cash account', 'account_type_id' => $cashAccountType->id, 'active' => 1, 'user_id' => $this->getUser()->id,]
+ );
+ }
+
+ $data = ['user_id' => $this->getUser()->id, 'account_type_id' => $accountType->id, 'name' => $name, 'active' => 1];
+
+ return \Account::firstOrCreate($data);
+
+ }
+
+ public function firstRevenueAccountOrCreate($name)
+ {
+ /** @var \FireflyIII\Database\AccountType $accountTypeRepos */
+ $accountTypeRepos = \App::make('FireflyIII\Database\AccountType');
+
+ $accountType = $accountTypeRepos->findByWhat('revenue');
+
+ $data = ['user_id' => $this->getUser()->id, 'account_type_id' => $accountType->id, 'name' => $name, 'active' => 1];
+
+ return \Account::firstOrCreate($data);
+
+ }
+
+ public function getAllTransactionJournals(\Account $account, $limit = 50)
+ {
+ $offset = intval(\Input::get('page')) > 0 ? intval(\Input::get('page')) * $limit : 0;
+ $set = $this->getUser()->transactionJournals()->withRelevantData()->leftJoin(
+ 'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
+ )->where('transactions.account_id', $account->id)->take($limit)->offset($offset)->orderBy('date', 'DESC')->get(
+ ['transaction_journals.*']
+ );
+ $count = $this->getUser()->transactionJournals()->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
+ ->orderBy('date', 'DESC')->where('transactions.account_id', $account->id)->count();
+ $items = [];
+ foreach ($set as $entry) {
+ $items[] = $entry;
+ }
+
+ return \Paginator::make($items, $count, $limit);
+
+
+ }
+
+ public function getTransactionJournals(\Account $account, $limit = 50)
+ {
+ $start = \Session::get('start');
+ $end = \Session::get('end');
+ $offset = intval(\Input::get('page')) > 0 ? intval(\Input::get('page')) * $limit : 0;
+ $set = $this->getUser()->transactionJournals()->withRelevantData()->leftJoin(
+ 'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
+ )->where('transactions.account_id', $account->id)->take($limit)->offset($offset)->before($end)->after($start)->orderBy('date', 'DESC')->get(
+ ['transaction_journals.*']
+ );
+ $count = $this->getUser()->transactionJournals()->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
+ ->before($end)->after($start)->orderBy('date', 'DESC')->where('transactions.account_id', $account->id)->count();
+ $items = [];
+ foreach ($set as $entry) {
+ $items[] = $entry;
+ }
+
+ return \Paginator::make($items, $count, $limit);
+
+
+ }
+
+ /**
+ * @param \Account $account
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return \Illuminate\Pagination\Paginator
+ */
+ public function getTransactionJournalsInRange(\Account $account, Carbon $start, Carbon $end)
+ {
+ $set = $this->getUser()->transactionJournals()->transactionTypes(['Withdrawal'])->withRelevantData()->leftJoin(
+ 'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
+ )->where('transactions.account_id', $account->id)->before($end)->after($start)->orderBy('date', 'DESC')->get(
+ ['transaction_journals.*']
+ );
+
+ return $set;
+
+ }
+
+
}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/AccountType.php b/app/lib/FireflyIII/Database/AccountType.php
index 8a4e13f1dc..6a7131d2b1 100644
--- a/app/lib/FireflyIII/Database/AccountType.php
+++ b/app/lib/FireflyIII/Database/AccountType.php
@@ -2,21 +2,82 @@
namespace FireflyIII\Database;
-use Firefly\Exception\FireflyException;
-use Illuminate\Support\Collection;
-use LaravelBook\Ardent\Ardent;
+use FireflyIII\Exception\FireflyException;
use FireflyIII\Database\Ifaces\AccountTypeInterface;
use FireflyIII\Database\Ifaces\CommonDatabaseCalls;
use FireflyIII\Database\Ifaces\CUD;
+use FireflyIII\Exception\NotImplementedException;
+use Illuminate\Support\Collection;
/**
* Class AccountType
*
* @package FireflyIII\Database
*/
-class AccountType implements AccountTypeInterface, CUD, CommonDatabaseCalls
+class AccountType implements CUD, CommonDatabaseCalls
{
+ /**
+ * @param \Eloquent $model
+ *
+ * @return bool
+ */
+ public function destroy(\Eloquent $model)
+ {
+ // TODO: Implement destroy() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * @param array $data
+ *
+ * @return \Eloquent
+ */
+ public function store(array $data)
+ {
+ // TODO: Implement store() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * @param \Eloquent $model
+ * @param array $data
+ *
+ * @return bool
+ */
+ public function update(\Eloquent $model, array $data)
+ {
+ // TODO: Implement update() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * Validates an array. Returns an array containing MessageBags
+ * errors/warnings/successes.
+ *
+ * @param array $model
+ *
+ * @return array
+ */
+ public function validate(array $model)
+ {
+ // TODO: Implement validate() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * Returns an object with id $id.
+ *
+ * @param int $id
+ *
+ * @return \Eloquent
+ */
+ public function find($id)
+ {
+ // TODO: Implement find() method.
+ throw new NotImplementedException;
+ }
+
/**
* Finds an account type using one of the "$what"'s: expense, asset, revenue
*
@@ -37,6 +98,9 @@ class AccountType implements AccountTypeInterface, CUD, CommonDatabaseCalls
case 'revenue':
return \AccountType::whereType('Revenue account')->first();
break;
+ case 'cash':
+ return \AccountType::whereType('Cash account')->first();
+ break;
case 'initial':
return \AccountType::whereType('Initial balance account')->first();
break;
@@ -45,65 +109,6 @@ class AccountType implements AccountTypeInterface, CUD, CommonDatabaseCalls
break;
}
- return null;
- }
-
- /**
- * @param Ardent $model
- *
- * @return bool
- */
- public function destroy(Ardent $model)
- {
- // TODO: Implement destroy() method.
- }
-
- /**
- * Validates a model. Returns an array containing MessageBags
- * errors/warnings/successes.
- *
- * @param Ardent $model
- *
- * @return array
- */
- public function validateObject(Ardent $model)
- {
- // TODO: Implement validateObject() method.
- }
-
- /**
- * Validates an array. Returns an array containing MessageBags
- * errors/warnings/successes.
- *
- * @param array $model
- *
- * @return array
- */
- public function validate(array $model)
- {
- // TODO: Implement validate() method.
- }
-
- /**
- * @param array $data
- *
- * @return Ardent
- */
- public function store(array $data)
- {
- // TODO: Implement store() method.
- }
-
- /**
- * Returns an object with id $id.
- *
- * @param int $id
- *
- * @return Ardent
- */
- public function find($id)
- {
- // TODO: Implement find() method.
}
/**
@@ -114,6 +119,7 @@ class AccountType implements AccountTypeInterface, CUD, CommonDatabaseCalls
public function get()
{
// TODO: Implement get() method.
+ throw new NotImplementedException;
}
/**
@@ -124,16 +130,6 @@ class AccountType implements AccountTypeInterface, CUD, CommonDatabaseCalls
public function getByIds(array $ids)
{
// TODO: Implement getByIds() method.
- }
-
- /**
- * @param Ardent $model
- * @param array $data
- *
- * @return bool
- */
- public function update(Ardent $model, array $data)
- {
- // TODO: Implement update() method.
+ throw new NotImplementedException;
}
}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/Budget.php b/app/lib/FireflyIII/Database/Budget.php
index ba8d22fcf4..f9563d8066 100644
--- a/app/lib/FireflyIII/Database/Budget.php
+++ b/app/lib/FireflyIII/Database/Budget.php
@@ -2,13 +2,13 @@
namespace FireflyIII\Database;
use Carbon\Carbon;
-use FireflyIII\Exception\NotImplementedException;
-use Illuminate\Support\MessageBag;
-use LaravelBook\Ardent\Ardent;
-use Illuminate\Support\Collection;
+use FireflyIII\Database\Ifaces\BudgetInterface;
use FireflyIII\Database\Ifaces\CommonDatabaseCalls;
use FireflyIII\Database\Ifaces\CUD;
-use FireflyIII\Database\Ifaces\BudgetInterface;
+use FireflyIII\Exception\NotImplementedException;
+use Illuminate\Support\Collection;
+use Illuminate\Support\MessageBag;
+
/**
* Class Budget
*
@@ -26,6 +26,178 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface
$this->setUser(\Auth::user());
}
+ /**
+ * @param \Eloquent $model
+ *
+ * @return bool
+ */
+ public function destroy(\Eloquent $model)
+ {
+ $model->delete();
+
+ return true;
+ }
+
+ /**
+ * @param array $data
+ *
+ * @return \Eloquent
+ */
+ public function store(array $data)
+ {
+ $data['user_id'] = $this->getUser()->id;
+
+ $budget = new \Budget($data);
+ $budget->class = 'Budget';
+
+ if (!$budget->isValid()) {
+ var_dump($budget->getErrors()->all());
+ exit;
+ }
+ $budget->save();
+
+ return $budget;
+ }
+
+ /**
+ * @param \Eloquent $model
+ * @param array $data
+ *
+ * @return bool
+ */
+ public function update(\Eloquent $model, array $data)
+ {
+ $model->name = $data['name'];
+ if (!$model->isValid()) {
+ var_dump($model->getErrors()->all());
+ exit;
+ }
+
+
+ $model->save();
+
+ return true;
+ }
+
+ /**
+ * Validates an array. Returns an array containing MessageBags
+ * errors/warnings/successes.
+ *
+ * @param array $model
+ *
+ * @return array
+ */
+ public function validate(array $model)
+ {
+ $warnings = new MessageBag;
+ $successes = new MessageBag;
+ $errors = new MessageBag;
+
+ if (isset($model['name'])) {
+ if (strlen($model['name']) < 1) {
+ $errors->add('name', 'Name is too short');
+ }
+ if (strlen($model['name']) > 200) {
+ $errors->add('name', 'Name is too long');
+
+ }
+ } else {
+ $errors->add('name', 'Name is mandatory');
+ }
+ $validator = \Validator::make($model, \Component::$rules);
+
+ if ($validator->invalid()) {
+ $errors->merge($validator->errors());
+ }
+
+
+ if (!$errors->has('name')) {
+ $successes->add('name', 'OK');
+ }
+
+ return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
+ }
+
+ /**
+ * Returns an object with id $id.
+ *
+ * @param int $id
+ *
+ * @return \Eloquent
+ */
+ public function find($id)
+ {
+ return $this->getUser()->budgets()->find($id);
+ }
+
+ /**
+ * Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc.
+ *
+ * @param $what
+ *
+ * @return \AccountType|null
+ */
+ public function findByWhat($what)
+ {
+ // TODO: Implement findByWhat() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * Returns all objects.
+ *
+ * @return Collection
+ */
+ public function get()
+ {
+ $budgets = $this->getUser()->budgets()->get();
+
+ return $budgets;
+ }
+
+ /**
+ * @param array $ids
+ *
+ * @return Collection
+ */
+ public function getByIds(array $ids)
+ {
+ // TODO: Implement getByIds() method.
+ throw new NotImplementedException;
+ }
+
+ public function getTransactionJournals(\Budget $budget, $limit = 50)
+ {
+ $offset = intval(\Input::get('page')) > 0 ? intval(\Input::get('page')) * $limit : 0;
+ $set = $budget->transactionJournals()->withRelevantData()->take($limit)->offset($offset)->orderBy('date', 'DESC')->get(['transaction_journals.*']);
+ $count = $budget->transactionJournals()->count();
+ $items = [];
+ foreach ($set as $entry) {
+ $items[] = $entry;
+ }
+
+ return \Paginator::make($items, $count, $limit);
+
+ }
+
+ public function getTransactionJournalsInRepetition(\Budget $budget, \LimitRepetition $repetition, $limit = 50)
+ {
+ $start = $repetition->startdate;
+ $end = $repetition->enddate;
+
+ $offset = intval(\Input::get('page')) > 0 ? intval(\Input::get('page')) * $limit : 0;
+ $set = $budget->transactionJournals()->withRelevantData()->before($end)->after($start)->take($limit)->offset($offset)->orderBy('date', 'DESC')->get(
+ ['transaction_journals.*']
+ );
+ $count = $budget->transactionJournals()->before($end)->after($start)->count();
+ $items = [];
+ foreach ($set as $entry) {
+ $items[] = $entry;
+ }
+
+ return \Paginator::make($items, $count, $limit);
+ }
+
/**
* @param \Budget $budget
* @param Carbon $date
@@ -42,152 +214,6 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface
)->first(['limit_repetitions.*']);
}
- /**
- * @param Ardent $model
- *
- * @return bool
- */
- public function destroy(Ardent $model)
- {
- $model->delete();
- return true;
- }
-
- /**
- * Validates a model. Returns an array containing MessageBags
- * errors/warnings/successes.
- *
- * @param Ardent $model
- *
- * @return array
- */
- public function validateObject(Ardent $model)
- {
- // TODO: Implement validateObject() method.
- }
-
- /**
- * Validates an array. Returns an array containing MessageBags
- * errors/warnings/successes.
- *
- * @param array $model
- *
- * @return array
- */
- public function validate(array $model)
- {
- $warnings = new MessageBag;
- $successes = new MessageBag;
- $errors = new MessageBag;
-
- if(isset($model['name'])) {
- if(strlen($model['name']) < 1) {
- $errors->add('name', 'Name is too short');
- }
- if(strlen($model['name']) > 200) {
- $errors->add('name', 'Name is too long');
-
- }
- } else {
- $errors->add('name', 'Name is mandatory');
- }
- $validator = \Validator::make($model, \Component::$rules);
-
- if ($validator->invalid()) {
- $errors->merge($validator->errors());
- }
-
-
- if(!$errors->has('name')) {
- $successes->add('name','OK');
- }
-
- return [
- 'errors' => $errors,
- 'warnings' => $warnings,
- 'successes' => $successes
- ];
- }
-
- /**
- * @param array $data
- *
- * @return Ardent
- */
- public function store(array $data)
- {
- $data['user_id'] = $this->getUser()->id;
-
- $budget = new \Budget($data);
- $budget->class = 'Budget';
-
- if (!$budget->validate()) {
- var_dump($budget->errors()->all());
- exit;
- }
- $budget->save();
- return $budget;
- }
-
- /**
- * Returns an object with id $id.
- *
- * @param int $id
- *
- * @return Ardent
- */
- public function find($id)
- {
- // TODO: Implement find() method.
- }
-
- /**
- * Returns all objects.
- *
- * @return Collection
- */
- public function get()
- {
- $budgets = $this->getUser()->budgets()->get();
-
- return $budgets;
- }
-
- /**
- * @param \Budget $budget
- * @param Carbon $date
- * @return float
- */
- public function spentInMonth(\Budget $budget, Carbon $date) {
- $end = clone $date;
- $date->startOfMonth();
- $end->endOfMonth();
- $sum = floatval($budget->transactionjournals()->before($end)->after($date)->lessThan(0)->sum('amount')) * -1;
- return $sum;
- }
-
- /**
- * @param array $ids
- *
- * @return Collection
- */
- public function getByIds(array $ids)
- {
- // TODO: Implement getByIds() method.
- }
-
- /**
- * Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc.
- *
- * @param $what
- *
- * @return \AccountType|null
- */
- public function findByWhat($what)
- {
- // TODO: Implement findByWhat() method.
- }
-
/**
* @param Carbon $start
* @param Carbon $end
@@ -197,38 +223,44 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface
public function transactionsWithoutBudgetInDateRange(Carbon $start, Carbon $end)
{
// Add expenses that have no budget:
- return \Auth::user()->transactionjournals()->whereNotIn(
+ return $this->getUser()->transactionjournals()->whereNotIn(
'transaction_journals.id', function ($query) use ($start, $end) {
- $query->select('transaction_journals.id')->from('transaction_journals')
- ->leftJoin(
- 'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
- 'transaction_journals.id'
- )
- ->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id')
- ->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
- ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
- ->where('components.class', 'Budget');
+ $query->select('transaction_journals.id')->from('transaction_journals')->leftJoin(
+ 'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
+ )->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id')->where(
+ 'transaction_journals.date', '>=', $start->format('Y-m-d')
+ )->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->where('components.class', 'Budget');
}
)->before($end)->after($start)->lessThan(0)->transactionTypes(['Withdrawal'])->get();
}
/**
- * @param Ardent $model
- * @param array $data
+ * @param \Budget $budget
+ * @param Carbon $date
*
- * @return bool
+ * @return float
*/
- public function update(Ardent $model, array $data)
+ public function spentInMonth(\Budget $budget, Carbon $date)
{
- $model->name = $data['name'];
- if (!$model->validate()) {
- var_dump($model->errors()->all());
- exit;
- }
+ $end = clone $date;
+ $date->startOfMonth();
+ $end->endOfMonth();
+ $sum = floatval($budget->transactionjournals()->before($end)->after($date)->lessThan(0)->sum('amount')) * -1;
+ return $sum;
+ }
- $model->save();
+ /**
+ * @param \Budget $budget
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return float
+ */
+ public function spentInPeriod(\Budget $budget, Carbon $start, Carbon $end)
+ {
+ $sum = floatval($budget->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1;
- return true;
+ return $sum;
}
}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/Category.php b/app/lib/FireflyIII/Database/Category.php
index 47349ac021..649dfc47ea 100644
--- a/app/lib/FireflyIII/Database/Category.php
+++ b/app/lib/FireflyIII/Database/Category.php
@@ -2,19 +2,20 @@
namespace FireflyIII\Database;
use Carbon\Carbon;
-use Illuminate\Support\MessageBag;
-use LaravelBook\Ardent\Ardent;
-use Illuminate\Support\Collection;
+use FireflyIII\Database\Ifaces\CategoryInterface;
use FireflyIII\Database\Ifaces\CommonDatabaseCalls;
use FireflyIII\Database\Ifaces\CUD;
-use FireflyIII\Database\Ifaces\CategoryInterface;
+use FireflyIII\Exception\NotImplementedException;
+use Illuminate\Support\Collection;
+use Illuminate\Support\MessageBag;
+
/**
* Class Category
*
* @package FireflyIII\Database
*/
-class Category implements CUD, CommonDatabaseCalls, CategoryInterface
+class Category implements CUD, CommonDatabaseCalls
{
use SwitchUser;
@@ -27,26 +28,55 @@ class Category implements CUD, CommonDatabaseCalls, CategoryInterface
}
/**
- * @param Ardent $model
+ * @param \Eloquent $model
*
* @return bool
*/
- public function destroy(Ardent $model)
+ public function destroy(\Eloquent $model)
{
- // TODO: Implement destroy() method.
+ $model->delete();
+
+ return true;
}
/**
- * Validates a model. Returns an array containing MessageBags
- * errors/warnings/successes.
+ * @param array $data
*
- * @param Ardent $model
- *
- * @return array
+ * @return \Eloquent
*/
- public function validateObject(Ardent $model)
+ public function store(array $data)
{
- // TODO: Implement validateObject() method.
+ $category = new \Category;
+ $category->name = $data['name'];
+ $category->class = 'Category';
+ $category->user()->associate($this->getUser());
+ if (!$category->isValid()) {
+ var_dump($category->getErrors());
+ exit();
+ }
+ $category->save();
+
+ return $category;
+ }
+
+ /**
+ * @param \Eloquent $model
+ * @param array $data
+ *
+ * @return bool
+ */
+ public function update(\Eloquent $model, array $data)
+ {
+ $model->name = $data['name'];
+ if (!$model->isValid()) {
+ var_dump($model->getErrors()->all());
+ exit;
+ }
+
+
+ $model->save();
+
+ return true;
}
/**
@@ -59,17 +89,33 @@ class Category implements CUD, CommonDatabaseCalls, CategoryInterface
*/
public function validate(array $model)
{
- // TODO: Implement validate() method.
- }
+ $warnings = new MessageBag;
+ $successes = new MessageBag;
+ $errors = new MessageBag;
- /**
- * @param array $data
- *
- * @return Ardent
- */
- public function store(array $data)
- {
- // TODO: Implement store() method.
+ if (isset($model['name'])) {
+ if (strlen($model['name']) < 1) {
+ $errors->add('name', 'Name is too short');
+ }
+ if (strlen($model['name']) > 200) {
+ $errors->add('name', 'Name is too long');
+
+ }
+ } else {
+ $errors->add('name', 'Name is mandatory');
+ }
+ $validator = \Validator::make($model, \Component::$rules);
+
+ if ($validator->invalid()) {
+ $errors->merge($validator->getErrors());
+ }
+
+
+ if (!$errors->has('name')) {
+ $successes->add('name', 'OK');
+ }
+
+ return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
}
/**
@@ -77,31 +123,12 @@ class Category implements CUD, CommonDatabaseCalls, CategoryInterface
*
* @param int $id
*
- * @return Ardent
+ * @return \Eloquent
*/
public function find($id)
{
// TODO: Implement find() method.
- }
-
- /**
- * Returns all objects.
- *
- * @return Collection
- */
- public function get()
- {
- // TODO: Implement get() method.
- }
-
- /**
- * @param array $ids
- *
- * @return Collection
- */
- public function getByIds(array $ids)
- {
- // TODO: Implement getByIds() method.
+ throw new NotImplementedException;
}
/**
@@ -114,16 +141,73 @@ class Category implements CUD, CommonDatabaseCalls, CategoryInterface
public function findByWhat($what)
{
// TODO: Implement findByWhat() method.
+ throw new NotImplementedException;
}
/**
- * @param Ardent $model
- * @param array $data
+ * Returns all objects.
*
- * @return bool
+ * @return Collection
*/
- public function update(Ardent $model, array $data)
+ public function get()
{
- // TODO: Implement update() method.
+ return $this->getUser()->categories()->orderBy('name', 'ASC')->get();
+ }
+
+ /**
+ * @param array $ids
+ *
+ * @return Collection
+ */
+ public function getByIds(array $ids)
+ {
+ // TODO: Implement getByIds() method.
+ throw new NotImplementedException;
+ }
+
+ public function firstOrCreate($name)
+ {
+ return \Category::firstOrCreate(['user_id' => $this->getUser()->id, 'name' => $name]);
+ }
+
+ public function getTransactionJournals(\Category $category, $limit = 50)
+ {
+ $offset = intval(\Input::get('page')) > 0 ? intval(\Input::get('page')) * $limit : 0;
+ $set = $category->transactionJournals()->withRelevantData()->take($limit)->offset($offset)->orderBy('date', 'DESC')->get(['transaction_journals.*']);
+ $count = $category->transactionJournals()->count();
+ $items = [];
+ foreach ($set as $entry) {
+ $items[] = $entry;
+ }
+
+ return \Paginator::make($items, $count, $limit);
+
+ }
+
+ /**
+ * @param \Category $budget
+ * @param Carbon $date
+ *
+ * @return null
+ */
+ public function repetitionOnStartingOnDate(\Category $category, Carbon $date)
+ {
+ return null;
+ }
+
+ /**
+ * @param \Category $category
+ * @param Carbon $date
+ *
+ * @return float
+ */
+ public function spentInMonth(\Category $category, Carbon $date)
+ {
+ $end = clone $date;
+ $date->startOfMonth();
+ $end->endOfMonth();
+ $sum = floatval($category->transactionjournals()->before($end)->after($date)->lessThan(0)->sum('amount')) * -1;
+
+ return $sum;
}
}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/Ifaces/AccountInterface.php b/app/lib/FireflyIII/Database/Ifaces/AccountInterface.php
index a24fa07421..614c476556 100644
--- a/app/lib/FireflyIII/Database/Ifaces/AccountInterface.php
+++ b/app/lib/FireflyIII/Database/Ifaces/AccountInterface.php
@@ -13,13 +13,13 @@ interface AccountInterface
{
/**
- * Get all asset accounts. The parameters are optional and are provided by the DataTables plugin.
+ * Counts the number of accounts found with the included types.
*
- * @param array $parameters
+ * @param array $types
*
- * @return Collection
+ * @return int
*/
- public function getAssetAccounts(array $parameters = []);
+ public function countAccountsByType(array $types);
/**
* Counts the number of total asset accounts. Useful for DataTables.
@@ -42,12 +42,6 @@ interface AccountInterface
*/
public function countRevenueAccounts();
- /**
- * @param array $parameters
- *
- * @return Collection
- */
-
/**
* @param \Account $account
*
@@ -55,42 +49,33 @@ interface AccountInterface
*/
public function findInitialBalanceAccount(\Account $account);
- public function getExpenseAccounts(array $parameters = []);
-
- /**
- * Get all revenue accounts.
- *
- * @param array $parameters
- *
- * @return Collection
- */
- public function getRevenueAccounts(array $parameters = []);
-
/**
* Get all accounts of the selected types. Is also capable of handling DataTables' parameters.
*
* @param array $types
- * @param array $parameters
*
* @return Collection
*/
- public function getAccountsByType(array $types, array $parameters = []);
+ public function getAccountsByType(array $types);
/**
- * Counts the number of accounts found with the included types.
- *
- * @param array $types
- *
- * @return int
- */
- public function countAccountsByType(array $types);
-
- /**
- * Get all default accounts.
+ * Get all asset accounts. The parameters are optional and are provided by the DataTables plugin.
*
* @return Collection
*/
- public function getDefaultAccounts();
+ public function getAssetAccounts();
+
+ /**
+ * @return Collection
+ */
+ public function getExpenseAccounts();
+
+ /**
+ * Get all revenue accounts.
+ *
+ * @return Collection
+ */
+ public function getRevenueAccounts();
/**
* @param \Account $account
@@ -101,7 +86,7 @@ interface AccountInterface
/**
* @param \Account $account
- * @param array $data
+ * @param array $data
*
* @return bool
*/
diff --git a/app/lib/FireflyIII/Database/Ifaces/AccountTypeInterface.php b/app/lib/FireflyIII/Database/Ifaces/AccountTypeInterface.php
deleted file mode 100644
index d06621d702..0000000000
--- a/app/lib/FireflyIII/Database/Ifaces/AccountTypeInterface.php
+++ /dev/null
@@ -1,13 +0,0 @@
-balance();
- /** @var \Piggybank $p */
- foreach ($account->piggybanks()->get() as $p) {
- $balance -= $p->currentRelevantRep()->currentamount;
- }
-
- return $balance;
-
- }
-
/**
*
*/
@@ -45,26 +29,75 @@ class Piggybank implements CUD, CommonDatabaseCalls, PiggybankInterface
}
/**
- * @param Ardent $model
+ * @param \Eloquent $model
*
* @return bool
*/
- public function destroy(Ardent $model)
+ public function destroy(\Eloquent $model)
{
$model->delete();
}
/**
- * Validates a model. Returns an array containing MessageBags
- * errors/warnings/successes.
+ * @param array $data
*
- * @param Ardent $model
- *
- * @return array
+ * @return \Eloquent
*/
- public function validateObject(Ardent $model)
+ public function store(array $data)
{
- // TODO: Implement validateObject() method.
+ $data['rep_every'] = isset($data['rep_every']) ? $data['rep_every'] : 0;
+ $data['reminder_skip'] = isset($data['reminder_skip']) ? $data['reminder_skip'] : 0;
+ $data['order'] = isset($data['order']) ? $data['order'] : 0;
+ $data['remind_me'] = isset($data['remind_me']) ? intval($data['remind_me']) : 0;
+ $data['startdate'] = isset($data['startdate']) ? $data['startdate'] : Carbon::now()->format('Y-m-d');
+ $data['targetdate'] = isset($data['targetdate']) && $data['targetdate'] != '' ? $data['targetdate'] : null;
+
+ if ($data['remind_me'] == 0) {
+ $data['reminder'] = null;
+ }
+
+
+ $piggybank = new \Piggybank($data);
+ if (!$piggybank->isValid()) {
+ var_dump($piggybank->getErrors()->all());
+ exit;
+ }
+ $piggybank->save();
+
+ return $piggybank;
+ }
+
+ /**
+ * @param \Eloquent $model
+ * @param array $data
+ *
+ * @return bool
+ */
+ public function update(\Eloquent $model, array $data)
+ {
+ /** @var \Piggybank $model */
+ $model->name = $data['name'];
+ $model->account_id = intval($data['account_id']);
+ $model->targetamount = floatval($data['targetamount']);
+ $model->targetdate = isset($data['targetdate']) && $data['targetdate'] != '' ? $data['targetdate'] : null;
+ $model->rep_every = isset($data['rep_every']) ? $data['rep_every'] : 0;
+ $model->reminder_skip = isset($data['reminder_skip']) ? $data['reminder_skip'] : 0;
+ $model->order = isset($data['order']) ? $data['order'] : 0;
+ $model->remind_me = isset($data['remind_me']) ? intval($data['remind_me']) : 0;
+ $model->reminder = isset($data['reminder']) ? $data['reminder'] : 'month';
+
+ if ($model->remind_me == 0) {
+ $model->reminder = null;
+ }
+
+ if (!$model->isValid()) {
+ var_dump($model->getErrors());
+ exit();
+ }
+
+ $model->save();
+
+ return true;
}
/**
@@ -105,7 +138,7 @@ class Piggybank implements CUD, CommonDatabaseCalls, PiggybankInterface
try {
new Carbon($model['targetdate']);
} catch (\Exception $e) {
- $errors->add('date', 'Invalid date.');
+ $errors->add('targetdate', 'Invalid date.');
}
}
if (floatval($model['targetamount']) < 0.01) {
@@ -147,36 +180,7 @@ class Piggybank implements CUD, CommonDatabaseCalls, PiggybankInterface
}
}
- return [
- 'errors' => $errors,
- 'warnings' => $warnings,
- 'successes' => $successes
- ];
- }
-
- /**
- * @param array $data
- *
- * @return Ardent
- */
- public function store(array $data)
- {
- $data['rep_every'] = isset($data['rep_every']) ? $data['rep_every'] : 0;
- $data['reminder_skip'] = isset($data['reminder_skip']) ? $data['reminder_skip'] : 0;
- $data['order'] = isset($data['order']) ? $data['order'] : 0;
- $data['remind_me'] = isset($data['remind_me']) ? intval($data['remind_me']) : 0;
- $data['startdate'] = isset($data['startdate']) ? $data['startdate'] : Carbon::now()->format('Y-m-d');
- $data['targetdate'] = isset($data['targetdate']) && $data['targetdate'] != '' ? $data['targetdate'] : null;
-
-
- $piggybank = new \Piggybank($data);
- if (!$piggybank->validate()) {
- var_dump($piggybank->errors()->all());
- exit;
- }
- $piggybank->save();
- \Event::fire('piggybanks.store', [$piggybank]);
- $piggybank->save();
+ return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
}
/**
@@ -184,11 +188,26 @@ class Piggybank implements CUD, CommonDatabaseCalls, PiggybankInterface
*
* @param int $id
*
- * @return Ardent
+ * @return \Eloquent
*/
public function find($id)
{
- // TODO: Implement find() method.
+ return \Piggybank::
+ leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where('piggybanks.id', '=', $id)->where('accounts.user_id', $this->getUser()->id)
+ ->first(['piggybanks.*']);
+ }
+
+ /**
+ * Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc.
+ *
+ * @param $what
+ *
+ * @return \AccountType|null
+ */
+ public function findByWhat($what)
+ {
+ // TODO: Implement findByWhat() method.
+ throw new NotImplementedException;
}
/**
@@ -209,42 +228,35 @@ class Piggybank implements CUD, CommonDatabaseCalls, PiggybankInterface
public function getByIds(array $ids)
{
// TODO: Implement getByIds() method.
+ throw new NotImplementedException;
}
- /**
- * Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc.
- *
- * @param $what
- *
- * @return \AccountType|null
- */
- public function findByWhat($what)
+ public function findRepetitionByDate(\Piggybank $piggybank, Carbon $date)
{
- // TODO: Implement findByWhat() method.
- }
-
- /**
- * @param Ardent $model
- * @param array $data
- *
- * @return bool
- */
- public function update(Ardent $model, array $data)
- {
- /** @var \Piggybank $model */
- $model->name = $data['name'];
- $model->account_id = intval($data['account_id']);
- $model->targetamount = floatval($data['targetamount']);
- $model->targetdate = isset($data['targetdate']) && $data['targetdate'] != '' ? $data['targetdate'] : null;
- $model->rep_every = isset($data['rep_every']) ? $data['rep_every'] : 0;
- $model->reminder_skip = isset($data['reminder_skip']) ? $data['reminder_skip'] : 0;
- $model->order = isset($data['order']) ? $data['order'] : 0;
- $model->remind_me = isset($data['remind_me']) ? intval($data['remind_me']) : 0;
- if(!$model->validate()) {
- var_dump($model->errors());
- exit();
+ $reps = $piggybank->piggybankrepetitions()->get();
+ if ($reps->count() == 1) {
+ return $reps->first();
}
- $model->save();
- return true;
+ if ($reps->count() == 0) {
+ throw new FireflyException('Should always find a piggy bank repetition.');
+ }
+ throw new NotImplementedException;
+ }
+
+ /**
+ * @param \Account $account
+ *
+ * @return float
+ */
+ public function leftOnAccount(\Account $account)
+ {
+ $balance = \Steam::balance($account);
+ /** @var \Piggybank $p */
+ foreach ($account->piggybanks()->get() as $p) {
+ $balance -= $p->currentRelevantRep()->currentamount;
+ }
+
+ return $balance;
+
}
}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/Recurring.php b/app/lib/FireflyIII/Database/Recurring.php
index b8cb6ba29f..d87a7f2b33 100644
--- a/app/lib/FireflyIII/Database/Recurring.php
+++ b/app/lib/FireflyIII/Database/Recurring.php
@@ -4,11 +4,14 @@ namespace FireflyIII\Database;
use Carbon\Carbon;
-use Illuminate\Support\Collection;
-use LaravelBook\Ardent\Ardent;
use FireflyIII\Database\Ifaces\CommonDatabaseCalls;
use FireflyIII\Database\Ifaces\CUD;
use FireflyIII\Database\Ifaces\RecurringInterface;
+use FireflyIII\Exception\NotImplementedException;
+use Illuminate\Support\Collection;
+use Illuminate\Support\MessageBag;
+
+use stdObject;
/**
* Class Recurring
@@ -28,39 +31,87 @@ class Recurring implements CUD, CommonDatabaseCalls, RecurringInterface
}
/**
- * @param \RecurringTransaction $recurring
- * @param Carbon $start
- * @param Carbon $end
- *
- * @return \TransactionJournal|null
- */
- public function getJournalForRecurringInRange(\RecurringTransaction $recurring, Carbon $start, Carbon $end)
- {
- return $this->getUser()->transactionjournals()->where('recurring_transaction_id', $recurring->id)->after($start)->before($end)->first();
-
- }
-
- /**
- * @param Ardent $model
+ * @param \Eloquent $model
*
* @return bool
*/
- public function destroy(Ardent $model)
+ public function destroy(\Eloquent $model)
{
- // TODO: Implement destroy() method.
+ $model->delete();
+
+ return true;
}
/**
- * Validates a model. Returns an array containing MessageBags
- * errors/warnings/successes.
+ * @param array $data
*
- * @param Ardent $model
- *
- * @return array
+ * @return \Eloquent
*/
- public function validateObject(Ardent $model)
+ public function store(array $data)
{
- // TODO: Implement validateObject() method.
+ var_dump($data);
+ $recurring = new \RecurringTransaction;
+ $recurring->user()->associate($this->getUser());
+ $recurring->name = $data['name'];
+ $recurring->match = $data['match'];
+ $recurring->amount_max = floatval($data['amount_max']);
+ $recurring->amount_min = floatval($data['amount_min']);
+
+ $date = new Carbon($data['date']);
+
+
+ $recurring->active = isset($data['active']) && intval($data['active']) == 1 ? 1 : 0;
+ $recurring->automatch = isset($data['automatch']) && intval($data['automatch']) == 1 ? 1 : 0;
+ $recurring->repeat_freq = $data['repeat_freq'];
+
+ /*
+ * Jump to the start of the period.
+ */
+ $date = DateKit::startOfPeriod($date, $data['repeat_freq']);
+ $recurring->date = $date;
+ $recurring->skip = intval($data['skip']);
+
+ if (!$recurring->isValid()) {
+ var_dump($recurring->getErrors());
+ exit();
+ }
+
+ $recurring->save();
+
+ return $recurring;
+ }
+
+ /**
+ * @param \Eloquent $model
+ * @param array $data
+ *
+ * @return bool
+ */
+ public function update(\Eloquent $model, array $data)
+ {
+ var_dump($data);
+
+ $model->name = $data['name'];
+ $model->match = $data['match'];
+ $model->amount_max = floatval($data['amount_max']);
+ $model->amount_min = floatval($data['amount_min']);
+
+ $date = new Carbon($data['date']);
+
+ $model->date = $date;
+ $model->active = isset($data['active']) && intval($data['active']) == 1 ? 1 : 0;
+ $model->automatch = isset($data['automatch']) && intval($data['automatch']) == 1 ? 1 : 0;
+ $model->repeat_freq = $data['repeat_freq'];
+ $model->skip = intval($data['skip']);
+
+ if (!$model->isValid()) {
+ var_dump($model->getErrors());
+ exit();
+ }
+
+ $model->save();
+
+ return true;
}
/**
@@ -73,17 +124,57 @@ class Recurring implements CUD, CommonDatabaseCalls, RecurringInterface
*/
public function validate(array $model)
{
- // TODO: Implement validate() method.
- }
+ $warnings = new MessageBag;
+ $successes = new MessageBag;
+ $errors = new MessageBag;
- /**
- * @param array $data
- *
- * @return Ardent
- */
- public function store(array $data)
- {
- // TODO: Implement store() method.
+ if (isset($model['name']) && strlen($model['name']) == 0) {
+ $errors->add('name', 'Name must be longer.');
+ }
+ if (isset($model['name']) && strlen($model['name']) > 200) {
+ $errors->add('name', 'Name must be shorter.');
+ }
+
+ if (isset($model['match']) && strlen(trim($model['match'])) <= 2) {
+ $errors->add('match', 'Needs more matches.');
+ }
+
+ if (isset($model['amount_min']) && floatval($model['amount_min']) < 0.01) {
+ $errors->add('amount_min', 'Minimum amount must be higher.');
+ }
+ if (isset($model['amount_max']) && floatval($model['amount_max']) < 0.02) {
+ $errors->add('amount_max', 'Maximum amount must be higher.');
+ }
+ if (isset($model['amount_min']) && isset($model['amount_max']) && floatval($model['amount_min']) > floatval($model['amount_max'])) {
+ $errors->add('amount_max', 'Maximum amount can not be less than minimum amount.');
+ $errors->add('amount_min', 'Minimum amount can not be more than maximum amount.');
+ }
+
+ if ($model['date'] != '') {
+ try {
+ new Carbon($model['date']);
+ } catch (\Exception $e) {
+ $errors->add('date', 'Invalid date.');
+ }
+ }
+
+ $reminders = \Config::get('firefly.budget_periods');
+ if (!isset($model['repeat_freq']) || (isset($model['repeat_freq']) && !in_array($model['repeat_freq'], $reminders))) {
+ $errors->add('repeat_freq', 'Invalid reminder period');
+ }
+
+ if (isset($model['skip']) && intval($model['skip']) < 0) {
+ $errors->add('skip', 'Invalid skip.');
+ }
+
+ $set = ['name', 'match', 'amount_min', 'amount_max', 'date', 'repeat_freq', 'skip', 'automatch', 'active'];
+ foreach ($set as $entry) {
+ if (!$errors->has($entry)) {
+ $successes->add($entry, 'OK');
+ }
+ }
+
+ return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
}
/**
@@ -91,11 +182,25 @@ class Recurring implements CUD, CommonDatabaseCalls, RecurringInterface
*
* @param int $id
*
- * @return Ardent
+ * @return \Eloquent
*/
public function find($id)
{
// TODO: Implement find() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc.
+ *
+ * @param $what
+ *
+ * @return \AccountType|null
+ */
+ public function findByWhat($what)
+ {
+ // TODO: Implement findByWhat() method.
+ throw new NotImplementedException;
}
/**
@@ -116,28 +221,124 @@ class Recurring implements CUD, CommonDatabaseCalls, RecurringInterface
public function getByIds(array $ids)
{
// TODO: Implement getByIds() method.
+ throw new NotImplementedException;
}
/**
- * Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc.
+ * @param \RecurringTransaction $recurring
+ * @param Carbon $start
+ * @param Carbon $end
*
- * @param $what
- *
- * @return \AccountType|null
+ * @return \TransactionJournal|null
*/
- public function findByWhat($what)
+ public function getJournalForRecurringInRange(\RecurringTransaction $recurring, Carbon $start, Carbon $end)
{
- // TODO: Implement findByWhat() method.
+ return $this->getUser()->transactionjournals()->where('recurring_transaction_id', $recurring->id)->after($start)->before($end)->first();
+
}
/**
- * @param Ardent $model
- * @param array $data
+ * @param \RecurringTransaction $recurring
+ * @param \TransactionJournal $journal
*
* @return bool
*/
- public function update(Ardent $model, array $data)
+ public function scan(\RecurringTransaction $recurring, \TransactionJournal $journal)
{
- // TODO: Implement update() method.
+ /*
+ * Match words.
+ */
+ $wordMatch = false;
+ $matches = explode(',', $recurring->match);
+ $description = strtolower($journal->description);
+
+ /*
+ * Attach expense account to description for more narrow matching.
+ */
+ if (count($journal->transactions) < 2) {
+ $transactions = $journal->transactions()->get();
+ } else {
+ $transactions = $journal->transactions;
+ }
+ /** @var \Transaction $transaction */
+ foreach ($transactions as $transaction) {
+ /** @var \Account $account */
+ $account = $transaction->account()->first();
+ /** @var \AccountType $type */
+ $type = $account->accountType()->first();
+ if ($type->type == 'Expense account' || $type->type == 'Beneficiary account') {
+ $description .= ' ' . strtolower($account->name);
+ }
+ }
+ \Log::debug('Final description: ' . $description);
+ \Log::debug('Matches searched: ' . join(':', $matches));
+
+ $count = 0;
+ foreach ($matches as $word) {
+ if (!(strpos($description, strtolower($word)) === false)) {
+ $count++;
+ }
+ }
+ if ($count >= count($matches)) {
+ $wordMatch = true;
+ \Log::debug('word match is true');
+ }
+
+
+ /*
+ * Match amount.
+ */
+
+ $amountMatch = false;
+ if (count($transactions) > 1) {
+
+ $amount = max(floatval($transactions[0]->amount), floatval($transactions[1]->amount));
+ $min = floatval($recurring->amount_min);
+ $max = floatval($recurring->amount_max);
+ if ($amount >= $min && $amount <= $max) {
+ $amountMatch = true;
+ \Log::debug('Amount match is true!');
+ }
+ }
+
+ /*
+ * If both, update!
+ */
+ if ($wordMatch && $amountMatch) {
+ $journal->recurringTransaction()->associate($recurring);
+ $journal->save();
+ }
+ }
+
+ /**
+ * @param \RecurringTransaction $recurring
+ *
+ * @return bool
+ */
+ public function scanEverything(\RecurringTransaction $recurring)
+ {
+ // get all journals that (may) be relevant.
+ // this is usually almost all of them.
+
+ /** @var \FireflyIII\Database\TransactionJournal $journalRepository */
+ $journalRepository = \App::make('FireflyIII\Database\TransactionJournal');
+
+ $set = \DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $recurring->amount_min)->where('amount', '<=', $recurring->amount_max)
+ ->get(['transaction_journal_id']);
+ $ids = [];
+
+ /** @var \Transaction $entry */
+ foreach ($set as $entry) {
+ $ids[] = intval($entry->transaction_journal_id);
+ }
+ if (count($ids) > 0) {
+ $journals = $journalRepository->getByIds($ids);
+ /** @var \TransactionJournal $journal */
+ foreach ($journals as $journal) {
+ $this->scan($recurring, $journal);
+ }
+ }
+
+ return true;
}
}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/RepeatedExpense.php b/app/lib/FireflyIII/Database/RepeatedExpense.php
new file mode 100644
index 0000000000..e0294558ce
--- /dev/null
+++ b/app/lib/FireflyIII/Database/RepeatedExpense.php
@@ -0,0 +1,480 @@
+setUser(\Auth::user());
+ }
+
+ /**
+ * Based on the piggy bank, the reminder-setting and
+ * other variables this method tries to divide the piggy bank into equal parts. Each is
+ * accommodated by a reminder (if everything goes to plan).
+ *
+ * @return \PiggybankRepetition
+ */
+ public function calculateParts(\PiggybankRepetition $repetition)
+ {
+ \Log::debug('NOW in calculateParts()');
+ \Log::debug('Repetition id is ' . $repetition->id);
+ /** @var \Piggybank $piggyBank */
+ $piggyBank = $repetition->piggybank()->first();
+ $bars = new Collection;
+ \Log::debug('connected piggy bank is: ' . $piggyBank->name . ' (#' . $piggyBank->id . ')');
+
+ /*
+ * If no reminders are set, the repetition is split in exactly one part:
+ */
+ if (is_null($piggyBank->reminder)) {
+ $part = new PiggybankPart;
+ $part->setRepetition($repetition);
+ $part->setAmountPerBar(floatval($piggyBank->targetamount));
+ $part->setCurrentamount($repetition->currentamount);
+ $part->setCumulativeAmount($piggyBank->targetamount);
+ $part->setStartdate(clone $repetition->startdate);
+ $part->setTargetdate(clone $repetition->targetdate);
+ $bars->push($part);
+ $repetition->bars = $bars;
+
+ return $repetition;
+ }
+ $currentStart = clone $repetition->startdate;
+ /*
+ * Loop between start and target instead of counting manually.
+ */
+ $index = 0;
+ //echo 'Looping! ';
+ //echo $repetition->startdate . ' until ' . $repetition->targetdate . ' ';
+ while ($currentStart < $repetition->targetdate) {
+ $currentTarget = \DateKit::endOfX($currentStart, $piggyBank->reminder);
+ if ($currentTarget > $repetition->targetdate) {
+ $currentTarget = clone $repetition->targetdate;
+ }
+
+ // create a part:
+ $part = new PiggybankPart;
+ $part->setRepetition($repetition);
+ $part->setCurrentamount($repetition->currentamount);
+ $part->setStartdate($currentStart);
+ $part->setTargetdate($currentTarget);
+ $bars->push($part);
+ //echo 'Loop #' . $index . ', from ' . $currentStart . ' until ' . $currentTarget . ' ';
+
+
+ /*
+ * Jump to the next period by adding a day.
+ */
+ $currentStart = clone $currentTarget;
+ $currentStart->addDay();//\DateKit::addPeriod($currentTarget, $piggyBank->reminder, 0);
+ $index++;
+
+ }
+ /*
+ * Loop parts again to add some
+ */
+ $parts = $bars->count();
+ $amountPerBar = floatval($piggyBank->targetamount) / $parts;
+ $cumulative = $amountPerBar;
+ /** @var PiggybankPart $bar */
+ foreach ($bars as $index => $bar) {
+ $bar->setAmountPerBar($amountPerBar);
+ $bar->setCumulativeAmount($cumulative);
+ if($parts -1 == $index) {
+ $bar->setCumulativeAmount($piggyBank->targetamount);
+ }
+
+ $reminder = $piggyBank->reminders()
+ ->where('startdate', $bar->getStartdate()->format('Y-m-d'))
+ ->where('enddate', $bar->getTargetdate()->format('Y-m-d'))
+ ->first();
+ if ($reminder) {
+ $bar->setReminder($reminder);
+ }
+
+ $cumulative += $amountPerBar;
+ }
+
+ $repetition->bars = $bars;
+
+ return $repetition;
+ //
+ // // if($parts > 12) {
+ // // $parts = 12;
+ // // $currentStart = \DateKit::startOfPeriod(Carbon::now(), $piggyBank->reminder);
+ // // $currentEnd = \DateKit::endOfPeriod($currentEnd, $piggyBank->reminder);
+ // // }
+ //
+ // for ($i = 0; $i < $parts; $i++) {
+ // /*
+ // * If it's not the first repetition, jump the start date a [period]
+ // * and jump the target date a [period]
+ // */
+ // if ($i > 0) {
+ // $currentStart = clone $currentTarget;
+ // $currentStart->addDay();
+ // $currentTarget = \DateKit::addPeriod($currentStart, $piggyBank->reminder, 0);
+ // }
+ // /*
+ // * If it's the first one, and has reminders, jump to the end of the [period]
+ // */
+ // if ($i == 0 && !is_null($piggyBank->reminder)) {
+ // $currentTarget = \DateKit::endOfX($currentStart, $piggyBank->reminder);
+ // }
+ // if ($currentStart > $repetition->targetdate) {
+ // break;
+ // }
+ //
+ //
+ // /*
+ // * Jump one month ahead after the first instance:
+ // */
+ // // if ($i > 0) {
+ // // $currentStart = \DateKit::addPeriod($currentStart, $piggyBank->reminder, 0);
+ // // /*
+ // // * Jump to the start of the period too:
+ // // */
+ // // $currentStart = \DateKit::startOfPeriod($currentStart, $piggyBank->reminder);
+ // //
+ // // }
+ //
+ //
+ // /*
+ // * Move the current start to the actual start of
+ // * the [period] once the first iteration has passed.
+ // */
+ // // if ($i != 0) {
+ // // $currentStart = \DateKit::startOfPeriod($currentStart, $piggyBank->reminder);
+ // // }
+ // // if($i == 0 && !is_null($piggyBank->reminder)) {
+ // // $currentEnd = \DateKit::startOfPeriod($currentStart, $piggyBank->reminder);
+ // // $currentEnd = \DateKit::endOfPeriod($currentEnd, $piggyBank->reminder);
+ // // }
+ //
+ // $part = new PiggybankPart;
+ // $part->setRepetition($repetition);
+ // $part->setAmount($currentAmount);
+ // $part->setAmountPerBar($amountPerBar);
+ // $part->setCurrentamount($repetition->currentamount);
+ // $part->setStartdate($currentStart);
+ // $part->setTargetdate($currentTarget);
+ // if (!is_null($piggyBank->reminder)) {
+ // // might be a reminder for this range?
+ // $reminder = $piggyBank->reminders()
+ // ->where('startdate', $currentStart->format('Y-m-d'))
+ // ->where('enddate', $currentTarget->format('Y-m-d'))
+ // ->first();
+ // if ($reminder) {
+ // $part->setReminder($reminder);
+ // }
+ //
+ // }
+ //
+ // // if (!is_null($piggyBank->reminder)) {
+ // // $currentStart = \DateKit::addPeriod($currentStart, $piggyBank->reminder, 0);
+ // // $currentEnd = \DateKit::endOfPeriod($currentStart, $piggyBank->reminder);
+ // // }
+ //
+ //
+ // $bars->push($part);
+ // $currentAmount += $amountPerBar;
+ // }
+ // $repetition->bars = $bars;
+ //
+ // return $repetition;
+ // exit;
+ //
+ //
+ // $repetition->hello = 'World!';
+ //
+ // return $repetition;
+ //
+ // $return = new Collection;
+ // $repetitions = $piggyBank->piggybankrepetitions()->get();
+ // /** @var \PiggybankRepetition $repetition */
+ // foreach ($repetitions as $repetition) {
+ //
+ //
+ // if (is_null($piggyBank->reminder)) {
+ // // simple, one part "repetition".
+ // $part = new PiggybankPart;
+ // $part->setRepetition($repetition);
+ // } else {
+ // $part = new PiggybankPart;
+ // }
+ //
+ //
+ // // end!
+ // $return->push($part);
+ // }
+ //
+ // exit;
+ //
+ // return $return;
+ // $piggyBank->currentRelevantRep(); // get the current relevant repetition.
+ // if (!is_null($piggyBank->reminder)) {
+ // switch ($piggyBank->reminder) {
+ // default:
+ // throw new FireflyException('Cannot handle "' . $piggyBank->reminder . '" reminders for repeated expenses');
+ // break;
+ // case 'month':
+ // $start = clone $piggyBank->currentRep->startdate;
+ // $start->startOfMonth();
+ // $end = clone $piggyBank->currentRep->targetdate;
+ // $end->endOfMonth();
+ // $piggyBank->parts = $start->diffInMonths($end);
+ // unset($start, $end);
+ // break;
+ // }
+ //
+ // } else {
+ // $piggyBank->parts = 1;
+ // }
+ //
+ // // number of bars:
+ // $piggyBank->barCount = floor(12 / $piggyBank->parts) == 0 ? 1 : floor(12 / $piggyBank->parts);
+ // $amountPerBar = floatval($piggyBank->targetamount) / $piggyBank->parts;
+ // $currentAmount = floatval($amountPerBar);
+ // $bars = [];
+ // $currentStart = clone $piggyBank->currentRep->startdate;
+ // for ($i = 0; $i < $piggyBank->parts; $i++) {
+ // // niet elke keer een andere dinges pakken? om target te redden?
+ // if (!is_null($piggyBank->reminder)) {
+ // $currentStart = \DateKit::addPeriod($currentStart, $piggyBank->reminder, 0);
+ // }
+ // $bars[] = [
+ // 'amount' => $currentAmount,
+ // 'date' => $currentStart
+ // ];
+ //
+ //
+ // $currentAmount += $amountPerBar;
+ // }
+ // $piggyBank->bars = $bars;
+ }
+
+ /**
+ * @param \Eloquent $model
+ *
+ * @return bool
+ */
+ public function destroy(\Eloquent $model)
+ {
+ // TODO: Implement destroy() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * @param array $data
+ *
+ * @return \Eloquent
+ */
+ public function store(array $data)
+ {
+
+ $data['rep_every'] = isset($data['rep_every']) ? $data['rep_every'] : 0;
+ $data['reminder_skip'] = isset($data['reminder_skip']) ? $data['reminder_skip'] : 0;
+ $data['order'] = isset($data['order']) ? $data['order'] : 0;
+ $data['remind_me'] = isset($data['remind_me']) ? intval($data['remind_me']) : 0;
+ $data['startdate'] = isset($data['startdate']) ? $data['startdate'] : Carbon::now()->format('Y-m-d');
+ $data['targetdate'] = isset($data['targetdate']) && $data['targetdate'] != '' ? $data['targetdate'] : null;
+ $data['account_id'] = intval($data['account_id']);
+
+
+ if ($data['remind_me'] == 0) {
+ $data['reminder'] = null;
+ }
+
+
+ $repeated = new \Piggybank($data);
+ if (!$repeated->isValid()) {
+ var_dump($repeated->getErrors()->all());
+ exit;
+ }
+ $repeated->save();
+
+ return $repeated;
+ }
+
+ /**
+ * @param \Eloquent $model
+ * @param array $data
+ *
+ * @return bool
+ */
+ public function update(\Eloquent $model, array $data)
+ {
+ // TODO: Implement update() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * Validates an array. Returns an array containing MessageBags
+ * errors/warnings/successes.
+ *
+ * @param array $model
+ *
+ * @return array
+ */
+ public function validate(array $model)
+ {
+ $warnings = new MessageBag;
+ $successes = new MessageBag;
+ $errors = new MessageBag;
+
+ /*
+ * Name validation:
+ */
+ if (!isset($model['name'])) {
+ $errors->add('name', 'Name is mandatory');
+ }
+
+ if (isset($model['name']) && strlen($model['name']) == 0) {
+ $errors->add('name', 'Name is too short');
+ }
+ if (isset($model['name']) && strlen($model['name']) > 100) {
+ $errors->add('name', 'Name is too long');
+ }
+
+ if (intval($model['account_id']) == 0) {
+ $errors->add('account_id', 'Account is mandatory');
+ }
+ if ($model['targetdate'] == '' && isset($model['remind_me']) && intval($model['remind_me']) == 1) {
+ $errors->add('targetdate', 'Target date is mandatory when setting reminders.');
+ }
+ if ($model['targetdate'] != '') {
+ try {
+ new Carbon($model['targetdate']);
+ } catch (\Exception $e) {
+ $errors->add('targetdate', 'Invalid date.');
+ }
+ $diff = Carbon::now()->diff(new Carbon($model['targetdate']));
+ if ($diff->days > 365) {
+ $errors->add('targetdate', 'First target date should a a year or less from now.');
+ }
+ } else {
+ $errors->add('targetdate', 'Invalid target date.');
+ }
+ if (floatval($model['targetamount']) < 0.01) {
+ $errors->add('targetamount', 'Amount should be above 0.01.');
+ }
+ if (!in_array(ucfirst($model['reminder']), \Config::get('firefly.piggybank_periods'))) {
+ $errors->add('reminder', 'Invalid reminder period (' . $model['reminder'] . ')');
+ }
+
+ if (!in_array(ucfirst($model['rep_length']), \Config::get('firefly.piggybank_periods'))) {
+ $errors->add('rep_length', 'Invalid repeat period (' . $model['rep_length'] . ')');
+ }
+
+ // check period.
+ if (!$errors->has('reminder') && !$errors->has('targetdate') && isset($model['remind_me']) && intval($model['remind_me']) == 1) {
+ $today = new Carbon;
+ $target = new Carbon($model['targetdate']);
+ switch ($model['reminder']) {
+ case 'week':
+ $today->addWeek();
+ break;
+ case 'month':
+ $today->addMonth();
+ break;
+ case 'year':
+ $today->addYear();
+ break;
+ }
+ if ($today > $target) {
+ $errors->add('reminder', 'Target date is too close to today to set reminders.');
+ }
+ }
+
+ $validator = \Validator::make($model, \Piggybank::$rules);
+ if ($validator->invalid()) {
+ $errors->merge($errors);
+ }
+
+ // add ok messages.
+ $list = ['name', 'account_id', 'rep_every', 'rep_times', 'rep_length', 'targetamount', 'targetdate', 'remind_me', 'reminder'];
+ foreach ($list as $entry) {
+ if (!$errors->has($entry) && !$warnings->has($entry)) {
+ $successes->add($entry, 'OK');
+ }
+ }
+
+ return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
+ }
+
+ /**
+ * Returns an object with id $id.
+ *
+ * @param int $id
+ *
+ * @return \Eloquent
+ */
+ public function find($id)
+ {
+ // TODO: Implement find() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc.
+ *
+ * @param $what
+ *
+ * @return \AccountType|null
+ */
+ public function findByWhat($what)
+ {
+ // TODO: Implement findByWhat() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * Returns all objects.
+ *
+ * @return Collection
+ */
+ public function get()
+ {
+ return $this->getUser()->piggybanks()->where('repeats', 1)->get();
+ }
+
+ /**
+ * @param array $ids
+ *
+ * @return Collection
+ */
+ public function getByIds(array $ids)
+ {
+ // TODO: Implement getByIds() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * @param \Account $account
+ *
+ * @return float
+ */
+ public function leftOnAccount(\Account $account)
+ {
+ // TODO: Implement leftOnAccount() method.
+ throw new NotImplementedException;
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/Report.php b/app/lib/FireflyIII/Database/Report.php
new file mode 100644
index 0000000000..db48935f09
--- /dev/null
+++ b/app/lib/FireflyIII/Database/Report.php
@@ -0,0 +1,175 @@
+sharedExpense) && $account->sharedExpense === true) {
+ $shared = true;
+ } else {
+ if (isset($account->sharedExpense) && $account->sharedExpense === false) {
+ $shared = false;
+ } else {
+ $shared = ($account->getMeta('accountRole') == 'sharedExpense');
+ }
+ }
+
+ $start = clone $month;
+ $end = clone $month;
+ $start->startOfMonth();
+ $end->endOfMonth();
+ $sum = 0;
+
+ // get all journals.
+ $journals = \TransactionJournal::whereIn(
+ 'id', function ($query) use ($account, $start, $end) {
+ $query->select('transaction_journal_id')
+ ->from('transactions')
+ ->where('account_id', $account->id);
+ }
+ )->before($end)->after($start)->get();
+
+
+ if ($shared) {
+ $expenses = $journals->filter(
+ function (\TransactionJournal $journal) use ($account) {
+ // any withdrawal is an expense:
+ if ($journal->transactionType->type == 'Withdrawal') {
+ return $journal;
+ }
+ // any transfer away from this account is an expense.
+ if ($journal->transactionType->type == 'Transfer') {
+ /** @var \Transaction $t */
+ foreach ($journal->transactions as $t) {
+ if ($t->account_id == $account->id && floatval($t->amount) < 0) {
+ return $journal;
+ }
+ }
+ }
+ return null;
+ }
+ );
+ } else {
+ $expenses = $journals->filter(
+ function (\TransactionJournal $journal) use ($account) {
+ // only withdrawals are expenses:
+ if ($journal->transactionType->type == 'Withdrawal') {
+ return $journal;
+ }
+ // transfers TO a shared account are also expenses.
+ if ($journal->transactionType->type == 'Transfer') {
+ /** @var \Transaction $t */
+ foreach ($journal->transactions() as $t) {
+ if ($t->account->getMeta('accountRole') == 'sharedExpense') {
+ echo '#'.$journal->id.' is a shared expense! ';
+ return $journal;
+ }
+ }
+ }
+ return null;
+ }
+ );
+ }
+ /** @var \TransactionJournal $expense */
+ foreach ($expenses as $expense) {
+ $sum += $expense->getAmount();
+ }
+
+
+ return $sum;
+ }
+
+ /**
+ * @param \Account $account
+ * @param Carbon $month
+ *
+ * @return float
+ */
+ public function getIncomeByMonth(\Account $account, Carbon $month)
+ {
+ if (isset($account->sharedExpense) && $account->sharedExpense === true) {
+ $shared = true;
+ } else {
+ if (isset($account->sharedExpense) && $account->sharedExpense === false) {
+ $shared = false;
+ } else {
+ $shared = ($account->getMeta('accountRole') == 'sharedExpense');
+ }
+ }
+
+ $start = clone $month;
+ $end = clone $month;
+ $start->startOfMonth();
+ $end->endOfMonth();
+ $sum = 0;
+
+ // get all journals.
+ $journals = \TransactionJournal::whereIn(
+ 'id', function ($query) use ($account, $start, $end) {
+ $query->select('transaction_journal_id')
+ ->from('transactions')
+ ->where('account_id', $account->id);
+ }
+ )->before($end)->after($start)->get();
+
+
+ if ($shared) {
+ $incomes = $journals->filter(
+ function (\TransactionJournal $journal) use ($account) {
+ // any deposit is an income:
+ if ($journal->transactionType->type == 'Deposit') {
+ return $journal;
+ }
+ // any transfer TO this account is an income.
+ if ($journal->transactionType->type == 'Transfer') {
+ /** @var \Transaction $t */
+ foreach ($journal->transactions as $t) {
+ if ($t->account_id == $account->id && floatval($t->amount) > 0) {
+ return $journal;
+ }
+ }
+ }
+ return null;
+ }
+ );
+ } else {
+ $incomes = $journals->filter(
+ function (\TransactionJournal $journal) use ($account) {
+ // only deposits are incomes:
+ if ($journal->transactionType->type == 'Deposit') {
+ return $journal;
+ }
+ return null;
+ }
+ );
+ }
+ /** @var \TransactionJournal $expense */
+ foreach ($incomes as $income) {
+ $sum += $income->getAmount();
+ }
+
+
+ return $sum;
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/Transaction.php b/app/lib/FireflyIII/Database/Transaction.php
index 744880dd73..514ea66217 100644
--- a/app/lib/FireflyIII/Database/Transaction.php
+++ b/app/lib/FireflyIII/Database/Transaction.php
@@ -2,44 +2,71 @@
namespace FireflyIII\Database;
-use Firefly\Exception\FireflyException;
-use FireflyIII\Exception\NotImplementedException;
-use Illuminate\Support\Collection;
-use Illuminate\Support\MessageBag;
-use LaravelBook\Ardent\Ardent;
+use FireflyIII\Exception\FireflyException;
use FireflyIII\Database\Ifaces\CommonDatabaseCalls;
use FireflyIII\Database\Ifaces\CUD;
use FireflyIII\Database\Ifaces\TransactionInterface;
+use FireflyIII\Exception\NotImplementedException;
+use Illuminate\Support\Collection;
+use Illuminate\Support\MessageBag;
+
+
/**
* Class Transaction
*
* @package FireflyIII\Database
*/
-class Transaction implements TransactionInterface, CUD, CommonDatabaseCalls
+class Transaction implements CUD, CommonDatabaseCalls
{
use SwitchUser;
/**
- * @param Ardent $model
+ * @param \Eloquent $model
*
* @return bool
*/
- public function destroy(Ardent $model)
+ public function destroy(\Eloquent $model)
{
// TODO: Implement destroy() method.
+ throw new NotImplementedException;
}
/**
- * Validates a model. Returns an array containing MessageBags
- * errors/warnings/successes.
+ * @param array $data
*
- * @param Ardent $model
- *
- * @return array
+ * @return \Eloquent
*/
- public function validateObject(Ardent $model)
+ public function store(array $data)
{
- // TODO: Implement validateObject() method.
+ $transaction = new \Transaction;
+ $transaction->account()->associate($data['account']);
+ $transaction->transactionJournal()->associate($data['transaction_journal']);
+ $transaction->amount = floatval($data['amount']);
+ if (isset($data['piggybank'])) {
+ $transaction->piggybank()->associate($data['piggybank']);
+ }
+ if (isset($data['description'])) {
+ $transaction->description = $data['description'];
+ }
+ if ($transaction->isValid()) {
+ $transaction->save();
+ } else {
+ throw new FireflyException($transaction->getErrors()->first());
+ }
+
+ return $transaction;
+ }
+
+ /**
+ * @param \Eloquent $model
+ * @param array $data
+ *
+ * @return bool
+ */
+ public function update(\Eloquent $model, array $data)
+ {
+ // TODO: Implement update() method.
+ throw new NotImplementedException;
}
/**
@@ -105,37 +132,7 @@ class Transaction implements TransactionInterface, CUD, CommonDatabaseCalls
$successes->add('amount', 'OK');
}
- return [
- 'errors' => $errors,
- 'warnings' => $warnings,
- 'successes' => $successes
- ];
- }
-
- /**
- * @param array $data
- *
- * @return Ardent
- */
- public function store(array $data)
- {
- // TODO: Implement store() method.
- $transaction = new \Transaction;
- $transaction->account()->associate($data['account']);
- $transaction->transactionJournal()->associate($data['transaction_journal']);
- $transaction->amount = floatval($data['amount']);
- if (isset($data['piggybank'])) {
- $transaction->piggybank()->associate($data['piggybank']);
- }
- if (isset($data['description'])) {
- $transaction->description = $data['description'];
- }
- if ($transaction->validate()) {
- $transaction->save();
- } else {
- throw new FireflyException($transaction->errors()->first());
- }
- return $transaction;
+ return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
}
/**
@@ -143,21 +140,12 @@ class Transaction implements TransactionInterface, CUD, CommonDatabaseCalls
*
* @param int $id
*
- * @return Ardent
+ * @return \Eloquent
*/
public function find($id)
{
// TODO: Implement find() method.
- }
-
- /**
- * Returns all objects.
- *
- * @return Collection
- */
- public function get()
- {
- // TODO: Implement get() method.
+ throw new NotImplementedException;
}
/**
@@ -170,17 +158,18 @@ class Transaction implements TransactionInterface, CUD, CommonDatabaseCalls
public function findByWhat($what)
{
// TODO: Implement findByWhat() method.
+ throw new NotImplementedException;
}
/**
- * @param Ardent $model
- * @param array $data
+ * Returns all objects.
*
- * @return bool
+ * @return Collection
*/
- public function update(Ardent $model, array $data)
+ public function get()
{
- // TODO: Implement update() method.
+ // TODO: Implement get() method.
+ throw new NotImplementedException;
}
/**
@@ -191,5 +180,6 @@ class Transaction implements TransactionInterface, CUD, CommonDatabaseCalls
public function getByIds(array $ids)
{
// TODO: Implement getByIds() method.
+ throw new NotImplementedException;
}
}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/TransactionCurrency.php b/app/lib/FireflyIII/Database/TransactionCurrency.php
index 9e46efb207..6de3860ada 100644
--- a/app/lib/FireflyIII/Database/TransactionCurrency.php
+++ b/app/lib/FireflyIII/Database/TransactionCurrency.php
@@ -3,10 +3,6 @@
namespace FireflyIII\Database;
-use Illuminate\Support\Collection;
-use LaravelBook\Ardent\Ardent;
-use FireflyIII\Database\Ifaces\CommonDatabaseCalls;
-use FireflyIII\Database\Ifaces\CUD;
use FireflyIII\Database\Ifaces\TransactionCurrencyInterface;
/**
@@ -14,89 +10,9 @@ use FireflyIII\Database\Ifaces\TransactionCurrencyInterface;
*
* @package FireflyIII\Database
*/
-class TransactionCurrency implements TransactionCurrencyInterface, CUD, CommonDatabaseCalls
+class TransactionCurrency implements TransactionCurrencyInterface
{
- /**
- * @param Ardent $model
- *
- * @return bool
- */
- public function destroy(Ardent $model)
- {
- // TODO: Implement destroy() method.
- }
-
- /**
- * Validates a model. Returns an array containing MessageBags
- * errors/warnings/successes.
- *
- * @param Ardent $model
- *
- * @return array
- */
- public function validateObject(Ardent $model)
- {
- // TODO: Implement validateObject() method.
- }
-
- /**
- * Validates an array. Returns an array containing MessageBags
- * errors/warnings/successes.
- *
- * @param array $model
- *
- * @return array
- */
- public function validate(array $model)
- {
- // TODO: Implement validate() method.
- }
-
- /**
- * @param array $data
- *
- * @return Ardent
- */
- public function store(array $data)
- {
- // TODO: Implement store() method.
- }
-
- /**
- * Returns an object with id $id.
- *
- * @param int $id
- *
- * @return Ardent
- */
- public function find($id)
- {
- // TODO: Implement find() method.
- }
-
- /**
- * Returns all objects.
- *
- * @return Collection
- */
- public function get()
- {
- // TODO: Implement get() method.
- }
-
- /**
- * Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc.
- *
- * @param $what
- *
- * @return \AccountType|null
- */
- public function findByWhat($what)
- {
- // TODO: Implement get() method.
- }
-
/**
* @param string $code
*
@@ -106,25 +22,4 @@ class TransactionCurrency implements TransactionCurrencyInterface, CUD, CommonDa
{
return \TransactionCurrency::whereCode($code)->first();
}
-
- /**
- * @param array $ids
- *
- * @return Collection
- */
- public function getByIds(array $ids)
- {
- // TODO: Implement getByIds() method.
- }
-
- /**
- * @param Ardent $model
- * @param array $data
- *
- * @return bool
- */
- public function update(Ardent $model, array $data)
- {
- // TODO: Implement update() method.
- }
}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/TransactionJournal.php b/app/lib/FireflyIII/Database/TransactionJournal.php
index 3355f458a8..e0f8184fc0 100644
--- a/app/lib/FireflyIII/Database/TransactionJournal.php
+++ b/app/lib/FireflyIII/Database/TransactionJournal.php
@@ -4,14 +4,13 @@ namespace FireflyIII\Database;
use Carbon\Carbon;
-use Firefly\Exception\FireflyException;
-use FireflyIII\Exception\NotImplementedException;
-use Illuminate\Support\Collection;
-use Illuminate\Support\MessageBag;
-use LaravelBook\Ardent\Ardent;
use FireflyIII\Database\Ifaces\CommonDatabaseCalls;
use FireflyIII\Database\Ifaces\CUD;
use FireflyIII\Database\Ifaces\TransactionJournalInterface;
+use FireflyIII\Exception\FireflyException;
+use FireflyIII\Exception\NotImplementedException;
+use Illuminate\Support\Collection;
+use Illuminate\Support\MessageBag;
/**
* Class TransactionJournal
@@ -31,90 +30,251 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData
}
/**
- * @param Carbon $date
- *
- * @return float
- */
- public function getSumOfIncomesByMonth(Carbon $date)
- {
- $end = clone $date;
- $date->startOfMonth();
- $end->endOfMonth();
-
- $sum = \DB::table('transactions')
- ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
- ->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
- ->where('amount', '>', 0)
- ->where('transaction_types.type', '=', 'Deposit')
- ->where('transaction_journals.date', '>=', $date->format('Y-m-d'))
- ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('transactions.amount');
- $sum = floatval($sum);
- return $sum;
- }
-
- /**
- * @param Carbon $date
- *
- * @return float
- */
- public function getSumOfExpensesByMonth(Carbon $date)
- {
- $end = clone $date;
- $date->startOfMonth();
- $end->endOfMonth();
-
- $sum = \DB::table('transactions')
- ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
- ->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
- ->where('amount', '>', 0)
- ->where('transaction_types.type', '=', 'Withdrawal')
- ->where('transaction_journals.date', '>=', $date->format('Y-m-d'))
- ->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('transactions.amount');
- $sum = floatval($sum);
- return $sum;
- }
-
- /**
- * @param Carbon $start
- * @param Carbon $end
- *
- * @return Collection
- */
- public function getInDateRange(Carbon $start, Carbon $end)
- {
- return $this->getuser()->transactionjournals()->withRelevantData()->before($end)->after($start)->get();
- }
-
- /**
- * @return TransactionJournal
- */
- public function first()
- {
- return $this->getUser()->transactionjournals()->orderBy('date', 'ASC')->first();
- }
-
-
- /**
- * @param Ardent $model
+ * @param \Eloquent $model
*
* @return bool
*/
- public function destroy(Ardent $model)
+ public function destroy(\Eloquent $model)
{
- // TODO: Implement destroy() method.
+ /*
+ * Trigger deletion.
+ */
+ \Event::fire('transactionJournal.destroy', [$model]); // new and used.
+ /*
+ * Since this event will also destroy both transactions, trigger on those as
+ * well because we might want to update some caches and what-not.
+ */
+ /** @var Transaction $transaction */
+ foreach ($model->transactions as $transaction) {
+ \Event::fire('transaction.destroy', [$transaction]);
+ }
+
+ $model->delete();
+
+ return true;
}
/**
- * Validates a model. Returns an array containing MessageBags
- * errors/warnings/successes.
+ * @param array $data
*
- * @param Ardent $model
- *
- * @return array
+ * @return \Eloquent
*/
- public function validateObject(Ardent $model)
+ public function store(array $data)
{
- // TODO: Implement validateObject() method.
+ /** @var \FireflyIII\Database\TransactionType $typeRepository */
+ $typeRepository = \App::make('FireflyIII\Database\TransactionType');
+
+ /** @var \FireflyIII\Database\Account $accountRepository */
+ $accountRepository = \App::make('FireflyIII\Database\Account');
+
+ /** @var \FireflyIII\Database\TransactionCurrency $currencyRepository */
+ $currencyRepository = \App::make('FireflyIII\Database\TransactionCurrency');
+
+ /** @var \FireflyIII\Database\Transaction $transactionRepository */
+ $transactionRepository = \App::make('FireflyIII\Database\Transaction');
+
+ $journalType = $typeRepository->findByWhat($data['what']);
+ $currency = $currencyRepository->findByCode($data['currency']);
+
+ $journal = new \TransactionJournal;
+ $journal->transactionType()->associate($journalType);
+ $journal->transactionCurrency()->associate($currency);
+ $journal->user()->associate($this->getUser());
+ $journal->description = $data['description'];
+ $journal->date = $data['date'];
+ $journal->completed = 0;
+
+ /*
+ * This must be enough to store the journal:
+ */
+ if (!$journal->isValid()) {
+ \Log::error($journal->getErrors()->all());
+ throw new FireflyException('store() transaction journal failed, but it should not!');
+ }
+ $journal->save();
+
+ /*
+ * Still need to find the accounts related to the transactions.
+ * This depends on the type of transaction.
+ */
+ switch ($data['what']) {
+ case 'withdrawal':
+ $data['from'] = $accountRepository->find($data['account_id']);
+ $data['to'] = $accountRepository->firstExpenseAccountOrCreate($data['expense_account']);
+ break;
+ case 'opening':
+ break;
+ case 'deposit':
+ $data['to'] = $accountRepository->find($data['account_id']);
+ $data['from'] = $accountRepository->firstRevenueAccountOrCreate($data['revenue_account']);
+ break;
+ case 'transfer':
+ $data['from'] = $accountRepository->find($data['account_from_id']);
+ $data['to'] = $accountRepository->find($data['account_to_id']);
+ break;
+
+ default:
+ throw new FireflyException('Cannot save transaction journal with accounts based on $what "' . $data['what'] . '".');
+ break;
+ }
+
+ /*
+ * Then store both transactions.
+ */
+ $first = ['account' => $data['from'], 'transaction_journal' => $journal, 'amount' => ($data['amount'] * -1),];
+ $validate = $transactionRepository->validate($first);
+ if ($validate['errors']->count() == 0) {
+ $transactionRepository->store($first);
+ } else {
+ throw new FireflyException($validate['errors']->first());
+ }
+
+ $second = ['account' => $data['to'], 'transaction_journal' => $journal, 'amount' => floatval($data['amount']),];
+
+ $validate = $transactionRepository->validate($second);
+ if ($validate['errors']->count() == 0) {
+ $transactionRepository->store($second);
+ } else {
+ throw new FireflyException($validate['errors']->first());
+ }
+
+ /*
+ * Store the budget.
+ */
+ if (isset($data['budget_id']) && intval($data['budget_id']) > 0) {
+ /** @var \FireflyIII\Database\Budget $budgetRepository */
+ $budgetRepository = \App::make('FireflyIII\Database\Budget');
+ $budget = $budgetRepository->find(intval($data['budget_id']));
+ if ($budget) {
+ $journal->budgets()->save($budget);
+ }
+ }
+ if (isset($data['category']) && strlen($data['category']) > 0) {
+ /** @var \FireflyIII\Database\Category $categoryRepository */
+ $categoryRepository = \App::make('FireflyIII\Database\Category');
+ $category = $categoryRepository->firstOrCreate($data['category']);
+ if ($category) {
+ $journal->categories()->save($category);
+ }
+ }
+
+ $journal->completed = 1;
+ $journal->save();
+
+ /*
+ * Trigger a search for a relevant recurring transaction.
+ */
+
+
+ return $journal;
+ }
+
+ /**
+ * @param \Eloquent $model
+ * @param array $data
+ *
+ * @return bool
+ */
+ public function update(\Eloquent $model, array $data)
+ {
+ /** @var \FireflyIII\Database\TransactionType $typeRepository */
+ $typeRepository = \App::make('FireflyIII\Database\TransactionType');
+
+ /** @var \FireflyIII\Database\Account $accountRepository */
+ $accountRepository = \App::make('FireflyIII\Database\Account');
+
+ /** @var \FireflyIII\Database\TransactionCurrency $currencyRepository */
+ $currencyRepository = \App::make('FireflyIII\Database\TransactionCurrency');
+
+ /** @var \FireflyIII\Database\Transaction $transactionRepository */
+ $transactionRepository = \App::make('FireflyIII\Database\Transaction');
+
+ $journalType = $typeRepository->findByWhat($data['what']);
+ $currency = $currencyRepository->findByCode($data['currency']);
+
+ $model->transactionType()->associate($journalType);
+ $model->transactionCurrency()->associate($currency);
+ $model->user()->associate($this->getUser());
+ $model->description = $data['description'];
+ $model->date = $data['date'];
+
+ /*
+ * This must be enough to store the journal:
+ */
+ if (!$model->isValid()) {
+ \Log::error($model->getErrors()->all());
+ throw new FireflyException('store() transaction journal failed, but it should not!');
+ }
+ $model->save();
+
+ /*
+ * Still need to find the accounts related to the transactions.
+ * This depends on the type of transaction.
+ */
+ switch ($data['what']) {
+ case 'withdrawal':
+ $data['from'] = $accountRepository->find($data['account_id']);
+ $data['to'] = $accountRepository->firstExpenseAccountOrCreate($data['expense_account']);
+ break;
+ case 'opening':
+ break;
+ case 'deposit':
+ $data['to'] = $accountRepository->find($data['account_id']);
+ $data['from'] = $accountRepository->firstRevenueAccountOrCreate($data['revenue_account']);
+ break;
+ case 'transfer':
+ $data['from'] = $accountRepository->find($data['account_from_id']);
+ $data['to'] = $accountRepository->find($data['account_to_id']);
+ break;
+
+ default:
+ throw new FireflyException('Cannot save transaction journal with accounts based on $what "' . $data['what'] . '".');
+ break;
+ }
+
+ /*
+ * Update the budget and the category.
+ */
+ $components = [];
+ if (isset($data['budget_id']) && intval($data['budget_id']) > 0) {
+ /** @var \FireflyIII\Database\Budget $budgetRepository */
+ $budgetRepository = \App::make('FireflyIII\Database\Budget');
+ $budget = $budgetRepository->find(intval($data['budget_id']));
+ if ($budget) {
+ $components[] = $budget->id;
+ }
+ }
+ if (strlen($data['category']) > 0) {
+ /** @var \FireflyIII\Database\Category $categoryRepository */
+ $categoryRepository = \App::make('FireflyIII\Database\Category');
+ $category = $categoryRepository->firstOrCreate($data['category']);
+ if ($category) {
+ $components[] = $category->id;
+ }
+ }
+ $model->components()->sync($components);
+
+ /*
+ * Now we can update the transactions related to this journal.
+ */
+ $amount = floatval($data['amount']);
+ /** @var \Transaction $transaction */
+ foreach ($model->transactions()->get() as $transaction) {
+ if (floatval($transaction->amount) > 0) {
+ // the TO transaction.
+ $transaction->account()->associate($data['to']);
+ $transaction->amount = $amount;
+ } else {
+ $transaction->account()->associate($data['from']);
+ $transaction->amount = $amount * -1;
+ }
+ if (!$transaction->isValid()) {
+ throw new FireflyException('Could not validate transaction while saving.');
+ }
+ $transaction->save();
+ }
+
+ return new MessageBag;
}
/**
@@ -163,26 +323,103 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData
$errors->add('date', 'This date is invalid.');
}
- if (isset($model['to_id']) && intval($model['to_id']) < 0) {
- $errors->add('account_to', 'Invalid to-account');
- }
- if (isset($model['from_id']) && intval($model['from_id']) < 0) {
- $errors->add('account_from', 'Invalid from-account');
- }
- if (isset($model['to']) && !($model['to'] instanceof \Account)) {
- $errors->add('account_to', 'Invalid to-account');
- }
- if (isset($model['from']) && !($model['from'] instanceof \Account)) {
- $errors->add('account_from', 'Invalid from-account');
- }
- if (!isset($model['amount']) || (isset($model['amount']) && floatval($model['amount']) < 0)) {
- $errors->add('amount', 'Invalid amount');
- }
- if (!isset($model['from']) && !isset($model['to'])) {
- $errors->add('account_to', 'No accounts found!');
+ /*
+ * Amount:
+ */
+ if (isset($model['amount']) && floatval($model['amount']) < 0.01) {
+ $errors->add('amount', 'Amount must be > 0.01');
+ } else {
+ if (!isset($model['amount'])) {
+ $errors->add('amount', 'Amount must be set!');
+ } else {
+ $successes->add('amount', 'OK');
+ }
}
- $validator = \Validator::make([$model], \Transaction::$rules);
+ /*
+ * Budget:
+ */
+ if (isset($model['budget_id']) && !ctype_digit($model['budget_id'])) {
+ $errors->add('budget_id', 'Invalid budget');
+ } else {
+ $successes->add('budget_id', 'OK');
+ }
+
+ $successes->add('category', 'OK');
+
+ /*
+ * Many checks to catch invalid or not-existing accounts.
+ */
+ $accountError = false;
+ switch (true) {
+ // this combination is often seen in withdrawals.
+ case (isset($model['account_id']) && isset($model['expense_account'])):
+ if (intval($model['account_id']) < 1) {
+ $errors->add('account_id', 'Invalid account.');
+ } else {
+ $successes->add('account_id', 'OK');
+ }
+ $successes->add('expense_account', 'OK');
+ break;
+ case (isset($model['account_id']) && isset($model['revenue_account'])):
+ if (intval($model['account_id']) < 1) {
+ $errors->add('account_id', 'Invalid account.');
+ } else {
+ $successes->add('account_id', 'OK');
+ }
+ $successes->add('revenue_account', 'OK');
+ break;
+ case (isset($model['account_from_id']) && isset($model['account_to_id'])):
+ if (intval($model['account_from_id']) < 1 || intval($model['account_from_id']) < 1) {
+ $errors->add('account_from_id', 'Invalid account selected.');
+ $errors->add('account_to_id', 'Invalid account selected.');
+
+ } else {
+ if (intval($model['account_from_id']) == intval($model['account_to_id'])) {
+ $errors->add('account_to_id', 'Cannot be the same as "from" account.');
+ $errors->add('account_from_id', 'Cannot be the same as "to" account.');
+ } else {
+ $successes->add('account_from_id', 'OK');
+ $successes->add('account_to_id', 'OK');
+ }
+ }
+ break;
+
+ case (isset($model['to']) && isset($model['from'])):
+ if (is_object($model['to']) && is_object($model['from'])) {
+ $successes->add('from', 'OK');
+ $successes->add('to', 'OK');
+ }
+ break;
+
+ default:
+ throw new FireflyException('Cannot validate accounts for transaction journal.');
+ break;
+ }
+
+ // if (isset($model['to_id']) && intval($model['to_id']) < 1) {
+ // $errors->add('account_to', 'Invalid to-account');
+ // }
+ //
+ // if (isset($model['from_id']) && intval($model['from_id']) < 1) {
+ // $errors->add('account_from', 'Invalid from-account');
+ //
+ // }
+ // if (isset($model['account_id']) && intval($model['account_id']) < 1) {
+ // $errors->add('account_id', 'Invalid account!');
+ // }
+ // if (isset($model['to']) && !($model['to'] instanceof \Account)) {
+ // $errors->add('account_to', 'Invalid to-account');
+ // }
+ // if (isset($model['from']) && !($model['from'] instanceof \Account)) {
+ // $errors->add('account_from', 'Invalid from-account');
+ // }
+ // if (!isset($model['amount']) || (isset($model['amount']) && floatval($model['amount']) < 0)) {
+ // $errors->add('amount', 'Invalid amount');
+ // }
+
+
+ $validator = \Validator::make([$model], \TransactionJournal::$rules);
if ($validator->invalid()) {
$errors->merge($errors);
}
@@ -197,108 +434,24 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData
if (!$errors->has('date')) {
$successes->add('date', 'OK');
}
- return [
- 'errors' => $errors,
- 'warnings' => $warnings,
- 'successes' => $successes
- ];
+
+ return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
}
- /**
- * @param array $data
- *
- * @return Ardent
- */
- public function store(array $data)
- {
-
- /** @var \FireflyIII\Database\TransactionType $typeRepository */
- $typeRepository = \App::make('FireflyIII\Database\TransactionType');
-
- /** @var \FireflyIII\Database\TransactionCurrency $currencyRepository */
- $currencyRepository = \App::make('FireflyIII\Database\TransactionCurrency');
-
- /** @var \FireflyIII\Database\Transaction $transactionRepository */
- $transactionRepository = \App::make('FireflyIII\Database\Transaction');
-
- $journalType = $typeRepository->findByWhat($data['what']);
- $currency = $currencyRepository->findByCode($data['currency']);
-
- $journal = new \TransactionJournal;
- $journal->transactionType()->associate($journalType);
- $journal->transactionCurrency()->associate($currency);
- $journal->user()->associate($this->getUser());
- $journal->description = $data['description'];
- $journal->date = $data['date'];
- $journal->completed = 0;
- //$journal->user_id = $this->getUser()->id;
-
- /*
- * This must be enough to store the journal:
- */
- if (!$journal->validate()) {
- \Log::error($journal->errors()->all());
- throw new FireflyException('store() transactionjournal failed, but it should not!');
- }
- $journal->save();
-
- /*
- * Then store both transactions.
- */
- $first = [
- 'account' => $data['from'],
- 'transaction_journal' => $journal,
- 'amount' => ($data['amount'] * -1),
- ];
- $validate = $transactionRepository->validate($first);
- if ($validate['errors']->count() == 0) {
- $transactionRepository->store($first);
- } else {
- throw new FireflyException($validate['errors']->first());
- }
-
- $second = [
- 'account' => $data['to'],
- 'transaction_journal' => $journal,
- 'amount' => floatval($data['amount']),
- ];
-
- $validate = $transactionRepository->validate($second);
- if ($validate['errors']->count() == 0) {
- $transactionRepository->store($second);
- } else {
- throw new FireflyException($validate['errors']->first());
- }
-
- $journal->completed = 1;
- $journal->save();
- return $journal;
- }
-
/**
* Returns an object with id $id.
*
* @param int $id
*
- * @return Ardent
+ * @return \Eloquent
*/
public function find($id)
{
return $this->getUser()->transactionjournals()->find($id);
}
- /**
- * Returns all objects.
- *
- * @return Collection
- */
- public function get()
- {
- return $this->getUser()->transactionjournals()->get();
- }
-
/**
* Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc.
*
@@ -309,6 +462,18 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData
public function findByWhat($what)
{
// TODO: Implement findByWhat() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * Returns all objects.
+ *
+ * @return Collection
+ */
+ public function get()
+ {
+ return $this->getUser()->transactionjournals()->with(['TransactionType', 'transactions', 'transactions.account', 'transactions.account.accountType'])
+ ->get();
}
/**
@@ -318,17 +483,171 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData
*/
public function getByIds(array $ids)
{
- // TODO: Implement getByIds() method.
+ return $this->getUser()->transactionjournals()->with('transactions')->whereIn('id', $ids)->orderBy('date', 'ASC')->get();
}
/**
- * @param Ardent $model
- * @param array $data
- *
- * @return bool
+ * @return TransactionJournal
*/
- public function update(Ardent $model, array $data)
+ public function first()
{
- // TODO: Implement update() method.
+ return $this->getUser()->transactionjournals()->orderBy('date', 'ASC')->first();
+ }
+
+ /**
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return Collection
+ */
+ public function getInDateRange(Carbon $start, Carbon $end)
+ {
+ return $this->getuser()->transactionjournals()->withRelevantData()->before($end)->after($start)->get();
+ }
+
+ /**
+ * @param Carbon $date
+ *
+ * @return float
+ */
+ public function getSumOfExpensesByMonth(Carbon $date)
+ {
+ $end = clone $date;
+ $date->startOfMonth();
+ $end->endOfMonth();
+
+ $sum = \DB::table('transactions')->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->leftJoin(
+ 'transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id'
+ )->where('amount', '>', 0)->where('transaction_types.type', '=', 'Withdrawal')->where('transaction_journals.date', '>=', $date->format('Y-m-d'))->where(
+ 'transaction_journals.date', '<=', $end->format('Y-m-d')
+ )->sum('transactions.amount');
+ $sum = floatval($sum);
+
+ return $sum;
+ }
+
+ /**
+ * @param Carbon $date
+ *
+ * @return float
+ */
+ public function getSumOfIncomesByMonth(Carbon $date)
+ {
+ $end = clone $date;
+ $date->startOfMonth();
+ $end->endOfMonth();
+
+ $sum = \DB::table('transactions')->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->leftJoin(
+ 'transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id'
+ )->where('amount', '>', 0)->where('transaction_types.type', '=', 'Deposit')->where('transaction_journals.date', '>=', $date->format('Y-m-d'))->where(
+ 'transaction_journals.date', '<=', $end->format('Y-m-d')
+ )->sum('transactions.amount');
+ $sum = floatval($sum);
+
+ return $sum;
+ }
+
+ public function getDepositsPaginated($limit = 50)
+ {
+ $offset = intval(\Input::get('page')) > 0 ? (intval(\Input::get('page')) - 1) * $limit : 0;
+
+ $set = $this->getUser()->transactionJournals()->transactionTypes(['Deposit'])->withRelevantData()->take($limit)->offset($offset)->orderBy(
+ 'date', 'DESC'
+ )->get(['transaction_journals.*']);
+ $count = $this->getUser()->transactionJournals()->transactionTypes(['Deposit'])->count();
+ $items = [];
+ foreach ($set as $entry) {
+ $items[] = $entry;
+ }
+
+ return \Paginator::make($items, $count, $limit);
+ }
+
+ /**
+ * @param \Account $account
+ * @param int $count
+ * @param Carbon $start
+ * @param Carbon $end
+ *
+ * @return Collection
+ */
+ public function getInDateRangeAccount(\Account $account, $count = 20, Carbon $start, Carbon $end)
+ {
+
+ $accountID = $account->id;
+ $query = $this->_user->transactionjournals()->with(['transactions', 'transactioncurrency', 'transactiontype'])->leftJoin(
+ 'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
+ )->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $accountID)->where(
+ 'date', '>=', $start->format('Y-m-d')
+ )->where('date', '<=', $end->format('Y-m-d'))->orderBy('transaction_journals.date', 'DESC')->orderBy('transaction_journals.id', 'DESC')->take(
+ $count
+ )->get(['transaction_journals.*']);
+
+ return $query;
+ }
+
+ public function getTransfersPaginated($limit = 50)
+ {
+ $offset = intval(\Input::get('page')) > 0 ? (intval(\Input::get('page')) - 1) * $limit : 0;
+
+ $set = $this->getUser()->transactionJournals()->transactionTypes(['Transfer'])->withRelevantData()->take($limit)->offset($offset)->orderBy(
+ 'date', 'DESC'
+ )->get(['transaction_journals.*']);
+ $count = $this->getUser()->transactionJournals()->transactionTypes(['Transfer'])->count();
+ $items = [];
+ foreach ($set as $entry) {
+ $items[] = $entry;
+ }
+
+ return \Paginator::make($items, $count, $limit);
+ }
+
+ public function getWithdrawalsPaginated($limit = 50)
+ {
+ $offset = intval(\Input::get('page')) > 0 ? (intval(\Input::get('page')) - 1) * $limit : 0;
+
+ $set = $this->getUser()->transactionJournals()->transactionTypes(['Withdrawal'])->withRelevantData()->take($limit)->offset($offset)->orderBy(
+ 'date', 'DESC'
+ )->get(['transaction_journals.*']);
+ $count = $this->getUser()->transactionJournals()->transactionTypes(['Withdrawal'])->count();
+ $items = [];
+ foreach ($set as $entry) {
+ $items[] = $entry;
+ }
+
+ return \Paginator::make($items, $count, $limit);
+ }
+
+ /**
+ * @param string $query
+ * @param \TransactionJournal $journal
+ *
+ * @return Collection
+ */
+ public function searchRelated($query, \TransactionJournal $journal)
+ {
+ $start = clone $journal->date;
+ $end = clone $journal->date;
+ $start->startOfMonth();
+ $end->endOfMonth();
+
+ // get already related transactions:
+ $exclude = [$journal->id];
+ foreach ($journal->transactiongroups()->get() as $group) {
+ foreach ($group->transactionjournals() as $jrnl) {
+ $exclude[] = $jrnl->id;
+ }
+ }
+ $exclude = array_unique($exclude);
+
+ $query = $this->getUser()->transactionjournals()
+ ->withRelevantData()
+ ->before($end)
+ ->after($start)
+ ->whereNotIn('id', $exclude)
+ ->where('description', 'LIKE', '%' . $query . '%')
+ ->get();
+
+ return $query;
}
}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/TransactionType.php b/app/lib/FireflyIII/Database/TransactionType.php
index 0022ec36fb..566c60ba45 100644
--- a/app/lib/FireflyIII/Database/TransactionType.php
+++ b/app/lib/FireflyIII/Database/TransactionType.php
@@ -3,41 +3,54 @@
namespace FireflyIII\Database;
-use Illuminate\Support\Collection;
-use LaravelBook\Ardent\Ardent;
use FireflyIII\Database\Ifaces\CommonDatabaseCalls;
use FireflyIII\Database\Ifaces\CUD;
use FireflyIII\Database\Ifaces\TransactionTypeInterface;
+use FireflyIII\Exception\FireflyException;
+use FireflyIII\Exception\NotImplementedException;
+use Illuminate\Support\Collection;
+
/**
* Class TransactionType
*
* @package FireflyIII\Database
*/
-class TransactionType implements TransactionTypeInterface, CUD, CommonDatabaseCalls
+class TransactionType implements CUD, CommonDatabaseCalls
{
/**
- * @param Ardent $model
+ * @param \Eloquent $model
*
* @return bool
*/
- public function destroy(Ardent $model)
+ public function destroy(\Eloquent $model)
{
// TODO: Implement destroy() method.
+ throw new NotImplementedException;
}
/**
- * Validates a model. Returns an array containing MessageBags
- * errors/warnings/successes.
+ * @param array $data
*
- * @param Ardent $model
- *
- * @return array
+ * @return \Eloquent
*/
- public function validateObject(Ardent $model)
+ public function store(array $data)
{
- // TODO: Implement validateObject() method.
+ // TODO: Implement store() method.
+ throw new NotImplementedException;
+ }
+
+ /**
+ * @param \Eloquent $model
+ * @param array $data
+ *
+ * @return bool
+ */
+ public function update(\Eloquent $model, array $data)
+ {
+ // TODO: Implement update() method.
+ throw new NotImplementedException;
}
/**
@@ -51,16 +64,7 @@ class TransactionType implements TransactionTypeInterface, CUD, CommonDatabaseCa
public function validate(array $model)
{
// TODO: Implement validate() method.
- }
-
- /**
- * @param array $data
- *
- * @return Ardent
- */
- public function store(array $data)
- {
- // TODO: Implement store() method.
+ throw new NotImplementedException;
}
/**
@@ -68,21 +72,12 @@ class TransactionType implements TransactionTypeInterface, CUD, CommonDatabaseCa
*
* @param int $id
*
- * @return Ardent
+ * @return \Eloquent
*/
public function find($id)
{
// TODO: Implement find() method.
- }
-
- /**
- * Returns all objects.
- *
- * @return Collection
- */
- public function get()
- {
- // TODO: Implement get() method.
+ throw new NotImplementedException;
}
/**
@@ -98,12 +93,32 @@ class TransactionType implements TransactionTypeInterface, CUD, CommonDatabaseCa
case 'opening':
return \TransactionType::whereType('Opening balance')->first();
break;
+ case 'transfer':
+ return \TransactionType::whereType('Transfer')->first();
+ break;
+ case 'withdrawal':
+ return \TransactionType::whereType('Withdrawal')->first();
+ break;
+ case 'deposit':
+ return \TransactionType::whereType('Deposit')->first();
+ break;
default:
throw new FireflyException('Cannot find transaction type described as "' . e($what) . '".');
break;
+
}
- return null;
+ }
+
+ /**
+ * Returns all objects.
+ *
+ * @return Collection
+ */
+ public function get()
+ {
+ // TODO: Implement get() method.
+ throw new NotImplementedException;
}
/**
@@ -114,16 +129,6 @@ class TransactionType implements TransactionTypeInterface, CUD, CommonDatabaseCa
public function getByIds(array $ids)
{
// TODO: Implement getByIds() method.
- }
-
- /**
- * @param Ardent $model
- * @param array $data
- *
- * @return bool
- */
- public function update(Ardent $model, array $data)
- {
- // TODO: Implement update() method.
+ throw new NotImplementedException;
}
}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Database/User.php b/app/lib/FireflyIII/Database/User.php
new file mode 100644
index 0000000000..e33ef42f4c
--- /dev/null
+++ b/app/lib/FireflyIII/Database/User.php
@@ -0,0 +1,73 @@
+first();
+ }
+
+ /**
+ * @param $reset
+ *
+ * @return null|User
+ */
+ public function findByReset($reset)
+ {
+ return \User::where('reset', $reset)->first();
+ }
+
+ /**
+ * @param array $data
+ *
+ * @return bool|\User
+ */
+ public function register(array $data)
+ {
+ $user = new \User;
+ $user->email = isset($data['email']) ? $data['email'] : null;
+ $user->migrated = 0;
+ $user->reset = \Str::random(32);
+ $user->password = \Hash::make(\Str::random(12));
+
+ if (!$user->save()) {
+ \Log::error('Invalid user with data: ' . isset($data['email']) ? $data['email'] : '(no email!)');
+ \Session::flash('error', 'Input invalid, please try again: ' . $user->getErrors()->first());
+
+ return false;
+ }
+ $user->save();
+
+ return $user;
+
+ }
+
+ /**
+ * @param \User $user
+ * @param $password
+ *
+ * @return bool
+ */
+ public function updatePassword(\User $user, $password)
+ {
+ $user->password = $password;
+ $user->forceSave();
+
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Event/Account.php b/app/lib/FireflyIII/Event/Account.php
new file mode 100644
index 0000000000..7b265b9816
--- /dev/null
+++ b/app/lib/FireflyIII/Event/Account.php
@@ -0,0 +1,39 @@
+id . '.latestBalance');
+ \Cache::forget('account.' . $account->id . '.lastActivityDate');
+ }
+
+ public function store(\Account $account)
+ {
+
+ \Cache::forget('account.' . $account->id . '.latestBalance');
+ \Cache::forget('account.' . $account->id . '.lastActivityDate');
+ }
+
+ /**
+ * @param Dispatcher $events
+ */
+ public function subscribe(Dispatcher $events)
+ {
+ // triggers when others are updated.
+ $events->listen('account.store', 'FireflyIII\Event\Account@store');
+ $events->listen('account.update', 'FireflyIII\Event\Account@update');
+ $events->listen('account.destroy', 'FireflyIII\Event\Account@destroy');
+ }
+
+ public function update(\Account $account)
+ {
+ \Cache::forget('account.' . $account->id . '.latestBalance');
+ \Cache::forget('account.' . $account->id . '.lastActivityDate');
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Event/Budget.php b/app/lib/FireflyIII/Event/Budget.php
new file mode 100644
index 0000000000..087d23c968
--- /dev/null
+++ b/app/lib/FireflyIII/Event/Budget.php
@@ -0,0 +1,62 @@
+startdate, $limit->repeat_freq, 0);
+ $end->subDay();
+
+ $set = $limit->limitrepetitions()->where('startdate', $limit->startdate->format('Y-m-d'))->where('enddate', $end->format('Y-m-d'))->get();
+ /*
+ * Create new LimitRepetition:
+ */
+ if ($set->count() == 0) {
+
+ $repetition = new \LimitRepetition();
+ $repetition->startdate = $limit->startdate;
+ $repetition->enddate = $end;
+ $repetition->amount = $limit->amount;
+ $repetition->limit()->associate($limit);
+
+ try {
+ $repetition->save();
+ } catch (QueryException $e) {
+ \Log::error('Trying to save new Limitrepetition failed!');
+ \Log::error($e->getMessage());
+ }
+ } else {
+ if ($set->count() == 1) {
+ /*
+ * Update existing one.
+ */
+ $repetition = $set->first();
+ $repetition->amount = $limit->amount;
+ $repetition->save();
+
+ }
+ }
+
+ }
+
+ /**
+ * @param Dispatcher $events
+ */
+ public function subscribe(Dispatcher $events)
+ {
+ $events->listen('limits.store', 'FireflyIII\Event\Budget@storeOrUpdateLimit');
+ $events->listen('limits.update', 'FireflyIII\Event\Budget@storeOrUpdateLimit');
+
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Event/Event.php b/app/lib/FireflyIII/Event/Event.php
new file mode 100644
index 0000000000..1f670ccb20
--- /dev/null
+++ b/app/lib/FireflyIII/Event/Event.php
@@ -0,0 +1,35 @@
+piggybanks()->get();
+
+ // get reminders for each
+ /** @var \Piggybank $piggyBank */
+ foreach ($piggies as $piggyBank) {
+ $reminders = $piggyBank->reminders()->get();
+ /** @var \Reminder $reminder */
+ foreach ($reminders as $reminder) {
+ $reminder->delete();
+ }
+ }
+ }
+
+
+ /**
+ * @param Dispatcher $events
+ */
+ public function subscribe(Dispatcher $events)
+ {
+ // triggers when others are updated.
+ $events->listen('account.destroy', 'FireflyIII\Event\Event@deleteAccount');
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Event/Piggybank.php b/app/lib/FireflyIII/Event/Piggybank.php
new file mode 100644
index 0000000000..05657efafb
--- /dev/null
+++ b/app/lib/FireflyIII/Event/Piggybank.php
@@ -0,0 +1,311 @@
+ 0) {
+ $event = new \PiggybankEvent;
+ $event->piggybank()->associate($piggybank);
+ $event->amount = floatval($amount);
+ $event->date = new Carbon;
+ if (!$event->isValid()) {
+ var_dump($event->getErrors());
+ exit();
+ }
+ $event->save();
+ }
+ }
+
+ public function destroyTransfer(\TransactionJournal $journal)
+ {
+ if ($journal->piggybankevents()->count() > 0) {
+
+ /** @var \FireflyIII\Database\Piggybank $repository */
+ $repository = \App::make('FireflyIII\Database\Piggybank');
+
+ /** @var \Piggybank $piggyBank */
+ $piggyBank = $journal->piggybankevents()->first()->piggybank()->first();
+
+ /** @var \PiggybankRepetition $repetition */
+ $repetition = $repository->findRepetitionByDate($piggyBank, $journal->date);
+
+ $relevantTransaction = null;
+ /** @var \Transaction $transaction */
+ foreach ($journal->transactions as $transaction) {
+ if ($transaction->account_id == $piggyBank->account_id) {
+ $relevantTransaction = $transaction;
+ }
+ }
+ if (is_null($relevantTransaction)) {
+ return;
+ }
+
+ $repetition->currentamount += floatval($relevantTransaction->amount * -1);
+ $repetition->save();
+
+
+ $event = new \PiggybankEvent;
+ $event->piggybank()->associate($piggyBank);
+ $event->amount = floatval($relevantTransaction->amount * -1);
+ $event->date = new Carbon;
+ if (!$event->isValid()) {
+ var_dump($event->getErrors());
+ exit();
+ }
+ $event->save();
+ }
+ }
+
+ /**
+ * @param \Piggybank $piggybank
+ * @param float $amount
+ */
+ public function removeMoney(\Piggybank $piggybank, $amount = 0.0)
+ {
+ $amount = $amount * -1;
+ if ($amount < 0) {
+ $event = new \PiggybankEvent;
+ $event->piggybank()->associate($piggybank);
+ $event->amount = floatval($amount);
+ $event->date = new Carbon;
+ if (!$event->isValid()) {
+ var_dump($event->getErrors());
+ exit();
+ }
+ $event->save();
+ }
+ }
+
+ public function storePiggybank(\Piggybank $piggybank)
+ {
+ if (intval($piggybank->repeats) == 0) {
+ $repetition = new \PiggybankRepetition;
+ $repetition->piggybank()->associate($piggybank);
+ $repetition->startdate = $piggybank->startdate;
+ $repetition->targetdate = $piggybank->targetdate;
+ $repetition->currentamount = 0;
+ $repetition->save();
+ }
+ }
+
+ /*
+ *
+ */
+
+ /**
+ * @param \TransactionJournal $journal
+ * @param int $piggybankId
+ */
+ public function storeTransfer(\TransactionJournal $journal, $piggybankId = 0)
+ {
+ if ($piggybankId == 0 || is_null($piggybankId)) {
+ return;
+ }
+ /** @var \FireflyIII\Database\Piggybank $repository */
+ $repository = \App::make('FireflyIII\Database\Piggybank');
+
+ /** @var \Piggybank $piggyBank */
+ $piggyBank = $repository->find($piggybankId);
+
+ /** @var \PiggybankRepetition $repetition */
+ $repetition = $repository->findRepetitionByDate($piggyBank, $journal->date);
+
+ \Log::debug(
+ 'Connecting transfer "' . $journal->description . '" (#' . $journal->id . ') to piggy bank "' . $piggyBank->name . '" (#' . $piggyBank->id . ').'
+ );
+
+ // some variables to double check the connection.
+ $start = $piggyBank->startdate;
+ $end = $piggyBank->targetdate;
+ $amount = floatval($piggyBank->targetamount);
+ $leftToSave = $amount - floatval($repetition->currentamount);
+ $relevantTransaction = null;
+ /** @var \Transaction $transaction */
+ foreach ($journal->transactions as $transaction) {
+ if ($transaction->account_id == $piggyBank->account_id) {
+ $relevantTransaction = $transaction;
+ }
+ }
+ if (is_null($relevantTransaction)) {
+ return;
+ }
+ \Log::debug('Relevant transaction is #' . $relevantTransaction->id . ' with amount ' . $relevantTransaction->amount);
+
+ // if FF3 should save this connection depends on some variables:
+ if ($start && $end && $journal->date >= $start && $journal->date <= $end) {
+ if ($relevantTransaction->amount < 0) { // amount removed from account, so removed from piggy bank.
+ \Log::debug('Remove from piggy bank.');
+ $continue = ($relevantTransaction->amount * -1 <= floatval($repetition->currentamount));
+ \Log::debug(
+ 'relevantTransaction.amount *-1 = ' . ($relevantTransaction->amount * -1) . ' >= current = ' . floatval($repetition->currentamount)
+ );
+ } else { // amount added
+ \Log::debug('Add from piggy bank.');
+ $continue = $relevantTransaction->amount <= $leftToSave;
+ }
+ if ($continue) {
+ \Log::debug('Update repetition.');
+ $repetition->currentamount += floatval($relevantTransaction->amount);
+ $repetition->save();
+
+ $event = new \PiggybankEvent;
+ $event->piggybank()->associate($piggyBank);
+ $event->transactionjournal()->associate($journal);
+ $event->amount = floatval($relevantTransaction->amount);
+ $event->date = new Carbon;
+ if (!$event->isValid()) {
+ var_dump($event->getErrors());
+ exit();
+ }
+ $event->save();
+ }
+ }
+ }
+
+ /**
+ * @param Dispatcher $events
+ */
+ public function subscribe(Dispatcher $events)
+ {
+ // triggers on piggy bank events:
+ $events->listen('piggybank.addMoney', 'FireflyIII\Event\Piggybank@addMoney');
+ $events->listen('piggybank.removeMoney', 'FireflyIII\Event\Piggybank@removeMoney');
+ $events->listen('piggybank.store', 'FireflyIII\Event\Piggybank@storePiggybank');
+ $events->listen('piggybank.update', 'FireflyIII\Event\Piggybank@updatePiggybank');
+
+ \App::before(
+ function ($request) {
+ $this->validateRepeatedExpenses();
+ }
+ );
+
+ //$events->listen('piggybank.boo', 'FireflyIII\Event\Piggybank@updatePiggybank');
+
+
+ // triggers when others are updated.
+ $events->listen('transactionJournal.store', 'FireflyIII\Event\Piggybank@storeTransfer');
+ $events->listen('transactionJournal.update', 'FireflyIII\Event\Piggybank@updateTransfer');
+ $events->listen('transactionJournal.destroy', 'FireflyIII\Event\Piggybank@destroyTransfer');
+ }
+
+ /**
+ * Validates the presence of repetitions for all repeated expenses!
+ */
+ public function validateRepeatedExpenses()
+ {
+ if(!\Auth::check()) {
+ return;
+ }
+ /** @var \FireflyIII\Database\RepeatedExpense $repository */
+ $repository = \App::make('FireflyIII\Database\RepeatedExpense');
+
+ $list = $repository->get();
+ $today = Carbon::now();
+
+ /** @var \Piggybank $entry */
+ foreach ($list as $entry) {
+ $start = $entry->startdate;
+ $target = $entry->targetdate;
+ // find a repetition on this date:
+ $count = $entry->piggybankrepetitions()->starts($start)->targets($target)->count();
+ if ($count == 0) {
+ $repetition = new \PiggybankRepetition;
+ $repetition->piggybank()->associate($entry);
+ $repetition->startdate = $start;
+ $repetition->targetdate = $target;
+ $repetition->currentamount = 0;
+ $repetition->save();
+ }
+ // then continue and do something in the current relevant timeframe.
+
+ $currentTarget = clone $target;
+ $currentStart = null;
+ while ($currentTarget < $today) {
+ $currentStart = \DateKit::subtractPeriod($currentTarget, $entry->rep_length, 0);
+ $currentTarget = \DateKit::addPeriod($currentTarget, $entry->rep_length, 0);
+ // create if not exists:
+ $count = $entry->piggybankrepetitions()->starts($currentStart)->targets($currentTarget)->count();
+ if ($count == 0) {
+ $repetition = new \PiggybankRepetition;
+ $repetition->piggybank()->associate($entry);
+ $repetition->startdate = $currentStart;
+ $repetition->targetdate = $currentTarget;
+ $repetition->currentamount = 0;
+ $repetition->save();
+ }
+
+ }
+ }
+ }
+
+ public function updatePiggybank(\Piggybank $piggyBank)
+ {
+ // get the repetition:
+ $repetition = $piggyBank->currentRelevantRep();
+ $repetition->startdate = $piggyBank->startdate;
+ $repetition->targetdate = $piggyBank->targetdate;
+ $repetition->save();
+ }
+
+ public function updateTransfer(\TransactionJournal $journal)
+ {
+
+ if ($journal->piggybankevents()->count() > 0) {
+
+ $event = $journal->piggybankevents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->first();
+ $eventSum = floatval($journal->piggybankevents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->sum('amount'));
+
+ /** @var \FireflyIII\Database\Piggybank $repository */
+ $repository = \App::make('FireflyIII\Database\Piggybank');
+
+ /** @var \Piggybank $piggyBank */
+ $piggyBank = $journal->piggybankevents()->first()->piggybank()->first();
+
+ /** @var \PiggybankRepetition $repetition */
+ $repetition = $repository->findRepetitionByDate($piggyBank, $journal->date);
+
+ $relevantTransaction = null;
+ /** @var \Transaction $transaction */
+ foreach ($journal->transactions as $transaction) {
+ if ($transaction->account_id == $piggyBank->account_id) {
+ $relevantTransaction = $transaction;
+ }
+ }
+ if (is_null($relevantTransaction)) {
+ return;
+ }
+
+ $diff = floatval($relevantTransaction->amount) - floatval($eventSum);
+ /*
+ * Create an event to remove /add the difference from the piggy
+ */
+ $repetition->currentamount += $diff;
+ $repetition->save();
+
+
+ $event = new \PiggybankEvent;
+ $event->piggybank()->associate($piggyBank);
+ $event->transactionJournal()->associate($journal);
+ $event->amount = $diff;
+ $event->date = new Carbon;
+ if (!$event->isValid()) {
+ var_dump($event->getErrors());
+ exit();
+ }
+ $event->save();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Event/Transaction.php b/app/lib/FireflyIII/Event/Transaction.php
new file mode 100644
index 0000000000..285e942875
--- /dev/null
+++ b/app/lib/FireflyIII/Event/Transaction.php
@@ -0,0 +1,38 @@
+account_id . '.latestBalance');
+ \Cache::forget('account.' . $transaction->account_id . '.lastActivityDate');
+ }
+
+ public function store(\Transaction $transaction)
+ {
+ \Cache::forget('account.' . $transaction->account_id . '.latestBalance');
+ \Cache::forget('account.' . $transaction->account_id . '.lastActivityDate');
+ }
+
+ /**
+ * @param Dispatcher $events
+ */
+ public function subscribe(Dispatcher $events)
+ {
+ // triggers when others are updated.
+ $events->listen('transaction.store', 'FireflyIII\Event\Transaction@store');
+ $events->listen('transaction.update', 'FireflyIII\Event\Transaction@update');
+ $events->listen('transaction.destroy', 'FireflyIII\Event\Transaction@destroy');
+ }
+
+ public function update(\Transaction $transaction)
+ {
+ \Cache::forget('account.' . $transaction->account_id . '.latestBalance');
+ \Cache::forget('account.' . $transaction->account_id . '.lastActivityDate');
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Event/TransactionJournal.php b/app/lib/FireflyIII/Event/TransactionJournal.php
new file mode 100644
index 0000000000..aabc4c0537
--- /dev/null
+++ b/app/lib/FireflyIII/Event/TransactionJournal.php
@@ -0,0 +1,46 @@
+get();
+
+
+ /** @var \RecurringTransaction $entry */
+ foreach ($set as $entry) {
+ $repository->scan($entry, $journal);
+ }
+ }
+
+ /**
+ * @param Dispatcher $events
+ */
+ public function subscribe(Dispatcher $events)
+ {
+ // triggers when others are updated.
+ $events->listen('transactionJournal.store', 'FireflyIII\Event\TransactionJournal@store');
+ $events->listen('transactionJournal.update', 'FireflyIII\Event\TransactionJournal@update');
+ }
+
+ public function update(\TransactionJournal $journal)
+ {
+ /** @var \FireflyIII\Database\Recurring $repository */
+ $repository = \App::make('FireflyIII\Database\Recurring');
+ $set = $repository->get();
+ $journal->recurring_transaction_id = null;
+ $journal->save();
+
+ /** @var \RecurringTransaction $entry */
+ foreach ($set as $entry) {
+ $repository->scan($entry, $journal);
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Exception/FireflyException.php b/app/lib/FireflyIII/Exception/FireflyException.php
new file mode 100644
index 0000000000..69890ddfc4
--- /dev/null
+++ b/app/lib/FireflyIII/Exception/FireflyException.php
@@ -0,0 +1,14 @@
+app->validator->resolver(
+ function ($translator, $data, $rules, $messages) {
+ return new FireflyValidator($translator, $data, $rules, $messages);
+ }
+ );
+ }
+
+ /**
+ * Return the services bla bla.
+ *
+ * @return array
+ */
+ public function provides()
+ {
+ return ['reminders', 'filters', 'datekit', 'navigation'];
+ }
+
+ /**
+ * Triggered automatically by Laravel
+ */
+ public function register()
+ {
+ // FORMAT:
+ #$this->app->bind('Interface', 'Class');
+
+ $this->app->bind(
+ 'reminders', function () {
+ return new Reminders;
+ }
+ );
+ $this->app->bind(
+ 'filter', function () {
+ return new Filter;
+ }
+ );
+ $this->app->bind(
+ 'datekit', function () {
+ return new Date;
+ }
+ );
+ $this->app->bind(
+ 'navigation', function () {
+ return new Navigation;
+ }
+ );
+ $this->app->bind(
+ 'ffform', function () {
+ return new Form;
+ }
+ );
+
+ /*
+ * For models, various stuff:
+ */
+ $this->app->bind(
+ 'steam', function () {
+ return new Steam;
+ }
+ );
+
+ // preferences:
+ $this->app->bind('FireflyIII\Shared\Preferences\PreferencesInterface', 'FireflyIII\Shared\Preferences\Preferences');
+
+ // registration and user mail:
+ $this->app->bind('FireflyIII\Shared\Mail\RegistrationInterface', 'FireflyIII\Shared\Mail\Registration');
+
+ // Shortcut so developers don't need to add an Alias in app/config/app.php
+ $this->app->booting(
+ function () {
+ $loader = AliasLoader::getInstance();
+ $loader->alias('Reminders', 'FireflyIII\Shared\Facade\Reminders');
+ $loader->alias('Filter', 'FireflyIII\Shared\Facade\Filter');
+ $loader->alias('DateKit', 'FireflyIII\Shared\Facade\DateKit');
+ $loader->alias('Navigation', 'FireflyIII\Shared\Facade\Navigation');
+ $loader->alias('FFForm', 'FireflyIII\Shared\Facade\FFForm');
+ $loader->alias('Steam', 'FireflyIII\Shared\Facade\Steam');
+ }
+ );
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Form/Form.php b/app/lib/FireflyIII/Form/Form.php
new file mode 100644
index 0000000000..7388523742
--- /dev/null
+++ b/app/lib/FireflyIII/Form/Form.php
@@ -0,0 +1,383 @@
+has($name)):
+ $classes = 'form-group has-error has-feedback';
+ break;
+ case (!is_null($warnings) && $warnings->has($name)):
+ $classes = 'form-group has-warning has-feedback';
+ break;
+ case (!is_null($successes) && $successes->has($name)):
+ $classes = 'form-group has-success has-feedback';
+ break;
+ default:
+ $classes = 'form-group';
+ break;
+ }
+
+ /*
+ * Add some HTML.
+ */
+ $html = '';
+ $html .= '
' . $label . ' ';
+ $html .= '
';
+
+
+ /*
+ * Switch input type:
+ */
+ unset($options['label']);
+ switch ($type) {
+ case 'text':
+ $html .= \Form::input('text', $name, $value, $options);
+ break;
+ case 'amount':
+ $html .= '
';
+ break;
+ case 'number':
+ $html .= \Form::input('number', $name, $value, $options);
+ break;
+ case 'checkbox':
+ $checked = $options['checked'];
+ unset($options['placeholder'], $options['autocomplete'], $options['class']);
+ $html .= '
';
+ $html .= \Form::checkbox($name, $value, $checked, $options);
+ $html .= '
';
+
+
+ break;
+ case 'date':
+ $html .= \Form::input('date', $name, $value, $options);
+ break;
+ case 'select':
+ $html .= \Form::select($name, $list, $value, $options);
+ break;
+ default:
+ throw new FireflyException('Cannot handle type "' . $type . '" in FFFormBuilder.');
+ break;
+ }
+
+ /*
+ * If errors, respond to them:
+ */
+
+ if (!is_null($errors)) {
+ if ($errors->has($name)) {
+ $html .= '
';
+ $html .= '
' . e($errors->first($name)) . '
';
+ }
+ }
+ unset($errors);
+ /*
+ * If warnings, respond to them:
+ */
+
+ if (!is_null($warnings)) {
+ if ($warnings->has($name)) {
+ $html .= '
';
+ $html .= '
' . e($warnings->first($name)) . '
';
+ }
+ }
+ unset($warnings);
+
+ /*
+ * If successes, respond to them:
+ */
+
+ if (!is_null($successes)) {
+ if ($successes->has($name)) {
+ $html .= '
';
+ $html .= '
' . e($successes->first($name)) . '
';
+ }
+ }
+ unset($successes);
+
+ $html .= '
';
+ $html .= '
';
+
+ return $html;
+
+ }
+
+ /**
+ * @param $name
+ * @param $options
+ *
+ * @return string
+ */
+ public static function label($name, $options)
+ {
+ if (isset($options['label'])) {
+ return $options['label'];
+ }
+ $labels = ['amount_min' => 'Amount (min)', 'amount_max' => 'Amount (max)', 'match' => 'Matches on', 'repeat_freq' => 'Repetition',
+ 'account_from_id' => 'Account from', 'account_to_id' => 'Account to', 'account_id' => 'Asset account'];
+
+ return isset($labels[$name]) ? $labels[$name] : str_replace('_', ' ', ucfirst($name));
+
+ }
+
+ /**
+ * @param $name
+ * @param null $value
+ * @param array $options
+ *
+ * @return string
+ * @throws FireflyException
+ */
+ public static function ffBalance($name, $value = null, array $options = [])
+ {
+ $options['step'] = 'any';
+
+ return self::ffInput('amount', $name, $value, $options);
+
+ }
+
+ /**
+ * @param $name
+ * @param int $value
+ * @param null $checked
+ * @param array $options
+ *
+ * @return string
+ * @throws FireflyException
+ */
+ public static function ffCheckbox($name, $value = 1, $checked = null, $options = [])
+ {
+ $options['checked'] = $checked === true ? true : null;
+
+ return self::ffInput('checkbox', $name, $value, $options);
+ }
+
+ /**
+ * @param $name
+ * @param null $value
+ * @param array $options
+ *
+ * @return string
+ * @throws FireflyException
+ */
+ public static function ffDate($name, $value = null, array $options = [])
+ {
+ return self::ffInput('date', $name, $value, $options);
+ }
+
+ /**
+ * @param $name
+ * @param null $value
+ * @param array $options
+ *
+ * @return string
+ * @throws FireflyException
+ */
+ public static function ffInteger($name, $value = null, array $options = [])
+ {
+ $options['step'] = '1';
+
+ return self::ffInput('number', $name, $value, $options);
+
+ }
+
+ /**
+ * Return buttons for update/validate/return.
+ *
+ * @param $type
+ * @param $name
+ *
+ * @return string
+ * @throws FireflyException
+ */
+ public static function ffOptionsList($type, $name)
+ {
+ $previousValue = \Input::old('post_submit_action');
+ $previousValue = is_null($previousValue) ? 'store' : $previousValue;
+ /*
+ * Store.
+ */
+ $store = '';
+ switch ($type) {
+ case 'create':
+ $store = '';
+ break;
+ case 'update':
+ $store = '';
+ break;
+ default:
+ throw new FireflyException('Cannot create ffOptionsList for option (store) ' . $type);
+ break;
+ }
+
+ /*
+ * validate is always the same:
+ */
+ $validate = '';
+
+ /*
+ * Store & return:
+ */
+ switch ($type) {
+ case 'create':
+ $return = '';
+ break;
+ case 'update':
+ $return = '';
+ break;
+ default:
+ throw new FireflyException('Cannot create ffOptionsList for option (store+return) ' . $type);
+ break;
+ }
+
+ return $store . $validate . $return;
+ }
+
+ /**
+ * @param $name
+ * @param array $list
+ * @param null $selected
+ * @param array $options
+ *
+ * @return string
+ * @throws FireflyException
+ */
+ public static function ffSelect($name, array $list = [], $selected = null, array $options = [])
+ {
+ return self::ffInput('select', $name, $selected, $options, $list);
+ }
+
+ /**
+ * @param $name
+ * @param null $value
+ * @param array $options
+ *
+ * @return string
+ * @throws FireflyException
+ */
+ public static function ffTags($name, $value = null, array $options = [])
+ {
+ $options['data-role'] = 'tagsinput';
+
+ return self::ffInput('text', $name, $value, $options);
+ }
+
+ /**
+ * @param $name
+ * @param null $value
+ * @param array $options
+ *
+ * @return string
+ * @throws FireflyException
+ */
+ public static function ffText($name, $value = null, array $options = [])
+ {
+ return self::ffInput('text', $name, $value, $options);
+
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Search/Search.php b/app/lib/FireflyIII/Search/Search.php
new file mode 100644
index 0000000000..6af5a92c15
--- /dev/null
+++ b/app/lib/FireflyIII/Search/Search.php
@@ -0,0 +1,101 @@
+accounts()->with('accounttype')->where(
+ function ($q) use ($words) {
+ foreach ($words as $word) {
+ $q->orWhere('name', 'LIKE', '%' . e($word) . '%');
+ }
+ }
+ )->get();
+ }
+
+ /**
+ * @param array $words
+ *
+ * @return Collection
+ */
+ public function searchBudgets(array $words)
+ {
+ /** @var Collection $set */
+ $set = \Auth::user()->budgets()->get();
+ $newSet = $set->filter(
+ function (\Budget $b) use ($words) {
+ $found = 0;
+ foreach ($words as $word) {
+ if (!(strpos(strtolower($b->name), strtolower($word)) === false)) {
+ $found++;
+ }
+ }
+
+ return $found > 0;
+ }
+ );
+
+ return $newSet;
+ }
+
+ /**
+ * @param array $words
+ *
+ * @return Collection
+ */
+ public function searchCategories(array $words)
+ {
+ /** @var Collection $set */
+ $set = \Auth::user()->categories()->get();
+ $newSet = $set->filter(
+ function (\Category $c) use ($words) {
+ $found = 0;
+ foreach ($words as $word) {
+ if (!(strpos(strtolower($c->name), strtolower($word)) === false)) {
+ $found++;
+ }
+ }
+
+ return $found > 0;
+ }
+ );
+
+ return $newSet;
+ }
+
+ /**
+ * @param array $words
+ *
+ * @return Collection
+ */
+ public function searchTags(array $words)
+ {
+ return new Collection;
+ }
+
+ /**
+ * @param array $words
+ *
+ * @return Collection
+ */
+ public function searchTransactions(array $words)
+ {
+ return \Auth::user()->transactionjournals()->withRelevantData()->where(
+ function ($q) use ($words) {
+ foreach ($words as $word) {
+ $q->orWhere('description', 'LIKE', '%' . e($word) . '%');
+ }
+ }
+ )->get();
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Shared/Facade/DateKit.php b/app/lib/FireflyIII/Shared/Facade/DateKit.php
new file mode 100644
index 0000000000..387d3c7372
--- /dev/null
+++ b/app/lib/FireflyIII/Shared/Facade/DateKit.php
@@ -0,0 +1,16 @@
+ intval(\Input::get('start')),
- 'length' => $length,
- 'draw' => intval(\Input::get('draw')),
- ];
-
-
- /*
- * Columns:
- */
- if (!is_null(\Input::get('columns')) && is_array(\Input::get('columns'))) {
- foreach (\Input::get('columns') as $column) {
- $parameters['columns'][] = [
- 'data' => $column['data'],
- 'name' => $column['name'],
- 'searchable' => $column['searchable'] == 'true' ? true : false,
- 'orderable' => $column['orderable'] == 'true' ? true : false,
- 'search' => [
- 'value' => $column['search']['value'],
- 'regex' => $column['search']['regex'] == 'true' ? true : false,
- ]
- ];
- }
- }
-
-
- /*
- * Sorting.
- */
- $parameters['orderOnAccount'] = false;
- if (!is_null(\Input::get('order')) && is_array(\Input::get('order'))) {
- foreach (\Input::get('order') as $order) {
- $columnIndex = intval($order['column']);
- $columnName = $parameters['columns'][$columnIndex]['name'];
- $parameters['order'][] = [
- 'name' => $columnName,
- 'dir' => strtoupper($order['dir'])
- ];
- if ($columnName == 'to' || $columnName == 'from') {
- $parameters['orderOnAccount'] = true;
- }
- }
- }
- /*
- * Search parameters:
- */
- $parameters['search'] = [
- 'value' => '',
- 'regex' => false
- ];
- if (!is_null(\Input::get('search')) && is_array(\Input::get('search'))) {
- $search = \Input::get('search');
- $parameters['search'] = [
- 'value' => $search['value'],
- 'regex' => $search['regex'] == 'true' ? true : false
- ];
- }
- return $parameters;
- }
-}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Shared/Mail/Registration.php b/app/lib/FireflyIII/Shared/Mail/Registration.php
new file mode 100644
index 0000000000..eecfd4a135
--- /dev/null
+++ b/app/lib/FireflyIII/Shared/Mail/Registration.php
@@ -0,0 +1,80 @@
+password = $password;
+ $user->reset = \Str::random(32); // new one.
+ $user->forceSave();
+ $email = $user->email;
+
+
+ $data = ['password' => $password];
+ try {
+ \Mail::send(
+ ['emails.user.register-html', 'emails.user.register-text'], $data, function ($message) use ($email) {
+ $message->to($email, $email)->subject('Welcome to Firefly!');
+ }
+ );
+ } catch(Swift_RfcComplianceException $e) {}
+ }
+
+ /**
+ * @param \User $user
+ *
+ * @return mixed|void
+ */
+ public function sendResetVerification(\User $user)
+ {
+ $reset = \Str::random(32);
+ $user->reset = $reset;
+ $user->forceSave();
+ $email = $user->email;
+
+ $data = ['reset' => $reset];
+ \Mail::send(
+ ['emails.user.remindme-html', 'emails.user.remindme-text'], $data, function ($message) use ($email) {
+ $message->to($email, $email)->subject('Forgot your password?');
+ }
+ );
+
+
+ }
+
+ /**
+ * @param \User $user
+ *
+ * @return mixed|void
+ */
+ public function sendVerificationMail(\User $user)
+ {
+
+ $reset = \Str::random(32);
+ $user->reset = $reset;
+ $user->forceSave();
+ $email = $user->email;
+ $data = ['reset' => $reset];
+
+ \Mail::send(
+ ['emails.user.verify-html', 'emails.user.verify-text'], $data, function ($message) use ($email) {
+ $message->to($email, $email)->subject('Verify your e-mail address.');
+ }
+ );
+ }
+
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Shared/Mail/RegistrationInterface.php b/app/lib/FireflyIII/Shared/Mail/RegistrationInterface.php
new file mode 100644
index 0000000000..0741757b4e
--- /dev/null
+++ b/app/lib/FireflyIII/Shared/Mail/RegistrationInterface.php
@@ -0,0 +1,34 @@
+mapData((array)$attributes)->newInstance([], true);
+ $instance->setRawAttributes((array)$attributes, true);
+
+ return $instance;
+ }
+
+ /**
+ *
+ * instead of using $this->newInstance(), call
+ * newInstance() on the object from mapData
+ *
+ * @param bool $excludeDeleted
+ *
+ * @return \Illuminate\Database\Eloquent\Builder|static
+ */
+ public function newQuery($excludeDeleted = true)
+ {
+ // If using Laravel 4.0.x then use the following commented version of this command
+ // $builder = new Builder($this->newBaseQueryBuilder());
+ // newEloquentBuilder() was added in 4.1
+ $builder = $this->newEloquentBuilder($this->newBaseQueryBuilder());
+
+ // Once Firefly has the query builders, it will set the model instances so the
+ // builder can easily access any information it may need from the model
+ // while it is constructing and executing various queries against it.
+ $builder->setModel($this)->with($this->with);
+
+ if ($excludeDeleted && $this->softDelete) {
+ $builder->whereNull($this->getQualifiedDeletedAtColumn());
+ }
+
+ if ($this->subclassField && $this->isSubclass()) {
+ $builder->where($this->subclassField, '=', get_class($this));
+ }
+
+ return $builder;
+ }
+
+ /**
+ * ensure that the subclass field is assigned on save
+ *
+ * @param array $rules
+ * @param array $customMessages
+ * @param array $options
+ * @param callable $beforeSave
+ * @param callable $afterSave
+ *
+ * @return bool
+ */
+ public function save(
+ array $rules = [], array $customMessages = [], array $options = [], \Closure $beforeSave = null, \Closure $afterSave = null
+ ) {
+ if ($this->subclassField) {
+ $this->attributes[$this->subclassField] = get_class($this);
+ }
+
+ return parent::save($rules, $customMessages, $options, $beforeSave, $afterSave);
+ }
+
+ /**
+ * if no subclass is defined, function as normal
+ *
+ * @param array $attributes
+ *
+ * @return \Illuminate\Database\Eloquent\Model|static
+ */
+ public function mapData(array $attributes)
+ {
+ if (!$this->subclassField) {
+ return $this->newInstance();
+ }
+
+ return new $attributes[$this->subclassField];
+ }
+
+ /**
+ * @return bool
+ */
+ public function isSubclass()
+ {
+ return $this->isSubclass;
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Shared/Toolkit/Date.php b/app/lib/FireflyIII/Shared/Toolkit/Date.php
index 1abf90e321..90152551ae 100644
--- a/app/lib/FireflyIII/Shared/Toolkit/Date.php
+++ b/app/lib/FireflyIII/Shared/Toolkit/Date.php
@@ -3,7 +3,7 @@
namespace FireflyIII\Shared\Toolkit;
use Carbon\Carbon;
-use Firefly\Exception\FireflyException;
+use FireflyIII\Exception\FireflyException;
/**
* Class Date
@@ -13,49 +13,17 @@ use Firefly\Exception\FireflyException;
class Date
{
/**
- * @param Carbon $currentEnd
- * @param $repeatFreq
- *
- * @throws FireflyException
- */
- public function endOfPeriod(Carbon $currentEnd, $repeatFreq)
- {
- switch ($repeatFreq) {
- default:
- throw new FireflyException('Cannot do endOfPeriod for $repeat_freq ' . $repeatFreq);
- break;
- case 'daily':
- $currentEnd->addDay();
- break;
- case 'weekly':
- $currentEnd->addWeek()->subDay();
- break;
- case 'monthly':
- $currentEnd->addMonth()->subDay();
- break;
- case 'quarterly':
- $currentEnd->addMonths(3)->subDay();
- break;
- case 'half-year':
- $currentEnd->addMonths(6)->subDay();
- break;
- case 'yearly':
- $currentEnd->addYear()->subDay();
- break;
- }
- }
-
- /**
- * @param Carbon $date
+ * @param Carbon $theDate
* @param $repeatFreq
* @param $skip
*
* @return Carbon
* @throws FireflyException
*/
- public function addPeriod(Carbon $date, $repeatFreq, $skip)
+ public function addPeriod(Carbon $theDate, $repeatFreq, $skip)
{
- $add = ($skip + 1);
+ $date = clone $theDate;
+ $add = ($skip + 1);
switch ($repeatFreq) {
default:
throw new FireflyException('Cannot do addPeriod for $repeat_freq ' . $repeatFreq);
@@ -63,12 +31,15 @@ class Date
case 'daily':
$date->addDays($add);
break;
+ case 'week':
case 'weekly':
$date->addWeeks($add);
break;
+ case 'month':
case 'monthly':
$date->addMonths($add);
break;
+ case 'quarter':
case 'quarterly':
$months = $add * 3;
$date->addMonths($months);
@@ -77,10 +48,213 @@ class Date
$months = $add * 6;
$date->addMonths($months);
break;
+ case 'year':
case 'yearly':
$date->addYears($add);
break;
}
+
return $date;
}
-}
\ No newline at end of file
+
+ /**
+ * @param Carbon $theCurrentEnd
+ * @param $repeatFreq
+ *
+ * @return mixed
+ * @throws FireflyException
+ */
+ public function endOfPeriod(Carbon $theCurrentEnd, $repeatFreq)
+ {
+ $currentEnd = clone $theCurrentEnd;
+ switch ($repeatFreq) {
+ default:
+ throw new FireflyException('Cannot do endOfPeriod for $repeat_freq ' . $repeatFreq);
+ break;
+ case 'daily':
+ $currentEnd->addDay();
+ break;
+ case 'week':
+ case 'weekly':
+ $currentEnd->addWeek()->subDay();
+ break;
+ case 'month':
+ case 'monthly':
+ $currentEnd->addMonth()->subDay();
+ break;
+ case 'quarter':
+ case 'quarterly':
+ $currentEnd->addMonths(3)->subDay();
+ break;
+ case 'half-year':
+ $currentEnd->addMonths(6)->subDay();
+ break;
+ case 'year':
+ case 'yearly':
+ $currentEnd->addYear()->subDay();
+ break;
+ }
+
+ return $currentEnd;
+ }
+
+ /**
+ * @param Carbon $theCurrentEnd
+ * @param $repeatFreq
+ *
+ * @return mixed
+ * @throws FireflyException
+ */
+ public function endOfX(Carbon $theCurrentEnd, $repeatFreq)
+ {
+ $currentEnd = clone $theCurrentEnd;
+ switch ($repeatFreq) {
+ default:
+ throw new FireflyException('Cannot do endOfPeriod for $repeat_freq ' . $repeatFreq);
+ break;
+ case 'daily':
+ $currentEnd->endOfDay();
+ break;
+ case 'week':
+ case 'weekly':
+ $currentEnd->endOfWeek();
+ break;
+ case 'month':
+ case 'monthly':
+ $currentEnd->endOfMonth();
+ break;
+ case 'quarter':
+ case 'quarterly':
+ $currentEnd->lastOfQuarter();
+ break;
+ case 'half-year':
+ $month = intval($theCurrentEnd->format('m'));
+ $currentEnd->endOfYear();
+ if($month <= 6) {
+ $currentEnd->subMonths(6);
+ }
+ break;
+ case 'year':
+ case 'yearly':
+ $currentEnd->endOfYear();
+ break;
+ }
+
+ return $currentEnd;
+ }
+
+ public function periodShow(Carbon $date, $repeatFrequency)
+ {
+ switch ($repeatFrequency) {
+ default:
+ throw new FireflyException('No date formats for frequency "' . $repeatFrequency . '"!');
+ break;
+ case 'daily':
+ return $date->format('j F Y');
+ break;
+ case 'week':
+ case 'weekly':
+ return $date->format('\W\e\e\k W, Y');
+ break;
+ case 'quarter':
+ return $date->format('F Y');
+ break;
+ case 'monthly':
+ case 'month':
+ return $date->format('F Y');
+ break;
+ case 'year':
+ case 'yearly':
+ return $date->format('Y');
+ break;
+ }
+ }
+
+ /**
+ * @param Carbon $theDate
+ * @param $repeatFreq
+ *
+ * @return Carbon
+ * @throws FireflyException
+ */
+ public function startOfPeriod(Carbon $theDate, $repeatFreq)
+ {
+ $date = clone $theDate;
+ switch ($repeatFreq) {
+ default:
+ throw new FireflyException('Cannot do startOfPeriod for $repeat_freq ' . $repeatFreq);
+ break;
+ case 'daily':
+ $date->startOfDay();
+ break;
+ case 'week':
+ case 'weekly':
+ $date->startOfWeek();
+ break;
+ case 'month':
+ case 'monthly':
+ $date->startOfMonth();
+ break;
+ case 'quarter':
+ case 'quarterly':
+ $date->firstOfQuarter();
+ break;
+ case 'half-year':
+ $month = intval($date->format('m'));
+ $date->startOfYear();
+ if ($month >= 7) {
+ $date->addMonths(6);
+ }
+ break;
+ case 'year':
+ case 'yearly':
+ $date->startOfYear();
+ break;
+ }
+
+ return $date;
+ }
+
+ /**
+ * @param Carbon $date
+ * @param $repeatFreq
+ * @param int $subtract
+ *
+ * @return Carbon
+ * @throws FireflyException
+ */
+ public function subtractPeriod(Carbon $theDate, $repeatFreq, $subtract = 1)
+ {
+ $date = clone $theDate;
+ switch ($repeatFreq) {
+ default:
+ throw new FireflyException('Cannot do subtractPeriod for $repeat_freq ' . $repeatFreq);
+ break;
+ case 'daily':
+ $date->subDays($subtract);
+ break;
+ case 'weekly':
+ $date->subWeeks($subtract);
+ break;
+ case 'monthly':
+ $date->subMonths($subtract);
+ break;
+ case 'quarter':
+ case 'quarterly':
+ $months = $subtract * 3;
+ $date->subMonths($months);
+ break;
+ case 'half-year':
+ $months = $subtract * 6;
+ $date->subMonths($months);
+ break;
+ case 'year':
+ case 'yearly':
+ $date->subYears($subtract);
+ break;
+ }
+
+ return $date;
+ }
+}
+
diff --git a/app/lib/FireflyIII/Shared/Toolkit/Filter.php b/app/lib/FireflyIII/Shared/Toolkit/Filter.php
new file mode 100644
index 0000000000..f9051252d2
--- /dev/null
+++ b/app/lib/FireflyIII/Shared/Toolkit/Filter.php
@@ -0,0 +1,296 @@
+setSessionRangeValue();
+ $start = \Session::has('start') ? \Session::get('start') : new Carbon;
+
+ /*
+ * Force start date to at the start of the $range.
+ * Ie. the start of the week, month, year. This also to protect against nefarious users
+ * who change their session data (I just wanted to use the word "nefarious").
+ */
+ $start = $this->updateStartDate($range, $start);
+
+ /*
+ * Force end date to at the END of the $range. Always based on $start.
+ * Ie. the END of the week, month, year.
+ */
+ $end = $this->updateEndDate($range, $start);
+ #\Log::debug('After update, session end is : ' . $end->format('Y-m-d'));
+
+ /*
+ * get the name of the month, depending on the range. Purely for astetics
+ */
+ $period = $this->periodName($range, $start);
+
+ /*
+ * Get the date for the previous and next period.
+ * Ie. next week, next month, etc.
+ */
+ $prev = $this->previous($range, clone $start);
+ $next = $this->next($range, clone $start);
+
+ /*
+ * Save everything in the session:
+ */
+ \Session::put('start', $start);
+ \Session::put('end', $end);
+ \Session::put('range', $range);
+ \Session::put('period', $period);
+ \Session::put('prev', $this->periodName($range, $prev));
+ \Session::put('next', $this->periodName($range, $next));
+
+ return null;
+
+ }
+
+ /**
+ * Checks and sets the currently set 'range' or defaults to a session
+ * and if that fails, defaults to 1M. Always returns the final value.
+ *
+ * @return string
+ */
+ public function setSessionRangeValue()
+ {
+ if (!is_null(\Session::get('range'))) {
+ $range = \Session::get('range');
+ } else {
+ /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */
+ $preferences = \App::make('FireflyIII\Shared\Preferences\PreferencesInterface');
+ $viewRange = $preferences->get('viewRange', '1M');
+
+ // default range:
+ $range = $viewRange->data;
+ \Session::put('range', $range);
+ }
+
+ return $range;
+
+ }
+
+ /**
+ * @param $range
+ * @param Carbon $start
+ *
+ * @return Carbon
+ * @throws FireflyException
+ */
+ protected function updateStartDate($range, Carbon $start)
+ {
+ switch ($range) {
+ default:
+ throw new FireflyException('updateStartDate cannot handle $range ' . $range);
+ break;
+ case '1D':
+ $start->startOfDay();
+ break;
+ case '1W':
+ $start->startOfWeek();
+ break;
+ case '1M':
+ $start->startOfMonth();
+ break;
+ case '3M':
+ $start->firstOfQuarter();
+ break;
+ case '6M':
+ if (intval($start->format('m')) >= 7) {
+ $start->startOfYear()->addMonths(6);
+ } else {
+ $start->startOfYear();
+ }
+ break;
+ case '1Y':
+ $start->startOfYear();
+ break;
+ }
+
+ return $start;
+
+ }
+
+ /**
+ * @param $range
+ * @param Carbon $start
+ *
+ * @return Carbon
+ * @throws FireflyException
+ */
+ protected function updateEndDate($range, Carbon $start)
+ {
+ $end = clone $start;
+ switch ($range) {
+ default:
+ throw new FireflyException('updateEndDate cannot handle $range ' . $range);
+ break;
+ case '1D':
+ $end->endOfDay();
+ break;
+ case '1W':
+ $end->endOfWeek();
+ break;
+ case '1M':
+ $end->endOfMonth();
+ break;
+ case '3M':
+ $end->lastOfQuarter();
+ break;
+ case '6M':
+ if (intval($start->format('m')) >= 7) {
+ $end->endOfYear();
+ } else {
+ $end->startOfYear()->addMonths(6);
+ }
+ break;
+ case '1Y':
+ $end->endOfYear();
+ break;
+
+ }
+
+ return $end;
+ }
+
+ /**
+ * @param $range
+ * @param Carbon $date
+ *
+ * @return string
+ * @throws FireflyException
+ */
+ protected function periodName($range, Carbon $date)
+ {
+ switch ($range) {
+ default:
+ throw new FireflyException('No _periodName() for range "' . $range . '"');
+ break;
+ case '1D':
+ return $date->format('jS F Y');
+ break;
+ case '1W':
+ return 'week ' . $date->format('W, Y');
+ break;
+ case '1M':
+ return $date->format('F Y');
+ break;
+ case '3M':
+ $month = intval($date->format('m'));
+
+ return 'Q' . ceil(($month / 12) * 4) . ' ' . $date->format('Y');
+ break;
+ case '6M':
+ $month = intval($date->format('m'));
+ $half = ceil(($month / 12) * 2);
+ $halfName = $half == 1 ? 'first' : 'second';
+
+ return $halfName . ' half of ' . $date->format('d-m-Y');
+ break;
+ case '1Y':
+ return $date->format('Y');
+ break;
+
+
+ }
+ }
+
+ /**
+ * @param $range
+ * @param Carbon $date
+ *
+ * @return Carbon
+ * @throws FireflyException
+ */
+ public function previous($range, Carbon $date)
+ {
+ switch ($range) {
+ default:
+ throw new FireflyException('Cannot do _previous() on ' . $range);
+ break;
+ case '1D':
+ $date->startOfDay()->subDay();
+ break;
+ case '1W':
+ $date->startOfWeek()->subWeek();
+ break;
+ case '1M':
+ $date->startOfMonth()->subMonth();
+ break;
+ case '3M':
+ $date->firstOfQuarter()->subMonths(3)->firstOfQuarter();
+ break;
+ case '6M':
+ $month = intval($date->format('m'));
+ if ($month <= 6) {
+ $date->startOfYear()->subMonths(6);
+ } else {
+ $date->startOfYear();
+ }
+ break;
+ case '1Y':
+ $date->startOfYear()->subYear();
+ break;
+
+ }
+
+ return $date;
+ }
+
+ /**
+ * @param $range
+ * @param Carbon $date
+ *
+ * @return Carbon
+ * @throws FireflyException
+ */
+ public function next($range, Carbon $date)
+ {
+ switch ($range) {
+ case '1D':
+ $date->endOfDay()->addDay();
+ break;
+ case '1W':
+ $date->endOfWeek()->addDay()->startOfWeek();
+ break;
+ case '1M':
+ $date->endOfMonth()->addDay()->startOfMonth();
+ break;
+ case '3M':
+ $date->lastOfQuarter()->addDay();
+ break;
+ case '6M':
+ if (intval($date->format('m')) >= 7) {
+ $date->startOfYear()->addYear();
+ } else {
+ $date->startOfYear()->addMonths(6);
+ }
+ break;
+ case '1Y':
+ $date->startOfYear()->addYear();
+ break;
+ default:
+ throw new FireflyException('Cannot do _next() on ' . $range);
+ break;
+ }
+
+ return $date;
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Shared/Toolkit/Form.php b/app/lib/FireflyIII/Shared/Toolkit/Form.php
index 7383a0e7a2..2fa690a427 100644
--- a/app/lib/FireflyIII/Shared/Toolkit/Form.php
+++ b/app/lib/FireflyIII/Shared/Toolkit/Form.php
@@ -9,12 +9,13 @@ use Illuminate\Support\Collection;
*
* @package FireflyIII\Shared\Toolkit
*/
-class Form {
+class Form
+{
/**
* Takes any collection and tries to make a sensible select list compatible array of it.
*
* @param Collection $set
- * @param null $titleField
+ * @param null $titleField
*
* @return mixed
*/
@@ -44,6 +45,7 @@ class Form {
}
$selectList[$id] = $title;
}
+
return $selectList;
}
diff --git a/app/lib/FireflyIII/Shared/Toolkit/Navigation.php b/app/lib/FireflyIII/Shared/Toolkit/Navigation.php
new file mode 100644
index 0000000000..701bfead28
--- /dev/null
+++ b/app/lib/FireflyIII/Shared/Toolkit/Navigation.php
@@ -0,0 +1,67 @@
+setSessionRangeValue();
+ $start = \Session::get('start');
+
+ /*
+ * Add some period to $start.
+ */
+ $next = $filter->next($range, clone $start);
+
+ /*
+ * Save in session:
+ */
+ \Session::put('start', $next);
+
+ return true;
+ }
+
+ /**
+ * @return bool
+ * @throws FireflyException
+ */
+ public function prev()
+ {
+ /*
+ * Get the start date and the range from the session
+ */
+ $filter = new Filter;
+
+ $range = $filter->setSessionRangeValue();
+ $start = \Session::get('start');
+
+ /*
+ * Substract some period to $start.
+ */
+ $prev = $filter->previous($range, clone $start);
+
+ /*
+ * Save in session:
+ */
+ \Session::put('start', $prev);
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Shared/Toolkit/Reminders.php b/app/lib/FireflyIII/Shared/Toolkit/Reminders.php
new file mode 100644
index 0000000000..ce330b1d42
--- /dev/null
+++ b/app/lib/FireflyIII/Shared/Toolkit/Reminders.php
@@ -0,0 +1,123 @@
+remindersable)) {
+
+ case 'Piggybank':
+ $start = new Carbon;
+ $end = !is_null($reminder->remindersable->targetdate) ? clone $reminder->remindersable->targetdate : new Carbon;
+ $reminders = 0;
+ while ($start <= $end) {
+ $reminders++;
+ $start = \DateKit::addPeriod($start, $reminder->remindersable->reminder, $reminder->remindersable->reminder_skip);
+ }
+ /*
+ * Now find amount yet to save.
+ */
+ $repetition = $reminder->remindersable->currentRelevantRep();
+ $leftToSave = floatval($reminder->remindersable->targetamount) - floatval($repetition->currentamount);
+ $reminders = $reminders == 0 ? 1 : $reminders;
+
+ return $leftToSave / $reminders;
+ break;
+ default:
+ throw new FireflyException('Cannot handle class ' . get_class($reminder->remindersable) . ' in amountForReminder.');
+ break;
+ }
+ }
+
+ /**
+ *
+ */
+ public function getReminders()
+ {
+ $reminders = \Auth::user()->reminders()
+ ->where('active', 1)
+ ->where('startdate', '<=', Carbon::now()->format('Y-m-d'))
+ ->where('enddate', '>=', Carbon::now()->format('Y-m-d'))
+ ->get();
+
+ return $reminders;
+ }
+
+ public function updateReminders()
+ {
+
+ /*
+ * Reminder capable objects are (so far) only piggy banks.
+ */
+ /** @var \FireflyIII\Database\Piggybank $repository */
+ $repository = \App::make('FireflyIII\Database\Piggybank');
+
+ /** @var \FireflyIII\Database\Piggybank $repeatedRepository */
+ $repeatedRepository = \App::make('FireflyIII\Database\RepeatedExpense');
+
+ /** @var Collection $piggybanks */
+ $piggybanks = $repository->get()->merge($repeatedRepository->get());
+
+
+ $set = $piggybanks->filter(
+ function (\Piggybank $piggybank) {
+ if (!is_null($piggybank->reminder)) {
+ return $piggybank;
+ }
+ return null;
+ }
+ );
+ $today = Carbon::now();
+ //$today = new Carbon('14-12-2014');
+
+ /** @var \Piggybank $piggybank */
+ foreach ($set as $piggybank) {
+ /*
+ * Try to find a reminder that is valid in the current [period]
+ * aka between [start of period] and [end of period] as denoted
+ * by the piggy's repeat_freq.
+ */
+ /** @var \PiggybankRepetition $repetition */
+ $repetition = $piggybank->currentRelevantRep();
+ $start = \DateKit::startOfPeriod($today, $piggybank->reminder);
+ if ($repetition->targetdate && $repetition->targetdate <= $today) {
+ // break when no longer relevant:
+ continue;
+ }
+ $end = \DateKit::endOfPeriod(clone $start, $piggybank->reminder);
+ // should have a reminder for this period:
+ /** @var Collection $reminders */
+ $reminders = $piggybank->reminders()->dateIs($start, $end)->get();
+ if ($reminders->count() == 0) {
+ // create new!
+ $reminder = new \Reminder;
+ $reminder->startdate = $start;
+ $reminder->enddate = $end;
+ $reminder->active = 1;
+ $reminder->user()->associate($repository->getUser());
+ $reminder->remindersable_id= $piggybank->id;
+ $reminder->remindersable_type = 'Piggybank';
+ $reminder->save();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Shared/Toolkit/Steam.php b/app/lib/FireflyIII/Shared/Toolkit/Steam.php
new file mode 100644
index 0000000000..9da5fc7b40
--- /dev/null
+++ b/app/lib/FireflyIII/Shared/Toolkit/Steam.php
@@ -0,0 +1,63 @@
+id . '.latestBalance')) {
+
+ return \Cache::get('account.' . $account->id . '.latestBalance');
+ }
+ }
+ $date = is_null($date) ? Carbon::now() : $date;
+ $balance = floatval(
+ $account->transactions()->leftJoin(
+ 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
+ )->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount')
+ );
+ if ($latest === true) {
+ \Cache::forever('account.' . $account->id . '.latestBalance', $balance);
+ }
+
+ return $balance;
+ }
+
+ /**
+ * @param \Piggybank $piggyBank
+ * @param \PiggybankRepetition $repetition
+ *
+ * @return int
+ */
+ public function percentage(\Piggybank $piggyBank, \PiggybankRepetition $repetition)
+ {
+ $pct = $repetition->currentamount / $piggyBank->targetamount * 100;
+ if ($pct > 100) {
+ return 100;
+ } else {
+ return floor($pct);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/lib/FireflyIII/Shared/Validation/FireflyValidator.php b/app/lib/FireflyIII/Shared/Validation/FireflyValidator.php
new file mode 100644
index 0000000000..1f26103651
--- /dev/null
+++ b/app/lib/FireflyIII/Shared/Validation/FireflyValidator.php
@@ -0,0 +1,22 @@
+app->validator->resolver(
+ function ($translator, $data, $rules, $messages) {
+ return new FireflyValidator($translator, $data, $rules, $messages);
+ }
+ );
+ }
+
+ public function register()
+ {
+ }
+}
\ No newline at end of file
diff --git a/app/models/Account.php b/app/models/Account.php
index 2346f5501d..96c07b06f0 100644
--- a/app/models/Account.php
+++ b/app/models/Account.php
@@ -1,88 +1,32 @@
['required', 'between:1,100', 'alphabasic'],
+ = [
+ 'name' => ['required', 'between:1,100'],
'user_id' => 'required|exists:users,id',
'account_type_id' => 'required|exists:account_types,id',
'active' => 'required|boolean'
];
-
+ protected $dates = ['deleted_at', 'created_at', 'updated_at'];
+ /**
+ * Fillable fields.
+ *
+ * @var array
+ */
protected $fillable = ['name', 'user_id', 'account_type_id', 'active'];
- /**
- * Get an accounts current balance.
- *
- * @param \Carbon\Carbon $date
- *
- * @return float
- */
- public function balance(\Carbon\Carbon $date = null)
- {
- $date = is_null($date) ? new \Carbon\Carbon : $date;
-
- return floatval(
- $this->transactions()
- ->leftJoin(
- 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
- )
- ->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount')
- );
- }
-
- /**
- * @param TransactionJournal $journal
- *
- * @return float
- */
- public function balanceBeforeJournal(TransactionJournal $journal)
- {
- return floatval(
- $this->transactions()
- ->leftJoin(
- 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
- )
- ->where('transaction_journals.date', '<=', $journal->date->format('Y-m-d'))
- ->where('transaction_journals.created_at', '<=', $journal->created_at->format('Y-m-d H:i:s'))
- ->where('transaction_journals.id', '!=', $journal->id)
- ->sum('transactions.amount')
- );
- }
-
/**
* Account type.
*
@@ -94,13 +38,21 @@ class Account extends Ardent
}
/**
- * Transactions.
*
- * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ * @param $fieldName
+ *
+ * @return mixed
*/
- public function transactions()
+ public function getMeta($fieldName)
{
- return $this->hasMany('Transaction');
+ foreach ($this->accountMeta as $meta) {
+ if ($meta->name == $fieldName) {
+ return $meta->data;
+ }
+ }
+
+ return null;
+
}
/**
@@ -112,28 +64,7 @@ class Account extends Ardent
}
/**
- * @param \Carbon\Carbon $date
*
- * @return null
- */
- public function predict(
- /** @noinspection PhpUnusedParameterInspection */
- \Carbon\Carbon $date
- ) {
- return null;
- }
-
- /**
- * User
- *
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function user()
- {
- return $this->belongsTo('User');
- }
-
- /**
* @param Builder $query
* @param array $types
*/
@@ -146,5 +77,60 @@ class Account extends Ardent
$query->whereIn('account_types.type', $types);
}
+ /**
+ *
+ * @param Builder $query
+ */
+ public function scopeWithMeta(Builder $query)
+ {
+ $query->with(['accountmeta']);
+ }
+
+ /**
+ * Transactions.
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function transactions()
+ {
+ return $this->hasMany('Transaction');
+ }
+
+ public function updateMeta($fieldName, $fieldValue)
+ {
+ $meta = $this->accountMeta()->get();
+ /** @var AccountMeta $entry */
+ foreach ($meta as $entry) {
+ if ($entry->name == $fieldName) {
+ $entry->data = $fieldValue;
+ $entry->save();
+
+ return $entry;
+ }
+ }
+ $meta = new AccountMeta;
+ $meta->account()->associate($this);
+ $meta->name = $fieldName;
+ $meta->data = $fieldValue;
+ $meta->save();
+
+ return $meta;
+ }
+
+ public function accountMeta()
+ {
+ return $this->hasMany('AccountMeta');
+ }
+
+ /**
+ * User
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function user()
+ {
+ return $this->belongsTo('User');
+ }
+
}
\ No newline at end of file
diff --git a/app/models/AccountMeta.php b/app/models/AccountMeta.php
index 12b09102b9..78dbc159dd 100644
--- a/app/models/AccountMeta.php
+++ b/app/models/AccountMeta.php
@@ -1,13 +1,9 @@
'required|between:1,250',
'data' => 'required'
];
-
/**
* @var array
*/
protected $fillable = ['account_id', 'name', 'date'];
-
+ protected $table = 'account_meta';
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
@@ -32,4 +27,22 @@ class AccountMeta extends Ardent
return $this->belongsTo('Account');
}
+ /**
+ * @param $value
+ *
+ * @return mixed
+ */
+ public function getDataAttribute($value)
+ {
+ return json_decode($value);
+ }
+
+ /**
+ * @param $value
+ */
+ public function setDataAttribute($value)
+ {
+ $this->attributes['data'] = json_encode($value);
+ }
+
}
\ No newline at end of file
diff --git a/app/models/AccountType.php b/app/models/AccountType.php
index 77a4ec8585..b5857f1fc2 100644
--- a/app/models/AccountType.php
+++ b/app/models/AccountType.php
@@ -1,24 +1,11 @@
['required', 'between:1,50', 'alphabasic'],
diff --git a/app/models/Budget.php b/app/models/Budget.php
index 18bf3d069c..ba7ca58652 100644
--- a/app/models/Budget.php
+++ b/app/models/Budget.php
@@ -1,29 +1,14 @@
hasManyThrough('LimitRepetition', 'Limit', 'component_id');
+ }
+
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
@@ -32,12 +17,5 @@ class Budget extends Component
return $this->hasMany('Limit', 'component_id');
}
- /**
- * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany|\TransactionJournal
- */
- public function transactionjournals()
- {
- return $this->belongsToMany('TransactionJournal', 'component_transaction_journal', 'component_id');
- }
}
\ No newline at end of file
diff --git a/app/models/Category.php b/app/models/Category.php
index 2469907cdc..50dda8a466 100644
--- a/app/models/Category.php
+++ b/app/models/Category.php
@@ -1,34 +1,8 @@
belongsToMany('TransactionJournal', 'component_transaction_journal', 'component_id');
- }
-}
\ No newline at end of file
+
+}
\ No newline at end of file
diff --git a/app/models/Component.php b/app/models/Component.php
index 9337fcced7..a67d457a53 100644
--- a/app/models/Component.php
+++ b/app/models/Component.php
@@ -1,46 +1,37 @@
'exists:users,id|required',
- 'name' => ['required', 'between:1,100','min:1', 'alphabasic'],
+ 'name' => 'required|between:1,100|alphabasic',
'class' => 'required',
];
- protected $table = 'components';
- protected $subclassField = 'class';
- protected $fillable = ['name','user_id'];
-
+ protected $dates = ['deleted_at', 'created_at', 'updated_at'];
+ protected $fillable = ['name', 'user_id'];
+ protected $subclassField = 'class';
+ protected $table = 'components';
+ use SoftDeletingTrait, ValidatingTrait;
/**
- * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
+ * @return Carbon
*/
- public function limits()
+ public function lastActionDate()
{
- return $this->hasMany('Limit');
+ $transaction = $this->transactionjournals()->orderBy('updated_at', 'DESC')->first();
+ if (is_null($transaction)) {
+ return null;
+ }
+
+ return $transaction->date;
}
/**
@@ -48,7 +39,7 @@ class Component extends SingleTableInheritanceEntity
*/
public function transactionjournals()
{
- return $this->belongsToMany('TransactionJournal');
+ return $this->belongsToMany('TransactionJournal', 'component_transaction_journal', 'component_id');
}
/**
diff --git a/app/models/Importentry.php b/app/models/Importentry.php
deleted file mode 100644
index 9bf832b31a..0000000000
--- a/app/models/Importentry.php
+++ /dev/null
@@ -1,29 +0,0 @@
-belongsTo('Importmap');
- }
-}
\ No newline at end of file
diff --git a/app/models/Importmap.php b/app/models/Importmap.php
deleted file mode 100644
index ab81ed683a..0000000000
--- a/app/models/Importmap.php
+++ /dev/null
@@ -1,52 +0,0 @@
- 'required|exists:users,id',
- 'file' => 'required',
- 'totaljobs' => 'numeric|required|min:0',
- 'jobsdone' => 'numeric|required|min:0',
-
- ];
-
- /**
- * User
- *
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function user()
- {
- return $this->belongsTo('User');
- }
-
- public function pct()
- {
- if ($this->jobsdone == 0 || $this->totaljobs == 0) {
- return 0;
- } else {
- return round((($this->jobsdone / $this->totaljobs) * 100), 1);
- }
- }
-}
\ No newline at end of file
diff --git a/app/models/Limit.php b/app/models/Limit.php
index 23f893ed1e..a215c98623 100644
--- a/app/models/Limit.php
+++ b/app/models/Limit.php
@@ -2,34 +2,12 @@
use Carbon\Carbon;
use Illuminate\Database\QueryException;
-use LaravelBook\Ardent\Ardent as Ardent;
+use Watson\Validating\ValidatingTrait;
-/**
- * Limit
- *
- * @property integer $id
- * @property \Carbon\Carbon $created_at
- * @property \Carbon\Carbon $updated_at
- * @property integer $component_id
- * @property \Carbon\Carbon $startdate
- * @property float $amount
- * @property boolean $repeats
- * @property string $repeat_freq
- * @property-read \Budget $budget
- * @property-read \Component $component
- * @property-read \Illuminate\Database\Eloquent\Collection|\LimitRepetition[] $limitrepetitions
- * @method static \Illuminate\Database\Query\Builder|\Limit whereId($value)
- * @method static \Illuminate\Database\Query\Builder|\Limit whereCreatedAt($value)
- * @method static \Illuminate\Database\Query\Builder|\Limit whereUpdatedAt($value)
- * @method static \Illuminate\Database\Query\Builder|\Limit whereComponentId($value)
- * @method static \Illuminate\Database\Query\Builder|\Limit whereStartdate($value)
- * @method static \Illuminate\Database\Query\Builder|\Limit whereAmount($value)
- * @method static \Illuminate\Database\Query\Builder|\Limit whereRepeats($value)
- * @method static \Illuminate\Database\Query\Builder|\Limit whereRepeatFreq($value)
- */
-class Limit extends Ardent
+class Limit extends Eloquent
{
+ use ValidatingTrait;
public static $rules
= [
'component_id' => 'required|exists:components,id',
@@ -50,14 +28,7 @@ class Limit extends Ardent
}
/**
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function component()
- {
- return $this->belongsTo('Component', 'component_id');
- }
-
- /**
+ * TODO see if this method is still used.
* Create a new repetition for this limit, starting on
* the given date.
*
@@ -90,15 +61,15 @@ class Limit extends Ardent
}
$end->subDay();
$count = $this->limitrepetitions()->where('startdate', $start->format('Y-m-d'))->where('enddate', $end->format('Y-m-d'))->count();
- \Log::debug('All: '.$this->limitrepetitions()->count().' (#'.$this->id.')');
- \Log::debug('Found ' . $count.' limit-reps for limit #' . $this->id.' with start '.$start->format('Y-m-d') .' and end ' . $end->format('Y-m-d'));
+ \Log::debug('All: ' . $this->limitrepetitions()->count() . ' (#' . $this->id . ')');
+ \Log::debug('Found ' . $count . ' limit-reps for limit #' . $this->id . ' with start ' . $start->format('Y-m-d') . ' and end ' . $end->format('Y-m-d'));
if ($count == 0) {
- $repetition = new \LimitRepetition();
+ $repetition = new \LimitRepetition();
$repetition->startdate = $start;
- $repetition->enddate = $end;
- $repetition->amount = $this->amount;
+ $repetition->enddate = $end;
+ $repetition->amount = $this->amount;
$repetition->limit()->associate($this);
try {
@@ -111,14 +82,16 @@ class Limit extends Ardent
\Log::error($e->getMessage());
}
if (isset($repetition->id)) {
- \Event::fire('limits.repetition', [$repetition]);
+ \Event::fire('limits.repetition', [$repetition]); // not used, I guess?
}
- } else if($count == 1) {
- // update this one:
- $repetition = $this->limitrepetitions()->where('startdate', $start->format('Y-m-d'))->where('enddate', $end->format('Y-m-d'))->first();
- $repetition->amount = $this->amount;
- $repetition->save();
+ } else {
+ if ($count == 1) {
+ // update this one:
+ $repetition = $this->limitrepetitions()->where('startdate', $start->format('Y-m-d'))->where('enddate', $end->format('Y-m-d'))->first();
+ $repetition->amount = $this->amount;
+ $repetition->save();
+ }
}
}
diff --git a/app/models/LimitRepetition.php b/app/models/LimitRepetition.php
index c61aed4364..07e9da433b 100644
--- a/app/models/LimitRepetition.php
+++ b/app/models/LimitRepetition.php
@@ -1,28 +1,11 @@
'required|exists:limits,id',
@@ -39,29 +22,6 @@ class LimitRepetition extends Ardent
return ['created_at', 'updated_at', 'startdate', 'enddate'];
}
- public function spentInRepetition() {
- $sum = \DB::table('transactions')
- ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
- ->leftJoin('component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
- ->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id')
- ->leftJoin('limits', 'limits.component_id', '=', 'components.id')
- ->leftJoin('limit_repetitions', 'limit_repetitions.limit_id', '=', 'limits.id')
- ->where('transaction_journals.date', '>=', $this->startdate->format('Y-m-d'))
- ->where('transaction_journals.date', '<=', $this->enddate->format('Y-m-d'))
- ->where('transactions.amount', '>', 0)
- ->where('limit_repetitions.id', '=', $this->id)->sum('transactions.amount');
- return floatval($sum);
- }
-
- /**
- * How much money is left in this?
- */
- public function leftInRepetition()
- {
- return floatval($this->amount - $this->spentInRepetition());
-
- }
-
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
@@ -71,6 +31,39 @@ class LimitRepetition extends Ardent
}
/**
+ * TODO see if this scope is still used.
+ *
+ * How much money is left in this?
+ */
+ public function leftInRepetition()
+ {
+ return floatval($this->amount - $this->spentInRepetition());
+
+ }
+
+ /**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
+ * @return float
+ */
+ public function spentInRepetition()
+ {
+ $sum = \DB::table('transactions')->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->leftJoin(
+ 'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
+ )->leftJoin('components', 'components.id', '=', 'component_transaction_journal.component_id')->leftJoin(
+ 'limits', 'limits.component_id', '=', 'components.id'
+ )->leftJoin('limit_repetitions', 'limit_repetitions.limit_id', '=', 'limits.id')->where(
+ 'transaction_journals.date', '>=', $this->startdate->format('Y-m-d')
+ )->where('transaction_journals.date', '<=', $this->enddate->format('Y-m-d'))->where('transactions.amount', '>', 0)->where(
+ 'limit_repetitions.id', '=', $this->id
+ )->sum('transactions.amount');
+
+ return floatval($sum);
+ }
+
+ /**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
* Returns a string used to sort this particular repetition
* based on the date and period it falls into. Ie. the limit
* repeats monthly and the start date is 12 dec 2012, this will
@@ -83,10 +76,7 @@ class LimitRepetition extends Ardent
}
switch ($this->repeat_freq) {
default:
- throw new \Firefly\Exception\FireflyException(
- 'No date formats for frequency "' . $this->repeat_freq
- . '"!'
- );
+ throw new FireflyException('No date formats for frequency "' . $this->repeat_freq . '"!');
break;
case 'daily':
return $this->startdate->format('Ymd') . '-5';
@@ -109,39 +99,4 @@ class LimitRepetition extends Ardent
}
}
- /**
- * Same as above, just with a more natural view. So "March 2012".
- */
- public function periodShow()
- {
- if (is_null($this->repeat_freq)) {
- $this->repeat_freq = $this->limit->repeat_freq;
- }
- switch ($this->repeat_freq) {
- default:
- throw new \Firefly\Exception\FireflyException(
- 'No date formats for frequency "' . $this->repeat_freq
- . '"!'
- );
- break;
- case 'daily':
- return $this->startdate->format('j F Y');
- break;
- case 'weekly':
- return $this->startdate->format('\W\e\e\k W, Y');
- break;
- case 'monthly':
- return $this->startdate->format('F Y');
- break;
- case 'half-year':
- case 'quarterly':
- return $this->startdate->format('M Y') . ' - ' . $this->enddate->format('M Y');
- break;
- case 'yearly':
- return $this->startdate->format('Y');
- break;
- }
- }
-
-
}
\ No newline at end of file
diff --git a/app/models/Piggybank.php b/app/models/Piggybank.php
index c364bcf0d2..a35f60e67d 100644
--- a/app/models/Piggybank.php
+++ b/app/models/Piggybank.php
@@ -1,81 +1,27 @@
'required|exists:accounts,id', // link to Account
- 'name' => 'required|between:1,255', // name
- 'targetamount' => 'required|min:0', // amount you want to save
- 'startdate' => 'date', // when you started
- 'targetdate' => 'date', // when its due
- 'repeats' => 'required|boolean', // does it repeat?
- 'rep_length' => 'in:day,week,month,year', // how long is the period?
- 'rep_every' => 'required|min:1|max:100', // how often does it repeat? every 3 years.
- 'rep_times' => 'min:1|max:100', // how many times do you want to save this amount? eg. 3 times
- 'reminder' => 'in:day,week,month,year', // want a reminder to put money in this?
- 'reminder_skip' => 'required|min:0|max:100', // every week? every 2 months?
- 'remind_me' => 'required|boolean',
- 'order' => 'required:min:1', // not yet used.
- ];
- public $fillable
- = [
- 'account_id',
- 'name',
- 'targetamount',
- 'startdate',
- 'targetdate',
- 'repeats',
- 'rep_length',
- 'rep_every',
- 'rep_times',
- 'reminder',
- 'reminder_skip',
- 'remind_me',
- 'order'
+ = ['account_id' => 'required|exists:accounts,id', // link to Account
+ 'name' => 'required|between:1,255', // name
+ 'targetamount' => 'required|min:0', // amount you want to save
+ 'startdate' => 'date', // when you started
+ 'targetdate' => 'date', // when its due
+ 'repeats' => 'required|boolean', // does it repeat?
+ 'rep_length' => 'in:day,week,month,quarter,year', // how long is the period?
+ 'rep_every' => 'required|min:1|max:100', // how often does it repeat? every 3 years.
+ 'rep_times' => 'min:1|max:100', // how many times do you want to save this amount? eg. 3 times
+ 'reminder' => 'in:day,week,quarter,month,year', // want a reminder to put money in this?
+ 'reminder_skip' => 'required|min:0|max:100', // every week? every 2 months?
+ 'remind_me' => 'required|boolean', 'order' => 'required:min:1', // not yet used.
];
+ public $fillable
+ = ['account_id', 'name', 'targetamount', 'startdate', 'targetdate', 'repeats', 'rep_length', 'rep_every', 'rep_times', 'reminder', 'reminder_skip',
+ 'remind_me', 'order'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
@@ -85,63 +31,102 @@ class Piggybank extends Ardent
return $this->belongsTo('Account');
}
+ /**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
+ * @return int
+ */
+ public function amountPerReminder()
+ {
+ return 0;
+
+ }
+
+ /**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
+ * @return int
+ */
+ public function countFutureReminders()
+ {
+ return 0;
+ }
+
+ /**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
+ * @param Carbon $start
+ * @param Carbon $target
+ *
+ * @return PiggybankRepetition
+ */
public function createRepetition(Carbon $start = null, Carbon $target = null)
{
$rep = new \PiggybankRepetition;
$rep->piggybank()->associate($this);
- $rep->startdate = $start;
- $rep->targetdate = $target;
+ $rep->startdate = $start;
+ $rep->targetdate = $target;
$rep->currentamount = 0;
$rep->save();
- \Event::fire('piggybanks.repetition', [$rep]);
return $rep;
}
/**
- * @return array
- */
- public function getDates()
- {
- return ['created_at', 'updated_at', 'targetdate', 'startdate'];
- }
-
- /**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
* Grabs the PiggyBankRepetition that's currently relevant / active
*
* @returns \PiggybankRepetition
*/
public function currentRelevantRep()
{
- $query = $this->piggybankrepetitions()
- ->where(
+ if ($this->currentRep) {
+ return $this->currentRep;
+ }
+ if ($this->repeats == 0) {
+ $rep = $this->piggybankrepetitions()->first(['piggybank_repetitions.*']);
+ $this->currentRep = $rep;
+
+ return $rep;
+ } else {
+ $query = $this->piggybankrepetitions()->where(
function ($q) {
$q->where(
function ($q) {
- $today = new Carbon;
- $q->whereNull('startdate');
- $q->orWhere('startdate', '<=', $today->format('Y-m-d'));
- }
- )
- ->where(
- function ($q) {
- $today = new Carbon;
- $q->whereNull('targetdate');
- $q->orWhere('targetdate', '>=', $today->format('Y-m-d'));
- }
- );
- }
- )->orWhere(
- function ($q) {
- $today = new Carbon;
- $q->where('startdate', '>=', $today->format('Y-m-d'));
- $q->where('targetdate', '>=', $today->format('Y-m-d'));
- }
- )->orderBy('startdate', 'ASC');
- $result = $query->first();
- return $result;
+ $q->where(
+ function ($q) {
+ $today = new Carbon;
+ $q->whereNull('startdate');
+ $q->orWhere('startdate', '<=', $today->format('Y-m-d'));
+ }
+ )->where(
+ function ($q) {
+ $today = new Carbon;
+ $q->whereNull('targetdate');
+ $q->orWhere('targetdate', '>=', $today->format('Y-m-d'));
+ }
+ );
+ }
+ )->orWhere(
+ function ($q) {
+ $today = new Carbon;
+ $q->where('startdate', '>=', $today->format('Y-m-d'));
+ $q->where('targetdate', '>=', $today->format('Y-m-d'));
+ }
+ );
+
+ }
+ )
+ ->orderBy('startdate', 'ASC');
+ $result = $query->first(['piggybank_repetitions.*']);
+ $this->currentRep = $result;
+ \Log::debug('Found relevant rep in currentRelevantRep(): ' . $result->id);
+
+ return $result;
+ }
}
@@ -154,6 +139,14 @@ class Piggybank extends Ardent
return $this->hasMany('PiggybankRepetition');
}
+ /**
+ * @return array
+ */
+ public function getDates()
+ {
+ return ['created_at', 'updated_at', 'targetdate', 'startdate'];
+ }
+
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
@@ -162,7 +155,14 @@ class Piggybank extends Ardent
return $this->hasMany('PiggybankEvent');
}
+ public function reminders()
+ {
+ return $this->morphMany('Reminder', 'remindersable');
+ }
+
/**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
* Same but for specific date.
*
* @param Carbon $date
@@ -171,29 +171,27 @@ class Piggybank extends Ardent
*/
public function repetitionForDate(Carbon $date)
{
- $query = $this->piggybankrepetitions()
- ->where(
- function ($q) use ($date) {
+ $query = $this->piggybankrepetitions()->where(
+ function ($q) use ($date) {
- $q->where(
- function ($q) use ($date) {
- $q->whereNull('startdate');
- $q->orWhere('startdate', '<=', $date->format('Y-m-d'));
- }
- )
- ->where(
- function ($q) use ($date) {
- $q->whereNull('targetdate');
- $q->orWhere('targetdate', '>=', $date->format('Y-m-d'));
- }
- );
- }
- )->orWhere(
- function ($q) use ($date) {
- $q->where('startdate', '>=', $date->format('Y-m-d'));
- $q->where('targetdate', '>=', $date->format('Y-m-d'));
- }
- )->orderBy('startdate', 'ASC');
+ $q->where(
+ function ($q) use ($date) {
+ $q->whereNull('startdate');
+ $q->orWhere('startdate', '<=', $date->format('Y-m-d'));
+ }
+ )->where(
+ function ($q) use ($date) {
+ $q->whereNull('targetdate');
+ $q->orWhere('targetdate', '>=', $date->format('Y-m-d'));
+ }
+ );
+ }
+ )->orWhere(
+ function ($q) use ($date) {
+ $q->where('startdate', '>=', $date->format('Y-m-d'));
+ $q->where('targetdate', '>=', $date->format('Y-m-d'));
+ }
+ )->orderBy('startdate', 'ASC');
$result = $query->first();
return $result;
diff --git a/app/models/PiggybankEvent.php b/app/models/PiggybankEvent.php
index 5c6cc88fb7..ecb85a8654 100644
--- a/app/models/PiggybankEvent.php
+++ b/app/models/PiggybankEvent.php
@@ -1,27 +1,10 @@
'required|exists:piggybanks,id',
@@ -45,4 +28,12 @@ class PiggybankEvent extends Ardent
return $this->belongsTo('Piggybank');
}
+ /**
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function transactionJournal()
+ {
+ return $this->belongsTo('TransactionJournal');
+ }
+
}
\ No newline at end of file
diff --git a/app/models/PiggybankRepetition.php b/app/models/PiggybankRepetition.php
index 9f66ef2820..a7cfe38bb5 100644
--- a/app/models/PiggybankRepetition.php
+++ b/app/models/PiggybankRepetition.php
@@ -1,34 +1,17 @@
'required|exists:piggybanks,id',
'targetdate' => 'date',
'startdate' => 'date',
- 'currentamount' => 'required|numeric'
- ];
+ 'currentamount' => 'required|numeric'];
/**
* @return array
@@ -38,6 +21,11 @@ class PiggybankRepetition extends Ardent
return ['created_at', 'updated_at', 'targetdate', 'startdate'];
}
+ /**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
+ * @return float|int
+ */
public function pct()
{
$total = $this->piggybank->targetamount;
@@ -58,5 +46,15 @@ class PiggybankRepetition extends Ardent
return $this->belongsTo('Piggybank');
}
+ public function scopeStarts(Builder $query, Carbon $date)
+ {
+ $query->where('startdate', $date->format('Y-m-d'));
+ }
+
+ public function scopeTargets(Builder $query, Carbon $date)
+ {
+ $query->where('targetdate', $date->format('Y-m-d'));
+ }
+
}
\ No newline at end of file
diff --git a/app/models/Preference.php b/app/models/Preference.php
index ba8ac43bf9..0f3c9700cf 100644
--- a/app/models/Preference.php
+++ b/app/models/Preference.php
@@ -1,48 +1,11 @@
'required|exists:users,id',
- 'name' => 'required|between:1,255',
- 'data' => 'required'
- ];
-
- /**
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function user()
- {
- return $this->belongsTo('User');
- }
-
- /**
- * @param $value
- */
- public function setDataAttribute($value)
- {
- $this->attributes['data'] = json_encode($value);
- }
+ = ['user_id' => 'required|exists:users,id', 'name' => 'required|between:1,255', 'data' => 'required'];
/**
* @param $value
@@ -54,4 +17,20 @@ class Preference extends Ardent
return json_decode($value);
}
+ /**
+ * @param $value
+ */
+ public function setDataAttribute($value)
+ {
+ $this->attributes['data'] = json_encode($value);
+ }
+
+ /**
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function user()
+ {
+ return $this->belongsTo('User');
+ }
+
}
\ No newline at end of file
diff --git a/app/models/RecurringTransaction.php b/app/models/RecurringTransaction.php
index c2781e1252..b3f5c4e9ae 100644
--- a/app/models/RecurringTransaction.php
+++ b/app/models/RecurringTransaction.php
@@ -1,41 +1,11 @@
'required|exists:users,id',
@@ -47,10 +17,9 @@ class RecurringTransaction extends Ardent
'active' => 'required|between:0,1',
'automatch' => 'required|between:0,1',
'repeat_freq' => 'required|in:daily,weekly,monthly,quarterly,half-year,yearly',
- 'skip' => 'required|between:0,31',
- ];
+ 'skip' => 'required|between:0,31',];
- protected $fillable = ['user_id','name','match','amount_min','amount_max','date','repeat_freq','skip','active','automatch'];
+ protected $fillable = ['user_id', 'name', 'match', 'amount_min', 'amount_max', 'date', 'repeat_freq', 'skip', 'active', 'automatch'];
/**
* @return array
@@ -60,44 +29,82 @@ class RecurringTransaction extends Ardent
return ['created_at', 'updated_at', 'date'];
}
+ /**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
+ * @return null
+ */
+ public function lastFoundMatch()
+ {
+ $last = $this->transactionjournals()->orderBy('date', 'DESC')->first();
+ if ($last) {
+ return $last->date;
+ }
+
+ return null;
+ }
/**
- * @return Carbon
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
- public function next()
+ public function transactionjournals()
{
- $today = new Carbon;
- $start = clone $this->date;
- $skip = $this->skip == 0 ? 1 : $this->skip;
- if ($today < $start) {
- return $start;
- }
+ return $this->hasMany('TransactionJournal');
+ }
- while ($start <= $this->date) {
- switch ($this->repeat_freq) {
- case 'daily':
- $start->addDays($skip);
- break;
- case 'weekly':
- $start->addWeeks($skip);
- break;
- case 'monthly':
- $start->addMonths($skip);
- break;
- case 'quarterly':
- $start->addMonths($skip * 3);
- break;
- case 'half-year':
- $start->addMonths($skip * 6);
- break;
- case 'yearly':
- $start->addYears($skip);
- break;
+ /**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
+ * Find the next expected match based on the set journals and the date stuff from the recurring
+ * transaction.
+ */
+ public function nextExpectedMatch()
+ {
+
+ /*
+ * The date Firefly tries to find. If this stays null, it's "unknown".
+ */
+ $finalDate = null;
+
+ /*
+ * $today is the start of the next period, to make sure FF3 won't miss anything
+ * when the current period has a transaction journal.
+ */
+ $today = DateKit::addPeriod(new Carbon, $this->repeat_freq, 0);
+
+ /*
+ * FF3 loops from the $start of the recurring transaction, and to make sure
+ * $skip works, it adds one (for modulo).
+ */
+ $skip = $this->skip + 1;
+ $start = DateKit::startOfPeriod(new Carbon, $this->repeat_freq);
+ /*
+ * go back exactly one month/week/etc because FF3 does not care about 'next'
+ * recurring transactions if they're too far into the past.
+ */
+ // echo 'Repeat freq is: ' . $recurringTransaction->repeat_freq . ' ';
+
+ // echo 'Start: ' . $start . ' ';
+
+ $counter = 0;
+ while ($start <= $today) {
+ if (($counter % $skip) == 0) {
+ // do something.
+ $end = DateKit::endOfPeriod(clone $start, $this->repeat_freq);
+ $journalCount = $this->transactionjournals()->before($end)->after($start)->count();
+ if ($journalCount == 0) {
+ $finalDate = clone $start;
+ break;
+ }
}
+
+ // add period for next round!
+ $start = DateKit::addPeriod($start, $this->repeat_freq, 0);
+ $counter++;
}
- return $start;
+ return $finalDate;
}
/**
diff --git a/app/models/Reminder.php b/app/models/Reminder.php
index c2fb74936c..8b61d63db2 100644
--- a/app/models/Reminder.php
+++ b/app/models/Reminder.php
@@ -1,34 +1,18 @@
morphTo();
+ }
+
+ public function scopeDateIs($query, Carbon $start, Carbon $end)
+ {
+ return $query->where('startdate', $start->format('Y-m-d'))->where('enddate', $end->format('Y-m-d'));
+ }
+
+ /**
+ * @param $value
+ */
+ public function setDataAttribute($value)
+ {
+ $this->attributes['data'] = json_encode($value);
+ }
+
/**
* User
*
@@ -47,4 +54,6 @@ class Reminder extends Ardent
{
return $this->belongsTo('User');
}
+
+
}
\ No newline at end of file
diff --git a/app/models/Transaction.php b/app/models/Transaction.php
index c09704ac54..6e549cee8b 100644
--- a/app/models/Transaction.php
+++ b/app/models/Transaction.php
@@ -1,52 +1,19 @@
'numeric|required|exists:accounts,id',
- 'piggybank_id' => 'numeric|exists:piggybanks,id',
- 'transaction_journal_id' => 'numeric|required|exists:transaction_journals,id',
- 'description' => 'between:1,255',
- 'amount' => 'required|between:-65536,65536|not_in:0,0.00',
- ];
+ = ['account_id' => 'numeric|required|exists:accounts,id',
+ 'piggybank_id' => 'numeric|exists:piggybanks,id',
+ 'transaction_journal_id' => 'numeric|required|exists:transaction_journals,id',
+ 'description' => 'between:1,255',
+ 'amount' => 'required|between:-65536,65536|not_in:0,0.00',];
/**
@@ -57,35 +24,6 @@ class Transaction extends Ardent
return $this->belongsTo('Account');
}
- /**
- * @param Piggybank $piggybank
- *
- * @return bool
- */
- public function connectPiggybank(\Piggybank $piggybank = null)
- {
- if (is_null($piggybank)) {
- return true;
- }
- /** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $piggyRepository */
- $piggyRepository = \App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
- if ($this->account_id == $piggybank->account_id) {
- $this->piggybank()->associate($piggybank);
- $this->save();
- \Event::fire('piggybanks.createRelatedTransfer', [$piggybank, $this->transactionJournal, $this]);
- return true;
- }
- return false;
- }
-
- /**
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function piggybank()
- {
- return $this->belongsTo('Piggybank');
- }
-
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
@@ -110,6 +48,14 @@ class Transaction extends Ardent
return $this->belongsToMany('Component');
}
+ /**
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function piggybank()
+ {
+ return $this->belongsTo('Piggybank');
+ }
+
public function scopeAccountIs(Builder $query, Account $account)
{
$query->where('transactions.account_id', $account->id);
@@ -119,8 +65,7 @@ class Transaction extends Ardent
{
if (is_null($this->joinedJournals)) {
$query->leftJoin(
- 'transaction_journals', 'transaction_journals.id', '=',
- 'transactions.transaction_journal_id'
+ 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
);
$this->joinedJournals = true;
}
@@ -131,8 +76,7 @@ class Transaction extends Ardent
{
if (is_null($this->joinedJournals)) {
$query->leftJoin(
- 'transaction_journals', 'transaction_journals.id', '=',
- 'transactions.transaction_journal_id'
+ 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
);
$this->joinedJournals = true;
}
@@ -153,15 +97,13 @@ class Transaction extends Ardent
{
if (is_null($this->joinedJournals)) {
$query->leftJoin(
- 'transaction_journals', 'transaction_journals.id', '=',
- 'transactions.transaction_journal_id'
+ 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
);
$this->joinedJournals = true;
}
if (is_null($this->joinedTransactionTypes)) {
$query->leftJoin(
- 'transaction_types', 'transaction_types.id', '=',
- 'transaction_journals.transaction_type_id'
+ 'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
);
$this->joinedTransactionTypes = true;
}
diff --git a/app/models/TransactionCurrency.php b/app/models/TransactionCurrency.php
index 23ee95ad1f..9fded03565 100644
--- a/app/models/TransactionCurrency.php
+++ b/app/models/TransactionCurrency.php
@@ -1,26 +1,17 @@
hasMany('TransactionJournal');
}
diff --git a/app/models/TransactionGroup.php b/app/models/TransactionGroup.php
new file mode 100644
index 0000000000..f689c97b49
--- /dev/null
+++ b/app/models/TransactionGroup.php
@@ -0,0 +1,41 @@
+ 'required|in:balance'
+ ];
+
+ /**
+ * @return array
+ */
+ public function getDates()
+ {
+ return ['created_at', 'updated_at'];
+ }
+
+ /**
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function transactionjournals()
+ {
+ return $this->belongsToMany('TransactionJournal');
+ }
+
+ /**
+ * User
+ *
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function user()
+ {
+ return $this->belongsTo('User');
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/models/TransactionJournal.php b/app/models/TransactionJournal.php
index 89513a0d46..61dd4424c9 100644
--- a/app/models/TransactionJournal.php
+++ b/app/models/TransactionJournal.php
@@ -1,64 +1,20 @@
'required|exists:transaction_types,id',
- 'transaction_currency_id' => 'required|exists:transaction_currencies,id',
- 'description' => 'required|between:1,255',
- 'date' => 'required|date',
- 'completed' => 'required|between:0,1'
- ];
-
+ = ['transaction_type_id' => 'required|exists:transaction_types,id',
+ 'transaction_currency_id' => 'required|exists:transaction_currencies,id',
+ 'description' => 'required|between:1,255',
+ 'date' => 'required|date',
+ 'completed' => 'required|between:0,1'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
@@ -89,6 +45,8 @@ class TransactionJournal extends Ardent
}
/**
+ * TODO remove this method in favour of something in the FireflyIII libraries.
+ *
* @return float
*/
public function getAmount()
@@ -99,15 +57,8 @@ class TransactionJournal extends Ardent
return floatval($t->amount);
}
}
- return -0.01;
- }
- /**
- * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
- */
- public function recurringTransaction()
- {
- return $this->belongsTo('RecurringTransaction');
+ return -0.01;
}
/**
@@ -118,6 +69,22 @@ class TransactionJournal extends Ardent
return ['created_at', 'updated_at', 'date'];
}
+ /**
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function piggybankevents()
+ {
+ return $this->hasMany('PiggybankEvent');
+ }
+
+ /**
+ * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
+ */
+ public function recurringTransaction()
+ {
+ return $this->belongsTo('RecurringTransaction');
+ }
+
/**
* @param Builder $query
* @param Account $account
@@ -158,25 +125,11 @@ class TransactionJournal extends Ardent
$query->orderBy('date', 'DESC')->orderBy('transaction_journals.id', 'DESC');
}
- public function scopeMoreThan(Builder $query, $amount)
- {
- if (is_null($this->joinedTransactions)) {
- $query->leftJoin(
- 'transactions', 'transactions.transaction_journal_id', '=',
- 'transaction_journals.id'
- );
- $this->joinedTransactions = true;
- }
-
- $query->where('transactions.amount', '>=', $amount);
- }
-
public function scopeLessThan(Builder $query, $amount)
{
if (is_null($this->joinedTransactions)) {
$query->leftJoin(
- 'transactions', 'transactions.transaction_journal_id', '=',
- 'transaction_journals.id'
+ 'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
);
$this->joinedTransactions = true;
}
@@ -184,6 +137,18 @@ class TransactionJournal extends Ardent
$query->where('transactions.amount', '<=', $amount);
}
+ public function scopeMoreThan(Builder $query, $amount)
+ {
+ if (is_null($this->joinedTransactions)) {
+ $query->leftJoin(
+ 'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
+ );
+ $this->joinedTransactions = true;
+ }
+
+ $query->where('transactions.amount', '>=', $amount);
+ }
+
/**
* @param $query
* @param Carbon $date
@@ -199,8 +164,7 @@ class TransactionJournal extends Ardent
{
if (is_null($this->joinedTransactionTypes)) {
$query->leftJoin(
- 'transaction_types', 'transaction_types.id', '=',
- 'transaction_journals.transaction_type_id'
+ 'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
);
$this->joinedTransactionTypes = true;
}
@@ -220,7 +184,7 @@ class TransactionJournal extends Ardent
$q->orderBy('amount', 'ASC');
}, 'transactiontype', 'components' => function ($q) {
$q->orderBy('class');
- }, 'transactions.account.accounttype', 'recurringTransaction']
+ }, 'transactions.account.accounttype', 'recurringTransaction', 'budgets', 'categories']
);
}
@@ -240,6 +204,11 @@ class TransactionJournal extends Ardent
return $this->belongsTo('TransactionType');
}
+ public function transactiongroups()
+ {
+ return $this->belongsToMany('TransactionGroup');
+ }
+
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
diff --git a/app/models/TransactionRelation.php b/app/models/TransactionRelation.php
new file mode 100644
index 0000000000..93109b2490
--- /dev/null
+++ b/app/models/TransactionRelation.php
@@ -0,0 +1,6 @@
+ 'required|email|unique:users,email',
'migrated' => 'required|boolean',
'password' => 'required|between:60,60',
'reset' => 'between:32,32',
];
- /**
- * The database table used by the model.
- *
- * @var string
- */
- protected $table = 'users';
+ protected $fillable = ['email'];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = ['remember_token'];
+ /**
+ * The database table used by the model.
+ *
+ * @var string
+ */
+ protected $table = 'users';
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
@@ -91,6 +65,11 @@ class User extends Ardent implements UserInterface, RemindableInterface
return $this->hasMany('Component');
}
+ public function piggybanks()
+ {
+ return $this->hasManyThrough('Piggybank', 'Account');
+ }
+
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
@@ -107,6 +86,14 @@ class User extends Ardent implements UserInterface, RemindableInterface
return $this->hasMany('RecurringTransaction');
}
+ /**
+ * @return \Illuminate\Database\Eloquent\Relations\HasMany
+ */
+ public function reminders()
+ {
+ return $this->hasMany('Reminder');
+ }
+
/**
* @param $value
*/
@@ -115,11 +102,6 @@ class User extends Ardent implements UserInterface, RemindableInterface
$this->attributes['password'] = Hash::make($value);
}
- public function piggybanks()
- {
- return $this->hasManyThrough('Piggybank', 'Account');
- }
-
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
@@ -128,4 +110,9 @@ class User extends Ardent implements UserInterface, RemindableInterface
return $this->hasMany('TransactionJournal');
}
+ public function transactions()
+ {
+ return $this->hasManyThrough('TransactionJournal', 'Transaction');
+ }
+
}
\ No newline at end of file
diff --git a/app/routes.php b/app/routes.php
index 4d85b37703..cb18fcd3cf 100644
--- a/app/routes.php
+++ b/app/routes.php
@@ -1,11 +1,9 @@
where('account_types.editable', 1)->where('accounts.id', $value)
@@ -26,6 +24,7 @@ Route::bind(
'user_id', Auth::user()->id
)->first();
}
+
return null;
}
);
@@ -37,6 +36,7 @@ Route::bind(
return RecurringTransaction::
where('id', $value)->where('user_id', Auth::user()->id)->first();
}
+
return null;
}
);
@@ -46,6 +46,18 @@ Route::bind(
return Budget::
where('id', $value)->where('user_id', Auth::user()->id)->first();
}
+
+ return null;
+ }
+);
+
+Route::bind(
+ 'component', function ($value, $route) {
+ if (Auth::check()) {
+ return Component::
+ where('id', $value)->where('user_id', Auth::user()->id)->first();
+ }
+
return null;
}
);
@@ -56,6 +68,7 @@ Route::bind(
return Reminder::
where('id', $value)->where('user_id', Auth::user()->id)->first();
}
+
return null;
}
);
@@ -66,6 +79,7 @@ Route::bind(
return Category::
where('id', $value)->where('user_id', Auth::user()->id)->first();
}
+
return null;
}
);
@@ -76,18 +90,7 @@ Route::bind(
return TransactionJournal::
where('id', $value)->where('user_id', Auth::user()->id)->first();
}
- return null;
- }
-);
-Route::bind(
- 'limit', function ($value, $route) {
- if (Auth::check()) {
- return Limit::
- where('limits.id', $value)->leftJoin('components', 'components.id', '=', 'limits.component_id')->where('components.class', 'Budget')->where(
- 'components.user_id', Auth::user()->id
- )->first(['limits.*']);
- }
return null;
}
);
@@ -100,6 +103,7 @@ Route::bind(
'components', 'components.id', '=', 'limits.component_id'
)->where('components.class', 'Budget')->where('components.user_id', Auth::user()->id)->first(['limit_repetitions.*']);
}
+
return null;
}
);
@@ -108,121 +112,104 @@ Route::bind(
'piggybank', function ($value, $route) {
if (Auth::check()) {
return Piggybank::
- where('piggybanks.id', $value)->leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where('accounts.user_id', Auth::user()->id)
- ->first(['piggybanks.*']);
+ where('piggybanks.id', $value)
+ ->leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')
+ ->where('accounts.user_id', Auth::user()->id)
+ ->where('repeats', 0)->first(['piggybanks.*']);
}
+
return null;
}
);
+Route::bind(
+ 'repeated', function ($value, $route) {
+ if (Auth::check()) {
+ return Piggybank::
+ where('piggybanks.id', $value)
+ ->leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')
+ ->where('accounts.user_id', Auth::user()->id)
+ ->where('repeats', 1)->first(['piggybanks.*']);
+ }
-// a development route:
-Route::get('/dev', ['uses' => 'HomeController@jobDev']);
+ return null;
+ }
+);
// protected routes:
Route::group(
['before' => 'auth'], function () {
- // some date routes:
+ // some date routes used for (well duh) date-based navigation.
Route::get('/prev', ['uses' => 'HomeController@sessionPrev', 'as' => 'sessionPrev']);
Route::get('/next', ['uses' => 'HomeController@sessionNext', 'as' => 'sessionNext']);
Route::get('/jump/{range}', ['uses' => 'HomeController@rangeJump', 'as' => 'rangeJump']);
- Route::get('/cleanup', ['uses' => 'HomeController@cleanup', 'as' => 'cleanup']);
+
// account controller:
- Route::get('/accounts/json/{what}', ['uses' => 'AccountController@json', 'as' => 'accounts.json'])->where('what', 'revenue|asset|expense');
Route::get('/accounts/{what}', ['uses' => 'AccountController@index', 'as' => 'accounts.index'])->where('what', 'revenue|asset|expense');
Route::get('/accounts/create/{what}', ['uses' => 'AccountController@create', 'as' => 'accounts.create'])->where('what', 'revenue|asset|expense');
Route::get('/accounts/edit/{account}', ['uses' => 'AccountController@edit', 'as' => 'accounts.edit']);
Route::get('/accounts/delete/{account}', ['uses' => 'AccountController@delete', 'as' => 'accounts.delete']);
- Route::get('/accounts/show/{account}', ['uses' => 'AccountController@show', 'as' => 'accounts.show']);
+ Route::get('/accounts/show/{account}/{view?}', ['uses' => 'AccountController@show', 'as' => 'accounts.show']);
+
// budget controller:
Route::get('/budgets', ['uses' => 'BudgetController@index', 'as' => 'budgets.index']);
- Route::get('/budgets/income', ['uses' => 'BudgetController@updateIncome', 'as' => 'budgets.income']);
- Route::get('/budgets/show/{budget}/{limitrepetition?}', ['uses' => 'BudgetController@show', 'as' => 'budgets.show']);
-
- #Route::get('/budgets/date', ['uses' => 'BudgetController@indexByDate', 'as' => 'budgets.index.date']);
- #Route::get('/budgets/budget', ['uses' => 'BudgetController@indexByBudget', 'as' => 'budgets.index.budget']);
+ Route::get('/budgets/income', ['uses' => 'BudgetController@updateIncome', 'as' => 'budgets.income']); # extra.
Route::get('/budgets/create', ['uses' => 'BudgetController@create', 'as' => 'budgets.create']);
- #Route::get('/budgets/nobudget/{period}', ['uses' => 'BudgetController@nobudget', 'as' => 'budgets.nobudget']);
-
Route::get('/budgets/edit/{budget}', ['uses' => 'BudgetController@edit', 'as' => 'budgets.edit']);
Route::get('/budgets/delete/{budget}', ['uses' => 'BudgetController@delete', 'as' => 'budgets.delete']);
+ Route::get('/budgets/show/{budget}/{limitrepetition?}', ['uses' => 'BudgetController@show', 'as' => 'budgets.show']);
// category controller:
Route::get('/categories', ['uses' => 'CategoryController@index', 'as' => 'categories.index']);
Route::get('/categories/create', ['uses' => 'CategoryController@create', 'as' => 'categories.create']);
- Route::get('/categories/show/{category}', ['uses' => 'CategoryController@show', 'as' => 'categories.show']);
Route::get('/categories/edit/{category}', ['uses' => 'CategoryController@edit', 'as' => 'categories.edit']);
Route::get('/categories/delete/{category}', ['uses' => 'CategoryController@delete', 'as' => 'categories.delete']);
+ Route::get('/categories/show/{category}', ['uses' => 'CategoryController@show', 'as' => 'categories.show']);
// google chart controller
Route::get('/chart/home/account', ['uses' => 'GoogleChartController@allAccountsBalanceChart']);
Route::get('/chart/home/budgets', ['uses' => 'GoogleChartController@allBudgetsHomeChart']);
Route::get('/chart/home/categories', ['uses' => 'GoogleChartController@allCategoriesHomeChart']);
Route::get('/chart/home/recurring', ['uses' => 'GoogleChartController@recurringTransactionsOverview']);
- Route::get('/chart/account/{account}', ['uses' => 'GoogleChartController@accountBalanceChart']);
- Route::get('/chart/sankey/{account}/out', ['uses' => 'GoogleChartController@accountSankeyOutChart']);
- Route::get('/chart/sankey/{account}/in', ['uses' => 'GoogleChartController@accountSankeyInChart']);
+ Route::get('/chart/account/{account}/{view?}', ['uses' => 'GoogleChartController@accountBalanceChart']);
+ Route::get('/chart/sankey/{account}/out/{view?}', ['uses' => 'GoogleChartController@accountSankeyOutChart']);
+ Route::get('/chart/sankey/{account}/in/{view?}', ['uses' => 'GoogleChartController@accountSankeyInChart']);
Route::get('/chart/reports/income-expenses/{year}', ['uses' => 'GoogleChartController@yearInExp']);
Route::get('/chart/reports/income-expenses-sum/{year}', ['uses' => 'GoogleChartController@yearInExpSum']);
+ Route::get('/chart/recurring/{recurring}', ['uses' => 'GoogleChartController@recurringOverview']);
Route::get('/chart/reports/budgets/{year}', ['uses' => 'GoogleChartController@budgetsReportChart']);
- Route::get('/chart/budgets/{budget}/spending/{year}', ['uses' => 'GoogleChartController@budgetsAndSpending']);
+ Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'GoogleChartController@budgetLimitSpending']);
+ Route::get('/chart/piggyhistory/{piggybank}', ['uses' => 'GoogleChartController@piggyBankHistory']);
- // google table controller
- Route::get('/table/account/{account}/transactions', ['uses' => 'GoogleTableController@transactionsByAccount']);
- Route::get('/table/accounts/{what}', ['uses' => 'GoogleTableController@accountList']);
- Route::get('/table/budget/{budget}/{limitrepetition?}/transactions', ['uses' => 'GoogleTableController@transactionsByBudget']);
+ // google chart for components (categories + budgets combined)
+ Route::get('/chart/component/{component}/spending/{year}', ['uses' => 'GoogleChartController@componentsAndSpending']);
-
- Route::get('/chart/home/info/{accountnameA}/{day}/{month}/{year}', ['uses' => 'ChartController@homeAccountInfo', 'as' => 'chart.info']);
- Route::get('/chart/categories/show/{category}', ['uses' => 'ChartController@categoryShowChart', 'as' => 'chart.showcategory']);
-
- // (new charts for budgets)
- Route::get('/chart/budget/{budget}/default', ['uses' => 'ChartController@budgetDefault', 'as' => 'chart.budget.default']);
- Route::get('chart/budget/{budget}/no_envelope', ['uses' => 'ChartController@budgetNoLimits', 'as' => 'chart.budget.nolimit']);
- Route::get('chart/budget/{budget}/session', ['uses' => 'ChartController@budgetSession', 'as' => 'chart.budget.session']);
- Route::get('chart/budget/envelope/{limitrepetition}', ['uses' => 'ChartController@budgetLimit', 'as' => 'chart.budget.limit']);
+ // help controller
+ Route::get('/help/{route}', ['uses' => 'HelpController@show', 'as' => 'help.show']);
// home controller
Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index']);
- Route::get('/flush', ['uses' => 'HomeController@flush', 'as' => 'flush']);
+ Route::get('/flush', ['uses' => 'HomeController@flush', 'as' => 'flush']); # even though nothing is cached.
- // JSON controller:
+ // JSON controller
Route::get('/json/expense-accounts', ['uses' => 'JsonController@expenseAccounts', 'as' => 'json.expense-accounts']);
Route::get('/json/revenue-accounts', ['uses' => 'JsonController@revenueAccounts', 'as' => 'json.revenue-accounts']);
Route::get('/json/categories', ['uses' => 'JsonController@categories', 'as' => 'json.categories']);
- Route::get('/json/expenses', ['uses' => 'JsonController@expenses', 'as' => 'json.expenses']);
- Route::get('/json/revenue', ['uses' => 'JsonController@revenue', 'as' => 'json.revenue']);
- Route::get('/json/transfers', ['uses' => 'JsonController@transfers', 'as' => 'json.transfers']);
- Route::get('/json/recurring', ['uses' => 'JsonController@recurring', 'as' => 'json.recurring']);
- Route::get('/json/recurringjournals/{recurring}', ['uses' => 'JsonController@recurringjournals', 'as' => 'json.recurringjournals']);
- // limit controller:
- Route::get('/budgets/limits/create/{budget?}', ['uses' => 'LimitController@create', 'as' => 'budgets.limits.create']);
- Route::get('/budgets/limits/delete/{limit}', ['uses' => 'LimitController@delete', 'as' => 'budgets.limits.delete']);
- Route::get('/budgets/limits/edit/{limit}', ['uses' => 'LimitController@edit', 'as' => 'budgets.limits.edit']);
-
- Route::get('/migrate', ['uses' => 'MigrateController@index', 'as' => 'migrate.index']);
// piggy bank controller
Route::get('/piggybanks', ['uses' => 'PiggybankController@index', 'as' => 'piggybanks.index']);
- Route::get('/piggybanks/add/{piggybank}', ['uses' => 'PiggybankController@add']);
- Route::get('/piggybanks/remove/{piggybank}', ['uses' => 'PiggybankController@remove']);
- Route::get('/piggybanks/edit/{piggybank}', ['uses' => 'PiggybankController@edit', 'as' => 'piggybanks.edit']);
+ Route::get('/piggybanks/add/{piggybank}', ['uses' => 'PiggybankController@add']); # add money
+ Route::get('/piggybanks/remove/{piggybank}', ['uses' => 'PiggybankController@remove']); #remove money
+
Route::get('/piggybanks/create', ['uses' => 'PiggybankController@create', 'as' => 'piggybanks.create']);
+ Route::get('/piggybanks/edit/{piggybank}', ['uses' => 'PiggybankController@edit', 'as' => 'piggybanks.edit']);
Route::get('/piggybanks/delete/{piggybank}', ['uses' => 'PiggybankController@delete', 'as' => 'piggybanks.delete']);
-
-
-// Route::get('/repeated',['uses' => 'PiggybankController@repeated','as' => 'piggybanks.index.repeated']);
-// Route::get('/piggybanks/create/repeated', ['uses' => 'PiggybankController@createRepeated','as' => 'piggybanks.create.repeated']);
-// Route::get('/piggybanks/addMoney/{piggybank}', ['uses' => 'PiggybankController@addMoney','as' => 'piggybanks.amount.add']);
-// Route::get('/piggybanks/removeMoney/{piggybank}', ['uses' => 'PiggybankController@removeMoney','as' => 'piggybanks.amount.remove']);
-// Route::get('/piggybanks/show/{piggybank}', ['uses' => 'PiggybankController@show','as' => 'piggybanks.show']);
-// Route::get('/piggybanks/delete/{piggybank}', ['uses' => 'PiggybankController@delete','as' => 'piggybanks.delete']);
-// Route::post('/piggybanks/updateAmount/{piggybank}',['uses' => 'PiggybankController@updateAmount','as' => 'piggybanks.updateAmount']);
+ Route::get('/piggybanks/show/{piggybank}', ['uses' => 'PiggybankController@show', 'as' => 'piggybanks.show']);
// preferences controller
Route::get('/preferences', ['uses' => 'PreferencesController@index', 'as' => 'preferences']);
@@ -233,34 +220,47 @@ Route::group(
// recurring transactions controller
Route::get('/recurring', ['uses' => 'RecurringController@index', 'as' => 'recurring.index']);
- Route::get('/recurring/show/{recurring}', ['uses' => 'RecurringController@show', 'as' => 'recurring.show']);
- Route::get('/recurring/rescan/{recurring}', ['uses' => 'RecurringController@rescan', 'as' => 'recurring.rescan']);
+ Route::get('/recurring/rescan/{recurring}', ['uses' => 'RecurringController@rescan', 'as' => 'recurring.rescan']); # rescan for matching.
Route::get('/recurring/create', ['uses' => 'RecurringController@create', 'as' => 'recurring.create']);
Route::get('/recurring/edit/{recurring}', ['uses' => 'RecurringController@edit', 'as' => 'recurring.edit']);
Route::get('/recurring/delete/{recurring}', ['uses' => 'RecurringController@delete', 'as' => 'recurring.delete']);
+ Route::get('/recurring/show/{recurring}', ['uses' => 'RecurringController@show', 'as' => 'recurring.show']);
+
+ // repeated expenses controller:
+ Route::get('/repeatedexpenses', ['uses' => 'RepeatedExpenseController@index', 'as' => 'repeated.index']);
+ Route::get('/repeatedexpenses/create', ['uses' => 'RepeatedExpenseController@create', 'as' => 'repeated.create']);
+ Route::get('/repeatedexpenses/show/{repeated}', ['uses' => 'RepeatedExpenseController@show', 'as' => 'repeated.show']);
// report controller:
Route::get('/reports', ['uses' => 'ReportController@index', 'as' => 'reports.index']);
Route::get('/reports/{year}', ['uses' => 'ReportController@year', 'as' => 'reports.year']);
+ Route::get('/reports/budgets/{year}/{month}', ['uses' => 'ReportController@budgets', 'as' => 'reports.budgets']);
+ Route::get('/reports/unbalanced/{year}/{month}', ['uses' => 'ReportController@unbalanced', 'as' => 'reports.unbalanced']);
+
+ // reminder controller
+ Route::get('/reminders/{reminder}', ['uses' => 'ReminderController@show', 'as' => 'reminders.show']);
+ Route::get('/reminders/{reminder}/dismiss', ['uses' => 'ReminderController@dismiss', 'as' => 'reminders.dismiss']);
+ Route::get('/reminders/{reminder}/notnow', ['uses' => 'ReminderController@notnow', 'as' => 'reminders.notnow']);
+ Route::get('/reminders/{reminder}/act', ['uses' => 'ReminderController@act', 'as' => 'reminders.act']);
// search controller:
Route::get('/search', ['uses' => 'SearchController@index', 'as' => 'search']);
// transaction controller:
- Route::get('/transactions/create/{what}', ['uses' => 'TransactionController@create', 'as' => 'transactions.create'])->where(
- ['what' => 'withdrawal|deposit|transfer']
+ Route::get('/transactions/{what}', ['uses' => 'TransactionController@index', 'as' => 'transactions.index'])->where(
+ ['what' => 'expenses|revenue|withdrawal|deposit|transfer|transfers']
+ );
+ Route::get('/transactions/create/{what}', ['uses' => 'TransactionController@create', 'as' => 'transactions.create'])->where(
+ ['what' => 'expenses|revenue|withdrawal|deposit|transfer|transfers']
);
- Route::get('/transaction/show/{tj}', ['uses' => 'TransactionController@show', 'as' => 'transactions.show']);
Route::get('/transaction/edit/{tj}', ['uses' => 'TransactionController@edit', 'as' => 'transactions.edit']);
Route::get('/transaction/delete/{tj}', ['uses' => 'TransactionController@delete', 'as' => 'transactions.delete']);
- Route::get('/transactions/index', ['uses' => 'TransactionController@index', 'as' => 'transactions.index']);
- Route::get('/transactions/expenses', ['uses' => 'TransactionController@expenses', 'as' => 'transactions.expenses']);
- Route::get('/transactions/revenue', ['uses' => 'TransactionController@revenue', 'as' => 'transactions.revenue']);
- Route::get('/transactions/transfers', ['uses' => 'TransactionController@transfers', 'as' => 'transactions.transfers']);
-
- Route::get('/transactions/expenses', ['uses' => 'TransactionController@expenses', 'as' => 'transactions.index.withdrawal']);
- Route::get('/transactions/revenue', ['uses' => 'TransactionController@revenue', 'as' => 'transactions.index.deposit']);
- Route::get('/transactions/transfers', ['uses' => 'TransactionController@transfers', 'as' => 'transactions.index.transfer']);
+ Route::get('/transaction/show/{tj}', ['uses' => 'TransactionController@show', 'as' => 'transactions.show']);
+ Route::get('/transaction/relate/{tj}', ['uses' => 'TransactionController@relate', 'as' => 'transactions.relate']);
+ Route::post('/transactions/relatedSearch/{tj}', ['uses' => 'TransactionController@relatedSearch', 'as' => 'transactions.relatedSearch']);
+ Route::post('/transactions/alreadyRelated/{tj}', ['uses' => 'TransactionController@alreadyRelated', 'as' => 'transactions.alreadyRelated']);
+ Route::post('/transactions/doRelate', ['uses' => 'TransactionController@doRelate', 'as' => 'transactions.doRelate']);
+ Route::any('/transactions/unrelate/{tj}', ['uses' => 'TransactionController@unrelate', 'as' => 'transactions.unrelate']);
// user controller
Route::get('/logout', ['uses' => 'UserController@logout', 'as' => 'logout']);
@@ -281,8 +281,8 @@ Route::group(
// budget controller:
Route::post('/budgets/income', ['uses' => 'BudgetController@postUpdateIncome', 'as' => 'budgets.postIncome']);
- Route::post('/budgets/update/{budget}', ['uses' => 'BudgetController@update', 'as' => 'budgets.update']);
Route::post('/budgets/store', ['uses' => 'BudgetController@store', 'as' => 'budgets.store']);
+ Route::post('/budgets/update/{budget}', ['uses' => 'BudgetController@update', 'as' => 'budgets.update']);
Route::post('/budgets/destroy/{budget}', ['uses' => 'BudgetController@destroy', 'as' => 'budgets.destroy']);
// category controller
@@ -290,23 +290,15 @@ Route::group(
Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']);
Route::post('/categories/destroy/{category}', ['uses' => 'CategoryController@destroy', 'as' => 'categories.destroy']);
- // limit controller:
- Route::post('/budgets/limits/store/{budget?}', ['uses' => 'LimitController@store', 'as' => 'budgets.limits.store']);
- Route::post('/budgets/limits/destroy/{limit}', ['uses' => 'LimitController@destroy', 'as' => 'budgets.limits.destroy']);
- Route::post('/budgets/limits/update/{limit}', ['uses' => 'LimitController@update', 'as' => 'budgets.limits.update']);
-
- Route::post('/migrate/upload', ['uses' => 'MigrateController@upload', 'as' => 'migrate.upload']);
-
-
// piggy bank controller
Route::post('/piggybanks/store', ['uses' => 'PiggybankController@store', 'as' => 'piggybanks.store']);
- #Route::post('/piggybanks/store/repeated', ['uses' => 'PiggybankController@storeRepeated', 'as' => 'piggybanks.store.repeated']);
Route::post('/piggybanks/update/{piggybank}', ['uses' => 'PiggybankController@update', 'as' => 'piggybanks.update']);
Route::post('/piggybanks/destroy/{piggybank}', ['uses' => 'PiggybankController@destroy', 'as' => 'piggybanks.destroy']);
- #Route::post('/piggybanks/mod/{piggybank}', ['uses' => 'PiggybankController@modMoney', 'as' => 'piggybanks.modMoney']);
- Route::post('/piggybanks/add/{piggybank}', ['uses' => 'PiggybankController@postAdd', 'as' => 'piggybanks.add']);
- Route::post('/piggybanks/remove/{piggybank}', ['uses' => 'PiggybankController@postRemove', 'as' => 'piggybanks.remove']);
+ Route::post('/piggybanks/add/{piggybank}', ['uses' => 'PiggybankController@postAdd', 'as' => 'piggybanks.add']); # add money
+ Route::post('/piggybanks/remove/{piggybank}', ['uses' => 'PiggybankController@postRemove', 'as' => 'piggybanks.remove']); # remove money.
+ // repeated expense controller
+ Route::post('/repeatedexpense/store', ['uses' => 'RepeatedExpenseController@store', 'as' => 'repeated.store']);
// preferences controller
Route::post('/preferences', ['uses' => 'PreferencesController@postIndex']);
@@ -321,7 +313,7 @@ Route::group(
// transaction controller:
Route::post('/transactions/store/{what}', ['uses' => 'TransactionController@store', 'as' => 'transactions.store'])->where(
- ['what' => 'withdrawal|deposit|transfer']
+ ['what' => 'expenses|revenue|withdrawal|deposit|transfer|transfers']
);
Route::post('/transaction/update/{tj}', ['uses' => 'TransactionController@update', 'as' => 'transactions.update']);
Route::post('/transaction/destroy/{tj}', ['uses' => 'TransactionController@destroy', 'as' => 'transactions.destroy']);
diff --git a/app/start/artisan.php b/app/start/artisan.php
index 1df850bc95..3b223f16ec 100644
--- a/app/start/artisan.php
+++ b/app/start/artisan.php
@@ -11,3 +11,4 @@
|
*/
+Artisan::add(new Cleanup);
\ No newline at end of file
diff --git a/app/start/global.php b/app/start/global.php
index 10109df498..5604f492bb 100644
--- a/app/start/global.php
+++ b/app/start/global.php
@@ -14,10 +14,7 @@
ClassLoader::addDirectories(
[
- app_path() . '/commands',
- app_path() . '/controllers',
- app_path() . '/models',
- app_path() . '/database/seeds',
+ app_path() . '/commands', app_path() . '/controllers', app_path() . '/models', app_path() . '/database/seeds',
]
);
@@ -74,47 +71,47 @@ App::down(
// forms:
\Form::macro(
'ffText', function ($name, $value = null, array $options = []) {
- return \Firefly\Form\Form::ffText($name, $value, $options);
+ return \FireflyIII\Form\Form::ffText($name, $value, $options);
}
);
\Form::macro(
'ffSelect', function ($name, array $list = [], $selected = null, array $options = []) {
- return \Firefly\Form\Form::ffSelect($name, $list, $selected, $options);
+ return \FireflyIII\Form\Form::ffSelect($name, $list, $selected, $options);
}
);
\Form::macro(
'ffInteger', function ($name, $value = null, array $options = []) {
- return \Firefly\Form\Form::ffInteger($name, $value, $options);
+ return \FireflyIII\Form\Form::ffInteger($name, $value, $options);
}
);
\Form::macro(
'ffAmount', function ($name, $value = null, array $options = []) {
- return \Firefly\Form\Form::ffAmount($name, $value, $options);
+ return \FireflyIII\Form\Form::ffAmount($name, $value, $options);
}
);
\Form::macro(
'ffBalance', function ($name, $value = null, array $options = []) {
- return \Firefly\Form\Form::ffBalance($name, $value, $options);
+ return \FireflyIII\Form\Form::ffBalance($name, $value, $options);
}
);
\Form::macro(
'ffDate', function ($name, $value = null, array $options = []) {
- return \Firefly\Form\Form::ffDate($name, $value, $options);
+ return \FireflyIII\Form\Form::ffDate($name, $value, $options);
}
);
\Form::macro(
'ffTags', function ($name, $value = null, array $options = []) {
- return \Firefly\Form\Form::ffTags($name, $value, $options);
+ return \FireflyIII\Form\Form::ffTags($name, $value, $options);
}
);
\Form::macro(
'ffCheckbox', function ($name, $value = 1, $checked = null, $options = []) {
- return \Firefly\Form\Form::ffCheckbox($name, $value, $checked, $options);
+ return \FireflyIII\Form\Form::ffCheckbox($name, $value, $checked, $options);
}
);
\Form::macro(
'ffOptionsList', function ($type, $name) {
- return \Firefly\Form\Form::ffOptionsList($type, $name);
+ return \FireflyIII\Form\Form::ffOptionsList($type, $name);
}
);
diff --git a/app/tests/TestCase.php b/app/tests/TestCase.php
index f6230dd2ef..c0d01d3355 100644
--- a/app/tests/TestCase.php
+++ b/app/tests/TestCase.php
@@ -1,24 +1,19 @@
seed();
+
+
+ //$this->
}
- /**
- * @param $class
- *
- * @return \Mockery\MockInterface
- */
public function mock($class)
{
$mock = Mockery::mock($class);
@@ -44,4 +38,13 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase
return $mock;
}
-}
+ static public function setupBeforeClass()
+ {
+ League\FactoryMuffin\Facade::loadFactories(__DIR__ . '/factories');
+ }
+
+ public function tearDown()
+ {
+ m::close();
+ }
+}
\ No newline at end of file
diff --git a/app/tests/factories/TransactionCurrency.php b/app/tests/factories/TransactionCurrency.php
new file mode 100644
index 0000000000..9804dd56c2
--- /dev/null
+++ b/app/tests/factories/TransactionCurrency.php
@@ -0,0 +1,7 @@
+ 'word',
+ ]
+);
diff --git a/app/tests/factories/TransactionJournal.php b/app/tests/factories/TransactionJournal.php
new file mode 100644
index 0000000000..58fd89d200
--- /dev/null
+++ b/app/tests/factories/TransactionJournal.php
@@ -0,0 +1,12 @@
+ 'factory|TransactionType',
+ 'transaction_currency_id' => 'factory|TransactionCurrency',
+ 'description' => 'text',
+ 'date' => 'date|Y-m-d',
+ 'completed' => 'boolean',
+ 'user_id' => 'factory|User'
+ ]
+);
diff --git a/app/tests/factories/TransactionType.php b/app/tests/factories/TransactionType.php
new file mode 100644
index 0000000000..0876277d2c
--- /dev/null
+++ b/app/tests/factories/TransactionType.php
@@ -0,0 +1,7 @@
+ 'word',
+ ]
+);
diff --git a/app/tests/factories/User.php b/app/tests/factories/User.php
new file mode 100644
index 0000000000..c7a74e8e82
--- /dev/null
+++ b/app/tests/factories/User.php
@@ -0,0 +1,8 @@
+ 'email',
+ 'migrated' => 1,
+ 'password' => 'empty'
+ ]
+);
diff --git a/app/views/accounts/create.blade.php b/app/views/accounts/create.blade.php
index edf174bce6..ac7ec268f8 100644
--- a/app/views/accounts/create.blade.php
+++ b/app/views/accounts/create.blade.php
@@ -1,5 +1,6 @@
@extends('layouts.default')
@section('content')
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $what) }}
{{Form::open(['class' => 'form-horizontal','route' => 'accounts.store'])}}
{{Form::hidden('what',$what)}}
@@ -32,6 +33,7 @@
{{Form::ffDate('openingbalancedate', date('Y-m-d'))}}
@endif
{{Form::ffCheckbox('active','1',true)}}
+ {{Form::ffSelect('account_role',Config::get('firefly.accountRoles'))}}
diff --git a/app/views/accounts/delete.blade.php b/app/views/accounts/delete.blade.php
index 6f2059a15e..5140108559 100644
--- a/app/views/accounts/delete.blade.php
+++ b/app/views/accounts/delete.blade.php
@@ -1,5 +1,6 @@
@extends('layouts.default')
@section('content')
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $account) }}
{{Form::open(['class' => 'form-horizontal','url' => route('accounts.destroy',$account->id)])}}
diff --git a/app/views/accounts/edit.blade.php b/app/views/accounts/edit.blade.php
index 39e14486ca..6a596f87ba 100644
--- a/app/views/accounts/edit.blade.php
+++ b/app/views/accounts/edit.blade.php
@@ -1,13 +1,6 @@
@extends('layouts.default')
@section('content')
-
-
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $account) }}
{{Form::model($account, ['class' => 'form-horizontal','url' => route('accounts.update',$account->id)])}}
@@ -35,6 +28,7 @@
@if($account->accounttype->type == 'Default account' || $account->accounttype->type == 'Asset account')
{{Form::ffBalance('openingbalance')}}
{{Form::ffDate('openingbalancedate')}}
+ {{Form::ffSelect('account_role',Config::get('firefly.accountRoles'))}}
@endif
diff --git a/app/views/accounts/index.blade.php b/app/views/accounts/index.blade.php
index 2410bc6c8e..c98c6e38b1 100644
--- a/app/views/accounts/index.blade.php
+++ b/app/views/accounts/index.blade.php
@@ -1,5 +1,6 @@
@extends('layouts.default')
@section('content')
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $what) }}
@@ -21,9 +22,7 @@
-
+ @include('list.accounts')
@@ -39,8 +38,5 @@
{{HTML::script('assets/javascript/firefly/gcharts.js')}}
-
-@stop
-
-@section('styles')
-@endsection
\ No newline at end of file
+{{HTML::script('assets/javascript/firefly/accounts.js')}}
+@stop
\ No newline at end of file
diff --git a/app/views/accounts/show.blade.php b/app/views/accounts/show.blade.php
index 8d5842fd67..9445421f28 100644
--- a/app/views/accounts/show.blade.php
+++ b/app/views/accounts/show.blade.php
@@ -1,5 +1,6 @@
@extends('layouts.default')
@section('content')
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $account) }}
@@ -14,6 +15,20 @@
@include('partials.date_nav')
+
@@ -48,7 +63,7 @@
Transactions
-
+ @include('list.journals-full')
@@ -59,6 +74,7 @@
@section('scripts')
diff --git a/app/views/budgets/create.blade.php b/app/views/budgets/create.blade.php
index 0b20da4663..28e28e4712 100644
--- a/app/views/budgets/create.blade.php
+++ b/app/views/budgets/create.blade.php
@@ -1,5 +1,6 @@
@extends('layouts.default')
@section('content')
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) }}
{{Form::open(['class' => 'form-horizontal','url' => route('budgets.store')])}}
diff --git a/app/views/budgets/delete.blade.php b/app/views/budgets/delete.blade.php
index 96775a8357..bf16e4881a 100644
--- a/app/views/budgets/delete.blade.php
+++ b/app/views/budgets/delete.blade.php
@@ -1,5 +1,6 @@
@extends('layouts.default')
@section('content')
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $budget) }}
{{Form::open(['class' => 'form-horizontal','url' => route('budgets.destroy',$budget->id)])}}
diff --git a/app/views/budgets/edit.blade.php b/app/views/budgets/edit.blade.php
index baeeb1cc8c..8fefee9bfd 100644
--- a/app/views/budgets/edit.blade.php
+++ b/app/views/budgets/edit.blade.php
@@ -1,5 +1,6 @@
@extends('layouts.default')
@section('content')
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $budget) }}
Use budgets to organize and limit your expenses.
diff --git a/app/views/budgets/index.blade.php b/app/views/budgets/index.blade.php
index 9dd76b21e6..dbcdb2ff41 100644
--- a/app/views/budgets/index.blade.php
+++ b/app/views/budgets/index.blade.php
@@ -1,5 +1,6 @@
@extends('layouts.default')
@section('content')
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) }}
@@ -19,10 +20,10 @@
-
+
@if($overspent)
@else
-
+
@endif
@@ -130,55 +131,6 @@
-
-
-@foreach($budgets as $budget)
-{{--
-
-
-
-
- {{$budget->name}}
-
-
-
-
-
-
-
-
-
-
- @if($budget->pct > 0)
-
-
-
-
- @else
-
-
-
-
- @endif
-
-
-
-
-
---}}
-@endforeach
-
diff --git a/app/views/budgets/show.blade.php b/app/views/budgets/show.blade.php
index 2cdc0f3e14..80e24ff00a 100644
--- a/app/views/budgets/show.blade.php
+++ b/app/views/budgets/show.blade.php
@@ -1,14 +1,14 @@
@extends('layouts.default')
@section('content')
-
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $budget, $repetition) }}
@@ -16,9 +16,7 @@
Transactions
-
+ @include('list.journals-full')
@@ -73,7 +71,7 @@
@stop
@section('scripts')
+{{HTML::script('assets/javascript/firefly/gcharts.options.js')}}
+{{HTML::script('assets/javascript/firefly/gcharts.js')}}
+{{HTML::script('assets/javascript/firefly/categories.js')}}
@stop
\ No newline at end of file
diff --git a/app/views/categories/show.blade.php b/app/views/categories/show.blade.php
index f6f4678b6d..16555e7a9e 100644
--- a/app/views/categories/show.blade.php
+++ b/app/views/categories/show.blade.php
@@ -1,44 +1,44 @@
@extends('layouts.default')
@section('content')
-
-
-
+{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $category) }}
-
-
Use categories to group your expenses
-
- Use categories to group expenses by hobby, for certain types of groceries or what bills are for.
- Expenses grouped in categories do not have to reoccur every month or every week, like budgets.
-
-
- This overview will show you the expenses you've made in each [period] and show you the actual
- transactions for the currently selected period.
-
-
-
+
+
-
-@include('partials.date_nav')
-
-
-
+
+
+ Transactions
+
+
+ @include('list.journals-full')
+
-
-
-
-
-
Transactions in current range
- @include('lists.transactions',['journals' => $journals,'sum' => true])
-
+
+
+ BLa bla something here.
-
-
+
@stop
@section('scripts')
+
+
+
+{{HTML::script('assets/javascript/firefly/gcharts.options.js')}}
+{{HTML::script('assets/javascript/firefly/gcharts.js')}}
{{HTML::script('assets/javascript/firefly/categories.js')}}
+
@stop
\ No newline at end of file
diff --git a/app/views/charts/info.blade.php b/app/views/charts/info.blade.php
deleted file mode 100644
index 00e590e129..0000000000
--- a/app/views/charts/info.blade.php
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- Total
- {{mf($sum*-1)}}
-
- @foreach($rows as $name => $entry)
-
- {{{$name}}}
- {{mf($entry['amount']*-1)}}
-
- @endforeach
-
\ No newline at end of file
diff --git a/app/views/emails/auth/reminder.blade.php b/app/views/emails/auth/reminder.blade.php
deleted file mode 100644
index 276f8c59f2..0000000000
--- a/app/views/emails/auth/reminder.blade.php
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
-
-
-
-
-
Password Reset
-
-
- To reset your password, complete this form: {{ URL::to('password/reset', array($token)) }}.
- This link will expire in {{ Config::get('auth.reminder.expire', 60) }} minutes.
-
-
-
-
\ No newline at end of file
diff --git a/app/views/help/show.blade.php b/app/views/help/show.blade.php
new file mode 100644
index 0000000000..e864585fd5
--- /dev/null
+++ b/app/views/help/show.blade.php
@@ -0,0 +1,14 @@
+
+
+
+
+ {{$helpText}}
+
+
+
+
diff --git a/app/views/index.blade.php b/app/views/index.blade.php
index 66857d7cfd..587f3a6f34 100644
--- a/app/views/index.blade.php
+++ b/app/views/index.blade.php
@@ -1,30 +1,19 @@
@extends('layouts.default')
@section('content')
-{{ Breadcrumbs::render('home') }}
+{{ Breadcrumbs::renderIfExists() }}
@if($count == 0)
Welcome to Firefly III.
- To get get started, choose below:
+ Create a new asset account to get started.
-
-
-
-
- Use this option if you have a JSON file from your current Firefly II installation.
-
-
-
-
- Use this option if you are new to Firefly (III).
-
@else
@@ -112,7 +101,7 @@
- @include('transactions.journals-small-index',['transactions' => $data[0],'account' => $data[1]])
+ @include('list.journals-tiny',['transactions' => $data[0],'account' => $data[1]])
@endforeach
@@ -121,6 +110,7 @@
@endif
+
@stop
@section('scripts')
diff --git a/app/views/layouts/default.blade.php b/app/views/layouts/default.blade.php
index 346742569b..ffad378639 100644
--- a/app/views/layouts/default.blade.php
+++ b/app/views/layouts/default.blade.php
@@ -1,5 +1,6 @@
+getName();?>
@@ -17,13 +18,15 @@
{{HTML::style('assets/stylesheets/metisMenu/metisMenu.min.css')}}
{{HTML::style('assets/stylesheets/sbadmin/sb.css')}}
{{HTML::style('assets/stylesheets/fa/css/font-awesome.min.css')}}
- {{HTML::style('http://fonts.googleapis.com/css?family=Roboto2')}}
+ {{HTML::style('https://fonts.googleapis.com/css?family=Roboto2')}}
@yield('styles')
+
+
@@ -47,31 +50,47 @@
{{$subTitle}}
@endif
+
+
@include('partials.flashes')
-
@yield('content')
+
+
+
-
{{HTML::script('assets/javascript/jquery/jquery-2.1.1.min.js')}}
{{HTML::script('assets/javascript/bootstrap/bootstrap.min.js')}}
{{HTML::script('assets/javascript/metisMenu/jquery.metisMenu.min.js')}}
{{HTML::script('assets/javascript/sb-admin/sb-admin-2.js')}}
+{{HTML::script('assets/javascript/firefly/help.js')}}
@yield('scripts')
\ No newline at end of file
diff --git a/app/views/layouts/guest.blade.php b/app/views/layouts/guest.blade.php
index df2a721548..85966199ce 100644
--- a/app/views/layouts/guest.blade.php
+++ b/app/views/layouts/guest.blade.php
@@ -5,7 +5,7 @@
-
Firefly
+
Firefly III
{{HTML::style('assets/stylesheets/bootstrap/bootstrap.min.css')}}
{{HTML::style('assets/stylesheets/metisMenu/metisMenu.min.css')}}
@@ -18,6 +18,8 @@
+
+
@@ -25,4 +27,4 @@
@yield('content')
-