Compare commits

...

10 Commits
3.0.0 ... 3.0.1

Author SHA1 Message Date
James Cole
2e342e47a7 Added unicity to AccountType model. Fixed some tests because of this. 2014-08-31 10:03:24 +02:00
James Cole
58b3334f05 Cleaned up some tests and moved some methods. 2014-08-31 08:59:43 +02:00
James Cole
4cd955e5cf Small text change in login. 2014-08-31 07:33:11 +02:00
James Cole
4dbf410cdf Removed codeception. 2014-08-31 07:32:59 +02:00
James Cole
074e6d52b1 Regenerated all model phpdocs. 2014-08-31 07:32:48 +02:00
James Cole
a0a36c5137 Ran model helper, added some new features. 2014-08-30 14:27:05 +02:00
James Cole
9db4137a1b Revamped the account controller. 2014-08-30 14:26:33 +02:00
James Cole
85f1e744b8 Added a new type of validation to be used for account names. 2014-08-30 14:25:52 +02:00
James Cole
8d90061d90 Included codeception for future use. 2014-08-30 14:25:21 +02:00
James Cole
b20d84e4b8 Fixed the accounts routes to be more strict about the types of accounts they accept. 2014-08-30 14:25:03 +02:00
45 changed files with 1176 additions and 1113 deletions

View File

@@ -40,6 +40,7 @@ return [
# 'Barryvdh\Debugbar\ServiceProvider', # 'Barryvdh\Debugbar\ServiceProvider',
'Firefly\Storage\StorageServiceProvider', 'Firefly\Storage\StorageServiceProvider',
'Firefly\Helper\HelperServiceProvider', 'Firefly\Helper\HelperServiceProvider',
'Firefly\Validation\ValidationServiceProvider',
'Codesleeve\AssetPipeline\AssetPipelineServiceProvider', 'Codesleeve\AssetPipeline\AssetPipelineServiceProvider',
], ],
'manifest' => storage_path() . '/meta', 'manifest' => storage_path() . '/meta',

View File

