Merge branch 'release/3.2.2'

This commit is contained in:
James Cole 2015-01-02 12:53:44 +01:00
commit 3e28e9a016
289 changed files with 7936 additions and 4591 deletions

View File

@ -1,3 +1,3 @@
src_dir: .
coverage_clover: tests/_output/coverage.xml
json_path: tests/_output/coveralls-upload.json
json_path: tests/_output/coveralls-upload.json

4
.gitignore vendored
View File

@ -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

View File

@ -13,4 +13,4 @@ script:
- php vendor/bin/codecept run --coverage --coverage-xml
after_script:
- php vendor/bin/coveralls
- php vendor/bin/coveralls

View File

@ -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)!
Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)!

View File

@ -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));
}
);
}
);

View File

@ -1,8 +1,6 @@
<?php
use Illuminate\Console\Command;
//use Symfony\Component\Console\Input\InputArgument;
//use Symfony\Component\Console\Input\InputOption;
/**
* Class Cleanup
@ -43,7 +41,7 @@ class Cleanup extends Command
$this->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...');

View File

@ -1,4 +1,4 @@
local/
laptop/
vagrant/
production/
production/

View File

@ -1,3 +1,3 @@
<?php
return [];
return [];

View File

@ -1,4 +1,4 @@
<?php
return [
'import' => ''
];
];

View File

@ -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'
],
];
];

View File

@ -12,4 +12,4 @@ return [
*/
'debug' => true,
'log_level' => 'debug',
];
];

View File

@ -34,4 +34,4 @@ return [
],
];
];

0
app/config/queue.php Executable file → Normal file
View File

View File

@ -1,2 +1,2 @@
<?php
return ['log_level' => 'debug',];
return ['log_level' => 'debug',];

View File

@ -9,4 +9,4 @@ return [
]
]
];
];

View File

@ -0,0 +1,2 @@
<?php
return ['log_level' => 'debug',];

View File

@ -0,0 +1,8 @@
<?php
return [
'verify_mail' => false,
'verify_reset' => true,
'allow_register' => true
];

View File

@ -0,0 +1,3 @@
<?php
return ['driver' => 'array',];

View File

@ -0,0 +1,12 @@
<?php
return [
'default' => 'sqlite',
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => ''
]
]
];

View File

@ -0,0 +1,13 @@
<?php
return [
'driver' => 'smtp',
'host' => '',
'port' => 587,
'from' => ['address' => '', 'name' => 'Firefly III'],
'encryption' => 'tls',
'username' => '',
'password' => '',
'sendmail' => '/usr/sbin/sendmail -bs',
'pretend' => true,
];

View File

@ -0,0 +1,3 @@
<?php
return ['driver' => 'array',];

View File

@ -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']);
}
}
}

View File

@ -0,0 +1,212 @@
<?php
use FireflyIII\Database\Bill\Bill as Repository;
use FireflyIII\Exception\FireflyException;
/**
*
* @SuppressWarnings("CamelCase") // I'm fine with this.
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
* @SuppressWarnings("NPathComplexity")
* Class BillController
*
*/
class BillController extends BaseController
{
/** @var Repository */
protected $_repository;
/**
* @param Repository $repository
*/
public function __construct(Repository $repository)
{
$this->_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']);
}
}

View File

@ -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') {

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -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());
}
}
}

View File

@ -1,6 +1,8 @@
<?php
/**
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
*
* Class HelpController
*/
class HelpController extends BaseController
@ -15,10 +17,10 @@ class HelpController extends BaseController
$helpText = '<p>There is no help for this route!</p>';
$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 = '<p>There is no help for this route.</p>';
\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 = '<p>There is no help for this route.</p>';
}
$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]);
}
}
}

View File

@ -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('/');
}
}
}

View File

@ -62,4 +62,4 @@ class JsonController extends BaseController
return Response::json($return);
}
}
}

View File

@ -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']);
}
}
}

View File

@ -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');
}
}
}

View File

@ -1,6 +1,8 @@
<?php
/**
* @SuppressWarnings("CyclomaticComplexity") // It's all 5. So ok.
*
* Class ProfileController
*/
class ProfileController extends BaseController
@ -64,4 +66,4 @@ class ProfileController extends BaseController
return Redirect::route('profile');
}
}
}

