diff --git a/.coveralls.yml b/.coveralls.yml index 68c3d23770..8951ac7b73 100644 --- a/.coveralls.yml +++ b/.coveralls.yml @@ -1,3 +1,3 @@ src_dir: . coverage_clover: tests/_output/coverage.xml -json_path: tests/_output/coveralls-upload.json \ No newline at end of file +json_path: tests/_output/coveralls-upload.json diff --git a/.gitignore b/.gitignore index 71d8f61ce0..90cd6c6a45 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ composer.phar .env.*.php .env.php -.DS_Store Thumbs.db .idea/ tests/_output/* @@ -23,3 +22,6 @@ tests/unit/UnitTester.php pi.php tests/_data/db.sqlite tests/_data/dump.sql +db.sqlite_snapshot +c3.php +db.sqlite-journal diff --git a/.travis.yml b/.travis.yml index 7638995c02..1f82f07b02 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,4 +13,4 @@ script: - php vendor/bin/codecept run --coverage --coverage-xml after_script: - - php vendor/bin/coveralls \ No newline at end of file + - php vendor/bin/coveralls diff --git a/README.md b/README.md index 25c2f0d92b..06fc100514 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Firefly III [![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=develop)](https://travis-ci.org/JC5/firefly-iii) [![Project Status](http://stillmaintained.com/JC5/firefly-iii.png?a=b)](http://stillmaintained.com/JC5/firefly-iii) [![Coverage Status](https://coveralls.io/repos/JC5/firefly-iii/badge.png?branch=master)](https://coveralls.io/r/JC5/firefly-iii?branch=master) +[![SensioLabsInsight](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102/mini.png)](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102) [![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable.svg)](https://packagist.org/packages/grumpydictator/firefly-iii) [![Total Downloads](https://poser.pugx.org/grumpydictator/firefly-iii/downloads.svg)](https://packagist.org/packages/grumpydictator/firefly-iii) @@ -70,4 +71,4 @@ I have the basics up and running. Test coverage is currently coming, slowly. Although I have not checked extensively, some forms and views have CSRF vulnerabilities. This is because not all views escape all characters by default. Will be fixed. -Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)! \ No newline at end of file +Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)! diff --git a/app/breadcrumbs.php b/app/breadcrumbs.php index 3269c6e773..126c478c30 100644 --- a/app/breadcrumbs.php +++ b/app/breadcrumbs.php @@ -17,347 +17,353 @@ Breadcrumbs::register( // accounts Breadcrumbs::register( 'accounts.index', function (Generator $breadcrumbs, $what) { - $breadcrumbs->parent('home'); - $breadcrumbs->push(ucfirst($what) . ' accounts', route('accounts.index', $what)); - } + $breadcrumbs->parent('home'); + $breadcrumbs->push(ucfirst(e($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)); + 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 'Cash account': + $what = 'cash'; + break; + case 'Expense account': + case 'Beneficiary account': + $what = 'expense'; + break; + case 'Revenue account': + $what = 'revenue'; + break; } + $breadcrumbs->parent('accounts.index', $what); + $breadcrumbs->push(e($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->parent('accounts.show', $account); + $breadcrumbs->push('Delete ' . e($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)); - } + $breadcrumbs->parent('accounts.show', $account); + $breadcrumbs->push('Edit ' . e($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->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->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->parent('budgets.show', $budget); + $breadcrumbs->push('Edit ' . e($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->parent('budgets.show', $budget); + $breadcrumbs->push('Delete ' . e($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->budgetlimit->repeat_freq), route('budgets.show', $budget->id, $repetition->id) - ); - } + $breadcrumbs->parent('budgets.index'); + $breadcrumbs->push(e($budget->name), route('budgets.show', $budget->id)); + if (!is_null($repetition)) { + $breadcrumbs->push( + DateKit::periodShow($repetition->startdate, $repetition->budgetlimit->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->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->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->parent('categories.show', $category); + $breadcrumbs->push('Edit ' . e($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->parent('categories.show', $category); + $breadcrumbs->push('Delete ' . e($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)); + $breadcrumbs->parent('categories.index'); + $breadcrumbs->push(e($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')); - } + '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')); - } + '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)); - } + 'piggyBanks.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('piggyBanks.show', $piggyBank); + $breadcrumbs->push('Edit ' . e($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)); - } + 'piggyBanks.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('piggyBanks.show', $piggyBank); + $breadcrumbs->push('Delete ' . e($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)); + 'piggyBanks.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('piggyBanks.index'); + $breadcrumbs->push(e($piggyBank->name), route('piggyBanks.show', $piggyBank->id)); - } +} ); // preferences Breadcrumbs::register( 'preferences', function (Generator $breadcrumbs) { - $breadcrumbs->parent('home'); - $breadcrumbs->push('Preferences', route('preferences')); + $breadcrumbs->parent('home'); + $breadcrumbs->push('Preferences', route('preferences')); - } +} ); // profile Breadcrumbs::register( 'profile', function (Generator $breadcrumbs) { - $breadcrumbs->parent('home'); - $breadcrumbs->push('Profile', route('profile')); + $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')); + $breadcrumbs->parent('profile'); + $breadcrumbs->push('Change your password', route('change-password')); - } +} ); -// recurring transactions +// bills Breadcrumbs::register( - 'recurring.index', function (Generator $breadcrumbs) { - $breadcrumbs->parent('home'); - $breadcrumbs->push('Recurring transactions', route('recurring.index')); - } + 'bills.index', function (Generator $breadcrumbs) { + $breadcrumbs->parent('home'); + $breadcrumbs->push('Bills', route('bills.index')); +} ); Breadcrumbs::register( - 'recurring.create', function (Generator $breadcrumbs) { - $breadcrumbs->parent('recurring.index'); - $breadcrumbs->push('Create new recurring transaction', route('recurring.create')); - } + 'bills.create', function (Generator $breadcrumbs) { + $breadcrumbs->parent('bills.index'); + $breadcrumbs->push('Create new bill', route('bills.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)); - } + 'bills.edit', function (Generator $breadcrumbs, Bill $bill) { + $breadcrumbs->parent('bills.show', $bill); + $breadcrumbs->push('Edit ' . e($bill->name), route('bills.edit', $bill->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)); - } + 'bills.delete', function (Generator $breadcrumbs, Bill $bill) { + $breadcrumbs->parent('bills.show', $bill); + $breadcrumbs->push('Delete ' . e($bill->name), route('bills.delete', $bill->id)); +} ); Breadcrumbs::register( - 'recurring.show', function (Generator $breadcrumbs, RecurringTransaction $recurring) { - $breadcrumbs->parent('recurring.index'); - $breadcrumbs->push($recurring->name, route('recurring.show', $recurring->id)); + 'bills.show', function (Generator $breadcrumbs, Bill $bill) { + $breadcrumbs->parent('bills.index'); + $breadcrumbs->push(e($bill->name), route('bills.show', $bill->id)); - } +} ); // reminders Breadcrumbs::register( 'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) { - $breadcrumbs->parent('home'); - $breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id)); + $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->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->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)); - } + 'repeated.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('repeated.show', $piggyBank); + $breadcrumbs->push('Edit ' . e($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)); - } + 'repeated.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('repeated.show', $piggyBank); + $breadcrumbs->push('Delete ' . e($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)); + 'repeated.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) { + $breadcrumbs->parent('repeated.index'); + $breadcrumbs->push(e($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->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->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'))); - } + 'reports.month', function (Generator $breadcrumbs, Carbon $date) { + $breadcrumbs->parent('reports.index'); + $breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', $date)); +} ); + 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'))); - } + 'reports.budget', function (Generator $breadcrumbs, Carbon $date) { + $breadcrumbs->parent('reports.index'); + $breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', $date)); +} ); + // search Breadcrumbs::register( 'search', function (Generator $breadcrumbs, $query) { - $breadcrumbs->parent('home'); - $breadcrumbs->push('Search for "' . e($query) . '"', route('search')); - } + $breadcrumbs->parent('home'); + $breadcrumbs->push('Search for "' . e($query) . '"', route('search')); +} ); // transactions Breadcrumbs::register( 'transactions.index', function (Generator $breadcrumbs, $what) { - $breadcrumbs->parent('home'); + $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)); + 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->parent('transactions.index', $what); + $breadcrumbs->push('Create new ' .e($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->parent('transactions.show', $journal); + $breadcrumbs->push('Edit ' . e($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->parent('transactions.show', $journal); + $breadcrumbs->push('Delete ' . e($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)); + $breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type)); + $breadcrumbs->push(e($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 index 76b734fe53..db76195588 100644 --- a/app/commands/Cleanup.php +++ b/app/commands/Cleanup.php @@ -1,8 +1,6 @@ info('Cleared compiled...'); Artisan::call('ide-helper:generate'); $this->info('IDE helper, done...'); - Artisan::call('ide-helper:models', ['nowrite']); + Artisan::call('ide-helper:models'); $this->info('IDE models, done...'); Artisan::call('optimize'); $this->info('Optimized...'); diff --git a/app/config/.gitignore b/app/config/.gitignore index 8205aab29b..10601ce198 100644 --- a/app/config/.gitignore +++ b/app/config/.gitignore @@ -1,4 +1,4 @@ local/ laptop/ vagrant/ -production/ \ No newline at end of file +production/ diff --git a/app/config/compile.php b/app/config/compile.php index b993871588..0b67a5fe47 100644 --- a/app/config/compile.php +++ b/app/config/compile.php @@ -1,3 +1,3 @@ '' -]; \ No newline at end of file +]; diff --git a/app/config/firefly.php b/app/config/firefly.php index eea3380786..c17ca873e3 100644 --- a/app/config/firefly.php +++ b/app/config/firefly.php @@ -3,7 +3,7 @@ return [ 'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'], 'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'], - 'piggybank_periods' => [ + 'piggy_bank_periods' => [ 'week' => 'Week', 'month' => 'Month', 'quarter' => 'Quarter', @@ -46,4 +46,4 @@ return [ '6M' => 'half-year', 'custom' => 'monthly' ], -]; \ No newline at end of file +]; diff --git a/app/config/homestead/app.php b/app/config/homestead/app.php index b6d461000d..0f1dd6a103 100644 --- a/app/config/homestead/app.php +++ b/app/config/homestead/app.php @@ -12,4 +12,4 @@ return [ */ 'debug' => true, 'log_level' => 'debug', -]; \ No newline at end of file +]; diff --git a/app/config/homestead/database.php b/app/config/homestead/database.php index 29737579f8..d585027ae3 100644 --- a/app/config/homestead/database.php +++ b/app/config/homestead/database.php @@ -34,4 +34,4 @@ return [ ], -]; \ No newline at end of file +]; diff --git a/app/config/queue.php b/app/config/queue.php old mode 100755 new mode 100644 diff --git a/app/config/testing/app.php b/app/config/testing/app.php index e729eb5ab7..7f9d13d6fb 100644 --- a/app/config/testing/app.php +++ b/app/config/testing/app.php @@ -1,2 +1,2 @@ 'debug',]; \ No newline at end of file +return ['log_level' => 'debug',]; diff --git a/app/config/testing/database.php b/app/config/testing/database.php index 3517df8d20..e0be6a4063 100644 --- a/app/config/testing/database.php +++ b/app/config/testing/database.php @@ -9,4 +9,4 @@ return [ ] ] -]; \ No newline at end of file +]; diff --git a/app/config/testingInMemory/app.php b/app/config/testingInMemory/app.php new file mode 100644 index 0000000000..7f9d13d6fb --- /dev/null +++ b/app/config/testingInMemory/app.php @@ -0,0 +1,2 @@ + 'debug',]; diff --git a/app/config/testingInMemory/auth.php b/app/config/testingInMemory/auth.php new file mode 100644 index 0000000000..0fe9e0172d --- /dev/null +++ b/app/config/testingInMemory/auth.php @@ -0,0 +1,8 @@ + false, + 'verify_reset' => true, + 'allow_register' => true + +]; diff --git a/app/config/testingInMemory/cache.php b/app/config/testingInMemory/cache.php new file mode 100644 index 0000000000..fef1e78b52 --- /dev/null +++ b/app/config/testingInMemory/cache.php @@ -0,0 +1,3 @@ + 'array',]; diff --git a/app/config/testingInMemory/database.php b/app/config/testingInMemory/database.php new file mode 100644 index 0000000000..06b50aa143 --- /dev/null +++ b/app/config/testingInMemory/database.php @@ -0,0 +1,12 @@ + 'sqlite', + 'connections' => [ + 'sqlite' => [ + 'driver' => 'sqlite', + 'database' => ':memory:', + 'prefix' => '' + ] + + ] +]; diff --git a/app/config/testingInMemory/mail.php b/app/config/testingInMemory/mail.php new file mode 100644 index 0000000000..d2df78f4cd --- /dev/null +++ b/app/config/testingInMemory/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/testingInMemory/session.php b/app/config/testingInMemory/session.php new file mode 100644 index 0000000000..fef1e78b52 --- /dev/null +++ b/app/config/testingInMemory/session.php @@ -0,0 +1,3 @@ + 'array',]; diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index 190df02a5d..b09766ed02 100644 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -28,6 +28,7 @@ class AccountController extends BaseController 'Expense account' => 'expense', 'Beneficiary account' => 'expense', 'Revenue account' => 'revenue', + 'Cash account' => 'cash', ]; /** @var array */ @@ -36,6 +37,7 @@ class AccountController extends BaseController 'asset' => 'fa-money', 'Asset account' => 'fa-money', 'Default account' => 'fa-money', + 'Cash account' => 'fa-money', 'expense' => 'fa-shopping-cart', 'Expense account' => 'fa-shopping-cart', 'Beneficiary account' => 'fa-shopping-cart', @@ -68,7 +70,7 @@ class AccountController extends BaseController public function create($what) { $subTitleIcon = $this->_subIconsByIdentifier[$what]; - $subTitle = 'Create a new ' . $what . ' account'; + $subTitle = 'Create a new ' . e($what) . ' account'; return View::make('accounts.create', compact('subTitleIcon', 'what', 'subTitle')); } @@ -80,7 +82,7 @@ class AccountController extends BaseController */ public function delete(Account $account) { - $subTitle = 'Delete ' . strtolower($account->accountType->type) . ' "' . $account->name . '"'; + $subTitle = 'Delete ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; return View::make('accounts.delete', compact('account', 'subTitle')); } @@ -99,7 +101,7 @@ class AccountController extends BaseController $this->_repository->destroy($account); - Session::flash('success', 'The ' . $typeName . ' account "' . e($name) . '" was deleted.'); + Session::flash('success', 'The ' . e($typeName) . ' account "' . e($name) . '" was deleted.'); return Redirect::route('accounts.index', $typeName); } @@ -114,7 +116,7 @@ class AccountController extends BaseController $openingBalance = $this->_repository->openingBalanceTransaction($account); $subTitleIcon = $this->_subIconsByIdentifier[$account->accountType->type]; - $subTitle = 'Edit ' . strtolower($account->accountType->type) . ' "' . $account->name . '"'; + $subTitle = 'Edit ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; // pre fill some useful values. $preFilled = [ @@ -155,7 +157,7 @@ class AccountController extends BaseController $subTitleIcon = $this->_subIconsByIdentifier[$account->accountType->type]; $what = $this->_shortNamesByFullName[$account->accountType->type]; $journals = $this->_repository->getTransactionJournals($account, 50, $range); - $subTitle = 'Details for ' . strtolower($account->accountType->type) . ' "' . $account->name . '"'; + $subTitle = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; return View::make('accounts.show', compact('account', 'what', 'range', 'subTitleIcon', 'journals', 'subTitle')); } @@ -182,17 +184,17 @@ class AccountController extends BaseController // return to create screen: if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { - return Redirect::route('accounts.create', $data['what'])->withInput(); + return Redirect::route('accounts.create', e($data['what']))->withInput(); } - // store: + // store $this->_repository->store($data); Session::flash('success', 'Account "' . e($data['name']) . '" stored.'); if ($data['post_submit_action'] == 'store') { - return Redirect::route('accounts.index', $data['what']); + return Redirect::route('accounts.index', e($data['what'])); } - return Redirect::route('accounts.create', $data['what'])->withInput(); + return Redirect::route('accounts.create', e($data['what']))->withInput(); } /** @@ -229,10 +231,10 @@ class AccountController extends BaseController // go back to list if ($data['post_submit_action'] == 'update') { - return Redirect::route('accounts.index', $data['what']); + return Redirect::route('accounts.index', e($data['what'])); } // go back to update screen. return Redirect::route('accounts.edit', $account->id)->withInput(['post_submit_action' => 'return_to_edit']); } -} \ No newline at end of file +} diff --git a/app/controllers/BillController.php b/app/controllers/BillController.php new file mode 100644 index 0000000000..521c21736b --- /dev/null +++ b/app/controllers/BillController.php @@ -0,0 +1,212 @@ +_repository = $repository; + + View::share('title', 'Bills'); + View::share('mainTitleIcon', 'fa-calendar-o'); + } + + /** + * @return $this + */ + public function create() + { + $periods = \Config::get('firefly.periods_to_text'); + + return View::make('bills.create')->with('periods', $periods)->with('subTitle', 'Create new'); + } + + /** + * @param Bill $bill + * + * @return $this + */ + public function delete(Bill $bill) + { + return View::make('bills.delete')->with('bill', $bill)->with( + 'subTitle', 'Delete "' . e($bill->name) . '"' + ); + } + + /** + * @param Bill $bill + * + * @return \Illuminate\Http\RedirectResponse + */ + public function destroy(Bill $bill) + { + $this->_repository->destroy($bill); + Session::flash('success', 'The bill was deleted.'); + + return Redirect::route('bills.index'); + + } + + /** + * @param Bill $bill + * + * @return $this + */ + public function edit(Bill $bill) + { + $periods = \Config::get('firefly.periods_to_text'); + + return View::make('bills.edit')->with('periods', $periods)->with('bill', $bill)->with( + 'subTitle', 'Edit "' . e($bill->name) . '"' + ); + } + + /** + * @return $this + */ + public function index() + { + $bills = $this->_repository->get(); + $bills->each( + function (Bill $bill) { + $bill->nextExpectedMatch = $this->_repository->nextExpectedMatch($bill); + $bill->lastFoundMatch = $this->_repository->lastFoundMatch($bill); + } + ); + + return View::make('bills.index', compact('bills')); + } + + /** + * @param Bill $bill + * + * @return mixed + */ + public function rescan(Bill $bill) + { + if (intval($bill->active) == 0) { + Session::flash('warning', 'Inactive bills cannot be scanned.'); + + return Redirect::intended('/'); + } + + $this->_repository->scanEverything($bill); + + Session::flash('success', 'Rescanned everything.'); + + return Redirect::intended('/'); + } + + /** + * @param Bill $bill + * + * @return mixed + */ + public function show(Bill $bill) + { + $journals = $bill->transactionjournals()->withRelevantData()->orderBy('date', 'DESC')->get(); + $bill->nextExpectedMatch = $this->_repository->nextExpectedMatch($bill); + $hideBill = true; + + + return View::make('bills.show', compact('journals', 'hideBill', 'bill'))->with( + 'subTitle', e($bill->name) + ); + } + + /** + * @return $this + * @throws FireflyException + */ + public function store() + { + $data = Input::all(); + $data['user_id'] = Auth::user()->id; + + + // always validate: + $messages = $this->_repository->validate($data); + + // flash messages: + Session::flash('warnings', $messages['warnings']); + Session::flash('successes', $messages['successes']); + Session::flash('errors', $messages['errors']); + if ($messages['errors']->count() > 0) { + Session::flash('error', 'Could not store bill: ' . $messages['errors']->first()); + } + + // return to create screen: + if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { + return Redirect::route('bills.create')->withInput(); + } + + // store + $this->_repository->store($data); + Session::flash('success', 'Bill "' . e($data['name']) . '" stored.'); + if ($data['post_submit_action'] == 'store') { + return Redirect::route('bills.index'); + } + + return Redirect::route('bills.create')->withInput(); + + } + + /** + * @param Bill $bill + * + * @return $this + * @throws FireflyException + */ + public function update(Bill $bill) + { + $data = Input::except('_token'); + $data['active'] = isset($data['active']) ? 1 : 0; + $data['automatch'] = isset($data['automatch']) ? 1 : 0; + $data['user_id'] = Auth::user()->id; + + // always validate: + $messages = $this->_repository->validate($data); + + // flash messages: + Session::flash('warnings', $messages['warnings']); + Session::flash('successes', $messages['successes']); + Session::flash('errors', $messages['errors']); + if ($messages['errors']->count() > 0) { + Session::flash('error', 'Could not update bill: ' . $messages['errors']->first()); + } + + // return to update screen: + if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { + return Redirect::route('bills.edit', $bill->id)->withInput(); + } + + // update + $this->_repository->update($bill, $data); + Session::flash('success', 'Bill "' . e($data['name']) . '" updated.'); + + // go back to list + if ($data['post_submit_action'] == 'update') { + return Redirect::route('bills.index'); + } + + // go back to update screen. + return Redirect::route('bills.edit', $bill->id)->withInput(['post_submit_action' => 'return_to_edit']); + + } +} diff --git a/app/controllers/BudgetController.php b/app/controllers/BudgetController.php index a3fa3bd014..c2888d1eab 100644 --- a/app/controllers/BudgetController.php +++ b/app/controllers/BudgetController.php @@ -99,7 +99,6 @@ class BudgetController extends BaseController /** * The index of the budget controller contains all budgets and the current relevant limit repetition. - * TODO move currentRep to the repository. * * @return $this */ @@ -179,7 +178,7 @@ class BudgetController extends BaseController return Redirect::route('budgets.create')->withInput(); } - // store: + // store $this->_repository->store($data); Session::flash('success', 'Budget "' . e($data['name']) . '" stored.'); if ($data['post_submit_action'] == 'store') { diff --git a/app/controllers/CategoryController.php b/app/controllers/CategoryController.php index b6d6da5df8..9994e30e2d 100644 --- a/app/controllers/CategoryController.php +++ b/app/controllers/CategoryController.php @@ -41,7 +41,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 "' . e($category->name) . '"'); } /** @@ -65,7 +65,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 "' . e($category->name) . '"'); } /** @@ -116,7 +116,7 @@ class CategoryController extends BaseController return Redirect::route('categories.create')->withInput(); } - // store: + // store $this->_repository->store($data); Session::flash('success', 'Category "' . e($data['name']) . '" stored.'); if ($data['post_submit_action'] == 'store') { @@ -169,4 +169,4 @@ class CategoryController extends BaseController } -} \ No newline at end of file +} diff --git a/app/controllers/CurrencyController.php b/app/controllers/CurrencyController.php index bc2ae575ea..d8c2d5b5d6 100644 --- a/app/controllers/CurrencyController.php +++ b/app/controllers/CurrencyController.php @@ -61,6 +61,8 @@ class CurrencyController extends BaseController /** * @param TransactionCurrency $currency + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View */ public function delete(TransactionCurrency $currency) { @@ -74,6 +76,11 @@ class CurrencyController extends BaseController return View::make('currency.delete', compact('currency')); } + /** + * @param TransactionCurrency $currency + * + * @return \Illuminate\Http\RedirectResponse + */ public function destroy(TransactionCurrency $currency) { Session::flash('success', 'Currency "' . e($currency->name) . '" deleted'); @@ -98,6 +105,9 @@ class CurrencyController extends BaseController } + /** + * @return \Illuminate\View\View + */ public function index() { $currencies = $this->_repository->get(); @@ -112,6 +122,9 @@ class CurrencyController extends BaseController return View::make('currency.index', compact('currencies', 'defaultCurrency')); } + /** + * @return $this|\Illuminate\Http\RedirectResponse + */ public function store() { $data = Input::except('_token'); @@ -132,7 +145,7 @@ class CurrencyController extends BaseController return Redirect::route('currency.create')->withInput(); } - // store: + // store $this->_repository->store($data); Session::flash('success', 'Currency "' . e($data['name']) . '" stored.'); if ($data['post_submit_action'] == 'store') { @@ -143,6 +156,11 @@ class CurrencyController extends BaseController } + /** + * @param TransactionCurrency $currency + * + * @return $this|\Illuminate\Http\RedirectResponse + */ public function update(TransactionCurrency $currency) { $data = Input::except('_token'); @@ -176,4 +194,4 @@ class CurrencyController extends BaseController } -} \ No newline at end of file +} diff --git a/app/controllers/GoogleChartController.php b/app/controllers/GoogleChartController.php index 2a5786c5f6..8edd0fe797 100644 --- a/app/controllers/GoogleChartController.php +++ b/app/controllers/GoogleChartController.php @@ -47,7 +47,6 @@ class GoogleChartController extends BaseController $this->_chart->addColumn('Day of month', 'date'); $this->_chart->addColumn('Balance for ' . $account->name, 'number'); - // TODO this can be combined in some method, it's coming up quite often, is it? $start = $this->_start; $end = $this->_end; $count = $account->transactions()->count(); @@ -62,7 +61,6 @@ class GoogleChartController extends BaseController $start = new Carbon($first->date); $end = new Carbon($last->date); } - // todo until this part. $current = clone $start; @@ -86,7 +84,7 @@ 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\Account $acct */ $acct = App::make('FireflyIII\Database\Account\Account'); @@ -97,6 +95,7 @@ class GoogleChartController extends BaseController $this->_chart->addColumn('Balance for ' . $account->name, 'number'); } $current = clone $this->_start; + $current->subDay(); while ($this->_end >= $current) { $row = [clone $current]; @@ -131,18 +130,18 @@ class GoogleChartController extends BaseController /** @var Budget $budget */ foreach ($budgets as $budget) { - Log::debug('Now working budget #'.$budget->id.', '.$budget->name); + Log::debug('Now working budget #' . $budget->id . ', ' . $budget->name); /** @var \LimitRepetition $repetition */ $repetition = $bdt->repetitionOnStartingOnDate($budget, $this->_start); if (is_null($repetition)) { - \Log::debug('Budget #'.$budget->id.' has no repetition on ' . $this->_start->format('Y-m-d')); + \Log::debug('Budget #' . $budget->id . ' has no repetition on ' . $this->_start->format('Y-m-d')); // use the session start and end for our search query $searchStart = $this->_start; $searchEnd = $this->_end; $limit = 0; // the limit is zero: } else { - \Log::debug('Budget #'.$budget->id.' has a repetition on ' . $this->_start->format('Y-m-d').'!'); + \Log::debug('Budget #' . $budget->id . ' has a repetition on ' . $this->_start->format('Y-m-d') . '!'); // use the limit's start and end for our search query $searchStart = $repetition->startdate; $searchEnd = $repetition->enddate; @@ -150,6 +149,7 @@ class GoogleChartController extends BaseController } $expenses = floatval($budget->transactionjournals()->before($searchEnd)->after($searchStart)->lessThan(0)->sum('amount')) * -1; + \Log::debug('Expenses in budget ' . $budget->name . ' before ' . $searchEnd->format('Y-m-d') . ' and after ' . $searchStart . ' are: ' . $expenses); if ($expenses > 0) { $this->_chart->addRow($budget->name, $limit, $expenses); } @@ -186,7 +186,75 @@ class GoogleChartController extends BaseController } /** - * TODO still in use? + * @param Bill $bill + * + * @return \Illuminate\Http\JsonResponse + */ + public function billOverview(Bill $bill) + { + + $this->_chart->addColumn('Date', 'date'); + $this->_chart->addColumn('Max amount', 'number'); + $this->_chart->addColumn('Min amount', 'number'); + $this->_chart->addColumn('Current entry', 'number'); + + // get first transaction or today for start: + $first = $bill->transactionjournals()->orderBy('date', 'ASC')->first(); + if ($first) { + $start = $first->date; + } else { + $start = new Carbon; + } + $end = new Carbon; + while ($start <= $end) { + $result = $bill->transactionjournals()->before($end)->after($start)->first(); + if ($result) { + $amount = $result->getAmount(); + } else { + $amount = 0; + } + unset($result); + $this->_chart->addRow(clone $start, $bill->amount_max, $bill->amount_min, $amount); + $start = DateKit::addPeriod($start, $bill->repeat_freq, 0); + } + + $this->_chart->generate(); + + return Response::json($this->_chart->getData()); + + } + + /** + * + * @return \Illuminate\Http\JsonResponse + * @throws \FireflyIII\Exception\FireflyException + */ + public function billsOverview() + { + $paid = ['items' => [], 'amount' => 0]; + $unpaid = ['items' => [], 'amount' => 0]; + $this->_chart->addColumn('Name', 'string'); + $this->_chart->addColumn('Amount', 'number'); + + $set = $this->_repository->getBillsSummary($this->_start, $this->_end); + + foreach ($set as $entry) { + if (intval($entry->journalId) == 0) { + $unpaid['items'][] = $entry->name; + $unpaid['amount'] += floatval($entry->averageAmount); + } else { + $paid['items'][] = $entry->description; + $paid['amount'] += floatval($entry->actualAmount); + } + } + $this->_chart->addRow('Unpaid: ' . join(', ', $unpaid['items']), $unpaid['amount']); + $this->_chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']); + $this->_chart->generate(); + + return Response::json($this->_chart->getData()); + } + + /** * * @param Budget $budget * @param LimitRepetition $repetition @@ -220,14 +288,13 @@ class GoogleChartController extends BaseController } /** - * TODO still in use? * - * @param Budget $component + * @param Budget $budget * @param $year * * @return \Illuminate\Http\JsonResponse */ - public function budgetsAndSpending(Budget $component, $year) + public function budgetsAndSpending(Budget $budget, $year) { try { new Carbon('01-01-' . $year); @@ -235,8 +302,8 @@ class GoogleChartController extends BaseController return View::make('error')->with('message', 'Invalid year.'); } - /** @var \FireflyIII\Database\Budget\Budget $repos */ - $repos = App::make('FireflyIII\Database\Budget\Budget'); + /** @var \FireflyIII\Database\Budget\Budget $budgetRepository */ + $budgetRepository = App::make('FireflyIII\Database\Budget\Budget'); $this->_chart->addColumn('Month', 'date'); $this->_chart->addColumn('Budgeted', 'number'); @@ -246,11 +313,14 @@ class GoogleChartController extends BaseController $end = clone $start; $end->endOfYear(); while ($start <= $end) { - $spent = $repos->spentInMonth($component, $start); - $repetition = $repos->repetitionOnStartingOnDate($component, $start); + $spent = $budgetRepository->spentInMonth($budget, $start); + $repetition = $budgetRepository->repetitionOnStartingOnDate($budget, $start); + if ($repetition) { $budgeted = floatval($repetition->amount); + \Log::debug('Found a repetition on ' . $start->format('Y-m-d'). ' for budget ' . $budget->name.'!'); } else { + \Log::debug('No repetition on ' . $start->format('Y-m-d'). ' for budget ' . $budget->name); $budgeted = null; } @@ -268,7 +338,6 @@ class GoogleChartController extends BaseController } /** - * TODO still in use? * * @param Category $component * @param $year @@ -283,8 +352,8 @@ class GoogleChartController extends BaseController return View::make('error')->with('message', 'Invalid year.'); } - /** @var \FireflyIII\Database\Category\Category $repos */ - $repos = App::make('FireflyIII\Database\Category\Category'); + /** @var \FireflyIII\Database\Category\Category $categoryRepository */ + $categoryRepository = App::make('FireflyIII\Database\Category\Category'); $this->_chart->addColumn('Month', 'date'); $this->_chart->addColumn('Budgeted', 'number'); @@ -295,7 +364,7 @@ class GoogleChartController extends BaseController $end->endOfYear(); while ($start <= $end) { - $spent = $repos->spentInMonth($component, $start); + $spent = $categoryRepository->spentInMonth($component, $start); $budgeted = null; $this->_chart->addRow(clone $start, $budgeted, $spent); @@ -312,16 +381,16 @@ class GoogleChartController extends BaseController } /** - * @param Piggybank $piggybank + * @param PiggyBank $piggyBank * * @return \Illuminate\Http\JsonResponse */ - public function piggyBankHistory(\Piggybank $piggybank) + public function piggyBankHistory(\PiggyBank $piggyBank) { $this->_chart->addColumn('Date', 'date'); $this->_chart->addColumn('Balance', 'number'); - $set = \DB::table('piggy_bank_events')->where('piggybank_id', $piggybank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]); + $set = \DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]); foreach ($set as $entry) { $this->_chart->addRow(new Carbon($entry->date), floatval($entry->sum)); @@ -334,77 +403,6 @@ class GoogleChartController extends BaseController } /** - * @param RecurringTransaction $recurring - * - * @return \Illuminate\Http\JsonResponse - */ - public function recurringOverview(RecurringTransaction $recurring) - { - - $this->_chart->addColumn('Date', 'date'); - $this->_chart->addColumn('Max amount', 'number'); - $this->_chart->addColumn('Min amount', 'number'); - $this->_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); - $this->_chart->addRow(clone $start, $recurring->amount_max, $recurring->amount_min, $amount); - $start = DateKit::addPeriod($start, $recurring->repeat_freq, 0); - } - - $this->_chart->generate(); - - return Response::json($this->_chart->getData()); - - } - - /** - * TODO query move to helper. - * - * @return \Illuminate\Http\JsonResponse - * @throws \FireflyIII\Exception\FireflyException - */ - public function recurringTransactionsOverview() - { - $paid = ['items' => [], 'amount' => 0]; - $unpaid = ['items' => [], 'amount' => 0]; - $this->_chart->addColumn('Name', 'string'); - $this->_chart->addColumn('Amount', 'number'); - - $set = $this->_repository->getRecurringSummary($this->_start, $this->_end); - - foreach ($set as $entry) { - if (intval($entry->journalId) == 0) { - $unpaid['items'][] = $entry->name; - $unpaid['amount'] += floatval($entry->averageAmount); - } else { - $paid['items'][] = $entry->description; - $paid['amount'] += floatval($entry->actualAmount); - } - } - $this->_chart->addRow('Unpaid: ' . join(', ', $unpaid['items']), $unpaid['amount']); - $this->_chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']); - $this->_chart->generate(); - - return Response::json($this->_chart->getData()); - } - - /** - * TODO see reports for better way to do this. * * @param $year * @@ -444,7 +442,6 @@ class GoogleChartController extends BaseController } /** - * TODO see reports for better way to do this. * * @param $year * @@ -488,4 +485,4 @@ class GoogleChartController extends BaseController return Response::json($this->_chart->getData()); } -} \ No newline at end of file +} diff --git a/app/controllers/HelpController.php b/app/controllers/HelpController.php index ee5f57fbfc..813b8faf5c 100644 --- a/app/controllers/HelpController.php +++ b/app/controllers/HelpController.php @@ -1,6 +1,8 @@ There is no help for this route!

'; $helpTitle = 'Help'; if (!Route::has($route)) { + \Log::error('No such route: ' . $route); + 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'); @@ -27,12 +29,20 @@ class HelpController extends BaseController } $uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md'; + \Log::debug('URL is: ' . $uri); try { - $content = file_get_contents($uri); + $helpText = file_get_contents($uri); } catch (ErrorException $e) { - $content = '

There is no help for this route.

'; + \Log::error(trim($e->getMessage())); } - $helpText = \Michelf\Markdown::defaultTransform($content); + \Log::debug('Found help for ' . $route); + \Log::debug('Help text length for route ' . $route . ' is ' . strlen($helpText)); + \Log::debug('Help text IS: "' . $helpText . '".'); + if (strlen(trim($helpText)) == 0) { + $helpText = '

There is no help for this route.

'; + } + + $helpText = \Michelf\Markdown::defaultTransform($helpText); $helpTitle = $route; Cache::put('help.' . $route . '.text', $helpText, 10080); // a week. @@ -41,4 +51,4 @@ class HelpController extends BaseController 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 faea3a7f68..090e24e3a1 100644 --- a/app/controllers/HomeController.php +++ b/app/controllers/HomeController.php @@ -26,8 +26,8 @@ class HomeController extends BaseController /** @var \FireflyIII\Database\Account\Account $acct */ $acct = App::make('FireflyIII\Database\Account\Account'); - /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $jrnls */ - $jrnls = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); + /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $journalRepository */ + $journalRepository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); /** @var \FireflyIII\Shared\Preferences\PreferencesInterface $preferences */ $preferences = App::make('FireflyIII\Shared\Preferences\PreferencesInterface'); @@ -39,16 +39,16 @@ class HomeController extends BaseController // get the preference for the home accounts to show: - $frontpage = $preferences->get('frontpageAccounts', []); - if ($frontpage->data == []) { + $frontPage = $preferences->get('frontPageAccounts', []); + if ($frontPage->data == []) { $accounts = $acct->getAssetAccounts(); } else { - $accounts = $acct->getByIds($frontpage->data); + $accounts = $acct->getByIds($frontPage->data); } $transactions = []; foreach ($accounts as $account) { - $set = $jrnls->getInDateRangeAccount($account, $start, $end, 10); + $set = $journalRepository->getInDateRangeAccount($account, $start, $end, 10); if (count($set) > 0) { $transactions[] = [$set, $account]; } @@ -99,4 +99,4 @@ class HomeController extends BaseController return Redirect::intended('/'); } -} \ No newline at end of file +} diff --git a/app/controllers/JsonController.php b/app/controllers/JsonController.php index 094a3fc040..fedc5768d2 100644 --- a/app/controllers/JsonController.php +++ b/app/controllers/JsonController.php @@ -62,4 +62,4 @@ class JsonController extends BaseController return Response::json($return); } -} \ No newline at end of file +} diff --git a/app/controllers/PiggybankController.php b/app/controllers/PiggybankController.php index 307197ac32..ce7da9f704 100644 --- a/app/controllers/PiggybankController.php +++ b/app/controllers/PiggybankController.php @@ -13,10 +13,10 @@ use Illuminate\Support\Collection; * @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove. * * - * Class PiggybankController + * Class PiggyBankController * */ -class PiggybankController extends BaseController +class PiggyBankController extends BaseController { /** @var Repository */ @@ -35,29 +35,21 @@ class PiggybankController extends BaseController /** * Add money to piggy bank * - * @param Piggybank $piggybank + * @param PiggyBank $piggyBank * * @return $this */ - public function add(Piggybank $piggybank) + public function add(PiggyBank $piggyBank) { - \Log::debug('Now in add() for piggy bank #' . $piggybank->id . ' (' . $piggybank->name . ')'); - \Log::debug('Z'); - \Log::debug('currentRelevantRep is null: ' . boolstr($piggybank->currentRelevantRep())); - $leftOnAccount = $this->_repository->leftOnAccount($piggybank->account); - \Log::debug('A'); - - $savedSoFar = $piggybank->currentRelevantRep()->currentamount; - \Log::debug('B'); - $leftToSave = $piggybank->targetamount - $savedSoFar; - \Log::debug('C'); - $maxAmount = min($leftOnAccount, $leftToSave); - \Log::debug('D'); + $leftOnAccount = $this->_repository->leftOnAccount($piggyBank->account); + $savedSoFar = $piggyBank->currentRelevantRep()->currentamount; + $leftToSave = $piggyBank->targetamount - $savedSoFar; + $maxAmount = min($leftOnAccount, $leftToSave); - \Log::debug('Now going to view for piggy bank #' . $piggybank->id . ' (' . $piggybank->name . ')'); + \Log::debug('Now going to view for piggy bank #' . $piggyBank->id . ' (' . $piggyBank->name . ')'); - return View::make('piggybanks.add', compact('piggybank', 'maxAmount')); + return View::make('piggy_banks.add', compact('piggyBank', 'maxAmount')); } /** @@ -69,75 +61,75 @@ class PiggybankController extends BaseController /** @var \FireflyIII\Database\Account\Account $acct */ $acct = App::make('FireflyIII\Database\Account\Account'); - $periods = Config::get('firefly.piggybank_periods'); + $periods = Config::get('firefly.piggy_bank_periods'); $accounts = FFForm::makeSelectList($acct->getAssetAccounts()); $subTitle = 'Create new piggy bank'; $subTitleIcon = 'fa-plus'; - return View::make('piggybanks.create', compact('accounts', 'periods', 'subTitle', 'subTitleIcon')); + return View::make('piggy_banks.create', compact('accounts', 'periods', 'subTitle', 'subTitleIcon')); } /** - * @param Piggybank $piggybank + * @param PiggyBank $piggyBank * * @return $this */ - public function delete(Piggybank $piggybank) + public function delete(PiggyBank $piggyBank) { - $subTitle = 'Delete "' . e($piggybank->name) . '"'; + $subTitle = 'Delete "' . e($piggyBank->name) . '"'; - return View::make('piggybanks.delete', compact('piggybank', 'subTitle')); + return View::make('piggy_banks.delete', compact('piggyBank', 'subTitle')); } /** - * @param Piggybank $piggyBank + * @param PiggyBank $piggyBank * * @return \Illuminate\Http\RedirectResponse */ - public function destroy(Piggybank $piggyBank) + public function destroy(PiggyBank $piggyBank) { Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.'); $this->_repository->destroy($piggyBank); - return Redirect::route('piggybanks.index'); + return Redirect::route('piggy_banks.index'); } /** - * @param Piggybank $piggybank + * @param PiggyBank $piggyBank * * @return $this */ - public function edit(Piggybank $piggybank) + public function edit(PiggyBank $piggyBank) { /** @var \FireflyIII\Database\Account\Account $acct */ $acct = App::make('FireflyIII\Database\Account\Account'); - $periods = Config::get('firefly.piggybank_periods'); + $periods = Config::get('firefly.piggy_bank_periods'); $accounts = FFForm::makeSelectList($acct->getAssetAccounts()); - $subTitle = 'Edit piggy bank "' . e($piggybank->name) . '"'; + $subTitle = 'Edit piggy bank "' . e($piggyBank->name) . '"'; $subTitleIcon = 'fa-pencil'; /* * Flash some data to fill the form. */ - if (is_null($piggybank->targetdate) || $piggybank->targetdate == '') { + if (is_null($piggyBank->targetdate) || $piggyBank->targetdate == '') { $targetDate = null; } else { - $targetDate = new Carbon($piggybank->targetdate); + $targetDate = new Carbon($piggyBank->targetdate); $targetDate = $targetDate->format('Y-m-d'); } - $preFilled = ['name' => $piggybank->name, - 'account_id' => $piggybank->account_id, - 'targetamount' => $piggybank->targetamount, + $preFilled = ['name' => $piggyBank->name, + 'account_id' => $piggyBank->account_id, + 'targetamount' => $piggyBank->targetamount, 'targetdate' => $targetDate, - 'reminder' => $piggybank->reminder, - 'remind_me' => intval($piggybank->remind_me) == 1 || !is_null($piggybank->reminder) ? true : false + '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('subTitle', 'subTitleIcon', 'piggybank', 'accounts', 'periods', 'preFilled')); + return View::make('piggy_banks.edit', compact('subTitle', 'subTitleIcon', 'piggyBank', 'accounts', 'periods', 'preFilled')); } /** @@ -145,134 +137,134 @@ class PiggybankController extends BaseController */ public function index() { - /** @var Collection $piggybanks */ - $piggybanks = $this->_repository->get(); + /** @var Collection $piggyBanks */ + $piggyBanks = $this->_repository->get(); $accounts = []; - /** @var Piggybank $piggybank */ - foreach ($piggybanks as $piggybank) { - $piggybank->savedSoFar = floatval($piggybank->currentRelevantRep()->currentamount); - $piggybank->percentage = intval($piggybank->savedSoFar / $piggybank->targetamount * 100); - $piggybank->leftToSave = $piggybank->targetamount - $piggybank->savedSoFar; + /** @var PiggyBank $piggyBank */ + foreach ($piggyBanks as $piggyBank) { + $piggyBank->savedSoFar = floatval($piggyBank->currentRelevantRep()->currentamount); + $piggyBank->percentage = intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100); + $piggyBank->leftToSave = $piggyBank->targetamount - $piggyBank->savedSoFar; /* * Fill account information: */ - $account = $piggybank->account; + $account = $piggyBank->account; if (!isset($accounts[$account->id])) { $accounts[$account->id] = [ 'name' => $account->name, 'balance' => Steam::balance($account), - 'leftForPiggybanks' => $this->_repository->leftOnAccount($account), - 'sumOfSaved' => $piggybank->savedSoFar, - 'sumOfTargets' => floatval($piggybank->targetamount), - 'leftToSave' => $piggybank->leftToSave + 'leftForPiggyBanks' => $this->_repository->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; + $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')); + return View::make('piggy_banks.index', compact('piggyBanks', 'accounts')); } /** * POST add money to piggy bank * - * @param Piggybank $piggybank + * @param PiggyBank $piggyBank * * @return \Illuminate\Http\RedirectResponse */ - public function postAdd(Piggybank $piggybank) + public function postAdd(PiggyBank $piggyBank) { $amount = round(floatval(Input::get('amount')), 2); /** @var \FireflyIII\Database\PiggyBank\PiggyBank $acct */ - $repos = App::make('FireflyIII\Database\PiggyBank\PiggyBank'); + $piggyRepository = App::make('FireflyIII\Database\PiggyBank\PiggyBank'); - $leftOnAccount = $repos->leftOnAccount($piggybank->account); - $savedSoFar = $piggybank->currentRelevantRep()->currentamount; - $leftToSave = $piggybank->targetamount - $savedSoFar; + $leftOnAccount = $piggyRepository->leftOnAccount($piggyBank->account); + $savedSoFar = $piggyBank->currentRelevantRep()->currentamount; + $leftToSave = $piggyBank->targetamount - $savedSoFar; $maxAmount = round(min($leftOnAccount, $leftToSave), 2); if ($amount <= $maxAmount) { - $repetition = $piggybank->currentRelevantRep(); + $repetition = $piggyBank->currentRelevantRep(); $repetition->currentamount += $amount; $repetition->save(); /* * Create event! */ - Event::fire('piggybank.addMoney', [$piggybank, $amount]); // new and used. + Event::fire('piggy_bank.addMoney', [$piggyBank, $amount]); // new and used. - Session::flash('success', 'Added ' . mf($amount, false) . ' to "' . e($piggybank->name) . '".'); + Session::flash('success', 'Added ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".'); } else { - Session::flash('error', 'Could not add ' . mf($amount, false) . ' to "' . e($piggybank->name) . '".'); + Session::flash('error', 'Could not add ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".'); } - return Redirect::route('piggybanks.index'); + return Redirect::route('piggy_banks.index'); } /** - * @param Piggybank $piggybank + * @param PiggyBank $piggyBank * * @return \Illuminate\Http\RedirectResponse */ - public function postRemove(Piggybank $piggybank) + public function postRemove(PiggyBank $piggyBank) { $amount = floatval(Input::get('amount')); - $savedSoFar = $piggybank->currentRelevantRep()->currentamount; + $savedSoFar = $piggyBank->currentRelevantRep()->currentamount; if ($amount <= $savedSoFar) { - $repetition = $piggybank->currentRelevantRep(); + $repetition = $piggyBank->currentRelevantRep(); $repetition->currentamount -= $amount; $repetition->save(); /* * Create event! */ - Event::fire('piggybank.removeMoney', [$piggybank, $amount]); // new and used. + Event::fire('piggy_bank.removeMoney', [$piggyBank, $amount]); // new and used. - Session::flash('success', 'Removed ' . mf($amount, false) . ' from "' . e($piggybank->name) . '".'); + Session::flash('success', 'Removed ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".'); } else { - Session::flash('error', 'Could not remove ' . mf($amount, false) . ' from "' . e($piggybank->name) . '".'); + Session::flash('error', 'Could not remove ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".'); } - return Redirect::route('piggybanks.index'); + return Redirect::route('piggy_banks.index'); } /** - * @param Piggybank $piggybank + * @param PiggyBank $piggyBank + * + * @SuppressWarnings("Unused") * * @return \Illuminate\View\View */ - public function remove(Piggybank $piggybank) + public function remove(PiggyBank $piggyBank) { - return View::make('piggybanks.remove')->with('piggybank', $piggybank); + return View::make('piggy_banks.remove', compact('piggyBank')); } /** - * @param Piggybank $piggybank + * @param PiggyBank $piggyBank * * @return $this */ - public function show(Piggybank $piggybank) + public function show(PiggyBank $piggyBank) { - $events = $piggybank->piggybankevents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get(); + $events = $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get(); /* * Number of reminders: */ - $amountPerReminder = $piggybank->amountPerReminder(); - $remindersCount = $piggybank->countFutureReminders(); - $subTitle = e($piggybank->name); + $subTitle = e($piggyBank->name); - return View::make('piggybanks.show', compact('amountPerReminder', 'remindersCount', 'piggybank', 'events', 'subTitle')); + return View::make('piggy_banks.show', compact('piggyBank', 'events', 'subTitle')); } @@ -300,27 +292,27 @@ class PiggybankController extends BaseController // return to create screen: if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { - return Redirect::route('piggybanks.create')->withInput(); + return Redirect::route('piggy_banks.create')->withInput(); } - // store: + // store $piggyBank = $this->_repository->store($data); - Event::fire('piggybank.store', [$piggyBank]); // new and used. + Event::fire('piggy_bank.store', [$piggyBank]); // new and used. Session::flash('success', 'Piggy bank "' . e($data['name']) . '" stored.'); if ($data['post_submit_action'] == 'store') { - return Redirect::route('piggybanks.index'); + return Redirect::route('piggy_banks.index'); } - return Redirect::route('piggybanks.create')->withInput(); + return Redirect::route('piggy_banks.create')->withInput(); } /** - * @param Piggybank $piggyBank + * @param PiggyBank $piggyBank * * @return $this * @throws FireflyException */ - public function update(Piggybank $piggyBank) + public function update(PiggyBank $piggyBank) { $data = Input::except('_token'); @@ -329,11 +321,11 @@ class PiggybankController extends BaseController $data['order'] = 0; $data['remind_me'] = isset($data['remind_me']) ? 1 : 0; $data['user_id'] = Auth::user()->id; + $data['repeats'] = 0; // always validate: $messages = $this->_repository->validate($data); - // flash messages: Session::flash('warnings', $messages['warnings']); Session::flash('successes', $messages['successes']); Session::flash('errors', $messages['errors']); @@ -343,7 +335,7 @@ class PiggybankController extends BaseController // return to update screen: if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { - return Redirect::route('piggybanks.edit', $piggyBank->id)->withInput(); + return Redirect::route('piggy_banks.edit', $piggyBank->id)->withInput(); } // update @@ -352,11 +344,11 @@ class PiggybankController extends BaseController // go back to list if ($data['post_submit_action'] == 'update') { - return Redirect::route('piggybanks.index'); + return Redirect::route('piggy_banks.index'); } // go back to update screen. - return Redirect::route('piggybanks.edit', $piggyBank->id)->withInput(['post_submit_action' => 'return_to_edit']); + return Redirect::route('piggy_banks.edit', $piggyBank->id)->withInput(['post_submit_action' => 'return_to_edit']); } -} \ No newline at end of file +} diff --git a/app/controllers/PreferencesController.php b/app/controllers/PreferencesController.php index 1330af52ef..b1a5ca0fc7 100644 --- a/app/controllers/PreferencesController.php +++ b/app/controllers/PreferencesController.php @@ -32,11 +32,11 @@ class PreferencesController extends BaseController $accounts = $acct->getAssetAccounts(); $viewRange = $preferences->get('viewRange', '1M'); $viewRangeValue = $viewRange->data; - $frontPage = $preferences->get('frontpageAccounts', []); + $frontPage = $preferences->get('frontPageAccounts', []); $budgetMax = $preferences->get('budgetMaximum', 1000); $budgetMaximum = $budgetMax->data; - return View::make('preferences.index', compact('budgetMaximum'))->with('accounts', $accounts)->with('frontpageAccounts', $frontPage)->with( + return View::make('preferences.index', compact('budgetMaximum'))->with('accounts', $accounts)->with('frontPageAccounts', $frontPage)->with( 'viewRange', $viewRangeValue ); } @@ -49,12 +49,12 @@ class PreferencesController extends BaseController /** @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); + // front page accounts + $frontPageAccounts = []; + foreach (Input::get('frontPageAccounts') as $id) { + $frontPageAccounts[] = intval($id); } - $preferences->set('frontpageAccounts', $frontpageAccounts); + $preferences->set('frontPageAccounts', $frontPageAccounts); // view range: $preferences->set('viewRange', Input::get('viewRange')); @@ -73,4 +73,4 @@ class PreferencesController extends BaseController return Redirect::route('preferences'); } -} \ No newline at end of file +} diff --git a/app/controllers/ProfileController.php b/app/controllers/ProfileController.php index d5373ec0c5..e9b397833c 100644 --- a/app/controllers/ProfileController.php +++ b/app/controllers/ProfileController.php @@ -1,6 +1,8 @@ with('periods', $periods)->with('subTitle', 'Create new'); - } - - /** - * @param RecurringTransaction $recurringTransaction - * - * @return $this - */ - public function delete(RecurringTransaction $recurringTransaction) - { - return View::make('recurring.delete')->with('recurringTransaction', $recurringTransaction)->with( - 'subTitle', 'Delete "' . $recurringTransaction->name . '"' - ); - } - - /** - * @param RecurringTransaction $recurringTransaction - * - * @return \Illuminate\Http\RedirectResponse - */ - public function destroy(RecurringTransaction $recurringTransaction) - { - //Event::fire('recurring.destroy', [$recurringTransaction]); - - /** @var \FireflyIII\Database\RecurringTransaction\RecurringTransaction $repository */ - $repository = App::make('FireflyIII\Database\RecurringTransaction\RecurringTransaction'); - - $result = $repository->destroy($recurringTransaction); - if ($result === true) { - Session::flash('success', 'The recurring transaction was deleted.'); - } else { - Session::flash('error', 'Could not delete the recurring transaction. Check the logs to be sure.'); - } - - return Redirect::route('recurring.index'); - - } - - /** - * @param RecurringTransaction $recurringTransaction - * - * @return $this - */ - public function edit(RecurringTransaction $recurringTransaction) - { - $periods = \Config::get('firefly.periods_to_text'); - - return View::make('recurring.edit')->with('periods', $periods)->with('recurringTransaction', $recurringTransaction)->with( - 'subTitle', 'Edit "' . $recurringTransaction->name . '"' - ); - } - - /** - * @return $this - */ - public function index() - { - /** @var \FireflyIII\Database\RecurringTransaction\RecurringTransaction $repos */ - $repos = App::make('FireflyIII\Database\RecurringTransaction\RecurringTransaction'); - - $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(); - } - - /** @var \FireflyIII\Database\RecurringTransaction\RecurringTransaction $repos */ - $repos = App::make('FireflyIII\Database\RecurringTransaction\RecurringTransaction'); - $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'); - /** @var \FireflyIII\Database\RecurringTransaction\RecurringTransaction $repos */ - $repos = App::make('FireflyIII\Database\RecurringTransaction\RecurringTransaction'); - - 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 recurring transaction: ' . $messages['errors']->first()); - - return Redirect::route('recurring.create')->withInput()->withErrors($messages['errors']); - } - // store! - $repos->store($data); - Session::flash('success', 'New recurring transaction stored!'); - - if ($data['post_submit_action'] == 'create_another') { - return Redirect::route('recurring.create')->withInput(); - } else { - return Redirect::route('recurring.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('recurring.create')->withInput(); - break; - } - - } - - /** - * @param RecurringTransaction $recurringTransaction - * - * @return $this - * @throws FireflyException - */ - public function update(RecurringTransaction $recurringTransaction) - { - /** @var \FireflyIII\Database\RecurringTransaction\RecurringTransaction $repos */ - $repos = App::make('FireflyIII\Database\RecurringTransaction\RecurringTransaction'); - $data = Input::except('_token'); - $data['active'] = isset($data['active']) ? 1 : 0; - $data['automatch'] = isset($data['automatch']) ? 1 : 0; - - switch (Input::get('post_submit_action')) { - default: - throw new FireflyException('Cannot handle post_submit_action "' . e(Input::get('post_submit_action')) . '"'); - break; - 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; - } - - } -} \ No newline at end of file diff --git a/app/controllers/RelatedController.php b/app/controllers/RelatedController.php new file mode 100644 index 0000000000..747dad5e3f --- /dev/null +++ b/app/controllers/RelatedController.php @@ -0,0 +1,139 @@ +_repository = $repository; + + } + + /** + * @param TransactionJournal $journal + * + * @return \Illuminate\Http\JsonResponse + */ + public function alreadyRelated(TransactionJournal $journal) + { + $ids = []; + /** @var TransactionGroup $group */ + foreach ($journal->transactiongroups()->get() as $group) { + /** @var TransactionJournal $loopJournal */ + foreach ($group->transactionjournals()->get() as $loopJournal) { + if ($loopJournal->id != $journal->id) { + $ids[] = $loopJournal->id; + } + } + } + $unique = array_unique($ids); + if (count($unique) > 0) { + + $set = $this->_repository->getJournalsByIds($unique); + $set->each( + function (TransactionJournal $journal) { + $journal->amount = Amount::format($journal->getAmount()); + } + ); + + return Response::json($set->toArray()); + } else { + return Response::json((new Collection)->toArray()); + } + } + + /** + * @param TransactionJournal $parentJournal + * @param TransactionJournal $childJournal + * + * @return \Illuminate\Http\JsonResponse + */ + public function relate(TransactionJournal $parentJournal, TransactionJournal $childJournal) + { + $group = new TransactionGroup; + $group->relation = 'balance'; + $group->user_id = $this->_repository->getUser()->id; + $group->save(); + $group->transactionjournals()->save($parentJournal); + $group->transactionjournals()->save($childJournal); + + return Response::json(true); + + } + + /** + * @param TransactionJournal $journal + * + * @return \Illuminate\View\View + */ + public function related(TransactionJournal $journal) + { + $groups = $journal->transactiongroups()->get(); + $members = new Collection; + /** @var TransactionGroup $group */ + foreach ($groups as $group) { + /** @var TransactionJournal $loopJournal */ + foreach ($group->transactionjournals()->get() as $loopJournal) { + if ($loopJournal->id != $journal->id) { + $members->push($loopJournal); + } + } + } + + return View::make('related.relate', compact('journal', 'members')); + } + + /** + * @param TransactionJournal $parentJournal + * @param TransactionJournal $childJournal + * + * @return \Illuminate\Http\JsonResponse + * @throws Exception + */ + public function removeRelation(TransactionJournal $parentJournal, TransactionJournal $childJournal) + { + $groups = $parentJournal->transactiongroups()->get(); + /** @var TransactionGroup $group */ + foreach ($groups as $group) { + foreach ($group->transactionjournals()->get() as $loopJournal) { + if ($loopJournal->id == $childJournal->id) { + // remove from group: + $group->transactionjournals()->detach($childJournal); + } + } + if ($group->transactionjournals()->count() == 1) { + $group->delete(); + } + } + + return Response::json(true); + } + + /** + * @param TransactionJournal $journal + * + * @return \Illuminate\Http\JsonResponse + */ + public function search(TransactionJournal $journal) + { + + $search = e(trim(Input::get('searchValue'))); + + $result = $this->_repository->search($search, $journal); + $result->each( + function (TransactionJournal $j) { + $j->amount = Amount::format($j->getAmount()); + } + ); + + return Response::json($result->toArray()); + } + +} diff --git a/app/controllers/ReminderController.php b/app/controllers/ReminderController.php index e22823e836..7b34fadb04 100644 --- a/app/controllers/ReminderController.php +++ b/app/controllers/ReminderController.php @@ -26,25 +26,22 @@ class ReminderController extends BaseController public function act(Reminder $reminder) { - switch (get_class($reminder->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); + $class = get_class($reminder->remindersable); - return Redirect::route('transactions.create', 'transfer'); - break; + if ($class == 'PiggyBank') { + $amount = Reminders::amountForReminder($reminder); + $preFilled = [ + 'amount' => round($amount, 2), + 'description' => 'Money for ' . $reminder->remindersable->name, + 'piggy_bank_id' => $reminder->remindersable_id, + 'account_to_id' => $reminder->remindersable->account_id + ]; + Session::flash('preFilled', $preFilled); + return Redirect::route('transactions.create', 'transfer'); } + + return View::make('error')->with('message', 'This reminder has an invalid class connected to it.'); } /** @@ -66,7 +63,7 @@ class ReminderController extends BaseController * * @return \Illuminate\Http\RedirectResponse */ - public function notnow(Reminder $reminder) + public function notNow(Reminder $reminder) { $reminder->active = 0; $reminder->notnow = 1; @@ -85,7 +82,7 @@ class ReminderController extends BaseController { $amount = null; - if (get_class($reminder->remindersable) == 'Piggybank') { + if (get_class($reminder->remindersable) == 'PiggyBank') { $amount = Reminders::amountForReminder($reminder); } @@ -93,4 +90,4 @@ class ReminderController extends BaseController 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 index 71f821dfbc..652e255578 100644 --- a/app/controllers/RepeatedExpenseController.php +++ b/app/controllers/RepeatedExpenseController.php @@ -5,6 +5,10 @@ use FireflyIII\Database\PiggyBank\RepeatedExpense as Repository; use FireflyIII\Exception\FireflyException; /** + * @SuppressWarnings("CamelCase") // I'm fine with this. + * @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok. + * @SuppressWarnings("CouplingBetweenObjects") // There's only so much I can remove. + * * Class RepeatedExpenseController */ class RepeatedExpenseController extends BaseController @@ -28,18 +32,72 @@ class RepeatedExpenseController extends BaseController public function create() { /** @var \FireflyIII\Database\Account\Account $acct */ - $acct = App::make('FireflyIII\Database\Account\Account'); - - $periods = Config::get('firefly.piggybank_periods'); - - + $acct = App::make('FireflyIII\Database\Account\Account'); + $periods = Config::get('firefly.piggy_bank_periods'); $accounts = FFForm::makeSelectList($acct->getAssetAccounts()); - return View::make('repeatedexpense.create', compact('accounts', 'periods'))->with('subTitle', 'Create new repeated expense')->with( + return View::make('repeatedExpense.create', compact('accounts', 'periods'))->with('subTitle', 'Create new repeated expense')->with( 'subTitleIcon', 'fa-plus' ); } + /** + * @param PiggyBank $repeatedExpense + * + * @return $this + */ + public function delete(PiggyBank $repeatedExpense) + { + $subTitle = 'Delete "' . e($repeatedExpense->name) . '"'; + + return View::make('repeatedExpense.delete', compact('repeatedExpense', 'subTitle')); + } + + /** + * @param PiggyBank $repeatedExpense + * + * @return \Illuminate\Http\RedirectResponse + */ + public function destroy(PiggyBank $repeatedExpense) + { + + Session::flash('success', 'Repeated expense "' . e($repeatedExpense->name) . '" deleted.'); + $this->_repository->destroy($repeatedExpense); + + return Redirect::route('repeated.index'); + } + + /** + * @param PiggyBank $repeatedExpense + * + * @return $this + */ + public function edit(PiggyBank $repeatedExpense) + { + + /** @var \FireflyIII\Database\Account\Account $acct */ + $acct = App::make('FireflyIII\Database\Account\Account'); + + $periods = Config::get('firefly.piggy_bank_periods'); + $accounts = FFForm::makeSelectList($acct->getAssetAccounts()); + $subTitle = 'Edit repeated expense "' . e($repeatedExpense->name) . '"'; + $subTitleIcon = 'fa-pencil'; + + /* + * Flash some data to fill the form. + */ + $preFilled = ['name' => $repeatedExpense->name, + 'account_id' => $repeatedExpense->account_id, + 'targetamount' => $repeatedExpense->targetamount, + 'targetdate' => $repeatedExpense->targetdate->format('Y-m-d'), + 'reminder' => $repeatedExpense->reminder, + 'remind_me' => intval($repeatedExpense->remind_me) == 1 || !is_null($repeatedExpense->reminder) ? true : false + ]; + Session::flash('preFilled', $preFilled); + + return View::make('repeatedExpense.edit', compact('subTitle', 'subTitleIcon', 'repeatedExpense', 'accounts', 'periods', 'preFilled')); + } + /** * @return \Illuminate\View\View */ @@ -48,78 +106,122 @@ class RepeatedExpenseController extends BaseController $subTitle = 'Overview'; - /** @var \FireflyIII\Database\PiggyBank\RepeatedExpense $repository */ - $repository = App::make('FireflyIII\Database\PiggyBank\RepeatedExpense'); - - $expenses = $repository->get(); + $expenses = $this->_repository->get(); $expenses->each( - function (Piggybank $piggyBank) use ($repository) { + function (PiggyBank $piggyBank) { $piggyBank->currentRelevantRep(); } ); - return View::make('repeatedexpense.index', compact('expenses', 'subTitle')); + return View::make('repeatedExpense.index', compact('expenses', 'subTitle')); } /** - * @param Piggybank $piggyBank + * @param PiggyBank $repeatedExpense * * @return \Illuminate\View\View */ - public function show(Piggybank $piggyBank) + public function show(PiggyBank $repeatedExpense) { - $subTitle = $piggyBank->name; - $today = Carbon::now(); + $subTitle = $repeatedExpense->name; + $today = Carbon::now(); + $repetitions = $repeatedExpense->piggyBankRepetitions()->get(); - /** @var \FireflyIII\Database\PiggyBank\RepeatedExpense $repository */ - $repository = App::make('FireflyIII\Database\PiggyBank\RepeatedExpense'); - - $repetitions = $piggyBank->piggybankrepetitions()->get(); $repetitions->each( - function (PiggybankRepetition $repetition) use ($repository) { - $repetition->bars = $repository->calculateParts($repetition); + function (PiggyBankRepetition $repetition) { + $repetition->bars = $this->_repository->calculateParts($repetition); } ); - return View::make('repeatedexpense.show', compact('repetitions', 'piggyBank', 'today', 'subTitle')); + return View::make('repeatedExpense.show', compact('repetitions', 'repeatedExpense', 'today', 'subTitle')); } /** - * @return $this - * @throws FireflyException + * */ public function store() { - $data = Input::except('_token'); - $data['repeats'] = 1; + $data = Input::all(); + $data['repeats'] = 1; + $data['user_id'] = Auth::user()->id; + $targetDate = new Carbon($data['targetdate']); + $startDate = \DateKit::subtractPeriod($targetDate, $data['rep_length']); + $data['startdate'] = $startDate->format('Y-m-d'); + $data['targetdate'] = $targetDate->format('Y-m-d'); + $data['reminder_skip'] = 0; + $data['remind_me'] = isset($data['remind_me']) ? 1 : 0; + $data['order'] = 0; // always validate: $messages = $this->_repository->validate($data); - // flash messages: Session::flash('warnings', $messages['warnings']); Session::flash('successes', $messages['successes']); Session::flash('errors', $messages['errors']); if ($messages['errors']->count() > 0) { - Session::flash('error', 'Could not validate repeated expense: ' . $messages['errors']->first()); + Session::flash('error', 'Could not store repeated expense: ' . $messages['errors']->first()); } + + // return to create screen: if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { return Redirect::route('repeated.create')->withInput(); } - // store: - $this->_repository->store($data); - Session::flash('success', 'Budget "' . e($data['name']) . '" stored.'); + // store + $piggyBank = $this->_repository->store($data); + Event::fire('piggy_bank.store', [$piggyBank]); // new and used. + Session::flash('success', 'Piggy bank "' . e($data['name']) . '" stored.'); if ($data['post_submit_action'] == 'store') { return Redirect::route('repeated.index'); } - // create another. - if ($data['post_submit_action'] == 'create_another') { - return Redirect::route('repeated.create')->withInput(); + return Redirect::route('repeated.create')->withInput(); + } + + /** + * @param PiggyBank $repeatedExpense + * + * @return $this + * @throws FireflyException + */ + public function update(PiggyBank $repeatedExpense) + { + + $data = Input::except('_token'); + $data['rep_every'] = 0; + $data['reminder_skip'] = 0; + $data['order'] = 0; + $data['repeats'] = 1; + $data['remind_me'] = isset($data['remind_me']) ? 1 : 0; + $data['user_id'] = Auth::user()->id; + + // always validate: + $messages = $this->_repository->validate($data); + + Session::flash('warnings', $messages['warnings']); + Session::flash('successes', $messages['successes']); + Session::flash('errors', $messages['errors']); + if ($messages['errors']->count() > 0) { + Session::flash('error', 'Could not update repeated expense: ' . $messages['errors']->first()); } - return Redirect::route('repeated.index'); + // return to update screen: + if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { + return Redirect::route('repeated.edit', $repeatedExpense->id)->withInput(); + } + + // update + $this->_repository->update($repeatedExpense, $data); + Session::flash('success', 'Repeated expense "' . e($data['name']) . '" updated.'); + + // go back to list + if ($data['post_submit_action'] == 'update') { + return Redirect::route('repeated.index'); + } + + // go back to update screen. + return Redirect::route('repeated.edit', $repeatedExpense->id)->withInput(['post_submit_action' => 'return_to_edit']); + } -} \ No newline at end of file +} diff --git a/app/controllers/ReportController.php b/app/controllers/ReportController.php index 96e806fa0b..29be01240f 100644 --- a/app/controllers/ReportController.php +++ b/app/controllers/ReportController.php @@ -1,34 +1,60 @@ _accounts = $accounts; $this->_journals = $journals; $this->_repository = $repository; + /** @var \FireflyIII\Database\Budget\Budget _budgets */ + $this->_budgets = App::make('FireflyIII\Database\Budget\Budget'); + + + View::share('title', 'Reports'); + View::share('mainTitleIcon', 'fa-line-chart'); + + } + + /** + * @param string $year + * @param string $month + * + * @return \Illuminate\View\View + */ + public function budget($year = '2014', $month = '1') + { + try { + new Carbon($year . '-' . $month . '-01'); + } catch (Exception $e) { + return View::make('error')->with('message', 'Invalid date'); + } + $date = new Carbon($year . '-' . $month . '-01'); + $dayEarly = clone $date; + $dayEarly = $dayEarly->subDay(); + $accounts = $this->_repository->getAccountListBudgetOverview($date); + $budgets = $this->_repository->getBudgetsForMonth($date); + + return View::make('reports.budget', compact('date', 'accounts', 'budgets', 'dayEarly')); } @@ -47,58 +73,32 @@ class ReportController extends BaseController } /** - * @param $year - * @param $month + * @param string $year + * @param string $month * * @return \Illuminate\View\View */ - public function unbalanced($year, $month) + public function month($year = '2014', $month = '1') { try { new Carbon($year . '-' . $month . '-01'); } catch (Exception $e) { - App::abort(500); + return View::make('error')->with('message', 'Invalid date.'); } - $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(); + $date = new Carbon($year . '-' . $month . '-01'); + $subTitle = 'Report for ' . $date->format('F Y'); + $subTitleIcon = 'fa-calendar'; + $displaySum = true; // to show sums in report. + $income = $this->_repository->getIncomeForMonth($date); + $expenses = $this->_repository->getExpenseGroupedForMonth($date, 10); + $budgets = $this->_repository->getBudgetsForMonth($date); + $categories = $this->_repository->getCategoriesForMonth($date, 10); + $accounts = $this->_repository->getAccountsForMonth($date); - /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $journalRepository */ - $journalRepository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); - $journals = $journalRepository->getInDateRange($start, $end); - - $withdrawals = $journals->filter( - function (TransactionJournal $journal) { - $relations = $journal->transactiongroups()->where('relation', 'balance')->count(); - $budgets = $journal->budgets()->count(); - $type = $journal->transactionType->type; - if ($type == 'Withdrawal' && $budgets == 0 && $relations == 0) { - return $journal; - } - - return null; - } + return View::make( + 'reports.month', + compact('date', 'accounts', 'categories', 'budgets', 'expenses', 'subTitle', 'displaySum', 'subTitleIcon', 'income') ); - $deposits = $journals->filter( - function (TransactionJournal $journal) { - $relations = $journal->transactiongroups()->where('relation', 'balance')->count(); - $budgets = $journal->budgets()->count(); - $type = $journal->transactionType->type; - if ($type == 'Deposit' && $budgets == 0 && $relations == 0) { - return $journal; - } - - return null; - } - ); - - $journals = $withdrawals->merge($deposits); - - return View::make('reports.unbalanced', compact('start', 'end', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon', 'journals')); } /** @@ -111,7 +111,7 @@ class ReportController extends BaseController try { new Carbon('01-01-' . $year); } catch (Exception $e) { - App::abort(500); + return View::make('error')->with('message', 'Invalid date.'); } $date = new Carbon('01-01-' . $year); $end = clone $date; @@ -130,4 +130,4 @@ class ReportController extends BaseController ); } -} \ No newline at end of file +} diff --git a/app/controllers/SearchController.php b/app/controllers/SearchController.php index e1588d8e3b..6bcbb73d35 100644 --- a/app/controllers/SearchController.php +++ b/app/controllers/SearchController.php @@ -17,7 +17,7 @@ class SearchController extends BaseController $subTitle = null; $rawQuery = null; $result = []; - if (!is_null(Input::get('q'))) { + if (!is_null(Input::get('q')) && strlen(Input::get('q')) > 0) { $rawQuery = trim(Input::get('q')); $words = explode(' ', $rawQuery); $subTitle = 'Results for "' . e($rawQuery) . '"'; @@ -35,4 +35,4 @@ class SearchController extends BaseController 'mainTitleIcon', 'fa-search' )->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 7f1eb8ca3a..a7c9b12e71 100644 --- a/app/controllers/TransactionController.php +++ b/app/controllers/TransactionController.php @@ -1,11 +1,19 @@ _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($unique) > 0) { - - /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $repository */ - $repository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); - $set = $repository->getByIds($unique); - $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. @@ -71,33 +50,18 @@ class TransactionController extends BaseController */ public function create($what = 'deposit') { - /** @var \FireflyIII\Database\Account\Account $accountRepository */ - $accountRepository = App::make('FireflyIII\Database\Account\Account'); + $accounts = FFForm::makeSelectList($this->_helper->getAssetAccounts()); + $budgets = FFForm::makeSelectList($this->_helper->getBudgets()); + $budgets[0] = '(no budget)'; + $piggyBanks = $this->_helper->getPiggyBanks(); + $repeatedExpenses = $this->_helper->getRepeatedExpenses(); + $list = $piggyBanks->merge($repeatedExpenses); + $piggies = FFForm::makeSelectList($list); + $piggies[0] = '(no piggy bank)'; + $preFilled = Session::has('preFilled') ? Session::get('preFilled') : []; + $respondTo = ['account_id', 'account_from_id']; + $subTitle = 'Add a new ' . e($what); - /** @var \FireflyIII\Database\Budget\Budget $budgetRepository */ - $budgetRepository = App::make('FireflyIII\Database\Budget\Budget'); - - /** @var \FireflyIII\Database\PiggyBank\PiggyBank $piggyRepository */ - $piggyRepository = App::make('FireflyIII\Database\PiggyBank\PiggyBank'); - - /** @var \FireflyIII\Database\PiggyBank\RepeatedExpense $repRepository */ - $repRepository = App::make('FireflyIII\Database\PiggyBank\RepeatedExpense'); - - // get asset accounts with names and id's . - $assetAccounts = FFForm::makeSelectList($accountRepository->getAssetAccounts()); - - // get budgets as a select list. - $budgets = FFForm::makeSelectList($budgetRepository->get()); - $budgets[0] = '(no budget)'; - - // get the piggy banks. - $list = $piggyRepository->get()->merge($repRepository->get()); - $piggies = FFForm::makeSelectList($list); - $piggies[0] = '(no piggy bank)'; - asort($piggies); - - $preFilled = Session::has('preFilled') ? Session::get('preFilled') : []; - $respondTo = ['account_id', 'account_from_id']; foreach ($respondTo as $r) { if (!is_null(Input::get($r))) { $preFilled[$r] = Input::get($r); @@ -105,24 +69,25 @@ 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); + asort($piggies); + + + return View::make('transactions.create', compact('accounts', 'budgets', 'what', 'piggies', 'subTitle')); } /** * Shows the form that allows a user to delete a transaction journal. * - * @param TransactionJournal $transactionJournal + * @param TransactionJournal $journal * * @return $this */ - public function delete(TransactionJournal $transactionJournal) + public function delete(TransactionJournal $journal) { - $type = strtolower($transactionJournal->transactionType->type); + $type = strtolower($journal->transactionType->type); + $subTitle = 'Delete ' . e($type) . ' "' . e($journal->description) . '"'; - return View::make('transactions.delete')->with('journal', $transactionJournal)->with( - 'subTitle', 'Delete ' . $type . ' "' . $transactionJournal->description . '"' - ); + return View::make('transactions.delete', compact('journal', 'subTitle')); } @@ -134,14 +99,12 @@ class TransactionController extends BaseController */ public function destroy(TransactionJournal $transactionJournal) { - $type = $transactionJournal->transactionType->type; - - /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $repository */ - $repository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); - $repository->destroy($transactionJournal); - + $type = $transactionJournal->transactionType->type; $return = 'withdrawal'; + Session::flash('success', 'Transaction "' . e($transactionJournal->description) . '" destroyed.'); + + $this->_repository->destroy($transactionJournal); switch ($type) { case 'Deposit': @@ -155,38 +118,6 @@ class TransactionController extends BaseController 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\TransactionJournal $repository */ - $repository = App::make('FireflyIII\Database\TransactionJournal\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); - - - } - /** * Shows the view to edit a transaction. * @@ -196,114 +127,42 @@ class TransactionController extends BaseController */ public function edit(TransactionJournal $journal) { - /* - * All the repositories we need: - */ - - /** @var \FireflyIII\Database\Account\Account $accountRepository */ - $accountRepository = App::make('FireflyIII\Database\Account\Account'); - - /** @var \FireflyIII\Database\Budget\Budget $budgetRepository */ - $budgetRepository = App::make('FireflyIII\Database\Budget\Budget'); - - /** @var \FireflyIII\Database\PiggyBank\PiggyBank $piggyRepository */ - $piggyRepository = App::make('FireflyIII\Database\PiggyBank\PiggyBank'); - - - // type is useful for display: - $what = strtolower($journal->transactiontype->type); - - // get asset accounts with names and id's. - - $budgets = FFForm::makeSelectList($budgetRepository->get(), true); - $accounts = FFForm::makeSelectList($accountRepository->getAssetAccounts()); - $piggies = FFForm::makeSelectList($piggyRepository->get(), true); - - - /* - * Data to properly display the edit form. - */ - $preFilled = [ - 'date' => $journal->date->format('Y-m-d'), - 'category' => '', - 'budget_id' => 0, - 'piggybank_id' => 0 + $what = strtolower($journal->transactiontype->type); + $subTitle = 'Edit ' . e($what) . ' "' . e($journal->description) . '"'; + $budgets = FFForm::makeSelectList($this->_helper->getBudgets(), true); + $accounts = FFForm::makeSelectList($this->_helper->getAssetAccounts()); + $piggies = FFForm::makeSelectList($this->_helper->getPiggyBanks(), true); + $transactions = $journal->transactions()->orderBy('amount', 'DESC')->get(); + $preFilled = [ + 'date' => $journal->date->format('Y-m-d'), + 'category' => '', + 'budget_id' => 0, + 'piggy_bank_id' => 0 ]; - /* - * Fill in the category. - */ $category = $journal->categories()->first(); if (!is_null($category)) { $preFilled['category'] = $category->name; } - /* - * Switch on the type of transaction edited by the user and fill in other - * relevant fields: - */ - switch ($what) { - case 'withdrawal': - 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': - 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': - 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; + $budget = $journal->budgets()->first(); + if (!is_null($budget)) { + $preFilled['budget_id'] = $budget->id; } - /* - * Show the view. - */ + if ($journal->piggyBankEvents()->count() > 0) { + $preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->first()->piggy_bank_id; + } - return View::make('transactions.edit')->with('journal', $journal)->with('accounts', $accounts)->with( - 'what', $what - )->with('budgets', $budgets)->with('data', $preFilled)->with('piggies', $piggies)->with( - 'subTitle', 'Edit ' . $what . ' "' . $journal->description . '"' - ); + $preFilled['amount'] = $journal->getAmount(); + $preFilled['account_id'] = $this->_helper->getAssetAccount($what, $transactions); + $preFilled['expense_account'] = $transactions[0]->account->name; + $preFilled['revenue_account'] = $transactions[1]->account->name; + $preFilled['account_from_id'] = $transactions[1]->account->id; + $preFilled['account_to_id'] = $transactions[0]->account->id; + + + return View::make('transactions.edit', compact('journal', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled); } /** @@ -313,28 +172,24 @@ class TransactionController extends BaseController */ public function index($what) { - - /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $repository */ - $repository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); - switch ($what) { case 'expenses': case 'withdrawal': $subTitleIcon = 'fa-long-arrow-left'; $subTitle = 'Expenses'; - $journals = $repository->getWithdrawalsPaginated(50); + $journals = $this->_repository->getWithdrawalsPaginated(50); break; case 'revenue': case 'deposit': $subTitleIcon = 'fa-long-arrow-right'; $subTitle = 'Revenue, income and deposits'; - $journals = $repository->getDepositsPaginated(50); + $journals = $this->_repository->getDepositsPaginated(50); break; case 'transfer': case 'transfers': $subTitleIcon = 'fa-arrows-h'; $subTitle = 'Transfers'; - $journals = $repository->getTransfersPaginated(50); + $journals = $this->_repository->getTransfersPaginated(50); break; } @@ -342,51 +197,7 @@ class TransactionController extends BaseController } - /** - * @param TransactionJournal $journal - * - * @return \Illuminate\View\View - */ - public function relate(TransactionJournal $journal) - { - $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\TransactionJournal $repository */ - $repository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); - - $result = $repository->searchRelated($search, $journal); - $result->each( - function (TransactionJournal $j) { - $j->amount = mf($j->getAmount()); - } - ); - - return Response::json($result->toArray()); - } /** * @param TransactionJournal $journal @@ -410,16 +221,16 @@ class TransactionController extends BaseController $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); + /** @var TransactionJournal $loopJournal */ + foreach ($group->transactionjournals()->get() as $loopJournal) { + if ($loopJournal->id != $journal->id) { + $members->push($loopJournal); } } } return View::make('transactions.show', compact('journal', 'members'))->with( - 'subTitle', $journal->transactionType->type . ' "' . $journal->description . '"' + 'subTitle', e($journal->transactionType->type) . ' "' . e($journal->description) . '"' ); } @@ -431,91 +242,50 @@ class TransactionController extends BaseController */ public function store($what) { - $data = Input::except('_token'); - $data['what'] = $what; - $data['currency'] = 'EUR'; + $data = Input::except('_token'); + $transactionType = $this->_repository->getJournalType($what); + $transactionCurrency = $this->_repository->getJournalCurrency('EUR'); + $data['transaction_type_id'] = $transactionType->id; + $data['transaction_currency_id'] = $transactionCurrency->id; + $data['completed'] = 0; + $data['what'] = $what; + $data['currency'] = 'EUR'; - /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $repository */ - $repository = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); + // always validate: + $messages = $this->_repository->validate($data); - 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 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!'); - - /* - * Trigger a search for the related (if selected) - * piggy bank and store an event. - */ - Event::fire('transactionJournal.store', [$journal, Input::get('piggybank_id')]); // new and used. - /* - * Also trigger on both transactions. - */ - /** @var Transaction $transaction */ - foreach ($journal->transactions as $transaction) { - Event::fire('transaction.store', [$transaction]); - } - - if ($data['post_submit_action'] == 'create_another') { - return Redirect::route('transactions.create', $what)->withInput(); - } else { - return Redirect::route('transactions.index', $what); - } - 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('transactions.create', $what)->withInput(); - break; - } - } - - /** - * TODO this needs cleaning up and thinking over. - * - * @param TransactionJournal $journal - * - * @return \Illuminate\Http\JsonResponse - * @throws Exception - */ - public function unrelate(TransactionJournal $journal) - { - $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(); - } + Session::flash('warnings', $messages['warnings']); + Session::flash('successes', $messages['successes']); + Session::flash('errors', $messages['errors']); + if ($messages['errors']->count() > 0) { + Session::flash('error', 'Could not store transaction: ' . $messages['errors']->first()); } - return Response::json(true); + // return to create screen: + if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { + return Redirect::route('transactions.create', $data['what'])->withInput(); + } + // store + $journal = $this->_repository->store($data); + Event::fire('transactionJournal.store', [$journal, Input::get('piggy_bank_id')]); // new and used. + /* + * Also trigger on both transactions. + */ + /** @var Transaction $transaction */ + foreach ($journal->transactions as $transaction) { + Event::fire('transaction.store', [$transaction]); + } + + Session::flash('success', 'Transaction "' . e($data['description']) . '" stored.'); + if ($data['post_submit_action'] == 'store') { + return Redirect::route('transactions.index', $data['what']); + } + + return Redirect::route('transactions.create', $data['what'])->withInput(); } + /** * @param TransactionJournal $journal * @@ -524,60 +294,38 @@ class TransactionController extends BaseController */ public function update(TransactionJournal $journal) { - /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $repos */ - $repos = App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); + $data = Input::except('_token'); + $data['currency'] = 'EUR'; + $data['what'] = strtolower($journal->transactionType->type); + $data['transaction_type_id'] = $journal->transaction_type_id; + $data['transaction_currency_id'] = $journal->transaction_currency_id; + $data['completed'] = 1; + $messages = $this->_repository->validate($data); - $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': - $messageBag = $repos->update($journal, $data); - if ($messageBag->count() == 0) { - // has been saved, return to index: - Session::flash('success', 'Transaction updated!'); - 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', $data['what']); - } - } else { - Session::flash('error', 'Could not update transaction: ' . $journal->getErrors()->first()); - - return Redirect::route('transactions.edit', $journal->id)->withInput()->withErrors( - $journal->getErrors() - ); - } - - 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('transactions.edit', $journal->id)->withInput(); - break; - default: - throw new FireflyException('Method ' . Input::get('post_submit_action') . ' not implemented yet.'); - break; + Session::flash('warnings', $messages['warnings']); + Session::flash('successes', $messages['successes']); + Session::flash('errors', $messages['errors']); + if ($messages['errors']->count() > 0) { + Session::flash('error', 'Could not update transaction: ' . $messages['errors']->first()); } + if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) { + return Redirect::route('transactions.edit', $journal->id)->withInput(); + } + $this->_repository->update($journal, $data); + Session::flash('success', 'Transaction "' . e($data['description']) . '" updated.'); + Event::fire('transactionJournal.update', [$journal]); // new and used. + /** @var Transaction $transaction */ + foreach ($journal->transactions()->get() as $transaction) { + Event::fire('transaction.update', [$transaction]); + } + if ($data['post_submit_action'] == 'update') { + return Redirect::route('transactions.index', $data['what']); + } + + // go back to update screen. + return Redirect::route('transactions.edit', $journal->id)->withInput(['post_submit_action' => 'return_to_edit']); } -} \ No newline at end of file +} diff --git a/app/controllers/UserController.php b/app/controllers/UserController.php index 4cf00ce1a1..82309e2460 100644 --- a/app/controllers/UserController.php +++ b/app/controllers/UserController.php @@ -33,7 +33,7 @@ class UserController extends BaseController Auth::logout(); Session::flush(); - return Redirect::route('index'); + return Redirect::route('login'); } /** @@ -67,9 +67,6 @@ class UserController extends BaseController */ public function postRegister() { - if (Config::get('auth.allow_register') !== true) { - return View::make('error')->with('message', 'Not possible'); - } /** @var \FireflyIII\Database\User\User $repository */ $repository = App::make('FireflyIII\Database\User\User'); @@ -79,17 +76,10 @@ class UserController extends BaseController $user = $repository->register(Input::all()); - - //$user = $this->user->register(Input::all()); if ($user) { - if (Config::get('auth.verify_mail') === true) { - $email->sendVerificationMail($user); + $email->sendVerificationMail($user); - return View::make('user.verification-pending'); - } - $email->sendPasswordMail($user); - - return View::make('user.registered'); + return View::make('user.verification-pending'); } @@ -102,7 +92,7 @@ class UserController extends BaseController * * @return \Illuminate\View\View */ - public function postRemindme() + public function postRemindMe() { /** @var \FireflyIII\Database\User\User $repository */ @@ -116,16 +106,11 @@ class UserController extends BaseController if (!$user) { Session::flash('error', 'No good!'); - return View::make('user.remindme'); + return View::make('user.remindMe'); } - if (Config::get('auth.verify_reset') === true) { - $email->sendResetVerification($user); + $email->sendResetVerification($user); - return View::make('user.verification-pending'); - } - $email->sendPasswordMail($user); - - return View::make('user.registered'); + return View::make('user.verification-pending'); } @@ -136,9 +121,6 @@ class UserController extends BaseController */ public function register() { - if (Config::get('auth.allow_register') !== true) { - return View::make('error')->with('message', 'Not possible'); - } return View::make('user.register'); } @@ -148,9 +130,9 @@ class UserController extends BaseController * * @return \Illuminate\View\View */ - public function remindme() + public function remindMe() { - return View::make('user.remindme'); + return View::make('user.remindMe'); } /** @@ -176,7 +158,7 @@ class UserController extends BaseController return View::make('user.registered'); } - return View::make('error')->with('message', 'Yo no hablo reset code!'); + return View::make('error')->with('message', 'No reset code found!'); } -} \ No newline at end of file +} 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 3100f7e9b8..e09703979a 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 @@ -1,6 +1,7 @@ string('id')->unique(); - $t->text('payload'); - $t->integer('last_activity'); - } + 'sessions', function (Blueprint $table) { + $table->string('id')->unique(); + $table->text('payload'); + $table->integer('last_activity'); + } ); } 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 fced678780..fc39882c7b 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 @@ -29,19 +29,19 @@ class CreateLimitsTable extends Migration { Schema::create( 'limits', function (Blueprint $table) { - $table->increments('id'); - $table->timestamps(); - $table->integer('component_id')->unsigned(); - $table->date('startdate'); - $table->decimal('amount', 10, 2); - $table->boolean('repeats'); - $table->enum('repeat_freq', ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly']); + $table->increments('id'); + $table->timestamps(); + $table->integer('component_id')->unsigned(); + $table->date('startdate'); + $table->decimal('amount', 10, 2); + $table->boolean('repeats'); + $table->enum('repeat_freq', ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly']); - $table->unique(['component_id', 'startdate', 'repeat_freq']); + $table->unique(['component_id', 'startdate', 'repeat_freq'], 'unique_ci_combi'); - // connect component - $table->foreign('component_id')->references('id')->on('components')->onDelete('cascade'); - } + // connect component + $table->foreign('component_id')->references('id')->on('components')->onDelete('cascade'); + } ); } diff --git a/app/database/migrations/2014_12_13_190730_changes_for_v321.php b/app/database/migrations/2014_12_13_190730_changes_for_v321.php index 7185cde1b8..4a9a743178 100644 --- a/app/database/migrations/2014_12_13_190730_changes_for_v321.php +++ b/app/database/migrations/2014_12_13_190730_changes_for_v321.php @@ -2,6 +2,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; /** * Down: @@ -271,19 +272,6 @@ class ChangesForV321 extends Migration $this->dropComponentIdFromBudgetLimits(); // 16. $this->expandCurrencyTable(); // 17. - - // $this->doRenameInLimitRepetitions(); - // $this->doBudgetLimits(); - // $this->doPiggyBankEvents(); - // $this->doCreateCategoryTables(); - // $this->doUpdateTransactionTable(); - // $this->doDropCompRecurTable(); - // $this->doDropCompTransTable(); - // $this->doMoveBudgets(); - // $this->doMoveCategories(); - // $this->doMoveLimitReferences(); - - } public function createBudgetTable() @@ -502,133 +490,5 @@ class ChangesForV321 extends Migration \DB::update('UPDATE `transaction_currencies` SET `symbol` = "€", `name` = "Euro" WHERE `code` = "EUR";'); } - // - // public function doRenameInLimitRepetitions() - // { - // Schema::table( - // 'limit_repetitions', function (Blueprint $table) { - // $table->renameColumn('limit_id', 'budget_limit_id'); - // } - // ); - // } - // - // public function doBudgetLimits() - // { - // Schema::rename('limits', 'budget_limits'); - // Schema::table( - // 'budget_limits', function (Blueprint $table) { - // $table->integer('budget_id')->unsigned()->after('updated_at'); - // $table->foreign('budget_id', 'bid_foreign')->references('id')->on('budgets')->onDelete('cascade'); - // } - // ); - // } - // - // public function doPiggyBankEvents() - // { - // Schema::rename('piggybank_events', 'piggy_bank_events'); - // - // } - // - // public function doCreateCategoryTables() - // { - // Schema::create( - // 'categories', function (Blueprint $table) { - // $table->increments('id'); - // $table->timestamps(); - // $table->softDeletes(); - // $table->string('name', 50); - // $table->integer('user_id')->unsigned(); - // $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); - // $table->unique(['user_id', 'name']); - // } - // ); - // Schema::create( - // 'category_transaction_journal', function (Blueprint $table) { - // $table->increments('id'); - // $table->integer('category_id')->unsigned(); - // $table->integer('transaction_journal_id')->unsigned(); - // $table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade'); - // $table->foreign('transaction_journal_id')->references('id')->on('transaction_journals')->onDelete('cascade'); - // $table->unique(['category_id', 'transaction_journal_id'], 'catid_tjid_unique'); - // } - // ); - // - // } - // - // public function doUpdateTransactionTable() - // { - // Schema::table( - // 'transactions', function (Blueprint $table) { - // $table->dropForeign('transactions_piggybank_id_foreign'); - // #$table->dropIndex('transactions_piggybank_id_foreign'); - // $table->dropColumn('piggybank_id'); - // } - // ); - // } - // - // public function doDropCompRecurTable() - // { - // Schema::drop('component_recurring_transaction'); - // } - // - // public function doDropCompTransTable() - // { - // Schema::drop('component_transaction'); - // } - // - // public function doMoveBudgets() - // { - // Component::where('class', 'Budget')->get()->each( - // function (Component $c) { - // $entry = [ - // 'user_id' => $c->user_id, - // 'name' => $c->name - // - // ]; - // $budget = Budget::firstOrCreate($entry); - // Log::debug('Migrated budget #' . $budget->id . ': ' . $budget->name); - // // create entry in budget_transaction_journal - // $connections = DB::table('component_transaction_journal')->where('component_id', $c->id)->get(); - // foreach ($connections as $connection) { - // DB::table('budget_transaction_journal')->insert( - // [ - // 'budget_id' => $budget->id, - // 'transaction_journal_id' => $connection->transaction_journal_id - // ] - // ); - // } - // } - // ); - // } - // - // public function doMoveCategories() - // { - // Component::where('class', 'Category')->get()->each( - // function (Component $c) { - // $entry = [ - // 'user_id' => $c->user_id, - // 'name' => $c->name - // - // ]; - // $category = Category::firstOrCreate($entry); - // Log::debug('Migrated category #' . $category->id . ': ' . $category->name); - // // create entry in category_transaction_journal - // $connections = DB::table('component_transaction_journal')->where('component_id', $c->id)->get(); - // foreach ($connections as $connection) { - // DB::table('category_transaction_journal')->insert( - // [ - // 'category_id' => $category->id, - // 'transaction_journal_id' => $connection->transaction_journal_id - // ] - // ); - // } - // } - // ); - // } - // - // public function doMoveLimitReferences() - // { - // throw new \FireflyIII\Exception\FireflyException('TODO'); - // } } diff --git a/app/database/migrations/2014_12_24_191544_changes_for_v322.php b/app/database/migrations/2014_12_24_191544_changes_for_v322.php new file mode 100644 index 0000000000..0714ea25fe --- /dev/null +++ b/app/database/migrations/2014_12_24_191544_changes_for_v322.php @@ -0,0 +1,168 @@ +renameColumn('piggy_bank_id', 'piggybank_id'); + } + ); + + Schema::table( + 'piggybank_repetitions', function (Blueprint $table) { + $table->renameColumn('piggy_bank_id', 'piggybank_id'); + } + ); + + // remove soft delete to piggy banks + Schema::table( + 'piggybanks', function (Blueprint $table) { + $table->dropSoftDeletes(); + } + ); + + // drop keys from bills (foreign bills_uid_for and unique uid_name_unique) + Schema::table( + 'bills', function (Blueprint $table) { + $table->dropForeign('bills_uid_for'); + $table->dropUnique('uid_name_unique'); + } + ); + // drop foreign key from transaction_journals (bill_id_foreign) + Schema::table( + 'transaction_journals', function (Blueprint $table) { + $table->dropForeign('bill_id_foreign'); + + } + ); + + // drop foreign key from budget_limits: + Schema::table( + 'budget_limits', function (Blueprint $table) { + $table->dropForeign('bid_foreign'); + $table->dropUnique('unique_bl_combi'); + } + ); + + // rename bills to recurring_transactions + Schema::rename('bills', 'recurring_transactions'); + // recreate foreign key recurring_transactions_user_id_foreign in recurring_transactions + // recreate unique recurring_transactions_user_id_name_unique in recurring_transactions + Schema::table( + 'recurring_transactions', function (Blueprint $table) { + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + $table->unique(['user_id', 'name']); + } + ); + + // rename bill_id to recurring_transaction_id + // recreate foreign transaction_journals_recurring_transaction_id_foreign in transaction_journals + Schema::table( + 'transaction_journals', function (Blueprint $table) { + $table->renameColumn('bill_id', 'recurring_transaction_id'); + $table->foreign('recurring_transaction_id')->references('id')->on('recurring_transactions')->onDelete('set null'); + } + ); + + + } + + + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + // rename tables: + Schema::rename('piggybank_repetitions', 'piggy_bank_repetitions'); + Schema::rename('piggybanks', 'piggy_banks'); + + // recreate it the correct way: + Schema::table( + 'budget_limits', function (Blueprint $table) { + $table->unique(['budget_id', 'startdate', 'repeat_freq'], 'unique_bl_combi'); + } + ); + + // rename fields + Schema::table( + 'piggy_bank_events', function (Blueprint $table) { + $table->renameColumn('piggybank_id', 'piggy_bank_id'); + } + ); + + Schema::table( + 'piggy_bank_repetitions', function (Blueprint $table) { + $table->renameColumn('piggybank_id', 'piggy_bank_id'); + } + ); + + // add soft delete to piggy banks + Schema::table( + 'piggy_banks', function (Blueprint $table) { + $table->softDeletes(); + } + ); + + // rename everything related to recurring transactions, aka bills: + Schema::table( + 'transaction_journals', function (Blueprint $table) { + + + // drop relation + $table->dropForeign('transaction_journals_recurring_transaction_id_foreign'); + // rename column + $table->renameColumn('recurring_transaction_id', 'bill_id'); + + } + ); + + Schema::table( + 'recurring_transactions', function (Blueprint $table) { + $table->dropForeign('recurring_transactions_user_id_foreign'); + $table->dropUnique('recurring_transactions_user_id_name_unique'); + } + ); + // rename table: + Schema::rename('recurring_transactions', 'bills'); + + // recreate foreign relation: + Schema::table( + 'transaction_journals', function (Blueprint $table) { + $table->foreign('bill_id', 'bill_id_foreign')->references('id')->on('bills')->onDelete('set null'); + } + ); + + // recreate more foreign relations. + Schema::table( + 'bills', function (Blueprint $table) { + // connect user id to users + $table->foreign('user_id', 'bills_uid_for')->references('id')->on('users')->onDelete('cascade'); + + // for a user, the name must be unique + $table->unique(['user_id', 'name'], 'uid_name_unique'); + } + ); + + + } + +} diff --git a/app/database/seeds/AccountTypeSeeder.php b/app/database/seeds/AccountTypeSeeder.php index 50f2d7f101..f0fd27b341 100644 --- a/app/database/seeds/AccountTypeSeeder.php +++ b/app/database/seeds/AccountTypeSeeder.php @@ -38,4 +38,4 @@ class AccountTypeSeeder extends Seeder } -} \ No newline at end of file +} diff --git a/app/database/seeds/DefaultUserSeeder.php b/app/database/seeds/DefaultUserSeeder.php index 4198ae4134..1b40e29097 100644 --- a/app/database/seeds/DefaultUserSeeder.php +++ b/app/database/seeds/DefaultUserSeeder.php @@ -13,8 +13,10 @@ class DefaultUserSeeder extends Seeder User::create(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james', 'reset' => null, 'remember_token' => null]); User::create(['email' => 'acceptance@example.com', 'password' => 'acceptance', 'reset' => null, 'remember_token' => null]); User::create(['email' => 'functional@example.com', 'password' => 'functional', 'reset' => null, 'remember_token' => null]); + User::create(['email' => 'reset@example.com', 'password' => 'functional', 'reset' => 'okokokokokokokokokokokokokokokok', 'remember_token' => null]); + } } -} \ No newline at end of file +} diff --git a/app/database/seeds/TestContentSeeder.php b/app/database/seeds/TestContentSeeder.php index dabac9f474..e2cdebf7d7 100644 --- a/app/database/seeds/TestContentSeeder.php +++ b/app/database/seeds/TestContentSeeder.php @@ -3,254 +3,183 @@ use Carbon\Carbon; /** + * + * @SuppressWarnings("CamelCase") // I'm fine with this. + * * Class TestContentSeeder */ class TestContentSeeder extends Seeder { + /** @var string */ + public $eom; + /** @var string */ + public $neom; + /** @var string */ + public $nsom; + /** @var string */ + public $som; + /** @var string */ + public $today; + /** @var string */ + public $yaeom; + /** @var string */ + public $yasom; + /** @var Carbon */ + protected $_endOfMonth; + /** @var Carbon */ + protected $_nextEndOfMonth; + /** @var Carbon */ + protected $_nextStartOfMonth; + /** @var Carbon */ + protected $_startOfMonth; + /** @var Carbon */ + protected $_today; + /** @var Carbon */ + protected $_yearAgoEndOfMonth; + /** @var Carbon */ + protected $_yearAgoStartOfMonth; + /** + * + */ + public function __construct() + { + $this->_startOfMonth = Carbon::now()->startOfMonth(); + $this->som = $this->_startOfMonth->format('Y-m-d'); + + $this->_endOfMonth = Carbon::now()->endOfMonth(); + $this->eom = $this->_endOfMonth->format('Y-m-d'); + + $this->_nextStartOfMonth = Carbon::now()->addMonth()->startOfMonth(); + $this->nsom = $this->_nextStartOfMonth->format('Y-m-d'); + + $this->_nextEndOfMonth = Carbon::now()->addMonth()->endOfMonth(); + $this->neom = $this->_nextEndOfMonth->format('Y-m-d'); + + $this->_yearAgoStartOfMonth = Carbon::now()->subYear()->startOfMonth(); + $this->yasom = $this->_yearAgoStartOfMonth->format('Y-m-d'); + + $this->_yearAgoEndOfMonth = Carbon::now()->subYear()->startOfMonth(); + $this->yaeom = $this->_yearAgoEndOfMonth->format('Y-m-d'); + + + $this->_today = Carbon::now(); + $this->today = $this->_today->format('Y-m-d'); + } + + /** + * Dates are always this month, the start of this month or earlier. + */ public function run() { if (App::environment() == 'testing' || App::environment() == 'homestead') { - $assetType = AccountType::whereType('Asset account')->first(); - $expenseType = AccountType::whereType('Expense account')->first(); - $revenueType = AccountType::whereType('Revenue account')->first(); - $ibType = AccountType::whereType('Initial balance account')->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]); - Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Delete me', 'active' => 1]); + // create initial accounts and various other stuff: + $this->createAssetAccounts($user); + $this->createBudgets($user); + $this->createCategories($user); + $this->createPiggyBanks($user); + $this->createReminders($user); + $this->createRecurringTransactions($user); + $this->createBills($user); + $this->createExpenseAccounts($user); + $this->createRevenueAccounts($user); - // create two budgets: - $groceriesBudget = Budget::create(['user_id' => $user->id, 'name' => 'Groceries']); - $billsBudget = Budget::create(['user_id' => $user->id, 'name' => 'Bills']); - $deleteBudget = Budget::create(['user_id' => $user->id, 'name' => 'Delete me']); - - // some limits: - $startDate = Carbon::now()->startOfMonth(); - $endDate = Carbon::now()->endOfMonth(); - $secondStart = Carbon::now()->subMonth()->startOfMonth(); - $secondEnd = Carbon::now()->subMonth()->endOfMonth(); - $limitOne = BudgetLimit::create( - ['startdate' => $startDate->format('Y-m-d'), 'amount' => 201, 'repeats' => 0, 'repeat_freq' => 'monthly', - 'budget_id' => $groceriesBudget->id] - ); - $limitTwo = BudgetLimit::create( - ['startdate' => $secondStart->format('Y-m-d'), 'amount' => 202, 'repeats' => 0, 'repeat_freq' => 'monthly', - 'budget_id' => $billsBudget->id] - ); - $limitThree = BudgetLimit::create( - ['startdate' => '2014-01-01', 'amount' => 203, 'repeats' => 0, 'repeat_freq' => 'monthly', - 'budget_id' => $deleteBudget->id] - ); - - // and because we have no filters, some repetitions: - $repOne = LimitRepetition::create( - ['budget_limit_id' => $limitOne->id, 'startdate' => $startDate->format('Y-m-d'), 'enddate' => $endDate->format('Y-m-d'), 'amount' => 201] - ); - $repTwo = LimitRepetition::create( - ['budget_limit_id' => $limitTwo->id, 'startdate' => $secondStart->format('Y-m-d'), 'enddate' => $secondEnd->format('Y-m-d'), 'amount' => 202] - ); - $repThree = LimitRepetition::create( - ['budget_limit_id' => $limitThree->id, 'startdate' => '2014-01-01', 'enddate' => '2014-01-31', 'amount' => 203] - ); - - // create two categories: - $dailyGroceries = Category::create(['user_id' => $user->id, 'name' => 'DailyGroceries']); - $lunch = Category::create(['user_id' => $user->id, 'name' => 'Lunch']); - $house = Category::create(['user_id' => $user->id, 'name' => 'House']); - $deleteMe = Category::create(['user_id' => $user->id, 'name' => 'Delete me']); - - Component::create(['user_id' => $user->id, 'name' => 'Some Component 1', 'class' => 'Budget']); - Component::create(['user_id' => $user->id, 'name' => 'Some Component 2', 'class' => 'Budget']); - Component::create(['user_id' => $user->id, 'name' => 'Some Component 3', 'class' => 'Budget']); - Component::create(['user_id' => $user->id, 'name' => 'Some Component 4', 'class' => 'Category']); - Component::create(['user_id' => $user->id, 'name' => 'Some Component 5', 'class' => 'Category']); - Component::create(['user_id' => $user->id, 'name' => 'Some Component 6', 'class' => 'Category']); - Component::create(['user_id' => $user->id, 'name' => 'Some Component 7', 'class' => 'Category']); - - // piggy bank - $piggy = Piggybank::create( - [ - 'account_id' => $savings->id, - 'name' => 'New camera', - 'targetamount' => 2000, - 'startdate' => Carbon::now()->format('Y-m-d'), - 'targetdate' => null, - 'repeats' => 0, - 'rep_length' => null, - 'rep_every' => 0, - 'rep_times' => null, - 'reminder' => null, - 'reminder_skip' => 0, - 'remind_me' => 0, - 'order' => 0, - ] - ); - PiggyBankEvent::create(['piggybank_id' => 1, 'date' => $startDate->format('Y-m-d'), 'amount' => 100]); - PiggybankRepetition::create( - [ - 'piggybank_id' => $piggy->id, - 'startdate' => Carbon::now()->format('Y-m-d'), - 'targetdate' => null, - 'currentamount' => 0 - ] - ); - - // piggy bank - $piggyTargeted = Piggybank::create( - [ - 'account_id' => $savings->id, - 'name' => 'New clothes', - 'targetamount' => 2000, - 'startdate' => Carbon::now()->format('Y-m-d'), - 'targetdate' => Carbon::now()->addMonths(4)->format('Y-m-d'), - 'repeats' => 0, - 'rep_length' => null, - 'rep_every' => 0, - 'rep_times' => null, - 'reminder' => null, - 'reminder_skip' => 0, - 'remind_me' => 0, - 'order' => 0, - ] - ); - - PiggyBankEvent::create(['piggybank_id' => $piggyTargeted->id, 'date' => $startDate->format('Y-m-d'), 'amount' => 100]); - PiggybankRepetition::create( - [ - 'piggybank_id' => $piggyTargeted->id, - 'startdate' => Carbon::now()->format('Y-m-d'), - 'targetdate' => Carbon::now()->addMonths(4)->format('Y-m-d'), - 'currentamount' => 0 - ] - ); - - // recurring transaction - $recurring = \RecurringTransaction::create( - [ - 'user_id' => $user->id, - 'name' => 'Huur', - 'match' => 'huur,portaal', - 'amount_min' => 500, - 'amount_max' => 700, - 'date' => '2014-01-12', - 'active' => 1, - 'automatch' => 1, - 'repeat_freq' => 'monthly', - 'skip' => 0, - ] - ); - - // recurring transaction - $secondRecurring = \RecurringTransaction::create( - [ - 'user_id' => $user->id, - 'name' => 'Gas licht', - 'match' => 'no,match', - 'amount_min' => 500, - 'amount_max' => 700, - 'date' => '2014-01-12', - 'active' => 1, - 'automatch' => 1, - 'repeat_freq' => 'monthly', - 'skip' => 0, - ] - ); - - // create some expense accounts. - $albert = 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]); - 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'); + // get some objects from the database: + $checking = Account::whereName('Checking account')->orderBy('id', 'DESC')->first(); + $savings = Account::whereName('Savings account')->orderBy('id', 'DESC')->first(); + $landLord = Account::whereName('Land lord')->orderBy('id', 'DESC')->first(); + $utilities = Account::whereName('Utilities company')->orderBy('id', 'DESC')->first(); + $television = Account::whereName('TV company')->orderBy('id', 'DESC')->first(); + $phone = Account::whereName('Phone agency')->orderBy('id', 'DESC')->first(); + $employer = Account::whereName('Employer')->orderBy('id', 'DESC')->first(); - // create some expenses and incomes and what-not (for every month): - $start = new Carbon('2014-01-01'); - $end = Carbon::now()->endOfMonth()->addDay(); - while ($start <= $end) { - $this->createTransaction( - $checking, $portaal, 500, $withdrawal, 'Huur Portaal for ' . $start->format('F Y'), $start->format('Y-m-') . '01', $billsBudget, $house, - $recurring - ); - $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 - ); + $bills = Budget::whereName('Bills')->orderBy('id', 'DESC')->first(); + $groceries = Budget::whereName('Groceries')->orderBy('id', 'DESC')->first(); - // 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, $albert, $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. + $house = Category::whereName('House')->orderBy('id', 'DESC')->first(); - $start->addMonth(); + $withdrawal = TransactionType::whereType('Withdrawal')->first(); + $deposit = TransactionType::whereType('Deposit')->first(); + $transfer = TransactionType::whereType('Transfer')->first(); - } + $euro = TransactionCurrency::whereCode('EUR')->first(); - // 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'); + $rentBill = Bill::where('name', 'Rent')->first(); - // create two budgets - // create two categories + $current = clone $this->_yearAgoStartOfMonth; + while ($current <= $this->_startOfMonth) { + $cur = $current->format('Y-m-d'); + $formatted = $current->format('F Y'); - // create + // create expenses for rent, utilities, TV, phone on the 1st of the month. + $this->createTransaction($checking, $landLord, 800, $withdrawal, 'Rent for ' . $formatted, $cur, $euro, $bills, $house, $rentBill); + $this->createTransaction($checking, $utilities, 150, $withdrawal, 'Utilities for ' . $formatted, $cur, $euro, $bills, $house); + $this->createTransaction($checking, $television, 50, $withdrawal, 'TV for ' . $formatted, $cur, $euro, $bills, $house); + $this->createTransaction($checking, $phone, 50, $withdrawal, 'Phone bill for ' . $formatted, $cur, $euro, $bills, $house); + + // two transactions. One without a budget, one without a category. + $this->createTransaction($checking, $phone, 10, $withdrawal, 'Extra charges on phone bill for ' . $formatted, $cur, $euro, null, $house); + $this->createTransaction($checking, $television, 5, $withdrawal, 'Extra charges on TV bill for ' . $formatted, $cur, $euro, $bills, null); + + // income from job: + $this->createTransaction($employer, $checking, rand(3500, 4000), $deposit, 'Salary for ' . $formatted, $cur, $euro); + $this->createTransaction($checking, $savings, 2000, $transfer, 'Salary to savings account in ' . $formatted, $cur, $euro); + + $this->createGroceries($current); + $this->createBigExpense(clone $current); + + echo 'Created test-content for ' . $current->format('F Y') . "\n"; + $current->addMonth(); } + + // piggy bank event + // add money to this piggy bank + // create a piggy bank event to match: + $piggyBank = PiggyBank::whereName('New camera')->orderBy('id', 'DESC')->first(); + $intoPiggy = $this->createTransaction($checking, $savings, 100, $transfer, 'Money for piggy', $this->yaeom, $euro, $groceries, $house); + PiggyBankEvent::create( + [ + 'piggy_bank_id' => $piggyBank->id, + 'transaction_journal_id' => $intoPiggy->id, + 'date' => $this->yaeom, + 'amount' => 100 + ] + ); } } + /** + * @param User $user + */ + public function createAssetAccounts(User $user) + { + $assetType = AccountType::whereType('Asset account')->first(); + $ibType = AccountType::whereType('Initial balance account')->first(); + $obType = TransactionType::whereType('Opening balance')->first(); + $euro = TransactionCurrency::whereCode('EUR')->first(); + + + $acc_a = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Checking account', 'active' => 1]); + $acc_b = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Savings account', 'active' => 1]); + $acc_c = Account::create(['user_id' => $user->id, 'account_type_id' => $assetType->id, 'name' => 'Delete me', 'active' => 1]); + + $acc_d = Account::create(['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Checking account initial balance', 'active' => 0]); + $acc_e = Account::create(['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Savings account initial balance', 'active' => 0]); + $acc_f = Account::create(['user_id' => $user->id, 'account_type_id' => $ibType->id, 'name' => 'Delete me initial balance', 'active' => 0]); + + + $this->createTransaction($acc_d, $acc_a, 4000, $obType, 'Initial Balance for Checking account', $this->yasom, $euro); + $this->createTransaction($acc_e, $acc_b, 10000, $obType, 'Initial Balance for Savings account', $this->yasom, $euro); + $this->createTransaction($acc_f, $acc_c, 100, $obType, 'Initial Balance for Delete me', $this->yasom, $euro); + } + /** * @param Account $from * @param Account $to @@ -258,48 +187,34 @@ class TestContentSeeder extends Seeder * @param TransactionType $type * @param $description * @param $date + * @param TransactionCurrency $currency * * @param Budget $budget * @param Category $category - * @param RecurringTransaction $recurring + * @param Bill $bill * * @return TransactionJournal */ public function createTransaction( - Account $from, Account $to, $amount, TransactionType $type, $description, $date, Budget $budget = null, Category $category = null, - $recurring = null + Account $from, Account $to, $amount, TransactionType $type, $description, $date, TransactionCurrency $currency, Budget $budget = null, + Category $category = null, Bill $bill = null ) { - $user = User::whereEmail('thegrumpydictator@gmail.com')->first(); - $euro = TransactionCurrency::whereCode('EUR')->first(); - $recurringID = is_null($recurring) ? null : $recurring->id; + $user = User::whereEmail('thegrumpydictator@gmail.com')->first(); + + $billID = is_null($bill) ? null : $bill->id; + /** @var TransactionJournal $journal */ $journal = TransactionJournal::create( [ - 'user_id' => $user->id, - 'transaction_type_id' => $type->id, - 'transaction_currency_id' => $euro->id, - 'recurring_transaction_id' => $recurringID, - 'description' => $description, - 'completed' => 1, - 'date' => $date + 'user_id' => $user->id, 'transaction_type_id' => $type->id, 'transaction_currency_id' => $currency->id, 'bill_id' => $billID, + '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 - ] - ); + 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); } @@ -309,4 +224,338 @@ class TestContentSeeder extends Seeder return $journal; } -} \ No newline at end of file + + /** + * @param User $user + */ + public function createBudgets(User $user) + { + + $groceries = Budget::create(['user_id' => $user->id, 'name' => 'Groceries']); + $bills = Budget::create(['user_id' => $user->id, 'name' => 'Bills']); + $deleteMe = Budget::create(['user_id' => $user->id, 'name' => 'Delete me']); + Budget::create(['user_id' => $user->id, 'name' => 'Budget without repetition']); + $groceriesLimit = BudgetLimit::create( + ['startdate' => $this->som, 'amount' => 201, 'repeats' => 0, 'repeat_freq' => 'monthly', 'budget_id' => $groceries->id] + ); + $billsLimit = BudgetLimit::create( + ['startdate' => $this->som, 'amount' => 202, 'repeats' => 0, 'repeat_freq' => 'monthly', 'budget_id' => $bills->id] + ); + $deleteMeLimit = BudgetLimit::create( + ['startdate' => $this->som, 'amount' => 203, 'repeats' => 0, 'repeat_freq' => 'monthly', 'budget_id' => $deleteMe->id] + ); + + // and because we have no filters, some repetitions: + LimitRepetition::create(['budget_limit_id' => $groceriesLimit->id, 'startdate' => $this->som, 'enddate' => $this->eom, 'amount' => 201]); + LimitRepetition::create(['budget_limit_id' => $billsLimit->id, 'startdate' => $this->som, 'enddate' => $this->eom, 'amount' => 202]); + LimitRepetition::create(['budget_limit_id' => $deleteMeLimit->id, 'startdate' => $this->som, 'enddate' => $this->eom, 'amount' => 203]); + } + + /** + * @param User $user + */ + public function createCategories(User $user) + { + Category::create(['user_id' => $user->id, 'name' => 'DailyGroceries']); + Category::create(['user_id' => $user->id, 'name' => 'Lunch']); + Category::create(['user_id' => $user->id, 'name' => 'House']); + Category::create(['user_id' => $user->id, 'name' => 'Delete me']); + + } + + /** + * @param User $user + */ + public function createPiggyBanks(User $user) + { + // account + $savings = Account::whereName('Savings account')->orderBy('id', 'DESC')->first(); + + // some dates + $endDate = clone $this->_startOfMonth; + $nextYear = clone $this->_startOfMonth; + + $endDate->addMonths(4); + $nextYear->addYear()->subDay(); + + $next = $nextYear->format('Y-m-d'); + $end = $endDate->format('Y-m-d'); + + // piggy bank + $newCamera = PiggyBank::create( + [ + 'account_id' => $savings->id, + 'name' => 'New camera', + 'targetamount' => 2000, + 'startdate' => $this->som, + 'targetdate' => null, + 'repeats' => 0, + 'rep_length' => null, + 'rep_every' => 0, + 'rep_times' => null, + 'reminder' => null, + 'reminder_skip' => 0, + 'remind_me' => 0, + 'order' => 0, + ] + ); + // and some events! + PiggyBankEvent::create(['piggy_bank_id' => $newCamera->id, 'date' => $this->som, 'amount' => 100]); + PiggyBankRepetition::create(['piggy_bank_id' => $newCamera->id, 'startdate' => $this->som, 'targetdate' => null, 'currentamount' => 100]); + + + $newClothes = PiggyBank::create( + [ + 'account_id' => $savings->id, + 'name' => 'New clothes', + 'targetamount' => 2000, + 'startdate' => $this->som, + 'targetdate' => $end, + 'repeats' => 0, + 'rep_length' => null, + 'rep_every' => 0, + 'rep_times' => null, + 'reminder' => null, + 'reminder_skip' => 0, + 'remind_me' => 0, + 'order' => 0, + ] + ); + + PiggyBankEvent::create(['piggy_bank_id' => $newClothes->id, 'date' => $this->som, 'amount' => 100]); + PiggyBankRepetition::create(['piggy_bank_id' => $newClothes->id, 'startdate' => $this->som, 'targetdate' => $end, 'currentamount' => 100]); + + // weekly reminder piggy bank + $weekly = PiggyBank::create( + [ + 'account_id' => $savings->id, + 'name' => 'Weekly reminder for clothes', + 'targetamount' => 2000, + 'startdate' => $this->som, + 'targetdate' => $next, + 'repeats' => 0, + 'rep_length' => null, + 'rep_every' => 0, + 'rep_times' => null, + 'reminder' => 'week', + 'reminder_skip' => 0, + 'remind_me' => 1, + 'order' => 0, + ] + ); + PiggyBankRepetition::create(['piggy_bank_id' => $weekly->id, 'startdate' => $this->som, 'targetdate' => $next, 'currentamount' => 0]); + } + + /** + * @param User $user + */ + public function createReminders(User $user) + { + // for weekly piggy bank (clothes) + $nextWeek = clone $this->_startOfMonth; + $piggyBank = PiggyBank::whereName('New clothes')->orderBy('id', 'DESC')->first(); + $nextWeek->addWeek(); + $week = $nextWeek->format('Y-m-d'); + + Reminder::create( + ['user_id' => $user->id, 'startdate' => $this->som, 'enddate' => $week, 'active' => 1, 'notnow' => 0, + 'remindersable_id' => $piggyBank->id, 'remindersable_type' => 'PiggyBank'] + ); + + // a fake reminder:: + Reminder::create( + ['user_id' => $user->id, 'startdate' => $this->som, 'enddate' => $week, 'active' => 0, 'notnow' => 0, 'remindersable_id' => 40, + 'remindersable_type' => 'Transaction'] + ); + } + + /** + * @param User $user + */ + public function createRecurringTransactions(User $user) + { + // account + $savings = Account::whereName('Savings account')->orderBy('id', 'DESC')->first(); + + $recurring = PiggyBank::create( + [ + 'account_id' => $savings->id, + 'name' => 'Nieuwe spullen', + 'targetamount' => 1000, + 'startdate' => $this->som, + 'targetdate' => $this->eom, + 'repeats' => 1, + 'rep_length' => 'month', + 'rep_every' => 0, + 'rep_times' => 0, + 'reminder' => 'month', + 'reminder_skip' => 0, + 'remind_me' => 1, + 'order' => 0, + ] + ); + PiggyBankRepetition::create(['piggy_bank_id' => $recurring->id, 'startdate' => $this->som, 'targetdate' => $this->eom, 'currentamount' => 0]); + PiggyBankRepetition::create( + ['piggy_bank_id' => $recurring->id, 'startdate' => $this->nsom, 'targetdate' => $this->neom, 'currentamount' => 0] + ); + Reminder::create( + ['user_id' => $user->id, 'startdate' => $this->som, 'enddate' => $this->neom, 'active' => 1, 'notnow' => 0, + 'remindersable_id' => $recurring->id, 'remindersable_type' => 'PiggyBank'] + ); + } + + /** + * @param $user + */ + public function createBills($user) + { + // bill + Bill::create( + [ + 'user_id' => $user->id, 'name' => 'Rent', 'match' => 'rent,landlord', + 'amount_min' => 700, + 'amount_max' => 900, + 'date' => $this->som, + 'active' => 1, + 'automatch' => 1, + 'repeat_freq' => 'monthly', + 'skip' => 0, + ] + ); + + // bill + Bill::create( + [ + 'user_id' => $user->id, + 'name' => 'Gas licht', + 'match' => 'no,match', + 'amount_min' => 500, + 'amount_max' => 700, + 'date' => $this->som, + 'active' => 1, + 'automatch' => 1, + 'repeat_freq' => 'monthly', + 'skip' => 0, + ] + ); + + // bill + Bill::create( + [ + 'user_id' => $user->id, + 'name' => 'Something something', + 'match' => 'mumble,mumble', + 'amount_min' => 500, + 'amount_max' => 700, + 'date' => $this->som, + 'active' => 0, + 'automatch' => 1, + 'repeat_freq' => 'monthly', + 'skip' => 0, + ] + ); + + } + + /** + * @param $user + */ + public function createExpenseAccounts($user) + { + //// create expenses for rent, utilities, water, TV, phone on the 1st of the month. + $expenseType = AccountType::whereType('Expense account')->first(); + + Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Land lord', 'active' => 1]); + Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Utilities company', 'active' => 1]); + Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Water company', 'active' => 1]); + Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'TV company', 'active' => 1]); + Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Phone agency', 'active' => 1]); + Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Super savers', 'active' => 1]); + Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Groceries House', 'active' => 1]); + Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Lunch House', 'active' => 1]); + + + Account::create(['user_id' => $user->id, 'account_type_id' => $expenseType->id, 'name' => 'Buy More', 'active' => 1]); + + } + + /** + * @param $user + */ + public function createRevenueAccounts($user) + { + $revenueType = AccountType::whereType('Revenue account')->first(); + + Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'Employer', 'active' => 1]); + Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'IRS', 'active' => 1]); + Account::create(['user_id' => $user->id, 'account_type_id' => $revenueType->id, 'name' => 'Second job employer', 'active' => 1]); + + } + + /** + * @param Carbon $date + */ + public function createGroceries(Carbon $date) + { + // variables we need: + $checking = Account::whereName('Checking account')->orderBy('id', 'DESC')->first(); + $shopOne = Account::whereName('Groceries House')->orderBy('id', 'DESC')->first(); + $shopTwo = Account::whereName('Super savers')->orderBy('id', 'DESC')->first(); + $lunchHouse = Account::whereName('Lunch House')->orderBy('id', 'DESC')->first(); + $lunch = Category::whereName('Lunch')->orderBy('id', 'DESC')->first(); + $daily = Category::whereName('DailyGroceries')->orderBy('id', 'DESC')->first(); + $euro = TransactionCurrency::whereCode('EUR')->first(); + $withdrawal = TransactionType::whereType('Withdrawal')->first(); + $groceries = Budget::whereName('Groceries')->orderBy('id', 'DESC')->first(); + + + $shops = [$shopOne, $shopTwo]; + + // create groceries and lunch (daily, between 5 and 10 euro). + $mStart = clone $date; + $mEnd = clone $date; + $mEnd->endOfMonth(); + while ($mStart <= $mEnd) { + $mFormat = $mStart->format('Y-m-d'); + $shop = $shops[rand(0, 1)]; + + $this->createTransaction($checking, $shop, (rand(500, 1000) / 100), $withdrawal, 'Groceries', $mFormat, $euro, $groceries, $daily); + $this->createTransaction($checking, $lunchHouse, (rand(200, 600) / 100), $withdrawal, 'Lunch', $mFormat, $euro, $groceries, $lunch); + + $mStart->addDay(); + } + } + + /** + * @param $date + */ + public function createBigExpense($date) + { + $date->addDays(12); + $dollar = TransactionCurrency::whereCode('USD')->first(); + $checking = Account::whereName('Checking account')->orderBy('id', 'DESC')->first(); + $savings = Account::whereName('Savings account')->orderBy('id', 'DESC')->first(); + $buyMore = Account::whereName('Buy More')->orderBy('id', 'DESC')->first(); + $withdrawal = TransactionType::whereType('Withdrawal')->first(); + $transfer = TransactionType::whereType('Transfer')->first(); + $user = User::whereEmail('thegrumpydictator@gmail.com')->first(); + + + // create some big expenses, move some money around. + $amount = rand(500, 2000); + $one = $this->createTransaction( + $savings, $checking, $amount, $transfer, 'Money for big expense in ' . $date->format('F Y'), $date->format('Y-m-d'), $dollar + ); + $two = $this->createTransaction( + $checking, $buyMore, $amount, $withdrawal, 'Big expense in ' . $date->format('F Y'), $date->format('Y-m-d'), $dollar + ); + $group = TransactionGroup::create( + [ + 'user_id' => $user->id, + 'relation' => 'balance' + ] + ); + $group->transactionjournals()->save($one); + $group->transactionjournals()->save($two); + } +} diff --git a/app/database/seeds/TransactionCurrencySeeder.php b/app/database/seeds/TransactionCurrencySeeder.php index 20f50e9f60..6bf2eb7010 100644 --- a/app/database/seeds/TransactionCurrencySeeder.php +++ b/app/database/seeds/TransactionCurrencySeeder.php @@ -12,6 +12,7 @@ class TransactionCurrencySeeder extends Seeder TransactionCurrency::create(['code' => 'EUR','name' => 'Euro','symbol' => '€']); TransactionCurrency::create(['code' => 'USD','name' => 'US Dollar','symbol' => '$']); + TransactionCurrency::create(['code' => 'HUF','name' => 'Hungarian forint','symbol' => 'Ft']); } -} \ No newline at end of file +} diff --git a/app/database/seeds/TransactionTypeSeeder.php b/app/database/seeds/TransactionTypeSeeder.php index a500ce6c00..cf0e6a5e12 100644 --- a/app/database/seeds/TransactionTypeSeeder.php +++ b/app/database/seeds/TransactionTypeSeeder.php @@ -17,4 +17,4 @@ class TransactionTypeSeeder extends Seeder TransactionType::create(['type' => 'Opening balance']); } -} \ No newline at end of file +} diff --git a/app/filters.php b/app/filters.php index 8a73c6b6da..27e9264440 100644 --- a/app/filters.php +++ b/app/filters.php @@ -94,3 +94,11 @@ Route::filter( } } ); + +Route::filter( + 'allow-register', function () { + if (Config::get('auth.allow_register') !== true) { + return View::make('error')->with('message', 'Not possible'); + } +} +); diff --git a/app/lib/FireflyIII/Chart/Chart.php b/app/lib/FireflyIII/Chart/Chart.php index 302a014c5b..6214e5079a 100644 --- a/app/lib/FireflyIII/Chart/Chart.php +++ b/app/lib/FireflyIII/Chart/Chart.php @@ -48,28 +48,28 @@ class Chart implements ChartInterface * * @return Collection */ - public function getRecurringSummary(Carbon $start, Carbon $end) + public function getBillsSummary(Carbon $start, Carbon $end) { - return \RecurringTransaction:: + return \Bill:: leftJoin( 'transaction_journals', function (JoinClause $join) use ($start, $end) { - $join->on('recurring_transactions.id', '=', 'transaction_journals.recurring_transaction_id') + $join->on('bills.id', '=', 'transaction_journals.bill_id') ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) ->where('transaction_journals.date', '<=', $end->format('Y-m-d')); } ) - ->leftJoin( - 'transactions', function (JoinClause $join) { - $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '>', 0); - } - ) - ->where('active', 1) - ->groupBy('recurring_transactions.id') - ->get( - ['recurring_transactions.id', 'recurring_transactions.name', 'transaction_journals.description', - 'transaction_journals.id as journalId', - \DB::Raw('SUM(`recurring_transactions`.`amount_min` + `recurring_transactions`.`amount_max`) / 2 as `averageAmount`'), - 'transactions.amount AS actualAmount'] - ); + ->leftJoin( + 'transactions', function (JoinClause $join) { + $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '>', 0); + } + ) + ->where('active', 1) + ->groupBy('bills.id') + ->get( + ['bills.id', 'bills.name', 'transaction_journals.description', + 'transaction_journals.id as journalId', + \DB::Raw('SUM(`bills`.`amount_min` + `bills`.`amount_max`) / 2 as `averageAmount`'), + 'transactions.amount AS actualAmount'] + ); } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Chart/ChartInterface.php b/app/lib/FireflyIII/Chart/ChartInterface.php index 7b29e3c9e9..62a2efa868 100644 --- a/app/lib/FireflyIII/Chart/ChartInterface.php +++ b/app/lib/FireflyIII/Chart/ChartInterface.php @@ -26,6 +26,6 @@ interface ChartInterface * * @return Collection */ - public function getRecurringSummary(Carbon $start, Carbon $end); + public function getBillsSummary(Carbon $start, Carbon $end); -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Collection/PiggybankPart.php b/app/lib/FireflyIII/Collection/PiggybankPart.php index 4c60b21591..7544e4d8e9 100644 --- a/app/lib/FireflyIII/Collection/PiggybankPart.php +++ b/app/lib/FireflyIII/Collection/PiggybankPart.php @@ -6,11 +6,11 @@ namespace FireflyIII\Collection; use Carbon\Carbon; /** - * Class PiggybankPart + * Class PiggyBankPart * * @package FireflyIII\Collection */ -class PiggybankPart +class PiggyBankPart { /** @var float */ public $amountPerBar; @@ -21,7 +21,7 @@ class PiggybankPart /** @var \Reminder */ public $reminder; - /** @var \PiggybankRepetition */ + /** @var \PiggyBankRepetition */ public $repetition; /** @var Carbon */ @@ -36,7 +36,7 @@ class PiggybankPart public function getReminder() { if (is_null($this->reminder)) { - $this->reminder = $this->repetition->piggybank->reminders()->where('startdate', $this->getStartdate()->format('Y-m-d'))->where( + $this->reminder = $this->repetition->piggyBank->reminders()->where('startdate', $this->getStartdate()->format('Y-m-d'))->where( 'enddate', $this->getTargetdate()->format('Y-m-d') )->first(); } @@ -85,7 +85,7 @@ class PiggybankPart } /** - * @return \PiggybankRepetition + * @return \PiggyBankRepetition */ public function getRepetition() { @@ -93,7 +93,7 @@ class PiggybankPart } /** - * @param \PiggybankRepetition $repetition + * @param \PiggyBankRepetition $repetition */ public function setRepetition($repetition) { @@ -115,7 +115,7 @@ class PiggybankPart { if ($this->getCurrentamount() < $this->getCumulativeAmount()) { $pct = 0; - // calculate halway point? + // calculate halfway point? if ($this->getCumulativeAmount() - $this->getCurrentamount() < $this->getAmountPerBar()) { $left = $this->getCurrentamount() % $this->getAmountPerBar(); $pct = round($left / $this->getAmountPerBar() * 100); @@ -176,4 +176,4 @@ class PiggybankPart } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/Account/Account.php b/app/lib/FireflyIII/Database/Account/Account.php index 1318bc040d..661db8d40c 100644 --- a/app/lib/FireflyIII/Database/Account/Account.php +++ b/app/lib/FireflyIII/Database/Account/Account.php @@ -3,21 +3,22 @@ namespace FireflyIII\Database\Account; use Carbon\Carbon; -use FireflyIII\Database\CommonDatabaseCalls; -use FireflyIII\Database\CUD; +use FireflyIII\Database\CommonDatabaseCallsInterface; +use FireflyIII\Database\CUDInterface; use FireflyIII\Database\SwitchUser; use FireflyIII\Exception\NotImplementedException; use Illuminate\Database\Eloquent\Model as Eloquent; use Illuminate\Support\Collection; use Illuminate\Support\MessageBag; - +use Illuminate\Database\Query\Builder as QueryBuilder; +use Illuminate\Database\Eloquent\Builder as EloquentBuilder; /** * Class Account * * @package FireflyIII\Database * @implements FireflyIII\Database\Account\AccountInterface */ -class Account implements CUD, CommonDatabaseCalls, AccountInterface +class Account implements CUDInterface, CommonDatabaseCallsInterface, AccountInterface { use SwitchUser; @@ -208,8 +209,8 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface return true; } else { - var_dump($validation['errors']); - exit; + \Log::error($validation['errors']->all()); + \App::abort(500); } } @@ -222,22 +223,22 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface public function destroy(Eloquent $model) { + // delete piggy banks // delete journals: $journals = \TransactionJournal::whereIn( - 'id', function ($query) use ($model) { + 'id', function (QueryBuilder $query) use ($model) { $query->select('transaction_journal_id') ->from('transactions')->whereIn( - 'account_id', function ($query) use ($model) { + 'account_id', function (QueryBuilder $query) use ($model) { $query ->select('id') ->from('accounts') ->where( - function ($q) use ($model) { + function (QueryBuilder $q) use ($model) { $q->where('id', $model->id); $q->orWhere( - function ($q) use ($model) { + function (QueryBuilder $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); } @@ -273,12 +274,11 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface // delete accounts: \Account::where( - function ($q) use ($model) { + function (EloquentBuilder $q) use ($model) { $q->where('id', $model->id); $q->orWhere( - function ($q) use ($model) { + function (EloquentBuilder $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); } @@ -314,15 +314,14 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface $data = array_except($data, ['_token', 'what']); $account = new \Account($data); if (!$account->isValid()) { - var_dump($account->getErrors()->all()); - exit; + \Log::error($account->getErrors()->all()); + \App::abort(500); } $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': @@ -350,7 +349,6 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface $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': @@ -361,8 +359,8 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface $model->save(); if (isset($data['openingbalance']) && isset($data['openingbalancedate']) && strlen($data['openingbalancedate']) > 0) { + /** @noinspection PhpParamsInspection */ $openingBalance = $this->openingBalanceTransaction($model); - // TODO this needs cleaning up and thinking over. if (is_null($openingBalance)) { $this->storeInitialBalance($model, $data); } else { @@ -480,7 +478,6 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface */ public function findByWhat($what) { - // TODO: Implement findByWhat() method. throw new NotImplementedException; } @@ -492,7 +489,6 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface */ public function get() { - // TODO: Implement get() method. throw new NotImplementedException; } @@ -514,14 +510,14 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface */ public function firstExpenseAccountOrCreate($name) { - /** @var \FireflyIII\Database\AccountType\AccountType $accountTypeRepos */ - $accountTypeRepos = \App::make('FireflyIII\Database\AccountType\AccountType'); + /** @var \FireflyIII\Database\AccountType\AccountType $accountTypeRepository */ + $accountTypeRepository = \App::make('FireflyIII\Database\AccountType\AccountType'); - $accountType = $accountTypeRepos->findByWhat('expense'); + $accountType = $accountTypeRepository->findByWhat('expense'); // if name is "", find cash account: if (strlen($name) == 0) { - $cashAccountType = $accountTypeRepos->findByWhat('cash'); + $cashAccountType = $accountTypeRepository->findByWhat('cash'); // find or create cash account: return \Account::firstOrCreate( @@ -543,10 +539,10 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface */ public function firstRevenueAccountOrCreate($name) { - /** @var \FireflyIII\Database\AccountType\AccountType $accountTypeRepos */ - $accountTypeRepos = \App::make('FireflyIII\Database\AccountType\AccountType'); + /** @var \FireflyIII\Database\AccountType\AccountType $accountTypeRepository */ + $accountTypeRepository = \App::make('FireflyIII\Database\AccountType\AccountType'); - $accountType = $accountTypeRepos->findByWhat('revenue'); + $accountType = $accountTypeRepository->findByWhat('revenue'); $data = ['user_id' => $this->getUser()->id, 'account_type_id' => $accountType->id, 'name' => $name, 'active' => 1]; @@ -659,4 +655,4 @@ class Account implements CUD, CommonDatabaseCalls, AccountInterface } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/Account/AccountInterface.php b/app/lib/FireflyIII/Database/Account/AccountInterface.php index 55c7883865..336df90401 100644 --- a/app/lib/FireflyIII/Database/Account/AccountInterface.php +++ b/app/lib/FireflyIII/Database/Account/AccountInterface.php @@ -91,4 +91,4 @@ interface AccountInterface * @return bool */ public function storeInitialBalance(\Account $account, array $data); -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/AccountType/AccountType.php b/app/lib/FireflyIII/Database/AccountType/AccountType.php index c3b8856f6a..58f6cebb13 100644 --- a/app/lib/FireflyIII/Database/AccountType/AccountType.php +++ b/app/lib/FireflyIII/Database/AccountType/AccountType.php @@ -2,8 +2,8 @@ namespace FireflyIII\Database\AccountType; -use FireflyIII\Database\CommonDatabaseCalls; -use FireflyIII\Database\CUD; +use FireflyIII\Database\CommonDatabaseCallsInterface; +use FireflyIII\Database\CUDInterface; use FireflyIII\Exception\FireflyException; use FireflyIII\Exception\NotImplementedException; use Illuminate\Database\Eloquent\Model as Eloquent; @@ -14,7 +14,7 @@ use Illuminate\Support\Collection; * * @package FireflyIII\Database */ -class AccountType implements CUD, CommonDatabaseCalls +class AccountType implements CUDInterface, CommonDatabaseCallsInterface { /** @@ -25,7 +25,6 @@ class AccountType implements CUD, CommonDatabaseCalls */ public function destroy(Eloquent $model) { - // TODO: Implement destroy() method. throw new NotImplementedException; } @@ -37,7 +36,6 @@ class AccountType implements CUD, CommonDatabaseCalls */ public function store(array $data) { - // TODO: Implement store() method. throw new NotImplementedException; } @@ -50,7 +48,6 @@ class AccountType implements CUD, CommonDatabaseCalls */ public function update(Eloquent $model, array $data) { - // TODO: Implement update() method. throw new NotImplementedException; } @@ -65,7 +62,6 @@ class AccountType implements CUD, CommonDatabaseCalls */ public function validate(array $model) { - // TODO: Implement validate() method. throw new NotImplementedException; } @@ -79,7 +75,6 @@ class AccountType implements CUD, CommonDatabaseCalls */ public function find($objectId) { - // TODO: Implement find() method. throw new NotImplementedException; } @@ -124,7 +119,6 @@ class AccountType implements CUD, CommonDatabaseCalls */ public function get() { - // TODO: Implement get() method. throw new NotImplementedException; } @@ -136,7 +130,6 @@ class AccountType implements 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/RecurringTransaction/RecurringTransaction.php b/app/lib/FireflyIII/Database/Bill/Bill.php similarity index 63% rename from app/lib/FireflyIII/Database/RecurringTransaction/RecurringTransaction.php rename to app/lib/FireflyIII/Database/Bill/Bill.php index 1a4b424043..6e17ffe827 100644 --- a/app/lib/FireflyIII/Database/RecurringTransaction/RecurringTransaction.php +++ b/app/lib/FireflyIII/Database/Bill/Bill.php @@ -1,11 +1,11 @@ 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']); + $bill = new \Bill; + $bill->user()->associate($this->getUser()); + $bill->name = $data['name']; + $bill->match = $data['match']; + $bill->amount_max = floatval($data['amount_max']); + $bill->amount_min = floatval($data['amount_min']); $date = new Carbon($data['date']); - $recurring->active = intval($data['active']); - $recurring->automatch = intval($data['automatch']); - $recurring->repeat_freq = $data['repeat_freq']; + $bill->active = intval($data['active']); + $bill->automatch = intval($data['automatch']); + $bill->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']); + $date = \DateKit::startOfPeriod($date, $data['repeat_freq']); + $bill->date = $date; + $bill->skip = intval($data['skip']); - $recurring->save(); + $bill->save(); - return $recurring; + return $bill; } /** @@ -118,7 +118,7 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac $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.'); } - $object = new \RecurringTransaction($model); + $object = new \Bill($model); $object->isValid(); $errors->merge($object->getErrors()); @@ -142,7 +142,6 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac */ public function find($objectId) { - // TODO: Implement find() method. throw new NotImplementedException; } @@ -156,7 +155,6 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac */ public function findByWhat($what) { - // TODO: Implement findByWhat() method. throw new NotImplementedException; } @@ -167,7 +165,7 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac */ public function get() { - return $this->getUser()->recurringtransactions()->get(); + return $this->getUser()->bills()->get(); } /** @@ -178,7 +176,6 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac */ public function getByIds(array $ids) { - // TODO: Implement getByIds() method. throw new NotImplementedException; } @@ -189,35 +186,102 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac */ public function getActive() { - return $this->getUser()->recurringtransactions()->where('active', 1)->get(); + return $this->getUser()->bills()->where('active', 1)->get(); } /** - * @param \RecurringTransaction $recurring - * @param Carbon $start - * @param Carbon $end + * @param \Bill $bill + * @param Carbon $start + * @param Carbon $end * * @return \TransactionJournal|null */ - public function getJournalForRecurringInRange(\RecurringTransaction $recurring, Carbon $start, Carbon $end) + public function getJournalForBillInRange(\Bill $bill, Carbon $start, Carbon $end) { - return $this->getUser()->transactionjournals()->where('recurring_transaction_id', $recurring->id)->after($start)->before($end)->first(); + return $this->getUser()->transactionjournals()->where('bill_id', $bill->id)->after($start)->before($end)->first(); } /** - * @param \RecurringTransaction $recurring - * @param \TransactionJournal $journal + * @param \Bill $bill + * + * @return Carbon|null + */ + public function lastFoundMatch(\Bill $bill) + { + $last = $bill->transactionjournals()->orderBy('date', 'DESC')->first(); + if ($last) { + return $last->date; + } + + return null; + } + + /** + * @param \Bill $bill + * + * @return Carbon|null + */ + public function nextExpectedMatch(\Bill $bill) + { + /* + * The date Firefly tries to find. If this stays null, it's "unknown". + */ + $finalDate = null; + if ($bill->active == 0) { + return $finalDate; + } + + /* + * $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, $bill->repeat_freq, 0); + + /* + * FF3 loops from the $start of the bill, and to make sure + * $skip works, it adds one (for modulo). + */ + $skip = $bill->skip + 1; + $start = \DateKit::startOfPeriod(new Carbon, $bill->repeat_freq); + /* + * go back exactly one month/week/etc because FF3 does not care about 'next' + * bills if they're too far into the past. + */ + + $counter = 0; + while ($start <= $today) { + if (($counter % $skip) == 0) { + // do something. + $end = \DateKit::endOfPeriod(clone $start, $bill->repeat_freq); + $journalCount = $bill->transactionjournals()->before($end)->after($start)->count(); + if ($journalCount == 0) { + $finalDate = clone $start; + break; + } + } + + // add period for next round! + $start = \DateKit::addPeriod($start, $bill->repeat_freq, 0); + $counter++; + } + + return $finalDate; + } + + /** + * @param \Bill $bill + * @param \TransactionJournal $journal * * @return bool */ - public function scan(\RecurringTransaction $recurring, \TransactionJournal $journal) + public function scan(\Bill $bill, \TransactionJournal $journal) { /* * Match words. */ $wordMatch = false; - $matches = explode(',', $recurring->match); + $matches = explode(',', $bill->match); $description = strtolower($journal->description); /* @@ -261,8 +325,8 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac if (count($transactions) > 1) { $amount = max(floatval($transactions[0]->amount), floatval($transactions[1]->amount)); - $min = floatval($recurring->amount_min); - $max = floatval($recurring->amount_max); + $min = floatval($bill->amount_min); + $max = floatval($bill->amount_max); if ($amount >= $min && $amount <= $max) { $amountMatch = true; \Log::debug('Amount match is true!'); @@ -273,17 +337,17 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac * If both, update! */ if ($wordMatch && $amountMatch) { - $journal->recurringTransaction()->associate($recurring); + $journal->bill()->associate($bill); $journal->save(); } } /** - * @param \RecurringTransaction $recurring + * @param \Bill $bill * * @return bool */ - public function scanEverything(\RecurringTransaction $recurring) + public function scanEverything(\Bill $bill) { // get all journals that (may) be relevant. // this is usually almost all of them. @@ -291,7 +355,7 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $journalRepository */ $journalRepository = \App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); - $set = \DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $recurring->amount_min)->where('amount', '<=', $recurring->amount_max) + $set = \DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max) ->get(['transaction_journal_id']); $ids = []; @@ -303,10 +367,10 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac $journals = $journalRepository->getByIds($ids); /** @var \TransactionJournal $journal */ foreach ($journals as $journal) { - $this->scan($recurring, $journal); + $this->scan($bill, $journal); } } return true; } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/Bill/BillInterface.php b/app/lib/FireflyIII/Database/Bill/BillInterface.php new file mode 100644 index 0000000000..f6dca6325f --- /dev/null +++ b/app/lib/FireflyIII/Database/Bill/BillInterface.php @@ -0,0 +1,55 @@ +where('limit_repetitions.startdate', $date->format('Y-m-d 00:00:00')) - ->where('budget_limits.budget_id', $budget->id) - ->first(['limit_repetitions.*']); + ->where('limit_repetitions.startdate', $date->format('Y-m-d 00:00:00')) + ->where('budget_limits.budget_id', $budget->id) + ->first(['limit_repetitions.*']); } /** @@ -264,7 +264,7 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface return $this->getUser() ->transactionjournals() ->whereNotIn( - 'transaction_journals.id', function ($query) use ($start, $end) { + 'transaction_journals.id', function (Builder $query) use ($start, $end) { $query ->select('transaction_journals.id') ->from('transaction_journals') @@ -333,8 +333,7 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface $limit->amount = $amount; $limit->repeat_freq = 'monthly'; $limit->repeats = 0; - $result = $limit->save(); - \Log::info('Created new limit? ' . boolstr($result)); + $limit->save(); \Log::info('ID: ' . $limit->id); /* * A newly stored limit also created a limit repetition. @@ -366,6 +365,8 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface */ public function limitOnStartingOnDate(\Budget $budget, Carbon $date) { - return $budget->budgetLimits()->where('startdate', $date->format('Y-m-d'))->first(); + return $budget->budgetLimits()->where('startdate', $date->format('Y-m-d 00:00:00'))->first(); + + } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/Budget/BudgetInterface.php b/app/lib/FireflyIII/Database/Budget/BudgetInterface.php index 1e1dc36de0..f001cdd7a3 100644 --- a/app/lib/FireflyIII/Database/Budget/BudgetInterface.php +++ b/app/lib/FireflyIII/Database/Budget/BudgetInterface.php @@ -28,4 +28,4 @@ interface BudgetInterface */ public function transactionsWithoutBudgetInDateRange(Carbon $start, Carbon $end); -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/CUD.php b/app/lib/FireflyIII/Database/CUDInterface.php similarity index 96% rename from app/lib/FireflyIII/Database/CUD.php rename to app/lib/FireflyIII/Database/CUDInterface.php index 5178f5c474..e4f60a6089 100644 --- a/app/lib/FireflyIII/Database/CUD.php +++ b/app/lib/FireflyIII/Database/CUDInterface.php @@ -10,7 +10,7 @@ use Illuminate\Database\Eloquent\Model as Eloquent; * * @package FireflyIII\Database */ -interface CUD +interface CUDInterface { /** @@ -45,4 +45,4 @@ interface CUD */ public function validate(array $model); -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/Category/Category.php b/app/lib/FireflyIII/Database/Category/Category.php index dd0167aaf9..a928c2d34e 100644 --- a/app/lib/FireflyIII/Database/Category/Category.php +++ b/app/lib/FireflyIII/Database/Category/Category.php @@ -2,8 +2,8 @@ namespace FireflyIII\Database\Category; use Carbon\Carbon; -use FireflyIII\Database\CommonDatabaseCalls; -use FireflyIII\Database\CUD; +use FireflyIII\Database\CommonDatabaseCallsInterface; +use FireflyIII\Database\CUDInterface; use FireflyIII\Database\SwitchUser; use FireflyIII\Exception\FireflyException; use FireflyIII\Exception\NotImplementedException; @@ -16,7 +16,7 @@ use Illuminate\Support\MessageBag; * * @package FireflyIII\Database */ -class Category implements CUD, CommonDatabaseCalls +class Category implements CUDInterface, CommonDatabaseCallsInterface { use SwitchUser; @@ -108,7 +108,6 @@ class Category implements CUD, CommonDatabaseCalls */ public function find($objectId) { - // TODO: Implement find() method. throw new NotImplementedException; } @@ -122,7 +121,6 @@ class Category implements CUD, CommonDatabaseCalls */ public function findByWhat($what) { - // TODO: Implement findByWhat() method. throw new NotImplementedException; } @@ -144,7 +142,6 @@ class Category implements CUD, CommonDatabaseCalls */ public function getByIds(array $ids) { - // TODO: Implement getByIds() method. throw new NotImplementedException; } @@ -206,4 +203,4 @@ class Category implements CUD, CommonDatabaseCalls return $sum; } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/CommonDatabaseCalls.php b/app/lib/FireflyIII/Database/CommonDatabaseCallsInterface.php similarity index 94% rename from app/lib/FireflyIII/Database/CommonDatabaseCalls.php rename to app/lib/FireflyIII/Database/CommonDatabaseCallsInterface.php index ba3bf5d6c7..6fbf57c68b 100644 --- a/app/lib/FireflyIII/Database/CommonDatabaseCalls.php +++ b/app/lib/FireflyIII/Database/CommonDatabaseCallsInterface.php @@ -10,7 +10,7 @@ use Illuminate\Support\Collection; * * @package FireflyIII\Database */ -interface CommonDatabaseCalls +interface CommonDatabaseCallsInterface { /** * Returns an object with id $id. @@ -44,4 +44,4 @@ interface CommonDatabaseCalls */ public function getByIds(array $objectIds); -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/PiggyBank/PiggyBank.php b/app/lib/FireflyIII/Database/PiggyBank/PiggyBank.php index 44d4a6adf9..b77f9246bb 100644 --- a/app/lib/FireflyIII/Database/PiggyBank/PiggyBank.php +++ b/app/lib/FireflyIII/Database/PiggyBank/PiggyBank.php @@ -2,236 +2,31 @@ namespace FireflyIII\Database\PiggyBank; use Carbon\Carbon; -use FireflyIII\Database\CommonDatabaseCalls; -use FireflyIII\Database\CUD; -use FireflyIII\Database\SwitchUser; +use FireflyIII\Database\CommonDatabaseCallsInterface; +use FireflyIII\Database\CUDInterface; use FireflyIII\Exception\FireflyException; use FireflyIII\Exception\NotImplementedException; -use Illuminate\Database\Eloquent\Model as Eloquent; use Illuminate\Support\Collection; -use Illuminate\Support\MessageBag; /** - * Class Piggybank + * Class PiggyBank * * @package FireflyIII\Database */ -class PiggyBank implements CUD, CommonDatabaseCalls, PiggyBankInterface +class PiggyBank extends PiggyBankShared implements CUDInterface, CommonDatabaseCallsInterface, PiggyBankInterface { - use SwitchUser; - /** - * - */ - public function __construct() - { - $this->setUser(\Auth::user()); - } - - /** - * @param Eloquent $model - * - * @return bool - */ - public function destroy(Eloquent $model) - { - $model->delete(); - } - - /** - * @param array $data - * - * @return \Eloquent - * @throws FireflyException - */ - public function store(array $data) - { - if (!isset($data['remind_me']) || (isset($data['remind_me']) && $data['remind_me'] == 0)) { - $data['reminder'] = null; - } - $piggyBank = new \Piggybank($data); - $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 = intval($data['rep_every']); - $model->reminder_skip = intval($data['reminder_skip']); - $model->order = intval($data['order']); - $model->remind_me = intval($data['remind_me']); - $model->reminder = isset($data['reminder']) ? $data['reminder'] : 'month'; - - if ($model->remind_me == 0) { - $model->reminder = null; - } - - $model->save(); - - return true; - } - - /** - * Validates an array. Returns an array containing MessageBags - * errors/warnings/successes. - * - * Ignore PHPMD rules because Laravel 5.0 will make this method superfluous anyway. - * - * @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.'); - } - } - 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'] . ')'); - } - // 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', '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 $objectId - * - * @return \Eloquent - */ - public function find($objectId) - { - return \Piggybank:: - leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where('piggybanks.id', '=', $objectId)->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 - * @throws NotImplementedException - */ - 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', 0)->get(); - } - - /** - * @param array $ids - * - * @return Collection - * @throws NotImplementedException - */ - public function getByIds(array $ids) - { - // TODO: Implement getByIds() method. - throw new NotImplementedException; - } - - /** - * @param \Piggybank $piggybank + * @param \PiggyBank $piggyBank * @param Carbon $date * * @return mixed * @throws FireflyException * @throws NotImplementedException */ - public function findRepetitionByDate(\Piggybank $piggybank, Carbon $date) + public function findRepetitionByDate(\PiggyBank $piggyBank, Carbon $date) { /** @var Collection $reps */ - $reps = $piggybank->piggybankrepetitions()->get(); + $reps = $piggyBank->piggyBankRepetitions()->get(); if ($reps->count() == 1) { return $reps->first(); } @@ -240,7 +35,7 @@ class PiggyBank implements CUD, CommonDatabaseCalls, PiggyBankInterface } // should filter the one we need: $repetitions = $reps->filter( - function (\PiggybankRepetition $rep) use ($date) { + function (\PiggyBankRepetition $rep) use ($date) { if ($date >= $rep->startdate && $date <= $rep->targetdate) { return $rep; } @@ -256,21 +51,12 @@ class PiggyBank implements CUD, CommonDatabaseCalls, PiggyBankInterface } /** - * @param \Account $account + * Returns all objects. * - * @return float + * @return Collection */ - public function leftOnAccount(\Account $account) + public function get() { - \Log::debug('Now in leftOnAccount() for account #'.$account->id.' ('.$account->name.')'); - $balance = \Steam::balance($account); - \Log::debug('Steam says: ' . $balance); - /** @var \Piggybank $p */ - foreach ($account->piggybanks()->get() as $p) { - $balance -= $p->currentRelevantRep()->currentamount; - } - - return $balance; - + return $this->getUser()->piggyBanks()->where('repeats', 0)->orderBy('name')->get(); } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/PiggyBank/PiggyBankShared.php b/app/lib/FireflyIII/Database/PiggyBank/PiggyBankShared.php new file mode 100644 index 0000000000..5a878e37f4 --- /dev/null +++ b/app/lib/FireflyIII/Database/PiggyBank/PiggyBankShared.php @@ -0,0 +1,183 @@ +setUser(\Auth::user()); + } + + /** + * @param Eloquent $model + * + * @return bool + */ + public function destroy(Eloquent $model) + { + $reminders = \Reminder::where('remindersable_id', $model->id)->get(); + /** @var \Reminder $reminder */ + foreach ($reminders as $reminder) { + $reminder->delete(); + } + $model->delete(); + + } + + /** + * Returns an object with id $id. + * + * @param int $objectId + * + * @return \Eloquent + */ + public function find($objectId) + { + return \PiggyBank:: + leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')->where('piggy_banks.id', '=', $objectId)->where( + 'accounts.user_id', $this->getUser()->id + ) + ->first(['piggy_banks.*']); + } + + /** + * Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc. + * + * @param $what + * + * @return \AccountType|null + * @throws NotImplementedException + */ + public function findByWhat($what) + { + throw new NotImplementedException; + } + + /** + * @param array $ids + * + * @return Collection + * @throws NotImplementedException + */ + public function getByIds(array $ids) + { + return \PiggyBank:: + leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')->whereIn('piggy_banks.id', [$ids])->where( + 'accounts.user_id', $this->getUser()->id + ) + ->first(['piggy_banks.*']); + } + + /** + * @param \Account $account + * + * @return float + */ + public function leftOnAccount(\Account $account) + { + \Log::debug('Now in leftOnAccount() for account #' . $account->id . ' (' . $account->name . ')'); + $balance = \Steam::balance($account); + \Log::debug('Steam says: ' . $balance); + /** @var \PiggyBank $p */ + foreach ($account->piggyBanks()->get() as $p) { + $balance -= $p->currentRelevantRep()->currentamount; + } + + return $balance; + + } + + /** + * @param array $data + * + * @return \Eloquent + * @throws FireflyException + */ + public function store(array $data) + { + if (!isset($data['remind_me']) || (isset($data['remind_me']) && $data['remind_me'] == 0)) { + $data['reminder'] = null; + } + $piggyBank = new \PiggyBank($data); + $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 = intval($data['rep_every']); + $model->reminder_skip = intval($data['reminder_skip']); + $model->order = intval($data['order']); + $model->remind_me = intval($data['remind_me']); + $model->reminder = isset($data['reminder']) ? $data['reminder'] : 'month'; + + if ($model->remind_me == 0) { + $model->reminder = null; + } + + $model->save(); + + return true; + } + + /** + * Validates an array. Returns an array containing MessageBags + * errors/warnings/successes. + * + * Ignore PHPMD rules because Laravel 5.0 will make this method superfluous anyway. + * + * @param array $model + * + * @return array + */ + public function validate(array $model) + { + $warnings = new MessageBag; + $successes = new MessageBag; + $model = new \PiggyBank($model); + $model->isValid(); + $errors = $model->getErrors(); + + // add ok messages. + $list = ['name', 'account_id', '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]; + } + +} diff --git a/app/lib/FireflyIII/Database/PiggyBank/PiggybankInterface.php b/app/lib/FireflyIII/Database/PiggyBank/PiggybankInterface.php index dbcbea2635..3c26f1c969 100644 --- a/app/lib/FireflyIII/Database/PiggyBank/PiggybankInterface.php +++ b/app/lib/FireflyIII/Database/PiggyBank/PiggybankInterface.php @@ -16,4 +16,4 @@ interface PiggyBankInterface * @return float */ public function leftOnAccount(\Account $account); -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/PiggyBank/RepeatedExpense.php b/app/lib/FireflyIII/Database/PiggyBank/RepeatedExpense.php index 100e78a427..171b4c7a88 100644 --- a/app/lib/FireflyIII/Database/PiggyBank/RepeatedExpense.php +++ b/app/lib/FireflyIII/Database/PiggyBank/RepeatedExpense.php @@ -3,46 +3,32 @@ namespace FireflyIII\Database\PiggyBank; -use Carbon\Carbon; -use FireflyIII\Collection\PiggybankPart; -use FireflyIII\Database\CommonDatabaseCalls; -use FireflyIII\Database\CUD; -use FireflyIII\Database\SwitchUser; -use FireflyIII\Exception\NotImplementedException; -use Illuminate\Database\Eloquent\Model as Eloquent; +use FireflyIII\Collection\PiggyBankPart; +use FireflyIII\Database\CommonDatabaseCallsInterface; +use FireflyIII\Database\CUDInterface; use Illuminate\Support\Collection; -use Illuminate\Support\MessageBag; /** * Class RepeatedExpense * * @package FireflyIII\Database */ -class RepeatedExpense implements CUD, CommonDatabaseCalls, PiggyBankInterface +class RepeatedExpense extends PiggyBankShared implements CUDInterface, CommonDatabaseCallsInterface, PiggyBankInterface { - use SwitchUser; - - /** - * - */ - public function __construct() - { - $this->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). * - * @param \PiggybankRepetition $repetition + * @param \PiggyBankRepetition $repetition * * @return Collection */ - public function calculateParts(\PiggybankRepetition $repetition) + public function calculateParts(\PiggyBankRepetition $repetition) { - /** @var \Piggybank $piggyBank */ - $piggyBank = $repetition->piggybank()->first(); + /** @var \PiggyBank $piggyBank */ + $piggyBank = $repetition->piggyBank()->first(); $bars = new Collection; $currentStart = clone $repetition->startdate; @@ -66,7 +52,7 @@ class RepeatedExpense implements CUD, CommonDatabaseCalls, PiggyBankInterface } $amountPerBar = floatval($piggyBank->targetamount) / $bars->count(); $cumulative = $amountPerBar; - /** @var PiggybankPart $bar */ + /** @var PiggyBankPart $bar */ foreach ($bars as $index => $bar) { $bar->setAmountPerBar($amountPerBar); $bar->setCumulativeAmount($cumulative); @@ -82,11 +68,11 @@ class RepeatedExpense implements CUD, CommonDatabaseCalls, PiggyBankInterface /** * @param array $data * - * @return PiggybankPart + * @return PiggyBankPart */ public function createPiggyBankPart(array $data) { - $part = new PiggybankPart; + $part = new PiggyBankPart; $part->setRepetition($data['repetition']); $part->setAmountPerBar($data['amountPerBar']); $part->setCurrentamount($data['currentAmount']); @@ -97,17 +83,6 @@ class RepeatedExpense implements CUD, CommonDatabaseCalls, PiggyBankInterface return $part; } - /** - * @param Eloquent $model - * - * @return bool - * @throws NotImplementedException - */ - public function destroy(Eloquent $model) - { - // TODO: Implement destroy() method. - throw new NotImplementedException; - } /** * @param array $data @@ -128,150 +103,12 @@ class RepeatedExpense implements CUD, CommonDatabaseCalls, PiggyBankInterface $data['reminder'] = null; } - $repeated = new \Piggybank($data); + $repeated = new \PiggyBank($data); $repeated->save(); return $repeated; } - /** - * @param Eloquent $model - * @param array $data - * - * @return bool - * @throws NotImplementedException - */ - 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. - * - * - * ignored because this method will be gone soon. - * - * @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 $objectId - * - * @return \Eloquent - * @throws NotImplementedException - */ - public function find($objectId) - { - // 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 - * @throws NotImplementedException - */ - public function findByWhat($what) - { - // TODO: Implement findByWhat() method. - throw new NotImplementedException; - } - /** * Returns all objects. * @@ -279,30 +116,7 @@ class RepeatedExpense implements CUD, CommonDatabaseCalls, PiggyBankInterface */ public function get() { - return $this->getUser()->piggybanks()->where('repeats', 1)->get(); + return $this->getUser()->piggyBanks()->where('repeats', 1)->get(); } - /** - * @param array $ids - * - * @return Collection - * @throws NotImplementedException - */ - public function getByIds(array $ids) - { - // TODO: Implement getByIds() method. - throw new NotImplementedException; - } - - /** - * @param \Account $account - * - * @return float - * @throws NotImplementedException - */ - 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/RecurringTransaction/RecurringTransactionInterface.php b/app/lib/FireflyIII/Database/RecurringTransaction/RecurringTransactionInterface.php deleted file mode 100644 index da28a75b52..0000000000 --- a/app/lib/FireflyIII/Database/RecurringTransaction/RecurringTransactionInterface.php +++ /dev/null @@ -1,41 +0,0 @@ -_user = $user; } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/Transaction/Transaction.php b/app/lib/FireflyIII/Database/Transaction/Transaction.php index 467ae5c9de..a92f110d2e 100644 --- a/app/lib/FireflyIII/Database/Transaction/Transaction.php +++ b/app/lib/FireflyIII/Database/Transaction/Transaction.php @@ -2,8 +2,8 @@ namespace FireflyIII\Database\Transaction; -use FireflyIII\Database\CommonDatabaseCalls; -use FireflyIII\Database\CUD; +use FireflyIII\Database\CommonDatabaseCallsInterface; +use FireflyIII\Database\CUDInterface; use FireflyIII\Database\SwitchUser; use FireflyIII\Exception\FireflyException; use FireflyIII\Exception\NotImplementedException; @@ -16,7 +16,7 @@ use Illuminate\Support\MessageBag; * * @package FireflyIII\Database */ -class Transaction implements CUD, CommonDatabaseCalls +class Transaction implements CUDInterface, CommonDatabaseCallsInterface { use SwitchUser; @@ -28,7 +28,6 @@ class Transaction implements CUD, CommonDatabaseCalls */ public function destroy(Eloquent $model) { - // TODO: Implement destroy() method. throw new NotImplementedException; } @@ -44,8 +43,8 @@ class Transaction implements CUD, CommonDatabaseCalls $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['piggyBank'])) { + $transaction->piggyBank()->associate($data['piggyBank']); } if (isset($data['description'])) { $transaction->description = $data['description']; @@ -68,7 +67,6 @@ class Transaction implements CUD, CommonDatabaseCalls */ public function update(Eloquent $model, array $data) { - // TODO: Implement update() method. throw new NotImplementedException; } @@ -103,7 +101,6 @@ class Transaction implements CUD, CommonDatabaseCalls */ public function find($objectId) { - // TODO: Implement find() method. throw new NotImplementedException; } @@ -117,7 +114,6 @@ class Transaction implements CUD, CommonDatabaseCalls */ public function findByWhat($what) { - // TODO: Implement findByWhat() method. throw new NotImplementedException; } @@ -129,7 +125,6 @@ class Transaction implements CUD, CommonDatabaseCalls */ public function get() { - // TODO: Implement get() method. throw new NotImplementedException; } @@ -141,7 +136,6 @@ class Transaction implements 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/TransactionCurrency.php b/app/lib/FireflyIII/Database/TransactionCurrency/TransactionCurrency.php index 887f792656..55b7c5f502 100644 --- a/app/lib/FireflyIII/Database/TransactionCurrency/TransactionCurrency.php +++ b/app/lib/FireflyIII/Database/TransactionCurrency/TransactionCurrency.php @@ -2,8 +2,8 @@ namespace FireflyIII\Database\TransactionCurrency; -use FireflyIII\Database\CommonDatabaseCalls; -use FireflyIII\Database\CUD; +use FireflyIII\Database\CommonDatabaseCallsInterface; +use FireflyIII\Database\CUDInterface; use FireflyIII\Exception\NotImplementedException; use Illuminate\Database\Eloquent\Model as Eloquent; use Illuminate\Support\Collection; @@ -14,7 +14,7 @@ use Illuminate\Support\MessageBag; * * @package FireflyIII\Database */ -class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabaseCalls, CUD +class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabaseCallsInterface, CUDInterface { /** @@ -35,7 +35,6 @@ class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabas public function store(array $data) { $currency = new \TransactionCurrency($data); - \Log::debug('Is valid? ' . boolstr($currency->isValid())); $currency->save(); return $currency; @@ -52,7 +51,6 @@ class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabas $model->symbol = $data['symbol']; $model->code = $data['code']; $model->name = $data['name']; - \Log::debug('Is valid? ' . boolstr($model->isValid())); $model->save(); return true; @@ -94,12 +92,12 @@ class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabas * Returns an object with id $id. * * @param int $objectId + * @throws NotImplementedException * * @return \Eloquent */ public function find($objectId) { - // TODO: Implement find() method. throw new NotImplementedException; } @@ -107,12 +105,12 @@ class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabas * Finds an account type using one of the "$what"'s: expense, asset, revenue, opening, etc. * * @param $what + * @throws NotImplementedException * * @return \AccountType|null */ public function findByWhat($what) { - // TODO: Implement findByWhat() method. throw new NotImplementedException; } @@ -128,12 +126,12 @@ class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabas /** * @param array $objectIds + * @throws NotImplementedException * * @return Collection */ public function getByIds(array $objectIds) { - // TODO: Implement getByIds() method. throw new NotImplementedException; } @@ -146,4 +144,4 @@ class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabas { return \TransactionCurrency::whereCode($code)->first(); } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/TransactionCurrency/TransactionCurrencyInterface.php b/app/lib/FireflyIII/Database/TransactionCurrency/TransactionCurrencyInterface.php index e3026ca6c3..bd2c0a159d 100644 --- a/app/lib/FireflyIII/Database/TransactionCurrency/TransactionCurrencyInterface.php +++ b/app/lib/FireflyIII/Database/TransactionCurrency/TransactionCurrencyInterface.php @@ -17,4 +17,4 @@ interface TransactionCurrencyInterface */ public function findByCode($code); -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/TransactionJournal/TransactionJournal.php b/app/lib/FireflyIII/Database/TransactionJournal/TransactionJournal.php index f3c8084dae..ff7cafa8e2 100644 --- a/app/lib/FireflyIII/Database/TransactionJournal/TransactionJournal.php +++ b/app/lib/FireflyIII/Database/TransactionJournal/TransactionJournal.php @@ -4,8 +4,8 @@ namespace FireflyIII\Database\TransactionJournal; use Carbon\Carbon; -use FireflyIII\Database\CommonDatabaseCalls; -use FireflyIII\Database\CUD; +use FireflyIII\Database\CommonDatabaseCallsInterface; +use FireflyIII\Database\CUDInterface; use FireflyIII\Database\SwitchUser; use FireflyIII\Exception\FireflyException; use FireflyIII\Exception\NotImplementedException; @@ -18,7 +18,7 @@ use Illuminate\Support\MessageBag; * * @package FireflyIII\Database */ -class TransactionJournal implements TransactionJournalInterface, CUD, CommonDatabaseCalls +class TransactionJournal implements TransactionJournalInterface, CUDInterface, CommonDatabaseCallsInterface { use SwitchUser; @@ -63,11 +63,12 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData */ public function store(array $data) { - $journalType = $this->getJournalType($data['what']); - $currency = $this->getJournalCurrency($data['currency']); - $journal = new \TransactionJournal( - ['transaction_type_id' => $journalType->id, 'transaction_currency_id' => $currency->id, 'user_id' => $this->getUser()->id, - 'description' => $data['description'], 'date' => $data['date'], 'completed' => 0] + $currency = $this->getJournalCurrency($data['currency']); + $journal = new \TransactionJournal( + [ + 'transaction_type_id' => $data['transaction_type_id'], + 'transaction_currency_id' => $currency->id, 'user_id' => $this->getUser()->id, + 'description' => $data['description'], 'date' => $data['date'], 'completed' => 0] ); $journal->save(); @@ -105,6 +106,7 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData list($fromAccount, $toAccount) = $this->storeAccounts($data); + /** @noinspection PhpParamsInspection */ $this->storeBudget($data, $model); $this->storeCategory($data, $model); @@ -128,7 +130,7 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData $transaction->save(); } - return new MessageBag; + return true; } /** @@ -147,41 +149,16 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData $warnings = new MessageBag; $successes = new MessageBag; - $errors = new MessageBag; + $journal = new \TransactionJournal($model); + $journal->isValid(); + $errors = $journal->getErrors(); if (!isset($model['what'])) { $errors->add('description', 'Internal error: need to know type of transaction!'); } - if (isset($model['recurring_transaction_id']) && intval($model['recurring_transaction_id']) < 0) { - $errors->add('recurring_transaction_id', 'Recurring transaction is invalid.'); - } - if (!isset($model['description'])) { - $errors->add('description', 'This field is mandatory.'); - } - if (isset($model['description']) && strlen($model['description']) == 0) { - $errors->add('description', 'This field is mandatory.'); - } - if (isset($model['description']) && strlen($model['description']) > 255) { - $errors->add('description', 'Description is too long.'); - } - - if (!isset($model['currency'])) { - $errors->add('description', 'Internal error: currency is mandatory!'); - } - if (isset($model['date']) && !($model['date'] instanceof Carbon) && strlen($model['date']) > 0) { - try { - new Carbon($model['date']); - } catch (\Exception $e) { - $errors->add('date', 'This date is invalid.'); - } - } - if (!isset($model['date'])) { - $errors->add('date', 'This date is invalid.'); - } - /* - * Amount: + * Amount */ if (isset($model['amount']) && floatval($model['amount']) < 0.01) { $errors->add('amount', 'Amount must be > 0.01'); @@ -194,7 +171,7 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData } /* - * Budget: + * Budget */ if (isset($model['budget_id']) && !ctype_digit($model['budget_id'])) { $errors->add('budget_id', 'Invalid budget'); @@ -254,12 +231,6 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData } - $validator = \Validator::make([$model], \TransactionJournal::$rules); - if ($validator->invalid()) { - $errors->merge($errors); - } - - /* * Add "OK" */ @@ -275,20 +246,6 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData } - /** - * @param $type - * - * @return \AccountType|null - * @throws FireflyException - */ - public function getJournalType($type) - { - /** @var \FireflyIII\Database\TransactionType\TransactionType $typeRepository */ - $typeRepository = \App::make('FireflyIII\Database\TransactionType\TransactionType'); - - return $typeRepository->findByWhat($type); - } - /** * @param $currency * @@ -389,7 +346,26 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData if ($category) { $journal->categories()->sync([$category->id]); } + + return; } + $journal->categories()->sync([]); + + return; + } + + /** + * @param $type + * + * @return \TransactionType|null + * @throws FireflyException + */ + public function getJournalType($type) + { + /** @var \FireflyIII\Database\TransactionType\TransactionType $typeRepository */ + $typeRepository = \App::make('FireflyIII\Database\TransactionType\TransactionType'); + + return $typeRepository->findByWhat($type); } /** @@ -414,7 +390,6 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData */ public function findByWhat($what) { - // TODO: Implement findByWhat() method. throw new NotImplementedException; } @@ -478,16 +453,15 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData */ public function getSumOfExpensesByMonth(Carbon $date) { - $end = clone $date; - $date->startOfMonth(); - $end->endOfMonth(); + /** @var \FireflyIII\Report\ReportInterface $reportRepository */ + $reportRepository = \App::make('FireflyIII\Report\ReportInterface'); + + $set = $reportRepository->getExpenseGroupedForMonth($date, 200); + $sum = 0; + foreach ($set as $entry) { + $sum += $entry['amount']; + } - $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; } @@ -499,18 +473,17 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData */ public function getSumOfIncomesByMonth(Carbon $date) { - $end = clone $date; - $date->startOfMonth(); - $end->endOfMonth(); + /** @var \FireflyIII\Report\ReportInterface $reportRepository */ + $reportRepository = \App::make('FireflyIII\Report\ReportInterface'); - $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); + $incomes = $reportRepository->getIncomeForMonth($date); + $totalIn = 0; + /** @var \TransactionJournal $entry */ + foreach ($incomes as $entry) { + $totalIn += $entry->getAmount(); + } - return $sum; + return $totalIn; } /** @@ -598,37 +571,4 @@ class TransactionJournal implements TransactionJournalInterface, CUD, CommonData 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/TransactionJournal/TransactionJournalInterface.php b/app/lib/FireflyIII/Database/TransactionJournal/TransactionJournalInterface.php index 54635e088f..0268d53d81 100644 --- a/app/lib/FireflyIII/Database/TransactionJournal/TransactionJournalInterface.php +++ b/app/lib/FireflyIII/Database/TransactionJournal/TransactionJournalInterface.php @@ -41,4 +41,4 @@ interface TransactionJournalInterface */ public function getSumOfIncomesByMonth(Carbon $date); -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Database/TransactionType/TransactionType.php b/app/lib/FireflyIII/Database/TransactionType/TransactionType.php index d5bf703404..b3b5191de4 100644 --- a/app/lib/FireflyIII/Database/TransactionType/TransactionType.php +++ b/app/lib/FireflyIII/Database/TransactionType/TransactionType.php @@ -3,8 +3,8 @@ namespace FireflyIII\Database\TransactionType; -use FireflyIII\Database\CommonDatabaseCalls; -use FireflyIII\Database\CUD; +use FireflyIII\Database\CommonDatabaseCallsInterface; +use FireflyIII\Database\CUDInterface; use FireflyIII\Exception\FireflyException; use FireflyIII\Exception\NotImplementedException; use Illuminate\Database\Eloquent\Model as Eloquent; @@ -16,7 +16,7 @@ use Illuminate\Support\Collection; * * @package FireflyIII\Database */ -class TransactionType implements CUD, CommonDatabaseCalls +class TransactionType implements CUDInterface, CommonDatabaseCallsInterface { /** @@ -27,7 +27,6 @@ class TransactionType implements CUD, CommonDatabaseCalls */ public function destroy(Eloquent $model) { - // TODO: Implement destroy() method. throw new NotImplementedException; } @@ -39,7 +38,6 @@ class TransactionType implements CUD, CommonDatabaseCalls */ public function store(array $data) { - // TODO: Implement store() method. throw new NotImplementedException; } @@ -52,7 +50,6 @@ class TransactionType implements CUD, CommonDatabaseCalls */ public function update(Eloquent $model, array $data) { - // TODO: Implement update() method. throw new NotImplementedException; } @@ -67,7 +64,6 @@ class TransactionType implements CUD, CommonDatabaseCalls */ public function validate(array $model) { - // TODO: Implement validate() method. throw new NotImplementedException; } @@ -81,7 +77,6 @@ class TransactionType implements CUD, CommonDatabaseCalls */ public function find($objectId) { - // TODO: Implement find() method. throw new NotImplementedException; } @@ -95,25 +90,16 @@ class TransactionType implements CUD, CommonDatabaseCalls */ public function findByWhat($what) { - switch ($what) { - 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; - - + $translation = [ + 'opening' => 'Opening balance', + 'transfer' => 'Transfer', + 'withdrawal' => 'Withdrawal', + 'deposit' => 'Deposit', + ]; + if(!isset($translation[$what])) { + throw new FireflyException('Cannot find transaction type described as "' . e($what) . '".'); } + return \TransactionType::whereType($translation[$what])->first(); } /** @@ -124,7 +110,6 @@ class TransactionType implements CUD, CommonDatabaseCalls */ public function get() { - // TODO: Implement get() method. throw new NotImplementedException; } @@ -136,7 +121,6 @@ class TransactionType implements 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/User/User.php b/app/lib/FireflyIII/Database/User/User.php index e63bd8d57d..f60bfc3037 100644 --- a/app/lib/FireflyIII/Database/User/User.php +++ b/app/lib/FireflyIII/Database/User/User.php @@ -14,7 +14,7 @@ class User /** * @param $mail * - * @return null|User + * @return null|\User */ public function findByEmail($mail) { @@ -43,7 +43,8 @@ class User $user->reset = \Str::random(32); $user->password = \Hash::make(\Str::random(12)); - if (!$user->save()) { + // validate user: + if (!$user->isValid()) { \Log::error('Invalid user with data: ' . isset($data['email']) ? $data['email'] : '(no email!)'); \Session::flash('error', 'Input invalid, please try again: ' . $user->getErrors()->first()); @@ -69,4 +70,4 @@ class User return true; } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Event/Account.php b/app/lib/FireflyIII/Event/Account.php index bdc87d8e9a..6890d5b1e1 100644 --- a/app/lib/FireflyIII/Event/Account.php +++ b/app/lib/FireflyIII/Event/Account.php @@ -50,4 +50,4 @@ class 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 index f40e02b958..940f87d887 100644 --- a/app/lib/FireflyIII/Event/Budget.php +++ b/app/lib/FireflyIII/Event/Budget.php @@ -64,4 +64,4 @@ class Budget $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 index 0f4bfda97a..34980e5a8d 100644 --- a/app/lib/FireflyIII/Event/Event.php +++ b/app/lib/FireflyIII/Event/Event.php @@ -20,10 +20,10 @@ class Event public function deleteAccount(\Account $account) { // get piggy banks - $piggies = $account->piggybanks()->get(); + $piggies = $account->piggyBanks()->get(); // get reminders for each - /** @var \Piggybank $piggyBank */ + /** @var \PiggyBank $piggyBank */ foreach ($piggies as $piggyBank) { $reminders = $piggyBank->reminders()->get(); /** @var \Reminder $reminder */ @@ -42,4 +42,4 @@ class Event // 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 index bd9ee555f5..5c1960a170 100644 --- a/app/lib/FireflyIII/Event/Piggybank.php +++ b/app/lib/FireflyIII/Event/Piggybank.php @@ -7,22 +7,22 @@ use Carbon\Carbon; use Illuminate\Events\Dispatcher; /** - * Class Piggybank + * Class PiggyBank * * @package FireflyIII\Event */ -class Piggybank +class PiggyBank { /** - * @param \Piggybank $piggybank + * @param \PiggyBank $piggyBank * @param float $amount */ - public function addMoney(\Piggybank $piggybank, $amount = 0.0) + public function addMoney(\PiggyBank $piggyBank, $amount = 0.0) { if ($amount > 0) { $event = new \PiggyBankEvent; - $event->piggybank()->associate($piggybank); + $event->piggyBank()->associate($piggyBank); $event->amount = floatval($amount); $event->date = new Carbon; if (!$event->isValid()) { @@ -41,15 +41,15 @@ class Piggybank */ public function destroyTransfer(\TransactionJournal $journal) { - if ($journal->piggybankevents()->count() > 0) { + if ($journal->piggyBankEvents()->count() > 0) { /** @var \FireflyIII\Database\PiggyBank\PiggyBank $repository */ $repository = \App::make('FireflyIII\Database\PiggyBank\PiggyBank'); - /** @var \Piggybank $piggyBank */ - $piggyBank = $journal->piggybankevents()->first()->piggybank()->first(); + /** @var \PiggyBank $piggyBank */ + $piggyBank = $journal->piggyBankEvents()->first()->piggyBank()->first(); - /** @var \PiggybankRepetition $repetition */ + /** @var \PiggyBankRepetition $repetition */ $repetition = $repository->findRepetitionByDate($piggyBank, $journal->date); $relevantTransaction = null; @@ -68,7 +68,7 @@ class Piggybank $event = new \PiggyBankEvent; - $event->piggybank()->associate($piggyBank); + $event->piggyBank()->associate($piggyBank); $event->amount = floatval($relevantTransaction->amount * -1); $event->date = new Carbon; $event->save(); @@ -76,15 +76,15 @@ class Piggybank } /** - * @param \Piggybank $piggybank + * @param \PiggyBank $piggyBank * @param float $amount */ - public function removeMoney(\Piggybank $piggybank, $amount = 0.0) + public function removeMoney(\PiggyBank $piggyBank, $amount = 0.0) { $amount = $amount * -1; if ($amount < 0) { $event = new \PiggyBankEvent; - $event->piggybank()->associate($piggybank); + $event->piggyBank()->associate($piggyBank); $event->amount = floatval($amount); $event->date = new Carbon; $event->save(); @@ -92,18 +92,16 @@ class Piggybank } /** - * @param \Piggybank $piggybank + * @param \PiggyBank $piggyBank */ - public function storePiggybank(\Piggybank $piggybank) + 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(); - } + $repetition = new \PiggyBankRepetition; + $repetition->piggyBank()->associate($piggyBank); + $repetition->startdate = $piggyBank->startdate; + $repetition->targetdate = $piggyBank->targetdate; + $repetition->currentamount = 0; + $repetition->save(); } /* @@ -112,23 +110,23 @@ class Piggybank /** * @param \TransactionJournal $journal - * @param int $piggybankId + * @param int $piggyBankId */ - public function storeTransfer(\TransactionJournal $journal, $piggybankId = 0) + public function storeTransfer(\TransactionJournal $journal, $piggyBankId = 0) { - if (intval($piggybankId) == 0) { + if (intval($piggyBankId) == 0) { return; } /** @var \FireflyIII\Database\PiggyBank\PiggyBank $repository */ $repository = \App::make('FireflyIII\Database\PiggyBank\PiggyBank'); - /** @var \Piggybank $piggyBank */ - $piggyBank = $repository->find($piggybankId); + /** @var \PiggyBank $piggyBank */ + $piggyBank = $repository->find($piggyBankId); if ($journal->transactions()->where('account_id', $piggyBank->account_id)->count() == 0) { return; } - /** @var \PiggybankRepetition $repetition */ + /** @var \PiggyBankRepetition $repetition */ $repetition = $repository->findRepetitionByDate($piggyBank, $journal->date); $amount = floatval($piggyBank->targetamount); $leftToSave = $amount - floatval($repetition->currentamount); @@ -146,7 +144,7 @@ class Piggybank $repetition->currentamount += floatval($transaction->amount); $repetition->save(); $event = new \PiggyBankEvent; - $event->piggybank()->associate($piggyBank); + $event->piggyBank()->associate($piggyBank); $event->transactionjournal()->associate($journal); $event->amount = floatval($transaction->amount); $event->date = new Carbon; @@ -160,10 +158,10 @@ class Piggybank 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'); + $events->listen('piggy_bank.addMoney', 'FireflyIII\Event\PiggyBank@addMoney'); + $events->listen('piggy_bank.removeMoney', 'FireflyIII\Event\PiggyBank@removeMoney'); + $events->listen('piggy_bank.store', 'FireflyIII\Event\PiggyBank@storePiggyBank'); + $events->listen('piggy_bank.update', 'FireflyIII\Event\PiggyBank@updatePiggyBank'); \App::before( function () { @@ -171,13 +169,10 @@ class Piggybank } ); - //$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'); + $events->listen('transactionJournal.store', 'FireflyIII\Event\PiggyBank@storeTransfer'); + $events->listen('transactionJournal.update', 'FireflyIII\Event\PiggyBank@updateTransfer'); + $events->listen('transactionJournal.destroy', 'FireflyIII\Event\PiggyBank@destroyTransfer'); } /** @@ -194,21 +189,21 @@ class Piggybank $list = $repository->get(); $today = Carbon::now(); - /** @var \Piggybank $entry */ + /** @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(); + $count = $entry->piggyBankrepetitions()->starts($start)->targets($target)->count(); if ($count == 0) { - $repetition = new \PiggybankRepetition; - $repetition->piggybank()->associate($entry); + $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. + // then continue and do something in the current relevant time frame. $currentTarget = clone $target; $currentStart = null; @@ -216,10 +211,10 @@ class Piggybank $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(); + $count = $entry->piggyBankRepetitions()->starts($currentStart)->targets($currentTarget)->count(); if ($count == 0) { - $repetition = new \PiggybankRepetition; - $repetition->piggybank()->associate($entry); + $repetition = new \PiggyBankRepetition; + $repetition->piggyBank()->associate($entry); $repetition->startdate = $currentStart; $repetition->targetdate = $currentTarget; $repetition->currentamount = 0; @@ -231,9 +226,9 @@ class Piggybank } /** - * @param \Piggybank $piggyBank + * @param \PiggyBank $piggyBank */ - public function updatePiggybank(\Piggybank $piggyBank) + public function updatePiggyBank(\PiggyBank $piggyBank) { // get the repetition: $repetition = $piggyBank->currentRelevantRep(); @@ -251,18 +246,18 @@ class Piggybank public function updateTransfer(\TransactionJournal $journal) { - if ($journal->piggybankevents()->count() > 0) { + 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')); + $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\PiggyBank $repository */ $repository = \App::make('FireflyIII\Database\PiggyBank\PiggyBank'); - /** @var \Piggybank $piggyBank */ - $piggyBank = $journal->piggybankevents()->first()->piggybank()->first(); + /** @var \PiggyBank $piggyBank */ + $piggyBank = $journal->piggyBankEvents()->first()->piggyBank()->first(); - /** @var \PiggybankRepetition $repetition */ + /** @var \PiggyBankRepetition $repetition */ $repetition = $repository->findRepetitionByDate($piggyBank, $journal->date); $relevantTransaction = null; @@ -285,16 +280,16 @@ class Piggybank $event = new \PiggyBankEvent; - $event->piggybank()->associate($piggyBank); + $event->piggyBank()->associate($piggyBank); $event->transactionJournal()->associate($journal); $event->amount = $diff; $event->date = new Carbon; if (!$event->isValid()) { - var_dump($event->getErrors()); - exit(); + \Log::error($event->getErrors()); + \App::abort(500); } $event->save(); } } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Event/Transaction.php b/app/lib/FireflyIII/Event/Transaction.php index 2b58b3c97e..9c96070cd0 100644 --- a/app/lib/FireflyIII/Event/Transaction.php +++ b/app/lib/FireflyIII/Event/Transaction.php @@ -52,4 +52,4 @@ class 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 index ed62684c96..c7cabb911c 100644 --- a/app/lib/FireflyIII/Event/TransactionJournal.php +++ b/app/lib/FireflyIII/Event/TransactionJournal.php @@ -17,12 +17,12 @@ class TransactionJournal */ public function store(\TransactionJournal $journal) { - /** @var \FireflyIII\Database\RecurringTransaction\RecurringTransaction $repository */ - $repository = \App::make('FireflyIII\Database\RecurringTransaction\RecurringTransaction'); + /** @var \FireflyIII\Database\Bill\Bill $repository */ + $repository = \App::make('FireflyIII\Database\Bill\Bill'); $set = $repository->get(); - /** @var \RecurringTransaction $entry */ + /** @var \Bill $entry */ foreach ($set as $entry) { $repository->scan($entry, $journal); } @@ -43,15 +43,15 @@ class TransactionJournal */ public function update(\TransactionJournal $journal) { - /** @var \FireflyIII\Database\RecurringTransaction\RecurringTransaction $repository */ - $repository = \App::make('FireflyIII\Database\RecurringTransaction\RecurringTransaction'); - $set = $repository->get(); - $journal->recurring_transaction_id = null; + /** @var \FireflyIII\Database\Bill\Bill $repository */ + $repository = \App::make('FireflyIII\Database\Bill\Bill'); + $set = $repository->get(); + $journal->bill_id = null; $journal->save(); - /** @var \RecurringTransaction $entry */ + /** @var \Bill $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 index 69890ddfc4..a2d36d3b59 100644 --- a/app/lib/FireflyIII/Exception/FireflyException.php +++ b/app/lib/FireflyIII/Exception/FireflyException.php @@ -11,4 +11,4 @@ namespace FireflyIII\Exception; class FireflyException extends \Exception { -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Exception/NotImplementedException.php b/app/lib/FireflyIII/Exception/NotImplementedException.php index 208566204f..718e394f3e 100644 --- a/app/lib/FireflyIII/Exception/NotImplementedException.php +++ b/app/lib/FireflyIII/Exception/NotImplementedException.php @@ -10,4 +10,4 @@ namespace FireflyIII\Exception; class NotImplementedException extends \Exception { -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Exception/ValidationException.php b/app/lib/FireflyIII/Exception/ValidationException.php index b33a078b1c..77f6de015e 100644 --- a/app/lib/FireflyIII/Exception/ValidationException.php +++ b/app/lib/FireflyIII/Exception/ValidationException.php @@ -9,4 +9,4 @@ namespace FireflyIII\Exception; class ValidationException extends \Exception { -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/FF3ServiceProvider.php b/app/lib/FireflyIII/FF3ServiceProvider.php index b79fcf3053..879313a2d2 100644 --- a/app/lib/FireflyIII/FF3ServiceProvider.php +++ b/app/lib/FireflyIII/FF3ServiceProvider.php @@ -7,6 +7,7 @@ use FireflyIII\Shared\Toolkit\Form; use FireflyIII\Shared\Toolkit\Navigation; use FireflyIII\Shared\Toolkit\Reminders; use FireflyIII\Shared\Toolkit\Steam; +use FireflyIII\Shared\Toolkit\Amount; use FireflyIII\Shared\Validation\FireflyValidator; use Illuminate\Foundation\AliasLoader; use Illuminate\Support\ServiceProvider; @@ -43,8 +44,6 @@ class FF3ServiceProvider extends ServiceProvider */ public function register() { - // FORMAT: - #$this->app->bind('Interface', 'Class'); $this->registerFacades(); $this->registerInterfaces(); $this->registerAliases(); @@ -84,18 +83,29 @@ class FF3ServiceProvider extends ServiceProvider return new Steam; } ); + $this->app->bind( + 'amount', function () { + return new Amount; + } + ); } public function registerInterfaces() { - // preferences: + // preferences $this->app->bind('FireflyIII\Shared\Preferences\PreferencesInterface', 'FireflyIII\Shared\Preferences\Preferences'); - // registration and user mail: + // registration and user mail $this->app->bind('FireflyIII\Shared\Mail\RegistrationInterface', 'FireflyIII\Shared\Mail\Registration'); // reports $this->app->bind('FireflyIII\Report\ReportInterface', 'FireflyIII\Report\Report'); + $this->app->bind('FireflyIII\Report\ReportQueryInterface', 'FireflyIII\Report\ReportQuery'); + $this->app->bind('FireflyIII\Report\ReportHelperInterface', 'FireflyIII\Report\ReportHelper'); + + $this->app->bind('FireflyIII\Helper\Related\RelatedInterface', 'FireflyIII\Helper\Related\Related'); + + $this->app->bind('FireflyIII\Helper\TransactionJournal\HelperInterface', 'FireflyIII\Helper\TransactionJournal\Helper'); // chart $this->app->bind('FireflyIII\Chart\ChartInterface', 'FireflyIII\Chart\Chart'); @@ -113,8 +123,9 @@ class FF3ServiceProvider extends ServiceProvider $loader->alias('Navigation', 'FireflyIII\Shared\Facade\Navigation'); $loader->alias('FFForm', 'FireflyIII\Shared\Facade\FFForm'); $loader->alias('Steam', 'FireflyIII\Shared\Facade\Steam'); + $loader->alias('Amount', 'FireflyIII\Shared\Facade\Amount'); } ); } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Form/Form.php b/app/lib/FireflyIII/Form/Form.php index 13bf163944..68409ab2df 100644 --- a/app/lib/FireflyIII/Form/Form.php +++ b/app/lib/FireflyIII/Form/Form.php @@ -123,7 +123,7 @@ class Form $html .= \Form::input('text', $name, $value, $options); break; case 'amount': - $html .= '
'.getCurrencySymbol().'
'; + $html .= '
' . \Amount::getCurrencySymbol() . '
'; $html .= \Form::input('number', $name, $value, $options); $html .= '
'; break; @@ -379,4 +379,4 @@ class Form return self::ffInput('text', $name, $value, $options); } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Helper/Related/Related.php b/app/lib/FireflyIII/Helper/Related/Related.php new file mode 100644 index 0000000000..0627374e74 --- /dev/null +++ b/app/lib/FireflyIII/Helper/Related/Related.php @@ -0,0 +1,69 @@ +setUser(\Auth::user()); + } + + /** + * @param array $objectIds + * + * @return Collection + */ + public function getJournalsByIds(array $objectIds) + { + /** @var \FireflyIII\Database\TransactionJournal\TransactionJournal $repository */ + $repository = \App::make('FireflyIII\Database\TransactionJournal\TransactionJournal'); + + return $repository->getByIds($objectIds); + } + + /** + * @param string $query + * @param \TransactionJournal $journal + * + * @return Collection + */ + public function search($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 $current) { + $exclude[] = $current->id; + } + } + $exclude = array_unique($exclude); + + $query = $this->getUser()->transactionjournals() + ->withRelevantData() + ->before($end) + ->after($start) + ->whereNotIn('id', $exclude) + ->where('description', 'LIKE', '%' . $query . '%') + ->get(); + + return $query; + } +} diff --git a/app/lib/FireflyIII/Helper/Related/RelatedInterface.php b/app/lib/FireflyIII/Helper/Related/RelatedInterface.php new file mode 100644 index 0000000000..f2072cf823 --- /dev/null +++ b/app/lib/FireflyIII/Helper/Related/RelatedInterface.php @@ -0,0 +1,29 @@ +account->id); + } + + // otherwise (its a deposit), it's been paid into account #0. + return intval($transactions[0]->account->id); + } + + /** + * @return Collection + */ + public function getAssetAccounts() + { + /** @var \FireflyIII\Database\Account\Account $accountRepository */ + $accountRepository = \App::make('FireflyIII\Database\Account\Account'); + + return $accountRepository->getAssetAccounts(); + } + + /** + * @return Collection + */ + public function getBudgets() + { + /** @var \FireflyIII\Database\Budget\Budget $budgetRepository */ + $budgetRepository = \App::make('FireflyIII\Database\Budget\Budget'); + + return $budgetRepository->get(); + + } + + /** + * @return Collection + */ + public function getPiggyBanks() + { + /** @var \FireflyIII\Database\PiggyBank\PiggyBank $piggyRepository */ + $piggyRepository = \App::make('FireflyIII\Database\PiggyBank\PiggyBank'); + + return $piggyRepository->get(); + + + } + + /** + * @return Collection + */ + public function getRepeatedExpenses() + { + /** @var \FireflyIII\Database\PiggyBank\RepeatedExpense $repRepository */ + $repRepository = \App::make('FireflyIII\Database\PiggyBank\RepeatedExpense'); + + return $repRepository->get(); + + + } + +} diff --git a/app/lib/FireflyIII/Helper/TransactionJournal/HelperInterface.php b/app/lib/FireflyIII/Helper/TransactionJournal/HelperInterface.php new file mode 100644 index 0000000000..f49046a42a --- /dev/null +++ b/app/lib/FireflyIII/Helper/TransactionJournal/HelperInterface.php @@ -0,0 +1,52 @@ +_accounts = $accounts; + $this->_journals = $journals; + $this->_queries = \App::make('FireflyIII\Report\ReportQueryInterface'); + $this->_helper = \App::make('FireflyIII\Report\ReportHelperInterface'); + } @@ -41,36 +53,263 @@ class Report implements ReportInterface */ public function expensesGroupedByAccount(Carbon $start, Carbon $end, $limit = 15) { - return \TransactionJournal:: - leftJoin( - 'transactions as t_from', function ($join) { - $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0); + $result = $this->_queries->journalsByExpenseAccount($start, $end); + $array = $this->_helper->makeArray($result); + $limited = $this->_helper->limitArray($array, $limit); + + return $limited; + + } + + /** + * Gets all the users shared and non-shared accounts combined with various meta-data + * to display the amount of money spent that month compared to what's been spend within + * budgets. + * + * @param Carbon $date + * + * @return Collection + */ + public function getAccountListBudgetOverview(Carbon $date) + { + $start = clone $date; + $start->startOfMonth(); + $end = clone $date; + $end->endOfMonth(); + $start->subDay(); + $accounts = $this->_queries->getAllAccounts($start, $end); + + $accounts->each( + function (\Account $account) use ($start, $end) { + $budgets = $this->_queries->getBudgetSummary($account, $start, $end); + $balancedAmount = $this->_queries->balancedTransactionsSum($account, $start, $end); + $array = []; + foreach ($budgets as $budget) { + $id = intval($budget->id); + $data = $budget->toArray(); + $array[$id] = $data; + } + $account->budgetInformation = $array; + $account->balancedAmount = $balancedAmount; + + } + ); + + return $accounts; + + } + + /** + * @param Carbon $date + * + * @return array + */ + public function getAccountsForMonth(Carbon $date) + { + $start = clone $date; + $start->startOfMonth()->subDay(); + $end = clone $date; + $end->endOfMonth(); + \Log::debug('Monthly report account dates: start:[' . $start->format('Y-m-d') . '] and end:[' . $end->format('Y-m-d') . ']'); + $list = $this->_queries->accountList(); + $accounts = []; + /** @var \Account $account */ + foreach ($list as $account) { + $id = intval($account->id); + /** @noinspection PhpParamsInspection */ + $accounts[$id] = [ + 'name' => $account->name, + 'startBalance' => \Steam::balance($account, $start), + 'endBalance' => \Steam::balance($account, $end) + ]; + + $accounts[$id]['difference'] = $accounts[$id]['endBalance'] - $accounts[$id]['startBalance']; } - ) - ->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id') - ->leftJoin( - 'account_meta as acm_from', function ($join) { - $join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole'); - } - ) - ->leftJoin( - 'transactions as t_to', function ($join) { - $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0); - } - ) - ->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id') - ->leftJoin( - 'account_meta as acm_to', function ($join) { - $join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole'); - } - ) - ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') - ->where('transaction_types.type', 'Withdrawal') - ->where('acm_from.data', '!=', '"sharedExpense"') - ->before($end)->after($start) - ->where('transaction_journals.user_id', \Auth::user()->id) - ->groupBy('account_id')->orderBy('sum', 'DESC')->limit(15) - ->get(['t_to.account_id as account_id', 'ac_to.name as name', \DB::Raw('SUM(t_to.amount) as `sum`')]); + + return $accounts; + } + + /** + * @param Carbon $date + * + * @return Collection + */ + public function getBudgetsForMonth(Carbon $date) + { + $start = clone $date; + $start->startOfMonth(); + $end = clone $date; + $end->endOfMonth(); + // all budgets + $set = $this->_queries->getAllBudgets($date); + $budgets = $this->_helper->makeArray($set); + $amountSet = $this->_queries->journalsByBudget($start, $end); + $amounts = $this->_helper->makeArray($amountSet); + $combined = $this->_helper->mergeArrays($budgets, $amounts); + $combined[0]['spent'] = isset($combined[0]['spent']) ? $combined[0]['spent'] : 0.0; + $combined[0]['amount'] = isset($combined[0]['amount']) ? $combined[0]['amount'] : 0.0; + $combined[0]['name'] = 'No budget'; + + // find transactions to shared expense accounts, which are without a budget by default: + $transfers = $this->_queries->sharedExpenses($start, $end); + foreach ($transfers as $transfer) { + $combined[0]['spent'] += floatval($transfer->amount) * -1; + } + + return $combined; + } + + /** + * @param Carbon $date + * @param int $limit + * + * @return array + */ + public function getCategoriesForMonth(Carbon $date, $limit = 15) + { + $start = clone $date; + $start->startOfMonth(); + $end = clone $date; + $end->endOfMonth(); + // all categories. + $result = $this->_queries->journalsByCategory($start, $end); + $categories = $this->_helper->makeArray($result); + + // all transfers + $result = $this->_queries->sharedExpensesByCategory($start, $end); + $transfers = $this->_helper->makeArray($result); + $merged = $this->_helper->mergeArrays($categories, $transfers); + + // sort. + $sorted = $this->_helper->sortNegativeArray($merged); + + // limit to $limit: + $cut = $this->_helper->limitArray($sorted, $limit); + + return $cut; + } + + /** + * @param Carbon $date + * @param int $limit + * + * @return Collection + */ + public function getExpenseGroupedForMonth(Carbon $date, $limit = 15) + { + $start = clone $date; + $start->startOfMonth(); + $end = clone $date; + $end->endOfMonth(); + + $set = $this->_queries->journalsByExpenseAccount($start, $end); + $expenses = $this->_helper->makeArray($set); + + $alt = $this->_queries->sharedExpenses($start, $end); + $transfers = $this->_helper->makeArray($alt); + + $expenses[-1] = [ + 'amount' => 0, + 'name' => 'Transfers to shared', + 'spent' => 0 + ]; + + foreach ($transfers as $transfer) { + $expenses[-1]['amount'] += $transfer['amount']; + } + + $expenses = $this->_helper->sortArray($expenses); + $limited = $this->_helper->limitArray($expenses, $limit); + + return $limited; + + } + + /** + * @param Carbon $date + * @param bool $shared + * + * @return Collection + */ + public function getIncomeForMonth(Carbon $date, $shared = false) + { + $start = clone $date; + $start->startOfMonth(); + $end = clone $date; + $end->endOfMonth(); + $userId = $this->_accounts->getUser()->id; + + + $list = \TransactionJournal::leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id') + ->leftJoin( + 'account_meta', function (JoinClause $join) { + $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); + } + ) + ->transactionTypes(['Deposit']) + ->where('transaction_journals.user_id', $userId) + ->where('transactions.amount', '>', 0) + ->where('transaction_journals.user_id', \Auth::user()->id) + ->where('account_meta.data', '!=', '"sharedExpense"') + ->orderBy('date', 'ASC') + ->before($end)->after($start)->get(['transaction_journals.*']); + + // incoming from a shared account: it's profit (income): + $transfers = \TransactionJournal::withRelevantData() + ->leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id') + ->leftJoin( + 'account_meta', function (JoinClause $join) { + $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); + } + ) + ->transactionTypes(['Transfer']) + ->where('transaction_journals.user_id', $userId) + ->where('transactions.amount', '<', 0) + ->where('account_meta.data', '=', '"sharedExpense"') + ->orderBy('date', 'ASC') + ->before($end)->after($start)->get(['transaction_journals.*']); + + $list = $list->merge($transfers); + $list->sort( + function (\TransactionJournal $journal) { + return $journal->date->format('U'); + } + ); + + return $list; + } + + /** + * @param Carbon $date + * + * @return Collection + */ + public function getPiggyBanksForMonth(Carbon $date) + { + $start = clone $date; + $start->startOfMonth(); + $end = clone $date; + $end->endOfMonth(); + + \PiggyBank:: + leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') + ->where('accounts.user_id', \Auth::user()->id) + ->where('repeats', 0) + ->where( + function (Builder $query) use ($start, $end) { + $query->whereNull('piggy_banks.deleted_at'); + $query->orWhere( + function (Builder $query) use ($start, $end) { + $query->whereNotNull('piggy_banks.deleted_at'); + $query->where('piggy_banks.deleted_at', '>=', $start->format('Y-m-d 00:00:00')); + $query->where('piggy_banks.deleted_at', '<=', $end->format('Y-m-d 00:00:00')); + } + ); + } + ) + ->get(['piggy_banks.*']); } @@ -122,36 +361,8 @@ class Report implements ReportInterface */ public function revenueGroupedByAccount(Carbon $start, Carbon $end, $limit = 15) { - return \TransactionJournal:: - leftJoin( - 'transactions as t_from', function ($join) { - $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0); - } - ) - ->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id') - ->leftJoin( - 'account_meta as acm_from', function ($join) { - $join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole'); - } - ) - ->leftJoin( - 'transactions as t_to', function ($join) { - $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0); - } - ) - ->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id') - ->leftJoin( - 'account_meta as acm_to', function ($join) { - $join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole'); - } - ) - ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') - ->where('transaction_types.type', 'Deposit') - ->where('acm_to.data', '!=', '"sharedExpense"') - ->before($end)->after($start) - ->where('transaction_journals.user_id', \Auth::user()->id) - ->groupBy('account_id')->orderBy('sum')->limit(15) - ->get(['t_from.account_id as account_id', 'ac_from.name as name', \DB::Raw('SUM(t_from.amount) as `sum`')]); + return $this->_queries->journalsByRevenueAccount($start, $end); + } @@ -186,7 +397,7 @@ class Report implements ReportInterface } ); $report = []; - $start->startOfYear(); + $start->startOfYear()->subDay(); $end->endOfYear(); foreach ($accounts as $account) { @@ -201,4 +412,4 @@ class Report implements ReportInterface return $report; } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Report/ReportHelper.php b/app/lib/FireflyIII/Report/ReportHelper.php new file mode 100644 index 0000000000..d2e79b6d8f --- /dev/null +++ b/app/lib/FireflyIII/Report/ReportHelper.php @@ -0,0 +1,142 @@ + 'Others', + 'amount' => 0 + ]; + $return = []; + $count = 0; + foreach ($array as $id => $entry) { + if ($count < ($limit - 1)) { + $return[$id] = $entry; + } else { + $others['amount'] += $entry['amount']; + } + + $count++; + } + $return[0] = $others; + + return $return; + + } + + /** + * Turns a collection into an array. Needs the field 'id' for the key, + * and saves only 'name' and 'amount' as a sub array. + * + * @param Collection $collection + * + * @return array + */ + public function makeArray(Collection $collection) + { + $array = []; + foreach ($collection as $entry) { + $entry->spent = isset($entry->spent) ? floatval($entry->spent) : 0.0; + $id = intval($entry->id); + if (isset($array[$id])) { + $array[$id]['amount'] += floatval($entry->amount); + $array[$id]['spent'] += floatval($entry->spent); + } else { + $array[$id] = [ + 'amount' => floatval($entry->amount), + 'spent' => floatval($entry->spent), + 'name' => $entry->name + ]; + } + } + + return $array; + } + + /** + * Merges two of the arrays as defined above. Can't handle more (yet) + * + * @param array $one + * @param array $two + * + * @return array + */ + public function mergeArrays(array $one, array $two) + { + foreach ($two as $id => $value) { + // $otherId also exists in $one: + if (isset($one[$id])) { + $one[$id]['amount'] += $value['amount']; + $one[$id]['spent'] += $value['spent']; + } else { + $one[$id] = $value; + } + } + + return $one; + } + + /** + * Sort an array where all 'amount' keys are positive floats. + * + * @param array $array + * + * @return array + */ + public function sortArray(array $array) + { + uasort( + $array, function ($left, $right) { + if ($left['amount'] == $right['amount']) { + return 0; + } + + return ($left['amount'] < $right['amount']) ? 1 : -1; + } + ); + + return $array; + + } + + /** + * Sort an array where all 'amount' keys are negative floats. + * + * @param array $array + * + * @return array + */ + public function sortNegativeArray(array $array) + { + uasort( + $array, function ($left, $right) { + if ($left['amount'] == $right['amount']) { + return 0; + } + + return ($left['amount'] < $right['amount']) ? -1 : 1; + } + ); + + return $array; + } +} diff --git a/app/lib/FireflyIII/Report/ReportHelperInterface.php b/app/lib/FireflyIII/Report/ReportHelperInterface.php new file mode 100644 index 0000000000..828e322603 --- /dev/null +++ b/app/lib/FireflyIII/Report/ReportHelperInterface.php @@ -0,0 +1,64 @@ +accounts() + ->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') + ->leftJoin( + 'account_meta', function (JoinClause $join) { + $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', "accountRole"); + } + ) + ->whereIn('account_types.type', ['Default account', 'Cash account', 'Asset account']) + ->where('active', 1) + ->where( + function (Builder $query) { + $query->where('account_meta.data', '!=', '"sharedExpense"'); + $query->orWhereNull('account_meta.data'); + } + ) + ->get(['accounts.*']); + } + + /** + * This method will get a list of all expenses in a certain time period that have no budget + * and are balanced by a transfer to make up for it. + * + * @param \Account $account + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function balancedTransactionsList(\Account $account, Carbon $start, Carbon $end) + { + + $set = \TransactionJournal:: + leftJoin('transaction_group_transaction_journal', 'transaction_group_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin( + 'transaction_group_transaction_journal as otherFromGroup', function (JoinClause $join) { + $join->on('otherFromGroup.transaction_group_id', '=', 'transaction_group_transaction_journal.transaction_group_id') + ->on('otherFromGroup.transaction_journal_id', '!=', 'transaction_journals.id'); + } + ) + ->leftJoin('transaction_journals as otherJournals', 'otherJournals.id', '=', 'otherFromGroup.transaction_journal_id') + ->leftJoin('transaction_types', 'transaction_types.id', '=', 'otherJournals.transaction_type_id') + ->leftJoin( + 'transactions', function (JoinClause $join) { + $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0); + } + ) + ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'otherJournals.id') + ->before($end) + ->after($start) + ->where('transaction_types.type', 'Withdrawal') + ->where('transaction_journals.user_id', \Auth::user()->id) + ->whereNull('budget_transaction_journal.budget_id') + ->whereNull('transaction_journals.deleted_at') + ->whereNull('otherJournals.deleted_at') + ->where('transactions.account_id', $account->id) + ->whereNotNull('transaction_group_transaction_journal.transaction_group_id') + ->groupBy('transaction_journals.id') + ->get( + [ + 'transaction_journals.id as transferId', + 'transaction_journals.description as transferDescription', + 'transaction_group_transaction_journal.transaction_group_id as groupId', + 'otherFromGroup.transaction_journal_id as expenseId', + 'otherJournals.description as expenseDescription', + 'transactions.amount' + ] + ); + + return $set; + } + + /** + * This method will sum up all expenses in a certain time period that have no budget + * and are balanced by a transfer to make up for it. + * + * @param \Account $account + * @param Carbon $start + * @param Carbon $end + * + * @return float + */ + public function balancedTransactionsSum(\Account $account, Carbon $start, Carbon $end) + { + $list = $this->balancedTransactionsList($account, $start, $end); + $sum = 0; + foreach ($list as $entry) { + $sum += floatval($entry->amount); + } + + return $sum; + } + + /** + * Get a users accounts combined with various meta-data related to the start and end date. + * + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getAllAccounts(Carbon $start, Carbon $end) + { + $set = \Auth::user()->accounts() + ->accountTypeIn(['Default account', 'Asset account', 'Cash account']) + ->leftJoin( + 'account_meta', function (JoinClause $join) { + $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); + } + ) + ->where( + function (Builder $query) { + $query->where('account_meta.data', '!=', '"sharedExpense"'); + $query->orWhereNull('account_meta.data'); + } + ) + ->get(['accounts.*']); + $set->each( + function (\Account $account) use ($start, $end) { + /** @noinspection PhpParamsInspection */ + $account->startBalance = \Steam::balance($account, $start); + $account->endBalance = \Steam::balance($account, $end); + } + ); + + return $set; + } + + /** + * Gets a list of all budgets and if present, the amount of the current BudgetLimit + * as well + * + * @param Carbon $date + * + * @return Collection + */ + public function getAllBudgets(Carbon $date) + { + return \Auth::user()->budgets() + ->leftJoin( + 'budget_limits', function (JoinClause $join) use ($date) { + $join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d')); + } + ) + ->get(['budgets.*', 'budget_limits.amount as amount']); + } + + /** + * Grabs a summary of all expenses grouped by budget, related to the account. + * + * @param \Account $account + * @param Carbon $start + * @param Carbon $end + * + * @return mixed + */ + public function getBudgetSummary(\Account $account, Carbon $start, Carbon $end) + { + $set = \TransactionJournal:: + leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id') + ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') + ->leftJoin( + 'transactions', function (JoinClause $join) { + $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0); + } + ) + ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') + ->before($end) + ->after($start) + ->where('accounts.id', $account->id) + ->where('transaction_journals.user_id', \Auth::user()->id) + ->where('transaction_types.type', 'Withdrawal') + ->groupBy('budgets.id') + ->orderBy('budgets.id') + ->get(['budgets.id', 'budgets.name', \DB::Raw('SUM(`transactions`.`amount`) as `amount`')]); + + return $set; + + + } + + /** + * Gets a list of expenses grouped by the budget they were filed under. + * + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function journalsByBudget(Carbon $start, Carbon $end) + { + return \Auth::user()->transactionjournals() + ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id') + ->leftJoin( + 'transactions', function (JoinClause $join) { + $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); + } + ) + ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') + ->leftJoin( + 'account_meta', function (JoinClause $join) { + $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); + } + ) + ->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id') + ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) + ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) + ->where('account_meta.data', '!=', '"sharedExpense"') + ->where('transaction_types.type', 'Withdrawal') + ->groupBy('budgets.id') + ->orderBy('budgets.name', 'ASC') + ->get(['budgets.id', 'budgets.name', \DB::Raw('SUM(`transactions`.`amount`) AS `spent`')]); + } + + /** + * Gets a list of categories and the expenses therein, grouped by the relevant category. + * This result excludes transfers to shared accounts which are expenses, technically. + * + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function journalsByCategory(Carbon $start, Carbon $end) + { + return \Auth::user()->transactionjournals() + ->leftJoin( + 'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' + ) + ->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id') + ->leftJoin( + 'transactions', function (JoinClause $join) { + $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); + } + ) + ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') + ->leftJoin( + 'account_meta', function (JoinClause $join) { + $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); + } + ) + ->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id') + ->where('transaction_journals.date', '>=', $start->format('Y-m-d')) + ->where('transaction_journals.date', '<=', $end->format('Y-m-d')) + ->where('account_meta.data', '!=', '"sharedExpense"') + ->where('transaction_types.type', 'Withdrawal') + ->groupBy('categories.id') + ->orderBy('amount') + ->get(['categories.id', 'categories.name', \DB::Raw('SUM(`transactions`.`amount`) AS `amount`')]); + + } + + /** + * Gets a list of expense accounts and the expenses therein, grouped by that expense account. + * This result excludes transfers to shared accounts which are expenses, technically. + * + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function journalsByExpenseAccount(Carbon $start, Carbon $end) + { + return \TransactionJournal:: + leftJoin( + 'transactions as t_from', function (JoinClause $join) { + $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0); + } + ) + ->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id') + ->leftJoin( + 'account_meta as acm_from', function (JoinClause $join) { + $join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole'); + } + ) + ->leftJoin( + 'transactions as t_to', function (JoinClause $join) { + $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0); + } + ) + ->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id') + ->leftJoin( + 'account_meta as acm_to', function (JoinClause $join) { + $join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole'); + } + ) + ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') + ->where('transaction_types.type', 'Withdrawal') + ->where('acm_from.data', '!=', '"sharedExpense"') + ->before($end) + ->after($start) + ->where('transaction_journals.user_id', \Auth::user()->id) + ->groupBy('t_to.account_id') + ->orderBy('amount', 'DESC') + ->get(['t_to.account_id as id', 'ac_to.name as name', \DB::Raw('SUM(t_to.amount) as `amount`')]); + } + + /** + * This method returns all deposits into asset accounts, grouped by the revenue account, + * + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function journalsByRevenueAccount(Carbon $start, Carbon $end) + { + return \TransactionJournal:: + leftJoin( + 'transactions as t_from', function (JoinClause $join) { + $join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0); + } + ) + ->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id') + ->leftJoin( + 'account_meta as acm_from', function (JoinClause $join) { + $join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole'); + } + ) + ->leftJoin( + 'transactions as t_to', function (JoinClause $join) { + $join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0); + } + ) + ->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id') + ->leftJoin( + 'account_meta as acm_to', function (JoinClause $join) { + $join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole'); + } + ) + ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') + ->where('transaction_types.type', 'Deposit') + ->where('acm_to.data', '!=', '"sharedExpense"') + ->before($end)->after($start) + ->where('transaction_journals.user_id', \Auth::user()->id) + ->groupBy('t_from.account_id')->orderBy('amount') + ->get(['t_from.account_id as account_id', 'ac_from.name as name', \DB::Raw('SUM(t_from.amount) as `amount`')]); + } + + /** + * With an equally misleading name, this query returns are transfers to shared accounts. These are considered + * expenses. + * + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function sharedExpenses(Carbon $start, Carbon $end) + { + return \TransactionJournal:: + leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') + ->leftJoin( + 'transactions', function (JoinClause $join) { + $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where( + 'transactions.amount', '>', 0 + ); + } + ) + ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') + ->leftJoin( + 'account_meta', function (JoinClause $join) { + $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); + } + ) + ->where('account_meta.data', '"sharedExpense"') + ->after($start) + ->before($end) + ->where('transaction_types.type', 'Transfer') + ->where('transaction_journals.user_id', \Auth::user()->id) + ->get( + ['transaction_journals.id', 'transaction_journals.description', 'transactions.account_id', 'accounts.name', + 'transactions.amount'] + ); + + } + + /** + * With a slightly misleading name, this query returns all transfers to shared accounts + * which are technically expenses, since it won't be just your money that gets spend. + * + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function sharedExpensesByCategory(Carbon $start, Carbon $end) + { + return \TransactionJournal:: + leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') + ->leftJoin( + 'transactions', function (JoinClause $join) { + $join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where( + 'transactions.amount', '>', 0 + ); + } + ) + ->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') + ->leftJoin( + 'account_meta', function (JoinClause $join) { + $join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole'); + } + ) + ->leftJoin( + 'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id' + ) + ->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id') + ->where('account_meta.data', '"sharedExpense"') + ->after($start) + ->before($end) + ->where('transaction_types.type', 'Transfer') + ->where('transaction_journals.user_id', \Auth::user()->id) + ->groupBy('categories.name') + ->get( + [ + 'categories.id', + 'categories.name as name', + \DB::Raw('SUM(`transactions`.`amount`) * -1 AS `amount`') + ] + ); + } +} diff --git a/app/lib/FireflyIII/Report/ReportQueryInterface.php b/app/lib/FireflyIII/Report/ReportQueryInterface.php new file mode 100644 index 0000000000..a2097c6635 --- /dev/null +++ b/app/lib/FireflyIII/Report/ReportQueryInterface.php @@ -0,0 +1,142 @@ +accounts()->with('accounttype')->where( - function ($q) use ($words) { + function (EloquentBuilder $q) use ($words) { foreach ($words as $word) { $q->orWhere('name', 'LIKE', '%' . e($word) . '%'); } @@ -96,11 +97,11 @@ class Search public function searchTransactions(array $words) { return \Auth::user()->transactionjournals()->withRelevantData()->where( - function ($q) use ($words) { + function (EloquentBuilder $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/Amount.php b/app/lib/FireflyIII/Shared/Facade/Amount.php new file mode 100644 index 0000000000..4a3eb4dba4 --- /dev/null +++ b/app/lib/FireflyIII/Shared/Facade/Amount.php @@ -0,0 +1,24 @@ + $password]; try { \Mail::send( - ['emails.user.register-html', 'emails.user.register-text'], $data, function ($message) use ($email) { + ['emails.user.register-html', 'emails.user.register-text'], $data, function (Message $message) use ($email) { + $message->to($email, $email)->subject('Welcome to Firefly!'); } ); @@ -49,11 +50,14 @@ class Registration implements RegistrationInterface $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?'); + try { + \Mail::send( + ['emails.user.remindMe-html', 'emails.user.remindMe-text'], $data, function (Message $message) use ($email) { + $message->to($email, $email)->subject('Forgot your password?'); + } + ); + } catch (Swift_RfcComplianceException $e) { } - ); } @@ -72,11 +76,15 @@ class Registration implements RegistrationInterface $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.'); + try { + \Mail::send( + ['emails.user.verify-html', 'emails.user.verify-text'], $data, function (Message $message) use ($email) { + + $message->to($email, $email)->subject('Verify your e-mail address.'); + } + ); + } catch (Swift_RfcComplianceException $e) { } - ); } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Shared/Mail/RegistrationInterface.php b/app/lib/FireflyIII/Shared/Mail/RegistrationInterface.php index 0741757b4e..df104cc50a 100644 --- a/app/lib/FireflyIII/Shared/Mail/RegistrationInterface.php +++ b/app/lib/FireflyIII/Shared/Mail/RegistrationInterface.php @@ -31,4 +31,4 @@ interface RegistrationInterface */ public function sendVerificationMail(\User $user); -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Shared/Preferences/Preferences.php b/app/lib/FireflyIII/Shared/Preferences/Preferences.php index d7d335dcd7..85ab05cbc7 100644 --- a/app/lib/FireflyIII/Shared/Preferences/Preferences.php +++ b/app/lib/FireflyIII/Shared/Preferences/Preferences.php @@ -24,6 +24,7 @@ class Preferences implements PreferencesInterface if (!is_null($pref)) { return $pref; } + return $this->set($name, $default); } @@ -50,4 +51,4 @@ class Preferences implements PreferencesInterface return $pref; } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Shared/Preferences/PreferencesInterface.php b/app/lib/FireflyIII/Shared/Preferences/PreferencesInterface.php index 1a3cb217eb..3dd5606235 100644 --- a/app/lib/FireflyIII/Shared/Preferences/PreferencesInterface.php +++ b/app/lib/FireflyIII/Shared/Preferences/PreferencesInterface.php @@ -26,4 +26,4 @@ interface PreferencesInterface */ public function set($name, $value); -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Shared/Toolkit/Amount.php b/app/lib/FireflyIII/Shared/Toolkit/Amount.php new file mode 100644 index 0000000000..39a1db073b --- /dev/null +++ b/app/lib/FireflyIII/Shared/Toolkit/Amount.php @@ -0,0 +1,148 @@ +getCurrencySymbol(); + + return $this->formatWithSymbol($currencySymbol, $amount, $coloured); + + + } + + /** + * @return string + */ + public function getCurrencySymbol() + { + if (defined('FFCURRENCYSYMBOL')) { + return FFCURRENCYSYMBOL; + } + if (\Cache::has('FFCURRENCYSYMBOL')) { + define('FFCURRENCYSYMBOL', \Cache::get('FFCURRENCYSYMBOL')); + + return FFCURRENCYSYMBOL; + } + + /** @var \FireflyIII\Database\TransactionCurrency\TransactionCurrency $currencies */ + $currencies = \App::make('FireflyIII\Database\TransactionCurrency\TransactionCurrency'); + + /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */ + $preferences = \App::make('FireflyIII\Shared\Preferences\Preferences'); + + $currencyPreference = $preferences->get('currencyPreference', 'EUR'); + $currency = $currencies->findByCode($currencyPreference->data); + + \Cache::forever('FFCURRENCYSYMBOL', $currency->symbol); + + define('FFCURRENCYSYMBOL', $currency->symbol); + + return $currency->symbol; + } + + /** + * @param string $symbol + * @param float $amount + * @param bool $coloured + * + * @return string + */ + protected function formatWithSymbol($symbol, $amount, $coloured = true) + { + $amount = floatval($amount); + $amount = round($amount, 2); + $string = number_format($amount, 2, ',', '.'); + + if ($coloured === true) { + if ($amount === 0.0) { + return '' . $symbol . ' ' . $string . ''; + } + if ($amount > 0) { + return '' . $symbol . ' ' . $string . ''; + } + + return '' . $symbol . ' ' . $string . ''; + } + + // € + return $symbol . ' ' . $string; + } + + /** + * @param \TransactionJournal $journal + * @param float $amount + * @param bool $coloured + * + * @return string + */ + public function formatJournal(\TransactionJournal $journal, $amount, $coloured = true) + { + $symbol = $journal->transactionCurrency->symbol; + + return $this->formatWithSymbol($symbol, $amount, $coloured); + + + } + + /** + * @param \Transaction $transaction + * @param bool $coloured + * + * @return string + */ + public function formatTransaction(\Transaction $transaction, $coloured = true) + { + $symbol = $transaction->transactionJournal->transactionCurrency->symbol; + $amount = floatval($transaction->amount); + + return $this->formatWithSymbol($symbol, $amount, $coloured); + + + } + + /** + * @return string + */ + public function getCurrencyCode() + { + if (defined('FFCURRENCYCODE')) { + return FFCURRENCYCODE; + } + if (\Cache::has('FFCURRENCYCODE')) { + define('FFCURRENCYCODE', \Cache::get('FFCURRENCYCODE')); + + return FFCURRENCYCODE; + } + + /** @var \FireflyIII\Database\TransactionCurrency\TransactionCurrency $currencies */ + $currencies = \App::make('FireflyIII\Database\TransactionCurrency\TransactionCurrency'); + + /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */ + $preferences = \App::make('FireflyIII\Shared\Preferences\Preferences'); + + $currencyPreference = $preferences->get('currencyPreference', 'EUR'); + $currency = $currencies->findByCode($currencyPreference->data); + + \Cache::forever('FFCURRENCYCODE', $currency->code); + + define('FFCURRENCYCODE', $currency->code); + + return $currency->code; + } + +} diff --git a/app/lib/FireflyIII/Shared/Toolkit/Date.php b/app/lib/FireflyIII/Shared/Toolkit/Date.php index 347a9b3c85..3f7b321216 100644 --- a/app/lib/FireflyIII/Shared/Toolkit/Date.php +++ b/app/lib/FireflyIII/Shared/Toolkit/Date.php @@ -14,10 +14,10 @@ class Date { /** * @param Carbon $theDate - * @param $repeatFreq - * @param $skip + * @param $repeatFreq + * @param $skip * - * @return Carbon + * @return \Carbon\Carbon * @throws FireflyException */ public function addPeriod(Carbon $theDate, $repeatFreq, $skip) @@ -27,7 +27,7 @@ class Date switch ($repeatFreq) { default: - throw new FireflyException('Cannot do addPeriod for $repeat_freq ' . $repeatFreq); + throw new FireflyException('Cannot do addPeriod for $repeat_freq "' . $repeatFreq . '"'); break; case 'daily': $date->addDays($add); @@ -60,9 +60,9 @@ class Date /** * @param Carbon $theCurrentEnd - * @param $repeatFreq + * @param $repeatFreq * - * @return mixed + * @return Carbon * @throws FireflyException */ public function endOfPeriod(Carbon $theCurrentEnd, $repeatFreq) @@ -101,10 +101,10 @@ class Date /** * @param Carbon $theCurrentEnd - * @param $repeatFreq + * @param $repeatFreq * @param Carbon $maxDate * - * @return mixed + * @return Carbon * @throws FireflyException */ public function endOfX(Carbon $theCurrentEnd, $repeatFreq, Carbon $maxDate) @@ -150,7 +150,7 @@ class Date /** * @param Carbon $date - * @param $repeatFrequency + * @param $repeatFrequency * * @return string * @throws FireflyException @@ -184,7 +184,7 @@ class Date /** * @param Carbon $theDate - * @param $repeatFreq + * @param $repeatFreq * * @return Carbon * @throws FireflyException @@ -229,8 +229,8 @@ class Date /** * @param Carbon $theDate - * @param $repeatFreq - * @param int $subtract + * @param $repeatFreq + * @param int $subtract * * @return Carbon * @throws FireflyException @@ -242,12 +242,15 @@ class Date default: throw new FireflyException('Cannot do subtractPeriod for $repeat_freq ' . $repeatFreq); break; + case 'day': case 'daily': $date->subDays($subtract); break; + case 'week': case 'weekly': $date->subWeeks($subtract); break; + case 'month': case 'monthly': $date->subMonths($subtract); break; diff --git a/app/lib/FireflyIII/Shared/Toolkit/Filter.php b/app/lib/FireflyIII/Shared/Toolkit/Filter.php index 0db6bb5d8a..9be82e313a 100644 --- a/app/lib/FireflyIII/Shared/Toolkit/Filter.php +++ b/app/lib/FireflyIII/Shared/Toolkit/Filter.php @@ -266,4 +266,4 @@ class Filter 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 036257fb1a..55457dc7d5 100644 --- a/app/lib/FireflyIII/Shared/Toolkit/Form.php +++ b/app/lib/FireflyIII/Shared/Toolkit/Form.php @@ -1,9 +1,9 @@ startOfMonth()); /* - * Substract some period to $start. + * Subtract some period to $start. */ $prev = $filter->previous($range, clone $start); @@ -65,4 +66,4 @@ class Navigation 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 index c70ea542e6..fe3b40ed9b 100644 --- a/app/lib/FireflyIII/Shared/Toolkit/Reminders.php +++ b/app/lib/FireflyIII/Shared/Toolkit/Reminders.php @@ -25,7 +25,7 @@ class Reminders switch (get_class($reminder->remindersable)) { - case 'Piggybank': + case 'PiggyBank': $start = new Carbon; $end = !is_null($reminder->remindersable->targetdate) ? clone $reminder->remindersable->targetdate : new Carbon; $reminders = 0; @@ -65,16 +65,16 @@ class Reminders public function updateReminders() { /** @var Collection $set */ - $set = \Piggybank::leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id') + $set = \PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') ->where('accounts.user_id', \Auth::user()->id) - ->whereNotNull('reminder')->get(['piggybanks.*']); + ->whereNotNull('reminder')->get(['piggy_banks.*']); $today = Carbon::now(); - /** @var \Piggybank $piggybank */ + /** @var \PiggyBank $piggyBank */ foreach ($set as $piggyBank) { - /** @var \PiggybankRepetition $repetition */ + /** @var \PiggyBankRepetition $repetition */ $repetition = $piggyBank->currentRelevantRep(); $start = \DateKit::startOfPeriod($today, $piggyBank->reminder); if ($repetition->targetdate && $repetition->targetdate <= $today) { @@ -93,9 +93,9 @@ class Reminders $reminder->active = 1; $reminder->user()->associate(\Auth::getUser()); $reminder->remindersable_id = $piggyBank->id; - $reminder->remindersable_type = 'Piggybank'; + $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 index 03d0238e57..2a2696372f 100644 --- a/app/lib/FireflyIII/Shared/Toolkit/Steam.php +++ b/app/lib/FireflyIII/Shared/Toolkit/Steam.php @@ -16,6 +16,7 @@ class Steam { /** + * * @param \Account $account * @param Carbon $date * @@ -23,35 +24,40 @@ class Steam */ public function balance(\Account $account, Carbon $date = null) { - \Log::debug('Now in Steam::balance() for account #' . $account->id.' ('.$account->name.')'); - if (is_null($date)) { - $key = 'account.' . $account->id . '.latestBalance'; - } else { - $key = 'account.' . $account->id . '.balanceOn' . $date->format('dmy'); - } - if (\Cache::has($key)) { - // TODO find a way to reliably remove cache entries for accounts. - #return \Cache::get($key); - } $date = is_null($date) ? Carbon::now() : $date; - \Log::debug('Now reached the moment we fire the query.'); $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') ); - \Cache::put($key, $balance, 20160); return $balance; } /** - * @param \Piggybank $piggyBank - * @param \PiggybankRepetition $repetition + * @param $boolean + * + * @return string + */ + public function boolString($boolean) + { + if ($boolean === true) { + return 'BOOLEAN TRUE'; + } + if ($boolean === false) { + return 'BOOLEAN FALSE'; + } + + return 'NO BOOLEAN: ' . $boolean; + } + + /** + * @param \PiggyBank $piggyBank + * @param \PiggyBankRepetition $repetition * * @return int */ - public function percentage(\Piggybank $piggyBank, \PiggybankRepetition $repetition) + public function percentage(\PiggyBank $piggyBank, \PiggyBankRepetition $repetition) { $pct = $repetition->currentamount / $piggyBank->targetamount * 100; if ($pct > 100) { @@ -69,4 +75,4 @@ class Steam } } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Shared/Validation/FireflyValidator.php b/app/lib/FireflyIII/Shared/Validation/FireflyValidator.php index 4b656d2723..544174a1c5 100644 --- a/app/lib/FireflyIII/Shared/Validation/FireflyValidator.php +++ b/app/lib/FireflyIII/Shared/Validation/FireflyValidator.php @@ -26,4 +26,4 @@ class FireflyValidator extends Validator return true; } } -} \ No newline at end of file +} diff --git a/app/lib/FireflyIII/Shared/Validation/ValidationServiceProvider.php b/app/lib/FireflyIII/Shared/Validation/ValidationServiceProvider.php index 96a421aeca..b8bc15ac2b 100644 --- a/app/lib/FireflyIII/Shared/Validation/ValidationServiceProvider.php +++ b/app/lib/FireflyIII/Shared/Validation/ValidationServiceProvider.php @@ -24,4 +24,4 @@ class ValidationServiceProvider extends ServiceProvider public function register() { } -} \ No newline at end of file +} diff --git a/app/models/Account.php b/app/models/Account.php index e69680cdf1..667aae069e 100644 --- a/app/models/Account.php +++ b/app/models/Account.php @@ -1,8 +1,10 @@ hasMany('Piggybank'); + return $this->hasMany('PiggyBank'); } /** * - * @param Builder $query + * @param EloquentBuilder $query * @param array $types */ - public function scopeAccountTypeIn(Builder $query, array $types) + public function scopeAccountTypeIn(EloquentBuilder $query, array $types) { if (is_null($this->joinedAccountTypes)) { $query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id'); @@ -78,9 +80,9 @@ class Account extends Eloquent /** * - * @param Builder $query + * @param EloquentBuilder $query */ - public function scopeWithMeta(Builder $query) + public function scopeWithMeta(EloquentBuilder $query) { $query->with(['accountmeta']); } @@ -141,4 +143,4 @@ class Account extends Eloquent } -} \ No newline at end of file +} diff --git a/app/models/AccountMeta.php b/app/models/AccountMeta.php index 40314b761a..5a481a2c90 100644 --- a/app/models/AccountMeta.php +++ b/app/models/AccountMeta.php @@ -48,4 +48,4 @@ class AccountMeta extends Eloquent $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 2d3f968198..eb3f495e87 100644 --- a/app/models/AccountType.php +++ b/app/models/AccountType.php @@ -22,4 +22,4 @@ class AccountType extends Eloquent { return $this->hasMany('Account'); } -} \ No newline at end of file +} diff --git a/app/models/Bill.php b/app/models/Bill.php new file mode 100644 index 0000000000..00d7d2c1e4 --- /dev/null +++ b/app/models/Bill.php @@ -0,0 +1,50 @@ + 'required|exists:users,id', + 'name' => 'required|between:1,255|min:1', + 'match' => 'required', + 'amount_max' => 'required|between:0,65536', + 'amount_min' => 'required|between:0,65536', + 'date' => 'required|date', + 'active' => 'between:0,1', + 'automatch' => 'between:0,1', + 'repeat_freq' => 'required|in:daily,weekly,monthly,quarterly,half-year,yearly', + 'skip' => 'required|between:0,31',]; + protected $fillable = ['user_id', 'name', 'match', 'amount_min', 'amount_max', 'date', 'repeat_freq', 'skip', 'active', 'automatch']; + /** + * @return array + */ + public function getDates() + { + return ['created_at', 'updated_at', 'date']; + } + + /** + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function transactionjournals() + { + return $this->hasMany('TransactionJournal'); + } + + + + /** + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function user() + { + return $this->belongsTo('User'); + } +} diff --git a/app/models/Budget.php b/app/models/Budget.php index e277b51ca6..83368d9143 100644 --- a/app/models/Budget.php +++ b/app/models/Budget.php @@ -28,7 +28,7 @@ class Budget extends Eloquent */ public function budgetlimits() { - return $this->hasMany('BudgetLimit', 'budget_id'); + return $this->hasMany('BudgetLimit'); } /** @@ -47,4 +47,4 @@ class Budget extends Eloquent return $this->belongsTo('User'); } -} \ No newline at end of file +} diff --git a/app/models/BudgetLimit.php b/app/models/BudgetLimit.php index 684ad1a11e..7c21bb74e9 100644 --- a/app/models/BudgetLimit.php +++ b/app/models/BudgetLimit.php @@ -1,9 +1,10 @@ 'required|exists:budgets,id', - 'startdate' => 'required|date', - 'amount' => 'numeric|required|min:0.01', - 'repeats' => 'required|boolean', - 'repeat_freq' => 'required|in:daily,weekly,monthly,quarterly,half-year,yearly' + 'budget_id' => 'required|exists:budgets,id', + 'startdate' => 'required|date', + 'amount' => 'numeric|required|min:0.01', + 'repeats' => 'required|boolean', + 'repeat_freq' => 'required|in:daily,weekly,monthly,quarterly,half-year,yearly' ]; @@ -27,73 +28,7 @@ class BudgetLimit extends Eloquent */ public function budget() { - return $this->belongsTo('Budget','budget_id'); - } - - /** - * TODO see if this method is still used. - * Create a new repetition for this limit, starting on - * the given date. - * - * @param Carbon $start - */ - public function createRepetition(Carbon $start) - { - - $end = clone $start; - // go to end: - switch ($this->repeat_freq) { - case 'daily': - $end->addDay(); - break; - case 'weekly': - $end->addWeek(); - break; - case 'monthly': - $end->addMonth(); - break; - case 'quarterly': - $end->addMonths(3); - break; - case 'half-year': - $end->addMonths(6); - break; - case 'yearly': - $end->addYear(); - break; - } - $end->subDay(); - $count = $this->limitrepetitions()->where('startdate', $start->format('Y-m-d'))->where('enddate', $end->format('Y-m-d'))->count(); - - if ($count == 0) { - - $repetition = new \LimitRepetition(); - $repetition->startdate = $start; - $repetition->enddate = $end; - $repetition->amount = $this->amount; - $repetition->budgetLimit()->associate($this); - - try { - $repetition->save(); - \Log::debug('Created new repetition with id #' . $repetition->id); - } catch (QueryException $e) { - // do nothing - - \Log::error('Trying to save new Limitrepetition failed!'); - \Log::error($e->getMessage()); - } - if (isset($repetition->id)) { - \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(); - - } - } + return $this->belongsTo('Budget'); } /** @@ -114,4 +49,4 @@ class BudgetLimit extends Eloquent } -} \ No newline at end of file +} diff --git a/app/models/Category.php b/app/models/Category.php index 782a394585..dab2639a0b 100644 --- a/app/models/Category.php +++ b/app/models/Category.php @@ -36,7 +36,7 @@ class Category extends Eloquent */ public function transactionjournals() { - return $this->belongsToMany('TransactionJournal', 'budget_transaction_journal', 'budget_id'); + return $this->belongsToMany('TransactionJournal', 'category_transaction_journal', 'category_id'); } /** @@ -46,4 +46,4 @@ class Category extends Eloquent { return $this->belongsTo('User'); } -} \ No newline at end of file +} diff --git a/app/models/Component.php b/app/models/Component.php index 151233d950..e09edbe19b 100644 --- a/app/models/Component.php +++ b/app/models/Component.php @@ -17,4 +17,4 @@ class Component extends Eloquent protected $fillable = ['name', 'user_id','class']; protected $table = 'components'; use ValidatingTrait; -} \ No newline at end of file +} diff --git a/app/models/LimitRepetition.php b/app/models/LimitRepetition.php index e36348f849..fc9eec5943 100644 --- a/app/models/LimitRepetition.php +++ b/app/models/LimitRepetition.php @@ -34,18 +34,6 @@ class LimitRepetition extends Eloquent } /** - * 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 */ @@ -64,43 +52,4 @@ class LimitRepetition extends Eloquent 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 - * return 2012-12. - */ - public function periodOrder() - { - if (is_null($this->repeat_freq)) { - $this->repeat_freq = $this->limit->repeat_freq; - } - switch ($this->repeat_freq) { - default: - throw new FireflyException('No date formats for frequency "' . $this->repeat_freq . '"!'); - break; - case 'daily': - return $this->startdate->format('Ymd') . '-5'; - break; - case 'weekly': - return $this->startdate->format('Ymd') . '-4'; - break; - case 'monthly': - return $this->startdate->format('Ymd') . '-3'; - break; - case 'quarterly': - return $this->startdate->format('Ymd') . '-2'; - break; - case 'half-year': - return $this->startdate->format('Ymd') . '-1'; - break; - case 'yearly': - return $this->startdate->format('Ymd') . '-0'; - break; - } - } - -} \ No newline at end of file +} diff --git a/app/models/Piggybank.php b/app/models/Piggybank.php index cb5d420795..49e7563445 100644 --- a/app/models/Piggybank.php +++ b/app/models/Piggybank.php @@ -1,18 +1,23 @@ 'required|exists:accounts,id', // link to Account 'name' => 'required|between:1,255', // name - 'targetamount' => 'required|min:0', // amount you want to save + 'targetamount' => 'required|min:0.01|numeric', // amount you want to save 'startdate' => 'date', // when you started 'targetdate' => 'date', // when its due 'repeats' => 'required|boolean', // does it repeat? @@ -23,9 +28,6 @@ class Piggybank extends Eloquent '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 @@ -36,52 +38,9 @@ class Piggybank extends Eloquent } /** - * 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->currentamount = 0; - $rep->save(); - - return $rep; - } - - /** - * TODO remove this method in favour of something in the FireflyIII libraries. - * * Grabs the PiggyBankRepetition that's currently relevant / active * - * @returns \PiggybankRepetition + * @returns \PiggyBankRepetition */ public function currentRelevantRep() { @@ -89,44 +48,42 @@ class Piggybank extends Eloquent return $this->currentRep; } if ($this->repeats == 0) { - $rep = $this->piggybankrepetitions()->first(['piggybank_repetitions.*']); + $rep = $this->piggyBankRepetitions()->first(['piggy_bank_repetitions.*']); $this->currentRep = $rep; - \Log::debug('currentRelevantRep() reports $rep is null: ' . boolstr(is_null($rep))); return $rep; } else { - $query = $this->piggybankrepetitions()->where( - function ($q) { + $query = $this->piggyBankRepetitions()->where( + function (EloquentBuilder $q) { $q->where( - function ($q) { + function (EloquentBuilder $q) { $q->where( - function ($q) { + function (EloquentBuilder $q) { $today = new Carbon; $q->whereNull('startdate'); - $q->orWhere('startdate', '<=', $today->format('Y-m-d')); + $q->orWhere('startdate', '<=', $today->format('Y-m-d 00:00:00')); } )->where( - function ($q) { + function (EloquentBuilder $q) { $today = new Carbon; $q->whereNull('targetdate'); - $q->orWhere('targetdate', '>=', $today->format('Y-m-d')); + $q->orWhere('targetdate', '>=', $today->format('Y-m-d 00:00:00')); } ); } )->orWhere( - function ($q) { + function (EloquentBuilder $q) { $today = new Carbon; - $q->where('startdate', '>=', $today->format('Y-m-d')); - $q->where('targetdate', '>=', $today->format('Y-m-d')); + $q->where('startdate', '>=', $today->format('Y-m-d 00:00:00')); + $q->where('targetdate', '>=', $today->format('Y-m-d 00:00:00')); } ); } - ) - ->orderBy('startdate', 'ASC'); - $result = $query->first(['piggybank_repetitions.*']); + )->orderBy('startdate', 'ASC'); + $result = $query->first(['piggy_bank_repetitions.*']); $this->currentRep = $result; \Log::debug('Found relevant rep in currentRelevantRep(): ' . $result->id); @@ -139,9 +96,9 @@ class Piggybank extends Eloquent /** * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function piggybankrepetitions() + public function piggyBankRepetitions() { - return $this->hasMany('PiggybankRepetition'); + return $this->hasMany('PiggyBankRepetition'); } /** @@ -155,9 +112,9 @@ class Piggybank extends Eloquent /** * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function piggybankevents() + public function piggyBankEvents() { - return $this->hasMany('PiggybankEvent'); + return $this->hasMany('PiggyBankEvent'); } /** @@ -167,50 +124,4 @@ class Piggybank extends Eloquent { 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 - * - * @returns \PiggybankRepetition - */ - public function repetitionForDate(Carbon $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'); - $result = $query->first(); - - return $result; - } - - /** - * @return \Illuminate\Database\Eloquent\Relations\HasMany - */ - public function transactions() - { - return $this->hasMany('Transaction'); - } - -} \ No newline at end of file +} diff --git a/app/models/PiggybankEvent.php b/app/models/PiggybankEvent.php index 3ef32f5504..1861c45319 100644 --- a/app/models/PiggybankEvent.php +++ b/app/models/PiggybankEvent.php @@ -9,7 +9,7 @@ class PiggyBankEvent extends Eloquent public static $rules = [ - 'piggybank_id' => 'required|exists:piggybanks,id', + 'piggy_bank_id' => 'required|exists:piggy_banks,id', 'date' => 'required|date', 'amount' => 'required|numeric' ]; @@ -26,9 +26,9 @@ class PiggyBankEvent extends Eloquent /** * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function piggybank() + public function piggyBank() { - return $this->belongsTo('Piggybank'); + return $this->belongsTo('PiggyBank'); } /** @@ -39,4 +39,4 @@ class PiggyBankEvent extends Eloquent return $this->belongsTo('TransactionJournal'); } -} \ No newline at end of file +} diff --git a/app/models/PiggybankRepetition.php b/app/models/PiggybankRepetition.php index 79a6fc06ce..e38eabd4b4 100644 --- a/app/models/PiggybankRepetition.php +++ b/app/models/PiggybankRepetition.php @@ -1,17 +1,17 @@ 'required|exists:piggybanks,id', + 'piggy_bank_id' => 'required|exists:piggy_banks,id', 'targetdate' => 'date', 'startdate' => 'date', 'currentamount' => 'required|numeric']; @@ -24,48 +24,31 @@ class PiggybankRepetition extends Eloquent 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; - $saved = $this->currentamount; - if ($total == 0) { - return 0; - } - $pct = round(($saved / $total) * 100, 1); - - return $pct; - } - /** * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ - public function piggybank() + public function piggyBank() { - return $this->belongsTo('Piggybank'); + return $this->belongsTo('PiggyBank'); } /** - * @param Builder $query + * @param EloquentBuilder $query * @param Carbon $date */ - public function scopeStarts(Builder $query, Carbon $date) + public function scopeStarts(EloquentBuilder $query, Carbon $date) { - $query->where('startdate', $date->format('Y-m-d')); + $query->where('startdate', $date->format('Y-m-d 00:00:00')); } /** - * @param Builder $query + * @param EloquentBuilder $query * @param Carbon $date */ - public function scopeTargets(Builder $query, Carbon $date) + public function scopeTargets(EloquentBuilder $query, Carbon $date) { - $query->where('targetdate', $date->format('Y-m-d')); + $query->where('targetdate', $date->format('Y-m-d 00:00:00')); } -} \ No newline at end of file +} diff --git a/app/models/Preference.php b/app/models/Preference.php index 67df6c44f0..b3e12a7ec6 100644 --- a/app/models/Preference.php +++ b/app/models/Preference.php @@ -1,14 +1,16 @@ 'required|exists:users,id', 'name' => 'required|between:1,255', 'data' => 'required']; + protected $fillable = ['name', 'data', 'user_id']; + protected $rules + = ['user_id' => 'required|exists:users,id', 'name' => 'required|between:1,255', 'data' => 'required']; /** * @param $value @@ -36,4 +38,4 @@ class Preference extends Eloquent return $this->belongsTo('User'); } -} \ No newline at end of file +} diff --git a/app/models/RecurringTransaction.php b/app/models/RecurringTransaction.php deleted file mode 100644 index f939cff382..0000000000 --- a/app/models/RecurringTransaction.php +++ /dev/null @@ -1,121 +0,0 @@ - 'required|exists:users,id', - 'name' => 'required|between:1,255|min:1', - 'match' => 'required', - 'amount_max' => 'required|between:0,65536', - 'amount_min' => 'required|between:0,65536', - 'date' => 'required|date', - 'active' => 'between:0,1', - 'automatch' => 'between:0,1', - 'repeat_freq' => 'required|in:daily,weekly,monthly,quarterly,half-year,yearly', - 'skip' => 'required|between:0,31',]; - protected $fillable = ['user_id', 'name', 'match', 'amount_min', 'amount_max', 'date', 'repeat_freq', 'skip', 'active', 'automatch']; - /** - * @return array - */ - public function getDates() - { - 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 \Illuminate\Database\Eloquent\Relations\HasMany - */ - public function transactionjournals() - { - return $this->hasMany('TransactionJournal'); - } - - - /** - * 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; - if ($this->active == 0) { - return $finalDate; - } - - /* - * $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 $finalDate; - } - - /** - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function user() - { - return $this->belongsTo('User'); - } -} \ No newline at end of file diff --git a/app/models/Reminder.php b/app/models/Reminder.php index b5002501b3..b9c7b326b8 100644 --- a/app/models/Reminder.php +++ b/app/models/Reminder.php @@ -1,8 +1,10 @@ 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); + return $query->where('startdate', $start->format('Y-m-d 00:00:00'))->where('enddate', $end->format('Y-m-d 00:00:00')); } /** @@ -71,4 +55,4 @@ class Reminder extends Eloquent } -} \ No newline at end of file +} diff --git a/app/models/Transaction.php b/app/models/Transaction.php index a6596cdea4..bb5c423bec 100644 --- a/app/models/Transaction.php +++ b/app/models/Transaction.php @@ -1,7 +1,7 @@ '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',]; @@ -27,29 +26,20 @@ class Transaction extends Eloquent return $this->belongsTo('Account'); } - /** - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo - */ - public function piggybank() - { - return $this->belongsTo('Piggybank'); - } - - /** - * @param Builder $query + * @param EloquentBuilder $query * @param Account $account */ - public function scopeAccountIs(Builder $query, Account $account) + public function scopeAccountIs(EloquentBuilder $query, Account $account) { $query->where('transactions.account_id', $account->id); } /** - * @param Builder $query + * @param EloquentBuilder $query * @param Carbon $date */ - public function scopeAfter(Builder $query, Carbon $date) + public function scopeAfter(EloquentBuilder $query, Carbon $date) { if (is_null($this->joinedJournals)) { $query->leftJoin( @@ -61,10 +51,10 @@ class Transaction extends Eloquent } /** - * @param Builder $query + * @param EloquentBuilder $query * @param Carbon $date */ - public function scopeBefore(Builder $query, Carbon $date) + public function scopeBefore(EloquentBuilder $query, Carbon $date) { if (is_null($this->joinedJournals)) { $query->leftJoin( @@ -76,28 +66,28 @@ class Transaction extends Eloquent } /** - * @param Builder $query + * @param EloquentBuilder $query * @param $amount */ - public function scopeLessThan(Builder $query, $amount) + public function scopeLessThan(EloquentBuilder $query, $amount) { $query->where('amount', '<', $amount); } /** - * @param Builder $query + * @param EloquentBuilder $query * @param $amount */ - public function scopeMoreThan(Builder $query, $amount) + public function scopeMoreThan(EloquentBuilder $query, $amount) { $query->where('amount', '>', $amount); } /** - * @param Builder $query + * @param EloquentBuilder $query * @param array $types */ - public function scopeTransactionTypes(Builder $query, array $types) + public function scopeTransactionTypes(EloquentBuilder $query, array $types) { if (is_null($this->joinedJournals)) { $query->leftJoin( @@ -121,4 +111,4 @@ class Transaction extends Eloquent { return $this->belongsTo('TransactionJournal'); } -} \ No newline at end of file +} diff --git a/app/models/TransactionCurrency.php b/app/models/TransactionCurrency.php index 8f55b14be6..a72d8168df 100644 --- a/app/models/TransactionCurrency.php +++ b/app/models/TransactionCurrency.php @@ -26,4 +26,4 @@ class TransactionCurrency extends Eloquent return $this->hasMany('TransactionJournal'); } -} \ No newline at end of file +} diff --git a/app/models/TransactionGroup.php b/app/models/TransactionGroup.php index 6e35577046..dea100af17 100644 --- a/app/models/TransactionGroup.php +++ b/app/models/TransactionGroup.php @@ -42,4 +42,4 @@ class TransactionGroup extends Eloquent } -} \ No newline at end of file +} diff --git a/app/models/TransactionJournal.php b/app/models/TransactionJournal.php index 60183f51f7..48b25b2ece 100644 --- a/app/models/TransactionJournal.php +++ b/app/models/TransactionJournal.php @@ -1,10 +1,11 @@ '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']; - protected $fillable - = ['transaction_type_id', 'transaction_currency_id', 'user_id', - 'description', 'date', 'completed']; + + /** + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function bill() + { + return $this->belongsTo('Bill'); + } /** * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany @@ -29,7 +38,7 @@ class TransactionJournal extends Eloquent public function budgets() { return $this->belongsToMany( - 'Budget', 'budget_transaction_journal', 'transaction_journal_id', 'budget_id' + 'Budget' ); } @@ -39,14 +48,11 @@ class TransactionJournal extends Eloquent public function categories() { return $this->belongsToMany( - 'Category', 'category_transaction_journal', 'transaction_journal_id', 'category_id' + 'Category' ); } - /** - * TODO remove this method in favour of something in the FireflyIII libraries. - * * @param Account $account * * @return float @@ -62,8 +68,6 @@ class TransactionJournal extends Eloquent return floatval($t->amount); } } - - return -0.01; } /** @@ -77,24 +81,16 @@ class TransactionJournal extends Eloquent /** * @return \Illuminate\Database\Eloquent\Relations\HasMany */ - public function piggybankevents() + public function piggyBankEvents() { - return $this->hasMany('PiggybankEvent'); + return $this->hasMany('PiggyBankEvent'); } /** - * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + * @param EloquentBuilder $query + * @param Account $account */ - public function recurringTransaction() - { - return $this->belongsTo('RecurringTransaction'); - } - - /** - * @param Builder $query - * @param Account $account - */ - public function scopeAccountIs(Builder $query, \Account $account) + public function scopeAccountIs(EloquentBuilder $query, \Account $account) { if (!isset($this->joinedTransactions)) { $query->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'); @@ -104,40 +100,32 @@ class TransactionJournal extends Eloquent } /** - * @param $query - * @param Carbon $date + * @param EloquentBuilder $query + * @param Carbon $date * * @return mixed */ - public function scopeAfter($query, Carbon $date) + public function scopeAfter(EloquentBuilder $query, Carbon $date) { - return $query->where('date', '>=', $date->format('Y-m-d')); + return $query->where('transaction_journals.date', '>=', $date->format('Y-m-d 00:00:00')); } /** - * @param $query - * @param Carbon $date + * @param EloquentBuilder $query + * @param Carbon $date * * @return mixed */ - public function scopeBefore($query, Carbon $date) + public function scopeBefore(EloquentBuilder $query, Carbon $date) { - return $query->where('date', '<=', $date->format('Y-m-d')); + return $query->where('transaction_journals.date', '<=', $date->format('Y-m-d 00:00:00')); } /** - * @param Builder $query + * @param EloquentBuilder $query + * @param $amount */ - public function scopeDefaultSorting(Builder $query) - { - $query->orderBy('date', 'DESC')->orderBy('transaction_journals.id', 'DESC'); - } - - /** - * @param Builder $query - * @param $amount - */ - public function scopeLessThan(Builder $query, $amount) + public function scopeLessThan(EloquentBuilder $query, $amount) { if (is_null($this->joinedTransactions)) { $query->leftJoin( @@ -150,10 +138,10 @@ class TransactionJournal extends Eloquent } /** - * @param Builder $query - * @param $amount + * @param EloquentBuilder $query + * @param $amount */ - public function scopeMoreThan(Builder $query, $amount) + public function scopeMoreThan(EloquentBuilder $query, $amount) { if (is_null($this->joinedTransactions)) { $query->leftJoin( @@ -166,21 +154,21 @@ class TransactionJournal extends Eloquent } /** - * @param $query - * @param Carbon $date + * @param EloquentBuilder $query + * @param Carbon $date * * @return mixed */ - public function scopeOnDate($query, Carbon $date) + public function scopeOnDate(EloquentBuilder $query, Carbon $date) { return $query->where('date', '=', $date->format('Y-m-d')); } /** - * @param Builder $query - * @param array $types + * @param EloquentBuilder $query + * @param array $types */ - public function scopeTransactionTypes(Builder $query, array $types) + public function scopeTransactionTypes(EloquentBuilder $query, array $types) { if (is_null($this->joinedTransactionTypes)) { $query->leftJoin( @@ -195,14 +183,14 @@ class TransactionJournal extends Eloquent * Automatically includes the 'with' parameters to get relevant related * objects. * - * @param $query + * @param EloquentBuilder $query */ - public function scopeWithRelevantData(Builder $query) + public function scopeWithRelevantData(EloquentBuilder $query) { $query->with( - ['transactions' => function ($q) { + ['transactions' => function (HasMany $q) { $q->orderBy('amount', 'ASC'); - }, 'transactiontype', 'budgets','categories', 'transactions.account.accounttype', 'recurringTransaction', 'budgets', 'categories'] + }, 'transactiontype', 'budgets', 'categories', 'transactions.account.accounttype', 'bill', 'budgets', 'categories'] ); } @@ -248,4 +236,4 @@ class TransactionJournal extends Eloquent return $this->belongsTo('User'); } -} \ No newline at end of file +} diff --git a/app/models/TransactionRelation.php b/app/models/TransactionRelation.php index b9f93873b3..cd34f354e9 100644 --- a/app/models/TransactionRelation.php +++ b/app/models/TransactionRelation.php @@ -7,4 +7,4 @@ use \Illuminate\Database\Eloquent\Model as Eloquent; class TransactionRelation extends Eloquent { -} \ No newline at end of file +} diff --git a/app/models/TransactionType.php b/app/models/TransactionType.php index 9cd87fb280..3e17b3c407 100644 --- a/app/models/TransactionType.php +++ b/app/models/TransactionType.php @@ -19,4 +19,4 @@ class TransactionType extends Eloquent return $this->hasMany('TransactionJournal'); } -} \ No newline at end of file +} diff --git a/app/models/User.php b/app/models/User.php index cef29d346c..a3dc1a47ce 100644 --- a/app/models/User.php +++ b/app/models/User.php @@ -4,8 +4,8 @@ use Illuminate\Auth\Reminders\RemindableInterface; use Illuminate\Auth\Reminders\RemindableTrait; use Illuminate\Auth\UserInterface; use Illuminate\Auth\UserTrait; +use Illuminate\Database\Eloquent\Model as Eloquent; use Watson\Validating\ValidatingTrait; -use \Illuminate\Database\Eloquent\Model as Eloquent; /** * Class User @@ -16,14 +16,14 @@ class User extends Eloquent implements UserInterface, RemindableInterface use UserTrait, RemindableTrait, ValidatingTrait; - public static $rules - = [ + protected $fillable = ['email']; + protected $hidden = ['remember_token']; + protected $rules + = [ 'email' => 'required|email|unique:users,email', 'password' => 'required|between:60,60', 'reset' => 'between:32,32', ]; - protected $fillable = ['email']; - protected $hidden = ['remember_token']; protected $table = 'users'; /** @@ -34,6 +34,14 @@ class User extends Eloquent implements UserInterface, RemindableInterface return $this->hasMany('Account'); } + /** + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function bills() + { + return $this->hasMany('Bill'); + } + /** * @return \Illuminate\Database\Eloquent\Relations\HasMany */ @@ -53,9 +61,9 @@ class User extends Eloquent implements UserInterface, RemindableInterface /** * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough */ - public function piggybanks() + public function piggyBanks() { - return $this->hasManyThrough('Piggybank', 'Account'); + return $this->hasManyThrough('PiggyBank', 'Account'); } /** @@ -66,14 +74,6 @@ class User extends Eloquent implements UserInterface, RemindableInterface return $this->hasMany('Preference'); } - /** - * @return \Illuminate\Database\Eloquent\Relations\HasMany - */ - public function recurringtransactions() - { - return $this->hasMany('RecurringTransaction'); - } - /** * @return \Illuminate\Database\Eloquent\Relations\HasMany */ @@ -98,12 +98,5 @@ class User extends Eloquent implements UserInterface, RemindableInterface return $this->hasMany('TransactionJournal'); } - /** - * @return \Illuminate\Database\Eloquent\Relations\HasManyThrough - */ - 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 463bd66dd2..9513bb3e20 100644 --- a/app/routes.php +++ b/app/routes.php @@ -1,13 +1,16 @@ where('account_types.editable', 1)->where('accounts.id', $value) - ->where('user_id', Auth::user()->id)->first(['accounts.*']); + leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') + ->where('account_types.editable', 1) + ->where('accounts.id', $value) + ->where('user_id', Auth::user()->id) + ->first(['accounts.*']); if ($account) { return $account; } @@ -31,9 +34,9 @@ Route::bind( Route::bind( - 'recurring', function ($value, $route) { + 'bill', function ($value, $route) { if (Auth::check()) { - return RecurringTransaction:: + return Bill:: where('id', $value)->where('user_id', Auth::user()->id)->first(); } @@ -94,6 +97,16 @@ Route::bind( return null; } ); +Route::bind( + 'tjSecond', function ($value, $route) { + if (Auth::check()) { + return TransactionJournal:: + where('id', $value)->where('user_id', Auth::user()->id)->first(); + } + + return null; +} +); Route::bind( 'currency', function ($value, $route) { @@ -116,13 +129,27 @@ Route::bind( ); Route::bind( - 'piggybank', function ($value, $route) { + 'piggyBank', function ($value, $route) { if (Auth::check()) { - return Piggybank:: - where('piggybanks.id', $value) - ->leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id') + return PiggyBank:: + where('piggy_banks.id', $value) + ->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') ->where('accounts.user_id', Auth::user()->id) - ->where('repeats', 0)->first(['piggybanks.*']); + ->where('repeats', 0)->first(['piggy_banks.*']); + } + + return null; +} +); + +Route::bind( + 'repeatedExpense', function ($value, $route) { + if (Auth::check()) { + return PiggyBank:: + where('piggy_banks.id', $value) + ->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') + ->where('accounts.user_id', Auth::user()->id) + ->where('repeats', 1)->first(['piggy_banks.*']); } return null; @@ -132,11 +159,11 @@ Route::bind( Route::bind( 'repeated', function ($value, $route) { if (Auth::check()) { - return Piggybank:: - where('piggybanks.id', $value) - ->leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id') + return PiggyBank:: + where('piggy_banks.id', $value) + ->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') ->where('accounts.user_id', Auth::user()->id) - ->where('repeats', 1)->first(['piggybanks.*']); + ->where('repeats', 1)->first(['piggy_banks.*']); } return null; @@ -150,7 +177,6 @@ Route::group( // some date routes used for (well duh) date-based navigation. Route::get('/prev', ['uses' => 'HomeController@sessionPrev', 'as' => 'sessionPrev']); - //Route::get('/repair', ['uses' => 'HomeController@repair']); Route::get('/next', ['uses' => 'HomeController@sessionNext', 'as' => 'sessionNext']); Route::get('/jump/{range}', ['uses' => 'HomeController@rangeJump', 'as' => 'rangeJump']); @@ -189,13 +215,13 @@ Route::group( 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/home/bills', ['uses' => 'GoogleChartController@billsOverview']); Route::get('/chart/account/{account}/{view?}', ['uses' => 'GoogleChartController@accountBalanceChart']); 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/bills/{bill}', ['uses' => 'GoogleChartController@billOverview']); Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'GoogleChartController@budgetLimitSpending']); - Route::get('/chart/piggyhistory/{piggybank}', ['uses' => 'GoogleChartController@piggyBankHistory']); + Route::get('/chart/piggy_history/{piggyBank}', ['uses' => 'GoogleChartController@piggyBankHistory']); // google chart for components (categories + budgets combined) Route::get('/chart/budget/{budget}/spending/{year}', ['uses' => 'GoogleChartController@budgetsAndSpending']); @@ -215,14 +241,14 @@ Route::group( // piggy bank controller - Route::get('/piggybanks', ['uses' => 'PiggybankController@index', 'as' => 'piggybanks.index']); - Route::get('/piggybanks/add/{piggybank}', ['uses' => 'PiggybankController@add']); # add money - Route::get('/piggybanks/remove/{piggybank}', ['uses' => 'PiggybankController@remove']); #remove money + Route::get('/piggy_banks', ['uses' => 'PiggyBankController@index', 'as' => 'piggy_banks.index']); + Route::get('/piggy_banks/add/{piggyBank}', ['uses' => 'PiggyBankController@add']); # add money + Route::get('/piggy_banks/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('/piggybanks/show/{piggybank}', ['uses' => 'PiggybankController@show', 'as' => 'piggybanks.show']); + Route::get('/piggy_banks/create', ['uses' => 'PiggyBankController@create', 'as' => 'piggy_banks.create']); + Route::get('/piggy_banks/edit/{piggyBank}', ['uses' => 'PiggyBankController@edit', 'as' => 'piggy_banks.edit']); + Route::get('/piggy_banks/delete/{piggyBank}', ['uses' => 'PiggyBankController@delete', 'as' => 'piggy_banks.delete']); + Route::get('/piggy_banks/show/{piggyBank}', ['uses' => 'PiggyBankController@show', 'as' => 'piggy_banks.show']); // preferences controller Route::get('/preferences', ['uses' => 'PreferencesController@index', 'as' => 'preferences']); @@ -231,28 +257,38 @@ Route::group( Route::get('/profile', ['uses' => 'ProfileController@index', 'as' => 'profile']); Route::get('/profile/change-password', ['uses' => 'ProfileController@changePassword', 'as' => 'change-password']); - // recurring transactions controller - Route::get('/recurring', ['uses' => 'RecurringController@index', 'as' => 'recurring.index']); - 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']); + // related controller: + Route::get('/related/alreadyRelated/{tj}', ['uses' => 'RelatedController@alreadyRelated','as' => 'related.alreadyRelated']); + Route::post('/related/relate/{tj}/{tjSecond}', ['uses' => 'RelatedController@relate','as' => 'related.relate']); + Route::get('/related/removeRelation/{tj}/{tjSecond}', ['uses' => 'RelatedController@removeRelation','as' => 'related.removeRelation']); + Route::get('/related/related/{tj}', ['uses' => 'RelatedController@related','as' => 'related.related']); + Route::post('/related/search/{tj}', ['uses' => 'RelatedController@search','as' => 'related.search']); + + // bills controller + Route::get('/bills', ['uses' => 'BillController@index', 'as' => 'bills.index']); + Route::get('/bills/rescan/{bill}', ['uses' => 'BillController@rescan', 'as' => 'bills.rescan']); # rescan for matching. + Route::get('/bills/create', ['uses' => 'BillController@create', 'as' => 'bills.create']); + Route::get('/bills/edit/{bill}', ['uses' => 'BillController@edit', 'as' => 'bills.edit']); + Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']); + Route::get('/bills/show/{bill}', ['uses' => 'BillController@show', 'as' => 'bills.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']); + Route::get('/repeatedexpenses/edit/{repeatedExpense}', ['uses' => 'RepeatedExpenseController@edit', 'as' => 'repeated.edit']); + Route::get('/repeatedexpenses/delete/{repeatedExpense}', ['uses' => 'RepeatedExpenseController@delete', 'as' => 'repeated.delete']); + Route::get('/repeatedexpenses/show/{repeatedExpense}', ['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/unbalanced/{year}/{month}', ['uses' => 'ReportController@unbalanced', 'as' => 'reports.unbalanced']); + Route::get('/reports/{year}/{month}', ['uses' => 'ReportController@month', 'as' => 'reports.month']); + Route::get('/reports/budget/{year}/{month}', ['uses' => 'ReportController@budget', 'as' => 'reports.budget']); // 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}/notNow', ['uses' => 'ReminderController@notNow', 'as' => 'reminders.notNow']); Route::get('/reminders/{reminder}/act', ['uses' => 'ReminderController@act', 'as' => 'reminders.act']); // search controller: @@ -308,14 +344,16 @@ Route::group( Route::post('/currency/destroy/{currency}', ['uses' => 'CurrencyController@destroy', 'as' => 'currency.destroy']); // piggy bank controller - Route::post('/piggybanks/store', ['uses' => 'PiggybankController@store', 'as' => 'piggybanks.store']); - 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/add/{piggybank}', ['uses' => 'PiggybankController@postAdd', 'as' => 'piggybanks.add']); # add money - Route::post('/piggybanks/remove/{piggybank}', ['uses' => 'PiggybankController@postRemove', 'as' => 'piggybanks.remove']); # remove money. + Route::post('/piggy_banks/store', ['uses' => 'PiggyBankController@store', 'as' => 'piggy_banks.store']); + Route::post('/piggy_banks/update/{piggyBank}', ['uses' => 'PiggyBankController@update', 'as' => 'piggy_banks.update']); + Route::post('/piggy_banks/destroy/{piggyBank}', ['uses' => 'PiggyBankController@destroy', 'as' => 'piggy_banks.destroy']); + Route::post('/piggy_banks/add/{piggyBank}', ['uses' => 'PiggyBankController@postAdd', 'as' => 'piggy_banks.add']); # add money + Route::post('/piggy_banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@postRemove', 'as' => 'piggy_banks.remove']); # remove money. // repeated expense controller Route::post('/repeatedexpense/store', ['uses' => 'RepeatedExpenseController@store', 'as' => 'repeated.store']); + Route::post('/repeatedexpense/update/{repeatedExpense}', ['uses' => 'RepeatedExpenseController@update', 'as' => 'repeated.update']); + Route::post('/repeatedexpense/destroy/{repeatedExpense}', ['uses' => 'RepeatedExpenseController@destroy', 'as' => 'repeated.destroy']); // preferences controller Route::post('/preferences', ['uses' => 'PreferencesController@postIndex']); @@ -323,10 +361,10 @@ Route::group( // profile controller Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword']); - // recurring controller - Route::post('/recurring/store', ['uses' => 'RecurringController@store', 'as' => 'recurring.store']); - Route::post('/recurring/update/{recurring}', ['uses' => 'RecurringController@update', 'as' => 'recurring.update']); - Route::post('/recurring/destroy/{recurring}', ['uses' => 'RecurringController@destroy', 'as' => 'recurring.destroy']); + // bills controller + Route::post('/bills/store', ['uses' => 'BillController@store', 'as' => 'bills.store']); + Route::post('/bills/update/{bill}', ['uses' => 'BillController@update', 'as' => 'bills.update']); + Route::post('/bills/destroy/{bill}', ['uses' => 'BillController@destroy', 'as' => 'bills.destroy']); // transaction controller: Route::post('/transactions/store/{what}', ['uses' => 'TransactionController@store', 'as' => 'transactions.store'])->where( @@ -343,9 +381,9 @@ Route::group( ['before' => 'guest'], function () { // user controller Route::get('/login', ['uses' => 'UserController@login', 'as' => 'login']); - Route::get('/register', ['uses' => 'UserController@register', 'as' => 'register']); + Route::get('/register', ['uses' => 'UserController@register', 'as' => 'register','before' => 'allow-register']); Route::get('/reset/{reset}', ['uses' => 'UserController@reset', 'as' => 'reset']); - Route::get('/remindme', ['uses' => 'UserController@remindme', 'as' => 'remindme']); + Route::get('/remindMe', ['uses' => 'UserController@remindMe', 'as' => 'remindMe']); } @@ -357,7 +395,7 @@ Route::group( // user controller Route::post('/login', ['uses' => 'UserController@postLogin', 'as' => 'login.post']); - Route::post('/register', ['uses' => 'UserController@postRegister', 'as' => 'register.post']); - Route::post('/remindme', ['uses' => 'UserController@postRemindme', 'as' => 'remindme.post']); + Route::post('/register', ['uses' => 'UserController@postRegister', 'as' => 'register.post','before' => 'allow-register']); + Route::post('/remindMe', ['uses' => 'UserController@postRemindMe', 'as' => 'remindMe.post']); } -); \ No newline at end of file +); diff --git a/app/start/artisan.php b/app/start/artisan.php index 3b223f16ec..8e36314924 100644 --- a/app/start/artisan.php +++ b/app/start/artisan.php @@ -11,4 +11,4 @@ | */ -Artisan::add(new Cleanup); \ No newline at end of file +Artisan::add(new Cleanup); diff --git a/app/start/global.php b/app/start/global.php index 36f6db85a9..cbe2ca8b88 100644 --- a/app/start/global.php +++ b/app/start/global.php @@ -68,7 +68,7 @@ App::down( } ); -// forms: +// forms \Form::macro( 'ffText', function ($name, $value = null, array $options = []) { return \FireflyIII\Form\Form::ffText($name, $value, $options); diff --git a/app/start/local.php b/app/start/local.php index 3d14850913..3d9949b800 100644 --- a/app/start/local.php +++ b/app/start/local.php @@ -1,3 +1,3 @@ object = new PiggybankPart; - } - - /** - * Tears down the fixture, for example, closes a network connection. - * This method is called after a test is executed. - */ - protected function tearDown() - { - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::getReminder - * @todo Implement testGetReminder(). - */ - public function testGetReminder() - { - $this->object->getReminder(); - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::setReminder - * @todo Implement testSetReminder(). - */ - public function testSetReminder() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::getStartdate - * @todo Implement testGetStartdate(). - */ - public function testGetStartdate() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::setStartdate - * @todo Implement testSetStartdate(). - */ - public function testSetStartdate() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::getTargetdate - * @todo Implement testGetTargetdate(). - */ - public function testGetTargetdate() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::setTargetdate - * @todo Implement testSetTargetdate(). - */ - public function testSetTargetdate() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::getRepetition - * @todo Implement testGetRepetition(). - */ - public function testGetRepetition() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::setRepetition - * @todo Implement testSetRepetition(). - */ - public function testSetRepetition() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::hasReminder - * @todo Implement testHasReminder(). - */ - public function testHasReminder() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::percentage - * @todo Implement testPercentage(). - */ - public function testPercentage() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::getCurrentamount - * @todo Implement testGetCurrentamount(). - */ - public function testGetCurrentamount() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::setCurrentamount - * @todo Implement testSetCurrentamount(). - */ - public function testSetCurrentamount() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::getCumulativeAmount - * @todo Implement testGetCumulativeAmount(). - */ - public function testGetCumulativeAmount() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::setCumulativeAmount - * @todo Implement testSetCumulativeAmount(). - */ - public function testSetCumulativeAmount() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::getAmountPerBar - * @todo Implement testGetAmountPerBar(). - */ - public function testGetAmountPerBar() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } - - /** - * @covers FireflyIII\Collection\PiggybankPart::setAmountPerBar - * @todo Implement testSetAmountPerBar(). - */ - public function testSetAmountPerBar() - { - // Remove the following lines when you implement this test. - $this->markTestIncomplete( - 'This test has not been implemented yet.' - ); - } -} diff --git a/app/tests/TestCase.php b/app/tests/TestCase.php index e3ce3bcc0d..e2e0cce790 100644 --- a/app/tests/TestCase.php +++ b/app/tests/TestCase.php @@ -1,5 +1,7 @@ seed(); + $this->prepareForTests(); - - //$this-> - } - - /** - * @param $class - * - * @return m\MockInterface - */ - public function mock($class) - { - $mock = Mockery::mock($class); - - $this->app->instance($class, $mock); - - return $mock; } static public function setupBeforeClass() { - League\FactoryMuffin\Facade::loadFactories(__DIR__ . '/factories'); + f::loadFactories(__DIR__ . '/factories'); } public function tearDown() { - m::close(); + //m::close(); } -} \ No newline at end of file + + /** + * Migrates the database and set the mailer to 'pretend'. + * This will cause the tests to run quickly. + * + */ + private function prepareForTests() + { + Artisan::call('migrate'); + Mail::pretend(true); + } +} diff --git a/app/tests/factories/Account.php b/app/tests/factories/Account.php new file mode 100644 index 0000000000..3d4032b4d1 --- /dev/null +++ b/app/tests/factories/Account.php @@ -0,0 +1,10 @@ + 'factory|User', + 'account_type_id' => 'factory|AccountType', + 'name' => 'word', + 'active' => 'boolean', + ] +); diff --git a/app/tests/factories/AccountMeta.php b/app/tests/factories/AccountMeta.php new file mode 100644 index 0000000000..a282aa9748 --- /dev/null +++ b/app/tests/factories/AccountMeta.php @@ -0,0 +1,9 @@ + 'factory|Account', + 'name' => 'word', + 'data' => 'text' + ] +); diff --git a/app/tests/factories/AccountType.php b/app/tests/factories/AccountType.php new file mode 100644 index 0000000000..e893ea89af --- /dev/null +++ b/app/tests/factories/AccountType.php @@ -0,0 +1,8 @@ + 'word', + 'editable' => 'boolean' + ] +); diff --git a/app/tests/factories/Budget.php b/app/tests/factories/Budget.php new file mode 100644 index 0000000000..1975cf53b0 --- /dev/null +++ b/app/tests/factories/Budget.php @@ -0,0 +1,8 @@ + 'word', + 'user_id' => 'factory|User' + ] +); diff --git a/app/tests/factories/PiggyBank.php b/app/tests/factories/PiggyBank.php new file mode 100644 index 0000000000..36f89debf8 --- /dev/null +++ b/app/tests/factories/PiggyBank.php @@ -0,0 +1,34 @@ + 'factory|Account', + 'name' => 'word', + 'targetamount' => function () { + return rand(1, 400); + }, + 'startdate' => 'date|Y-m-d', + 'targetdate' => 'date|Y-m-d', + 'repeats' => 'boolean', + 'rep_length' => function () { + $set = ['day', 'week', 'quarter', 'month', 'year']; + + return $set[rand(0, count($set) - 1)]; + }, + 'rep_every' => function() {return rand(0,3);}, + 'rep_times' => function() {return rand(0,3);}, + 'reminder' => function () { + $set = ['day', 'week', 'quarter', 'month', 'year']; + + return $set[rand(0, count($set) - 1)]; + }, + 'reminder_skip' => function () { + return rand(0, 3); + }, + 'remind_me' => 'boolean', + 'order' => function () { + return rand(0, 10); + }, + + ] +); diff --git a/app/tests/factories/PiggyBankRepetition.php b/app/tests/factories/PiggyBankRepetition.php new file mode 100644 index 0000000000..a266af2283 --- /dev/null +++ b/app/tests/factories/PiggyBankRepetition.php @@ -0,0 +1,13 @@ + 'factory|PiggyBank', + 'startdate' => 'date|Y-m-d', + 'targetdate' => 'date|Y-m-d', + 'currentamount' => function () { + return rand(0, 100); + }, + + ] +); diff --git a/app/tests/factories/Preference.php b/app/tests/factories/Preference.php new file mode 100644 index 0000000000..89a26f5812 --- /dev/null +++ b/app/tests/factories/Preference.php @@ -0,0 +1,9 @@ + 'factory|User', + 'name' => 'word', + 'data' => 'sentence', + ] +); diff --git a/app/tests/factories/Reminder.php b/app/tests/factories/Reminder.php new file mode 100644 index 0000000000..62f2a3d513 --- /dev/null +++ b/app/tests/factories/Reminder.php @@ -0,0 +1,13 @@ + 'factory|User', + 'startdate' => 'date|Y-m-d', + 'enddate' => 'date|Y-m-d', + 'active' => 'boolean', + 'notnow' => 'boolean', + 'remindersable_id' => 0, + 'remindersable_type' => '', + ] +); diff --git a/app/tests/factories/Transaction.php b/app/tests/factories/Transaction.php new file mode 100644 index 0000000000..9f812b8ce0 --- /dev/null +++ b/app/tests/factories/Transaction.php @@ -0,0 +1,12 @@ + 'factory|Account', + 'transaction_journal_id' => 'factory|TransactionJournal', + 'description' => 'sentence', + 'amount' => function() { + return round(rand(100,10000) / 100,2); + } + ] +); diff --git a/app/tests/factories/TransactionCurrency.php b/app/tests/factories/TransactionCurrency.php index 9804dd56c2..cfb3b685b0 100644 --- a/app/tests/factories/TransactionCurrency.php +++ b/app/tests/factories/TransactionCurrency.php @@ -2,6 +2,29 @@ League\FactoryMuffin\Facade::define( 'TransactionCurrency', [ - 'code' => 'word', - ] + 'code' => function () { + $code = ''; + for ($i = 0; $i < 3; $i++) { + $code .= chr(rand(65, 90)); + } + + return $code; + }, + 'name' => function () { + $code = ''; + for ($i = 0; $i < 8; $i++) { + $code .= chr(rand(65, 90)); + } + + return $code; + }, + 'symbol' => function () { + $code = ''; + for ($i = 0; $i < 2; $i++) { + $code .= chr(rand(65, 90)); + } + + return $code; + } + ] ); diff --git a/app/tests/factories/TransactionGroup.php b/app/tests/factories/TransactionGroup.php new file mode 100644 index 0000000000..74e917a8ae --- /dev/null +++ b/app/tests/factories/TransactionGroup.php @@ -0,0 +1,8 @@ + 'factory|User', + 'relation' => 'balance', + ] +); diff --git a/app/views/accounts/create.blade.php b/app/views/accounts/create.blade.php index d3a9e376d2..8fc3f78c5a 100644 --- a/app/views/accounts/create.blade.php +++ b/app/views/accounts/create.blade.php @@ -52,4 +52,4 @@
{{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/accounts/delete.blade.php b/app/views/accounts/delete.blade.php index 0f60d5298d..017224a1fd 100644 --- a/app/views/accounts/delete.blade.php +++ b/app/views/accounts/delete.blade.php @@ -30,4 +30,4 @@ {{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/accounts/edit.blade.php b/app/views/accounts/edit.blade.php index cfa7c3357a..547068fae8 100644 --- a/app/views/accounts/edit.blade.php +++ b/app/views/accounts/edit.blade.php @@ -47,4 +47,4 @@ {{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/accounts/index.blade.php b/app/views/accounts/index.blade.php index 5c2416ab00..e837940541 100644 --- a/app/views/accounts/index.blade.php +++ b/app/views/accounts/index.blade.php @@ -30,7 +30,7 @@ @section('scripts') @@ -40,4 +40,4 @@ {{HTML::script('assets/javascript/firefly/accounts.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/accounts/show.blade.php b/app/views/accounts/show.blade.php index b7da493119..e5b4fc9e04 100644 --- a/app/views/accounts/show.blade.php +++ b/app/views/accounts/show.blade.php @@ -52,11 +52,11 @@ {{HTML::script('assets/javascript/firefly/gcharts.options.js')}} {{HTML::script('assets/javascript/firefly/gcharts.js')}} {{HTML::script('assets/javascript/firefly/accounts.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/recurring/create.blade.php b/app/views/bills/create.blade.php similarity index 88% rename from app/views/recurring/create.blade.php rename to app/views/bills/create.blade.php index ef42865842..f2ddc3b828 100644 --- a/app/views/recurring/create.blade.php +++ b/app/views/bills/create.blade.php @@ -1,7 +1,7 @@ @extends('layouts.default') @section('content') {{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) }} -{{Form::open(['class' => 'form-horizontal','url' => route('recurring.store')])}} +{{Form::open(['class' => 'form-horizontal','id' => 'store','url' => route('bills.store')])}}
@@ -21,7 +21,7 @@

@@ -44,7 +44,7 @@ Options
- {{Form::ffOptionsList('create','recurring transaction')}} + {{Form::ffOptionsList('create','bill')}}
@@ -61,4 +61,4 @@ @section('scripts') {{HTML::script('assets/javascript/tagsinput/bootstrap-tagsinput.min.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/piggybanks/delete.blade.php b/app/views/bills/delete.blade.php similarity index 87% rename from app/views/piggybanks/delete.blade.php rename to app/views/bills/delete.blade.php index 0e37e8d585..801db34b94 100644 --- a/app/views/piggybanks/delete.blade.php +++ b/app/views/bills/delete.blade.php @@ -1,12 +1,12 @@ @extends('layouts.default') @section('content') -{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $piggybank) }} -{{Form::open(['class' => 'form-horizontal','id' => 'destroy','url' => route('piggybanks.destroy',$piggybank->id)])}} +{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $bill) }} +{{Form::open(['class' => 'form-horizontal','id' => 'destroy','url' => route('bills.destroy',$bill->id)])}}
- Delete piggy bank "{{{$piggybank->name}}}" + Delete bill "{{{$bill->name}}}"

@@ -34,4 +34,4 @@ {{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/recurring/edit.blade.php b/app/views/bills/edit.blade.php similarity index 81% rename from app/views/recurring/edit.blade.php rename to app/views/bills/edit.blade.php index d7bf99bc25..e68d445918 100644 --- a/app/views/recurring/edit.blade.php +++ b/app/views/bills/edit.blade.php @@ -1,7 +1,7 @@ @extends('layouts.default') @section('content') -{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $recurringTransaction) }} -{{Form::model($recurringTransaction, ['class' => 'form-horizontal','url' => route('recurring.update', $recurringTransaction->id)])}} +{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $bill) }} +{{Form::model($bill, ['class' => 'form-horizontal','id' => 'update','url' => route('bills.update', $bill->id)])}}

@@ -15,14 +15,14 @@ {{Form::ffTags('match')}} {{Form::ffAmount('amount_min')}} {{Form::ffAmount('amount_max')}} - {{Form::ffDate('date',$recurringTransaction->date->format('Y-m-d'))}} + {{Form::ffDate('date',$bill->date->format('Y-m-d'))}} {{Form::ffSelect('repeat_freq',$periods)}}

@@ -44,7 +44,7 @@ Options
- {{Form::ffOptionsList('update','recurring transaction')}} + {{Form::ffOptionsList('update','bill')}}
@@ -59,4 +59,4 @@ @stop @section('scripts') {{HTML::script('assets/javascript/tagsinput/bootstrap-tagsinput.min.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/recurring/index.blade.php b/app/views/bills/index.blade.php similarity index 84% rename from app/views/recurring/index.blade.php rename to app/views/bills/index.blade.php index ac615b33b8..c9319ac213 100644 --- a/app/views/recurring/index.blade.php +++ b/app/views/bills/index.blade.php @@ -6,10 +6,9 @@
{{{$title}}} -
- @include('list.recurring') + @include('list.bills')
@@ -17,4 +16,4 @@ @stop @section('scripts') -@stop \ No newline at end of file +@stop diff --git a/app/views/recurring/show.blade.php b/app/views/bills/show.blade.php similarity index 71% rename from app/views/recurring/show.blade.php rename to app/views/bills/show.blade.php index b877599d47..6437e6fdcb 100644 --- a/app/views/recurring/show.blade.php +++ b/app/views/bills/show.blade.php @@ -1,19 +1,19 @@ @extends('layouts.default') @section('content') -{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $recurring) }} +{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $bill) }}
- {{{$recurring->name}}} + {{{$bill->name}}} - @if($recurring->active) + @if($bill->active) @else @endif - @if($recurring->automatch) + @if($bill->automatch) @else @@ -27,8 +27,8 @@
@@ -39,19 +39,18 @@ Matching on - @foreach(explode(',',$recurring->match) as $word) + @foreach(explode(',',$bill->match) as $word) {{{$word}}} @endforeach - between {{mf($recurring->amount_min)}} and {{mf($recurring->amount_max)}}. - Repeats {{$recurring->repeat_freq}}. + between {{Amount::format($bill->amount_min)}} and {{Amount::format($bill->amount_max)}}. + Repeats {{$bill->repeat_freq}}. Next expected match - nextExpectedMatch();?> - @if($nextExpectedMatch) - {{$nextExpectedMatch->format('j F Y')}} + @if($bill->nextExpectedMatch) + {{$bill->nextExpectedMatch->format('j F Y')}} @else Unknown @endif @@ -68,7 +67,7 @@

- Rescan old transactions + Rescan old transactions

@@ -82,7 +81,7 @@ Chart
-
+
@@ -105,13 +104,13 @@ @section('scripts') {{HTML::script('assets/javascript/firefly/gcharts.options.js')}} {{HTML::script('assets/javascript/firefly/gcharts.js')}} -{{HTML::script('assets/javascript/firefly/recurring.js')}} -@stop \ No newline at end of file +{{HTML::script('assets/javascript/firefly/bills.js')}} +@stop diff --git a/app/views/budgets/delete.blade.php b/app/views/budgets/delete.blade.php index fde512aa42..1e8a1a68d7 100644 --- a/app/views/budgets/delete.blade.php +++ b/app/views/budgets/delete.blade.php @@ -34,4 +34,4 @@ {{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/budgets/income.blade.php b/app/views/budgets/income.blade.php index 803b2ce8d5..713c61a20c 100644 --- a/app/views/budgets/income.blade.php +++ b/app/views/budgets/income.blade.php @@ -18,4 +18,4 @@ - \ No newline at end of file + diff --git a/app/views/budgets/index.blade.php b/app/views/budgets/index.blade.php index 60aa1d4d03..2b5f62be48 100644 --- a/app/views/budgets/index.blade.php +++ b/app/views/budgets/index.blade.php @@ -10,11 +10,11 @@
- Budgeted: {{mf(300)}} + Budgeted: {{Amount::format(300)}}
Income {{\Session::get('start', \Carbon\Carbon::now()->startOfMonth())->format('F Y')}}: - {{mf($amount)}} + {{Amount::format($amount)}}
@@ -29,7 +29,7 @@
- Spent: {{mf($spent)}} + Spent: {{Amount::format($spent)}}
@@ -100,21 +100,21 @@ @if($budget->currentRep->amount > $budget->spent) - {{getCurrencySymbol()}} + {{Amount::getCurrencySymbol()}} @else - {{getCurrencySymbol()}} + {{Amount::getCurrencySymbol()}} @endif @else No budget - + @endif

- Spent: {{mf($budget->spent)}} + Spent: {{Amount::format($budget->spent)}}

@@ -139,4 +139,4 @@ @stop @section('scripts') {{HTML::script('assets/javascript/firefly/budgets.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/budgets/show.blade.php b/app/views/budgets/show.blade.php index 7228e03054..b6c35c646d 100644 --- a/app/views/budgets/show.blade.php +++ b/app/views/budgets/show.blade.php @@ -29,10 +29,10 @@
- Amount: {{mf($rep->amount)}} + Amount: {{Amount::format($rep->amount)}}
- Spent: {{mf($rep->spentInRepetition())}} + Spent: {{Amount::format($rep->spentInRepetition())}}
@@ -87,4 +87,4 @@ {{HTML::script('assets/javascript/firefly/gcharts.js')}} {{HTML::script('assets/javascript/firefly/budgets.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/categories/delete.blade.php b/app/views/categories/delete.blade.php index 399e2762fd..52d457b457 100644 --- a/app/views/categories/delete.blade.php +++ b/app/views/categories/delete.blade.php @@ -34,4 +34,4 @@ {{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/categories/edit.blade.php b/app/views/categories/edit.blade.php index 24123a7103..69987b85a6 100644 --- a/app/views/categories/edit.blade.php +++ b/app/views/categories/edit.blade.php @@ -35,4 +35,4 @@
{{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/categories/index.blade.php b/app/views/categories/index.blade.php index 8a0a4034b1..3c176f36b6 100644 --- a/app/views/categories/index.blade.php +++ b/app/views/categories/index.blade.php @@ -29,11 +29,11 @@ @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 +@stop diff --git a/app/views/categories/show.blade.php b/app/views/categories/show.blade.php index a80f0a9bb5..bdfefd3e52 100644 --- a/app/views/categories/show.blade.php +++ b/app/views/categories/show.blade.php @@ -22,7 +22,6 @@
- BLa bla something here.
@@ -32,7 +31,7 @@ @@ -40,4 +39,4 @@ {{HTML::script('assets/javascript/firefly/gcharts.js')}} {{HTML::script('assets/javascript/firefly/categories.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/currency/create.blade.php b/app/views/currency/create.blade.php index 4ce88ea5a0..1cca5bee88 100644 --- a/app/views/currency/create.blade.php +++ b/app/views/currency/create.blade.php @@ -37,4 +37,4 @@ {{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/currency/delete.blade.php b/app/views/currency/delete.blade.php index ea333c6641..8fd0af69aa 100644 --- a/app/views/currency/delete.blade.php +++ b/app/views/currency/delete.blade.php @@ -22,4 +22,4 @@ {{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/currency/edit.blade.php b/app/views/currency/edit.blade.php index f9482210b4..246f9d5c9d 100644 --- a/app/views/currency/edit.blade.php +++ b/app/views/currency/edit.blade.php @@ -37,4 +37,4 @@ {{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/currency/index.blade.php b/app/views/currency/index.blade.php index f7f3a09367..fdbe0e66ea 100644 --- a/app/views/currency/index.blade.php +++ b/app/views/currency/index.blade.php @@ -64,4 +64,4 @@ -@stop \ No newline at end of file +@stop diff --git a/app/views/emails/user/register-html.blade.php b/app/views/emails/user/register-html.blade.php index b130d167a1..e81ca6d95e 100644 --- a/app/views/emails/user/register-html.blade.php +++ b/app/views/emails/user/register-html.blade.php @@ -16,4 +16,4 @@

- \ No newline at end of file + diff --git a/app/views/emails/user/register-text.blade.php b/app/views/emails/user/register-text.blade.php index 7cfa0e4735..0993031a88 100644 --- a/app/views/emails/user/register-text.blade.php +++ b/app/views/emails/user/register-text.blade.php @@ -2,4 +2,4 @@ Hi! Here's the password you need to login at Firefly: {{$password}} -Cya! \ No newline at end of file +Cya! diff --git a/app/views/emails/user/verify-html.blade.php b/app/views/emails/user/verify-html.blade.php index 961b9c79ac..90b477e351 100644 --- a/app/views/emails/user/verify-html.blade.php +++ b/app/views/emails/user/verify-html.blade.php @@ -16,4 +16,4 @@

- \ No newline at end of file + diff --git a/app/views/emails/user/verify-text.blade.php b/app/views/emails/user/verify-text.blade.php index 5b82b79d99..27f1d553a0 100644 --- a/app/views/emails/user/verify-text.blade.php +++ b/app/views/emails/user/verify-text.blade.php @@ -4,4 +4,4 @@ To verify your registration, please verify your e-mail address: {{route('reset',$reset)}} -Cya! \ No newline at end of file +Cya! diff --git a/app/views/error.blade.php b/app/views/error.blade.php index 27aff067df..4140018572 100644 --- a/app/views/error.blade.php +++ b/app/views/error.blade.php @@ -13,4 +13,4 @@ {{$message or 'General unknown errror'}} -@stop \ No newline at end of file +@stop diff --git a/app/views/index.blade.php b/app/views/index.blade.php index 5a90e8ce31..22520f85b5 100644 --- a/app/views/index.blade.php +++ b/app/views/index.blade.php @@ -67,10 +67,10 @@
- Recurring transactions + Bills
-
+
@@ -114,7 +114,7 @@ @stop @section('scripts') @@ -126,4 +126,4 @@ {{HTML::script('assets/javascript/firefly/index.js')}} @stop @section('styles') -@stop \ No newline at end of file +@stop diff --git a/app/views/layouts/default.blade.php b/app/views/layouts/default.blade.php index ffad378639..17595c0643 100644 --- a/app/views/layouts/default.blade.php +++ b/app/views/layouts/default.blade.php @@ -93,4 +93,4 @@ {{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 85966199ce..6b5a7d023b 100644 --- a/app/views/layouts/guest.blade.php +++ b/app/views/layouts/guest.blade.php @@ -27,4 +27,4 @@ @yield('content') - \ No newline at end of file + diff --git a/app/views/list/accounts.blade.php b/app/views/list/accounts.blade.php index b7976d4df3..84f88bdfcc 100644 --- a/app/views/list/accounts.blade.php +++ b/app/views/list/accounts.blade.php @@ -17,7 +17,7 @@ {{{$account->name}}} {{{$account->accountRole}}} - {{mf(Steam::balance($account))}} + {{Amount::format(Steam::balance($account))}} @if($account->active) @@ -35,4 +35,4 @@ @endforeach - \ No newline at end of file + diff --git a/app/views/list/recurring.blade.php b/app/views/list/bills.blade.php similarity index 64% rename from app/views/list/recurring.blade.php rename to app/views/list/bills.blade.php index cab075f3b0..1540af42de 100644 --- a/app/views/list/recurring.blade.php +++ b/app/views/list/bills.blade.php @@ -10,16 +10,16 @@ Will be automatched Repeats every - @foreach($recurring as $entry) + @foreach($bills as $entry)
- - + +
- {{{$entry->name}}} + {{{$entry->name}}} @foreach(explode(',',$entry->match) as $match) @@ -27,22 +27,20 @@ @endforeach - {{mf($entry->amount_min)}} + {{Amount::format($entry->amount_min)}} — - {{mf($entry->amount_max)}} + {{Amount::format($entry->amount_max)}} - lastFoundMatch();?> - @if($lastMatch) - {{$lastMatch->format('j F Y')}} + @if($entry->lastFoundMatch) + {{$entry->lastFoundMatch->format('j F Y')}} @else Unknown @endif - nextExpectedMatch();?> - @if($nextExpectedMatch) - {{$nextExpectedMatch->format('j F Y')}} + @if($entry->nextExpectedMatch) + {{$entry->nextExpectedMatch->format('j F Y')}} @else Unknown @endif @@ -70,4 +68,4 @@ @endforeach - \ No newline at end of file + diff --git a/app/views/list/categories.blade.php b/app/views/list/categories.blade.php index 6cfdb19eb2..29e6d7e27f 100644 --- a/app/views/list/categories.blade.php +++ b/app/views/list/categories.blade.php @@ -25,4 +25,4 @@ @endforeach - \ No newline at end of file + diff --git a/app/views/list/journals-full.blade.php b/app/views/list/journals-full.blade.php index 61929f43d9..4979b6a428 100644 --- a/app/views/list/journals-full.blade.php +++ b/app/views/list/journals-full.blade.php @@ -15,8 +15,8 @@ @if(!isset($hideCategory) || (isset($hideCategory) && $hideCategory=== false)) @endif - @if(!isset($hideRecurring) || (isset($hideRecurring) && $hideRecurring=== false)) - + @if(!isset($hideBill) || (isset($hideBill) && $hideBill=== false)) + @endif @foreach($journals as $journal) @@ -58,13 +58,13 @@ @if($journal->transactiontype->type == 'Withdrawal') - {{mf($journal->transactions[1]->amount,false)}} + {{Amount::formatTransaction($journal->transactions[1],false)}} @endif @if($journal->transactiontype->type == 'Deposit') - {{mf($journal->transactions[1]->amount,false)}} + {{Amount::formatTransaction($journal->transactions[1],false)}} @endif @if($journal->transactiontype->type == 'Transfer') - {{mf($journal->transactions[1]->amount,false)}} + {{Amount::formatTransaction($journal->transactions[1],false)}} @endif @@ -100,10 +100,10 @@ @endif @endif - @if(!isset($hideRecurring) || (isset($hideRecurring) && $hideRecurring=== false)) + @if(!isset($hideBill) || (isset($hideBill) && $hideBill=== false)) - @if($journal->recurringTransaction) - {{{$journal->recurringTransaction->name}}} + @if($journal->bill) + {{{$journal->bill->name}}} @endif @endif @@ -117,4 +117,4 @@ @if(is_object($journals) && method_exists($journals, 'links')) {{$journals->links()}} -@endif \ No newline at end of file +@endif diff --git a/app/views/list/journals-small.blade.php b/app/views/list/journals-small.blade.php new file mode 100644 index 0000000000..9bf33f4b0b --- /dev/null +++ b/app/views/list/journals-small.blade.php @@ -0,0 +1,40 @@ + + + @foreach($journals as $journal) + + + + + + + + @endforeach + @if(isset($displaySum) && $displaySum === true) + + + + + + @endif +
+ {{{$journal->description}}} + + transactions[1]->amount);?> + @if($journal->transactiontype->type == 'Withdrawal') + {{Amount::formatTransaction($journal->transactions[1],false)}} + @endif + @if($journal->transactiontype->type == 'Deposit') + {{Amount::formatTransaction($journal->transactions[1],false)}} + @endif + @if($journal->transactiontype->type == 'Transfer') + {{Amount::formatTransaction($journal->transactions[1],false)}} + @endif + + {{$journal->date->format('j F Y')}} + + @if($journal->transactions[1]->account->accounttype->description == 'Cash account') + (cash) + @else + {{{$journal->transactions[1]->account->name}}} + @endif +
Sum{{Amount::format($tableSum)}}
diff --git a/app/views/list/journals-tiny.blade.php b/app/views/list/journals-tiny.blade.php index 91c2b6f2d3..9987e28ae4 100644 --- a/app/views/list/journals-tiny.blade.php +++ b/app/views/list/journals-tiny.blade.php @@ -18,13 +18,13 @@ @if(isset($account)) @foreach($journal->transactions as $index => $t) @if($t->account_id == $account->id) - {{mf($t->amount)}} + {{Amount::formatTransaction($t)}} @endif @endforeach @else @foreach($journal->transactions as $index => $t) @if($index == 0) - {{mf($t->amount)}} + {{Amount::formatTransaction($t)}} @endif @endforeach @endif @@ -32,4 +32,4 @@ @endforeach - \ No newline at end of file + diff --git a/app/views/list/piggybank-events.blade.php b/app/views/list/piggy-bank-events.blade.php similarity index 62% rename from app/views/list/piggybank-events.blade.php rename to app/views/list/piggy-bank-events.blade.php index e80ddc4c61..e7527ed54e 100644 --- a/app/views/list/piggybank-events.blade.php +++ b/app/views/list/piggy-bank-events.blade.php @@ -1,6 +1,6 @@ - @if(isset($showPiggybank) && $showPiggybank === true) + @if(isset($showPiggyBank) && $showPiggyBank === true) @endif @@ -8,9 +8,9 @@ @foreach($events as $event) - @if(isset($showPiggybank) && $showPiggybank === true) + @if(isset($showPiggyBank) && $showPiggyBank === true) @endif @endforeach -
Piggy bankDate
- {{{$event->piggybank->name}}} + {{{$event->piggyBank->name}}} @@ -23,11 +23,11 @@ @if($event->amount < 0) - Removed {{mf($event->amount*-1,false)}} + Removed {{Amount::format($event->amount*-1,false)}} @else - Added {{mf($event->amount,false)}} + Added {{Amount::format($event->amount,false)}} @endif
\ No newline at end of file + diff --git a/app/views/partials/date_nav.blade.php b/app/views/partials/date_nav.blade.php index 7cce808a0d..1230471443 100644 --- a/app/views/partials/date_nav.blade.php +++ b/app/views/partials/date_nav.blade.php @@ -25,4 +25,4 @@ {{{\Session::get('next')}}} - \ No newline at end of file + diff --git a/app/views/partials/flashes.blade.php b/app/views/partials/flashes.blade.php index e9d28fd3a2..e97d346de0 100644 --- a/app/views/partials/flashes.blade.php +++ b/app/views/partials/flashes.blade.php @@ -24,4 +24,4 @@ Error! {{{Session::get('error')}}} -@endif \ No newline at end of file +@endif diff --git a/app/views/partials/menu.blade.php b/app/views/partials/menu.blade.php index 5e34833a5f..05ed6c3bbd 100644 --- a/app/views/partials/menu.blade.php +++ b/app/views/partials/menu.blade.php @@ -137,19 +137,19 @@
  • Money management diff --git a/app/views/piggybanks/add.blade.php b/app/views/piggy_banks/add.blade.php similarity index 80% rename from app/views/piggybanks/add.blade.php rename to app/views/piggy_banks/add.blade.php index a4c7f5dc6e..b9ee7be0d0 100644 --- a/app/views/piggybanks/add.blade.php +++ b/app/views/piggy_banks/add.blade.php @@ -1,14 +1,14 @@ -
    + {{Form::token()}}
    -
    -
    -
    - Budget reports -
    -
    - + +
    +
    +
    + Monthly reports +
    +
    + +
    +
    +
    + +
    +
    +
    + Budget reports +
    +
    + +
    -
    -
    -
    -
    - Unbalanced transactions -
    -
    - -
    -
    -
    -@stop \ No newline at end of file +@stop diff --git a/app/views/reports/month.blade.php b/app/views/reports/month.blade.php new file mode 100644 index 0000000000..c60d473d62 --- /dev/null +++ b/app/views/reports/month.blade.php @@ -0,0 +1,197 @@ +@extends('layouts.default') +@section('content') +{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $date) }} +
    +
    +
    +
    Income
    + @include('list.journals-small',['journals' => $income]) +
    +
    +
    +
    +
    Expenses (top 10)
    + + + @foreach($expenses as $id => $expense) + + + @if($id > 0) + + @else + + @endif + + + @endforeach + + + + +
    {{{$expense['name']}}}{{{$expense['name']}}}{{Amount::format($expense['amount'])}}
    Sum{{Amount::format($sum)}}
    +
    +
    +
    +
    +
    Sums
    + transactions[1]->amount); + } + ?> + + + + + + + + + + + + + +
    In{{Amount::format($in)}}
    Out{{Amount::format($sum)}}
    Difference{{Amount::format($in - $sum)}}
    +
    +
    +
    +
    +
    +
    +
    Budgets
    + + + + + + + + + @foreach($budgets as $id => $budget) + + + + + + + + @endforeach + + + + + + +
    BudgetEnvelopeSpentLeft
    + @if($id > 0) + {{{$budget['name']}}} + @else + {{{$budget['name']}}} + @endif + {{Amount::format($budget['amount'])}}{{Amount::format($budget['spent'],false)}}{{Amount::format($budget['amount'] + $budget['spent'])}}
    Sum{{Amount::format($sumEnvelope)}}{{Amount::format($sumSpent)}}{{Amount::format($sumLeft)}}
    +
    +
    +
    +
    +
    Categories
    + + + + + + + @foreach($categories as $id => $category) + + + + + + @endforeach + + + + +
    CategorySpent
    + @if($id > 0) + {{{$category['name']}}} + @else + {{{$category['name']}}} + @endif + {{Amount::format($category['amount'],false)}}
    Sum{{Amount::format($sum)}}
    +
    +
    +
    +
    +
    +
    +
    Accounts
    + + + @foreach($accounts as $id => $account) + + + + + + + + @endforeach + + + + + + +
    {{{$account['name']}}}{{Amount::format($account['startBalance'])}}{{Amount::format($account['endBalance'])}}{{Amount::format($account['difference'])}}
    Sum{{Amount::format($sumStart)}}{{Amount::format($sumEnd)}}{{Amount::format($sumDiff)}}
    +
    +
    +
    +
    +
    +
    +
    Piggy banks
    +
    Body
    +
    +
    +
    +
    +
    Repeated expenses
    +
    Body
    +
    +
    +
    +
    +
    +
    +
    Bills
    +
    Body
    +
    +
    +
    +
    +
    +
    +
    Outside of budgets
    +
    Body
    +
    +
    +
    +@stop diff --git a/app/views/reports/unbalanced.blade.php b/app/views/reports/unbalanced.blade.php deleted file mode 100644 index 74aa64fe41..0000000000 --- a/app/views/reports/unbalanced.blade.php +++ /dev/null @@ -1,56 +0,0 @@ -@extends('layouts.default') -@section('content') -{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $start) }} -@if(count($journals) == 0) -
    -
    -

    Everything accounted for.

    -
    -
    -@endif -@if(count($journals) > 0) -
    -
    -

    Withdrawals

    -
    -
    - -
    - @foreach($journals as $journal) -
    -
    -
    - @if($journal->transactiontype->type == 'Withdrawal') - - @endif - @if($journal->transactiontype->type == 'Deposit') - - @endif - @if($journal->transactiontype->type == 'Transfer') - - @endif - @if($journal->transactiontype->type == 'Opening balance') - - @endif - {{{$journal->description}}} -
    -
    -

    Spent {{mf($journal->getAmount())}}

    -

    No counter transaction!

    -

    - Add counter transaction -

    -
    -
    -
    - @endforeach -
    -@endif -@stop -@section('scripts') - -{{HTML::script('assets/javascript/firefly/reports.js')}} -{{HTML::script('assets/javascript/firefly/related-manager.js')}} -@stop \ No newline at end of file diff --git a/app/views/reports/year.blade.php b/app/views/reports/year.blade.php index 827f988a37..130f29ec55 100644 --- a/app/views/reports/year.blade.php +++ b/app/views/reports/year.blade.php @@ -30,7 +30,7 @@
    Account balance
    - +
    shared @endif - - - + + + @endforeach - - - + + +
    {{mf($balance['start'])}}{{mf($balance['end'])}}{{mf($balance['end']-$balance['start'])}}{{Amount::format($balance['start'])}}{{Amount::format($balance['end'])}}{{Amount::format($balance['end']-$balance['start'])}}
    Sum of sums{{mf($start)}}{{mf($end)}}{{mf($diff)}}{{Amount::format($start)}}{{Amount::format($end)}}{{Amount::format($diff)}}
    + +
    +
    + Income vs. expense +
    + amount); + } + foreach($groupedExpenses as $exp) { + $expenseSum += floatval($exp['amount']); + } + $incomeSum = floatval($incomeSum*-1); + + ?> + + + + + + + + + + + + + + +
    In{{Amount::format($incomeSum)}}
    Out{{Amount::format($expenseSum*-1)}}
    Difference{{Amount::format($incomeSum - $expenseSum)}}
    +
    @@ -69,12 +102,18 @@ Income
    + @foreach($groupedIncomes as $income) + amount)*-1;?> - + @endforeach + + + +
    {{{$income->name}}}{{mf(floatval($income->sum)*-1)}}{{Amount::format(floatval($income->amount)*-1)}}
    Sum{{Amount::format($sum)}}
    @@ -84,10 +123,10 @@ Expenses - @foreach($groupedExpenses as $expense) + @foreach($groupedExpenses as $id => $expense) - - + + @endforeach
    {{{$expense->name}}}{{mf(floatval($expense->sum)*-1)}}{{{$expense['name']}}}{{Amount::format(floatval($expense['amount'])*-1)}}
    @@ -117,9 +156,9 @@ {{HTML::script('assets/javascript/firefly/reports.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/search/index.blade.php b/app/views/search/index.blade.php index d5f9e43e46..c6f6f16a4b 100644 --- a/app/views/search/index.blade.php +++ b/app/views/search/index.blade.php @@ -10,7 +10,7 @@ Transactions ({{$result['transactions']->count()}})
    - @include('...lists.old.journals-small-noaccount',['transactions' => $result['transactions']]) + @include('list.journals-small',['journals' => $result['transactions']])
    @@ -103,4 +103,4 @@ -@stop \ No newline at end of file +@stop diff --git a/app/views/transactions/create.blade.php b/app/views/transactions/create.blade.php index 9575d6ac21..5585ddb4c6 100644 --- a/app/views/transactions/create.blade.php +++ b/app/views/transactions/create.blade.php @@ -1,7 +1,7 @@ @extends('layouts.default') @section('content') {{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $what) }} -{{Form::open(['class' => 'form-horizontal','url' => route('transactions.store',$what)])}} +{{Form::open(['class' => 'form-horizontal','id' => 'store','url' => route('transactions.store',$what)])}} {{Form::hidden('reminder',Input::get('reminder_id'))}}
    @@ -70,7 +70,7 @@ @if($what == 'transfer' && count($piggies) > 0) - {{Form::ffSelect('piggybank_id',$piggies)}} + {{Form::ffSelect('piggy_bank_id',$piggies)}} @endif
    @@ -93,4 +93,4 @@ @section('scripts') {{HTML::script('assets/javascript/typeahead/bootstrap3-typeahead.min.js')}} {{HTML::script('assets/javascript/firefly/transactions.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/transactions/delete.blade.php b/app/views/transactions/delete.blade.php index e99253a64c..aef2335fc8 100644 --- a/app/views/transactions/delete.blade.php +++ b/app/views/transactions/delete.blade.php @@ -1,7 +1,7 @@ @extends('layouts.default') @section('content') {{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $journal) }} -{{Form::open(['class' => 'form-horizontal','url' => route('transactions.destroy',$journal->id)])}} +{{Form::open(['class' => 'form-horizontal','id' => 'destroy','url' => route('transactions.destroy',$journal->id)])}}
    @@ -16,7 +16,7 @@ associated data.

    - This action will not destroy categories, piggybanks, accounts, etc. + This action will not destroy categories, piggy banks, accounts, etc.

    Are you sure? diff --git a/app/views/transactions/edit.blade.php b/app/views/transactions/edit.blade.php index d1a268c654..0b60dd357e 100644 --- a/app/views/transactions/edit.blade.php +++ b/app/views/transactions/edit.blade.php @@ -1,7 +1,7 @@ @extends('layouts.default') @section('content') {{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $journal) }} -{{Form::open(['class' => 'form-horizontal','url' => route('transactions.update',$journal->id)])}} +{{Form::open(['class' => 'form-horizontal','id' => 'update','url' => route('transactions.update',$journal->id)])}}

    @@ -68,7 +68,7 @@ @if($what == 'transfer' && count($piggies) > 0) - {{Form::ffSelect('piggybank_id',$piggies,$data['piggybank_id'])}} + {{Form::ffSelect('piggy_bank_id',$piggies,$data['piggy_bank_id'])}} @endif
    @@ -93,4 +93,4 @@ @section('scripts') {{HTML::script('assets/javascript/typeahead/bootstrap3-typeahead.min.js')}} {{HTML::script('assets/javascript/firefly/transactions.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/transactions/show.blade.php b/app/views/transactions/show.blade.php index 474ce848fa..2bdc086cf1 100644 --- a/app/views/transactions/show.blade.php +++ b/app/views/transactions/show.blade.php @@ -48,13 +48,13 @@
    - @if(count($journal->piggybankevents) > 0) + @if(count($journal->piggyBankEvents) > 0)
    Piggy banks
    - @include('list.piggybank-events',['events' => $journal->piggybankevents,'showPiggybank' => true]) + @include('list.piggy-bank-events',['events' => $journal->piggyBankEvents,'showPiggyBank' => true])
    @endif @@ -74,7 +74,7 @@ {{{$jrnl->description}}} - {{mf($jrnl->getAmount())}} + {{Amount::formatJournal($jrnl, $jrnl->getAmount())}} @endforeach @@ -97,11 +97,11 @@ - + - + @if(!is_null($t->description)) @@ -128,4 +128,4 @@ @section('scripts') {{HTML::script('assets/javascript/firefly/transactions.js')}} {{HTML::script('assets/javascript/firefly/related-manager.js')}} -@stop \ No newline at end of file +@stop diff --git a/app/views/user/login.blade.php b/app/views/user/login.blade.php index c3b6efe898..a2efbcfa9e 100644 --- a/app/views/user/login.blade.php +++ b/app/views/user/login.blade.php @@ -29,11 +29,11 @@ @if(Config::get('auth.allow_register') === true) Register @endif - Forgot your password? + Forgot your password? {{Form::close()}} -@stop \ No newline at end of file +@stop diff --git a/app/views/user/register.blade.php b/app/views/user/register.blade.php index c4cb0fb74a..a7a11f07fc 100644 --- a/app/views/user/register.blade.php +++ b/app/views/user/register.blade.php @@ -23,11 +23,11 @@
    Back to the login form - Forgot your password? + Forgot your password?
    -@stop \ No newline at end of file +@stop diff --git a/app/views/user/registered.blade.php b/app/views/user/registered.blade.php index 3724140e4e..ce4e3e056e 100644 --- a/app/views/user/registered.blade.php +++ b/app/views/user/registered.blade.php @@ -16,4 +16,4 @@ -@stop \ No newline at end of file +@stop diff --git a/app/views/emails/user/remindme-html.blade.php b/app/views/user/remindMe-html.blade.php similarity index 96% rename from app/views/emails/user/remindme-html.blade.php rename to app/views/user/remindMe-html.blade.php index e16c85fafe..16f09cc04d 100644 --- a/app/views/emails/user/remindme-html.blade.php +++ b/app/views/user/remindMe-html.blade.php @@ -16,4 +16,4 @@

    - \ No newline at end of file + diff --git a/app/views/emails/user/remindme-text.blade.php b/app/views/user/remindMe-text.blade.php similarity index 100% rename from app/views/emails/user/remindme-text.blade.php rename to app/views/user/remindMe-text.blade.php diff --git a/app/views/user/remindme.blade.php b/app/views/user/remindMe.blade.php similarity index 95% rename from app/views/user/remindme.blade.php rename to app/views/user/remindMe.blade.php index 5ee87b70e7..18b48954ac 100644 --- a/app/views/user/remindme.blade.php +++ b/app/views/user/remindMe.blade.php @@ -7,7 +7,7 @@

    Firefly III — Reset your password

    - {{Form::open()}} + {{Form::open(['id' => 'remindMe'])}}
    @@ -24,4 +24,4 @@
    -@stop \ No newline at end of file +@stop diff --git a/app/views/user/verification-pending.blade.php b/app/views/user/verification-pending.blade.php index 7e224b82ef..a10b2d53da 100644 --- a/app/views/user/verification-pending.blade.php +++ b/app/views/user/verification-pending.blade.php @@ -16,4 +16,4 @@ -@stop \ No newline at end of file +@stop diff --git a/bootstrap/functions.php b/bootstrap/functions.php new file mode 100644 index 0000000000..b3d9bbc7f3 --- /dev/null +++ b/bootstrap/functions.php @@ -0,0 +1 @@ +' . $currencySymbol . ' ' . $string . ''; - } - if ($amount > 0) { - return '' . $currencySymbol . ' ' . $string . ''; - } - - return '' . $currencySymbol . ' ' . $string . ''; - } - - // € - return $currencySymbol . ' ' . $string; - } -} - -if (!function_exists('getCurrencySymbol')) { - /** - * @return string - */ - function getCurrencySymbol() - { - if (defined('FFCURRENCYSYMBOL')) { - return FFCURRENCYSYMBOL; - } - if (Cache::has('FFCURRENCYSYMBOL')) { - define('FFCURRENCYSYMBOL', Cache::get('FFCURRENCYSYMBOL')); - - return FFCURRENCYSYMBOL; - } - - /** @var \FireflyIII\Database\TransactionCurrency\TransactionCurrency $currencies */ - $currencies = App::make('FireflyIII\Database\TransactionCurrency\TransactionCurrency'); - - /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */ - $preferences = App::make('FireflyIII\Shared\Preferences\Preferences'); - - $currencyPreference = $preferences->get('currencyPreference', 'EUR'); - $currency = $currencies->findByCode($currencyPreference->data); - - Cache::forever('FFCURRENCYSYMBOL', $currency->symbol); - - define('FFCURRENCYSYMBOL', $currency->symbol); - - return $currency->symbol; - } -} - -if (!function_exists('getCurrencyCode')) { - /** - * @return string - */ - function getCurrencyCode() - { - if (defined('FFCURRENCYCODE')) { - return FFCURRENCYCODE; - } - if (Cache::has('FFCURRENCYCODE')) { - define('FFCURRENCYCODE', Cache::get('FFCURRENCYCODE')); - - return FFCURRENCYCODE; - } - - /** @var \FireflyIII\Database\TransactionCurrency\TransactionCurrency $currencies */ - $currencies = App::make('FireflyIII\Database\TransactionCurrency\TransactionCurrency'); - - /** @var \FireflyIII\Shared\Preferences\Preferences $preferences */ - $preferences = App::make('FireflyIII\Shared\Preferences\Preferences'); - - $currencyPreference = $preferences->get('currencyPreference', 'EUR'); - $currency = $currencies->findByCode($currencyPreference->data); - - Cache::forever('FFCURRENCYCODE', $currency->code); - - define('FFCURRENCYCODE', $currency->code); - - return $currency->code; - } -} - -if (!function_exists('boolstr')) { - /** - * @param $boolean - * - * @return string - */ - function boolstr($boolean) - { - if (is_bool($boolean) && $boolean === true) { - return 'BOOLEAN TRUE'; - } - if (is_bool($boolean) && $boolean === false) { - return 'BOOLEAN FALSE'; - } - - return 'NO BOOLEAN: ' . $boolean; - } -} +include('functions.php'); $app = new Illuminate\Foundation\Application; @@ -176,11 +64,6 @@ require $framework . '/Illuminate/Foundation/start.php'; */ // do something with events: -//Event::subscribe('Firefly\Trigger\Limits\EloquentLimitTrigger'); -//Event::subscribe('Firefly\Trigger\Piggybanks\EloquentPiggybankTrigger'); -//Event::subscribe('Firefly\Trigger\Budgets\EloquentBudgetTrigger'); -//Event::subscribe('Firefly\Trigger\Recurring\EloquentRecurringTrigger'); -//Event::subscribe('Firefly\Trigger\Journals\EloquentJournalTrigger'); Event::subscribe('FireflyIII\Event\Account'); Event::subscribe('FireflyIII\Event\Budget'); @@ -213,6 +96,6 @@ Event::subscribe('FireflyIII\Event\TransactionJournal'); // see if the various has-many-throughs actually get used. // set very tight rules on all models // create custom uniquely rules. -// TODO add "Create new X" button to any list there is: categories, accounts, piggies, etc. -// TODO Install PHP5 and code thing and create very small methods. +// add "Create new X" button to any list there is: categories, accounts, piggies, etc. +// Install PHP5 and code thing and create very small methods. return $app; diff --git a/c3.php b/c3.php deleted file mode 100644 index 7f77e7cde2..0000000000 --- a/c3.php +++ /dev/null @@ -1,240 +0,0 @@ - $value) { - $_SERVER["HTTP_X_CODECEPTION_".strtoupper($key)] = $value; - } - } -} - -if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE', $_SERVER)) { - return; -} - -if (!function_exists('__c3_error')) { - function __c3_error($message) - { - file_put_contents(C3_CODECOVERAGE_MEDIATE_STORAGE . DIRECTORY_SEPARATOR . 'error.txt', $message); - if (!headers_sent()) { - header('X-Codeception-CodeCoverage-Error: ' . str_replace("\n", ' ', $message), true, 500); - } - setcookie('CODECEPTION_CODECOVERAGE_ERROR', $message); - } -} - -// Autoload Codeception classes -if (!class_exists('\\Codeception\\Codecept')) { - if (stream_resolve_include_path(__DIR__ . '/vendor/autoload.php')) { - require_once __DIR__ . '/vendor/autoload.php'; - } elseif (file_exists(__DIR__ . '/codecept.phar')) { - require_once 'phar://'.__DIR__ . '/codecept.phar/autoload.php'; - } elseif (stream_resolve_include_path('Codeception/autoload.php')) { - require_once 'Codeception/autoload.php'; - } else { - __c3_error('Codeception is not loaded. Please check that either PHAR or Composer or PEAR package can be used'); - } -} - -// Load Codeception Config -$config_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'codeception.yml'; -if (array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG', $_SERVER)) { - $config_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG']; -} -if (!file_exists($config_file)) { - __c3_error(sprintf("Codeception config file '%s' not found", $config_file)); -} -try { - \Codeception\Configuration::config($config_file); -} catch (\Exception $e) { - __c3_error($e->getMessage()); -} - -if (!defined('C3_CODECOVERAGE_MEDIATE_STORAGE')) { - - // workaround for 'zend_mm_heap corrupted' problem - gc_disable(); - - if ((integer)ini_get('memory_limit') < 384) { - ini_set('memory_limit', '384M'); - } - - define('C3_CODECOVERAGE_MEDIATE_STORAGE', Codeception\Configuration::logDir() . 'c3tmp'); - define('C3_CODECOVERAGE_PROJECT_ROOT', Codeception\Configuration::projectDir()); - define('C3_CODECOVERAGE_TESTNAME', $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE']); - - function __c3_build_html_report(PHP_CodeCoverage $codeCoverage, $path) - { - $writer = new PHP_CodeCoverage_Report_HTML(); - $writer->process($codeCoverage, $path . 'html'); - - if (file_exists($path . '.tar')) { - unlink($path . '.tar'); - } - - $phar = new PharData($path . '.tar'); - $phar->setSignatureAlgorithm(Phar::SHA1); - $files = $phar->buildFromDirectory($path . 'html'); - array_map('unlink', $files); - - if (in_array('GZ', Phar::getSupportedCompression())) { - if (file_exists($path . '.tar.gz')) { - unlink($path . '.tar.gz'); - } - - $phar->compress(\Phar::GZ); - - // close the file so that we can rename it - unset($phar); - - unlink($path . '.tar'); - rename($path . '.tar.gz', $path . '.tar'); - } - - return $path . '.tar'; - } - - function __c3_build_clover_report(PHP_CodeCoverage $codeCoverage, $path) - { - $writer = new PHP_CodeCoverage_Report_Clover(); - $writer->process($codeCoverage, $path . '.clover.xml'); - - return $path . '.clover.xml'; - } - - function __c3_send_file($filename) - { - if (!headers_sent()) { - readfile($filename); - } - - return __c3_exit(); - } - - /** - * @param $filename - * @return null|PHP_CodeCoverage - */ - function __c3_factory($filename) - { - $phpCoverage = is_readable($filename) - ? unserialize(file_get_contents($filename)) - : new PHP_CodeCoverage(); - - - if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE'])) { - $suite = $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE']; - try { - $settings = \Codeception\Configuration::suiteSettings($suite, \Codeception\Configuration::config()); - } catch (Exception $e) { - __c3_error($e->getMessage()); - } - } else { - $settings = \Codeception\Configuration::config(); - } - - try { - \Codeception\Coverage\Filter::setup($phpCoverage) - ->whiteList($settings) - ->blackList($settings); - } catch (Exception $e) { - __c3_error($e->getMessage()); - } - - return $phpCoverage; - } - - function __c3_exit() - { - if (!isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'])) { - exit; - } - return null; - } - - function __c3_clear() - { - \Codeception\Util\FileSystem::doEmptyDir(C3_CODECOVERAGE_MEDIATE_STORAGE); - } -} - -if (!is_dir(C3_CODECOVERAGE_MEDIATE_STORAGE)) { - if (mkdir(C3_CODECOVERAGE_MEDIATE_STORAGE, 0777, true) === false) { - __c3_error('Failed to create directory "' . C3_CODECOVERAGE_MEDIATE_STORAGE . '"'); - } -} - -// evaluate base path for c3-related files -$path = realpath(C3_CODECOVERAGE_MEDIATE_STORAGE) . DIRECTORY_SEPARATOR . 'codecoverage'; - -$requested_c3_report = (strpos($_SERVER['REQUEST_URI'], 'c3/report') !== false); - -$complete_report = $current_report = $path . '.serialized'; -if ($requested_c3_report) { - set_time_limit(0); - - $route = ltrim(strrchr($_SERVER['REQUEST_URI'], '/'), '/'); - - if ($route == 'clear') { - __c3_clear(); - return __c3_exit(); - } - - $codeCoverage = __c3_factory($complete_report); - - switch ($route) { - case 'html': - try { - __c3_send_file(__c3_build_html_report($codeCoverage, $path)); - } catch (Exception $e) { - __c3_error($e->getMessage()); - } - return __c3_exit(); - case 'clover': - try { - __c3_send_file(__c3_build_clover_report($codeCoverage, $path)); - } catch (Exception $e) { - __c3_error($e->getMessage()); - } - return __c3_exit(); - case 'serialized': - try { - __c3_send_file($complete_report); - } catch (Exception $e) { - __c3_error($e->getMessage()); - } - return __c3_exit(); - } - -} else { - $codeCoverage = __c3_factory($current_report); - $codeCoverage->start(C3_CODECOVERAGE_TESTNAME); - if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG', $_SERVER)) { - register_shutdown_function( - function () use ($codeCoverage, $current_report) { - $codeCoverage->stop(); - file_put_contents($current_report, serialize($codeCoverage)); - } - ); - } -} - -// @codeCoverageIgnoreEnd \ No newline at end of file diff --git a/codeception.yml b/codeception.yml index f552c34999..1c64b071f9 100644 --- a/codeception.yml +++ b/codeception.yml @@ -10,13 +10,6 @@ settings: memory_limit: 1024M modules: config: - Db: - dsn: 'sqlite:tests/_data/db.sqlite' - user: '' - password: '' - dump: tests/_data/dump.sql - cleanup: true - populate: true coverage: enabled: true remote: false @@ -26,4 +19,4 @@ coverage: - app/models/* - app/lib/FireflyIII/* exclude: - - app/controllers/BaseController.php \ No newline at end of file + - app/controllers/BaseController.php diff --git a/composer.json b/composer.json index 005a9d3189..e33048e239 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,6 @@ "license": "MIT", "keywords": ["finance", "finances", "manager", "euro", "laravel", "money", "financials", "budgets", "transactions", "transfers", "management"], "homepage": "https://github.com/JC5/firefly-iii", - "php": ">=5.4.0", "type": "project", "authors": [ { @@ -33,12 +32,16 @@ "doctrine/dbal": "~2.3", "satooshi/php-coveralls": "dev-master", "mockery/mockery": "@stable", - "league/factory-muffin": "~2.0", + "league/factory-muffin": "~2.1", "codeception/codeception": "*", "codeception/c3": "2.*", "sebastian/phpcpd": "*", "sebastian/phpdcd": "*", - "codeception/phpbuiltinserver": "*" + "codeception/phpbuiltinserver": "*", + "codeception/specify": "*", + "codeception/verify": "*", + "fzaninotto/faker": "1.*" + }, "autoload": { diff --git a/composer.lock b/composer.lock index 20676b73a9..0cd57619c0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "9c8cafd9d3f40fa1e56b3a7cee419da5", + "hash": "0d6a322d9bcdb03029984f771d36f10f", "packages": [ { "name": "classpreloader/classpreloader", @@ -490,16 +490,16 @@ }, { "name": "monolog/monolog", - "version": "1.11.0", + "version": "1.12.0", "source": { "type": "git", "url": "https://github.com/Seldaek/monolog.git", - "reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa" + "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Seldaek/monolog/zipball/ec3961874c43840e96da3a8a1ed20d8c73d7e5aa", - "reference": "ec3961874c43840e96da3a8a1ed20d8c73d7e5aa", + "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1fbe8c2641f2b163addf49cc5e18f144bec6b19f", + "reference": "1fbe8c2641f2b163addf49cc5e18f144bec6b19f", "shasum": "" }, "require": { @@ -513,7 +513,7 @@ "aws/aws-sdk-php": "~2.4, >2.4.8", "doctrine/couchdb": "~1.0@dev", "graylog2/gelf-php": "~1.0", - "phpunit/phpunit": "~3.7.0", + "phpunit/phpunit": "~4.0", "raven/raven": "~0.5", "ruflin/elastica": "0.90.*", "videlalvaro/php-amqplib": "~2.4" @@ -532,7 +532,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.11.x-dev" + "dev-master": "1.12.x-dev" } }, "autoload": { @@ -558,7 +558,7 @@ "logging", "psr-3" ], - "time": "2014-09-30 13:30:58" + "time": "2014-12-29 21:29:35" }, { "name": "nesbot/carbon", @@ -1825,21 +1825,21 @@ "packages-dev": [ { "name": "barryvdh/laravel-debugbar", - "version": "v1.8.4", + "version": "v1.8.5", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-debugbar.git", - "reference": "410e98739c58ccd1b9ad2f49afd77a8d40144515" + "reference": "548e12d45760ee66192029f4b642d2f4e3d64118" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/410e98739c58ccd1b9ad2f49afd77a8d40144515", - "reference": "410e98739c58ccd1b9ad2f49afd77a8d40144515", + "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/548e12d45760ee66192029f4b642d2f4e3d64118", + "reference": "548e12d45760ee66192029f4b642d2f4e3d64118", "shasum": "" }, "require": { "laravel/framework": "4.*|5.0.*", - "maximebf/debugbar": "~1.10.1", + "maximebf/debugbar": "~1.10.2", "php": ">=5.3.0", "symfony/finder": "~2.3" }, @@ -1875,7 +1875,7 @@ "profiler", "webprofiler" ], - "time": "2014-12-04 12:14:32" + "time": "2014-12-24 08:00:07" }, { "name": "barryvdh/laravel-ide-helper", @@ -2104,6 +2104,77 @@ ], "time": "2014-09-19 10:14:07" }, + { + "name": "codeception/specify", + "version": "0.4.1", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Specify.git", + "reference": "0c0ae07adfc231115b3b72ade22f44c23c199ded" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Specify/zipball/0c0ae07adfc231115b3b72ade22f44c23c199ded", + "reference": "0c0ae07adfc231115b3b72ade22f44c23c199ded", + "shasum": "" + }, + "require": { + "myclabs/deep-copy": "~1.1", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Codeception\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert.php@mailican.com" + } + ], + "description": "BDD code blocks for PHPUnit and Codeception", + "time": "2014-10-17 00:06:51" + }, + { + "name": "codeception/verify", + "version": "0.2.7", + "source": { + "type": "git", + "url": "https://github.com/Codeception/Verify.git", + "reference": "66e5074905f4d9590ddb805d123fe632f4baa488" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Codeception/Verify/zipball/66e5074905f4d9590ddb805d123fe632f4baa488", + "reference": "66e5074905f4d9590ddb805d123fe632f4baa488", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "autoload": { + "files": [ + "src/Codeception/function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "authors": [ + { + "name": "Michael Bodnarchuk", + "email": "davert.php@mailican.com", + "homepage": "http://codeception.com" + } + ], + "description": "BDD assertion library for PHPUnit", + "time": "2014-01-22 14:40:33" + }, { "name": "doctrine/annotations", "version": "v1.2.3", @@ -3153,6 +3224,48 @@ ], "time": "2014-12-22 10:06:19" }, + { + "name": "myclabs/deep-copy", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "d93c485e71bcd22df0a994e9e3e03a3ef3a3e3f3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/d93c485e71bcd22df0a994e9e3e03a3ef3a3e3f3", + "reference": "d93c485e71bcd22df0a994e9e3e03a3ef3a3e3f3", + "shasum": "" + }, + "require": { + "php": ">=5.4.0" + }, + "require-dev": { + "doctrine/collections": "1.*", + "phpunit/phpunit": "~4.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "homepage": "https://github.com/myclabs/DeepCopy", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "time": "2014-11-20 05:11:17" + }, { "name": "phpdocumentor/reflection-docblock", "version": "2.0.3", @@ -3204,16 +3317,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "2.0.13", + "version": "2.0.14", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "0e7d2eec5554f869fa7a4ec2d21e4b37af943ea5" + "reference": "ca158276c1200cc27f5409a5e338486bc0b4fc94" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/0e7d2eec5554f869fa7a4ec2d21e4b37af943ea5", - "reference": "0e7d2eec5554f869fa7a4ec2d21e4b37af943ea5", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/ca158276c1200cc27f5409a5e338486bc0b4fc94", + "reference": "ca158276c1200cc27f5409a5e338486bc0b4fc94", "shasum": "" }, "require": { @@ -3265,7 +3378,7 @@ "testing", "xunit" ], - "time": "2014-12-03 06:41:44" + "time": "2014-12-26 13:28:33" }, { "name": "phpunit/php-file-iterator", @@ -3451,16 +3564,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.4.0", + "version": "4.4.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "bbe7bcb83b6ec1a9eaabbe1b70d4795027c53ee0" + "reference": "6a5e49a86ce5e33b8d0657abe145057fc513543a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/bbe7bcb83b6ec1a9eaabbe1b70d4795027c53ee0", - "reference": "bbe7bcb83b6ec1a9eaabbe1b70d4795027c53ee0", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/6a5e49a86ce5e33b8d0657abe145057fc513543a", + "reference": "6a5e49a86ce5e33b8d0657abe145057fc513543a", "shasum": "" }, "require": { @@ -3518,7 +3631,7 @@ "testing", "xunit" ], - "time": "2014-12-05 06:49:03" + "time": "2014-12-28 07:57:05" }, { "name": "phpunit/phpunit-mock-objects", @@ -3577,16 +3690,16 @@ }, { "name": "react/promise", - "version": "v2.1.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/reactphp/promise.git", - "reference": "937b04f1b0ee8f6d180e75a0830aac778ca4bcd6" + "reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/reactphp/promise/zipball/937b04f1b0ee8f6d180e75a0830aac778ca4bcd6", - "reference": "937b04f1b0ee8f6d180e75a0830aac778ca4bcd6", + "url": "https://api.github.com/repos/reactphp/promise/zipball/365fcee430dfa4ace1fbc75737ca60ceea7eeeef", + "reference": "365fcee430dfa4ace1fbc75737ca60ceea7eeeef", "shasum": "" }, "require": { @@ -3603,7 +3716,7 @@ "React\\Promise\\": "src/" }, "files": [ - "src/functions.php" + "src/functions_include.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -3617,7 +3730,7 @@ } ], "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "time": "2014-10-15 20:05:57" + "time": "2014-12-30 13:32:42" }, { "name": "satooshi/php-coveralls", @@ -4122,16 +4235,16 @@ }, { "name": "sebastian/version", - "version": "1.0.3", + "version": "1.0.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43" + "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43", - "reference": "b6e1f0cf6b9e1ec409a0d3e2f2a5fb0998e36b43", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b", + "reference": "a77d9123f8e809db3fbdea15038c27a95da4058b", "shasum": "" }, "type": "library", @@ -4153,7 +4266,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2014-03-07 15:35:33" + "time": "2014-12-15 14:25:24" }, { "name": "symfony/class-loader", diff --git a/phpunit.xml b/phpunit.xml index e7253a467b..82d93aac97 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -37,5 +37,8 @@ ./app/tests/ + + ./tests/unit/ + diff --git a/provider/assets/stylesheets/readme.txt b/provider/assets/stylesheets/readme.txt index d8f094f58d..cd3d23335f 100644 --- a/provider/assets/stylesheets/readme.txt +++ b/provider/assets/stylesheets/readme.txt @@ -1 +1 @@ -No vendor/provider stylesheets here at the moment. But this is where you could put things like twitter bootstrap, gumby, font awesome... \ No newline at end of file +No vendor/provider stylesheets here at the moment. But this is where you could put things like twitter bootstrap, gumby, font awesome... diff --git a/public/assets/javascript/firefly/bills.js b/public/assets/javascript/firefly/bills.js new file mode 100644 index 0000000000..01c26984ce --- /dev/null +++ b/public/assets/javascript/firefly/bills.js @@ -0,0 +1,7 @@ +$(document).ready(function () { + + if (typeof(googleComboChart) == 'function' && typeof(billID) != 'undefined') { + googleComboChart('chart/bills/' + billID, 'bill-overview'); + } + } +); \ No newline at end of file diff --git a/public/assets/javascript/firefly/help.js b/public/assets/javascript/firefly/help.js index b40c59479c..cfe25448b4 100644 --- a/public/assets/javascript/firefly/help.js +++ b/public/assets/javascript/firefly/help.js @@ -1,5 +1,8 @@ $(function () { $('#help').click(showHelp); + $(function () { + $('[data-toggle="tooltip"]').tooltip() + }) }); function showHelp(e) { diff --git a/public/assets/javascript/firefly/index.js b/public/assets/javascript/firefly/index.js index d776da45b1..3328f23d6f 100644 --- a/public/assets/javascript/firefly/index.js +++ b/public/assets/javascript/firefly/index.js @@ -5,5 +5,5 @@ function drawChart() { googleLineChart('chart/home/account', 'accounts-chart'); googleBarChart('chart/home/budgets','budgets-chart'); googleColumnChart('chart/home/categories','categories-chart'); - googlePieChart('chart/home/recurring','recurring-chart') + googlePieChart('chart/home/bills','bills-chart') } diff --git a/public/assets/javascript/firefly/piggybanks.js b/public/assets/javascript/firefly/piggy_banks.js similarity index 60% rename from public/assets/javascript/firefly/piggybanks.js rename to public/assets/javascript/firefly/piggy_banks.js index f97c71339f..f336d2d3fd 100644 --- a/public/assets/javascript/firefly/piggybanks.js +++ b/public/assets/javascript/firefly/piggy_banks.js @@ -3,20 +3,20 @@ $(function () { $('.removeMoney').on('click', removeMoney); if (typeof(googleLineChart) == 'function' && typeof(piggyBankID) != 'undefined') { - googleLineChart('chart/piggyhistory/' + piggyBankID, 'piggybank-history'); + googleLineChart('chart/piggy_history/' + piggyBankID, 'piggy-bank-history'); } }); function addMoney(e) { var pigID = parseInt($(e.target).data('id')); - $('#moneyManagementModal').empty().load('piggybanks/add/' + pigID).modal('show'); + $('#moneyManagementModal').empty().load('piggy_banks/add/' + pigID).modal('show'); return false; } function removeMoney(e) { var pigID = parseInt($(e.target).data('id')); - $('#moneyManagementModal').empty().load('piggybanks/remove/' + pigID).modal('show'); + $('#moneyManagementModal').empty().load('piggy_banks/remove/' + pigID).modal('show'); return false; } \ No newline at end of file diff --git a/public/assets/javascript/firefly/recurring.js b/public/assets/javascript/firefly/recurring.js deleted file mode 100644 index b0857f6629..0000000000 --- a/public/assets/javascript/firefly/recurring.js +++ /dev/null @@ -1,14 +0,0 @@ -$(document).ready(function () { - - if (typeof(googleTable) == 'function') { - googleTable('table/recurring', 'recurring-table'); - - if (typeof(recurringID) != 'undefined') { - googleTable('table/recurring/' + recurringID + '/transactions', 'transaction-table'); - } - } - if (typeof(googleComboChart) == 'function' && typeof(recurringID) != 'undefined') { - googleComboChart('chart/recurring/' + recurringID, 'recurring-overview'); - } - } -); \ No newline at end of file diff --git a/public/assets/javascript/firefly/related-manager.js b/public/assets/javascript/firefly/related-manager.js index dc4171512a..2c3e55f8af 100644 --- a/public/assets/javascript/firefly/related-manager.js +++ b/public/assets/javascript/firefly/related-manager.js @@ -9,7 +9,7 @@ function unrelateTransaction(e) { var id = target.data('id'); var relatedTo = target.data('relatedto'); - $.post('transactions/unrelate/' + relatedTo, {relation: id}).success(function (data) { + $.post('related/removeRelation/' + id + '/' + relatedTo).success(function (data) { target.parent().parent().remove(); }).fail(function () { alert('Could not!'); @@ -23,7 +23,7 @@ function relateTransaction(e) { console.log($('#searchRelated').length); - $('#relationModal').empty().load('transaction/relate/' + ID, function () { + $('#relationModal').empty().load('related/related/' + ID, function () { $('#relationModal').modal('show'); getAlreadyRelatedTransactions(e, ID); @@ -42,10 +42,9 @@ function relateTransaction(e) { function searchRelatedTransactions(e, ID) { var searchValue = $('#relatedSearchValue').val(); if (searchValue != '') { - $.post('transactions/relatedSearch/' + ID, {searchValue: searchValue}).success(function (data) { + $.post('related/search/' + ID, {searchValue: searchValue}).success(function (data) { // post each result to some div. $('#relatedSearchResults').empty(); - // TODO this is the worst. $.each(data, function (i, row) { var tr = $(''); @@ -74,7 +73,7 @@ function doRelateNewTransaction(e) { var relateToId = target.data('relateto'); if (!target.checked) { var relateID = target.data('id'); - $.post('transactions/doRelate', {relateTo: relateToId, id: id}).success(function (data) { + $.post('related/relate/' + id + '/' + relateToId).success(function (data) { // success! target.parent().parent().remove(); getAlreadyRelatedTransactions(null, relateToId); @@ -91,7 +90,7 @@ function doRelateNewTransaction(e) { function getAlreadyRelatedTransactions(e, ID) { //#alreadyRelated - $.post('transactions/alreadyRelated/' + ID).success(function (data) { + $.get('related/alreadyRelated/' + ID).success(function (data) { $('#alreadyRelated').empty(); $.each(data, function (i, row) { var tr = $(''); diff --git a/server.php b/server.php index 5f187f3441..dfdf3bcd6b 100644 --- a/server.php +++ b/server.php @@ -11,7 +11,7 @@ $requested = $paths['public'].$uri; // This file allows us to emulate Apache's "mod_rewrite" functionality from the // built-in PHP web server. This provides a convenient way to test a Laravel // application without having installed a "real" web server software here. -if ($uri !== '/' and file_exists($requested)) +if ($uri !== '/' && file_exists($requested)) { return false; } diff --git a/tests/_bootstrap.php b/tests/_bootstrap.php index bc088a8f9e..2a9ae24d6c 100644 --- a/tests/_bootstrap.php +++ b/tests/_bootstrap.php @@ -1,21 +1,9 @@ tests/_data/dump.sql'); +$db = realpath(__DIR__ . '/_data') . '/db.sqlite'; +$dump = realpath(__DIR__ . '/_data') . '/dump.sql'; +if (!file_exists($db)) { + $out = []; + exec('touch ' . $db); + exec('php artisan migrate --seed --env=testing', $out); + exec('sqlite3 tests/_data/db.sqlite .dump > tests/_data/dump.sql', $out); } - -/** - * Class resetToClean - */ -class resetToClean -{ - /** - * - */ - static public function clean() - { - //exec('cp ' . realpath(__DIR__ . '/_data') . '/clean.sqlite ' . realpath(__DIR__ . '/_data') . '/testing.sqlite'); - } -} \ No newline at end of file diff --git a/tests/acceptance.suite.yml b/tests/acceptance.suite.yml index 407ab416ff..601e703cd6 100644 --- a/tests/acceptance.suite.yml +++ b/tests/acceptance.suite.yml @@ -7,4 +7,4 @@ class_name: AcceptanceTester modules: enabled: - - AcceptanceHelper \ No newline at end of file + - AcceptanceHelper diff --git a/tests/functional.suite.yml b/tests/functional.suite.yml index 6c67a707ca..d3effb537d 100644 --- a/tests/functional.suite.yml +++ b/tests/functional.suite.yml @@ -10,7 +10,11 @@ modules: config: Db: populate: false - cleanup: false + cleanup: true + dsn: 'sqlite:tests/_data/db.sqlite' + user: '' + password: '' + dump: tests/_data/dump.sql Laravel4: environment: 'testing' - filters: false \ No newline at end of file + filters: false diff --git a/tests/functional/AccountControllerCest.php b/tests/functional/AccountControllerCest.php index 6f63f66031..35ea055806 100644 --- a/tests/functional/AccountControllerCest.php +++ b/tests/functional/AccountControllerCest.php @@ -55,7 +55,6 @@ class AccountControllerCest $I->see('Delete account "Delete me"'); $I->submitForm('#destroy', []); $I->dontSeeRecord('accounts', ['id' => 3, 'deleted_at' => null]); - resetToClean::clean(); } /** @@ -68,6 +67,19 @@ class AccountControllerCest $I->see('Edit asset account "Delete me"'); } + /** + * @param FunctionalTester $I + */ + public function failUpdate(FunctionalTester $I) + { + $I->wantTo('update an asset account and fail'); + $I->amOnPage('/accounts/edit/3'); + $I->see('Edit asset account "Delete me"'); + $I->submitForm('#update', ['name' => '', 'what' => 'asset', 'account_role' => 'defaultExpense', 'post_submit_action' => 'update']); + $I->seeRecord('accounts', ['name' => 'Delete me']); + + } + /** * @param FunctionalTester $I */ @@ -100,22 +112,6 @@ class AccountControllerCest $I->see('Create a new asset account'); $I->submitForm('#store', ['name' => 'New through tests.', 'what' => 'asset', 'account_role' => 'defaultExpense', 'post_submit_action' => 'store']); $I->seeRecord('accounts', ['name' => 'New through tests.']); - resetToClean::clean(); - } - - /** - * @param FunctionalTester $I - */ - public function storeValidateOnly(FunctionalTester $I) - { - $I->amOnPage('/accounts/create/asset'); - $I->wantTo('validate a new asset account'); - $I->see('Create a new asset account'); - $I->submitForm( - '#store', ['name' => 'New through tests.', 'what' => 'asset', 'account_role' => 'defaultExpense', 'post_submit_action' => 'validate_only'] - ); - $I->dontSeeRecord('accounts', ['name' => 'New through tests.']); - resetToClean::clean(); } /** @@ -130,7 +126,6 @@ class AccountControllerCest '#store', ['name' => 'New through tests.', 'what' => 'asset', 'account_role' => 'defaultExpense', 'post_submit_action' => 'create_another'] ); $I->seeRecord('accounts', ['name' => 'New through tests.']); - resetToClean::clean(); } /** @@ -143,7 +138,20 @@ class AccountControllerCest $I->see('Create a new asset account'); $I->submitForm('#store', ['name' => null, 'what' => 'asset', 'account_role' => 'defaultExpense', 'post_submit_action' => 'validate_only']); $I->dontSeeRecord('accounts', ['name' => 'New through tests.']); - resetToClean::clean(); + } + + /** + * @param FunctionalTester $I + */ + public function storeValidateOnly(FunctionalTester $I) + { + $I->amOnPage('/accounts/create/asset'); + $I->wantTo('validate a new asset account'); + $I->see('Create a new asset account'); + $I->submitForm( + '#store', ['name' => 'New through tests.', 'what' => 'asset', 'account_role' => 'defaultExpense', 'post_submit_action' => 'validate_only'] + ); + $I->dontSeeRecord('accounts', ['name' => 'New through tests.']); } /** @@ -156,20 +164,21 @@ class AccountControllerCest $I->see('Edit asset account "Delete me"'); $I->submitForm('#update', ['name' => 'Update me', 'what' => 'asset', 'account_role' => 'defaultExpense', 'post_submit_action' => 'update']); $I->seeRecord('accounts', ['name' => 'Update me']); - resetToClean::clean(); } /** * @param FunctionalTester $I */ - public function failUpdate(FunctionalTester $I) + public function updateAndReturn(FunctionalTester $I) { - $I->wantTo('update an asset account and fail'); - $I->amOnPage('/accounts/edit/3'); - $I->see('Edit asset account "Delete me"'); - $I->submitForm('#update', ['name' => '', 'what' => 'asset', 'account_role' => 'defaultExpense', 'post_submit_action' => 'update']); - $I->seeRecord('accounts', ['name' => 'Delete me']); + $I->wantTo('update an asset account and return to form'); + $I->amOnPage('/accounts/edit/2'); + $I->see('Edit asset account "Savings account"'); + $I->submitForm( + '#update', ['name' => 'Savings accountXX', 'what' => 'asset', 'account_role' => 'defaultExpense', 'post_submit_action' => 'return_to_edit'] + ); + $I->seeRecord('accounts', ['name' => 'Savings accountXX']); } @@ -188,20 +197,4 @@ class AccountControllerCest } - /** - * @param FunctionalTester $I - */ - public function updateAndReturn(FunctionalTester $I) - { - $I->wantTo('update an asset account and return to form'); - $I->amOnPage('/accounts/edit/2'); - $I->see('Edit asset account "Savings account"'); - $I->submitForm( - '#update', ['name' => 'Savings accountXX', 'what' => 'asset', 'account_role' => 'defaultExpense', 'post_submit_action' => 'return_to_edit'] - ); - $I->seeRecord('accounts', ['name' => 'Savings accountXX']); - resetToClean::clean(); - - } - -} \ No newline at end of file +} diff --git a/tests/functional/BillControllerCest.php b/tests/functional/BillControllerCest.php new file mode 100644 index 0000000000..5347420f5a --- /dev/null +++ b/tests/functional/BillControllerCest.php @@ -0,0 +1,276 @@ +amLoggedAs(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james']); + } + + /** + * @param FunctionalTester $I + */ + public function create(FunctionalTester $I) + { + $I->wantTo('create a bill'); + $I->amOnPage('/bills/create'); + } + + /** + * @param FunctionalTester $I + */ + public function delete(FunctionalTester $I) + { + $bill = User::whereEmail('thegrumpydictator@gmail.com')->first()->bills()->first(); + $I->wantTo('delete a bill'); + $I->amOnPage('/bills/delete/' . $bill->id); + $I->see('Delete "' . $bill->name . '"'); + } + + /** + * @param FunctionalTester $I + */ + public function destroy(FunctionalTester $I) + { + $bill = User::whereEmail('thegrumpydictator@gmail.com')->first()->bills()->first(); + $I->wantTo('destroy a bill'); + $I->amOnPage('/bills/delete/' . $bill->id); + $I->see('Delete "' . $bill->name . '"'); + $I->submitForm('#destroy', []); + $I->see('The bill was deleted.'); + + } + + /** + * @param FunctionalTester $I + */ + public function edit(FunctionalTester $I) + { + $bill = User::whereEmail('thegrumpydictator@gmail.com')->first()->bills()->first(); + $I->wantTo('edit a bill'); + $I->amOnPage('/bills/edit/' . $bill->id); + $I->see($bill->name); + + + } + + /** + * @param FunctionalTester $I + */ + public function index(FunctionalTester $I) + { + $bill = User::whereEmail('thegrumpydictator@gmail.com')->first()->bills()->first(); + $I->wantTo('see all bills'); + $I->amOnPage('/bills'); + $I->see('Bills'); + $I->see($bill->name); + } + + /** + * @param FunctionalTester $I + */ + public function rescan(FunctionalTester $I) + { + $bill = User::whereEmail('thegrumpydictator@gmail.com')->first()->bills()->first(); + $I->wantTo('rescan a bill'); + $I->amOnPage('/bills/rescan/' . $bill->id); + $I->see('Rescanned everything.'); + } + + /** + * @param FunctionalTester $I + */ + public function rescanInactive(FunctionalTester $I) + { + $bill = User::whereEmail('thegrumpydictator@gmail.com')->first()->bills()->where('active', 0)->first(); + $I->wantTo('rescan an inactive bill'); + $I->amOnPage('/bills/rescan/' . $bill->id); + $I->see('Inactive bills cannot be scanned.'); + } + + /** + * @param FunctionalTester $I + */ + public function show(FunctionalTester $I) + { + $bill = User::whereEmail('thegrumpydictator@gmail.com')->first()->bills()->first(); + $I->wantTo('show a bill'); + $I->amOnPage('/bills/show/' . $bill->id); + $I->see($bill->name); + } + + /** + * @param FunctionalTester $I + */ + public function store(FunctionalTester $I) + { + $I->wantTo('store a bill'); + $I->amOnPage('/bills/create'); + $I->submitForm( + '#store', [ + 'name' => 'Some bill', + 'match' => 'one,two', + 'amount_min' => 10, + 'amount_max' => 20, + 'post_submit_action' => 'store', + 'date' => date('Y-m-d'), + 'repeat_freq' => 'monthly', + 'skip' => 0 + ] + ); + $I->see('Bill "Some bill" stored.'); + } + + /** + * @param FunctionalTester $I + */ + public function storeFail(FunctionalTester $I) + { + $I->wantTo('store a bill and fail'); + $I->amOnPage('/bills/create'); + $I->submitForm( + '#store', [ + 'name' => 'Some bill', + 'match' => '', + 'amount_min' => 10, + 'amount_max' => 20, + 'date' => date('Y-m-d'), + 'repeat_freq' => 'monthly', + 'skip' => 0 + ] + ); + $I->dontSeeInDatabase('bills', ['name' => 'Some bill']); + $I->see('Could not store bill'); + } + + /** + * @param FunctionalTester $I + */ + public function storeRecreate(FunctionalTester $I) + { + $I->wantTo('validate a bill and create another one'); + $I->amOnPage('/bills/create'); + $I->submitForm( + '#store', [ + 'name' => 'Some bill', + 'match' => 'one,two', + 'amount_min' => 10, + 'amount_max' => 20, + 'post_submit_action' => 'create_another', + 'date' => date('Y-m-d'), + 'repeat_freq' => 'monthly', + 'skip' => 0, + + ] + ); + $I->see('Bill "Some bill" stored.'); + } + + /** + * @param FunctionalTester $I + */ + public function storeValidate(FunctionalTester $I) + { + $I->wantTo('validate a bill'); + $I->amOnPage('/bills/create'); + $I->submitForm( + '#store', [ + 'name' => 'Some bill', + 'match' => 'one,two', + 'amount_min' => 10, + 'amount_max' => 20, + 'post_submit_action' => 'validate_only', + 'date' => date('Y-m-d'), + 'repeat_freq' => 'monthly', + 'skip' => 0, + + ] + ); + $I->see('form-group has-success has-feedback'); + } + + /** + * @param FunctionalTester $I + */ + public function update(FunctionalTester $I) + { + $bill = User::whereEmail('thegrumpydictator@gmail.com')->first()->bills()->first(); + $I->wantTo('update a bill'); + $I->amOnPage('/bills/edit/' . $bill->id); + $I->submitForm( + '#update', [ + 'name' => 'Some bill', + 'match' => 'bla,bla', + 'amount_min' => 10, + 'amount_max' => 20, + 'date' => date('Y-m-d'), + 'repeat_freq' => 'monthly', + 'skip' => 0 + ] + ); + $I->see('Bill "Some bill" updated.'); + } + + /** + * @param FunctionalTester $I + */ + public function updateFail(FunctionalTester $I) + { + $bill = User::whereEmail('thegrumpydictator@gmail.com')->first()->bills()->first(); + $I->wantTo('update a bill and fail'); + $I->amOnPage('/bills/edit/' . $bill->id); + $I->submitForm( + '#update', [ + 'name' => 'Some bill', + 'match' => '', + 'amount_min' => 10, + 'amount_max' => 20, + 'date' => date('Y-m-d'), + 'repeat_freq' => 'monthly', + 'skip' => 0 + ] + ); + $I->see('Could not update bill'); + } + + /** + * @param FunctionalTester $I + */ + public function updateReturn(FunctionalTester $I) + { + $bill = User::whereEmail('thegrumpydictator@gmail.com')->first()->bills()->first(); + $I->wantTo('update a bill and return to edit it'); + $I->amOnPage('/bills/edit/' . $bill->id); + $I->submitForm( + '#update', [ + 'name' => 'Some bill', + 'match' => 'bla,bla', + 'amount_min' => 10, + 'amount_max' => 20, + 'post_submit_action' => 'return_to_edit', + 'date' => date('Y-m-d'), + 'repeat_freq' => 'monthly', + 'skip' => 0 + ] + ); + $I->see('Bill "Some bill" updated.'); + } + +} diff --git a/tests/functional/BudgetControllerCest.php b/tests/functional/BudgetControllerCest.php index 2789345917..a81c7e0b33 100644 --- a/tests/functional/BudgetControllerCest.php +++ b/tests/functional/BudgetControllerCest.php @@ -82,6 +82,19 @@ class BudgetControllerCest $I->see('Edit budget "Delete me"'); } + /** + * @param FunctionalTester $I + */ + public function failUpdate(FunctionalTester $I) + { + $I->wantTo('update a budget and fail'); + $I->amOnPage('/budgets/edit/3'); + $I->see('Edit budget "Delete me"'); + $I->submitForm('#update', ['name' => '', 'post_submit_action' => 'update']); + $I->seeRecord('budgets', ['name' => 'Delete me']); + + } + /** * @param FunctionalTester $I */ @@ -135,19 +148,6 @@ class BudgetControllerCest $I->see('Create a new budget'); $I->submitForm('#store', ['name' => 'New budget.', 'post_submit_action' => 'store']); $I->seeRecord('budgets', ['name' => 'New budget.']); - resetToClean::clean(); - } - - /** - * @param FunctionalTester $I - */ - public function storeValidateOnly(FunctionalTester $I) - { - $I->amOnPage('/budgets/create'); - $I->wantTo('validate a new budget'); - $I->see('Create a new budget'); - $I->submitForm('#store', ['name' => 'New budget.', 'post_submit_action' => 'validate_only']); - $I->dontSeeRecord('budgets', ['name' => 'New budget.']); } /** @@ -170,10 +170,21 @@ class BudgetControllerCest $I->amOnPage('/budgets/create'); $I->wantTo('make storing a new budget fail.'); $I->see('Create a new budget'); - $I->submitForm('#store', ['name' => null, 'post_submit_action' => 'store']); + $I->submitForm('#store', ['name' => null, 'post_submit_action' => 'store']); $I->dontSeeRecord('budgets', ['name' => 'New budget.']); } + /** + * @param FunctionalTester $I + */ + public function storeValidateOnly(FunctionalTester $I) + { + $I->amOnPage('/budgets/create'); + $I->wantTo('validate a new budget'); + $I->see('Create a new budget'); + $I->submitForm('#store', ['name' => 'New budget.', 'post_submit_action' => 'validate_only']); + $I->dontSeeRecord('budgets', ['name' => 'New budget.']); + } /** * @param FunctionalTester $I @@ -185,23 +196,34 @@ class BudgetControllerCest $I->see('Edit budget "Delete me"'); $I->submitForm('#update', ['name' => 'Update me', 'post_submit_action' => 'update']); $I->seeRecord('budgets', ['name' => 'Update me']); - resetToClean::clean(); } /** * @param FunctionalTester $I */ - public function failUpdate(FunctionalTester $I) + public function updateAndReturn(FunctionalTester $I) { - $I->wantTo('update a budget and fail'); + $I->wantTo('update a budget and return to form'); $I->amOnPage('/budgets/edit/3'); $I->see('Edit budget "Delete me"'); - $I->submitForm('#update', ['name' => '', 'post_submit_action' => 'update']); - $I->seeRecord('budgets', ['name' => 'Delete me']); + $I->submitForm( + '#update', ['name' => 'Savings accountXX', 'post_submit_action' => 'return_to_edit'] + ); + $I->seeRecord('budgets', ['name' => 'Savings accountXX']); } + /** + * @param FunctionalTester $I + */ + public function updateIncome(FunctionalTester $I) + { + $I->amOnPage('/budgets/income'); + $I->wantTo('update my monthly income'); + $I->see('Update (expected) income for '); + } + /** * @param FunctionalTester $I */ @@ -217,29 +239,4 @@ class BudgetControllerCest $I->seeRecord('budgets', ['name' => 'Delete me']); } - - /** - * @param FunctionalTester $I - */ - public function updateAndReturn(FunctionalTester $I) - { - $I->wantTo('update a budget and return to form'); - $I->amOnPage('/budgets/edit/3'); - $I->see('Edit budget "Delete me"'); - $I->submitForm( - '#update', ['name' => 'Savings accountXX', 'post_submit_action' => 'return_to_edit'] - ); - $I->seeRecord('budgets', ['name' => 'Savings accountXX']); - - } - - /** - * @param FunctionalTester $I - */ - public function updateIncome(FunctionalTester $I) - { - $I->amOnPage('/budgets/income'); - $I->wantTo('update my monthly income'); - $I->see('Update (expected) income for '); - } -} \ No newline at end of file +} diff --git a/tests/functional/CategoryControllerCest.php b/tests/functional/CategoryControllerCest.php index 85db3e03f3..3a7b5d10ba 100644 --- a/tests/functional/CategoryControllerCest.php +++ b/tests/functional/CategoryControllerCest.php @@ -65,6 +65,19 @@ class CategoryControllerCest $I->see('Edit category "Delete me"'); } + /** + * @param FunctionalTester $I + */ + public function failUpdate(FunctionalTester $I) + { + $I->wantTo('update a category and fail'); + $I->amOnPage('/categories/edit/4'); + $I->see('Edit category "Delete me"'); + $I->submitForm('#update', ['name' => '', 'post_submit_action' => 'update']); + $I->seeRecord('categories', ['name' => 'Delete me']); + + } + /** * @param FunctionalTester $I */ @@ -94,20 +107,6 @@ class CategoryControllerCest $I->see('Create a new category'); $I->submitForm('#store', ['name' => 'New category.', 'post_submit_action' => 'store']); $I->seeRecord('categories', ['name' => 'New category.']); - resetToClean::clean(); - } - - /** - * @param FunctionalTester $I - */ - public function storeValidateOnly(FunctionalTester $I) - { - $I->amOnPage('/categories/create'); - $I->wantTo('validate a new category'); - $I->see('Create a new category'); - $I->submitForm('#store', ['name' => 'New category.', 'post_submit_action' => 'validate_only']); - $I->dontSeeRecord('categories', ['name' => 'New category.']); - resetToClean::clean(); } /** @@ -120,7 +119,6 @@ class CategoryControllerCest $I->see('Create a new category'); $I->submitForm('#store', ['name' => 'New category.', 'post_submit_action' => 'create_another']); $I->seeRecord('categories', ['name' => 'New category.']); - resetToClean::clean(); } /** @@ -131,10 +129,22 @@ class CategoryControllerCest $I->amOnPage('/categories/create'); $I->wantTo('make storing a new category fail.'); $I->see('Create a new category'); - $I->submitForm('#store', ['name' => null, 'post_submit_action' => 'validate_only']); + $I->submitForm('#store', ['name' => null, 'post_submit_action' => 'validate_only']); $I->dontSeeRecord('categories', ['name' => 'New category.']); - resetToClean::clean(); } + + /** + * @param FunctionalTester $I + */ + public function storeValidateOnly(FunctionalTester $I) + { + $I->amOnPage('/categories/create'); + $I->wantTo('validate a new category'); + $I->see('Create a new category'); + $I->submitForm('#store', ['name' => 'New category.', 'post_submit_action' => 'validate_only']); + $I->dontSeeRecord('categories', ['name' => 'New category.']); + } + /** * @param FunctionalTester $I */ @@ -145,20 +155,21 @@ class CategoryControllerCest $I->see('Edit category "Delete me"'); $I->submitForm('#update', ['name' => 'Update me', 'post_submit_action' => 'update']); $I->seeRecord('categories', ['name' => 'Update me']); - resetToClean::clean(); } /** * @param FunctionalTester $I */ - public function failUpdate(FunctionalTester $I) + public function updateAndReturn(FunctionalTester $I) { - $I->wantTo('update a category and fail'); + $I->wantTo('update a category and return to form'); $I->amOnPage('/categories/edit/4'); $I->see('Edit category "Delete me"'); - $I->submitForm('#update', ['name' => '', 'post_submit_action' => 'update']); - $I->seeRecord('categories', ['name' => 'Delete me']); + $I->submitForm( + '#update', ['name' => 'Savings accountXX', 'post_submit_action' => 'return_to_edit'] + ); + $I->seeRecord('categories', ['name' => 'Savings accountXX']); } @@ -178,19 +189,4 @@ class CategoryControllerCest } - /** - * @param FunctionalTester $I - */ - public function updateAndReturn(FunctionalTester $I) - { - $I->wantTo('update a category and return to form'); - $I->amOnPage('/categories/edit/4'); - $I->see('Edit category "Delete me"'); - $I->submitForm( - '#update', ['name' => 'Savings accountXX', 'post_submit_action' => 'return_to_edit'] - ); - $I->seeRecord('categories', ['name' => 'Savings accountXX']); - - } - -} \ No newline at end of file +} diff --git a/tests/functional/CurrencyControllerCest.php b/tests/functional/CurrencyControllerCest.php index 0f59b4136f..168fffc5cb 100644 --- a/tests/functional/CurrencyControllerCest.php +++ b/tests/functional/CurrencyControllerCest.php @@ -35,14 +35,24 @@ class CurrencyControllerCest $I->see('Create a new currency'); } + /** + * @param FunctionalTester $I + */ + public function defaultCurrency(FunctionalTester $I) + { + $I->wantTo('make US Dollar the default currency'); + $I->amOnPage('/currency/default/2'); + $I->see('US Dollar is now the default currency.'); + } + /** * @param FunctionalTester $I */ public function delete(FunctionalTester $I) { $I->wantTo('delete a currency'); - $I->amOnPage('/currency/delete/2'); - $I->see('Delete currency "US Dollar"'); + $I->amOnPage('/currency/delete/3'); + $I->see('Delete currency "Hungarian forint"'); } /** @@ -51,20 +61,10 @@ class CurrencyControllerCest public function destroy(FunctionalTester $I) { $I->wantTo('destroy a currency'); - $I->amOnPage('/currency/delete/2'); - $I->see('Delete currency "US Dollar"'); + $I->amOnPage('/currency/delete/3'); + $I->see('Delete currency "Hungarian forint"'); $I->submitForm('#destroy', []); - $I->see('Currency "US Dollar" deleted'); - } - - /** - * @param FunctionalTester $I - */ - public function defaultCurrency(FunctionalTester $I) - { - $I->wantTo('make US Dollar the default currency'); - $I->amOnPage('/currency/default/2'); - $I->see('US Dollar is now the default currency.'); + $I->see('Currency "Hungarian forint" deleted'); } /** @@ -87,6 +87,19 @@ class CurrencyControllerCest $I->see('Edit currency "US Dollar"'); } + /** + * @param FunctionalTester $I + */ + public function failUpdate(FunctionalTester $I) + { + $I->wantTo('update a currency and fail'); + $I->amOnPage('/currency/edit/2'); + $I->see('Edit currency "US Dollar"'); + $I->submitForm('#update', ['name' => 'Failed update', 'code' => '123', 'post_submit_action' => 'update']); + $I->dontSeeRecord('transaction_currencies', ['name' => 'Failed update']); + + } + /** * @param FunctionalTester $I */ @@ -155,34 +168,6 @@ class CurrencyControllerCest $I->see('Edit currency "US Dollar"'); $I->submitForm('#update', ['name' => 'Successful update', 'symbol' => '$', 'code' => 'USD', 'post_submit_action' => 'update']); $I->seeRecord('transaction_currencies', ['name' => 'Successful update']); - resetToClean::clean(); - - } - - /** - * @param FunctionalTester $I - */ - public function failUpdate(FunctionalTester $I) - { - $I->wantTo('update a currency and fail'); - $I->amOnPage('/currency/edit/2'); - $I->see('Edit currency "US Dollar"'); - $I->submitForm('#update', ['name' => 'Failed update', 'code' => '123', 'post_submit_action' => 'update']); - $I->dontSeeRecord('transaction_currencies', ['name' => 'Failed update']); - - } - - /** - * @param FunctionalTester $I - */ - public function validateUpdateOnly(FunctionalTester $I) - { - $I->wantTo('update a currency and validate only'); - $I->amOnPage('/currency/edit/2'); - $I->see('Edit currency "US Dollar"'); - $I->submitForm('#update', ['name' => 'Update Validate Only', 'post_submit_action' => 'validate_only']); - $I->dontSeeRecord('transaction_currencies', ['name' => 'Update Validate Only']); - $I->seeRecord('transaction_currencies', ['name' => 'US Dollar']); } @@ -200,4 +185,18 @@ class CurrencyControllerCest $I->seeRecord('transaction_currencies', ['name' => 'US DollarXXX']); } -} \ No newline at end of file + + /** + * @param FunctionalTester $I + */ + public function validateUpdateOnly(FunctionalTester $I) + { + $I->wantTo('update a currency and validate only'); + $I->amOnPage('/currency/edit/2'); + $I->see('Edit currency "US Dollar"'); + $I->submitForm('#update', ['name' => 'Update Validate Only', 'post_submit_action' => 'validate_only']); + $I->dontSeeRecord('transaction_currencies', ['name' => 'Update Validate Only']); + $I->seeRecord('transaction_currencies', ['name' => 'US Dollar']); + + } +} diff --git a/tests/functional/GoogleChartControllerCest.php b/tests/functional/GoogleChartControllerCest.php index 468ac29683..578204b153 100644 --- a/tests/functional/GoogleChartControllerCest.php +++ b/tests/functional/GoogleChartControllerCest.php @@ -26,20 +26,20 @@ class GoogleChartControllerCest /** * @param FunctionalTester $I */ - public function accountBalanceChart(FunctionalTester $I) + public function accountAllBalanceChart(FunctionalTester $I) { - $I->wantTo('see the session balance chart of an account.'); - $I->amOnPage('chart/account/1/session'); + $I->wantTo('see the complete balance chart of an account.'); + $I->amOnPage('chart/account/1/all'); $I->seeResponseCodeIs(200); } /** * @param FunctionalTester $I */ - public function accountAllBalanceChart(FunctionalTester $I) + public function accountBalanceChart(FunctionalTester $I) { - $I->wantTo('see the complete balance chart of an account.'); - $I->amOnPage('chart/account/1/all'); + $I->wantTo('see the session balance chart of an account.'); + $I->amOnPage('chart/account/1/session'); $I->seeResponseCodeIs(200); } @@ -73,6 +73,26 @@ class GoogleChartControllerCest $I->seeResponseCodeIs(200); } + /** + * @param FunctionalTester $I + */ + public function billOverview(FunctionalTester $I) + { + $I->wantTo('see the chart for the history of a bill'); + $I->amOnPage('/chart/bills/1'); + $I->seeResponseCodeIs(200); + } + + /** + * @param FunctionalTester $I + */ + public function billsOverview(FunctionalTester $I) + { + $I->wantTo('see the chart for which bills I have yet to pay'); + $I->amOnPage('/chart/home/bills'); + $I->seeResponseCodeIs(200); + } + /** * @param FunctionalTester $I */ @@ -88,8 +108,9 @@ class GoogleChartControllerCest */ public function budgetsAndSpending(FunctionalTester $I) { + $year = date('Y'); $I->wantTo('see the chart for a budget in a specific year'); - $I->amOnPage('/chart/budget/1/spending/2014'); + $I->amOnPage('/chart/budget/1/spending/'.$year); $I->seeResponseCodeIs(200); } @@ -109,8 +130,9 @@ class GoogleChartControllerCest */ public function categoriesAndSpending(FunctionalTester $I) { + $year = date('Y'); $I->wantTo('see the chart for a category in a specific year'); - $I->amOnPage('/chart/category/1/spending/2014'); + $I->amOnPage('/chart/category/1/spending/'.$year); $I->seeResponseCodeIs(200); } @@ -125,43 +147,23 @@ class GoogleChartControllerCest $I->see('Invalid year'); } + /** + * @param FunctionalTester $I + */ + public function emptyBillOverview(FunctionalTester $I) + { + $I->wantTo('see the chart for the history of an empty bill'); + $I->amOnPage('/chart/bills/2'); + $I->seeResponseCodeIs(200); + } + /** * @param FunctionalTester $I */ public function piggyBankHistory(FunctionalTester $I) { $I->wantTo('see the chart for the history of a piggy bank'); - $I->amOnPage('/chart/piggyhistory/1'); - $I->seeResponseCodeIs(200); - } - - /** - * @param FunctionalTester $I - */ - public function recurringOverview(FunctionalTester $I) - { - $I->wantTo('see the chart for the history of a recurring transaction'); - $I->amOnPage('/chart/recurring/1'); - $I->seeResponseCodeIs(200); - } - - /** - * @param FunctionalTester $I - */ - public function emptyRecurringOverview(FunctionalTester $I) - { - $I->wantTo('see the chart for the history of an empty recurring transaction'); - $I->amOnPage('/chart/recurring/2'); - $I->seeResponseCodeIs(200); - } - - /** - * @param FunctionalTester $I - */ - public function recurringTransactionsOverview(FunctionalTester $I) - { - $I->wantTo('see the chart for which recurring transactions I have yet to pay'); - $I->amOnPage('/chart/home/recurring'); + $I->amOnPage('/chart/piggy_history/1'); $I->seeResponseCodeIs(200); } @@ -208,4 +210,4 @@ class GoogleChartControllerCest } -} \ No newline at end of file +} diff --git a/tests/functional/HelpControllerCest.php b/tests/functional/HelpControllerCest.php index b728147027..a8bb6c2d66 100644 --- a/tests/functional/HelpControllerCest.php +++ b/tests/functional/HelpControllerCest.php @@ -49,6 +49,18 @@ class HelpControllerCest } + /** + * @param FunctionalTester $I + */ + public function showHelpEmptyHelpFile(FunctionalTester $I) + { + $I->wantTo('show help for a route with no text.'); + $I->amOnPage('/help/transactions.doRelate'); + $I->canSeeResponseCodeIs(200); + $I->see('There is no help for this route'); + + } + /** * @param FunctionalTester $I */ @@ -60,6 +72,7 @@ class HelpControllerCest $I->see('There is no help for this route'); } + // /** * @param FunctionalTester $I @@ -73,4 +86,4 @@ class HelpControllerCest } -} \ No newline at end of file +} diff --git a/tests/functional/HomeControllerCest.php b/tests/functional/HomeControllerCest.php index c48de4a0e4..176351aa98 100644 --- a/tests/functional/HomeControllerCest.php +++ b/tests/functional/HomeControllerCest.php @@ -45,6 +45,25 @@ class HomeControllerCest $I->see('Firefly'); } + /** + * @param FunctionalTester $I + */ + public function indexWithPrefs(FunctionalTester $I) + { + \Preference::whereName('frontPageAccounts')->delete(); + \Preference::create( + [ + 'user_id' => 1, + 'name' => 'frontPageAccounts', + 'data' => [1,2] + ] + ); + $I->wantTo('see the home page of Firefly using pre-set accounts'); + $I->amOnPage('/'); + $I->canSeeResponseCodeIs(200); + $I->see('Firefly'); + } + /** * @param FunctionalTester $I */ @@ -75,4 +94,4 @@ class HomeControllerCest $I->amOnPage('/prev'); $I->canSeeResponseCodeIs(200); } -} \ No newline at end of file +} diff --git a/tests/functional/JsonControllerCest.php b/tests/functional/JsonControllerCest.php index 6aee764604..907d6cf724 100644 --- a/tests/functional/JsonControllerCest.php +++ b/tests/functional/JsonControllerCest.php @@ -53,4 +53,4 @@ class JsonControllerCest $I->amOnPage('/json/revenue-accounts'); $I->canSeeResponseCodeIs(200); } -} \ No newline at end of file +} diff --git a/tests/functional/PiggyBankControllerCest.php b/tests/functional/PiggyBankControllerCest.php index 136eb6cbd7..fc00a93005 100644 --- a/tests/functional/PiggyBankControllerCest.php +++ b/tests/functional/PiggyBankControllerCest.php @@ -5,7 +5,7 @@ * @SuppressWarnings("CamelCase") * @SuppressWarnings("short") * - * Class PiggybankControllerCest + * Class PiggyBankControllerCest */ class PiggyBankControllerCest { @@ -30,7 +30,7 @@ class PiggyBankControllerCest public function add(FunctionalTester $I) { $I->wantTo('add money to a piggy bank'); - $I->amOnPage('/piggybanks/add/1'); + $I->amOnPage('/piggy_banks/add/1'); $I->see('Add money to New camera'); } @@ -40,7 +40,7 @@ class PiggyBankControllerCest public function create(FunctionalTester $I) { $I->wantTo('create a piggy bank'); - $I->amOnPage('/piggybanks/create'); + $I->amOnPage('/piggy_banks/create'); $I->see('Create new piggy bank'); } @@ -50,8 +50,9 @@ class PiggyBankControllerCest public function delete(FunctionalTester $I) { $I->wantTo('delete a piggy bank'); - $I->amOnPage('/piggybanks/delete/1'); + $I->amOnPage('/piggy_banks/delete/1'); $I->see('Delete "New camera"'); + } /** @@ -60,10 +61,11 @@ class PiggyBankControllerCest public function destroy(FunctionalTester $I) { $I->wantTo('destroy a piggy bank'); - $I->amOnPage('/piggybanks/delete/1'); + $I->amOnPage('/piggy_banks/delete/1'); $I->see('Delete "New camera"'); $I->submitForm('#destroy', []); $I->see('Piggy bank "New camera" deleted.'); + } /** @@ -72,7 +74,7 @@ class PiggyBankControllerCest public function edit(FunctionalTester $I) { $I->wantTo('edit a piggy bank'); - $I->amOnPage('/piggybanks/edit/1'); + $I->amOnPage('/piggy_banks/edit/1'); $I->see('Edit piggy bank "New camera"'); } @@ -82,7 +84,7 @@ class PiggyBankControllerCest public function editWithTargetDate(FunctionalTester $I) { $I->wantTo('edit a piggy bank with a target date'); - $I->amOnPage('/piggybanks/edit/2'); + $I->amOnPage('/piggy_banks/edit/2'); $I->see('Edit piggy bank "New clothes"'); } @@ -92,7 +94,7 @@ class PiggyBankControllerCest public function index(FunctionalTester $I) { $I->wantTo('view all piggy banks'); - $I->amOnPage('/piggybanks'); + $I->amOnPage('/piggy_banks'); $I->see('Piggy banks'); $I->see('New camera'); } @@ -103,8 +105,22 @@ class PiggyBankControllerCest public function postAdd(FunctionalTester $I) { $I->wantTo('process adding money to a piggy bank'); - $I->amOnPage('/piggybanks/add/1'); + $I->amOnPage('/piggy_banks/add/1'); $I->see('Add money to New camera'); + $I->submitForm('#add', ['amount' => 100]); + $I->see(',00 to "New camera".'); + } + + /** + * @param FunctionalTester $I + */ + public function postAddTooMuch(FunctionalTester $I) + { + $I->wantTo('try to add too much money to a piggy bank'); + $I->amOnPage('/piggy_banks/add/1'); + $I->see('Add money to New camera'); + $I->submitForm('#add', ['amount' => 100000]); + $I->see(',00 to "New camera".'); } /** @@ -113,17 +129,40 @@ class PiggyBankControllerCest public function postRemove(FunctionalTester $I) { $I->wantTo('process removing money from a piggy bank'); - $I->amOnPage('/piggybanks/remove/1'); + $I->amOnPage('/piggy_banks/add/1'); + $I->see('Add money to New camera'); + $I->submitForm('#add', ['amount' => 100]); + $I->see(',00 to "New camera".'); + $I->amOnPage('/piggy_banks/remove/1'); $I->see('Remove money from New camera'); + $I->submitForm('#remove', ['amount' => 50]); + $I->see(',00 from "New camera".'); } + /** + * @param FunctionalTester $I + */ + public function postRemoveFail(FunctionalTester $I) + { + $I->wantTo('process removing too much money from a piggy bank'); + $I->amOnPage('/piggy_banks/add/1'); + $I->see('Add money to New camera'); + $I->submitForm('#add', ['amount' => 100]); + $I->see(',00 to "New camera".'); + $I->amOnPage('/piggy_banks/remove/1'); + $I->see('Remove money from New camera'); + $I->submitForm('#remove', ['amount' => 500]); + $I->see(',00 from "New camera".'); + } + + /** * @param FunctionalTester $I */ public function remove(FunctionalTester $I) { $I->wantTo('removing money from a piggy bank'); - $I->amOnPage('/piggybanks/remove/1'); + $I->amOnPage('/piggy_banks/remove/1'); $I->see('Remove money from New camera'); } @@ -133,7 +172,7 @@ class PiggyBankControllerCest public function show(FunctionalTester $I) { $I->wantTo('view a piggy bank'); - $I->amOnPage('/piggybanks/show/1'); + $I->amOnPage('/piggy_banks/show/1'); $I->see('New camera'); } @@ -143,8 +182,59 @@ class PiggyBankControllerCest public function store(FunctionalTester $I) { $I->wantTo('store a new piggy bank'); - $I->amOnPage('/piggybanks/create'); + $I->amOnPage('/piggy_banks/create'); $I->see('Create new piggy bank'); + $I->submitForm( + '#store', ['name' => 'Some new piggy bank', + 'rep_every' => 0, + 'reminder_skip' => 0, + 'remind_me' => 0, + 'order' => 3, + 'account_id' => 1, 'targetamount' => 1000] + ); + $I->see('Piggy bank "Some new piggy bank" stored.'); + } + + /** + * @param FunctionalTester $I + */ + public function storeAndReturn(FunctionalTester $I) + { + $I->wantTo('store a new piggy bank and return'); + $I->amOnPage('/piggy_banks/create'); + $I->see('Create new piggy bank'); + $I->submitForm( + '#store', ['name' => 'Some new piggy bank', + 'rep_every' => 0, + 'reminder_skip' => 0, + 'post_submit_action' => 'create_another', + 'remind_me' => 0, + 'order' => 3, + 'account_id' => 1, + 'targetamount' => 1000] + ); + $I->see('Piggy bank "Some new piggy bank" stored.'); + } + + /** + * @param FunctionalTester $I + */ + public function storeFail(FunctionalTester $I) + { + $I->wantTo('fail storing a new piggy bank'); + $I->amOnPage('/piggy_banks/create'); + $I->see('Create new piggy bank'); + $I->submitForm( + '#store', ['name' => null, + 'rep_every' => 0, + 'reminder_skip' => 0, + 'remind_me' => 0, + 'order' => 3, + 'account_id' => 1, + 'post_submit_action' => 'store', + 'targetamount' => 1000] + ); + $I->see('The name field is required.'); } /** @@ -153,8 +243,90 @@ class PiggyBankControllerCest public function update(FunctionalTester $I) { $I->wantTo('update a piggy bank'); - $I->amOnPage('/piggybanks/edit/1'); + $I->amOnPage('/piggy_banks/edit/1'); $I->see('Edit piggy bank "New camera"'); + $I->submitForm( + '#update', [ + 'name' => 'Updated camera', + 'account_id' => 2, + 'targetamount' => 2000, + 'targetdate' => '', + 'reminder' => 'week', + 'post_submit_action' => 'update', + ] + ); + $I->see('Piggy bank "Updated camera" updated.'); + + } -} \ No newline at end of file + /** + * @param FunctionalTester $I + */ + public function updateAndReturn(FunctionalTester $I) + { + $I->wantTo('update a piggy bank and return'); + $I->amOnPage('/piggy_banks/edit/1'); + $I->see('Edit piggy bank "New camera"'); + $I->submitForm( + '#update', [ + 'name' => 'Updated camera', + 'account_id' => 2, + 'targetamount' => 2000, + 'targetdate' => '', + 'reminder' => 'week', + 'post_submit_action' => 'return_to_edit', + ] + ); + $I->see('Piggy bank "Updated camera" updated.'); + + + } + + /** + * @param FunctionalTester $I + */ + public function updateFail(FunctionalTester $I) + { + $I->wantTo('update a piggy bank and fail'); + $I->amOnPage('/piggy_banks/edit/1'); + $I->see('Edit piggy bank "New camera"'); + $I->submitForm( + '#update', [ + 'name' => '', + 'account_id' => 2, + 'targetamount' => 2000, + 'targetdate' => '', + 'reminder' => 'week', + 'post_submit_action' => 'update', + ] + ); + $I->see('The name field is required.'); + $I->seeInDatabase('piggy_banks', ['name' => 'New camera']); + + } + + /** + * @param FunctionalTester $I + */ + public function updateValidateOnly(FunctionalTester $I) + { + $I->wantTo('validate a piggy bank'); + $I->amOnPage('/piggy_banks/edit/1'); + $I->see('Edit piggy bank "New camera"'); + $I->submitForm( + '#update', [ + 'name' => 'Updated camera', + 'account_id' => 2, + 'targetamount' => 2000, + 'targetdate' => '', + 'reminder' => 'week', + 'post_submit_action' => 'validate_only', + ] + ); + $I->see('Updated camera'); + + + } + +} diff --git a/tests/functional/PreferencesControllerCest.php b/tests/functional/PreferencesControllerCest.php new file mode 100644 index 0000000000..44080b93d6 --- /dev/null +++ b/tests/functional/PreferencesControllerCest.php @@ -0,0 +1,48 @@ +amLoggedAs(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james']); + } + + /** + * @param FunctionalTester $I + */ + public function index(FunctionalTester $I) + { + $I->wantTo('see my current set of preferences'); + $I->amOnPage('/preferences'); + $I->see('Preferences'); + } + + /** + * @param FunctionalTester $I + */ + public function postIndex(FunctionalTester $I) + { + $I->wantTo('want to update my preferences'); + $I->amOnPage('/preferences'); + $I->see('Preferences'); + $I->submitForm('#preferences', []); + $I->see('Preferences saved!'); + } +} diff --git a/tests/functional/ProfileControllerCest.php b/tests/functional/ProfileControllerCest.php new file mode 100644 index 0000000000..7f6c980d20 --- /dev/null +++ b/tests/functional/ProfileControllerCest.php @@ -0,0 +1,150 @@ +amLoggedAs(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james']); + } + + /** + * @param FunctionalTester $I + */ + public function changePassword(FunctionalTester $I) + { + $I->wantTo('change my password.'); + $I->amOnPage('/profile/change-password'); + $I->see('thegrumpydictator@gmail.com'); + $I->see('Change your password'); + } + + /** + * @param FunctionalTester $I + */ + public function index(FunctionalTester $I) + { + $I->wantTo('see my profile options'); + $I->amOnPage('/profile'); + $I->see('thegrumpydictator@gmail.com'); + $I->see('Profile'); + } + + /** + * @param FunctionalTester $I + */ + public function postChangePassword(FunctionalTester $I) + { + $I->wantTo('submit a new password.'); + $I->amOnPage('/profile/change-password'); + $I->see('thegrumpydictator@gmail.com'); + $I->see('Change your password'); + $I->submitForm( + '#change-password', [ + 'old' => 'james', + 'new1' => 'James', + 'new2' => 'James' + ] + ); + $I->see('Password changed!'); + } + + /** + * @param FunctionalTester $I + */ + public function postChangePasswordInvalidCurrent(FunctionalTester $I) + { + $I->wantTo('submit a new password and enter the wrong current password.'); + $I->amOnPage('/profile/change-password'); + $I->see('thegrumpydictator@gmail.com'); + $I->see('Change your password'); + + $I->submitForm( + '#change-password', [ + 'old' => 'Blablabla', + 'new1' => 'James', + 'new2' => 'James' + ] + ); + $I->see('Invalid current password!'); + } + + /** + * @param FunctionalTester $I + */ + public function postChangePasswordNoMatch(FunctionalTester $I) + { + $I->wantTo('submit a new password but make a mistake in filling it in twice.'); + $I->amOnPage('/profile/change-password'); + $I->see('thegrumpydictator@gmail.com'); + $I->see('Change your password'); + + $I->submitForm( + '#change-password', [ + 'old' => 'james', + 'new1' => 'blabla', + 'new2' => 'bla' + ] + ); + $I->see('New passwords do not match!'); + } + + /** + * @param FunctionalTester $I + */ + public function postChangePasswordNoNewPassword(FunctionalTester $I) + { + $I->wantTo('submit a new password and forget to fill in a new one.'); + $I->amOnPage('/profile/change-password'); + $I->see('thegrumpydictator@gmail.com'); + $I->see('Change your password'); + + $I->submitForm( + '#change-password', [ + 'old' => 'james', + 'new1' => '', + 'new2' => '' + ] + ); + $I->see('Do fill in a password!'); + + } + + /** + * @param FunctionalTester $I + */ + public function postChangePasswordToSame(FunctionalTester $I) + { + $I->wantTo('submit a new password but fill in my old one twice.'); + $I->amOnPage('/profile/change-password'); + $I->see('thegrumpydictator@gmail.com'); + $I->see('Change your password'); + + $I->submitForm( + '#change-password', [ + 'old' => 'james', + 'new1' => 'james', + 'new2' => 'james' + ] + ); + $I->see('The idea is to change your password.'); + } + + +} diff --git a/tests/functional/RelatedControllerCest.php b/tests/functional/RelatedControllerCest.php new file mode 100644 index 0000000000..629ee5e975 --- /dev/null +++ b/tests/functional/RelatedControllerCest.php @@ -0,0 +1,99 @@ +amLoggedAs(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james']); + + } + + public function alreadyRelated(FunctionalTester $I) + { + $group = TransactionGroup::first(); + $journal = $group->transactionjournals()->first(); + + $I->wantTo('see already related transactions'); + $I->amOnPage('/related/alreadyRelated/' . $journal->id); + $I->see('Big expense in '); + + } + + public function alreadyRelatedNoRelations(FunctionalTester $I) + { + $journal = TransactionJournal::first(); + + $I->wantTo('see already related transactions for a journal without any'); + $I->amOnPage('/related/alreadyRelated/' . $journal->id); + $I->see('[]'); + + } + + public function relate(FunctionalTester $I) + { + $journal = TransactionJournal::leftJoin( + 'transaction_group_transaction_journal', 'transaction_journals.id', '=', 'transaction_group_transaction_journal.transaction_journal_id' + ) + ->whereNull('transaction_group_transaction_journal.transaction_group_id')->first(['transaction_journals.*']); + $otherJournal = TransactionJournal::leftJoin( + 'transaction_group_transaction_journal', 'transaction_journals.id', '=', 'transaction_group_transaction_journal.transaction_journal_id' + ) + ->whereNull('transaction_group_transaction_journal.transaction_group_id')->where( + 'transaction_journals.id', '!=', $journal->id + )->first( + ['transaction_journals.*'] + ); + $I->wantTo('relate two journals'); + $I->sendAjaxPostRequest('/related/relate/' . $journal->id . '/' . $otherJournal->id); + $I->see('true'); + } + + public function related(FunctionalTester $I) + { + $group = TransactionGroup::first(); + $journal = $group->transactionjournals()->first(); + + $I->wantTo('see the popup with already related transactions'); + $I->amOnPage('/related/related/' . $journal->id); + $I->see('Big expense in '); + } + + public function removeRelation(FunctionalTester $I) + { + $group = TransactionGroup::first(); + $one = $group->transactionjournals[0]; + $two = $group->transactionjournals[1]; + $I->wantTo('relate two journals'); + $I->amOnPage('/related/removeRelation/' . $one->id . '/' . $two->id); + $I->see('true'); + + } + + public function search(FunctionalTester $I) + { + $group = TransactionGroup::first(); + $one = $group->transactionjournals[0]; + + $I->wantTo('search for a transaction to relate'); + + $I->sendAjaxPostRequest('/related/search/' . $one->id . '?searchValue=expense'); + $I->see('Big expense in'); + } +} \ No newline at end of file diff --git a/tests/functional/ReminderControllerCest.php b/tests/functional/ReminderControllerCest.php new file mode 100644 index 0000000000..139e4e279b --- /dev/null +++ b/tests/functional/ReminderControllerCest.php @@ -0,0 +1,86 @@ +amLoggedAs(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james']); + } + + /** + * @param FunctionalTester $I + */ + public function act(FunctionalTester $I) + { + $reminder = Reminder::leftJoin('piggy_banks', 'piggy_banks.id', '=', 'reminders.remindersable_id')->where('piggy_banks.reminder','!=','')->first( + ['reminders.*'] + ); + + $I->wantTo('act on a reminder'); + $I->amOnPage('/reminders/' . $reminder->id . '/act'); + $I->see('Money for Nieuwe spullen'); + } + + /** + * @param FunctionalTester $I + */ + public function actOnInvalid(FunctionalTester $I) + { + $I->wantTo('act on an invalid reminder'); + $I->amOnPage('/reminders/2/act'); + $I->see('This reminder has an invalid class connected to it.'); + } + + /** + * @param FunctionalTester $I + */ + public function dismiss(FunctionalTester $I) + { + $I->wantTo('dismiss a reminder'); + $I->amOnPage('/reminders/1/dismiss'); + $I->see('Reminder dismissed'); + } + + /** + * @param FunctionalTester $I + */ + public function notNow(FunctionalTester $I) + { + $I->wantTo('ignore a reminder'); + $I->amOnPage('/reminders/1/notNow'); + $I->see('Reminder dismissed'); + } + + /** + * @param FunctionalTester $I + */ + public function show(FunctionalTester $I) + { + $reminder = Reminder::leftJoin('piggy_banks', 'piggy_banks.id', '=', 'reminders.remindersable_id')->where('piggy_banks.reminder','!=','')->first( + ['reminders.*'] + ); + + $I->wantTo('see a reminder'); + $I->amOnPage('/reminders/'.$reminder->id); + $I->see('A reminder about'); + $I->see('your piggy bank labelled "Nieuwe spullen"'); + } + +} diff --git a/tests/functional/RepeatedExpenseControllerCest.php b/tests/functional/RepeatedExpenseControllerCest.php new file mode 100644 index 0000000000..58d2392ee2 --- /dev/null +++ b/tests/functional/RepeatedExpenseControllerCest.php @@ -0,0 +1,244 @@ +amLoggedAs(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james']); + } + + /** + * @param FunctionalTester $I + */ + public function create(FunctionalTester $I) + { + $I->wantTo('create a repeated expense'); + $I->amOnPage('/repeatedexpenses/create'); + $I->see('Create new repeated expense'); + } + + /** + * @param FunctionalTester $I + */ + public function delete(FunctionalTester $I) + { + $repeatedExpense = PiggyBank::where('repeats', 1)->first(); + $I->wantTo('delete a repeated expense'); + $I->amOnPage('/repeatedexpenses/delete/' . $repeatedExpense->id); + $I->see('Delete "' . $repeatedExpense->name . '"'); + } + + /** + * @param FunctionalTester $I + */ + public function destroy(FunctionalTester $I) + { + $repeatedExpense = PiggyBank::where('repeats', 1)->first(); + $I->wantTo('destroy a repeated expense'); + $I->amOnPage('/repeatedexpenses/delete/' . $repeatedExpense->id); + $I->submitForm('#destroy', []); + $I->see('Repeated expense "' . $repeatedExpense->name . '" deleted.'); + } + + /** + * @param FunctionalTester $I + */ + public function edit(FunctionalTester $I) + { + $repeatedExpense = PiggyBank::where('repeats', 1)->first(); + $I->wantTo('edit a repeated expense'); + $I->amOnPage('/repeatedexpenses/edit/' . $repeatedExpense->id); + $I->see('Edit repeated expense "' . $repeatedExpense->name . '"'); + + } + + /** + * @param FunctionalTester $I + */ + public function index(FunctionalTester $I) + { + $repeatedExpense = PiggyBank::where('repeats', 1)->first(); + $I->wantTo('see all repeated expenses'); + $I->amOnPage('/repeatedexpenses'); + $I->see('Overview'); + $I->see($repeatedExpense->name); + } + + /** + * @param FunctionalTester $I + */ + public function show(FunctionalTester $I) + { + $repeatedExpense = PiggyBank::where('repeats', 1)->first(); + $I->wantTo('view a repeated expense'); + $I->amOnPage('/repeatedexpenses/show/' . $repeatedExpense->id); + $I->see($repeatedExpense->name); + } + + /** + * @param FunctionalTester $I + */ + public function store(FunctionalTester $I) + { + $I->wantTo('store a repeated expense'); + $I->amOnPage('/repeatedexpenses/create'); + $I->submitForm( + '#store', [ + 'name' => 'TestRepeatedExpense', + 'account_id' => 1, + 'targetamount' => 1000, + 'targetdate' => Carbon::now()->format('Y-m-d'), + 'rep_length' => 'month', + 'rep_every' => 0, + 'rep_times' => 0, + 'remind_me' => 1, + 'reminder' => 'month', + 'post_submit_action' => 'store', + ] + ); + + $I->see('Piggy bank "TestRepeatedExpense" stored.'); + } + + /** + * @param FunctionalTester $I + */ + public function storeAndReturn(FunctionalTester $I) + { + $I->wantTo('store a repeated expense and return'); + $I->amOnPage('/repeatedexpenses/create'); + $I->submitForm( + '#store', [ + 'name' => 'TestRepeatedExpense', + 'account_id' => 1, + 'targetamount' => 1000, + 'targetdate' => Carbon::now()->format('Y-m-d'), + 'rep_length' => 'month', + 'rep_every' => 0, + 'rep_times' => 0, + 'remind_me' => 1, + 'reminder' => 'month', + 'post_submit_action' => 'create_another', + ] + ); + + $I->see('Piggy bank "TestRepeatedExpense" stored.'); + } + + /** + * @param FunctionalTester $I + */ + public function storeFail(FunctionalTester $I) + { + $I->wantTo('store a repeated expense and fail'); + $I->amOnPage('/repeatedexpenses/create'); + $I->submitForm( + '#store', [ + 'name' => '', + 'account_id' => 1, + 'targetamount' => 1000, + 'targetdate' => Carbon::now()->format('Y-m-d'), + 'rep_length' => 'month', + 'rep_every' => 0, + 'rep_times' => 0, + 'remind_me' => 1, + 'reminder' => 'month', + 'post_submit_action' => 'store', + ] + ); + + $I->see('Could not store repeated expense: The name field is required.'); + } + + /** + * @param FunctionalTester $I + */ + public function update(FunctionalTester $I) + { + $repeatedExpense = PiggyBank::where('repeats', 1)->first(); + $I->wantTo('update a repeated expense'); + $I->amOnPage('/repeatedexpenses/edit/' . $repeatedExpense->id); + $I->submitForm( + '#update', [ + 'name' => $repeatedExpense->name . '!', + 'account_id' => 2, + 'targetamount' => 1000.00, + 'targetdate' => $repeatedExpense->targetdate->format('Y-m-d'), + 'rep_length' => 'month', + 'rep_every' => 0, + 'rep_times' => 0, + 'remind_me' => 1, + 'reminder' => 'month', + 'post_submit_action' => 'update', + ] + ); + $I->see('Repeated expense "' . $repeatedExpense->name . '!" updated.'); + } + + /** + * @param FunctionalTester $I + */ + public function updateAndReturnToEdit(FunctionalTester $I) + { + $repeatedExpense = PiggyBank::where('repeats', 1)->first(); + $I->wantTo('update a repeated expense and return to edit screen'); + $I->amOnPage('/repeatedexpenses/edit/' . $repeatedExpense->id); + $I->submitForm( + '#update', [ + 'name' => $repeatedExpense->name . '!', + 'account_id' => 2, + 'targetamount' => 1000.00, + 'targetdate' => $repeatedExpense->targetdate->format('Y-m-d'), + 'rep_length' => 'month', + 'rep_every' => 0, + 'rep_times' => 0, + 'remind_me' => 1, + 'reminder' => 'month', + 'post_submit_action' => 'return_to_edit', + ] + ); + $I->see('Repeated expense "' . $repeatedExpense->name . '!" updated.'); + } + + /** + * @param FunctionalTester $I + */ + public function updateFail(FunctionalTester $I) + { + $repeatedExpense = PiggyBank::where('repeats', 1)->first(); + $I->wantTo('try to update a repeated expense and fail'); + $I->amOnPage('/repeatedexpenses/edit/' . $repeatedExpense->id); + $I->submitForm( + '#update', [ + 'name' => '', + 'account_id' => 2, + 'targetamount' => 1000.00, + 'targetdate' => '2014-12-30', + 'rep_length' => 'month', + 'rep_every' => 0, + 'rep_times' => 0, + 'remind_me' => 1, + 'reminder' => 'month', + 'post_submit_action' => 'update', + ] + ); + $I->see('The name field is required.'); + } +} diff --git a/tests/functional/ReportControllerCest.php b/tests/functional/ReportControllerCest.php new file mode 100644 index 0000000000..cd1a546a19 --- /dev/null +++ b/tests/functional/ReportControllerCest.php @@ -0,0 +1,79 @@ +amLoggedAs(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james']); + } + + public function budget(FunctionalTester $I) + { + $I->wantTo('see a budget report'); + $I->amOnPage('/reports/budget/2014/9'); + $I->see('Budget report for September 2014'); + } + + public function budgetInvalidDate(FunctionalTester $I) + { + $I->wantTo('see a budget report for an invalid date'); + $I->amOnPage('/reports/budget/XXXX/XX'); + $I->see('Invalid date'); + } + + public function index(FunctionalTester $I) + { + $I->wantTo('see all possible reports'); + $I->amOnPage('/reports'); + $I->see('Reports'); + $I->see('Monthly reports'); + $I->see('Budget reports'); + } + + public function month(FunctionalTester $I) + { + $I->wantTo('see a monthly report'); + $I->amOnPage('/reports/2014/9'); + $I->see('Report for September 2014'); + } + + public function monthInvalidDate(FunctionalTester $I) + { + $I->wantTo('see a monthly report for an invalid month'); + $I->amOnPage('/reports/XXXX/XX'); + $I->see('Invalid date'); + } + + public function year(FunctionalTester $I) + { + $I->wantTo('see a yearly report'); + $I->amOnPage('/reports/2014'); + $I->see('Income vs. expenses'); + $I->see('Account balance'); + } + + public function yearInvalidDate(FunctionalTester $I) + { + $I->wantTo('see a yearly report for an invalid year'); + $I->amOnPage('/reports/XXXX'); + $I->see('Invalid date'); + } + +} diff --git a/tests/functional/SearchControllerCest.php b/tests/functional/SearchControllerCest.php new file mode 100644 index 0000000000..8b8341f59b --- /dev/null +++ b/tests/functional/SearchControllerCest.php @@ -0,0 +1,39 @@ +amLoggedAs(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james']); + } + + public function index(FunctionalTester $I) + { + $I->wantTo('search for "salary"'); + $I->amOnPage('/search?q=salary'); + $I->see('Transactions'); + $I->see('Results for "salary"'); + + } + + public function indexNoQuery(FunctionalTester $I) + { + $I->wantTo('Search for empty string'); + $I->amOnPage('/search?q='); + $I->see('Search for ""'); + + } +} diff --git a/tests/functional/TransactionControllerCest.php b/tests/functional/TransactionControllerCest.php new file mode 100644 index 0000000000..54e337305b --- /dev/null +++ b/tests/functional/TransactionControllerCest.php @@ -0,0 +1,235 @@ +amLoggedAs(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james']); + } + + public function create(FunctionalTester $I) + { + $I->wantTo('create a transaction'); + $I->amOnPage('/transactions/create/withdrawal?account_id=1'); + $I->see('Add a new withdrawal'); + } + + public function deleteWithdrawal(FunctionalTester $I) + { + $journal = TransactionJournal::where('description', 'LIKE', '%Rent for %')->first(); + $I->wantTo('delete a transaction'); + $I->amOnPage('/transaction/delete/' . $journal->id); + $I->see('Delete withdrawal "' . $journal->description . '"'); + } + + public function destroyDeposit(FunctionalTester $I) + { + $journal = TransactionJournal::where('description', 'LIKE', '%Salary for %')->first(); + $I->wantTo('destroy a deposit'); + $I->amOnPage('/transaction/delete/' . $journal->id); + $I->submitForm('#destroy', []); + $I->see('Transaction "' . $journal->description . '" destroyed.'); + + } + + public function destroyTransfer(FunctionalTester $I) + { + $I->wantTo('destroy a transfer'); + + $journal = TransactionJournal::where('description', 'LIKE', '%Money for big expense in%')->first(); + + $I->amOnPage('/transaction/delete/' . $journal->id); + $I->submitForm('#destroy', []); + $I->see('Transaction "' . $journal->description . '" destroyed.'); + + } + + public function destroyWithdrawal(FunctionalTester $I) + { + $journal = TransactionJournal::where('description', 'LIKE', '%Rent for %')->first(); + $I->wantTo('destroy a withdrawal'); + $I->amOnPage('/transaction/delete/' . $journal->id); + $I->submitForm('#destroy', []); + $I->see('Transaction "' . $journal->description . '" destroyed.'); + + } + + public function edit(FunctionalTester $I) + { + $journal = TransactionJournal::whereDescription('Money for piggy')->first(); + $I->wantTo('edit a transaction'); + $I->amOnPage('/transaction/edit/' . $journal->id); + $I->see('Edit transfer "Money for piggy"'); + } + + public function index(FunctionalTester $I) + { + $I->wantTo('see all withdrawals'); + $I->amOnPage('/transactions/withdrawal'); + $I->see('Expenses'); + } + + public function indexExpenses(FunctionalTester $I) + { + $I->wantTo('see all expenses'); + $I->amOnPage('/transactions/deposit'); + $I->see('Revenue, income and deposits'); + } + + public function indexTransfers(FunctionalTester $I) + { + $I->wantTo('see all transfers'); + $I->amOnPage('/transactions/transfers'); + $I->see('Transfers'); + } + + public function show(FunctionalTester $I) + { + $journal = TransactionJournal::where('description', 'LIKE', '%Rent for %')->first(); + + $I->wantTo('see a transaction'); + $I->amOnPage('/transaction/show/' . $journal->id); + $I->see($journal->description); + $I->see(intval($journal->getAmount())); + } + + public function store(FunctionalTester $I) + { + $I->wantTo('store a transaction'); + $I->amOnPage('/transactions/create/withdrawal'); + $I->submitForm( + '#store', [ + 'reminder' => '', + 'description' => 'Test', + 'account_id' => 1, + 'expense_account' => 'Zomaar', + 'amount' => 100, + 'date' => '2014-12-30', + 'budget_id' => 3, + 'category' => 'Categorrr', + 'post_submit_action' => 'store' + ] + ); + $I->see('Transaction "Test" stored.'); + } + + public function storeAndFail(FunctionalTester $I) + { + $I->wantTo('store a transaction and fail'); + $I->amOnPage('/transactions/create/withdrawal'); + $I->submitForm( + '#store', [ + 'reminder' => '', + 'description' => '', + 'account_id' => 1, + 'expense_account' => 'Zomaar', + 'amount' => 100, + 'date' => '2014-12-30', + 'budget_id' => 3, + 'category' => 'Categorrr', + 'post_submit_action' => 'store' + ] + ); + $I->see('Could not store transaction: The description field is required.'); + } + + public function storeAndReturn(FunctionalTester $I) + { + $I->wantTo('store a transaction'); + $I->amOnPage('/transactions/create/withdrawal'); + $I->submitForm( + '#store', [ + 'reminder' => '', + 'description' => 'Test', + 'account_id' => 1, + 'expense_account' => 'Zomaar', + 'amount' => 100, + 'date' => '2014-12-30', + 'budget_id' => 3, + 'category' => 'Categorrr', + 'post_submit_action' => 'create_another' + ] + ); + $I->see('Transaction "Test" stored.'); + } + + public function update(FunctionalTester $I) + { + $journal = TransactionJournal::where('description', 'LIKE', '%Salary for %')->first(); + + $I->wantTo('update a transaction'); + $I->amOnPage('/transaction/edit/' . $journal->id); + $I->see($journal->description); + $I->submitForm( + '#update', [ + 'description' => $journal->description . '!', + 'account_id' => 1, + 'expense_account' => 'Portaal', + 'amount' => 500, + 'date' => $journal->date->format('Y-m-d'), + 'budget_id' => is_null($journal->budgets()->first()) ? 0 : $journal->budgets()->first()->id, + 'category' => is_null($journal->categories()->first()) ? '' : $journal->categories()->first()->id, + 'post_submit_action' => 'update' + ] + ); + $I->see($journal->description . '!'); + } + + public function updateAndFail(FunctionalTester $I) + { + $journal = TransactionJournal::where('description', 'LIKE', '%Salary for %')->first(); + + $I->wantTo('update a transaction and fail'); + $I->amOnPage('/transaction/edit/' . $journal->id); + $I->see($journal->description); + $I->submitForm( + '#update', [ + 'description' => '', + 'account_id' => 1, + 'expense_account' => 'Portaal', + 'amount' => 500, + 'date' => '2014-01-01', + 'budget_id' => 2, + 'category' => 'House', + 'post_submit_action' => 'update' + ] + ); + $I->see('Could not update transaction: The description field is required.'); + } + + public function updateAndReturn(FunctionalTester $I) + { + $journal = TransactionJournal::where('description', 'LIKE', '%Salary for %')->first(); + $I->wantTo('update a transaction and return to the edit screen'); + $I->amOnPage('/transaction/edit/' . $journal->id); + $I->see($journal->description); + $I->submitForm( + '#update', [ + 'description' => $journal->description . '!', + 'account_id' => 1, + 'expense_account' => 'Portaal', + 'amount' => 500, + 'date' => $journal->date->format('Y-m-d'), + 'budget_id' => is_null($journal->budgets()->first()) ? 0 : $journal->budgets()->first()->id, + 'category' => is_null($journal->categories()->first()) ? '' : $journal->categories()->first()->id, + 'post_submit_action' => 'return_to_edit' + ] + ); + $I->see($journal->description . '!'); + } + + +} diff --git a/tests/functional/UserControllerCest.php b/tests/functional/UserControllerCest.php index 06050c1bb6..a9a5141632 100644 --- a/tests/functional/UserControllerCest.php +++ b/tests/functional/UserControllerCest.php @@ -53,18 +53,11 @@ class UserControllerCest */ public function logout(FunctionalTester $I) { + $I->amLoggedAs(['email' => 'thegrumpydictator@gmail.com', 'password' => 'james']); $I->wantTo('logout'); - #$I->amOnPage('/logout'); - #$I->am - } - - /** - * @param FunctionalTester $I - */ - public function postLogin(FunctionalTester $I) - { - $I->wantTo('post login'); - $I->amOnRoute('login'); + $I->amOnPage('/'); + $I->click('Logout'); + $I->see('Firefly III — Sign In'); } /** @@ -72,14 +65,23 @@ class UserControllerCest */ public function postRegister(FunctionalTester $I) { - // @codingStandardsIgnoreStart $I->wantTo('post-register a new account'); $I->amOnPage('/register'); - $token = $I->grabValueFrom('input[name=_token]'); - $I->submitForm('#register', ['email' => 'noreply@gmail.com', '_token' => $token]); - $I->see('Password sent!'); + $I->submitForm('#register', ['email' => 'noreply@gmail.com']); + $I->see('You\'re about to get an e-mail. Please follow its instructions.'); $I->seeRecord('users', ['email' => 'noreply@gmail.com']); - // @codingStandardsIgnoreEnd + } + + /** + * @param FunctionalTester $I + */ + public function postRegisterFail(FunctionalTester $I) + { + $I->wantTo('post-register a new account and fail'); + $I->amOnPage('/register'); + $I->submitForm('#register', ['email' => 'XXxxxxx']); + $I->see('Input invalid, please try again: The email must be a valid email address.'); + $I->dontseeRecord('users', ['email' => 'XXxxxxx']); } /** @@ -88,7 +90,20 @@ class UserControllerCest public function postRemindme(FunctionalTester $I) { $I->wantTo('get a password reminder'); - $I->amOnRoute('remindme'); + $I->amOnRoute('remindMe'); + $I->submitForm('#remindMe', ['email' => 'functional@example.com']); + $I->see('You\'re about to get an e-mail.'); + } + + /** + * @param FunctionalTester $I + */ + public function postRemindmeFail(FunctionalTester $I) + { + $I->wantTo('get a password reminder and fail'); + $I->amOnRoute('remindMe'); + $I->submitForm('#remindMe', ['email' => 'abcdee']); + $I->see('No good!'); } /** @@ -105,10 +120,21 @@ class UserControllerCest /** * @param FunctionalTester $I */ - public function remindme(FunctionalTester $I) + public function remindMe(FunctionalTester $I) { $I->wantTo('reminded of my password'); - $I->amOnRoute('remindme'); + $I->amOnRoute('remindMe'); + $I->see('Firefly III — Reset your password'); + } + + /** + * @param FunctionalTester $I + */ + public function resetFail(FunctionalTester $I) + { + $I->wantTo('reset my password and fail'); + $I->amOnPage('/reset/123'); + $I->see('No reset code found!'); } /** @@ -117,7 +143,8 @@ class UserControllerCest public function reset(FunctionalTester $I) { $I->wantTo('reset my password'); - $I->amOnRoute('reset'); + $I->amOnPage('/reset/okokokokokokokokokokokokokokokok'); + $I->see('You\'re about to get an e-mail.'); } -} \ No newline at end of file +} diff --git a/tests/functional/_bootstrap.php b/tests/functional/_bootstrap.php index 8a88555806..e489e45b9e 100644 --- a/tests/functional/_bootstrap.php +++ b/tests/functional/_bootstrap.php @@ -1,2 +1,8 @@ tests/_data/dump.sql', $out); +} diff --git a/tests/unit/AccountTest.php b/tests/unit/AccountTest.php new file mode 100644 index 0000000000..16145d8932 --- /dev/null +++ b/tests/unit/AccountTest.php @@ -0,0 +1,40 @@ +updateMeta('field', 'value'); + $this->assertInstanceOf('AccountMeta', $newMeta); + $secondMeta = $account->updateMeta('field', 'newValue'); + $this->assertEquals($newMeta->id, $secondMeta->id); + $this->assertEquals($newMeta->data, 'value'); + $this->assertEquals($secondMeta->data, 'newValue'); + } + + public function testAccountUser() + { + $account = f::create('Account'); + $this->assertInstanceOf('Account', $account); + $this->assertInstanceOf('User', $account->user); + } + +} diff --git a/tests/unit/AccountTypeTest.php b/tests/unit/AccountTypeTest.php new file mode 100644 index 0000000000..94aede8b6a --- /dev/null +++ b/tests/unit/AccountTypeTest.php @@ -0,0 +1,27 @@ +assertCount(1, $account->accountType()->first()->accounts()->get()); + } + +} diff --git a/tests/unit/BudgetTest.php b/tests/unit/BudgetTest.php new file mode 100644 index 0000000000..88321ee974 --- /dev/null +++ b/tests/unit/BudgetTest.php @@ -0,0 +1,26 @@ +assertInstanceOf('User', $budget->user); + + } +} diff --git a/tests/unit/PiggyBankRepetitionTest.php b/tests/unit/PiggyBankRepetitionTest.php new file mode 100644 index 0000000000..3bf35313e6 --- /dev/null +++ b/tests/unit/PiggyBankRepetitionTest.php @@ -0,0 +1,29 @@ +startdate; + $target = clone $repetition->targetdate; + + $this->assertCount(1, PiggyBankRepetition::starts($start)->get()); + $this->assertCount(1, PiggyBankRepetition::targets($target)->get()); + } +} diff --git a/tests/unit/PiggyBankTest.php b/tests/unit/PiggyBankTest.php new file mode 100644 index 0000000000..efe7210cc0 --- /dev/null +++ b/tests/unit/PiggyBankTest.php @@ -0,0 +1,27 @@ +reminders()->save($reminder); + $this->assertCount(1, $piggyBank->reminders()->get()); + } +} diff --git a/tests/unit/ReminderTest.php b/tests/unit/ReminderTest.php new file mode 100644 index 0000000000..6a792ff9c4 --- /dev/null +++ b/tests/unit/ReminderTest.php @@ -0,0 +1,38 @@ +startdate; + $end = clone $reminder->enddate; + $this->assertCount(1, Reminder::dateIs($start, $end)->get()); + + } + + public function testUser() + { + $user = f::create('User'); + $reminder = f::create('Reminder'); + $reminder->user_id = $user->id; + $reminder->save(); + + $this->assertEquals($reminder->user->id, $user->id); + } +} diff --git a/tests/unit/TransactionGroupTest.php b/tests/unit/TransactionGroupTest.php new file mode 100644 index 0000000000..9c3b72272b --- /dev/null +++ b/tests/unit/TransactionGroupTest.php @@ -0,0 +1,25 @@ +assertEquals($group->user_id, $group->user->id); + } +} diff --git a/tests/unit/TransactionJournalTest.php b/tests/unit/TransactionJournalTest.php new file mode 100644 index 0000000000..863c87cff8 --- /dev/null +++ b/tests/unit/TransactionJournalTest.php @@ -0,0 +1,33 @@ +transactions()->save($transaction); + $journal->transactions()->save($other); + + $amount = floatval($transaction->amount); + $amount--; + + $this->assertCount(1, TransactionJournal::moreThan($amount)->get()); + } +} diff --git a/tests/unit/TransactionTest.php b/tests/unit/TransactionTest.php new file mode 100644 index 0000000000..f154d5130e --- /dev/null +++ b/tests/unit/TransactionTest.php @@ -0,0 +1,67 @@ +assertCount(1, Transaction::accountIs($transaction->account)->get()); + } + + public function testDateAfter() + { + $transaction = f::create('Transaction'); + $date = clone $transaction->transactionJournal->date; + $date->subDay(); + + $this->assertCount(1, Transaction::after($date)->get()); + } + + public function testDateBefore() + { + $transaction = f::create('Transaction'); + $date = clone $transaction->transactionJournal->date; + $date->addDay(); + + $this->assertCount(1, Transaction::before($date)->get()); + } + + public function testLessThan() + { + $transaction = f::create('Transaction'); + $amount = floatval($transaction->amount); + $amount++; + $this->assertCount(1, Transaction::lessThan($amount)->get()); + } + + public function testMoreThan() + { + $transaction = f::create('Transaction'); + $amount = floatval($transaction->amount); + $amount--; + $this->assertCount(1, Transaction::moreThan($amount)->get()); + } + + public function testTransactionTypes() + { + $transaction = f::create('Transaction'); + $type = $transaction->transactionJournal->transactionType->type; + $this->assertCount(1, Transaction::transactionTypes([$type])->get()); + } +} diff --git a/tests/unit/TransactionTypeTest.php b/tests/unit/TransactionTypeTest.php new file mode 100644 index 0000000000..d2b4033d69 --- /dev/null +++ b/tests/unit/TransactionTypeTest.php @@ -0,0 +1,30 @@ +transactionType; + $this->assertCount(1, $type->transactionJournals()->get()); + } + + +} diff --git a/tests/unit/UserTest.php b/tests/unit/UserTest.php new file mode 100644 index 0000000000..8a1b60a65f --- /dev/null +++ b/tests/unit/UserTest.php @@ -0,0 +1,34 @@ +assertEquals($pref->user_id, $pref->user->id); + } + + public function testReminder() + { + $reminder = f::create('Reminder'); + $this->assertEquals($reminder->user_id, $reminder->user->id); + } + +}
    Amount{{mf($t->amount)}}{{Amount::formatTransaction($t)}}
    New balance{{mf($t->before)}} → {{mf($t->after)}}{{Amount::format($t->before)}} → {{Amount::format($t->after)}}