mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Completely revamped the account controller.
This commit is contained in:
parent
97e7ac4052
commit
d84d88cc10
@ -1,31 +1,229 @@
|
||||
<?php
|
||||
|
||||
use Firefly\Helper\Controllers\AccountInterface as AI;
|
||||
use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
|
||||
use Firefly\Exception\FireflyException;
|
||||
use Illuminate\Support\MessageBag;
|
||||
|
||||
/**
|
||||
* Class AccountController
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
|
||||
*/
|
||||
class AccountController extends \BaseController
|
||||
class AccountController extends BaseController
|
||||
{
|
||||
|
||||
protected $_repository;
|
||||
protected $_accounts;
|
||||
|
||||
/**
|
||||
* @param ARI $repository
|
||||
* @param AI $accounts
|
||||
*
|
||||
*/
|
||||
public function __construct(ARI $repository, AI $accounts)
|
||||
public function __construct()
|
||||
{
|
||||
$this->_accounts = $accounts;
|
||||
$this->_repository = $repository;
|
||||
View::share('mainTitleIcon', 'fa-credit-card');
|
||||
View::share('title', 'Accounts');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $what
|
||||
*
|
||||
* @return View
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function index($what = 'default')
|
||||
{
|
||||
switch ($what) {
|
||||
default:
|
||||
throw new FireflyException('Cannot handle account type "' . e($what) . '".');
|
||||
break;
|
||||
case 'asset':
|
||||
View::share('subTitleIcon', 'fa-money');
|
||||
View::share('subTitle', 'Asset accounts');
|
||||
break;
|
||||
case 'expense':
|
||||
View::share('subTitleIcon', 'fa-shopping-cart');
|
||||
View::share('subTitle', 'Expense accounts');
|
||||
break;
|
||||
case 'revenue':
|
||||
View::share('subTitleIcon', 'fa-download');
|
||||
View::share('subTitle', 'Revenue accounts');
|
||||
break;
|
||||
}
|
||||
return View::make('accounts.index')->with('what', $what);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $what
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function json($what = 'default')
|
||||
{
|
||||
/** @var \FireflyIII\Database\Account $acct */
|
||||
$acct = App::make('FireflyIII\Database\Account');
|
||||
|
||||
/** @var \FireflyIII\Shared\Json\Json $json */
|
||||
$json = App::make('FireflyIII\Shared\Json\Json');
|
||||
|
||||
$parameters = $json->dataTableParameters();
|
||||
|
||||
switch ($what) {
|
||||
default:
|
||||
throw new FireflyException('Cannot handle account type "' . e($what) . '".');
|
||||
break;
|
||||
case 'asset':
|
||||
$accounts = $acct->getAssetAccounts($parameters);
|
||||
$count = $acct->countAssetAccounts();
|
||||
break;
|
||||
case 'expense':
|
||||
$accounts = $acct->getExpenseAccounts($parameters);
|
||||
$count = $acct->countExpenseAccounts();
|
||||
break;
|
||||
case 'revenue':
|
||||
$accounts = $acct->getRevenueAccounts($parameters);
|
||||
$count = $acct->countRevenueAccounts();
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output the set compatible with data tables:
|
||||
*/
|
||||
$return = [
|
||||
'draw' => intval(Input::get('draw')),
|
||||
'recordsTotal' => $count,
|
||||
'recordsFiltered' => $accounts->count(),
|
||||
'data' => [],
|
||||
];
|
||||
|
||||
/*
|
||||
* Loop the accounts:
|
||||
*/
|
||||
/** @var \Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$entry = [
|
||||
'name' => ['name' => $account->name, 'url' => route('accounts.show', $account->id)],
|
||||
'balance' => $account->balance(),
|
||||
'id' => [
|
||||
'edit' => route('accounts.edit', $account->id),
|
||||
'delete' => route('accounts.delete', $account->id),
|
||||
]
|
||||
];
|
||||
$return['data'][] = $entry;
|
||||
}
|
||||
|
||||
|
||||
return Response::jsoN($return);
|
||||
}
|
||||
|
||||
public function transactions(Account $account) {
|
||||
/*
|
||||
* TODO get the JSON helper to get transactions or something.
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $account
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function sankey($account)
|
||||
{
|
||||
|
||||
/*
|
||||
* Get the stuff.
|
||||
*/
|
||||
$start = Session::get('start');
|
||||
$end = Session::get('end');
|
||||
$query = \TransactionJournal::withRelevantData()
|
||||
->defaultSorting()
|
||||
->accountIs($account)
|
||||
->after($start)
|
||||
->before($end);
|
||||
$set = $query->get(['transaction_journals.*']);
|
||||
/*
|
||||
* Arrays we need:
|
||||
*/
|
||||
$collection = [];
|
||||
$filtered = [];
|
||||
$result = [];
|
||||
/** @var \TransactionJournal $entry */
|
||||
foreach ($set as $entry) {
|
||||
switch ($entry->transactionType->type) {
|
||||
case 'Withdrawal':
|
||||
/** @var Budget $budget */
|
||||
$budget = isset($entry->budgets[0]) ? $entry->budgets[0] : null;
|
||||
$from = $entry->transactions[0]->account->name;
|
||||
$amount = floatval($entry->transactions[1]->amount);
|
||||
if ($budget) {
|
||||
$to = $budget->name;
|
||||
} else {
|
||||
$to = '(no budget)';
|
||||
}
|
||||
$collection[] = [$from, $to, $amount];
|
||||
|
||||
// also make one for the budget:
|
||||
$from = $to;
|
||||
$category = $entry->categories()->first();
|
||||
if ($category) {
|
||||
$to = $category->name . ' (cat)';
|
||||
} else {
|
||||
$to = '(no category)';
|
||||
}
|
||||
$collection[] = [$from, $to, $amount];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* To break "cycles", aka money going back AND forth Firefly searches for previously existing
|
||||
* key sets (in reversed order) and if we find them, fix it.
|
||||
*
|
||||
* If the from-to amount found is larger than the amount going back, the amount going back
|
||||
* is removed and substracted from the current amount.
|
||||
*
|
||||
* If the from-to amount found is less than the amount going back, the entry is ignored
|
||||
* but substracted from the amount going back.
|
||||
*/
|
||||
foreach ($collection as $current) {
|
||||
list($from, $to, $amount) = $current;
|
||||
$key = $from . $to;
|
||||
$reversed = $to . $from;
|
||||
if (!isset($result[$reversed])) {
|
||||
if (isset($result[$key])) {
|
||||
$filtered[$key]['amount'] += $amount;
|
||||
} else {
|
||||
$filtered[$key] = ['from' => $from, 'to' => $to, 'amount' => $amount];
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If there is one, see which one will make it:
|
||||
*/
|
||||
$otherAmount = $result[$reversed]['amount'];
|
||||
if ($amount >= $otherAmount) {
|
||||
unset($result[$reversed]);
|
||||
$amount = $amount - $otherAmount;
|
||||
// set:
|
||||
if (isset($result[$key])) {
|
||||
$filtered[$key]['amount'] += $amount;
|
||||
} else {
|
||||
$filtered[$key] = ['from' => $from, 'to' => $to, 'amount' => $amount];
|
||||
}
|
||||
} else {
|
||||
$filtered[$reversed]['amount'] -= $amount;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
ksort($filtered);
|
||||
|
||||
/*
|
||||
* Collect amounts to give the labels the proper
|
||||
*/
|
||||
|
||||
/*
|
||||
* Loop it again to add the amounts.
|
||||
*/
|
||||
return View::make('accounts.sankey', compact('filtered'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
@ -43,52 +241,7 @@ class AccountController extends \BaseController
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return View::make('accounts.create')->with('subTitle', 'Create a new ' . $what . ' account')->with(
|
||||
'what', $what
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function asset()
|
||||
{
|
||||
View::share('subTitleIcon', 'fa-money');
|
||||
|
||||
$accounts = $this->_repository->getOfTypes(['Asset account', 'Default account']);
|
||||
|
||||
return View::make('accounts.asset')->with('subTitle', 'Asset accounts')->with(
|
||||
'accounts', $accounts
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function expense()
|
||||
{
|
||||
View::share('subTitleIcon', 'fa-shopping-cart');
|
||||
|
||||
$accounts = $this->_repository->getOfTypes(['Expense account', 'Beneficiary account']);
|
||||
|
||||
return View::make('accounts.expense')->with('subTitle', 'Expense accounts')->with(
|
||||
'accounts', $accounts
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function revenue()
|
||||
{
|
||||
View::share('subTitleIcon', 'fa-download');
|
||||
|
||||
$accounts = $this->_repository->getOfTypes(['Revenue account']);
|
||||
|
||||
return View::make('accounts.revenue')->with('subTitle', 'Revenue accounts')->with(
|
||||
'accounts', $accounts
|
||||
);
|
||||
return View::make('accounts.create')->with('subTitle', 'Create a new ' . $what . ' account')->with('what', $what);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,9 +252,9 @@ class AccountController extends \BaseController
|
||||
public function delete(Account $account)
|
||||
{
|
||||
return View::make('accounts.delete')->with('account', $account)
|
||||
->with(
|
||||
'subTitle', 'Delete ' . strtolower($account->accountType->type) . ' "' . $account->name . '"'
|
||||
);
|
||||
->with(
|
||||
'subTitle', 'Delete ' . strtolower($account->accountType->type) . ' "' . $account->name . '"'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -111,20 +264,67 @@ class AccountController extends \BaseController
|
||||
*/
|
||||
public function destroy(Account $account)
|
||||
{
|
||||
|
||||
$type = $account->accountType->type;
|
||||
$this->_repository->destroy($account);
|
||||
|
||||
/** @var \FireflyIII\Database\Account $acct */
|
||||
$acct = App::make('FireflyIII\Database\Account');
|
||||
|
||||
/** @var \FireflyIII\Database\TransactionJournal $jrnls */
|
||||
$jrnls = App::make('FireflyIII\Database\TransactionJournal');
|
||||
|
||||
/*
|
||||
* Find the "initial balance account", should it exist:
|
||||
*/
|
||||
$initialBalance = $acct->findInitialBalanceAccount($account);
|
||||
|
||||
/*
|
||||
* Get all the transaction journals that are part of this/these account(s):
|
||||
*/
|
||||
$journals = [];
|
||||
if ($initialBalance) {
|
||||
$transactions = $initialBalance->transactions()->get();
|
||||
/** @var \Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$journals[] = $transaction->transaction_journal_id;
|
||||
}
|
||||
}
|
||||
/** @var \Transaction $transaction */
|
||||
foreach ($account->transactions() as $transaction) {
|
||||
$journals[] = $transaction->transaction_journal_id;
|
||||
}
|
||||
|
||||
$journals = array_unique($journals);
|
||||
|
||||
/*
|
||||
* Delete the journals. Should get rid of the transactions as well.
|
||||
*/
|
||||
foreach ($journals as $id) {
|
||||
$journal = $jrnls->find($id);
|
||||
$journal->delete();
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete it
|
||||
*/
|
||||
if ($initialBalance) {
|
||||
$acct->destroy($initialBalance);
|
||||
}
|
||||
|
||||
$acct->destroy($account);
|
||||
|
||||
Session::flash('success', 'The account was deleted.');
|
||||
switch ($type) {
|
||||
case 'Asset account':
|
||||
case 'Default account':
|
||||
return Redirect::route('accounts.asset');
|
||||
return Redirect::route('accounts.index', 'asset');
|
||||
break;
|
||||
case 'Expense account':
|
||||
case 'Beneficiary account':
|
||||
return Redirect::route('accounts.expense');
|
||||
return Redirect::route('accounts.index', 'expense');
|
||||
break;
|
||||
case 'Revenue account':
|
||||
return Redirect::route('accounts.revenue');
|
||||
return Redirect::route('accounts.index', 'revenue');
|
||||
break;
|
||||
}
|
||||
|
||||
@ -153,18 +353,23 @@ class AccountController extends \BaseController
|
||||
break;
|
||||
}
|
||||
|
||||
$openingBalance = $this->_accounts->openingBalanceTransaction($account);
|
||||
return View::make('accounts.edit')->with('account', $account)->with('openingBalance', $openingBalance)
|
||||
/** @var \FireflyIII\Database\Account $acct */
|
||||
$acct = App::make('FireflyIII\Database\Account');
|
||||
|
||||
->with('subTitle', 'Edit ' . strtolower($account->accountType->type) . ' "' . $account->name . '"');
|
||||
}
|
||||
$openingBalance = $acct->openingBalanceTransaction($account);
|
||||
Session::forget('prefilled');
|
||||
if (!is_null($openingBalance)) {
|
||||
$prefilled['openingbalancedate'] = $openingBalance->date->format('Y-m-d');
|
||||
$prefilled['openingbalance'] = floatval($openingBalance->transactions()->where('account_id', $account->id)->first()->amount);
|
||||
Session::flash('prefilled', $prefilled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return View::make('error')->with('message', 'This view has been disabled');
|
||||
|
||||
return View::make('accounts.edit')->with('account', $account)->with('openingBalance', $openingBalance)->with(
|
||||
'subTitle', 'Edit ' . strtolower(
|
||||
$account->accountType->type
|
||||
) . ' "' . $account->name . '"'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,54 +394,55 @@ class AccountController extends \BaseController
|
||||
}
|
||||
|
||||
|
||||
$data = $this->_accounts->show($account, 40);
|
||||
|
||||
return View::make('accounts.show')->with('account', $account)->with('show', $data)->with(
|
||||
'subTitle',
|
||||
'Details for ' . strtolower($account->accountType->type) . ' "' . $account->name . '"'
|
||||
);
|
||||
//$data = $this->_accounts->show($account, 40);
|
||||
return View::make('accounts.show')
|
||||
->with('account', $account)
|
||||
->with('subTitle', 'Details for ' . strtolower($account->accountType->type) . ' "' . $account->name . '"');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function store()
|
||||
{
|
||||
|
||||
$data = Input::all();
|
||||
$data['what'] = isset($data['what']) && $data['what'] != '' ? $data['what'] : 'asset';
|
||||
/** @var \FireflyIII\Database\Account $acct */
|
||||
$acct = App::make('FireflyIII\Database\Account');
|
||||
|
||||
|
||||
switch ($data['what']) {
|
||||
switch ($data['post_submit_action']) {
|
||||
default:
|
||||
case 'asset':
|
||||
$data['account_type'] = 'Asset account';
|
||||
break;
|
||||
case 'expense':
|
||||
$data['account_type'] = 'Expense account';
|
||||
break;
|
||||
case 'revenue':
|
||||
$data['account_type'] = 'Revenue account';
|
||||
throw new FireflyException('Cannot handle post_submit_action "' . e($data['post_submit_action']) . '"');
|
||||
break;
|
||||
case 'create_another':
|
||||
case 'store':
|
||||
$messages = $acct->validate($data);
|
||||
/** @var MessageBag $messages ['errors'] */
|
||||
if ($messages['errors']->count() > 0) {
|
||||
Session::flash('warnings', $messages['warnings']);
|
||||
Session::flash('successes', $messages['successes']);
|
||||
Session::flash('error', 'Could not save account: ' . $messages['errors']->first());
|
||||
return Redirect::route('accounts.create', $data['what'])->withInput()->withErrors($messages['errors']);
|
||||
}
|
||||
// store!
|
||||
$acct->store($data);
|
||||
Session::flash('success', 'New account stored!');
|
||||
|
||||
}
|
||||
$account = $this->_repository->store($data);
|
||||
|
||||
if ($account->validate()) {
|
||||
// saved! return to wherever.
|
||||
Session::flash('success', 'Account "' . $account->name . '" created!');
|
||||
if (intval(Input::get('create')) === 1) {
|
||||
if ($data['post_submit_action'] == 'create_another') {
|
||||
return Redirect::route('accounts.create', $data['what']);
|
||||
} else {
|
||||
return Redirect::route('accounts.index', $data['what']);
|
||||
}
|
||||
break;
|
||||
case 'validate_only':
|
||||
$messageBags = $acct->validate($data);
|
||||
Session::flash('warnings', $messageBags['warnings']);
|
||||
Session::flash('successes', $messageBags['successes']);
|
||||
Session::flash('errors', $messageBags['errors']);
|
||||
return Redirect::route('accounts.create', $data['what'])->withInput();
|
||||
} else {
|
||||
|
||||
return Redirect::route('accounts.' . e($data['what']));
|
||||
}
|
||||
} else {
|
||||
// did not save, return with error:
|
||||
Session::flash('error', 'Could not save the new account: ' . $account->errors()->first());
|
||||
|
||||
return Redirect::route('accounts.create', $data['what'])->withErrors($account->errors())->withInput();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user