View File

@ -1,227 +0,0 @@
<?php
use FireflyIII\Exception\FireflyException;
use Illuminate\Support\MessageBag;
/**
* Class RecurringController
*
*/
class RecurringController extends BaseController
{
/**
*
*/
public function __construct()
{
View::share('title', 'Recurring transactions');
View::share('mainTitleIcon', 'fa-rotate-right');
}
/**
* @return $this
*/
public function create()
{
$periods = \Config::get('firefly.periods_to_text');
return View::make('recurring.create')->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;
}
}
}

View File

@ -0,0 +1,139 @@
<?php
use FireflyIII\Helper\Related\RelatedInterface;
use Illuminate\Support\Collection;
/**
* Class RelatedController
*/
class RelatedController extends BaseController
{
protected $_repository;
public function __construct(RelatedInterface $repository)
{
$this->_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());
}
}

View File

@ -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'));
}
}
}

View File

@ -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']);
}
}
}

View File

@ -1,34 +1,60 @@
<?php
use Carbon\Carbon;
use FireflyIII\Database\Account\Account as AccountRepository;
use FireflyIII\Database\TransactionJournal\TransactionJournal as TransactionJournalRepository;
use FireflyIII\Report\ReportInterface as Report;
/**
*
* @SuppressWarnings("CamelCase") // I'm fine with this.
*
* Class ReportController
*/
class ReportController extends BaseController
{
/** @var AccountRepository */
protected $_accounts;
/** @var \FireflyIII\Database\Budget\Budget */
protected $_budgets;
/** @var TransactionJournalRepository */
protected $_journals;
/** @var Report */
protected $_repository;
/**
* @param AccountRepository $accounts
* @param TransactionJournalRepository $journals
* @param Report $repository
*/
public function __construct(AccountRepository $accounts, TransactionJournalRepository $journals, Report $repository)
public function __construct(TransactionJournalRepository $journals, Report $repository)
{
$this->_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
);
}
}
}

View File

@ -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);
}
}
}

View File

@ -1,11 +1,19 @@
<?php
use FireflyIII\Database\TransactionJournal\TransactionJournal as Repository;
use FireflyIII\Exception\FireflyException;
use FireflyIII\Helper\TransactionJournal\HelperInterface as Helper;
use Illuminate\Support\Collection;
use Illuminate\Support\MessageBag;
/**
*
* @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.
* @SuppressWarnings("TooManyMethods") // I'm also fine with this.
* @SuppressWarnings("ExcessiveClassComplexity")
*
* Class TransactionController
*
*/
@ -13,54 +21,25 @@ class TransactionController extends BaseController
{
/** @var Helper */
protected $_helper;
/** @var Repository */
protected $_repository;
/**
* Construct a new transaction controller with two of the most often used helpers.
*
* @param Repository $repository
* @param Helper $helper
*/
public function __construct()
public function __construct(Repository $repository, Helper $helper)
{
$this->_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']);
}
}
}

View File

@ -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!');
}
}
}

View File

@ -1,6 +1,7 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* Class CreateSessionTable
@ -27,11 +28,11 @@ class CreateSessionTable extends Migration
public function up()
{
Schema::create(
'sessions', function ($t) {
$t->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');
}
);
}

View File

@ -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');
}
);
}

View File

@ -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` = "&#8364;", `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');
// }
}

View File

@ -0,0 +1,168 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* Class ChangesForV322
*/
class ChangesForV322 extends Migration
{
/**
*
*/
public function down()
{
// rename tables:
Schema::rename('piggy_bank_repetitions', 'piggybank_repetitions');
Schema::rename('piggy_banks', 'piggybanks');
// rename fields
Schema::table(
'piggy_bank_events', function (Blueprint $table) {
$table->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');
}
);
}
}

View File

@ -38,4 +38,4 @@ class AccountTypeSeeder extends Seeder
}
}
}

View File

@ -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]);
}
}
}
}

View File