@@ -5,6 +5,8 @@ use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
/** /**
* Class AccountController * Class AccountController
*
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/ */
class AccountController extends \BaseController class AccountController extends \BaseController
{ {
@@ -14,11 +16,11 @@ class AccountController extends \BaseController
/** /**
* @param ARI $repository * @param ARI $repository
* @param AI $accounts * @param AI $accounts
*/ */
public function __construct(ARI $repository, AI $accounts) public function __construct(ARI $repository, AI $accounts)
{ {
$this->_accounts = $accounts; $this->_accounts = $accounts;
$this->_repository = $repository; $this->_repository = $repository;
} }
@@ -27,47 +29,30 @@ class AccountController extends \BaseController
*/ */
public function create() public function create()
{ {
return View::make('accounts.create'); return View::make('accounts.create')->with('title', 'Create account');
} }
/** /**
* @param Account $account * @param Account $account
* *
* @return \Illuminate\View\View * @return $this
*/ */
public function delete(Account $account) public function delete(Account $account)
{ {
$accountType = $account->accountType()->first(); return View::make('accounts.delete')->with('account', $account)
->with('title', 'Delete account "' . $account->name . '"');
if ($accountType->description == 'Initial balance account' || $accountType->description == 'Cash account') {
return \View::make('error')->with(
'message', 'Cannot edit this account type (' . $accountType->description . ').'
);
}
return View::make('accounts.delete')->with('account', $account);
} }
/** /**
* @param Account $account * @param Account $account
* *
* @return \Illuminate\Http\RedirectResponse * @return $this|\Illuminate\Http\RedirectResponse
*/ */
public function destroy(Account $account) public function destroy(Account $account)
{ {
$accountType = $account->accountType()->first();
if ($accountType->description == 'Initial balance account' || $accountType->description == 'Cash account') { $this->_repository->destroy($account);
return View::make('error')->with( Session::flash('success', 'The account was deleted.');
'message', 'Cannot edit this account type (' . $accountType->description . ').'
);
}
$result = $this->_repository->destroy($account);
if ($result === true) {
Session::flash('success', 'The account was deleted.');
} else {
Session::flash('error', 'Could not delete the account.');
}
return Redirect::route('accounts.index'); return Redirect::route('accounts.index');
@@ -76,54 +61,53 @@ class AccountController extends \BaseController
/** /**
* @param Account $account * @param Account $account
* *
* @return \Illuminate\View\View * @return $this
*/ */
public function edit(Account $account) public function edit(Account $account)
{ {
$accountType = $account->accountType()->first();
if ($accountType->description == 'Initial balance account' || $accountType->description == 'Cash account') {
return View::make('error')->with(
'message', 'Cannot edit this account type (' . $accountType->description . ').'
);
}
$openingBalance = $this->_accounts->openingBalanceTransaction($account); $openingBalance = $this->_accounts->openingBalanceTransaction($account);
return View::make('accounts.edit')->with('account', $account)->with('openingBalance', $openingBalance)->with('title','Edit account "'.$account->name.'"');
return View::make('accounts.edit')->with('account', $account)->with('openingBalance', $openingBalance);
} }
/** /**
* @return \Illuminate\View\View * @return $this
*/ */
public function index() public function index()
{ {
$accounts = $this->_repository->get(); $accounts = $this->_repository->get();
$display = $this->_accounts->index($accounts); $set = [
'personal' => [],
'beneficiaries' => []
];
foreach ($accounts as $account) {
switch ($account->accounttype->type) {
case 'Default account':
$set['personal'][] = $account;
break;
case 'Beneficiary account':
$set['beneficiaries'][] = $account;
break;
}
}
return View::make('accounts.index')->with('accounts', $display); return View::make('accounts.index')->with('accounts', $set)->with('title','All your accounts');
} }
/** /**
* @param Account $account * @param Account $account
* *
* @return \Illuminate\View\View * @return $this
*/ */
public function show(Account $account) public function show(Account $account)
{ {
$accountType = $account->accountType()->first(); $data = $this->_accounts->show($account, 40);
if ($accountType->description == 'Initial balance account' || $accountType->description == 'Cash account') {
return View::make('error')->with(
'message', 'Cannot show this account type (' . $accountType->description . ').'
);
}
$show = $this->_accounts->show($account, 40); return View::make('accounts.show')->with('account', $account)->with('show', $data)->with('title',
'Details for account "' . $account->name . '"');
return View::make('accounts.show')->with('account', $account)->with('show', $show);
} }
/** /**
* @return \Illuminate\Http\RedirectResponse * @return $this|\Illuminate\Http\RedirectResponse
*/ */
public function store() public function store()
{ {
@@ -133,14 +117,14 @@ class AccountController extends \BaseController
if ($account->validate()) { if ($account->validate()) {
// saved! return to wherever. // saved! return to wherever.
Session::flash('success', 'Account "' . $account->name . '" created!'); Session::flash('success', 'Account "' . $account->name . '" created!');
if (Input::get('create') == '1') { if (intval(Input::get('create')) === 1) {
return Redirect::route('accounts.create')->withInput(); return Redirect::route('accounts.create')->withInput();
} else { } else {
return Redirect::route('accounts.index'); return Redirect::route('accounts.index');
} }
} else { } else {
// did not save, return with error: // did not save, return with error:
Session::flash('error', 'Could not save the new account. Please check the form.'); Session::flash('error', 'Could not save the new account: ' . $account->errors()->first());
return Redirect::route('accounts.create')->withErrors($account->errors())->withInput(); return Redirect::route('accounts.create')->withErrors($account->errors())->withInput();
@@ -150,16 +134,10 @@ class AccountController extends \BaseController
/** /**
* @param Account $account * @param Account $account
* *
* @return \Illuminate\Http\RedirectResponse * @return $this|\Illuminate\Http\RedirectResponse
*/ */
public function update(Account $account) public function update(Account $account)
{ {
$accountType = $account->accountType()->first();
if ($accountType->description == 'Initial balance account' || $accountType->description == 'Cash account') {
return View::make('error')->with(
'message', 'Cannot show this account type (' . $accountType->description . ').'
);
}
$account = $this->_repository->update($account, Input::all()); $account = $this->_repository->update($account, Input::all());
if ($account->validate()) { if ($account->validate()) {
Session::flash('success', 'Account "' . $account->name . '" updated.'); Session::flash('success', 'Account "' . $account->name . '" updated.');

View File

@@ -11,22 +11,6 @@ use Illuminate\Database\Schema\Blueprint;
class CreateAccountTypesTable extends Migration class CreateAccountTypesTable extends Migration
{ {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(
'account_types', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('description', 50);
}
);
}
/** /**
* Reverse the migrations. * Reverse the migrations.
* *
@@ -37,4 +21,23 @@ class CreateAccountTypesTable extends Migration
Schema::drop('account_types'); Schema::drop('account_types');
} }
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(
'account_types', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('type', 50);
$table->boolean('editable');
$table->unique('type');
}
);
}
} }

View File

@@ -11,16 +11,16 @@ class AccountTypeSeeder extends Seeder
DB::table('account_types')->delete(); DB::table('account_types')->delete();
AccountType::create( AccountType::create(
['description' => 'Default account'] ['type' => 'Default account','editable' => true]
); );
AccountType::create( AccountType::create(
['description' => 'Cash account'] ['type' => 'Cash account','editable' => false]
); );
AccountType::create( AccountType::create(
['description' => 'Initial balance account'] ['type' => 'Initial balance account','editable' => false]
); );
AccountType::create( AccountType::create(
['description' => 'Beneficiary account'] ['type' => 'Beneficiary account','editable' => true]
); );
} }

View File

@@ -1,104 +1,105 @@
<?php <?php
return array( return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Validation Language Lines | Validation Language Lines
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The following language lines contain the default error messages used by | The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such | the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here. | as the size rules. Feel free to tweak each of these messages here.
| |
*/ */
"accepted" => "The :attribute must be accepted.", "accepted" => "The :attribute must be accepted.",
"active_url" => "The :attribute is not a valid URL.", "active_url" => "The :attribute is not a valid URL.",
"after" => "The :attribute must be a date after :date.", "after" => "The :attribute must be a date after :date.",
"alpha" => "The :attribute may only contain letters.", "alpha" => "The :attribute may only contain letters.",
"alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.", "alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.",
"alpha_num" => "The :attribute may only contain letters and numbers.", "alpha_num" => "The :attribute may only contain letters and numbers.",
"array" => "The :attribute must be an array.", "array" => "The :attribute must be an array.",
"before" => "The :attribute must be a date before :date.", "before" => "The :attribute must be a date before :date.",
"between" => array( "between" => array(
"numeric" => "The :attribute must be between :min and :max.", "numeric" => "The :attribute must be between :min and :max.",
"file" => "The :attribute must be between :min and :max kilobytes.", "file" => "The :attribute must be between :min and :max kilobytes.",
"string" => "The :attribute must be between :min and :max characters.", "string" => "The :attribute must be between :min and :max characters.",
"array" => "The :attribute must have between :min and :max items.", "array" => "The :attribute must have between :min and :max items.",
), ),
"confirmed" => "The :attribute confirmation does not match.", "confirmed" => "The :attribute confirmation does not match.",
"date" => "The :attribute is not a valid date.", "date" => "The :attribute is not a valid date.",
"date_format" => "The :attribute does not match the format :format.", "date_format" => "The :attribute does not match the format :format.",
"different" => "The :attribute and :other must be different.", "different" => "The :attribute and :other must be different.",
"digits" => "The :attribute must be :digits digits.", "digits" => "The :attribute must be :digits digits.",
"digits_between" => "The :attribute must be between :min and :max digits.", "digits_between" => "The :attribute must be between :min and :max digits.",
"email" => "The :attribute must be a valid email address.", "email" => "The :attribute must be a valid email address.",
"exists" => "The selected :attribute is invalid.", "exists" => "The selected :attribute is invalid.",
"image" => "The :attribute must be an image.", "image" => "The :attribute must be an image.",
"in" => "The selected :attribute is invalid.", "in" => "The selected :attribute is invalid.",
"integer" => "The :attribute must be an integer.", "integer" => "The :attribute must be an integer.",
"ip" => "The :attribute must be a valid IP address.", "ip" => "The :attribute must be a valid IP address.",
"max" => array( "max" => array(
"numeric" => "The :attribute may not be greater than :max.", "numeric" => "The :attribute may not be greater than :max.",
"file" => "The :attribute may not be greater than :max kilobytes.", "file" => "The :attribute may not be greater than :max kilobytes.",
"string" => "The :attribute may not be greater than :max characters.", "string" => "The :attribute may not be greater than :max characters.",
"array" => "The :attribute may not have more than :max items.", "array" => "The :attribute may not have more than :max items.",
), ),
"mimes" => "The :attribute must be a file of type: :values.", "mimes" => "The :attribute must be a file of type: :values.",
"min" => array( "min" => array(
"numeric" => "The :attribute must be at least :min.", "numeric" => "The :attribute must be at least :min.",
"file" => "The :attribute must be at least :min kilobytes.", "file" => "The :attribute must be at least :min kilobytes.",
"string" => "The :attribute must be at least :min characters.", "string" => "The :attribute must be at least :min characters.",
"array" => "The :attribute must have at least :min items.", "array" => "The :attribute must have at least :min items.",
), ),
"not_in" => "The selected :attribute is invalid.", "not_in" => "The selected :attribute is invalid.",
"numeric" => "The :attribute must be a number.", "numeric" => "The :attribute must be a number.",
"regex" => "The :attribute format is invalid.", "regex" => "The :attribute format is invalid.",
"required" => "The :attribute field is required.", "required" => "The :attribute field is required.",
"required_if" => "The :attribute field is required when :other is :value.", "required_if" => "The :attribute field is required when :other is :value.",
"required_with" => "The :attribute field is required when :values is present.", "required_with" => "The :attribute field is required when :values is present.",
"required_with_all" => "The :attribute field is required when :values is present.", "required_with_all" => "The :attribute field is required when :values is present.",
"required_without" => "The :attribute field is required when :values is not present.", "required_without" => "The :attribute field is required when :values is not present.",
"required_without_all" => "The :attribute field is required when none of :values are present.", "required_without_all" => "The :attribute field is required when none of :values are present.",
"same" => "The :attribute and :other must match.", "same" => "The :attribute and :other must match.",
"size" => array( "size" => array(
"numeric" => "The :attribute must be :size.", "numeric" => "The :attribute must be :size.",
"file" => "The :attribute must be :size kilobytes.", "file" => "The :attribute must be :size kilobytes.",
"string" => "The :attribute must be :size characters.", "string" => "The :attribute must be :size characters.",
"array" => "The :attribute must contain :size items.", "array" => "The :attribute must contain :size items.",
), ),
"unique" => "The :attribute has already been taken.", "unique" => "The :attribute has already been taken.",
"url" => "The :attribute format is invalid.", "url" => "The :attribute format is invalid.",
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Custom Validation Language Lines | Custom Validation Language Lines
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may specify custom validation messages for attributes using the | Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to | convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule. | specify a specific custom language line for a given attribute rule.
| |
*/ */
'custom' => array( 'custom' => array(
'attribute-name' => array( 'attribute-name' => array(
'rule-name' => 'custom-message', 'rule-name' => 'custom-message',
), ),
), ),
'alphabasic' => 'The :attribute field must consist of basic alphanumeric characters.',
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Custom Validation Attributes | Custom Validation Attributes
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The following language lines are used to swap attribute place-holders | The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead | with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner. | of "email". This simply helps us make messages a little cleaner.
| |
*/ */
'attributes' => array(), 'attributes' => array(),
); ];

View File

@@ -2,7 +2,7 @@
namespace Firefly\Helper\Controllers; namespace Firefly\Helper\Controllers;
use Illuminate\Database\Eloquent\Collection; use Firefly\Exception\FireflyException;
/** /**
* Class Account * Class Account
@@ -11,43 +11,6 @@ use Illuminate\Database\Eloquent\Collection;
*/ */
class Account implements AccountInterface class Account implements AccountInterface
{ {
/**
* @param Collection $accounts
*
* @return array|mixed
*/
public function index(Collection $accounts)
{
$list = [
'personal' => [],
'beneficiaries' => [],
'initial' => [],
'cash' => []
];
foreach ($accounts as $account) {
switch ($account->accounttype->description) {
case 'Default account':
$list['personal'][] = $account;
break;
case 'Cash account':
$list['cash'][] = $account;
break;
case 'Initial balance account':
$list['initial'][] = $account;
break;
case 'Beneficiary account':
$list['beneficiaries'][] = $account;
break;
}
}
return $list;
}
/** /**
* @param \Account $account * @param \Account $account
* *
@@ -55,17 +18,12 @@ class Account implements AccountInterface
*/ */
public function openingBalanceTransaction(\Account $account) public function openingBalanceTransaction(\Account $account)
{ {
$transactionType = \TransactionType::where('type', 'Opening balance')->first();
return \TransactionJournal:: return \TransactionJournal::
with( withRelevantData()->account($account)
['transactions' => function ($q) { ->leftJoin('transaction_types', 'transaction_types.id', '=',
$q->orderBy('amount', 'ASC'); 'transaction_journals.transaction_type_id')
}] ->where('transaction_types.type', 'Opening balance')
)->where('transaction_type_id', $transactionType->id) ->first(['transaction_journals.*']);
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.account_id', $account->id)->first(['transaction_journals.*']);
} }
/** /**
@@ -77,7 +35,7 @@ class Account implements AccountInterface
public function show(\Account $account, $perPage) public function show(\Account $account, $perPage)
{ {
$start = \Session::get('start'); $start = \Session::get('start');
$end = \Session::get('end'); $end = \Session::get('end');
$stats = [ $stats = [
'budgets' => [], 'budgets' => [],
'categories' => [], 'categories' => [],
@@ -87,29 +45,51 @@ class Account implements AccountInterface
// build a query: // build a query:
$query = \TransactionJournal::with( $query = \TransactionJournal::withRelevantData()->defaultSorting()->account($account)->after($start)
['transactions' => function ($q) { ->before($end);
$q->orderBy('amount', 'ASC'); // filter some:
}, 'transactiontype', 'components' => function ($q) { if (\Input::get('type')) {
$q->orderBy('class'); switch (\Input::get('type')) {
}, 'transactions.account.accounttype'] case 'transactions':
)->orderBy('date', 'DESC')->leftJoin( $query->transactionTypes(['Deposit', 'Withdrawal']);
'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id' break;
)->where('transactions.account_id', $account->id)->where('date', '>=', $start->format('Y-m-d'))->where( case 'transfers':
'date', '<=', $end->format('Y-m-d') $query->transactionTypes(['Transfer']);
)->orderBy('transaction_journals.id', 'DESC'); break;
default:
throw new FireflyException('No case for type "' . \Input::get('type') . '"!');
break;
}
}
if (\Input::get('show')) {
switch (\Input::get('show')) {
case 'expenses':
case 'out':
$query->lessThan(0);
break;
case 'income':
case 'in':
$query->moreThan(0);
break;
default:
throw new FireflyException('No case for show "' . \Input::get('show') . '"!');
break;
}
}
// build paginator: // build paginator:
$totalItems = $query->count(); $totalItems = $query->count();
$page = intval(\Input::get('page')) > 1 ? intval(\Input::get('page')) : 1; $page = max(1, intval(\Input::get('page')));
$skip = ($page - 1) * $perPage; $skip = ($page - 1) * $perPage;
$result = $query->skip($skip)->take($perPage)->get(['transaction_journals.*']); $result = $query->skip($skip)->take($perPage)->get(['transaction_journals.*']);
// in the mean time, build list of categories, budgets and other accounts:
// get the relevant budgets, categories and accounts from this list:
/** @var $item \TransactionJournal */ /** @var $item \TransactionJournal */
foreach ($result as $item) { foreach ($result as $index => $item) {
$items[] = $item;
foreach ($item->components as $component) { foreach ($item->components as $component) {
if ($component->class == 'Budget') { if ($component->class == 'Budget') {
$stats['budgets'][$component->id] = $component; $stats['budgets'][$component->id] = $component;
@@ -118,59 +98,56 @@ class Account implements AccountInterface
$stats['categories'][$component->id] = $component; $stats['categories'][$component->id] = $component;
} }
} }
$fromAccount = $item->transactions[0]->account; // since it is entirely possible the database is messed up somehow
$toAccount = $item->transactions[1]->account; // it might be that a transaction journal has only one transaction.
// this is mainly caused by wrong deletions and other artefacts from the past.
// if it is the case, we remove $item and continue like nothing ever happened.
// this will however, mess up some statisics but we can live with that.
// we might be needing some cleanup routine in the future.
// for now, we simply warn the user of this.
if (count($item->transactions) < 2) {
\Session::flash('warning',
'Some transactions are incomplete; they will not be shown. Statistics may differ.');
unset($result[$index]);
continue;
}
$items[] = $item;
$fromAccount = $item->transactions[0]->account;
$toAccount = $item->transactions[1]->account;
$stats['accounts'][$fromAccount->id] = $fromAccount; $stats['accounts'][$fromAccount->id] = $fromAccount;
$stats['accounts'][$toAccount->id] = $toAccount; $stats['accounts'][$toAccount->id] = $toAccount;
} }
unset($result, $page);
$paginator = \Paginator::make($items, $totalItems, $perPage); $paginator = \Paginator::make($items, $totalItems, $perPage);
unset($result, $page, $item, $fromAccount, $toAccount);
// statistics
$stats['period']['in'] = floatval(
\Transaction::where('account_id', $account->id)->where('amount', '>', 0)->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)->leftJoin(
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
)->whereIn('transaction_types.type', ['Deposit', 'Withdrawal'])->where(
'transaction_journals.date', '>=', $start->format('Y-m-d')
)->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount')
);
$stats['period']['out'] = floatval( // statistics (transactions)
\Transaction::where('account_id', $account->id)->where('amount', '<', 0)->leftJoin( $trIn = floatval(\Transaction::before($end)->after($start)->account($account)->moreThan(0)
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' ->transactionTypes(['Deposit', 'Withdrawal'])->sum('transactions.amount'));
)->leftJoin( $trOut = floatval(\Transaction::before($end)->after($start)->account($account)->lessThan(0)
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id' ->transactionTypes(['Deposit', 'Withdrawal'])->sum('transactions.amount'));
)->whereIn('transaction_types.type', ['Deposit', 'Withdrawal'])->where( $trDiff = $trIn + $trOut;
'transaction_journals.date', '>=', $start->format('Y-m-d')
)->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount')
);
$stats['period']['diff'] = $stats['period']['in'] + $stats['period']['out'];
$stats['period']['t_in'] = floatval( // statistics (transfers)
\Transaction::where('account_id', $account->id)->where('amount', '>', 0)->leftJoin( $trfIn = floatval(\Transaction::before($end)->after($start)->account($account)->moreThan(0)
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' ->transactionTypes(['Transfer'])->sum('transactions.amount'));
)->leftJoin( $trfOut = floatval(\Transaction::before($end)->after($start)->account($account)->lessThan(0)
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id' ->transactionTypes(['Transfer'])->sum('transactions.amount'));
)->where('transaction_types.type', 'Transfer')->where( $trfDiff = $trfIn + $trfOut;
'transaction_journals.date', '>=', $start->format('Y-m-d')
)->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount')
);
$stats['period']['t_out'] = floatval(
\Transaction::where('account_id', $account->id)->where('amount', '<', 0)->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)->leftJoin(
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
)->where('transaction_types.type', 'Transfer')->where(
'transaction_journals.date', '>=', $start->format('Y-m-d')
)->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount')
);
$stats['period']['t_diff'] = $stats['period']['t_in'] + $stats['period']['t_out']; $stats['period'] = [
'in' => $trIn,
'out' => $trOut,
'diff' => $trDiff,
't_in' => $trfIn,
't_out' => $trfOut,
't_diff' => $trfDiff
];
$return = [ $return = [
'journals' => $paginator, 'journals' => $paginator,

View File

@@ -12,15 +12,6 @@ use Illuminate\Database\Eloquent\Collection;
interface AccountInterface interface AccountInterface
{ {
/**
* Build the index:
*
* @param Collection $accounts
*
* @return mixed
*/
public function index(Collection $accounts);
/** /**
* @param \Account $account * @param \Account $account
* *

View File

@@ -36,7 +36,6 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/ */
public function createOrFind($name, \AccountType $type = null) public function createOrFind($name, \AccountType $type = null)
{ {
$account = $this->findByName($name, $type); $account = $this->findByName($name, $type);
if (!$account) { if (!$account) {
$data = [ $data = [
@@ -60,10 +59,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
if (is_null($name) || strlen($name) == 0) { if (is_null($name) || strlen($name) == 0) {
return null; return null;
} }
$type = \AccountType::where('description', 'Beneficiary account')->first(); $type = \AccountType::where('type', 'Beneficiary account')->first();
/** @noinspection PhpParamsInspection */
return $this->createOrFind($name, $type); return $this->createOrFind($name, $type);
} }
@@ -74,38 +70,29 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/ */
public function destroy(\Account $account) public function destroy(\Account $account)
{ {
// find the oldest transaction which also is a "Opening balance" // find all transaction journals related to this account:
$first = \Transaction:: $journals = \TransactionJournal::withRelevantData()->account($account)->get(['transaction_journals.*']);
leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') $accountIDs = [];
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where('transaction_journals.user_id', \Auth::user()->id)
->where('transaction_types.type', 'Opening balance')
->where('account_id', '!=', $account->id)
->orderBy('transactions.id', 'DESC')->first(['transactions.*']);
$initialbalanceAccount = null;
if (!is_null($first)) {
$initialbalanceAccount = $first->account()->first();
}
// loop the account, find all transaction journals, and delete them:
$transactions = $account->transactions()->with('transactionjournal')->get();
$journals = [];
/** @var \Transaction $transaction */
foreach ($transactions as $transaction) {
$journals[$transaction->transaction_journal_id] = $transaction->transactionJournal;
}
/** @var \TransactionJournal $journal */ /** @var \TransactionJournal $journal */
foreach ($journals as $journal) { foreach ($journals as $journal) {
// remember the account id's of the transactions involved:
foreach ($journal->transactions as $t) {
$accountIDs[] = $t->account_id;
}
$journal->delete(); $journal->delete();
} }
$accountIDs = array_unique($accountIDs);
if (!is_null($initialbalanceAccount)) { if (count($accountIDs) > 0) {
$initialbalanceAccount->delete(); // find the "initial balance" type accounts in this list. Should be just 1.
$query = \Auth::user()->accounts()->accountTypeIn(['Initial balance account'])
->whereIn('accounts.id', $accountIDs);
if ($query->count() == 1) {
$iba = $query->first(['accounts.*']);
$iba->delete();
}
} }
$account->delete(); $account->delete();
/** /**
@@ -135,10 +122,11 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/ */
public function findByName($name, \AccountType $type = null) public function findByName($name, \AccountType $type = null)
{ {
$type = is_null($type) ? \AccountType::where('description', 'Default account')->first() : $type; $type = is_null($type) ? \AccountType::where('type', 'Default account')->first() : $type;
return \Auth::user()->accounts()->where('account_type_id', $type->id)->where('name', 'like', '%' . $name . '%') return \Auth::user()->accounts()->where('account_type_id', $type->id)
->first(); ->where('name', 'like', '%' . $name . '%')
->first();
} }
/** /**
@@ -155,9 +143,9 @@ class EloquentAccountRepository implements AccountRepositoryInterface
public function getActiveDefault() public function getActiveDefault()
{ {
return \Auth::user()->accounts()->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') return \Auth::user()->accounts()->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.description', 'Default account')->where('accounts.active', 1) ->where('account_types.type', 'Default account')->where('accounts.active', 1)
->get(['accounts.*']); ->get(['accounts.*']);
} }
/** /**
@@ -165,12 +153,12 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/ */
public function getActiveDefaultAsSelectList() public function getActiveDefaultAsSelectList()
{ {
$list = \Auth::user()->accounts()->leftJoin( $list = \Auth::user()->accounts()->leftJoin(
'account_types', 'account_types.id', '=', 'accounts.account_type_id' 'account_types', 'account_types.id', '=', 'accounts.account_type_id'
) )
->where('account_types.description', 'Default account')->where('accounts.active', 1) ->where('account_types.type', 'Default account')->where('accounts.active', 1)
->orderBy('accounts.name', 'ASC')->get(['accounts.*']); ->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
$return = []; $return = [];
foreach ($list as $entry) { foreach ($list as $entry) {
$return[intval($entry->id)] = $entry->name; $return[intval($entry->id)] = $entry->name;
@@ -185,11 +173,11 @@ class EloquentAccountRepository implements AccountRepositoryInterface
public function getBeneficiaries() public function getBeneficiaries()
{ {
$list = \Auth::user()->accounts()->leftJoin( $list = \Auth::user()->accounts()->leftJoin(
'account_types', 'account_types.id', '=', 'accounts.account_type_id' 'account_types', 'account_types.id', '=', 'accounts.account_type_id'
) )
->where('account_types.description', 'Beneficiary account')->where('accounts.active', 1) ->where('account_types.type', 'Beneficiary account')->where('accounts.active', 1)
->orderBy('accounts.name', 'ASC')->get(['accounts.*']); ->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
return $list; return $list;
} }
@@ -213,7 +201,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/ */
public function getCashAccount() public function getCashAccount()
{ {
$type = \AccountType::where('description', 'Cash account')->first(); $type = \AccountType::where('type', 'Cash account')->first();
$cash = \Auth::user()->accounts()->where('account_type_id', $type->id)->first(); $cash = \Auth::user()->accounts()->where('account_type_id', $type->id)->first();
return $cash; return $cash;
@@ -226,9 +214,9 @@ class EloquentAccountRepository implements AccountRepositoryInterface
public function getDefault() public function getDefault()
{ {
return \Auth::user()->accounts()->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') return \Auth::user()->accounts()->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.description', 'Default account') ->where('account_types.type', 'Default account')
->orderBy('accounts.name', 'ASC')->get(['accounts.*']); ->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
} }
/** /**
@@ -239,16 +227,26 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/ */
public function store($data) public function store($data)
{ {
$defaultAccountType = \AccountType::where('description', 'Default account')->first(); /**
$accountType = isset($data['account_type']) ? $data['account_type'] : $defaultAccountType; * If the AccountType has been passed through, use it:
*/
if (isset($data['account_type']) && is_object($data['account_type'])
&& get_class($data['account_type']) == 'AccountType'
) {
$accountType = $data['account_type'];
} else {
$accountType = \AccountType::where('type', 'Default account')->first();
}
// create Account: /**
* Create new account:
*/
$account = new \Account; $account = new \Account;
$account->accountType()->associate($accountType); $account->accountType()->associate($accountType);
$account->user()->associate(\Auth::user()); $account->user()->associate(\Auth::user());
$account->name = $data['name']; $account->name = $data['name'];
$account->active $account->active
= isset($data['active']) && intval($data['active']) >= 0 && intval($data['active']) <= 1 ? intval( = isset($data['active']) && intval($data['active']) >= 0 && intval($data['active']) <= 1 ? intval(
$data['active'] $data['active']
) : 1; ) : 1;
@@ -257,7 +255,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
// create initial balance, if necessary: // create initial balance, if necessary:
if (isset($data['openingbalance']) && isset($data['openingbalancedate'])) { if (isset($data['openingbalance']) && isset($data['openingbalancedate'])) {
$amount = floatval($data['openingbalance']); $amount = floatval($data['openingbalance']);
$date = new Carbon($data['openingbalancedate']); $date = new Carbon($data['openingbalancedate']);
$this->_createInitialBalance($account, $amount, $date); $this->_createInitialBalance($account, $amount, $date);
} }
} }
@@ -286,12 +284,12 @@ class EloquentAccountRepository implements AccountRepositoryInterface
/** @var \Firefly\Helper\Controllers\AccountInterface $interface */ /** @var \Firefly\Helper\Controllers\AccountInterface $interface */
$interface = \App::make('Firefly\Helper\Controllers\AccountInterface'); $interface = \App::make('Firefly\Helper\Controllers\AccountInterface');
if ($account->accounttype->description == 'Default account') { if ($account->accounttype->type == 'Default account') {
$journal = $interface->openingBalanceTransaction($account); $journal = $interface->openingBalanceTransaction($account);
if ($journal) { if ($journal) {
$journal->date = new Carbon($data['openingbalancedate']); $journal->date = new Carbon($data['openingbalancedate']);
$journal->transactions[0]->amount = floatval($data['openingbalance']) * -1; $journal->transactions[0]->amount = floatval($data['openingbalance']) * -1;
$journal->transactions[1]->amount = floatval($data['openingbalance']); $journal->transactions[1]->amount = floatval($data['openingbalance']);
$journal->transactions[0]->save(); $journal->transactions[0]->save();
@@ -306,8 +304,8 @@ class EloquentAccountRepository implements AccountRepositoryInterface
/** /**
* @param \Account $account * @param \Account $account
* @param int $amount * @param int $amount
* @param Carbon $date * @param Carbon $date
* *
* @return bool * @return bool
* @SuppressWarnings(PHPMD.CamelCaseMethodName) * @SuppressWarnings(PHPMD.CamelCaseMethodName)
@@ -315,24 +313,24 @@ class EloquentAccountRepository implements AccountRepositoryInterface
protected function _createInitialBalance(\Account $account, $amount = 0, Carbon $date) protected function _createInitialBalance(\Account $account, $amount = 0, Carbon $date)
{ {
// get account type: // get account type:
$initialBalanceAT = \AccountType::where('description', 'Initial balance account')->first(); $initialBalanceAT = \AccountType::where('type', 'Initial balance account')->first();
// create new account: // create new account:
$initial = new \Account; $initial = new \Account;
$initial->accountType()->associate($initialBalanceAT); $initial->accountType()->associate($initialBalanceAT);
$initial->user()->associate(\Auth::user()); $initial->user()->associate(\Auth::user());
$initial->name = $account->name . ' initial balance'; $initial->name = $account->name . ' initial balance';
$initial->active = 0; $initial->active = 0;
if ($initial->validate()) { if ($initial->validate()) {
$initial->save(); $initial->save();
// create new transaction journal (and transactions): // create new transaction journal (and transactions):
/** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $transactionJournal */ /** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $transactionJournal */
$transactionJournal = \App::make( $transactionJournal = \App::make(
'Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface' 'Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'
); );
$transactionJournal->createSimpleJournal( $transactionJournal->createSimpleJournal(
$initial, $account, 'Initial Balance for ' . $account->name, $amount, $date $initial, $account, 'Initial Balance for ' . $account->name, $amount, $date
); );
return true; return true;

View File

@@ -64,8 +64,8 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
} }
// account types for both: // account types for both:
$toAT = $toAccount->accountType->description; $toAT = $toAccount->accountType->type;
$fromAT = $from->accountType->description; $fromAT = $from->accountType->type;
$journalType = null; $journalType = null;
@@ -287,6 +287,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
$fromAccount = $accountRepository->find(intval($data['account_id'])); $fromAccount = $accountRepository->find(intval($data['account_id']));
$toAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']); $toAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']);
break; break;
case 'deposit': case 'deposit':
$fromAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']); $fromAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']);
$toAccount = $accountRepository->find(intval($data['account_id'])); $toAccount = $accountRepository->find(intval($data['account_id']));
@@ -295,7 +296,6 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
$fromAccount = $accountRepository->find(intval($data['account_from_id'])); $fromAccount = $accountRepository->find(intval($data['account_from_id']));
$toAccount = $accountRepository->find(intval($data['account_to_id'])); $toAccount = $accountRepository->find(intval($data['account_to_id']));
break; break;
} }
// fall back to cash if necessary: // fall back to cash if necessary:

View File

@@ -0,0 +1,22 @@
<?php
namespace Firefly\Validation;
use Illuminate\Validation\Validator;
/**
* Class FireflyValidator
*
* @package Firefly\Validation
*/
class FireflyValidator extends Validator
{
public function validateAlphabasic($attribute, $value, $parameters)
{
$pattern = '/[^a-z_\-0-9 ]/i';
if (preg_match($pattern, $value)) {
return false;
} else {
return true;
}
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Firefly\Validation;
use Illuminate\Support\ServiceProvider;
class ValidationServiceProvider extends ServiceProvider
{
public function boot()
{
$this->app->validator->resolver(
function ($translator, $data, $rules, $messages) {
return new FireflyValidator($translator, $data, $rules, $messages);
}
);
}
public function register()
{
}
}

View File

@@ -1,20 +1,21 @@
<?php <?php
use LaravelBook\Ardent\Ardent as Ardent; use LaravelBook\Ardent\Ardent as Ardent;
use LaravelBook\Ardent\Builder;
/** /**
* Account * Account
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property integer $user_id * @property integer $user_id
* @property integer $account_type_id * @property integer $account_type_id
* @property string $name * @property string $name
* @property boolean $active * @property boolean $active
* @property-read \AccountType $accountType * @property-read \AccountType $accountType
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions * @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \Illuminate\Database\Eloquent\Collection|\Piggybank[] $piggybanks * @property-read \Illuminate\Database\Eloquent\Collection|\Piggybank[] $piggybanks
* @property-read \User $user * @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Account whereId($value) * @method static \Illuminate\Database\Query\Builder|\Account whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Account whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Account whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Account whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Account whereUpdatedAt($value)
@@ -22,6 +23,7 @@ use LaravelBook\Ardent\Ardent as Ardent;
* @method static \Illuminate\Database\Query\Builder|\Account whereAccountTypeId($value) * @method static \Illuminate\Database\Query\Builder|\Account whereAccountTypeId($value)
* @method static \Illuminate\Database\Query\Builder|\Account whereName($value) * @method static \Illuminate\Database\Query\Builder|\Account whereName($value)
* @method static \Illuminate\Database\Query\Builder|\Account whereActive($value) * @method static \Illuminate\Database\Query\Builder|\Account whereActive($value)
* @method static \Account accountTypeIn($types)
*/ */
class Account extends Ardent class Account extends Ardent
{ {
@@ -33,7 +35,7 @@ class Account extends Ardent
*/ */
public static $rules public static $rules
= [ = [
'name' => 'required|between:1,100', 'name' => ['required', 'between:1,100', 'alphabasic'],
'user_id' => 'required|exists:users,id', 'user_id' => 'required|exists:users,id',
'account_type_id' => 'required|exists:account_types,id', 'account_type_id' => 'required|exists:account_types,id',
'active' => 'required|boolean' 'active' => 'required|boolean'
@@ -63,10 +65,10 @@ class Account extends Ardent
return floatval( return floatval(
$this->transactions() $this->transactions()
->leftJoin( ->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id' 'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
) )
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount') ->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount')
); );
} }
@@ -96,7 +98,8 @@ class Account extends Ardent
public function predict( public function predict(
/** @noinspection PhpUnusedParameterInspection */ /** @noinspection PhpUnusedParameterInspection */
\Carbon\Carbon $date \Carbon\Carbon $date
) { )
{
return null; return null;
} }
@@ -110,4 +113,13 @@ class Account extends Ardent
return $this->belongsTo('User'); return $this->belongsTo('User');
} }
} public function scopeAccountTypeIn(Builder $query, array $types) {
if(is_null($this->joinedAccountTypes)) {
$query->leftJoin('account_types','account_types.id','=','accounts.account_type_id');
$this->joinedAccountTypes = true;
}
$query->whereIn('account_types.type',$types);
}
}

View File

@@ -1,21 +1,28 @@
<?php <?php
/** /**
* AccountType * AccountType
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property string $description * @property string $type
* @property boolean $editable
* @property-read \Illuminate\Database\Eloquent\Collection|\Account[] $accounts * @property-read \Illuminate\Database\Eloquent\Collection|\Account[] $accounts
* @method static \Illuminate\Database\Query\Builder|\AccountType whereId($value) * @method static \Illuminate\Database\Query\Builder|\AccountType whereId($value)
* @method static \Illuminate\Database\Query\Builder|\AccountType whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\AccountType whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\AccountType whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\AccountType whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\AccountType whereDescription($value) * @method static \Illuminate\Database\Query\Builder|\AccountType whereType($value)
* @method static \Illuminate\Database\Query\Builder|\AccountType whereEditable($value)
*/ */
class AccountType extends Eloquent class AccountType extends Eloquent
{ {
public static $rules
= [
'type' => ['required', 'between:1,50', 'alphabasic'],
'editable' => 'required|boolean',
];
/** /**
* @return \Illuminate\Database\Eloquent\Relations\HasMany * @return \Illuminate\Database\Eloquent\Relations\HasMany

View File

@@ -3,16 +3,16 @@
/** /**
* Budget * Budget
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property string $name * @property string $name
* @property integer $user_id * @property integer $user_id
* @property string $class * @property string $class
* @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits * @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals * @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions * @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user * @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Budget whereId($value) * @method static \Illuminate\Database\Query\Builder|\Budget whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Budget whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Budget whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Budget whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Budget whereUpdatedAt($value)

View File

@@ -3,16 +3,16 @@
/** /**
* Category * Category
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property string $name * @property string $name
* @property integer $user_id * @property integer $user_id
* @property string $class * @property string $class
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals * @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits * @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions * @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user * @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Category whereId($value) * @method static \Illuminate\Database\Query\Builder|\Category whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Category whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Category whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Category whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Category whereUpdatedAt($value)

View File

@@ -4,16 +4,16 @@ use Firefly\Database\SingleTableInheritanceEntity;
/** /**
* Component * Component
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property string $name * @property string $name
* @property integer $user_id * @property integer $user_id
* @property string $class * @property string $class
* @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits * @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals * @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions * @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user * @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Component whereId($value) * @method static \Illuminate\Database\Query\Builder|\Component whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Component whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Component whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Component whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Component whereUpdatedAt($value)

View File

@@ -7,16 +7,16 @@ use LaravelBook\Ardent\Ardent as Ardent;
/** /**
* Limit * Limit
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property integer $component_id * @property integer $component_id
* @property \Carbon\Carbon $startdate * @property \Carbon\Carbon $startdate
* @property float $amount * @property float $amount
* @property boolean $repeats * @property boolean $repeats
* @property string $repeat_freq * @property string $repeat_freq
* @property-read \Budget $budget * @property-read \Budget $budget
* @property-read \Component $component * @property-read \Component $component
* @property-read \Illuminate\Database\Eloquent\Collection|\LimitRepetition[] $limitrepetitions * @property-read \Illuminate\Database\Eloquent\Collection|\LimitRepetition[] $limitrepetitions
* @method static \Illuminate\Database\Query\Builder|\Limit whereId($value) * @method static \Illuminate\Database\Query\Builder|\Limit whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Limit whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Limit whereCreatedAt($value)

View File

@@ -5,14 +5,14 @@ use LaravelBook\Ardent\Ardent as Ardent;
/** /**
* LimitRepetition * LimitRepetition
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property integer $limit_id * @property integer $limit_id
* @property \Carbon\Carbon $startdate * @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $enddate * @property \Carbon\Carbon $enddate
* @property float $amount * @property float $amount
* @property-read \Limit $limit * @property-read \Limit $limit
* @method static \Illuminate\Database\Query\Builder|\LimitRepetition whereId($value) * @method static \Illuminate\Database\Query\Builder|\LimitRepetition whereId($value)
* @method static \Illuminate\Database\Query\Builder|\LimitRepetition whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\LimitRepetition whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\LimitRepetition whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\LimitRepetition whereUpdatedAt($value)

View File

@@ -5,25 +5,26 @@ use LaravelBook\Ardent\Ardent as Ardent;
/** /**
* Piggybank * Piggybank
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property integer $account_id * @property integer $account_id
* @property string $name * @property string $name
* @property float $targetamount * @property float $targetamount
* @property \Carbon\Carbon $startdate * @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $targetdate * @property \Carbon\Carbon $targetdate
* @property boolean $repeats * @property boolean $repeats
* @property string $rep_length * @property string $rep_length
* @property integer $rep_every * @property integer $rep_every
* @property integer $rep_times * @property integer $rep_times
* @property string $reminder * @property string $reminder
* @property integer $reminder_skip * @property integer $reminder_skip
* @property integer $order * @property integer $order
* @property-read \Account $account * @property-read \Account $account
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankRepetition[] $piggybankrepetitions * @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankRepetition[] $piggybankrepetitions
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankEvent[] $piggybankevents * @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankEvent[] $piggybankevents
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions * @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankReminder[] $piggybankreminders
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereId($value) * @method static \Illuminate\Database\Query\Builder|\Piggybank whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Piggybank whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Piggybank whereUpdatedAt($value)
@@ -39,7 +40,6 @@ use LaravelBook\Ardent\Ardent as Ardent;
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereReminder($value) * @method static \Illuminate\Database\Query\Builder|\Piggybank whereReminder($value)
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereReminderSkip($value) * @method static \Illuminate\Database\Query\Builder|\Piggybank whereReminderSkip($value)
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereOrder($value) * @method static \Illuminate\Database\Query\Builder|\Piggybank whereOrder($value)
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankReminder[] $piggybankreminders
*/ */
class Piggybank extends Ardent class Piggybank extends Ardent
{ {

View File

@@ -5,12 +5,12 @@ use LaravelBook\Ardent\Ardent as Ardent;
/** /**
* PiggybankEvent * PiggybankEvent
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property integer $piggybank_id * @property integer $piggybank_id
* @property \Carbon\Carbon $date * @property \Carbon\Carbon $date
* @property float $amount * @property float $amount
* @property-read \Piggybank $piggybank * @property-read \Piggybank $piggybank
* @method static \Illuminate\Database\Query\Builder|\PiggybankEvent whereId($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankEvent whereId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankEvent whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankEvent whereCreatedAt($value)

View File

@@ -2,7 +2,7 @@
use Carbon\Carbon; use Carbon\Carbon;
/** /**
* Class PiggybankReminder * PiggybankReminder
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
@@ -17,18 +17,18 @@ use Carbon\Carbon;
* @property-read \Piggybank $piggybank * @property-read \Piggybank $piggybank
* @property-read \RecurringTransaction $recurringTransaction * @property-read \RecurringTransaction $recurringTransaction
* @property-read \User $user * @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereId($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereClass($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereClass($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder wherePiggybankId($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankReminder wherePiggybankId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereRecurringTransactionId($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereRecurringTransactionId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereUserId($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereStartdate($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereEnddate($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereActive($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereActive($value)
* @method static \Reminder validOn($date) * @method static \Reminder validOn($date)
* @method static \Reminder validOnOrAfter($date) * @method static \Reminder validOnOrAfter($date)
*/ */
class PiggybankReminder extends Reminder class PiggybankReminder extends Reminder
{ {

View File

@@ -1,17 +1,16 @@
<?php <?php
use LaravelBook\Ardent\Ardent as Ardent; use LaravelBook\Ardent\Ardent as Ardent;
/** /**
* PiggybankRepetition * PiggybankRepetition
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property integer $piggybank_id * @property integer $piggybank_id
* @property \Carbon\Carbon $startdate * @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $targetdate * @property \Carbon\Carbon $targetdate
* @property float $currentamount * @property float $currentamount
* @property-read \Piggybank $piggybank * @property-read \Piggybank $piggybank
* @method static \Illuminate\Database\Query\Builder|\PiggybankRepetition whereId($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankRepetition whereId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankRepetition whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\PiggybankRepetition whereCreatedAt($value)

View File

@@ -2,17 +2,16 @@
use LaravelBook\Ardent\Ardent; use LaravelBook\Ardent\Ardent;
/** /**
* Preference * Preference
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property integer $user_id * @property integer $user_id
* @property string $name * @property string $name
* @property string $data * @property string $data
* @property-read \User $user * @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Preference whereId($value) * @method static \Illuminate\Database\Query\Builder|\Preference whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Preference whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Preference whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Preference whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Preference whereUpdatedAt($value)

View File

@@ -5,20 +5,21 @@ use LaravelBook\Ardent\Ardent;
/** /**
* RecurringTransaction * RecurringTransaction
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property integer $user_id * @property integer $user_id
* @property string $name * @property string $name
* @property string $match * @property string $match
* @property float $amount_max * @property float $amount_max
* @property float $amount_min * @property float $amount_min
* @property \Carbon\Carbon $date * @property \Carbon\Carbon $date
* @property boolean $active * @property boolean $active
* @property boolean $automatch * @property boolean $automatch
* @property string $repeat_freq * @property string $repeat_freq
* @property integer $skip * @property integer $skip
* @property-read \User $user * @property-read \Illuminate\Database\Eloquent\Collection|\RecurringTransactionReminder[] $reminders
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereId($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereUpdatedAt($value)
@@ -32,7 +33,6 @@ use LaravelBook\Ardent\Ardent;
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereAutomatch($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereAutomatch($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereRepeatFreq($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereRepeatFreq($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereSkip($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereSkip($value)
* @property-read \Illuminate\Database\Eloquent\Collection|\RecurringTransactionReminder[] $reminders
*/ */
class RecurringTransaction extends Ardent class RecurringTransaction extends Ardent
{ {

View File

@@ -1,7 +1,7 @@
<?php <?php
/** /**
* Class RecurringTransactionReminder * RecurringTransactionReminder
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
@@ -16,18 +16,18 @@
* @property-read \Piggybank $piggybank * @property-read \Piggybank $piggybank
* @property-read \RecurringTransaction $recurringTransaction * @property-read \RecurringTransaction $recurringTransaction
* @property-read \User $user * @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereId($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereClass($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereClass($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder wherePiggybankId($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder wherePiggybankId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereRecurringTransactionId($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereRecurringTransactionId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereUserId($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereStartdate($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereEnddate($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereActive($value) * @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereActive($value)
* @method static \Reminder validOn($date) * @method static \Reminder validOn($date)
* @method static \Reminder validOnOrAfter($date) * @method static \Reminder validOnOrAfter($date)
*/ */
class RecurringTransactionReminder extends Reminder class RecurringTransactionReminder extends Reminder
{ {

View File

@@ -3,10 +3,8 @@
use Carbon\Carbon; use Carbon\Carbon;
use Firefly\Database\SingleTableInheritanceEntity; use Firefly\Database\SingleTableInheritanceEntity;
/** /**
* Class Reminder * Reminder
* // reminder for: recurring, piggybank.
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
@@ -21,18 +19,18 @@ use Firefly\Database\SingleTableInheritanceEntity;
* @property-read \Piggybank $piggybank * @property-read \Piggybank $piggybank
* @property-read \RecurringTransaction $recurringTransaction * @property-read \RecurringTransaction $recurringTransaction
* @property-read \User $user * @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Reminder whereId($value) * @method static \Illuminate\Database\Query\Builder|\Reminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Reminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Reminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereClass($value) * @method static \Illuminate\Database\Query\Builder|\Reminder whereClass($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder wherePiggybankId($value) * @method static \Illuminate\Database\Query\Builder|\Reminder wherePiggybankId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereRecurringTransactionId($value) * @method static \Illuminate\Database\Query\Builder|\Reminder whereRecurringTransactionId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereUserId($value) * @method static \Illuminate\Database\Query\Builder|\Reminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereStartdate($value) * @method static \Illuminate\Database\Query\Builder|\Reminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereEnddate($value) * @method static \Illuminate\Database\Query\Builder|\Reminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereActive($value) * @method static \Illuminate\Database\Query\Builder|\Reminder whereActive($value)
* @method static \Reminder validOn($date) * @method static \Reminder validOn($date)
* @method static \Reminder validOnOrAfter($date) * @method static \Reminder validOnOrAfter($date)
*/ */
class Reminder extends SingleTableInheritanceEntity class Reminder extends SingleTableInheritanceEntity
{ {

View File

@@ -1,25 +1,27 @@
<?php <?php
use Carbon\Carbon;
use LaravelBook\Ardent\Ardent; use LaravelBook\Ardent\Ardent;
use LaravelBook\Ardent\Builder;
/** /**
* Transaction * Transaction
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property integer $account_id * @property integer $account_id
* @property integer $piggybank_id * @property integer $piggybank_id
* @property integer $transaction_journal_id * @property integer $transaction_journal_id
* @property string $description * @property string $description
* @property float $amount * @property float $amount
* @property-read \Account $account * @property-read \Account $account
* @property-read \Illuminate\Database\Eloquent\Collection|\Budget[] $budgets * @property-read \Illuminate\Database\Eloquent\Collection|\Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\Category[] $categories * @property-read \Illuminate\Database\Eloquent\Collection|\Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components * @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
* @property-read \Piggybank $piggybank * @property-read \Piggybank $piggybank
* @property-read \TransactionJournal $transactionJournal * @property-read \TransactionJournal $transactionJournal
* @method static \Illuminate\Database\Query\Builder|\Transaction whereId($value) * @method static \Illuminate\Database\Query\Builder|\Transaction whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Transaction whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Transaction whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Transaction whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\Transaction whereUpdatedAt($value)
@@ -28,6 +30,12 @@ use LaravelBook\Ardent\Ardent;
* @method static \Illuminate\Database\Query\Builder|\Transaction whereTransactionJournalId($value) * @method static \Illuminate\Database\Query\Builder|\Transaction whereTransactionJournalId($value)
* @method static \Illuminate\Database\Query\Builder|\Transaction whereDescription($value) * @method static \Illuminate\Database\Query\Builder|\Transaction whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\Transaction whereAmount($value) * @method static \Illuminate\Database\Query\Builder|\Transaction whereAmount($value)
* @method static \Transaction account($account)
* @method static \Transaction after($date)
* @method static \Transaction before($date)
* @method static \Transaction lessThan($amount)
* @method static \Transaction moreThan($amount)
* @method static \Transaction transactionTypes($types)
*/ */
class Transaction extends Ardent class Transaction extends Ardent
{ {
@@ -81,6 +89,56 @@ class Transaction extends Ardent
return $this->belongsTo('Piggybank'); return $this->belongsTo('Piggybank');
} }
public function scopeAccount(Builder $query, Account $account)
{
$query->where('transactions.account_id', $account->id);
}
public function scopeAfter(Builder $query, Carbon $date)
{
if (is_null($this->joinedJournals)) {
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=',
'transactions.transaction_journal_id');
$this->joinedJournals = true;
}
$query->where('transaction_journals.date', '>=', $date->format('Y-m-d'));
}
public function scopeBefore(Builder $query, Carbon $date)
{
if (is_null($this->joinedJournals)) {
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=',
'transactions.transaction_journal_id');
$this->joinedJournals = true;
}
$query->where('transaction_journals.date', '<=', $date->format('Y-m-d'));
}
public function scopeLessThan(Builder $query, $amount)
{
$query->where('amount', '<', $amount);
}
public function scopeMoreThan(Builder $query, $amount)
{
$query->where('amount', '>', $amount);
}
public function scopeTransactionTypes(Builder $query, array $types)
{
if (is_null($this->joinedJournals)) {
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=',
'transactions.transaction_journal_id');
$this->joinedJournals = true;
}
if (is_null($this->joinedTransactionTypes)) {
$query->leftJoin('transaction_types', 'transaction_types.id', '=',
'transaction_journals.transaction_type_id');
$this->joinedTransactionTypes = true;
}
$query->whereIn('transaction_types.type', $types);
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/ */

View File

@@ -3,10 +3,10 @@
/** /**
* TransactionCurrency * TransactionCurrency
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property string $code * @property string $code
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals * @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @method static \Illuminate\Database\Query\Builder|\TransactionCurrency whereId($value) * @method static \Illuminate\Database\Query\Builder|\TransactionCurrency whereId($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionCurrency whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\TransactionCurrency whereCreatedAt($value)

View File

@@ -2,29 +2,29 @@
use Carbon\Carbon; use Carbon\Carbon;
use LaravelBook\Ardent\Ardent; use LaravelBook\Ardent\Ardent;
use LaravelBook\Ardent\Builder;
/** /**
* TransactionJournal * TransactionJournal
* *
* @property integer $id * @property integer $id
* @property Carbon $created_at * @property \Carbon\Carbon $created_at
* @property Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property integer $user_id * @property integer $user_id
* @property integer $transaction_type_id * @property integer $transaction_type_id
* @property integer $transaction_currency_id * @property integer $transaction_currency_id
* @property string $description * @property string $description
* @property boolean $completed * @property boolean $completed
* @property Carbon $date * @property \Carbon\Carbon $date
* @property-read \Illuminate\Database\Eloquent\Collection|\ * @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets * 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\ * @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories * 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components * @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
* @property-read \TransactionCurrency $transactionCurrency * @property-read \TransactionCurrency $transactionCurrency
* @property-read \TransactionType $transactionType * @property-read \TransactionType $transactionType
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions * @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user * @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereId($value) * @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereId($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereUpdatedAt($value)
@@ -34,13 +34,19 @@ use LaravelBook\Ardent\Ardent;
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDescription($value) * @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCompleted($value) * @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCompleted($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDate($value) * @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDate($value)
* @method static \TransactionJournal account($account)
* @method static \TransactionJournal after($date) * @method static \TransactionJournal after($date)
* @method static \TransactionJournal before($date) * @method static \TransactionJournal before($date)
* @method static \TransactionJournal defaultSorting()
* @method static \TransactionJournal moreThan($amount)
* @method static \TransactionJournal lessThan($amount)
* @method static \TransactionJournal onDate($date)
* @method static \TransactionJournal transactionTypes($types)
* @method static \TransactionJournal withRelevantData()
* @property-read \Illuminate\Database\Eloquent\Collection|\ * @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets * 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\ * @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories * 'Category[] $categories
* @method static \TransactionJournal onDate($date)
*/ */
class TransactionJournal extends Ardent class TransactionJournal extends Ardent
{ {
@@ -61,7 +67,7 @@ class TransactionJournal extends Ardent
public function budgets() public function budgets()
{ {
return $this->belongsToMany( return $this->belongsToMany(
'Budget', 'component_transaction_journal', 'transaction_journal_id', 'component_id' 'Budget', 'component_transaction_journal', 'transaction_journal_id', 'component_id'
); );
} }
@@ -71,7 +77,7 @@ class TransactionJournal extends Ardent
public function categories() public function categories()
{ {
return $this->belongsToMany( return $this->belongsToMany(
'Category', 'component_transaction_journal', 'transaction_journal_id', 'component_id' 'Category', 'component_transaction_journal', 'transaction_journal_id', 'component_id'
); );
} }
@@ -91,9 +97,18 @@ class TransactionJournal extends Ardent
return ['created_at', 'updated_at', 'date']; return ['created_at', 'updated_at', 'date'];
} }
public function scopeAccount(Builder $query, \Account $account)
{
if (!isset($this->joinedTransactions)) {
$query->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id');
$this->joinedTransactions = true;
}
$query->where('transactions.account_id', $account->id);
}
/** /**
* @param $query * @param $query
* @param Carbon $date * @param Carbon $date
* *
* @return mixed * @return mixed
*/ */
@@ -104,7 +119,7 @@ class TransactionJournal extends Ardent
/** /**
* @param $query * @param $query
* @param Carbon $date * @param Carbon $date
* *
* @return mixed * @return mixed
*/ */
@@ -113,6 +128,33 @@ class TransactionJournal extends Ardent
return $query->where('date', '<=', $date->format('Y-m-d')); return $query->where('date', '<=', $date->format('Y-m-d'));
} }
public function scopeDefaultSorting(Builder $query)
{
$query->orderBy('date', 'DESC')->orderBy('transaction_journals.id', 'DESC');
}
public function scopeMoreThan(Builder $query, $amount)
{
if (is_null($this->joinedTransactions)) {
$query->leftJoin('transactions', 'transactions.transaction_journal_id', '=',
'transaction_journals.id');
$this->joinedTransactions = true;
}
$query->where('transactions.amount', '>=', $amount);
}
public function scopeLessThan(Builder $query, $amount)
{
if (is_null($this->joinedTransactions)) {
$query->leftJoin('transactions', 'transactions.transaction_journal_id', '=',
'transaction_journals.id');
$this->joinedTransactions = true;
}
$query->where('transactions.amount', '<=', $amount);
}
/** /**
* @param $query * @param $query
* @param Carbon $date * @param Carbon $date
@@ -124,6 +166,33 @@ class TransactionJournal extends Ardent
return $query->where('date', '=', $date->format('Y-m-d')); return $query->where('date', '=', $date->format('Y-m-d'));
} }
public function scopeTransactionTypes(Builder $query, array $types)
{
if (is_null($this->joinedTransactionTypes)) {
$query->leftJoin('transaction_types', 'transaction_types.id', '=',
'transaction_journals.transaction_type_id');
$this->joinedTransactionTypes = true;
}
$query->whereIn('transaction_types.type', $types);
}
/**
* Automatically includes the 'with' parameters to get relevant related
* objects.
*
* @param $query
*/
public function scopeWithRelevantData(Builder $query)
{
$query->with(
['transactions' => function ($q) {
$q->orderBy('amount', 'ASC');
}, 'transactiontype', 'components' => function ($q) {
$q->orderBy('class');
}, 'transactions.account.accounttype']
);
}
/** /**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/ */
@@ -158,4 +227,4 @@ class TransactionJournal extends Ardent
return $this->belongsTo('User'); return $this->belongsTo('User');
} }
} }

View File

@@ -5,10 +5,10 @@ use LaravelBook\Ardent\Ardent;
/** /**
* TransactionType * TransactionType
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property string $type * @property string $type
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionJournals * @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionJournals
* @method static \Illuminate\Database\Query\Builder|\TransactionType whereId($value) * @method static \Illuminate\Database\Query\Builder|\TransactionType whereId($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionType whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\TransactionType whereCreatedAt($value)

View File

@@ -10,21 +10,23 @@ use LaravelBook\Ardent\Ardent;
/** /**
* User * User
* *
* @property integer $id * @property integer $id
* @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at * @property \Carbon\Carbon $updated_at
* @property string $email * @property string $email
* @property string $password * @property string $password
* @property string $reset * @property string $reset
* @property string $remember_token * @property string $remember_token
* @property boolean $migrated * @property boolean $migrated
* @property-read \Illuminate\Database\Eloquent\Collection|\Account[] $accounts * @property-read \Illuminate\Database\Eloquent\Collection|\Account[] $accounts
* @property-read \Illuminate\Database\Eloquent\Collection|\Budget[] $budgets * @property-read \Illuminate\Database\Eloquent\Collection|\Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\Category[] $categories * @property-read \Illuminate\Database\Eloquent\Collection|\Reminder[] $reminders
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components * @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankReminder[] $piggybankreminders
* @property-read \Illuminate\Database\Eloquent\Collection|\Preference[] $preferences * @property-read \Illuminate\Database\Eloquent\Collection|\Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
* @property-read \Illuminate\Database\Eloquent\Collection|\Preference[] $preferences
* @property-read \Illuminate\Database\Eloquent\Collection|\RecurringTransaction[] $recurringtransactions * @property-read \Illuminate\Database\Eloquent\Collection|\RecurringTransaction[] $recurringtransactions
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals * @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @method static \Illuminate\Database\Query\Builder|\User whereId($value) * @method static \Illuminate\Database\Query\Builder|\User whereId($value)
* @method static \Illuminate\Database\Query\Builder|\User whereCreatedAt($value) * @method static \Illuminate\Database\Query\Builder|\User whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\User whereUpdatedAt($value) * @method static \Illuminate\Database\Query\Builder|\User whereUpdatedAt($value)
@@ -33,8 +35,6 @@ use LaravelBook\Ardent\Ardent;
* @method static \Illuminate\Database\Query\Builder|\User whereReset($value) * @method static \Illuminate\Database\Query\Builder|\User whereReset($value)
* @method static \Illuminate\Database\Query\Builder|\User whereRememberToken($value) * @method static \Illuminate\Database\Query\Builder|\User whereRememberToken($value)
* @method static \Illuminate\Database\Query\Builder|\User whereMigrated($value) * @method static \Illuminate\Database\Query\Builder|\User whereMigrated($value)
* @property-read \Illuminate\Database\Eloquent\Collection|\Reminder[] $reminders
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankReminder[] $piggybankreminders
*/ */
class User extends Ardent implements UserInterface, RemindableInterface class User extends Ardent implements UserInterface, RemindableInterface
{ {

View File

@@ -1,23 +1,33 @@
<?php <?php
//use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
// models: // models:
Route::bind('account', function($value, $route) Route::bind('account', function($value, $route)
{ {
if(Auth::check()) { if(Auth::check()) {
return Account:: $account = Account::
where('id', $value)-> leftJoin('account_types','account_types.id','=','accounts.account_type_id')->
where('user_id',Auth::user()->id)->first(); where('account_types.editable',1)->
where('accounts.id', $value)->
where('user_id',Auth::user()->id)->
first(['accounts.*']);
if($account) {
return $account;
}
} }
return null; App::abort(404);
}); });
Route::bind('accountname', function($value, $route) Route::bind('accountname', function($value, $route)
{ {
if(Auth::check()) { if(Auth::check()) {
$type = AccountType::where('description','Default account')->first();
return Account:: return Account::
leftJoin('account_types','account_types.id','=','accounts.account_type_id')->
where('account_types.editable',1)->
where('name', $value)-> where('name', $value)->
where('account_type_id',$type->id)->
where('user_id',Auth::user()->id)->first(); where('user_id',Auth::user()->id)->first();
} }
return null; return null;

View File

@@ -1,452 +0,0 @@
<?php
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class AccountControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
* @coversDefaultClass \AccountController
*/
class AccountControllerTest extends TestCase
{
protected $_repository;
protected $_user;
protected $_accounts;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_repository = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
$this->_accounts = $this->mock('Firefly\Helper\Controllers\AccountInterface');
$this->_user = m::mock('User', 'Eloquent');
}
public function tearDown()
{
Mockery::close();
}
/**
* @covers ::create
*/
public function testCreate()
{
View::shouldReceive('make')->with('accounts.create')->once();
$this->action('GET', 'AccountController@create');
$this->assertResponseOk();
}
/**
* @covers ::delete
*/
public function testDelete()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'AccountController@delete', $account->id);
$this->assertViewHas('account');
$this->assertResponseOk();
}
/**
* @covers ::delete
*/
public function testDeleteWrongType()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Initial balance account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'AccountController@delete', $account->id);
$this->assertViewHas('message');
$this->assertResponseOk();
}
/**
* @covers ::destroy
*/
public function testDestroy()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->once()->andReturn($this->_user);
Auth::shouldReceive('check')->once()->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_repository->shouldReceive('destroy')->once()->andReturn(true);
$this->action('POST', 'AccountController@destroy', $account->id);
$this->assertRedirectedToRoute('accounts.index');
$this->assertSessionHas('success');
}
/**
* @covers ::destroy
*/
public function testDestroyWrongType()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Initial balance account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->once()->andReturn($this->_user);
Auth::shouldReceive('check')->once()->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->action('POST', 'AccountController@destroy', $account->id);
$this->assertViewHas('message');
$this->assertResponseOk();
}
/**
* @covers ::destroy
*/
public function testDestroyFails()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->once()->andReturn($this->_user);
Auth::shouldReceive('check')->once()->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_repository->shouldReceive('destroy')->once()->andReturn(false);
$this->action('POST', 'AccountController@destroy', $account->id);
$this->assertRedirectedToRoute('accounts.index');
$this->assertSessionHas('error');
}
public function testEdit()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_accounts->shouldReceive('openingBalanceTransaction')->once()->andReturn(null);
// test if the view works:
View::shouldReceive('make')->with('accounts.edit')->once()->andReturn(m::self())->shouldReceive('with')->with(
'account', m::any()
)
->andReturn(m::self())->shouldReceive('with')->with('openingBalance', null)->andReturn(m::self());
$this->action('GET', 'AccountController@edit', $account->id);
$this->assertResponseOk();
}
public function testEditWrongType()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Initial balance account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'AccountController@edit', $account->id);
$this->assertViewHas('message');
$this->assertResponseOk();
}
public function testIndex()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
$collection = new Collection();
$collection->add($account);
$list = [
'personal' => [],
'beneficiaries' => [],
'initial' => [],
'cash' => []
];
$this->_repository->shouldReceive('get')->once()->andReturn($collection);
$this->_accounts->shouldReceive('index')->with($collection)->once()->andReturn($list);
$this->action('GET', 'AccountController@index');
$this->assertResponseOk();
}
public function testShow()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn($account->email);
$this->session(['start' => new Carbon, 'end' => new Carbon]);
// some more mockery
$paginator = \Paginator::make([], 0, 10);
$data = [
'statistics' => [
'period' => [
'in' => 0,
'out' => 0,
'diff' => 0,
't_in' => 0,
't_out' => 0,
't_diff' => 0
],
'categories' => [],
'budgets' => [],
'accounts' => []
],
'journals' => $paginator,
];
$this->_accounts->shouldReceive('show')->once()->andReturn($data);
$this->action('GET', 'AccountController@show', $account->id);
$this->assertResponseOk();
}
public function testShowWrongType()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Initial balance account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn($account->email);
$this->action('GET', 'AccountController@show', $account->id);
$this->assertViewHas('message');
$this->assertResponseOk();
}
public function testStore()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
$this->_repository->shouldReceive('store')->andReturn($account);
$this->action('POST', 'AccountController@store');
$this->assertRedirectedToRoute('accounts.index');
}
public function testStoreFails()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
unset($account->name);
$this->_repository->shouldReceive('store')->andReturn($account);
$this->action('POST', 'AccountController@store');
$this->assertRedirectedToRoute('accounts.create');
}
public function testStoreRecreate()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
$this->_repository->shouldReceive('store')->andReturn($account);
$this->action('POST', 'AccountController@store', ['create' => '1']);
$this->assertRedirectedToRoute('accounts.create');
}
public function testUpdate()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_repository->shouldReceive('update')->andReturn($account);
$this->action('POST', 'AccountController@update', $account->id);
$this->assertRedirectedToRoute('accounts.index');
}
public function testUpdateWrongType()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Initial balance account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_repository->shouldReceive('update')->andReturn($account);
$this->action('POST', 'AccountController@update', $account->id);
$this->assertViewHas('message');
$this->assertResponseOk();
}
public function testUpdateFails()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
unset($account->name);
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_repository->shouldReceive('update')->andReturn($account);
$this->action('POST', 'AccountController@update', $account->id);
$this->assertRedirectedToRoute('accounts.edit', $account->id);
}
}

View File

@@ -0,0 +1,373 @@
<?php
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class AccountTest
*
* Test EVERYTHING related to accounts. Models, views controllers.
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
* @coversDefaultClass \AccountController
*/
class AccountTest extends TestCase
{
protected $_repository;
protected $_user;
protected $_accounts;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_repository = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
$this->_accounts = $this->mock('Firefly\Helper\Controllers\AccountInterface');
$this->_user = m::mock('User', 'Eloquent');
}
public function tearDown()
{
Mockery::close();
}
public function testAccountModel()
{
// create account and user:
$account = f::create('Account');
$user = f::create('User');
$user->accounts()->save($account);
// new account? balance should be 0.00
$this->assertEquals(0.0, $account->balance());
// create and link two transactions / piggybanks:
for ($i = 0; $i < 2; $i++) {
$transaction = f::create('Transaction');
$transaction->account()->associate($account);
$transaction->save();
$piggy = f::create('Piggybank');
$piggy->account()->associate($account);
$piggy->save();
}
// test related models
$this->assertCount(2, $account->transactions()->get());
$this->assertCount(2, $account->piggybanks()->get());
// predict should always be null:
$this->assertNull($account->predict(new Carbon));
// user should equal test user:
$this->assertEquals($user->id, $account->user()->first()->id);
$this->assertEquals('testing',\App::environment());
\Log::debug('Hello from test!');
\Log::debug('Number of accounts: ' . \Account::count());
\Log::debug('Number of account types: ' . \AccountType::count());
foreach(\AccountType::get() as $t) {
\Log::debug('AccountType: #'.$t->id.', ' . $t->type);
}
// whatever the account type of this account, searching for it using the
// scope method should return one account:
$accountType = $account->accounttype()->first();
$accounts = $accountType->accounts()->count();
$this->assertCount($accounts, \Account::AccountTypeIn([$accountType->type])->get());
}
/**
* @covers ::create
*/
public function testCreate()
{
// test the view:
View::shouldReceive('make')->once()->with('accounts.create')->andReturn(m::self())
->shouldReceive('with')->once()->with('title', 'Create account');
// call and final test:
$this->action('GET', 'AccountController@create');
$this->assertResponseOk();
}
/**
* @covers ::delete
*/
public function testDelete()
{
// some prep work.
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = \AccountType::whereType('Default account')->first();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding with the account to delete:
Auth::shouldReceive('user')->andReturn($this->_user)->between(1, 3);
Auth::shouldReceive('check')->andReturn(true)->between(1, 2);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
// test the view:
View::shouldReceive('make')->once()->with('accounts.delete')->andReturn(m::self())
->shouldReceive('with')->once()->with('account', m::any())->andReturn(m::self())
->shouldReceive('with')->once()->with('title', 'Delete account "' . $account->name . '"');
// call and final test:
$this->action('GET', 'AccountController@delete', $account->id);
$this->assertResponseOk();
}
/**
* @covers ::destroy
*/
public function testDestroy()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = \AccountType::whereType('Default account')->first();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding with the account to destroy:
Auth::shouldReceive('user')->andReturn($this->_user)->between(1, 3);
Auth::shouldReceive('check')->andReturn(true)->between(1, 2);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
// test if the repository receives an argument:
$this->_repository->shouldReceive('destroy')->once();
// post it:
$this->action('POST', 'AccountController@destroy', $account->id);
$this->assertRedirectedToRoute('accounts.index');
$this->assertSessionHas('success');
}
/**
* @covers ::edit
*/
public function testEdit()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = \AccountType::whereType('Default account')->first();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding with the account to edit:
Auth::shouldReceive('user')->andReturn($this->_user)->between(1, 3);
Auth::shouldReceive('check')->andReturn(true)->between(1, 2);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
// test if the repository works:
$this->_accounts->shouldReceive('openingBalanceTransaction')->once()->with(m::any())->andReturn(null);
// test if the view works:
View::shouldReceive('make')->once()->with('accounts.edit')->andReturn(m::self())
->shouldReceive('with')->once()->with('account', m::any())->andReturn(m::self())
->shouldReceive('with')->once()->with('openingBalance', null)->andReturn(m::self())
->shouldReceive('with')->once()->with('title', 'Edit account "' . $account->name . '"');
$this->action('GET', 'AccountController@edit', $account->id);
$this->assertResponseOk();
}
/**
* @covers ::index
*/
public function testIndex()
{
// two account types:
$personalType = \AccountType::whereType('Default account')->first();
$benType = \AccountType::whereType('Beneficiary account')->first();
// create two accounts:
/** @var \Account $account */
$personal = f::create('Account');
$personal->accountType()->associate($personalType);
$personal->save();
$ben = f::create('Account');
$ben->accountType()->associate($benType);
$ben->save();
/** @var \AccountType $accountType */
$collection = new Collection();
$collection->add($personal);
$collection->add($ben);
$list = [
'personal' => [$personal],
'beneficiaries' => [$ben],
];
// test repository:
$this->_repository->shouldReceive('get')->once()->andReturn($collection);
// test view:
View::shouldReceive('make')->once()->with('accounts.index')->andReturn(m::self())
->shouldReceive('with')->once()->with('accounts', $list)->andReturn(m::self())
->shouldReceive('with')->once()->with('title', 'All your accounts');
$this->action('GET', 'AccountController@index');
$this->assertResponseOk();
}
/**
* @covers ::show
*/
public function testShow()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = \AccountType::whereType('Default account')->first();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding with the account to show:
Auth::shouldReceive('user')->andReturn($this->_user)->between(1, 3);
Auth::shouldReceive('check')->andReturn(true)->between(1, 2);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
// test view:
View::shouldReceive('make')->once()->with('accounts.show')->andReturn(m::self())
->shouldReceive('with')->once()->with('account', m::any())->andReturn(m::self())
->shouldReceive('with')->once()->with('show', [])->andReturn(m::self())
->shouldReceive('with')->once()->with('title', 'Details for account "' . $account->name . '"');
$this->_accounts->shouldReceive('show')->once()->andReturn([]);
$this->action('GET', 'AccountController@show', $account->id);
$this->assertResponseOk();
}
/**
* @covers ::store
*/
public function testStore()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = \AccountType::whereType('Default account')->first();
$account->accountType()->associate($accountType);
$account->save();
$this->_repository->shouldReceive('store')->andReturn($account);
$this->action('POST', 'AccountController@store');
$this->assertRedirectedToRoute('accounts.index');
$this->assertSessionHas('success');
}
/**
* @covers ::store
*/
public function testStoreFails()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = \AccountType::whereType('Default account')->first();
$account->accountType()->associate($accountType);
$account->save();
unset($account->name);
$this->_repository->shouldReceive('store')->andReturn($account);
$this->action('POST', 'AccountController@store');
$this->assertRedirectedToRoute('accounts.create');
$this->assertSessionHas('error');
}
public function testStoreRecreate()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = \AccountType::whereType('Default account')->first();
$account->accountType()->associate($accountType);
$account->save();
$this->_repository->shouldReceive('store')->andReturn($account);
$this->action('POST', 'AccountController@store', ['create' => '1']);
$this->assertRedirectedToRoute('accounts.create');
$this->assertSessionHas('success');
}
public function testUpdate()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = \AccountType::whereType('Default account')->first();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding with the account to update:
Auth::shouldReceive('user')->andReturn($this->_user)->between(1, 3);
Auth::shouldReceive('check')->andReturn(true)->between(1, 2);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
// test
$this->_repository->shouldReceive('update')->andReturn($account);
$this->action('POST', 'AccountController@update', $account->id);
$this->assertRedirectedToRoute('accounts.index');
$this->assertSessionHas('success');
}
public function testUpdateFails()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = \AccountType::whereType('Default account')->first();
$account->accountType()->associate($accountType);
$account->save();
unset($account->name);
// for successful binding with the account to show:
Auth::shouldReceive('user')->andReturn($this->_user)->between(1, 3);
Auth::shouldReceive('check')->andReturn(true)->between(1, 2);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
// test
$this->_repository->shouldReceive('update')->andReturn($account);
$this->action('POST', 'AccountController@update', $account->id);
$this->assertRedirectedToRoute('accounts.edit', $account->id);
$this->assertSessionHas('error');
}
}

View File

@@ -77,10 +77,8 @@ class ChartControllerTest extends TestCase
public function testHomeAccountInfo() public function testHomeAccountInfo()
{ {
$account = f::create('Account'); $account = f::create('Account');
$type = f::create('AccountType'); $accountType = \AccountType::whereType('Default account')->first();
$type->description = 'Default account'; $account->accounttype()->associate($accountType);
$type->save();
$account->accounttype()->associate($type);
$account->save(); $account->save();
// for successful binding: // for successful binding:
Auth::shouldReceive('user')->andReturn($account->user()->first()); Auth::shouldReceive('user')->andReturn($account->user()->first());

View File

@@ -2,17 +2,9 @@
use League\FactoryMuffin\Facade; use League\FactoryMuffin\Facade;
Facade::define( Facade::define(
'AccountType', 'AccountType',
[ [
'description' => function () { 'type' => 'unique:word',
$types = [ 'editable' => 1
'Default account', ]
'Cash account',
'Initial balance account',
'Beneficiary account'
];
return $types[rand(0, 3)];
}
]
); );

View File

@@ -7,7 +7,7 @@ Facade::define(
[ [
'account_id' => 'factory|Account', 'account_id' => 'factory|Account',
'name' => 'string', 'name' => 'word',
'targetamount' => 'integer', 'targetamount' => 'integer',
'startdate' => function () { 'startdate' => function () {
$start = new Carbon; $start = new Carbon;

View File

@@ -119,51 +119,51 @@ class ModelTest extends TestCase
} }
/** // /**
* @expectedException \Firefly\Exception\FireflyException // * @expectedException \Firefly\Exception\FireflyException
*/ // */
public function testLimitrepetition() // public function testLimitrepetition()
{ // {
$limit = f::create('Limit'); // $limit = f::create('Limit');
$rep = f::create('LimitRepetition'); // $rep = f::create('LimitRepetition');
$budget = f::create('Budget'); // $budget = f::create('Budget');
$journal = f::create('TransactionJournal'); // $journal = f::create('TransactionJournal');
$one = f::create('Transaction'); // $one = f::create('Transaction');
$two = f::create('Transaction'); // $two = f::create('Transaction');
$one->amount = 300; // $one->amount = 300;
$two->amount = -300; // $two->amount = -300;
//
$rep->limit()->associate($limit); // $rep->limit()->associate($limit);
$limit->budget()->associate($budget); // $limit->budget()->associate($budget);
$journal->transactions()->save($one); // $journal->transactions()->save($one);
$journal->transactions()->save($two); // $journal->transactions()->save($two);
$journal->budgets()->save($budget); // $journal->budgets()->save($budget);
//
$this->assertEquals(($rep->amount - 300), $rep->left()); // $this->assertEquals(($rep->amount - 300), $rep->left());
//
// repeat frequency (not present) for periodOrder // // repeat frequency (not present) for periodOrder
$testDate = new Carbon; // $testDate = new Carbon;
$testDate->startOfMonth(); // $testDate->startOfMonth();
$rep->repeat_freq = null; // $rep->repeat_freq = null;
//
// this test will FAIL because nowadays the $rep has a random thing. // // this test will FAIL because nowadays the $rep has a random thing.
// TODO // // TODO
//
//
//$this->assertEquals($testDate->format('Ymd') . '-3', $rep->periodOrder()); // //$this->assertEquals($testDate->format('Ymd') . '-3', $rep->periodOrder());
//
// repeat frequency (present) for periodOrder // // repeat frequency (present) for periodOrder
$list = ['yearly', 'half-year', 'quarterly', 'monthly', 'weekly', 'daily']; // $list = ['yearly', 'half-year', 'quarterly', 'monthly', 'weekly', 'daily'];
foreach ($list as $index => $entry) { // foreach ($list as $index => $entry) {
$rep->repeat_freq = $entry; // $rep->repeat_freq = $entry;
$this->assertEquals($testDate->format('Ymd') . '-' . $index, $rep->periodOrder()); // $this->assertEquals($testDate->format('Ymd') . '-' . $index, $rep->periodOrder());
} // }
//
// repeat freq (invalid) for periodOrder // // repeat freq (invalid) for periodOrder
$rep->repeat_freq = 'bad'; // $rep->repeat_freq = 'bad';
$rep->periodOrder(); // $rep->periodOrder();
//
} // }
/** /**
* @expectedException \Firefly\Exception\FireflyException * @expectedException \Firefly\Exception\FireflyException

View File

@@ -10,11 +10,14 @@
Accounts are the record holders for transactions and transfers. Money moves Accounts are the record holders for transactions and transfers. Money moves
from one account to another. from one account to another.
</p> </p>
</div>
</div>
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<p class="text-info"> <p class="text-info">
In a double-entry bookkeeping system (such as this one) there is a "from" account and a "to" In a double-entry bookkeeping system (such as this one) there is a "from"-account and a "to"-account,
account, even when money is created from thin air (such as interest, or when new accounts already have even when money is created from thin air (such as interest, or when new accounts already have a
a positive balance). positive balance).
</p> </p>
<p class="text-info"><span class="text-danger">This form creates personal accounts only.</span> <p class="text-info"><span class="text-danger">This form creates personal accounts only.</span>
@@ -34,9 +37,9 @@
<div class="col-sm-8"> <div class="col-sm-8">
{{ Form::text('name', Input::old('name'), ['class' => 'form-control']) }} {{ Form::text('name', Input::old('name'), ['class' => 'form-control']) }}
@if($errors->has('name')) @if($errors->has('name'))
<p class="text-danger">{{$errors->first('name')}}</p> <p class="text-danger">{{$errors->first('name')}}</p>
@else @else
<span class="help-block">Use something descriptive such as "checking account" or "My Bank Main Account".</span> <span class="help-block">Use something descriptive such as "checking account" or "My Bank Main Account".</span>
@endif @endif
</div> </div>

View File

@@ -33,7 +33,7 @@
</div> </div>
<div class="col-lg-6 col-md-6 col-sm-12"> <div class="col-lg-6 col-md-6 col-sm-12">
@if($account->accounttype->description == 'Default account') @if($account->accounttype->type == 'Default account')
<h4>Optional fields</h4> <h4>Optional fields</h4>
<div class="form-group"> <div class="form-group">

View File

@@ -35,22 +35,22 @@
<td>Out</td> <td>Out</td>
<td> <td>
{{mf($show['statistics']['period']['out'])}} {{mf($show['statistics']['period']['out'])}}
<a href="{{route('accounts.show',$account->id)}}#transactions-thisaccount-this-period-expensesonly"><span class="glyphicon glyphicon-circle-arrow-right"></span></a> <a href="{{route('accounts.show',$account->id)}}?type=transactions&amp;show=expenses"><span class="glyphicon glyphicon-circle-arrow-right"></span></a>
</td> </td>
<td> <td>
{{mf($show['statistics']['period']['t_out'])}} {{mf($show['statistics']['period']['t_out'])}}
<a href="#transactions-thisaccount-this-period-transfers-out-only"><span class="glyphicon glyphicon-circle-arrow-right"></span></a> <a href="{{route('accounts.show',$account->id)}}?type=transfers&amp;show=out"><span class="glyphicon glyphicon-circle-arrow-right"></span></a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td>In</td> <td>In</td>
<td> <td>
{{mf($show['statistics']['period']['in'])}} {{mf($show['statistics']['period']['in'])}}
<a href="#transactions-thisaccount-this-period-incomeonly"><span class="glyphicon glyphicon-circle-arrow-right"></span></a> <a href="{{route('accounts.show',$account->id)}}?type=transactions&amp;show=income"><span class="glyphicon glyphicon-circle-arrow-right"></span></a>
</td> </td>
<td> <td>
{{mf($show['statistics']['period']['t_in'])}} {{mf($show['statistics']['period']['t_in'])}}
<a href="#transactions-thisaccount-this-period-transfers-in-only"><span class="glyphicon glyphicon-circle-arrow-right"></span></a> <a href="{{route('accounts.show',$account->id)}}?type=transfers&amp;show=in"><span class="glyphicon glyphicon-circle-arrow-right"></span></a>
</td> </td>
</tr> </tr>
<tr> <tr>
@@ -101,7 +101,7 @@
<h4>Transactions <small> For selected account and period</small></h4> <h4>Transactions <small> For selected account and period</small></h4>
@include('paginated.transactions',['journals' => $show['journals']]) @include('paginated.transactions',['journals' => $show['journals'],'sum' => true])
</div> </div>
</div> </div>

View File

@@ -5,7 +5,11 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<base href="{{URL::route('index')}}/"> <base href="{{URL::route('index')}}/">
<title>Firefly</title> <title>Firefly
@if(isset($title))
// {{{$title}}}
@endif
</title>
<?php echo stylesheet_link_tag(); ?> <?php echo stylesheet_link_tag(); ?>
@yield('styles') @yield('styles')

View File

@@ -50,7 +50,7 @@ $r = Route::current()->getName();
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Create ... <span class="caret"></span></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Create ... <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu"> <ul class="dropdown-menu" role="menu">
<li><a href="{{route('transactions.create','withdrawal')}}" title="For when you spend money"><span class="glyphicon glyphicon-arrow-left"></span> Withdrawal</a></li> <li><a href="{{route('accounts.create')}}" title="Create new account"><span class="glyphicon glyphicon-inbox"></span> Account</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>

View File

@@ -29,7 +29,7 @@
<input type="checkbox" name="remember_me" value="1"> Remember login <input type="checkbox" name="remember_me" value="1"> Remember login
</label> </label>
</div> </div>
<button type="submit" class="btn btn-info">Submit</button> <button type="submit" class="btn btn-info">Login</button>
{{Form::close()}} {{Form::close()}}
</div> </div>
</div> </div>

View File

@@ -26,12 +26,12 @@
"codesleeve/asset-pipeline": "~2.0" "codesleeve/asset-pipeline": "~2.0"
}, },
"require-dev": { "require-dev": {
"barryvdh/laravel-debugbar": "~1.6", "barryvdh/laravel-debugbar": "@stable",
"barryvdh/laravel-ide-helper": "~1.9", "barryvdh/laravel-ide-helper": "@stable",
"mockery/mockery": "~0.9", "mockery/mockery": "@dev",
"satooshi/php-coveralls": "~0.6", "satooshi/php-coveralls": "@stable",
"league/factory-muffin": "~2.0", "league/factory-muffin": "@stable",
"doctrine/dbal": "2.4.*" "doctrine/dbal": "@stable"
}, },
"autoload": { "autoload": {
"classmap": [ "classmap": [