mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Revamped the account controller.
This commit is contained in:
parent
85f1e744b8
commit
9db4137a1b
@ -5,6 +5,8 @@ use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
|
||||
|
||||
/**
|
||||
* Class AccountController
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
|
||||
*/
|
||||
class AccountController extends \BaseController
|
||||
{
|
||||
@ -33,41 +35,23 @@ class AccountController extends \BaseController
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return $this
|
||||
*/
|
||||
public function delete(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 . ').'
|
||||
);
|
||||
}
|
||||
|
||||
return View::make('accounts.delete')->with('account', $account);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(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 . ').'
|
||||
);
|
||||
}
|
||||
$result = $this->_repository->destroy($account);
|
||||
if ($result === true) {
|
||||
$this->_repository->destroy($account);
|
||||
Session::flash('success', 'The account was deleted.');
|
||||
} else {
|
||||
Session::flash('error', 'Could not delete the account.');
|
||||
}
|
||||
|
||||
return Redirect::route('accounts.index');
|
||||
|
||||
@ -76,54 +60,52 @@ class AccountController extends \BaseController
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return $this
|
||||
*/
|
||||
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);
|
||||
|
||||
return View::make('accounts.edit')->with('account', $account)->with('openingBalance', $openingBalance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
* @return $this
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return $this
|
||||
*/
|
||||
public function show(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 . ').'
|
||||
);
|
||||
}
|
||||
$data = $this->_accounts->show($account, 40);
|
||||
|
||||
$show = $this->_accounts->show($account, 40);
|
||||
|
||||
return View::make('accounts.show')->with('account', $account)->with('show', $show);
|
||||
return View::make('accounts.show')->with('account', $account)->with('show', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
@ -133,14 +115,14 @@ class AccountController extends \BaseController
|
||||
if ($account->validate()) {
|
||||
// saved! return to wherever.
|
||||
Session::flash('success', 'Account "' . $account->name . '" created!');
|
||||
if (Input::get('create') == '1') {
|
||||
if (intval(Input::get('create')) === 1) {
|
||||
return Redirect::route('accounts.create')->withInput();
|
||||
} else {
|
||||
return Redirect::route('accounts.index');
|
||||
}
|
||||
} else {
|
||||
// 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();
|
||||
|
||||
@ -150,16 +132,10 @@ class AccountController extends \BaseController
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
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());
|
||||
if ($account->validate()) {
|
||||
Session::flash('success', 'Account "' . $account->name . '" updated.');
|
||||
|
@ -22,7 +22,8 @@ class CreateAccountTypesTable extends Migration
|
||||
'account_types', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
$table->string('description', 50);
|
||||
$table->string('type', 50);
|
||||
$table->boolean('editable');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -11,16 +11,16 @@ class AccountTypeSeeder extends Seeder
|
||||
DB::table('account_types')->delete();
|
||||
|
||||
AccountType::create(
|
||||
['description' => 'Default account']
|
||||
['type' => 'Default account','editable' => true]
|
||||
);
|
||||
AccountType::create(
|
||||
['description' => 'Cash account']
|
||||
['type' => 'Cash account','editable' => false]
|
||||
);
|
||||
AccountType::create(
|
||||
['description' => 'Initial balance account']
|
||||
['type' => 'Initial balance account','editable' => false]
|
||||
);
|
||||
AccountType::create(
|
||||
['description' => 'Beneficiary account']
|
||||
['type' => 'Beneficiary account','editable' => true]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
return array(
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -87,6 +87,7 @@ return array(
|
||||
'rule-name' => 'custom-message',
|
||||
),
|
||||
),
|
||||
'alphabasic' => 'The :attribute field must consist of basic alphanumeric characters.',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@ -101,4 +102,4 @@ return array(
|
||||
|
||||
'attributes' => array(),
|
||||
|
||||
);
|
||||
];
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Firefly\Helper\Controllers;
|
||||
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Firefly\Exception\FireflyException;
|
||||
|
||||
/**
|
||||
* Class Account
|
||||
@ -11,43 +11,6 @@ use Illuminate\Database\Eloquent\Collection;
|
||||
*/
|
||||
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
|
||||
*
|
||||
@ -55,17 +18,12 @@ class Account implements AccountInterface
|
||||
*/
|
||||
public function openingBalanceTransaction(\Account $account)
|
||||
{
|
||||
$transactionType = \TransactionType::where('type', 'Opening balance')->first();
|
||||
|
||||
return \TransactionJournal::
|
||||
with(
|
||||
['transactions' => function ($q) {
|
||||
$q->orderBy('amount', 'ASC');
|
||||
}]
|
||||
)->where('transaction_type_id', $transactionType->id)
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transactions.account_id', $account->id)->first(['transaction_journals.*']);
|
||||
|
||||
withRelevantData()->account($account)
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=',
|
||||
'transaction_journals.transaction_type_id')
|
||||
->where('transaction_types.type', 'Opening balance')
|
||||
->first(['transaction_journals.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -87,29 +45,51 @@ class Account implements AccountInterface
|
||||
|
||||
|
||||
// build a query:
|
||||
$query = \TransactionJournal::with(
|
||||
['transactions' => function ($q) {
|
||||
$q->orderBy('amount', 'ASC');
|
||||
}, 'transactiontype', 'components' => function ($q) {
|
||||
$q->orderBy('class');
|
||||
}, 'transactions.account.accounttype']
|
||||
)->orderBy('date', 'DESC')->leftJoin(
|
||||
'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)->where('transactions.account_id', $account->id)->where('date', '>=', $start->format('Y-m-d'))->where(
|
||||
'date', '<=', $end->format('Y-m-d')
|
||||
)->orderBy('transaction_journals.id', 'DESC');
|
||||
$query = \TransactionJournal::withRelevantData()->defaultSorting()->account($account)->after($start)
|
||||
->before($end);
|
||||
// filter some:
|
||||
if (\Input::get('type')) {
|
||||
switch (\Input::get('type')) {
|
||||
case 'transactions':
|
||||
$query->transactionTypes(['Deposit', 'Withdrawal']);
|
||||
break;
|
||||
case 'transfers':
|
||||
$query->transactionTypes(['Transfer']);
|
||||
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:
|
||||
$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;
|
||||
$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 */
|
||||
foreach ($result as $item) {
|
||||
$items[] = $item;
|
||||
foreach ($result as $index => $item) {
|
||||
|
||||
foreach ($item->components as $component) {
|
||||
if ($component->class == 'Budget') {
|
||||
$stats['budgets'][$component->id] = $component;
|
||||
@ -118,59 +98,56 @@ class Account implements AccountInterface
|
||||
$stats['categories'][$component->id] = $component;
|
||||
}
|
||||
}
|
||||
// since it is entirely possible the database is messed up somehow
|
||||
// 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'][$toAccount->id] = $toAccount;
|
||||
}
|
||||
unset($result, $page);
|
||||
$paginator = \Paginator::make($items, $totalItems, $perPage);
|
||||
|
||||
// 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')
|
||||
);
|
||||
unset($result, $page, $item, $fromAccount, $toAccount);
|
||||
|
||||
|
||||
$stats['period']['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'
|
||||
)->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']['diff'] = $stats['period']['in'] + $stats['period']['out'];
|
||||
// statistics (transactions)
|
||||
$trIn = floatval(\Transaction::before($end)->after($start)->account($account)->moreThan(0)
|
||||
->transactionTypes(['Deposit', 'Withdrawal'])->sum('transactions.amount'));
|
||||
$trOut = floatval(\Transaction::before($end)->after($start)->account($account)->lessThan(0)
|
||||
->transactionTypes(['Deposit', 'Withdrawal'])->sum('transactions.amount'));
|
||||
$trDiff = $trIn + $trOut;
|
||||
|
||||
$stats['period']['t_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'
|
||||
)->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')
|
||||
);
|
||||
// statistics (transfers)
|
||||
$trfIn = floatval(\Transaction::before($end)->after($start)->account($account)->moreThan(0)
|
||||
->transactionTypes(['Transfer'])->sum('transactions.amount'));
|
||||
$trfOut = floatval(\Transaction::before($end)->after($start)->account($account)->lessThan(0)
|
||||
->transactionTypes(['Transfer'])->sum('transactions.amount'));
|
||||
$trfDiff = $trfIn + $trfOut;
|
||||
|
||||
$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 = [
|
||||
'journals' => $paginator,
|
||||
|
@ -12,15 +12,6 @@ use Illuminate\Database\Eloquent\Collection;
|
||||
interface AccountInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Build the index:
|
||||
*
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function index(Collection $accounts);
|
||||
|
||||
/**
|
||||
* @param \Account $account
|
||||
*
|
||||
|
@ -36,7 +36,6 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
public function createOrFind($name, \AccountType $type = null)
|
||||
{
|
||||
|
||||
$account = $this->findByName($name, $type);
|
||||
if (!$account) {
|
||||
$data = [
|
||||
@ -60,10 +59,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
if (is_null($name) || strlen($name) == 0) {
|
||||
return null;
|
||||
}
|
||||
$type = \AccountType::where('description', 'Beneficiary account')->first();
|
||||
|
||||
/** @noinspection PhpParamsInspection */
|
||||
|
||||
$type = \AccountType::where('type', 'Beneficiary account')->first();
|
||||
return $this->createOrFind($name, $type);
|
||||
}
|
||||
|
||||
@ -74,38 +70,29 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
public function destroy(\Account $account)
|
||||
{
|
||||
// find the oldest transaction which also is a "Opening balance"
|
||||
$first = \Transaction::
|
||||
leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->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.*']);
|
||||
// find all transaction journals related to this account:
|
||||
$journals = \TransactionJournal::withRelevantData()->account($account)->get(['transaction_journals.*']);
|
||||
$accountIDs = [];
|
||||
|
||||
$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 */
|
||||
foreach ($journals as $journal) {
|
||||
// remember the account id's of the transactions involved:
|
||||
foreach ($journal->transactions as $t) {
|
||||
$accountIDs[] = $t->account_id;
|
||||
}
|
||||
$journal->delete();
|
||||
|
||||
}
|
||||
$accountIDs = array_unique($accountIDs);
|
||||
if (count($accountIDs) > 0) {
|
||||
// find the "initial balance" type accounts in this list. Should be just 1.
|
||||
$query = \Auth::user()->accounts()->accountType(['Initial balance account'])
|
||||
->whereIn('accounts.id', $accountIDs);
|
||||
if ($query->count() == 1) {
|
||||
$iba = $query->first(['accounts.*']);
|
||||
$iba->delete();
|
||||
}
|
||||
|
||||
if (!is_null($initialbalanceAccount)) {
|
||||
$initialbalanceAccount->delete();
|
||||
}
|
||||
|
||||
|
||||
$account->delete();
|
||||
|
||||
/**
|
||||
@ -135,9 +122,10 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
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)
|
||||
->where('name', 'like', '%' . $name . '%')
|
||||
->first();
|
||||
}
|
||||
|
||||
@ -155,7 +143,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
public function getActiveDefault()
|
||||
{
|
||||
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.*']);
|
||||
}
|
||||
@ -168,7 +156,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
$list = \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)
|
||||
|
||||
->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
|
||||
$return = [];
|
||||
@ -187,7 +175,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
$list = \Auth::user()->accounts()->leftJoin(
|
||||
'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.*']);
|
||||
|
||||
@ -213,7 +201,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
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();
|
||||
|
||||
return $cash;
|
||||
@ -226,7 +214,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
public function getDefault()
|
||||
{
|
||||
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.*']);
|
||||
}
|
||||
@ -239,10 +227,20 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
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->accountType()->associate($accountType);
|
||||
$account->user()->associate(\Auth::user());
|
||||
@ -286,7 +284,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
/** @var \Firefly\Helper\Controllers\AccountInterface $interface */
|
||||
$interface = \App::make('Firefly\Helper\Controllers\AccountInterface');
|
||||
|
||||
if ($account->accounttype->description == 'Default account') {
|
||||
if ($account->accounttype->type == 'Default account') {
|
||||
|
||||
|
||||
$journal = $interface->openingBalanceTransaction($account);
|
||||
@ -315,7 +313,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
protected function _createInitialBalance(\Account $account, $amount = 0, Carbon $date)
|
||||
{
|
||||
// get account type:
|
||||
$initialBalanceAT = \AccountType::where('description', 'Initial balance account')->first();
|
||||
$initialBalanceAT = \AccountType::where('type', 'Initial balance account')->first();
|
||||
|
||||
// create new account:
|
||||
$initial = new \Account;
|
||||
|
@ -64,8 +64,8 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
||||
}
|
||||
|
||||
// account types for both:
|
||||
$toAT = $toAccount->accountType->description;
|
||||
$fromAT = $from->accountType->description;
|
||||
$toAT = $toAccount->accountType->type;
|
||||
$fromAT = $from->accountType->type;
|
||||
|
||||
$journalType = null;
|
||||
|
||||
@ -287,6 +287,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
||||
$fromAccount = $accountRepository->find(intval($data['account_id']));
|
||||
$toAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']);
|
||||
break;
|
||||
|
||||
case 'deposit':
|
||||
$fromAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']);
|
||||
$toAccount = $accountRepository->find(intval($data['account_id']));
|
||||
@ -295,7 +296,6 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
||||
$fromAccount = $accountRepository->find(intval($data['account_from_id']));
|
||||
$toAccount = $accountRepository->find(intval($data['account_to_id']));
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
// fall back to cash if necessary:
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?php
|
||||
use LaravelBook\Ardent\Ardent as Ardent;
|
||||
use LaravelBook\Ardent\Builder;
|
||||
|
||||
/**
|
||||
* Account
|
||||
@ -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 whereName($value)
|
||||
* @method static \Illuminate\Database\Query\Builder|\Account whereActive($value)
|
||||
* @method static \Account accountType($types)
|
||||
*/
|
||||
class Account extends Ardent
|
||||
{
|
||||
@ -33,7 +35,7 @@ class Account extends Ardent
|
||||
*/
|
||||
public static $rules
|
||||
= [
|
||||
'name' => 'required|between:1,100',
|
||||
'name' => ['required', 'between:1,100', 'alphabasic'],
|
||||
'user_id' => 'required|exists:users,id',
|
||||
'account_type_id' => 'required|exists:account_types,id',
|
||||
'active' => 'required|boolean'
|
||||
@ -96,7 +98,8 @@ class Account extends Ardent
|
||||
public function predict(
|
||||
/** @noinspection PhpUnusedParameterInspection */
|
||||
\Carbon\Carbon $date
|
||||
) {
|
||||
)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -110,4 +113,13 @@ class Account extends Ardent
|
||||
return $this->belongsTo('User');
|
||||
}
|
||||
|
||||
public function scopeAccountType(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);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -7,15 +7,23 @@
|
||||
* @property integer $id
|
||||
* @property \Carbon\Carbon $created_at
|
||||
* @property \Carbon\Carbon $updated_at
|
||||
* @property string $description
|
||||
* @property string $type
|
||||
* @property boolean $editable
|
||||
* @property-read \Illuminate\Database\Eloquent\Collection|\Account[] $accounts
|
||||
* @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 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
|
||||
{
|
||||
public static $rules
|
||||
= [
|
||||
'type' => ['required', 'between:1,50', 'alphabasic'],
|
||||
'editable' => 'required|boolean',
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
|
@ -57,7 +57,7 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
/** @var \AccountType $accountType */
|
||||
$accountType = f::create('AccountType');
|
||||
$accountType->description = 'Default account';
|
||||
$accountType->type = 'Default account';
|
||||
$accountType->save();
|
||||
$account->accountType()->associate($accountType);
|
||||
$account->save();
|
||||
@ -72,33 +72,6 @@ class AccountControllerTest extends TestCase
|
||||
$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
|
||||
*/
|
||||
@ -109,7 +82,7 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
/** @var \AccountType $accountType */
|
||||
$accountType = f::create('AccountType');
|
||||
$accountType->description = 'Default account';
|
||||
$accountType->type = 'Default account';
|
||||
$accountType->save();
|
||||
$account->accountType()->associate($accountType);
|
||||
$account->save();
|
||||
@ -126,57 +99,6 @@ class AccountControllerTest extends TestCase
|
||||
$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()
|
||||
{
|
||||
@ -185,7 +107,7 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
/** @var \AccountType $accountType */
|
||||
$accountType = f::create('AccountType');
|
||||
$accountType->description = 'Default account';
|
||||
$accountType->type = 'Default account';
|
||||
$accountType->save();
|
||||
$account->accountType()->associate($accountType);
|
||||
$account->save();
|
||||
@ -208,28 +130,6 @@ class AccountControllerTest extends TestCase
|
||||
}
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
@ -238,7 +138,7 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
/** @var \AccountType $accountType */
|
||||
$accountType = f::create('AccountType');
|
||||
$accountType->description = 'Default account';
|
||||
$accountType->type = 'Default account';
|
||||
$accountType->save();
|
||||
$account->accountType()->associate($accountType);
|
||||
$account->save();
|
||||
@ -254,7 +154,6 @@ class AccountControllerTest extends TestCase
|
||||
];
|
||||
|
||||
$this->_repository->shouldReceive('get')->once()->andReturn($collection);
|
||||
$this->_accounts->shouldReceive('index')->with($collection)->once()->andReturn($list);
|
||||
$this->action('GET', 'AccountController@index');
|
||||
$this->assertResponseOk();
|
||||
}
|
||||
@ -266,7 +165,7 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
/** @var \AccountType $accountType */
|
||||
$accountType = f::create('AccountType');
|
||||
$accountType->description = 'Default account';
|
||||
$accountType->type = 'Default account';
|
||||
$accountType->save();
|
||||
$account->accountType()->associate($accountType);
|
||||
$account->save();
|
||||
@ -303,29 +202,6 @@ class AccountControllerTest extends TestCase
|
||||
$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()
|
||||
{
|
||||
@ -334,7 +210,7 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
/** @var \AccountType $accountType */
|
||||
$accountType = f::create('AccountType');
|
||||
$accountType->description = 'Default account';
|
||||
$accountType->type = 'Default account';
|
||||
$accountType->save();
|
||||
$account->accountType()->associate($accountType);
|
||||
$account->save();
|
||||
@ -351,7 +227,7 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
/** @var \AccountType $accountType */
|
||||
$accountType = f::create('AccountType');
|
||||
$accountType->description = 'Default account';
|
||||
$accountType->type = 'Default account';
|
||||
$accountType->save();
|
||||
$account->accountType()->associate($accountType);
|
||||
$account->save();
|
||||
@ -369,7 +245,7 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
/** @var \AccountType $accountType */
|
||||
$accountType = f::create('AccountType');
|
||||
$accountType->description = 'Default account';
|
||||
$accountType->type = 'Default account';
|
||||
$accountType->save();
|
||||
$account->accountType()->associate($accountType);
|
||||
$account->save();
|
||||
@ -386,7 +262,7 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
/** @var \AccountType $accountType */
|
||||
$accountType = f::create('AccountType');
|
||||
$accountType->description = 'Default account';
|
||||
$accountType->type = 'Default account';
|
||||
$accountType->save();
|
||||
$account->accountType()->associate($accountType);
|
||||
$account->save();
|
||||
@ -402,30 +278,6 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
}
|
||||
|
||||
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 */
|
||||
@ -433,7 +285,7 @@ class AccountControllerTest extends TestCase
|
||||
|
||||
/** @var \AccountType $accountType */
|
||||
$accountType = f::create('AccountType');
|
||||
$accountType->description = 'Default account';
|
||||
$accountType->type = 'Default account';
|
||||
$accountType->save();
|
||||
$account->accountType()->associate($accountType);
|
||||
$account->save();
|
||||
|
@ -4,7 +4,7 @@ use League\FactoryMuffin\Facade;
|
||||
Facade::define(
|
||||
'AccountType',
|
||||
[
|
||||
'description' => function () {
|
||||
'type' => function () {
|
||||
$types = [
|
||||
'Default account',
|
||||
'Cash account',
|
||||
@ -13,6 +13,7 @@ Facade::define(
|
||||
];
|
||||
|
||||
return $types[rand(0, 3)];
|
||||
}
|
||||
},
|
||||
'editable' => 1
|
||||
]
|
||||
);
|
@ -10,11 +10,14 @@
|
||||
Accounts are the record holders for transactions and transfers. Money moves
|
||||
from one account to another.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-12 col-sm-12">
|
||||
<p class="text-info">
|
||||
In a double-entry bookkeeping system (such as this one) there is a "from" account and a "to"
|
||||
account, even when money is created from thin air (such as interest, or when new accounts already have
|
||||
a positive balance).
|
||||
In a double-entry bookkeeping system (such as this one) there is a "from"-account and a "to"-account,
|
||||
even when money is created from thin air (such as interest, or when new accounts already have a
|
||||
positive balance).
|
||||
</p>
|
||||
|
||||
<p class="text-info"><span class="text-danger">This form creates personal accounts only.</span>
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
</div>
|
||||
<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>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -35,22 +35,22 @@
|
||||
<td>Out</td>
|
||||
<td>
|
||||
{{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&show=expenses"><span class="glyphicon glyphicon-circle-arrow-right"></span></a>
|
||||
</td>
|
||||
<td>
|
||||
{{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&show=out"><span class="glyphicon glyphicon-circle-arrow-right"></span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>In</td>
|
||||
<td>
|
||||
{{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&show=income"><span class="glyphicon glyphicon-circle-arrow-right"></span></a>
|
||||
</td>
|
||||
<td>
|
||||
{{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&show=in"><span class="glyphicon glyphicon-circle-arrow-right"></span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -101,7 +101,7 @@
|
||||
|
||||
|
||||
<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>
|
||||
|
||||
|
@ -50,7 +50,7 @@ $r = Route::current()->getName();
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Create ... <span class="caret"></span></a>
|
||||
<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>
|
||||
</li>
|
||||
</ul>
|
||||
|
Loading…
Reference in New Issue
Block a user