@ -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;
}
}
/**
* @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);
}
}

View File

@ -12,6 +12,7 @@ class TransactionCurrencySeeder extends Seeder
TransactionCurrency::create(['code' => 'EUR','name' => 'Euro','symbol' => '&#8364;']);
TransactionCurrency::create(['code' => 'USD','name' => 'US Dollar','symbol' => '$']);
TransactionCurrency::create(['code' => 'HUF','name' => 'Hungarian forint','symbol' => 'Ft']);
}
}
}

View File

@ -17,4 +17,4 @@ class TransactionTypeSeeder extends Seeder
TransactionType::create(['type' => 'Opening balance']);
}
}
}

View File

@ -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');
}
}
);

View File

@ -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']
);
}
}
}

View File

@ -26,6 +26,6 @@ interface ChartInterface
*
* @return Collection
*/
public function getRecurringSummary(Carbon $start, Carbon $end);
public function getBillsSummary(Carbon $start, Carbon $end);
}
}

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -91,4 +91,4 @@ interface AccountInterface
* @return bool
*/
public function storeInitialBalance(\Account $account, array $data);
}
}

View File

@ -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;
}
}
}

View File

@ -1,11 +1,11 @@
<?php
namespace FireflyIII\Database\RecurringTransaction;
namespace FireflyIII\Database\Bill;
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;
@ -13,11 +13,11 @@ use Illuminate\Support\Collection;
use Illuminate\Support\MessageBag;
/**
* Class Recurring
* Class Bill
*
* @package FireflyIII\Database
*/
class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransactionInterface
class Bill implements CUDInterface, CommonDatabaseCallsInterface, BillInterface
{
use SwitchUser;
@ -48,30 +48,30 @@ class RecurringTransaction implements CUD, CommonDatabaseCalls, RecurringTransac
*/
public function store(array $data)
{
$recurring = new \RecurringTransaction;
$recurring->user()->associate($this->getUser());
$recurring->name = $data['name'];
$recurring->match = $data['match'];
$recurring->amount_max = floatval($data['amount_max']);
$recurring->amount_min = floatval($data['amount_min']);
$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;
}
}
}

View File

@ -0,0 +1,55 @@
<?php
namespace FireflyIII\Database\Bill;
use Carbon\Carbon;
/**
* Interface BillInterface
*
* @package FireflyIII\Database
*/
interface BillInterface
{
/**
* @param \Bill $bill
* @param Carbon $start
* @param Carbon $end
*
* @return null|\TransactionJournal
* @internal param Carbon $current
* @internal param Carbon $currentEnd
*
*/
public function getJournalForBillInRange(\Bill $bill, Carbon $start, Carbon $end);
/**
* @param \Bill $bill
*
* @return Carbon|null
*/
public function lastFoundMatch(\Bill $bill);
/**
* @param \Bill $bill
*
* @return Carbon|null
*/
public function nextExpectedMatch(\Bill $bill);
/**
* @param \Bill $bill
* @param \TransactionJournal $journal
*
* @return bool
*/
public function scan(\Bill $bill, \TransactionJournal $journal);
/**
* @param \Bill $bill
*
* @return bool
*/
public function scanEverything(\Bill $bill);
}

View File

@ -2,21 +2,22 @@
namespace FireflyIII\Database\Budget;
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;
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Support\Collection;
use Illuminate\Support\MessageBag;
use Illuminate\Database\Query\Builder;
/**
* Class Budget
*
* @package FireflyIII\Database
*/
class Budget implements CUD, CommonDatabaseCalls, BudgetInterface
class Budget implements CUDInterface, CommonDatabaseCallsInterface, BudgetInterface
{
use SwitchUser;
@ -118,7 +119,6 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface
*/
public function findByWhat($what)
{
// TODO: Implement findByWhat() method.
throw new NotImplementedException;
}
@ -142,7 +142,6 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface
*/
public function getByIds(array $ids)
{
// TODO: Implement getByIds() method.
throw new NotImplementedException;
}
@ -237,7 +236,8 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface
}
/**
* This method includes the time because otherwise, SQLite doesn't understand it.
* This method includes the time because otherwise, SQLite does not understand it.
*
* @param \Budget $budget
* @param Carbon $date
*
@ -247,9 +247,9 @@ class Budget implements CUD, CommonDatabaseCalls, BudgetInterface
{
return \LimitRepetition::
leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
->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();
}
}
}

View File

@ -28,4 +28,4 @@ interface BudgetInterface
*/
public function transactionsWithoutBudgetInDateRange(Carbon $start, Carbon $end);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}

