mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-12 15:35:15 +00:00
Expanded the 'save transaction' routine and cleaned it up. Still some work to do though.
This commit is contained in:
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use Firefly\Exception\FireflyException;
|
||||||
|
use Firefly\Helper\Controllers\TransactionInterface as TI;
|
||||||
use Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface as TJRI;
|
use Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface as TJRI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,13 +16,16 @@ class TransactionController extends BaseController
|
|||||||
{
|
{
|
||||||
|
|
||||||
protected $_repository;
|
protected $_repository;
|
||||||
|
protected $_helper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param TJRI $repository
|
* @param TJRI $repository
|
||||||
|
* @param TI $helper
|
||||||
*/
|
*/
|
||||||
public function __construct(TJRI $repository)
|
public function __construct(TJRI $repository, TI $helper)
|
||||||
{
|
{
|
||||||
$this->_repository = $repository;
|
$this->_repository = $repository;
|
||||||
|
$this->_helper = $helper;
|
||||||
View::share('title', 'Transactions');
|
View::share('title', 'Transactions');
|
||||||
View::share('mainTitleIcon', 'fa-repeat');
|
View::share('mainTitleIcon', 'fa-repeat');
|
||||||
}
|
}
|
||||||
@@ -55,7 +60,7 @@ class TransactionController extends BaseController
|
|||||||
|
|
||||||
return View::make('transactions.create')->with('accounts', $assetAccounts)->with('budgets', $budgets)->with(
|
return View::make('transactions.create')->with('accounts', $assetAccounts)->with('budgets', $budgets)->with(
|
||||||
'what', $what
|
'what', $what
|
||||||
)->with('piggies', $piggies)->with('subTitle', 'Add a new ' . $what)->with('title', 'Transactions');
|
)->with('piggies', $piggies)->with('subTitle', 'Add a new ' . $what);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -272,34 +277,37 @@ class TransactionController extends BaseController
|
|||||||
/**
|
/**
|
||||||
* @param $what
|
* @param $what
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Http\RedirectResponse
|
* @return $this|\Illuminate\Http\RedirectResponse
|
||||||
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function store($what)
|
public function store($what)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Collect data to process:
|
||||||
|
*/
|
||||||
|
$data = Input::except(['_token']);
|
||||||
|
$data['what'] = $what;
|
||||||
|
|
||||||
$journal = $this->_repository->store($what, Input::all());
|
switch (Input::get('post_submit_action')) {
|
||||||
if ($journal->errors()->count() > 0) {
|
case 'store':
|
||||||
Session::flash('error', 'Could not save transaction: ' . $journal->errors()->first() . '!');
|
/*
|
||||||
return Redirect::route('transactions.create', [$what])->withInput()->withErrors($journal->errors());
|
* Try to store:
|
||||||
}
|
*/
|
||||||
|
$messageBag = $this->_helper->store($data);
|
||||||
|
|
||||||
if ($journal->validate() && !is_null($journal->id)) {
|
/*
|
||||||
Session::flash('success', 'Transaction "' . $journal->description . '" saved!');
|
* Failure!
|
||||||
|
*/
|
||||||
|
if($messageBag->count() > 0) {
|
||||||
|
Session::flash('error', 'Could not save transaction: ' . $messageBag->first());
|
||||||
|
return Redirect::route('transactions.create', [$what])->withInput()->withErrors($messageBag);
|
||||||
|
}
|
||||||
|
|
||||||
// if reminder present, deactivate it:
|
/*
|
||||||
if (Input::get('reminder')) {
|
* Success!
|
||||||
/** @var \Firefly\Storage\Reminder\ReminderRepositoryInterface $reminders */
|
*/
|
||||||
$reminders = App::make('Firefly\Storage\Reminder\ReminderRepositoryInterface');
|
Session::flash('success', 'Transaction "' . e(Input::get('description')) . '" saved!');
|
||||||
$reminder = $reminders->find(Input::get('reminder'));
|
|
||||||
$reminders->deactivate($reminder);
|
|
||||||
}
|
|
||||||
|
|
||||||
// trigger the creation for recurring transactions.
|
|
||||||
Event::fire('journals.store', [$journal]);
|
|
||||||
|
|
||||||
if (Input::get('create') == '1') {
|
|
||||||
return Redirect::route('transactions.create', [$what])->withInput();
|
|
||||||
} else {
|
|
||||||
switch ($what) {
|
switch ($what) {
|
||||||
case 'withdrawal':
|
case 'withdrawal':
|
||||||
return Redirect::route('transactions.expenses');
|
return Redirect::route('transactions.expenses');
|
||||||
@@ -312,14 +320,11 @@ class TransactionController extends BaseController
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
break;
|
||||||
} else {
|
default:
|
||||||
Session::flash('error', 'Could not save transaction: ' . $journal->errors()->first() . '!');
|
throw new FireflyException('Method ' . Input::get('post_submit_action') . ' not implemented yet.');
|
||||||
|
break;
|
||||||
return Redirect::route('transactions.create', [$what])->withInput()->withErrors($journal->errors());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
119
app/lib/Firefly/Helper/Controllers/Transaction.php
Normal file
119
app/lib/Firefly/Helper/Controllers/Transaction.php
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Firefly\Helper\Controllers;
|
||||||
|
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Transaction
|
||||||
|
*
|
||||||
|
* @package Firefly\Helper\Controllers
|
||||||
|
*/
|
||||||
|
class Transaction implements TransactionInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a full transaction journal and associated stuff
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return MessageBag
|
||||||
|
*
|
||||||
|
* @SuppressWarnings(PHPMD.ShortVariable)
|
||||||
|
*/
|
||||||
|
public function store(array $data)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* save journal using repository
|
||||||
|
*/
|
||||||
|
/** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $journals */
|
||||||
|
$journals = \App::make('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
|
||||||
|
$journal = $journals->store($data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If invalid, return the message bag:
|
||||||
|
*/
|
||||||
|
if (!$journal->validate()) {
|
||||||
|
return $journal->errors();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save budget using repository
|
||||||
|
*/
|
||||||
|
if (isset($data['budget_id'])) {
|
||||||
|
/** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budgets */
|
||||||
|
$budgets = \App::make('Firefly\Storage\Budget\BudgetRepositoryInterface');
|
||||||
|
$budget = $budgets->find($data['budget_id']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save category using repository
|
||||||
|
*/
|
||||||
|
/** @var \Firefly\Storage\Category\CategoryRepositoryInterface $categories */
|
||||||
|
$categories = \App::make('Firefly\Storage\Category\CategoryRepositoryInterface');
|
||||||
|
$category = $categories->firstOrCreate($data['category']);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save accounts using repositories
|
||||||
|
* this depends on the kind of transaction and i've yet to fix this.
|
||||||
|
*/
|
||||||
|
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
|
||||||
|
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||||
|
|
||||||
|
if (isset($data['account_id'])) {
|
||||||
|
$from = $accounts->findAssetAccountById($data['account_id']);
|
||||||
|
}
|
||||||
|
if (isset($data['expense_account'])) {
|
||||||
|
$to = $accounts->findExpenseAccountByName($data['expense_account']);
|
||||||
|
}
|
||||||
|
if (isset($data['revenue_account'])) {
|
||||||
|
$from = $accounts->findRevenueAccountByName($data['revenue_account']);
|
||||||
|
$to = $accounts->findAssetAccountById($data['account_id']);
|
||||||
|
}
|
||||||
|
if (isset($data['account_from_id'])) {
|
||||||
|
$from = $accounts->findAssetAccountById($data['account_from_id']);
|
||||||
|
}
|
||||||
|
if (isset($data['account_to_id'])) {
|
||||||
|
$to = $accounts->findAssetAccountById($data['account_to_id']);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Add a custom error when they are the same.
|
||||||
|
*/
|
||||||
|
if($to->id == $from->id) {
|
||||||
|
$bag = new MessageBag;
|
||||||
|
$bag->add('account_from_id','The account from cannot be the same as the account to.');
|
||||||
|
return $bag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* save transactions using repository.
|
||||||
|
*/
|
||||||
|
$one = $journals->saveTransaction($journal, $from, floatval($data['amount']) * -1);
|
||||||
|
$two = $journals->saveTransaction($journal, $to, floatval($data['amount']));
|
||||||
|
/*
|
||||||
|
* Count for $journal is zero? Then there were errors!
|
||||||
|
*/
|
||||||
|
if ($journal->transactions()->count() < 2) {
|
||||||
|
/*
|
||||||
|
* Join message bags and return them:
|
||||||
|
*/
|
||||||
|
$bag = $one->errors();
|
||||||
|
$bag->merge($two->errors());
|
||||||
|
return $bag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Connect budget and category:
|
||||||
|
*/
|
||||||
|
if (isset($budget) && !is_null($budget)) {
|
||||||
|
$journal->budgets()->save($budget);
|
||||||
|
}
|
||||||
|
if (!is_null($category)) {
|
||||||
|
$journal->categories()->save($category);
|
||||||
|
}
|
||||||
|
$journal->completed = true;
|
||||||
|
$journal->save();
|
||||||
|
return $journal->errors();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
22
app/lib/Firefly/Helper/Controllers/TransactionInterface.php
Normal file
22
app/lib/Firefly/Helper/Controllers/TransactionInterface.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Firefly\Helper\Controllers;
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface TransactionInterface
|
||||||
|
*
|
||||||
|
* @package Firefly\Helper\Controllers
|
||||||
|
*/
|
||||||
|
interface TransactionInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a full transaction journal and associated stuff
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return MessageBag
|
||||||
|
*/
|
||||||
|
public function store(array $data);
|
||||||
|
|
||||||
|
}
|
@@ -26,6 +26,12 @@ class HelperServiceProvider extends ServiceProvider
|
|||||||
'Firefly\Helper\Controllers\ChartInterface',
|
'Firefly\Helper\Controllers\ChartInterface',
|
||||||
'Firefly\Helper\Controllers\Chart'
|
'Firefly\Helper\Controllers\Chart'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$this->app->bind(
|
||||||
|
'Firefly\Helper\Controllers\TransactionInterface',
|
||||||
|
'Firefly\Helper\Controllers\Transaction'
|
||||||
|
);
|
||||||
|
|
||||||
$this->app->bind(
|
$this->app->bind(
|
||||||
'Firefly\Helper\Controllers\CategoryInterface',
|
'Firefly\Helper\Controllers\CategoryInterface',
|
||||||
'Firefly\Helper\Controllers\Category'
|
'Firefly\Helper\Controllers\Category'
|
||||||
|
@@ -96,6 +96,13 @@ interface AccountRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function findExpenseAccountByName($name);
|
public function findExpenseAccountByName($name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $name
|
||||||
|
*
|
||||||
|
* @return |Account|null
|
||||||
|
*/
|
||||||
|
public function findRevenueAccountByName($name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \Account $from
|
* @param \Account $from
|
||||||
* @param \Account $to
|
* @param \Account $to
|
||||||
|
@@ -118,6 +118,40 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
|||||||
|
|
||||||
return $account;
|
return $account;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @param $name
|
||||||
|
*
|
||||||
|
* @return |Account|null
|
||||||
|
*/
|
||||||
|
public function findRevenueAccountByName($name)
|
||||||
|
{
|
||||||
|
// find account:
|
||||||
|
$type = $this->findAccountType('Revenue account');
|
||||||
|
$account = $this->_user->accounts()->where('name', $name)->where('account_type_id', $type->id)->first();
|
||||||
|
|
||||||
|
// find cash account as fall back:
|
||||||
|
if (is_null($account)) {
|
||||||
|
$cashType = $this->findAccountType('Cash account');
|
||||||
|
$account = $this->_user->accounts()->where('account_type_id', $cashType->id)->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create cash account as ultimate fall back:
|
||||||
|
if (is_null($account)) {
|
||||||
|
$set = [
|
||||||
|
'name' => 'Cash account',
|
||||||
|
'user_id' => $this->_user->id,
|
||||||
|
'active' => 1,
|
||||||
|
'account_type_id' => $cashType->id
|
||||||
|
];
|
||||||
|
$account = $this->firstOrCreate($set);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($account->active == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $account;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $type
|
* @param $type
|
||||||
|
@@ -55,7 +55,7 @@ interface CategoryRepositoryInterface
|
|||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function createOrFind($name);
|
public function firstOrCreate($name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \User $user
|
* @param \User $user
|
||||||
|
@@ -29,7 +29,8 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
|
|||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function importUpdateTransfer(Job $job, array $payload) {
|
public function importUpdateTransfer(Job $job, array $payload)
|
||||||
|
{
|
||||||
/** @var \Firefly\Storage\Import\ImportRepositoryInterface $repository */
|
/** @var \Firefly\Storage\Import\ImportRepositoryInterface $repository */
|
||||||
$repository = \App::make('Firefly\Storage\Import\ImportRepositoryInterface');
|
$repository = \App::make('Firefly\Storage\Import\ImportRepositoryInterface');
|
||||||
|
|
||||||
@@ -57,13 +58,13 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
|
|||||||
/*
|
/*
|
||||||
* Prep some vars from the payload
|
* Prep some vars from the payload
|
||||||
*/
|
*/
|
||||||
$transferId = intval($payload['data']['transfer_id']);
|
$transferId = intval($payload['data']['transfer_id']);
|
||||||
$componentId = intval($payload['data']['component_id']);
|
$componentId = intval($payload['data']['component_id']);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the import map for both:
|
* Find the import map for both:
|
||||||
*/
|
*/
|
||||||
$categoryMap = $repository->findImportEntry($importMap, 'Category', $componentId);
|
$categoryMap = $repository->findImportEntry($importMap, 'Category', $componentId);
|
||||||
$transferMap = $repository->findImportEntry($importMap, 'Transfer', $transferId);
|
$transferMap = $repository->findImportEntry($importMap, 'Transfer', $transferId);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -71,7 +72,7 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
if (is_null($categoryMap) || is_null($transferMap)) {
|
if (is_null($categoryMap) || is_null($transferMap)) {
|
||||||
\Log::notice('No map found in category/transfer mapper. Release.');
|
\Log::notice('No map found in category/transfer mapper. Release.');
|
||||||
if(\Config::get('queue.default') == 'sync') {
|
if (\Config::get('queue.default') == 'sync') {
|
||||||
$importMap->jobsdone++;
|
$importMap->jobsdone++;
|
||||||
$importMap->save();
|
$importMap->save();
|
||||||
$job->delete(); // count fixed
|
$job->delete(); // count fixed
|
||||||
@@ -93,7 +94,7 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
if (is_null($category) || is_null($journal)) {
|
if (is_null($category) || is_null($journal)) {
|
||||||
\Log::notice('Map is incorrect in category/transfer mapper. Release.');
|
\Log::notice('Map is incorrect in category/transfer mapper. Release.');
|
||||||
if(\Config::get('queue.default') == 'sync') {
|
if (\Config::get('queue.default') == 'sync') {
|
||||||
$importMap->jobsdone++;
|
$importMap->jobsdone++;
|
||||||
$importMap->save();
|
$importMap->save();
|
||||||
$job->delete(); // count fixed
|
$job->delete(); // count fixed
|
||||||
@@ -119,6 +120,27 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \User $user
|
||||||
|
*
|
||||||
|
* @return mixed|void
|
||||||
|
*/
|
||||||
|
public function overruleUser(\User $user)
|
||||||
|
{
|
||||||
|
$this->_user = $user;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $categoryId
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function find($categoryId)
|
||||||
|
{
|
||||||
|
return $this->_user->categories()->find($categoryId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Takes a transaction/category component and updates the transaction journal to match.
|
* Takes a transaction/category component and updates the transaction journal to match.
|
||||||
*
|
*
|
||||||
@@ -170,7 +192,7 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
if (is_null($categoryMap) || is_null($transactionMap)) {
|
if (is_null($categoryMap) || is_null($transactionMap)) {
|
||||||
\Log::notice('No map found in category/transaction mapper. Release.');
|
\Log::notice('No map found in category/transaction mapper. Release.');
|
||||||
if(\Config::get('queue.default') == 'sync') {
|
if (\Config::get('queue.default') == 'sync') {
|
||||||
$importMap->jobsdone++;
|
$importMap->jobsdone++;
|
||||||
$importMap->save();
|
$importMap->save();
|
||||||
$job->delete(); // count fixed
|
$job->delete(); // count fixed
|
||||||
@@ -192,7 +214,7 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
if (is_null($category) || is_null($journal)) {
|
if (is_null($category) || is_null($journal)) {
|
||||||
\Log::notice('Map is incorrect in category/transaction mapper. Release.');
|
\Log::notice('Map is incorrect in category/transaction mapper. Release.');
|
||||||
if(\Config::get('queue.default') == 'sync') {
|
if (\Config::get('queue.default') == 'sync') {
|
||||||
$importMap->jobsdone++;
|
$importMap->jobsdone++;
|
||||||
$importMap->save();
|
$importMap->save();
|
||||||
$job->delete(); // count fixed
|
$job->delete(); // count fixed
|
||||||
@@ -218,27 +240,6 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \User $user
|
|
||||||
*
|
|
||||||
* @return mixed|void
|
|
||||||
*/
|
|
||||||
public function overruleUser(\User $user)
|
|
||||||
{
|
|
||||||
$this->_user = $user;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $categoryId
|
|
||||||
*
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function find($categoryId)
|
|
||||||
{
|
|
||||||
return $this->_user->categories()->find($categoryId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Job $job
|
* @param Job $job
|
||||||
* @param array $payload
|
* @param array $payload
|
||||||
@@ -334,18 +335,16 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
|
|||||||
*
|
*
|
||||||
* @return \Category|mixed
|
* @return \Category|mixed
|
||||||
*/
|
*/
|
||||||
public function createOrFind($name)
|
public function firstOrCreate($name)
|
||||||
{
|
{
|
||||||
if (strlen($name) == 0) {
|
if (strlen($name) == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
$category = $this->findByName($name);
|
$data = [
|
||||||
if (!$category) {
|
'name' => $name,
|
||||||
return $this->store(['name' => $name]);
|
'user_id' => $this->_user->id,
|
||||||
}
|
];
|
||||||
|
return \Category::firstOrCreate($data);
|
||||||
return $category;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -52,7 +52,6 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
|
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
|
||||||
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
|
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||||
$accounts->overruleUser($user);
|
$accounts->overruleUser($user);
|
||||||
@@ -102,7 +101,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
|||||||
*/
|
*/
|
||||||
if (is_null($accountTo) || is_null($accountFrom)) {
|
if (is_null($accountTo) || is_null($accountFrom)) {
|
||||||
\Log::notice('No account to, or account from. Release transfer ' . $description);
|
\Log::notice('No account to, or account from. Release transfer ' . $description);
|
||||||
if(\Config::get('queue.default') == 'sync') {
|
if (\Config::get('queue.default') == 'sync') {
|
||||||
$importMap->jobsdone++;
|
$importMap->jobsdone++;
|
||||||
$importMap->save();
|
$importMap->save();
|
||||||
$job->delete(); // count fixed
|
$job->delete(); // count fixed
|
||||||
@@ -140,143 +139,58 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function store(array $data)
|
||||||
*
|
|
||||||
* We're building this thinking the money goes from A to B.
|
|
||||||
* If the amount is negative however, the money still goes
|
|
||||||
* from A to B but the balances are reversed.
|
|
||||||
*
|
|
||||||
* Aka:
|
|
||||||
*
|
|
||||||
* Amount = 200
|
|
||||||
* A loses 200 (-200). * -1
|
|
||||||
* B gains 200 (200). * 1
|
|
||||||
*
|
|
||||||
* Final balance: -200 for A, 200 for B.
|
|
||||||
*
|
|
||||||
* When the amount is negative:
|
|
||||||
*
|
|
||||||
* Amount = -200
|
|
||||||
* A gains 200 (200). * -1
|
|
||||||
* B loses 200 (-200). * 1
|
|
||||||
*
|
|
||||||
* @param \Account $from
|
|
||||||
* @param \Account $toAccount
|
|
||||||
* @param $description
|
|
||||||
* @param $amount
|
|
||||||
* @param \Carbon\Carbon $date
|
|
||||||
*
|
|
||||||
* @return \TransactionJournal
|
|
||||||
* @throws \Firefly\Exception\FireflyException
|
|
||||||
*/
|
|
||||||
public function createSimpleJournal(\Account $fromAccount, \Account $toAccount, $description, $amount, Carbon $date)
|
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Create the journal and fill relevant fields.
|
||||||
|
*/
|
||||||
$journal = new \TransactionJournal;
|
$journal = new \TransactionJournal;
|
||||||
|
$journal->description = trim($data['description']);
|
||||||
|
$journal->date = new Carbon($data['date']);
|
||||||
|
$journal->user_id = $this->_user->id;
|
||||||
$journal->completed = false;
|
$journal->completed = false;
|
||||||
$journal->description = $description;
|
|
||||||
$journal->date = $date;
|
|
||||||
|
|
||||||
$amountFrom = $amount * -1;
|
/*
|
||||||
$amountTo = $amount;
|
* Find the more complex fields and fill those:
|
||||||
|
*/
|
||||||
|
$currency = \TransactionCurrency::where('code', 'EUR')->first();
|
||||||
|
$journal->transaction_currency_id = $currency->id;
|
||||||
|
$transactionType = \TransactionType::where('type', $data['what'])->first();
|
||||||
|
$journal->transaction_type_id = $transactionType->id;
|
||||||
|
|
||||||
if (round(floatval($amount), 2) == 0.00) {
|
/*
|
||||||
$journal->errors()->add('amount', 'Amount must not be zero.');
|
* Validatre & save journal
|
||||||
|
*/
|
||||||
return $journal;
|
$journal->validate();
|
||||||
}
|
|
||||||
|
|
||||||
// account types for both:
|
|
||||||
$toAT = $toAccount->accountType->type;
|
|
||||||
$fromAT = $fromAccount->accountType->type;
|
|
||||||
|
|
||||||
$journalType = null;
|
|
||||||
|
|
||||||
switch (true) {
|
|
||||||
case ($fromAccount->transactions()->count() == 0 && $toAccount->transactions()->count() == 0):
|
|
||||||
$journalType = \TransactionType::where('type', 'Opening balance')->first();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case (in_array($fromAT, ['Default account', 'Asset account'])
|
|
||||||
&& in_array(
|
|
||||||
$toAT, ['Default account', 'Asset account']
|
|
||||||
)): // both are yours:
|
|
||||||
// determin transaction type. If both accounts are new, it's an initial balance transfer.
|
|
||||||
$journalType = \TransactionType::where('type', 'Transfer')->first();
|
|
||||||
break;
|
|
||||||
case ($amount < 0):
|
|
||||||
$journalType = \TransactionType::where('type', 'Deposit')->first();
|
|
||||||
break;
|
|
||||||
// is deposit into one of your own accounts:
|
|
||||||
case ($toAT == 'Default account' || $toAT == 'Asset account'):
|
|
||||||
$journalType = \TransactionType::where('type', 'Deposit')->first();
|
|
||||||
break;
|
|
||||||
// is withdrawal from one of your own accounts:
|
|
||||||
case ($fromAT == 'Default account' || $fromAT == 'Asset account'):
|
|
||||||
$journalType = \TransactionType::where('type', 'Withdrawal')->first();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_null($journalType)) {
|
|
||||||
throw new FireflyException('Could not figure out transaction type.');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// always the same currency:
|
|
||||||
$currency = \TransactionCurrency::where('code', 'EUR')->first();
|
|
||||||
if (is_null($currency)) {
|
|
||||||
throw new FireflyException('No currency for journal!');
|
|
||||||
}
|
|
||||||
|
|
||||||
// new journal:
|
|
||||||
|
|
||||||
$journal->transactionType()->associate($journalType);
|
|
||||||
$journal->transactionCurrency()->associate($currency);
|
|
||||||
$journal->user()->associate($this->_user);
|
|
||||||
|
|
||||||
// same account:
|
|
||||||
if ($fromAccount->id == $toAccount->id) {
|
|
||||||
|
|
||||||
$journal->errors()->add('account_to_id', 'Must be different from the "account from".');
|
|
||||||
$journal->errors()->add('account_from_id', 'Must be different from the "account to".');
|
|
||||||
return $journal;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!$journal->validate()) {
|
|
||||||
return $journal;
|
|
||||||
}
|
|
||||||
$journal->save();
|
|
||||||
|
|
||||||
// create transactions:
|
|
||||||
$fromTransaction = new \Transaction;
|
|
||||||
$fromTransaction->account()->associate($fromAccount);
|
|
||||||
$fromTransaction->transactionJournal()->associate($journal);
|
|
||||||
$fromTransaction->description = null;
|
|
||||||
$fromTransaction->amount = $amountFrom;
|
|
||||||
if (!$fromTransaction->validate()) {
|
|
||||||
throw new FireflyException('Cannot create valid transaction (from): ' . $fromTransaction->errors()
|
|
||||||
->first());
|
|
||||||
}
|
|
||||||
$fromTransaction->save();
|
|
||||||
|
|
||||||
$toTransaction = new \Transaction;
|
|
||||||
$toTransaction->account()->associate($toAccount);
|
|
||||||
$toTransaction->transactionJournal()->associate($journal);
|
|
||||||
$toTransaction->description = null;
|
|
||||||
$toTransaction->amount = $amountTo;
|
|
||||||
if (!$toTransaction->validate()) {
|
|
||||||
|
|
||||||
throw new FireflyException('Cannot create valid transaction (to): ' . $toTransaction->errors()->first()
|
|
||||||
. ': ' . print_r($toAccount->toArray(), true));
|
|
||||||
}
|
|
||||||
$toTransaction->save();
|
|
||||||
|
|
||||||
$journal->completed = true;
|
|
||||||
$journal->save();
|
$journal->save();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return regardless.
|
||||||
|
*/
|
||||||
return $journal;
|
return $journal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \TransactionJournal $journal
|
||||||
|
* @param \Account $account
|
||||||
|
* @param $amount
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function saveTransaction(\TransactionJournal $journal, \Account $account, $amount)
|
||||||
|
{
|
||||||
|
$transaction = new \Transaction;
|
||||||
|
$transaction->account_id = $account->id;
|
||||||
|
$transaction->transaction_journal_id = $journal->id;
|
||||||
|
$transaction->amount = $amount;
|
||||||
|
if ($transaction->validate()) {
|
||||||
|
$transaction->save();
|
||||||
|
}
|
||||||
|
return $transaction;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Job $job
|
* @param Job $job
|
||||||
* @param array $payload
|
* @param array $payload
|
||||||
@@ -304,7 +218,6 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
|
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
|
||||||
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
|
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||||
$accounts->overruleUser($user);
|
$accounts->overruleUser($user);
|
||||||
@@ -364,7 +277,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
|||||||
*/
|
*/
|
||||||
if (is_null($assetAccount)) {
|
if (is_null($assetAccount)) {
|
||||||
\Log::notice('No asset account for "' . $description . '", try again later.');
|
\Log::notice('No asset account for "' . $description . '", try again later.');
|
||||||
if(\Config::get('queue.default') == 'sync') {
|
if (\Config::get('queue.default') == 'sync') {
|
||||||
$importMap->jobsdone++;
|
$importMap->jobsdone++;
|
||||||
$importMap->save();
|
$importMap->save();
|
||||||
$job->delete(); // count fixed
|
$job->delete(); // count fixed
|
||||||
@@ -417,20 +330,20 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
|||||||
{
|
{
|
||||||
return $this->_user->transactionjournals()->with(
|
return $this->_user->transactionjournals()->with(
|
||||||
['transactions' => function ($q) {
|
['transactions' => function ($q) {
|
||||||
return $q->orderBy('amount', 'ASC');
|
return $q->orderBy('amount', 'ASC');
|
||||||
}, 'transactioncurrency', 'transactiontype', 'components', 'transactions.account',
|
}, 'transactioncurrency', 'transactiontype', 'components', 'transactions.account',
|
||||||
'transactions.account.accounttype']
|
'transactions.account.accounttype']
|
||||||
)
|
)
|
||||||
->where('id', $journalId)->first();
|
->where('id', $journalId)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
*
|
// *
|
||||||
*/
|
// */
|
||||||
public function get()
|
// public function get()
|
||||||
{
|
// {
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $type
|
* @param $type
|
||||||
@@ -534,129 +447,6 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $what
|
|
||||||
* @param $data
|
|
||||||
*
|
|
||||||
* @return mixed|\TransactionJournal
|
|
||||||
*/
|
|
||||||
public function store($what, $data)
|
|
||||||
{
|
|
||||||
// $fromAccount and $toAccount are found
|
|
||||||
// depending on the $what
|
|
||||||
|
|
||||||
$fromAccount = null;
|
|
||||||
$toAccount = null;
|
|
||||||
|
|
||||||
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */
|
|
||||||
$accountRepository = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
|
|
||||||
$accountRepository->overruleUser($this->_user);
|
|
||||||
|
|
||||||
/** @var \Firefly\Storage\Category\CategoryRepositoryInterface $catRepository */
|
|
||||||
$catRepository = \App::make('Firefly\Storage\Category\CategoryRepositoryInterface');
|
|
||||||
$catRepository->overruleUser($this->_user);
|
|
||||||
|
|
||||||
/** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budRepository */
|
|
||||||
$budRepository = \App::make('Firefly\Storage\Budget\BudgetRepositoryInterface');
|
|
||||||
$budRepository->overruleUser($this->_user);
|
|
||||||
|
|
||||||
|
|
||||||
switch ($what) {
|
|
||||||
case 'withdrawal':
|
|
||||||
$fromAccount = $accountRepository->find(intval($data['account_id']));
|
|
||||||
$expenseAccountType = $accountRepository->findAccountType('Expense account');
|
|
||||||
$set = [
|
|
||||||
'name' => $data['expense_account'],
|
|
||||||
'account_type_id' => $expenseAccountType->id,
|
|
||||||
'user_id' => $this->_user->id,
|
|
||||||
'active' => 1];
|
|
||||||
$toAccount = $accountRepository->firstOrCreate($set);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'deposit':
|
|
||||||
$revenueAccountType = $accountRepository->findAccountType('Revenue account');
|
|
||||||
$set = [
|
|
||||||
'name' => $data['revenue_account'],
|
|
||||||
'account_type_id' => $revenueAccountType->id,
|
|
||||||
'user_id' => $this->_user->id,
|
|
||||||
'active' => 1];
|
|
||||||
|
|
||||||
$fromAccount = $accountRepository->firstOrCreate($set);
|
|
||||||
$toAccount = $accountRepository->find(intval($data['account_id']));
|
|
||||||
break;
|
|
||||||
case 'transfer':
|
|
||||||
$fromAccount = $accountRepository->find(intval($data['account_from_id']));
|
|
||||||
$toAccount = $accountRepository->find(intval($data['account_to_id']));
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// fall back to cash if necessary:
|
|
||||||
$fromAccount = is_null($fromAccount) ? $fromAccount = $accountRepository->getCashAccount() : $fromAccount;
|
|
||||||
$toAccount = is_null($toAccount) ? $toAccount = $accountRepository->getCashAccount() : $toAccount;
|
|
||||||
|
|
||||||
// create or find category:
|
|
||||||
$category = isset($data['category']) ? $catRepository->createOrFind($data['category']) : null;
|
|
||||||
|
|
||||||
// find budget:
|
|
||||||
$budget = isset($data['budget_id']) ? $budRepository->find(intval($data['budget_id'])) : null;
|
|
||||||
// find amount & description:
|
|
||||||
$description = trim($data['description']);
|
|
||||||
$amount = floatval($data['amount']);
|
|
||||||
$date = new Carbon($data['date']);
|
|
||||||
|
|
||||||
// try to create a journal:
|
|
||||||
$transactionJournal = $this->createSimpleJournal($fromAccount, $toAccount, $description, $amount, $date);
|
|
||||||
if (!$transactionJournal->id || $transactionJournal->completed == 0) {
|
|
||||||
return $transactionJournal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// here we're done and we have transactions in the journal:
|
|
||||||
// do something with the piggy bank:
|
|
||||||
if ($what == 'transfer') {
|
|
||||||
/** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $piggyRepository */
|
|
||||||
$piggyRepository = \App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
|
|
||||||
$piggyRepository->overruleUser($this->_user);
|
|
||||||
|
|
||||||
if (isset($data['piggybank_id'])) {
|
|
||||||
/** @var \Piggybank $piggyBank */
|
|
||||||
$piggyBank = $piggyRepository->find(intval($data['piggybank_id']));
|
|
||||||
|
|
||||||
if ($piggyBank) {
|
|
||||||
// one of the two transactions may be connected to this piggy bank.
|
|
||||||
$connected = false;
|
|
||||||
foreach ($transactionJournal->transactions()->get() as $transaction) {
|
|
||||||
if ($transaction->account_id == $piggyBank->account_id) {
|
|
||||||
$connected = true;
|
|
||||||
$transaction->piggybank()->associate($piggyBank);
|
|
||||||
$transaction->save();
|
|
||||||
\Event::fire(
|
|
||||||
'piggybanks.createRelatedTransfer', [$piggyBank, $transactionJournal, $transaction]
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ($connected === false) {
|
|
||||||
\Session::flash(
|
|
||||||
'warning', 'Piggy bank "' . e($piggyBank->name)
|
|
||||||
. '" is not set to draw money from any of the accounts in this transfer'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// attach:
|
|
||||||
if (!is_null($budget)) {
|
|
||||||
$transactionJournal->budgets()->save($budget);
|
|
||||||
}
|
|
||||||
if (!is_null($category)) {
|
|
||||||
$transactionJournal->categories()->save($category);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $transactionJournal;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \TransactionJournal $journal
|
* @param \TransactionJournal $journal
|
||||||
* @param $data
|
* @param $data
|
||||||
|
@@ -28,21 +28,21 @@ interface TransactionJournalRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function importTransfer(Job $job, array $payload);
|
public function importTransfer(Job $job, array $payload);
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* @param \Account $from
|
// * @param \Account $from
|
||||||
* @param \Account $toAccount
|
// * @param \Account $toAccount
|
||||||
* @param $description
|
// * @param $description
|
||||||
* @param $amount
|
// * @param $amount
|
||||||
* @param Carbon $date
|
// * @param Carbon $date
|
||||||
*
|
// *
|
||||||
* @return mixed
|
// * @return mixed
|
||||||
*/
|
// */
|
||||||
public function createSimpleJournal(\Account $from, \Account $toAccount, $description, $amount, Carbon $date);
|
// public function createSimpleJournal(\Account $from, \Account $toAccount, $description, $amount, Carbon $date);
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* @return mixed
|
// * @return mixed
|
||||||
*/
|
// */
|
||||||
public function get();
|
// public function get();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,12 +53,22 @@ interface TransactionJournalRepositoryInterface
|
|||||||
public function overruleUser(\User $user);
|
public function overruleUser(\User $user);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $what
|
* Store a new transaction journal.
|
||||||
|
*
|
||||||
* @param $data
|
* @param $data
|
||||||
*
|
*
|
||||||
|
* @return \TransactionJournal|null
|
||||||
|
*/
|
||||||
|
public function store(array $data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param \TransactionJournal $journal
|
||||||
|
* @param \Account $account
|
||||||
|
* @param $amount
|
||||||
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function store($what, $data);
|
public function saveTransaction(\TransactionJournal $journal, \Account $account, $amount);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \TransactionJournal $journal
|
* @param \TransactionJournal $journal
|
||||||
|
@@ -27,11 +27,13 @@ class Component extends SingleTableInheritanceEntity
|
|||||||
public static $rules
|
public static $rules
|
||||||
= [
|
= [
|
||||||
'user_id' => 'exists:users,id|required',
|
'user_id' => 'exists:users,id|required',
|
||||||
'name' => ['required', 'between:1,100', 'alphabasic'],
|
'name' => ['required', 'between:1,100','min:1', 'alphabasic'],
|
||||||
'class' => 'required',
|
'class' => 'required',
|
||||||
];
|
];
|
||||||
protected $table = 'components';
|
protected $table = 'components';
|
||||||
protected $subclassField = 'class';
|
protected $subclassField = 'class';
|
||||||
|
protected $fillable = ['name','user_id'];
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
|
@@ -1,235 +1,277 @@
|
|||||||
@extends('layouts.default')
|
@extends('layouts.default')
|
||||||
@section('content')
|
@section('content')
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-6 col-md-12 col-sm-12">
|
|
||||||
<p class="text-info">
|
|
||||||
@if($what == 'withdrawal')
|
|
||||||
Some text about moving from asset accounts to expense accounts
|
|
||||||
@endif
|
|
||||||
@if($what == 'deposit')
|
|
||||||
A deposit is when you earn money, moving an amount from a beneficiary into your own account.
|
|
||||||
@endif
|
|
||||||
@if($what == 'transfer')
|
|
||||||
TRANSFER
|
|
||||||
@endif
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{Form::open(['class' => 'form-horizontal','url' => route('transactions.store',$what)])}}
|
{{Form::open(['class' => 'form-horizontal','url' => route('transactions.store',$what)])}}
|
||||||
{{Form::hidden('reminder',Input::get('reminder_id'))}}
|
{{Form::hidden('reminder',Input::get('reminder_id'))}}
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-6 col-md-12 col-sm-12">
|
<div class="col-lg-6 col-md-12 col-sm-12">
|
||||||
<h4>Mandatory fields</h4>
|
<!-- panel for mandatory fields -->
|
||||||
|
<div class="panel panel-primary">
|
||||||
<!-- ALWAYS AVAILABLE -->
|
<div class="panel-heading">
|
||||||
<div class="form-group">
|
<i class="fa fa-exclamation-circle"></i> Mandatory fields
|
||||||
<label for="description" class="col-sm-4 control-label">Description</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" name="description" value="{{{Input::old('description') ?: Input::get('description')}}}" autocomplete="off" class="form-control" placeholder="Description" />
|
|
||||||
@if($errors->has('description'))
|
|
||||||
<p class="text-danger">{{$errors->first('description')}}</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<!-- DESCRIPTION ALWAYS AVAILABLE -->
|
||||||
|
<div
|
||||||
|
@if($errors->has('description'))
|
||||||
|
class="form-group has-error has-feedback"
|
||||||
|
@else
|
||||||
|
class="form-group"
|
||||||
|
@endif
|
||||||
|
>
|
||||||
|
<label for="description" class="col-sm-4 control-label">Description</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input
|
||||||
|
type="text" name="description"
|
||||||
|
value="{{{Input::old('description') ?: Input::get('description')}}}"
|
||||||
|
placeholder="Description"
|
||||||
|
autocomplete="off"
|
||||||
|
class="form-control" />
|
||||||
|
@if($errors->has('description'))
|
||||||
|
<p class="text-danger">{{$errors->first('description')}}</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- SHOW ACCOUNT (FROM) ONLY FOR WITHDRAWALS AND DEPOSITS -->
|
||||||
|
@if($what == 'deposit' || $what == 'withdrawal')
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="account_id" class="col-sm-4 control-label">
|
||||||
|
Asset account
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
{{Form::select('account_id',$accounts,Input::old('account_id') ?: Input::get('account_id'),['class' => 'form-control'])}}
|
||||||
|
@if($errors->has('account_id'))
|
||||||
|
<p class="text-danger">{{$errors->first('account_id')}}</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- SHOW EXPENSE ACCOUNT ONLY FOR WITHDRAWALS -->
|
||||||
|
@if($what == 'withdrawal')
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="expense_account" class="col-sm-4 control-label">Expense account</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="text" name="expense_account" value="{{{Input::old('expense_account')}}}" autocomplete="off" class="form-control" placeholder="Expense account" />
|
||||||
|
@if($errors->has('expense_account'))
|
||||||
|
<p class="text-danger">{{$errors->first('expense_account')}}</p>
|
||||||
|
@else
|
||||||
|
<span class="help-block">
|
||||||
|
This field will auto-complete your existing expense accounts (where you spent the
|
||||||
|
money), but you can type freely to create new ones. If you took the money from
|
||||||
|
an ATM, you should leave this field empty.</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- SHOW REVENUE ACCOUNT ONLY FOR DEPOSITS -->
|
||||||
|
@if($what == 'deposit')
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="revenue_account" class="col-sm-4 control-label">
|
||||||
|
Revenue account
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="text" name="revenue_account" value="{{{Input::old('revenue_account')}}}" autocomplete="off" class="form-control" placeholder="Revenue account" />
|
||||||
|
@if($errors->has('beneficiary'))
|
||||||
|
<p class="text-danger">{{$errors->first('revenue_account')}}</p>
|
||||||
|
@else
|
||||||
|
<span class="help-block">
|
||||||
|
This field will auto-complete your existing revenue accounts (if any), but you can type freely to create new ones.</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- ONLY SHOW FROM/TO ACCOUNT WHEN CREATING TRANSFER -->
|
||||||
|
@if($what == 'transfer')
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="account_from_id" class="col-sm-4 control-label">Account from</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
{{Form::select('account_from_id',$accounts,Input::old('account_from_id') ?: Input::get('account_from_id'),['class' => 'form-control'])}}
|
||||||
|
@if($errors->has('account_from_id'))
|
||||||
|
<p class="text-danger">{{$errors->first('account_from_id')}}</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="account_to_id" class="col-sm-4 control-label">Account to</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
{{Form::select('account_to_id',$accounts,Input::old('account_to_id') ?: Input::get('account_to_id'),['class' => 'form-control'])}}
|
||||||
|
@if($errors->has('account_to_id'))
|
||||||
|
<p class="text-danger">{{$errors->first('account_to_id')}}</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
|
<!-- ALWAYS SHOW AMOUNT -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="amount" class="col-sm-4 control-label">
|
||||||
|
@if($what == 'withdrawal')
|
||||||
|
Amount spent
|
||||||
|
@endif
|
||||||
|
@if($what == 'deposit')
|
||||||
|
Amount received
|
||||||
|
@endif
|
||||||
|
@if($what == 'transfer')
|
||||||
|
Amount transferred
|
||||||
|
@endif
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="number" name="amount" min="0.01" value="{{Input::old('amount') ?: Input::get('amount')}}" step="any" class="form-control" />
|
||||||
|
@if($errors->has('amount'))
|
||||||
|
<p class="text-danger">{{$errors->first('amount')}}</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ALWAYS SHOW DATE -->
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="date" class="col-sm-4 control-label">Date</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input type="date" name="date" value="{{Input::old('date') ?: date('Y-m-d')}}" class="form-control" />
|
||||||
|
@if($errors->has('date'))
|
||||||
|
<p class="text-danger">{{$errors->first('date')}}</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- SHOW ACCOUNT (FROM) ONLY FOR WITHDRAWALS AND DEPOSITS -->
|
<p>
|
||||||
@if($what == 'deposit' || $what == 'withdrawal')
|
<button type="submit" class="btn btn-lg btn-success">
|
||||||
<div class="form-group">
|
<i class="fa fa-plus-circle"></i> Store new {{{$what}}}
|
||||||
<label for="account_id" class="col-sm-4 control-label">
|
</button>
|
||||||
Asset account
|
</p>
|
||||||
</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
{{Form::select('account_id',$accounts,Input::old('account_id') ?: Input::get('account_id'),['class' => 'form-control'])}}
|
|
||||||
@if($errors->has('account_id'))
|
|
||||||
<p class="text-danger">{{$errors->first('account_id')}}</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<!-- SHOW EXPENSE ACCOUNT ONLY FOR WITHDRAWALS -->
|
|
||||||
@if($what == 'withdrawal')
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="expense_account" class="col-sm-4 control-label">Expense account</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" name="expense_account" value="{{{Input::old('expense_account')}}}" autocomplete="off" class="form-control" placeholder="Expense account" />
|
|
||||||
@if($errors->has('expense_account'))
|
|
||||||
<p class="text-danger">{{$errors->first('expense_account')}}</p>
|
|
||||||
@else
|
|
||||||
<span class="help-block">This field will auto-complete your existing expense accounts (if any), but you can type freely to create new ones.</span>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<!-- SHOW REVENUE ACCOUNT ONLY FOR DEPOSITS -->
|
|
||||||
@if($what == 'deposit')
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="revenue_account" class="col-sm-4 control-label">
|
|
||||||
Revenue account
|
|
||||||
</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" name="revenue_account" value="{{{Input::old('revenue_account')}}}" autocomplete="off" class="form-control" placeholder="Revenue account" />
|
|
||||||
@if($errors->has('beneficiary'))
|
|
||||||
<p class="text-danger">{{$errors->first('revenue_account')}}</p>
|
|
||||||
@else
|
|
||||||
<span class="help-block">This field will auto-complete your existing revenue accounts (if any), but you can type freely to create new ones.</span>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<!-- ONLY SHOW FROM/TO ACCOUNT WHEN CREATING TRANSFER -->
|
|
||||||
@if($what == 'transfer')
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="account_from_id" class="col-sm-4 control-label">Account from</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
{{Form::select('account_from_id',$accounts,Input::old('account_from_id') ?: Input::get('account_from_id'),['class' => 'form-control'])}}
|
|
||||||
@if($errors->has('account_from_id'))
|
|
||||||
<p class="text-danger">{{$errors->first('account_from_id')}}</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="account_to_id" class="col-sm-4 control-label">Account to</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
{{Form::select('account_to_id',$accounts,Input::old('account_to_id') ?: Input::get('account_to_id'),['class' => 'form-control'])}}
|
|
||||||
@if($errors->has('account_to_id'))
|
|
||||||
<p class="text-danger">{{$errors->first('account_to_id')}}</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<!-- ALWAYS SHOW AMOUNT -->
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="amount" class="col-sm-4 control-label">
|
|
||||||
@if($what == 'withdrawal')
|
|
||||||
Amount spent
|
|
||||||
@endif
|
|
||||||
@if($what == 'deposit')
|
|
||||||
Amount received
|
|
||||||
@endif
|
|
||||||
@if($what == 'transfer')
|
|
||||||
Amount transferred
|
|
||||||
@endif
|
|
||||||
</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="number" name="amount" min="0.01" value="{{Input::old('amount') ?: Input::get('amount')}}" step="any" class="form-control" />
|
|
||||||
@if($errors->has('amount'))
|
|
||||||
<p class="text-danger">{{$errors->first('amount')}}</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- ALWAYS SHOW DATE -->
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="date" class="col-sm-4 control-label">Date</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="date" name="date" value="{{Input::old('date') ?: date('Y-m-d')}}" class="form-control" />
|
|
||||||
@if($errors->has('date'))
|
|
||||||
<p class="text-danger">{{$errors->first('date')}}</p>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6 col-md-12 col-sm-12">
|
<div class="col-lg-6 col-md-12 col-sm-12">
|
||||||
<h4>Optional fields</h4>
|
<!-- panel for mandatory fields -->
|
||||||
|
<div class="panel panel-default">
|
||||||
<!-- BUDGET ONLY WHEN CREATING A WITHDRAWAL -->
|
<div class="panel-heading">
|
||||||
@if($what == 'withdrawal')
|
<i class="fa fa-smile-o"></i> Optional fields
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label for="budget_id" class="col-sm-4 control-label">Budget</label>
|
<div class="panel-body">
|
||||||
<div class="col-sm-8">
|
<!-- BUDGET ONLY WHEN CREATING A WITHDRAWAL -->
|
||||||
{{Form::select('budget_id',$budgets,Input::old('budget_id') ?: 0,['class' => 'form-control'])}}
|
@if($what == 'withdrawal')
|
||||||
@if($errors->has('budget_id'))
|
<div class="form-group">
|
||||||
<p class="text-danger">{{$errors->first('budget_id')}}</p>
|
<label for="budget_id" class="col-sm-4 control-label">Budget</label>
|
||||||
@else
|
<div class="col-sm-8">
|
||||||
<span class="help-block">Select one of your budgets to make this transaction a part of it.</span>
|
{{Form::select('budget_id',$budgets,Input::old('budget_id') ?: 0,['class' => 'form-control'])}}
|
||||||
@endif
|
@if($errors->has('budget_id'))
|
||||||
</div>
|
<p class="text-danger">{{$errors->first('budget_id')}}</p>
|
||||||
</div>
|
@else
|
||||||
@endif
|
<span class="help-block">Select one of your budgets to make this transaction a part of it.</span>
|
||||||
<!-- CATEGORY ALWAYS -->
|
@endif
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label for="category" class="col-sm-4 control-label">Category</label>
|
</div>
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="text" name="category" value="{{Input::old('category')}}" autocomplete="off" class="form-control" placeholder="Category" />
|
|
||||||
@if($errors->has('category'))
|
|
||||||
<p class="text-danger">{{$errors->first('category')}}</p>
|
|
||||||
@else
|
|
||||||
<span class="help-block">Add more fine-grained information to this transaction by entering a category.
|
|
||||||
Like the beneficiary-field, this field will auto-complete existing categories but can also be used
|
|
||||||
to create new ones.
|
|
||||||
</span>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- RELATE THIS TRANSFER TO A PIGGY BANK -->
|
|
||||||
@if($what == 'transfer' && count($piggies) > 0)
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="piggybank_id" class="col-sm-4 control-label">
|
|
||||||
Piggy bank
|
|
||||||
</label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<select name="piggybank_id" class="form-control">
|
|
||||||
<option value="0" label="(no piggy bank)">(no piggy bank)</option>
|
|
||||||
@foreach($piggies as $piggy)
|
|
||||||
@if($piggy->id == Input::old('piggybank_id') || $piggy->id == Input::get('piggybank_id'))
|
|
||||||
<option value="{{$piggy->id}}" label="{{{$piggy->name}}}" selected="selected ">{{{$piggy->name}}}</option>
|
|
||||||
@else
|
|
||||||
<option value="{{$piggy->id}}" label="{{{$piggy->name}}}">{{{$piggy->name}}}</option>
|
|
||||||
@endif
|
@endif
|
||||||
@endforeach
|
<!-- CATEGORY ALWAYS -->
|
||||||
</select>
|
<div class="form-group">
|
||||||
@if($errors->has('piggybank_id'))
|
<label for="category" class="col-sm-4 control-label">Category</label>
|
||||||
<p class="text-danger">{{$errors->first('piggybank_id')}}</p>
|
<div class="col-sm-8">
|
||||||
@else
|
<input type="text" name="category" value="{{Input::old('category')}}" autocomplete="off" class="form-control" placeholder="Category" />
|
||||||
<span class="help-block">
|
@if($errors->has('category'))
|
||||||
You can directly add the amount you're transferring
|
<p class="text-danger">{{$errors->first('category')}}</p>
|
||||||
to one of your piggy banks, provided they are related to the account your
|
@else
|
||||||
transferring <em>to</em>.
|
<span class="help-block">Add more fine-grained information to this transaction by entering a category.
|
||||||
</span>
|
This field will auto-complete existing categories but can also be used to create new ones.
|
||||||
@endif
|
</span>
|
||||||
</div>
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endif
|
</div>
|
||||||
|
<!-- TAGS -->
|
||||||
|
|
||||||
|
|
||||||
</div>
|
<!-- RELATE THIS TRANSFER TO A PIGGY BANK -->
|
||||||
</div>
|
@if($what == 'transfer' && count($piggies) > 0)
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="piggybank_id" class="col-sm-4 control-label">
|
||||||
|
Piggy bank
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<select name="piggybank_id" class="form-control">
|
||||||
|
<option value="0" label="(no piggy bank)">(no piggy bank)</option>
|
||||||
|
@foreach($piggies as $piggy)
|
||||||
|
@if($piggy->id == Input::old('piggybank_id') || $piggy->id == Input::get('piggybank_id'))
|
||||||
|
<option value="{{$piggy->id}}" label="{{{$piggy->name}}}" selected="selected ">{{{$piggy->name}}}</option>
|
||||||
|
@else
|
||||||
|
<option value="{{$piggy->id}}" label="{{{$piggy->name}}}">{{{$piggy->name}}}</option>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
@if($errors->has('piggybank_id'))
|
||||||
|
<p class="text-danger">{{$errors->first('piggybank_id')}}</p>
|
||||||
|
@else
|
||||||
|
<span class="help-block">
|
||||||
|
You can directly add the amount you're transferring
|
||||||
|
to one of your piggy banks, provided they are related to the account your
|
||||||
|
transferring <em>to</em>.
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="panel panel-default">
|
||||||
<div class="col-lg-6">
|
<div class="panel-heading">
|
||||||
<!-- add another after this one? -->
|
<i class="fa fa-bolt"></i> Options
|
||||||
<div class="form-group">
|
</div>
|
||||||
<label for="submit" class="col-sm-4 control-label"> </label>
|
<div class="panel-body">
|
||||||
<div class="col-sm-8">
|
<div class="form-group">
|
||||||
<div class="checkbox">
|
<label for="default" class="col-sm-4 control-label">
|
||||||
<label>
|
Store
|
||||||
<input type="checkbox" value="1" name="create" @if(Input::old('create') == '1') checked @endif>
|
</label>
|
||||||
Create another (return to this form)
|
<div class="col-sm-8">
|
||||||
</label>
|
<div class="radio">
|
||||||
|
<label>
|
||||||
|
{{Form::radio('post_submit_action','store',true)}}
|
||||||
|
Store the {{{$what}}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="validate_only" class="col-sm-4 control-label">
|
||||||
|
Validate only
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<div class="radio">
|
||||||
|
<label>
|
||||||
|
{{Form::radio('post_submit_action','validate_only')}}
|
||||||
|
Only validate, do not save
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="return_to_form" class="col-sm-4 control-label">
|
||||||
|
Return here
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<div class="radio">
|
||||||
|
<label>
|
||||||
|
{{Form::radio('post_submit_action','create_another')}}
|
||||||
|
After storing, return here to create another one.
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- ALWAYS SHOW SUBMit -->
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="submit" class="col-sm-4 control-label"> </label>
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<input type="submit" name="submit" value="Create {{$what}}" class="btn btn-info" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{{Form::close()}}
|
{{Form::close()}}
|
||||||
|
|
||||||
@stop
|
@stop
|
||||||
@section('scripts')
|
@section('scripts')
|
||||||
|
<!-- a -->
|
||||||
<?php echo javascript_include_tag('transactions'); ?>
|
<?php echo javascript_include_tag('transactions'); ?>
|
||||||
|
<!-- b -->
|
||||||
@stop
|
@stop
|
Reference in New Issue
Block a user