Revamped the account controller.

This commit is contained in:
James Cole
2014-08-30 14:26:33 +02:00
parent 85f1e744b8
commit 9db4137a1b
16 changed files with 339 additions and 519 deletions

View File

@@ -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.*']);
}
/**
@@ -77,7 +35,7 @@ class Account implements AccountInterface
public function show(\Account $account, $perPage)
{
$start = \Session::get('start');
$end = \Session::get('end');
$end = \Session::get('end');
$stats = [
'budgets' => [],
'categories' => [],
@@ -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;
$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:
$page = max(1, intval(\Input::get('page')));
$skip = ($page - 1) * $perPage;
$result = $query->skip($skip)->take($perPage)->get(['transaction_journals.*']);
// 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;
}
}
$fromAccount = $item->transactions[0]->account;
$toAccount = $item->transactions[1]->account;
// 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;
$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,

View File

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

View File

@@ -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();
}
if (!is_null($initialbalanceAccount)) {
$initialbalanceAccount->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();
}
}
$account->delete();
/**
@@ -135,10 +122,11 @@ 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 . '%')
->first();
return \Auth::user()->accounts()->where('account_type_id', $type->id)
->where('name', 'like', '%' . $name . '%')
->first();
}
/**
@@ -155,9 +143,9 @@ 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.*']);
->get(['accounts.*']);
}
/**
@@ -165,12 +153,12 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function getActiveDefaultAsSelectList()
{
$list = \Auth::user()->accounts()->leftJoin(
'account_types', 'account_types.id', '=', 'accounts.account_type_id'
$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.*']);
->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
$return = [];
foreach ($list as $entry) {
$return[intval($entry->id)] = $entry->name;
@@ -185,11 +173,11 @@ class EloquentAccountRepository implements AccountRepositoryInterface
public function getBeneficiaries()
{
$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;
}
@@ -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,9 +214,9 @@ 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.*']);
->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
}
/**
@@ -239,16 +227,26 @@ 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());
$account->name = $data['name'];
$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']
) : 1;
@@ -257,7 +255,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
// create initial balance, if necessary:
if (isset($data['openingbalance']) && isset($data['openingbalancedate'])) {
$amount = floatval($data['openingbalance']);
$date = new Carbon($data['openingbalancedate']);
$date = new Carbon($data['openingbalancedate']);
$this->_createInitialBalance($account, $amount, $date);
}
}
@@ -286,12 +284,12 @@ 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);
if ($journal) {
$journal->date = new Carbon($data['openingbalancedate']);
$journal->date = new Carbon($data['openingbalancedate']);
$journal->transactions[0]->amount = floatval($data['openingbalance']) * -1;
$journal->transactions[1]->amount = floatval($data['openingbalance']);
$journal->transactions[0]->save();
@@ -306,8 +304,8 @@ class EloquentAccountRepository implements AccountRepositoryInterface
/**
* @param \Account $account
* @param int $amount
* @param Carbon $date
* @param int $amount
* @param Carbon $date
*
* @return bool
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
@@ -315,24 +313,24 @@ 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;
$initial->accountType()->associate($initialBalanceAT);
$initial->user()->associate(\Auth::user());
$initial->name = $account->name . ' initial balance';
$initial->name = $account->name . ' initial balance';
$initial->active = 0;
if ($initial->validate()) {
$initial->save();
// create new transaction journal (and transactions):
/** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $transactionJournal */
$transactionJournal = \App::make(
'Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'
'Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'
);
$transactionJournal->createSimpleJournal(
$initial, $account, 'Initial Balance for ' . $account->name, $amount, $date
$initial, $account, 'Initial Balance for ' . $account->name, $amount, $date
);
return true;

View File

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