View File

@ -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);
}
}

View File

@ -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();
}
}
}

View File

@ -0,0 +1,183 @@
<?php
namespace FireflyIII\Database\PiggyBank;
use FireflyIII\Database\SwitchUser;
use FireflyIII\Exception\NotImplementedException;
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Support\Collection;
use Illuminate\Support\MessageBag;
/**
* Class PiggyBankShared
*
* @package FireflyIII\Database\PiggyBank
*/
class PiggyBankShared
{
use SwitchUser;
/**
*
*/
public function __construct()
{
$this->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];
}
}

View File

@ -16,4 +16,4 @@ interface PiggyBankInterface
* @return float
*/
public function leftOnAccount(\Account $account);
}
}

View File

@ -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;
}
}
}

View File

@ -1,41 +0,0 @@
<?php
namespace FireflyIII\Database\RecurringTransaction;
use Carbon\Carbon;
/**
* Interface RecurringInterface
*
* @package FireflyIII\Database
*/
interface RecurringTransactionInterface
{
/**
* @param \RecurringTransaction $recurring
* @param Carbon $start
* @param Carbon $end
*
* @return null|\TransactionJournal
* @internal param Carbon $current
* @internal param Carbon $currentEnd
*
*/
public function getJournalForRecurringInRange(\RecurringTransaction $recurring, Carbon $start, Carbon $end);
/**
* @param \RecurringTransaction $recurring
* @param \TransactionJournal $journal
*
* @return bool
*/
public function scan(\RecurringTransaction $recurring, \TransactionJournal $journal);
/**
* @param \RecurringTransaction $recurring
*
* @return bool
*/
public function scanEverything(\RecurringTransaction $recurring);
}

View File

@ -24,4 +24,4 @@ trait SwitchUser
{
$this->_user = $user;
}
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}
}

View File

@ -17,4 +17,4 @@ interface TransactionCurrencyInterface
*/
public function findByCode($code);
}
}

View File

@ -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;
}
}
}

View File

@ -41,4 +41,4 @@ interface TransactionJournalInterface
*/
public function getSumOfIncomesByMonth(Carbon $date);
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}

View File

@ -50,4 +50,4 @@ class Account
\Cache::forget('account.' . $account->id . '.latestBalance');
\Cache::forget('account.' . $account->id . '.lastActivityDate');
}
}
}

View File

@ -64,4 +64,4 @@ class Budget
$events->listen('limits.update', 'FireflyIII\Event\Budget@storeOrUpdateLimit');
}
}
}

View File

@ -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');
}
}
}

View File

@ -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();
}
}
}
}

View File

@ -52,4 +52,4 @@ class Transaction
\Cache::forget('account.' . $transaction->account_id . '.latestBalance');
\Cache::forget('account.' . $transaction->account_id . '.lastActivityDate');
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -11,4 +11,4 @@ namespace FireflyIII\Exception;
class FireflyException extends \Exception
{
}
}

View File

@ -10,4 +10,4 @@ namespace FireflyIII\Exception;
class NotImplementedException extends \Exception
{
}
}

View File

@ -9,4 +9,4 @@ namespace FireflyIII\Exception;
class ValidationException extends \Exception
{
}
}

View File

@ -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');
}
);
}
}
}

View File

@ -123,7 +123,7 @@ class Form
$html .= \Form::input('text', $name, $value, $options);
break;
case 'amount':
$html .= '<div class="input-group"><div class="input-group-addon">'.getCurrencySymbol().'</div>';
$html .= '<div class="input-group"><div class="input-group-addon">' . \Amount::getCurrencySymbol() . '</div>';
$html .= \Form::input('number', $name, $value, $options);
$html .= '</div>';
break;
@ -379,4 +379,4 @@ class Form
return self::ffInput('text', $name, $value, $options);
}
}
}

View File

@ -0,0 +1,69 @@
<?php
namespace FireflyIII\Helper\Related;
use FireflyIII\Database\SwitchUser;
use Illuminate\Support\Collection;
/**
* Class Related
*
* @package FireflyIII\Helper\Related
*/
class Related implements RelatedInterface
{
use SwitchUser;
/**
*
*/
public function __construct()
{
$this->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;
}
}

View File

@ -0,0 +1,29 @@
<?php
namespace FireflyIII\Helper\Related;
use Illuminate\Support\Collection;
/**
* Interface RelatedInterface
*
* @package FireflyIII\Helper\Related
*/
interface RelatedInterface
{
/**
* @param string $query
* @param \TransactionJournal $journal
*
* @return Collection
*/
public function search($query, \TransactionJournal $journal);
/**
* @param array $objectIds
*
* @return Collection
*/
public function getJournalsByIds(array $objectIds);
}

View File

@ -0,0 +1,93 @@
<?php
namespace FireflyIII\Helper\TransactionJournal;
use Illuminate\Support\Collection;
/**
* Class Helper
*
* @package FireflyIII\Helper\TransactionJournal
*/
class Helper implements HelperInterface
{
/**
* @param $what
*
* @return int
*/
public function getTransactionTypeIdByWhat($what) {
}
/**
*
* Get the account_id, which is the asset account that paid for the transaction.
*
* @param string $what
* @param Collection $transactions
*
* @return mixed
*/
public function getAssetAccount($what, Collection $transactions)
{
if ($what == 'withdrawal') {
// transaction #1 is the one that paid for it.
return intval($transactions[1]->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();
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace FireflyIII\Helper\TransactionJournal;
use Illuminate\Support\Collection;
/**
* Interface HelperInterface
*
* @package FireflyIII\Helper\TransactionJournal
*/
interface HelperInterface
{
/**
*
* Get the account_id, which is the asset account that paid for the transaction.
*
* @param string $what
* @param Collection $transactions
*
* @return int
*/
public function getAssetAccount($what, Collection $transactions);
/**
* @param $what
*
* @return int
*/
public function getTransactionTypeIdByWhat($what);
/**
* @return Collection
*/
public function getAssetAccounts();
/**
* @return Collection
*/
public function getBudgets();
/**
* @return Collection
*/
public function getPiggyBanks();
/**
* @return Collection
*/
public function getRepeatedExpenses();
}

View File

@ -5,10 +5,11 @@ namespace FireflyIII\Report;
use Carbon\Carbon;
use FireflyIII\Database\Account\Account as AccountRepository;
use FireflyIII\Database\SwitchUser;
use FireflyIII\Database\TransactionJournal\TransactionJournal as JournalRepository;
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
// todo add methods to itnerface
/**
* Class Report
*
@ -22,13 +23,24 @@ class Report implements ReportInterface
/** @var AccountRepository */
protected $_accounts;
/** @var \FireflyIII\Report\ReportHelperInterface */
protected $_helper;
/** @var JournalRepository */
protected $_journals;
/** @var \FireflyIII\Report\ReportQueryInterface */
protected $_queries;
/**
* @param AccountRepository $accounts
* @param JournalRepository $journals
*/
public function __construct(AccountRepository $accounts)
public function __construct(AccountRepository $accounts, JournalRepository $journals)
{
$this->_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;
}
}
}

View File

@ -0,0 +1,142 @@
<?php
namespace FireflyIII\Report;
use Illuminate\Support\Collection;
/**
* Class ReportHelper
*
* @package FireflyIII\Report
*/
class ReportHelper implements ReportHelperInterface
{
/**
* Only return the top X entries, group the rest by amount
* and described as 'Others'. id = 0 as well
*
* @param array $array
* @param int $limit
*
* @return array
*/
public function limitArray(array $array, $limit = 10)
{
$others = [
'name' => '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;
}
}

View File

@ -0,0 +1,64 @@
<?php
namespace FireflyIII\Report;
use Illuminate\Support\Collection;
/**
* Interface ReportHelperInterface
*
* @package FireflyIII\Report
*/
interface ReportHelperInterface
{
/**
* Only return the top X entries, group the rest by amount
* and described as 'Others'. id = 0 as well
*
* @param array $array
* @param int $limit
*
* @return array
*/
public function limitArray(array $array, $limit = 10);
/**
* Turns a collection into an array. Needs the field 'id' for the key,
* and saves 'name', 'amount','spent' (if present) as a sub array.
*
* @param Collection $collection
*
* @return array
*/
public function makeArray(Collection $collection);
/**
* 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);
/**
* Sort an array where all 'amount' keys are positive floats.
*
* @param array $array
*
* @return array
*/
public function sortArray(array $array);
/**
* Sort an array where all 'amount' keys are negative floats.
*
* @param array $array
*
* @return array
*/
public function sortNegativeArray(array $array);
}

View File

@ -15,21 +15,68 @@ interface ReportInterface
/**
* @param Carbon $start
* @param Carbon $end
* @param int $limit
*
* @return Collection
*/
public function revenueGroupedByAccount(Carbon $start, Carbon $end, $limit = 15);
/**
* @param Carbon $start
* @param Carbon $end
* @param int $limit
* @param int $limit
*
* @return Collection
*/
public function expensesGroupedByAccount(Carbon $start, Carbon $end, $limit = 15);
/**
* 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);
/**
* @param Carbon $date
*
* @return array
*/
public function getAccountsForMonth(Carbon $date);
/**
* @param Carbon $date
*
* @return Collection
*/
public function getBudgetsForMonth(Carbon $date);
/**
* @param Carbon $date
* @param int $limit
*
* @return array
*/
public function getCategoriesForMonth(Carbon $date, $limit = 15);
/**
* @param Carbon $date
* @param int $limit
*
* @return Collection
*/
public function getExpenseGroupedForMonth(Carbon $date, $limit = 15);
/**
* @param Carbon $date
* @param bool $shared
*
* @return Collection
*/
public function getIncomeForMonth(Carbon $date, $shared = false);
/**
* @param Carbon $date
*
* @return Collection
*/
public function getPiggyBanksForMonth(Carbon $date);
/**
* @param Carbon $start
*
@ -44,10 +91,19 @@ interface ReportInterface
*/
public function listOfYears(Carbon $start);
/**
* @param Carbon $start
* @param Carbon $end
* @param int $limit
*
* @return Collection
*/
public function revenueGroupedByAccount(Carbon $start, Carbon $end, $limit = 15);
/**
* @param Carbon $date
*
* @return array
*/
public function yearBalanceReport(Carbon $date);
}
}

View File

@ -0,0 +1,446 @@
<?php
namespace FireflyIII\Report;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
/**
* Class ReportQuery
*
* @package FireflyIII\Report
*/
class ReportQuery implements ReportQueryInterface
{
/**
* This query retrieves a list of accounts that are active and not shared.
*
* @return Collection
*/
public function accountList()
{
return \Auth::user()->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`')
]
);
}
}

View File

@ -0,0 +1,142 @@
<?php
namespace FireflyIII\Report;
use Carbon\Carbon;
use Illuminate\Support\Collection;
/**
* Interface ReportQueryInterface
*
* @package FireflyIII\Report
*/
interface ReportQueryInterface
{
/**
* This query retrieves a list of accounts that are active and not shared.
*
* @return Collection
*/
public function accountList();
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* 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);
/**
* With a slightly misleading name, this query returns all transfers to shared accounts
* grouped by category (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);
}

View File

@ -4,6 +4,7 @@ namespace FireflyIII\Search;
use Illuminate\Support\Collection;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
/**
* Class Search
@ -20,7 +21,7 @@ class Search
public function searchAccounts(array $words)
{
return \Auth::user()->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();
}
}
}

View File

@ -0,0 +1,24 @@
<?php
namespace FireflyIII\Shared\Facade;
use Illuminate\Support\Facades\Facade;
/**
* Class Amount
*
* @package FireflyIII\Shared\Facade
*/
class Amount extends Facade
{
/**
* @return string
*/
protected static function getFacadeAccessor()
{
return 'amount';
}
}

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