mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Create deposits, transfers and withdrawals. Also tests!
This commit is contained in:
parent
1f4436cb75
commit
9687b5fb33
@ -35,16 +35,46 @@ class TransactionController extends BaseController
|
||||
|
||||
$budgets[0] = '(no budget)';
|
||||
|
||||
|
||||
return View::make('transactions.withdrawal')->with('accounts', $accounts)->with('budgets', $budgets);
|
||||
}
|
||||
|
||||
public function createDeposit()
|
||||
{
|
||||
// get accounts with names and id's.
|
||||
$accounts = $this->accounts->getActiveDefaultAsSelectList();
|
||||
|
||||
$budgets = $this->budgets->getAsSelectList();
|
||||
|
||||
$budgets[0] = '(no budget)';
|
||||
|
||||
return View::make('transactions.deposit')->with('accounts', $accounts)->with('budgets', $budgets);
|
||||
|
||||
}
|
||||
|
||||
public function createTransfer()
|
||||
{
|
||||
// get accounts with names and id's.
|
||||
$accounts = $this->accounts->getActiveDefaultAsSelectList();
|
||||
|
||||
$budgets = $this->budgets->getAsSelectList();
|
||||
|
||||
$budgets[0] = '(no budget)';
|
||||
|
||||
return View::make('transactions.transfer')->with('accounts', $accounts)->with('budgets', $budgets);
|
||||
|
||||
}
|
||||
|
||||
public function postCreateWithdrawal()
|
||||
{
|
||||
|
||||
// create or find beneficiary:
|
||||
$beneficiary = $this->accounts->createOrFindBeneficiary(Input::get('beneficiary'));
|
||||
|
||||
// fall back to cash account if empty:
|
||||
if (is_null($beneficiary)) {
|
||||
$beneficiary = $this->accounts->getCashAccount();
|
||||
}
|
||||
|
||||
// create or find category:
|
||||
$category = $this->categories->createOrFind(Input::get('category'));
|
||||
|
||||
@ -61,7 +91,11 @@ class TransactionController extends BaseController
|
||||
|
||||
// create journal
|
||||
/** @var \TransactionJournal $journal */
|
||||
$journal = $this->tj->createSimpleJournal($account, $beneficiary, $description, $amount, $date);
|
||||
try {
|
||||
$journal = $this->tj->createSimpleJournal($account, $beneficiary, $description, $amount, $date);
|
||||
} catch (\Firefly\Exception\FireflyException $e) {
|
||||
return Redirect::route('transactions.withdrawal')->withInput();
|
||||
}
|
||||
|
||||
// attach bud/cat (?)
|
||||
if (!is_null($budget)) {
|
||||
@ -75,4 +109,72 @@ class TransactionController extends BaseController
|
||||
return Redirect::route('index');
|
||||
}
|
||||
|
||||
public function postCreateDeposit()
|
||||
{
|
||||
// create or find beneficiary:
|
||||
$beneficiary = $this->accounts->createOrFindBeneficiary(Input::get('beneficiary'));
|
||||
|
||||
// fall back to cash account if empty:
|
||||
if (is_null($beneficiary)) {
|
||||
$beneficiary = $this->accounts->getCashAccount();
|
||||
}
|
||||
|
||||
// create or find category:
|
||||
$category = $this->categories->createOrFind(Input::get('category'));
|
||||
|
||||
// find account:
|
||||
$account = $this->accounts->find(intval(Input::get('account_id')));
|
||||
|
||||
// find amount & description:
|
||||
$description = trim(Input::get('description'));
|
||||
$amount = floatval(Input::get('amount'));
|
||||
$date = new \Carbon\Carbon(Input::get('date'));
|
||||
|
||||
// create journal
|
||||
/** @var \TransactionJournal $journal */
|
||||
try {
|
||||
$journal = $this->tj->createSimpleJournal($beneficiary, $account, $description, $amount, $date);
|
||||
} catch (\Firefly\Exception\FireflyException $e) {
|
||||
return Redirect::route('transactions.deposit')->withInput();
|
||||
}
|
||||
|
||||
if (!is_null($category)) {
|
||||
$journal->categories()->save($category);
|
||||
}
|
||||
|
||||
Session::flash('success', 'Transaction saved');
|
||||
return Redirect::route('index');
|
||||
}
|
||||
|
||||
public function postCreateTransfer()
|
||||
{
|
||||
// create or find category:
|
||||
$category = $this->categories->createOrFind(Input::get('category'));
|
||||
|
||||
// find account to:
|
||||
$to = $this->accounts->find(intval(Input::get('account_to_id')));
|
||||
|
||||
// find account from
|
||||
$from = $this->accounts->find(intval(Input::get('account_from_id')));
|
||||
|
||||
// find amount & description:
|
||||
$description = trim(Input::get('description'));
|
||||
$amount = floatval(Input::get('amount'));
|
||||
$date = new \Carbon\Carbon(Input::get('date'));
|
||||
|
||||
// create journal
|
||||
/** @var \TransactionJournal $journal */
|
||||
try {
|
||||
$journal = $this->tj->createSimpleJournal($from, $to, $description, $amount, $date);
|
||||
} catch (\Firefly\Exception\FireflyException $e) {
|
||||
return Redirect::route('transactions.transfer')->withInput();
|
||||
}
|
||||
if (!is_null($category)) {
|
||||
$journal->categories()->save($category);
|
||||
}
|
||||
|
||||
Session::flash('success', 'Transaction saved');
|
||||
return Redirect::route('index');
|
||||
}
|
||||
|
||||
}
|
@ -17,6 +17,8 @@ interface AccountRepositoryInterface
|
||||
|
||||
public function findByName($name);
|
||||
|
||||
public function getCashAccount();
|
||||
|
||||
public function getByIds($ids);
|
||||
|
||||
public function getDefault();
|
||||
|
@ -129,6 +129,9 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
|
||||
public function createOrFindBeneficiary($name)
|
||||
{
|
||||
if (is_null($name) || strlen($name) == 0) {
|
||||
return null;
|
||||
}
|
||||
$type = \AccountType::where('description', 'Beneficiary account')->first();
|
||||
return $this->createOrFind($name, $type);
|
||||
}
|
||||
@ -151,4 +154,12 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
return \Auth::user()->accounts()->where('name', 'like', '%' . $name . '%')->first();
|
||||
}
|
||||
|
||||
public function getCashAccount()
|
||||
{
|
||||
$type = \AccountType::where('description','Cash account')->first();
|
||||
$cash = \Auth::user()->accounts()->where('account_type_id',$type->id)->first();
|
||||
return $cash;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,8 @@
|
||||
namespace Firefly\Storage\TransactionJournal;
|
||||
|
||||
|
||||
use Firefly\Exception\FireflyException;
|
||||
|
||||
class EloquentTransactionJournalRepository implements TransactionJournalRepositoryInterface
|
||||
{
|
||||
|
||||
@ -36,6 +38,18 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
||||
$amountFrom = $amount * -1;
|
||||
$amountTo = $amount;
|
||||
|
||||
if(round(floatval($amount),2) == 0.00) {
|
||||
\Log::error('Transaction will never save: amount = 0');
|
||||
\Session::flash('error','The amount should not be empty or zero.');
|
||||
throw new \Firefly\Exception\FireflyException('Could not figure out transaction type.');
|
||||
}
|
||||
// same account:
|
||||
if($from->id == $to->id) {
|
||||
\Log::error('Accounts cannot be equal');
|
||||
\Session::flash('error','Select two different accounts.');
|
||||
throw new \Firefly\Exception\FireflyException('Select two different accounts.');
|
||||
}
|
||||
|
||||
// account types for both:
|
||||
$toAT = $to->accountType->description;
|
||||
$fromAT = $from->accountType->description;
|
||||
@ -94,6 +108,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
||||
if (!$journal->save()) {
|
||||
\Log::error('Cannot create valid journal.');
|
||||
\Log::error('Errors: ' . print_r($journal->errors()->all(), true));
|
||||
\Session::flash('error','Could not create journal: ' . $journal->errors()->first());
|
||||
throw new \Firefly\Exception\FireflyException('Cannot create valid journal.');
|
||||
}
|
||||
$journal->save();
|
||||
@ -158,6 +173,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
||||
}]
|
||||
)
|
||||
->after($start)->before($end)
|
||||
->where('completed',1)
|
||||
->whereIn('transaction_type_id', $types)
|
||||
->get(['transaction_journals.*']);
|
||||
unset($types);
|
||||
@ -166,6 +182,9 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
||||
|
||||
foreach ($journals as $journal) {
|
||||
// has to be one:
|
||||
if(!isset($journal->transactions[0])) {
|
||||
throw new FireflyException('Journal #'.$journal->id.' has ' . count($journal->transactions).' transactions!');
|
||||
}
|
||||
$transaction = $journal->transactions[0];
|
||||
$amount = floatval($transaction->amount);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
use \League\FactoryMuffin\Facade\FactoryMuffin;
|
||||
use League\FactoryMuffin\Facade\FactoryMuffin;
|
||||
|
||||
class TransactionControllerTest extends TestCase
|
||||
{
|
||||
@ -51,6 +51,63 @@ class TransactionControllerTest extends TestCase
|
||||
$this->assertResponseOk();
|
||||
}
|
||||
|
||||
public function testCreateDeposit()
|
||||
{
|
||||
|
||||
$set = [0 => '(no budget)'];
|
||||
View::shouldReceive('share');
|
||||
View::shouldReceive('make')->with('transactions.deposit')->andReturn(\Mockery::self())
|
||||
->shouldReceive('with')->once()
|
||||
->with('accounts', [])
|
||||
->andReturn(Mockery::self())
|
||||
->shouldReceive('with')->once()
|
||||
->with('budgets', $set)->andReturn(Mockery::self());
|
||||
|
||||
// mock account repository:
|
||||
$accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||
$accounts->shouldReceive('getActiveDefaultAsSelectList')->andReturn([]);
|
||||
|
||||
// mock budget repository:
|
||||
$budgets = $this->mock('Firefly\Storage\Budget\BudgetRepositoryInterface');
|
||||
$budgets->shouldReceive('getAsSelectList')->andReturn($set);
|
||||
|
||||
|
||||
// call
|
||||
$this->call('GET', '/transactions/add/deposit');
|
||||
|
||||
// test
|
||||
$this->assertResponseOk();
|
||||
}
|
||||
|
||||
public function testCreateTransfer()
|
||||
{
|
||||
|
||||
$set = [0 => '(no budget)'];
|
||||
View::shouldReceive('share');
|
||||
View::shouldReceive('make')->with('transactions.transfer')->andReturn(\Mockery::self())
|
||||
->shouldReceive('with')->once()
|
||||
->with('accounts', [])
|
||||
->andReturn(Mockery::self())
|
||||
->shouldReceive('with')->once()
|
||||
->with('budgets', $set)->andReturn(Mockery::self());
|
||||
|
||||
// mock account repository:
|
||||
$accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||
$accounts->shouldReceive('getActiveDefaultAsSelectList')->andReturn([]);
|
||||
|
||||
// mock budget repository:
|
||||
$budgets = $this->mock('Firefly\Storage\Budget\BudgetRepositoryInterface');
|
||||
$budgets->shouldReceive('getAsSelectList')->andReturn($set);
|
||||
|
||||
|
||||
// call
|
||||
$this->call('GET', '/transactions/add/transfer');
|
||||
|
||||
// test
|
||||
$this->assertResponseOk();
|
||||
}
|
||||
|
||||
|
||||
public function testPostCreateWithdrawal()
|
||||
{
|
||||
// create objects.
|
||||
@ -90,7 +147,130 @@ class TransactionControllerTest extends TestCase
|
||||
$tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
|
||||
$tj->shouldReceive('createSimpleJournal')->once()->andReturn($journal);
|
||||
|
||||
// $tj->shouldReceive('createSimpleJournal')->with($account, $beneficiary, $data['description'], $data['amount'], new \Carbon\Carbon($data['date']))->once()->andReturn($journal);
|
||||
// call
|
||||
$this->call('POST', '/transactions/add/withdrawal', $data);
|
||||
|
||||
// test
|
||||
$this->assertRedirectedToRoute('index');
|
||||
}
|
||||
|
||||
public function testPostCreateDeposit()
|
||||
{
|
||||
// create objects.
|
||||
$account = FactoryMuffin::create('Account');
|
||||
$beneficiary = FactoryMuffin::create('Account');
|
||||
$category = FactoryMuffin::create('Category');
|
||||
|
||||
|
||||
// data to send:
|
||||
$data = [
|
||||
'beneficiary' => $beneficiary->name,
|
||||
'category' => $category->name,
|
||||
'account_id' => $account->id,
|
||||
'description' => 'Bla',
|
||||
'amount' => 1.2,
|
||||
'date' => '2012-01-01'
|
||||
];
|
||||
$journal = FactoryMuffin::create('TransactionJournal');
|
||||
|
||||
// mock account repository:
|
||||
$accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||
$accounts->shouldReceive('createOrFindBeneficiary')->with($beneficiary->name)->andReturn($beneficiary);
|
||||
$accounts->shouldReceive('find')->andReturn($account);
|
||||
|
||||
// mock category repository
|
||||
$categories = $this->mock('Firefly\Storage\Category\CategoryRepositoryInterface');
|
||||
$categories->shouldReceive('createOrFind')->with($category->name)->andReturn($category);
|
||||
|
||||
// mock transaction journal:
|
||||
$tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
|
||||
$tj->shouldReceive('createSimpleJournal')->once()->andReturn($journal);
|
||||
|
||||
// call
|
||||
$this->call('POST', '/transactions/add/deposit', $data);
|
||||
|
||||
// test
|
||||
$this->assertRedirectedToRoute('index');
|
||||
}
|
||||
|
||||
public function testPostCreateTransfer()
|
||||
{
|
||||
// create objects.
|
||||
$from = FactoryMuffin::create('Account');
|
||||
$to = FactoryMuffin::create('Account');
|
||||
$category = FactoryMuffin::create('Category');
|
||||
|
||||
|
||||
// data to send:
|
||||
$data = [
|
||||
'category' => $category->name,
|
||||
'account_from_id' => $from->id,
|
||||
'account_to_id' => $to->id,
|
||||
'description' => 'Bla',
|
||||
'amount' => 1.2,
|
||||
'date' => '2012-01-01'
|
||||
];
|
||||
$journal = FactoryMuffin::create('TransactionJournal');
|
||||
|
||||
// mock account repository:
|
||||
$accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||
$accounts->shouldReceive('find')->with($from->id)->andReturn($from);
|
||||
$accounts->shouldReceive('find')->with($to->id)->andReturn($to);
|
||||
|
||||
// mock category repository
|
||||
$categories = $this->mock('Firefly\Storage\Category\CategoryRepositoryInterface');
|
||||
$categories->shouldReceive('createOrFind')->with($category->name)->andReturn($category);
|
||||
|
||||
// mock transaction journal:
|
||||
$tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
|
||||
$tj->shouldReceive('createSimpleJournal')->once()->andReturn($journal);
|
||||
|
||||
// call
|
||||
$this->call('POST', '/transactions/add/transfer', $data);
|
||||
|
||||
// test
|
||||
$this->assertRedirectedToRoute('index');
|
||||
}
|
||||
|
||||
public function testPostCreateWithdrawalEmptyBeneficiary()
|
||||
{
|
||||
// create objects.
|
||||
$account = FactoryMuffin::create('Account');
|
||||
$beneficiary = FactoryMuffin::create('Account');
|
||||
$category = FactoryMuffin::create('Category');
|
||||
$budget = FactoryMuffin::create('Budget');
|
||||
|
||||
|
||||
// data to send:
|
||||
$data = [
|
||||
'beneficiary' => '',
|
||||
'category' => $category->name,
|
||||
'budget_id' => $budget->id,
|
||||
'account_id' => $account->id,
|
||||
'description' => 'Bla',
|
||||
'amount' => 1.2,
|
||||
'date' => '2012-01-01'
|
||||
];
|
||||
$journal = FactoryMuffin::create('TransactionJournal');
|
||||
|
||||
// mock account repository:
|
||||
$accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||
$accounts->shouldReceive('createOrFindBeneficiary')->with('')->andReturn(null);
|
||||
$accounts->shouldReceive('getCashAccount')->andReturn($beneficiary);
|
||||
$accounts->shouldReceive('find')->andReturn($account);
|
||||
|
||||
// mock category repository
|
||||
$categories = $this->mock('Firefly\Storage\Category\CategoryRepositoryInterface');
|
||||
$categories->shouldReceive('createOrFind')->with($category->name)->andReturn($category);
|
||||
|
||||
// mock budget repository
|
||||
$budgets = $this->mock('Firefly\Storage\Budget\BudgetRepositoryInterface');
|
||||
$budgets->shouldReceive('createOrFind')->with($budget->name)->andReturn($budget);
|
||||
$budgets->shouldReceive('find')->andReturn($budget);
|
||||
|
||||
// mock transaction journal:
|
||||
$tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
|
||||
$tj->shouldReceive('createSimpleJournal')->once()->andReturn($journal);
|
||||
|
||||
// call
|
||||
$this->call('POST', '/transactions/add/withdrawal', $data);
|
||||
@ -98,6 +278,194 @@ class TransactionControllerTest extends TestCase
|
||||
// test
|
||||
$this->assertRedirectedToRoute('index');
|
||||
}
|
||||
|
||||
public function testPostCreateDepositEmptyBeneficiary()
|
||||
{
|
||||
// create objects.
|
||||
$account = FactoryMuffin::create('Account');
|
||||
$beneficiary = FactoryMuffin::create('Account');
|
||||
$category = FactoryMuffin::create('Category');
|
||||
$budget = FactoryMuffin::create('Budget');
|
||||
|
||||
|
||||
// data to send:
|
||||
$data = [
|
||||
'beneficiary' => '',
|
||||
'category' => $category->name,
|
||||
'budget_id' => $budget->id,
|
||||
'account_id' => $account->id,
|
||||
'description' => 'Bla',
|
||||
'amount' => 1.2,
|
||||
'date' => '2012-01-01'
|
||||
];
|
||||
$journal = FactoryMuffin::create('TransactionJournal');
|
||||
|
||||
// mock account repository:
|
||||
$accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||
$accounts->shouldReceive('createOrFindBeneficiary')->with('')->andReturn(null);
|
||||
$accounts->shouldReceive('getCashAccount')->andReturn($beneficiary);
|
||||
$accounts->shouldReceive('find')->andReturn($account);
|
||||
|
||||
// mock category repository
|
||||
$categories = $this->mock('Firefly\Storage\Category\CategoryRepositoryInterface');
|
||||
$categories->shouldReceive('createOrFind')->with($category->name)->andReturn($category);
|
||||
|
||||
// mock budget repository
|
||||
$budgets = $this->mock('Firefly\Storage\Budget\BudgetRepositoryInterface');
|
||||
$budgets->shouldReceive('createOrFind')->with($budget->name)->andReturn($budget);
|
||||
$budgets->shouldReceive('find')->andReturn($budget);
|
||||
|
||||
// mock transaction journal:
|
||||
$tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
|
||||
$tj->shouldReceive('createSimpleJournal')->once()->andReturn($journal);
|
||||
|
||||
// call
|
||||
$this->call('POST', '/transactions/add/deposit', $data);
|
||||
|
||||
// test
|
||||
$this->assertRedirectedToRoute('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Firefly\Exception\FireflyException;
|
||||
*/
|
||||
public function testPostCreateWithdrawalException()
|
||||
{
|
||||
// create objects.
|
||||
$account = FactoryMuffin::create('Account');
|
||||
$beneficiary = FactoryMuffin::create('Account');
|
||||
$category = FactoryMuffin::create('Category');
|
||||
$budget = FactoryMuffin::create('Budget');
|
||||
|
||||
|
||||
// data to send:
|
||||
$data = [
|
||||
'beneficiary' => '',
|
||||
'category' => $category->name,
|
||||
'budget_id' => $budget->id,
|
||||
'account_id' => $account->id,
|
||||
'description' => 'Bla',
|
||||
'amount' => 1.2,
|
||||
'date' => '2012-01-01'
|
||||
];
|
||||
$journal = FactoryMuffin::create('TransactionJournal');
|
||||
|
||||
// mock account repository:
|
||||
$accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||
$accounts->shouldReceive('createOrFindBeneficiary')->with('')->andReturn(null);
|
||||
$accounts->shouldReceive('getCashAccount')->andReturn($beneficiary);
|
||||
$accounts->shouldReceive('find')->andReturn($account);
|
||||
|
||||
// mock category repository
|
||||
$categories = $this->mock('Firefly\Storage\Category\CategoryRepositoryInterface');
|
||||
$categories->shouldReceive('createOrFind')->with($category->name)->andReturn($category);
|
||||
|
||||
// mock budget repository
|
||||
$budgets = $this->mock('Firefly\Storage\Budget\BudgetRepositoryInterface');
|
||||
$budgets->shouldReceive('createOrFind')->with($budget->name)->andReturn($budget);
|
||||
$budgets->shouldReceive('find')->andReturn($budget);
|
||||
|
||||
// mock transaction journal:
|
||||
$tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
|
||||
$tj->shouldReceive('createSimpleJournal')->andThrow('Firefly\Exception\FireflyException');
|
||||
|
||||
// call
|
||||
$this->call('POST', '/transactions/add/withdrawal', $data);
|
||||
|
||||
// test
|
||||
$this->assertRedirectedToRoute('transactions.withdrawal');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Firefly\Exception\FireflyException;
|
||||
*/
|
||||
public function testPostCreateDepositException()
|
||||
{
|
||||
// create objects.
|
||||
$account = FactoryMuffin::create('Account');
|
||||
$beneficiary = FactoryMuffin::create('Account');
|
||||
$category = FactoryMuffin::create('Category');
|
||||
$budget = FactoryMuffin::create('Budget');
|
||||
|
||||
|
||||
// data to send:
|
||||
$data = [
|
||||
'beneficiary' => '',
|
||||
'category' => $category->name,
|
||||
'budget_id' => $budget->id,
|
||||
'account_id' => $account->id,
|
||||
'description' => 'Bla',
|
||||
'amount' => 1.2,
|
||||
'date' => '2012-01-01'
|
||||
];
|
||||
$journal = FactoryMuffin::create('TransactionJournal');
|
||||
|
||||
// mock account repository:
|
||||
$accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||
$accounts->shouldReceive('createOrFindBeneficiary')->with('')->andReturn(null);
|
||||
$accounts->shouldReceive('getCashAccount')->andReturn($beneficiary);
|
||||
$accounts->shouldReceive('find')->andReturn($account);
|
||||
|
||||
// mock category repository
|
||||
$categories = $this->mock('Firefly\Storage\Category\CategoryRepositoryInterface');
|
||||
$categories->shouldReceive('createOrFind')->with($category->name)->andReturn($category);
|
||||
|
||||
// mock budget repository
|
||||
$budgets = $this->mock('Firefly\Storage\Budget\BudgetRepositoryInterface');
|
||||
$budgets->shouldReceive('createOrFind')->with($budget->name)->andReturn($budget);
|
||||
$budgets->shouldReceive('find')->andReturn($budget);
|
||||
|
||||
// mock transaction journal:
|
||||
$tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
|
||||
$tj->shouldReceive('createSimpleJournal')->andThrow('Firefly\Exception\FireflyException');
|
||||
|
||||
// call
|
||||
$this->call('POST', '/transactions/add/deposit', $data);
|
||||
|
||||
// test
|
||||
$this->assertRedirectedToRoute('transactions.deposit');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException Firefly\Exception\FireflyException;
|
||||
*/
|
||||
public function testPostCreateTransferException()
|
||||
{
|
||||
// create objects.
|
||||
$from = FactoryMuffin::create('Account');
|
||||
$category = FactoryMuffin::create('Category');
|
||||
|
||||
|
||||
// data to send:
|
||||
$data = [
|
||||
'category' => $category->name,
|
||||
'account_from_id' => $from->id,
|
||||
'account_to_id' => $from->id,
|
||||
'description' => 'Bla',
|
||||
'amount' => 1.2,
|
||||
'date' => '2012-01-01'
|
||||
];
|
||||
|
||||
// mock account repository:
|
||||
$accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||
$accounts->shouldReceive('find')->with($from->id)->andReturn($from);
|
||||
$accounts->shouldReceive('find')->with($from->id)->andReturn($from);
|
||||
|
||||
// mock category repository
|
||||
$categories = $this->mock('Firefly\Storage\Category\CategoryRepositoryInterface');
|
||||
$categories->shouldReceive('createOrFind')->with($category->name)->andReturn($category);
|
||||
|
||||
// mock transaction journal:
|
||||
$tj = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
|
||||
$tj->shouldReceive('createSimpleJournal')->andThrow('Firefly\Exception\FireflyException');
|
||||
|
||||
// call
|
||||
$this->call('POST', '/transactions/add/transfer', $data);
|
||||
|
||||
// test
|
||||
$this->assertRedirectedToRoute('transactions.transfer');
|
||||
}
|
||||
|
||||
public function tearDown()
|
||||
{
|
||||
Mockery::close();
|
||||
|
98
app/views/transactions/deposit.blade.php
Normal file
98
app/views/transactions/deposit.blade.php
Normal file
@ -0,0 +1,98 @@
|
||||
@extends('layouts.default')
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<h1>Firefly
|
||||
<small>Add a new deposit</small>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-12 col-sm-12">
|
||||
<p class="text-info">
|
||||
Technically speaking, withdrawals, deposits and transfers are all transactions, moving money from
|
||||
account <em>A</em> to account <em>B</em>.
|
||||
</p>
|
||||
<p class="text-info">
|
||||
A deposit is when you earn money, moving an amount from a beneficiary into your own account.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{Form::open(['class' => 'form-horizontal'])}}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-12 col-sm-12">
|
||||
<h4>Mandatory fields</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<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')}}}" autocomplete="off" class="form-control" placeholder="Description" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="beneficiary" class="col-sm-4 control-label">Beneficiary (payer)</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" name="beneficiary" value="{{{Input::old('beneficiary')}}}" autocomplete="off" class="form-control" placeholder="Beneficiary" />
|
||||
<span class="help-block">This field will auto-complete your existing beneficiaries (if any), but you can type freely to create new ones.</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="account_id" class="col-sm-4 control-label">Account</label>
|
||||
<div class="col-sm-8">
|
||||
{{Form::select('account_id',$accounts,Input::old('account_id'),['class' => 'form-control'])}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="amount" class="col-sm-4 control-label">Amount spent</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" name="amount" min="0.01" value="{{Input::old('amount') or 0}}" step="any" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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 deposit" class="btn btn-info" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-12 col-sm-12">
|
||||
<h4>Optional fields</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="category" class="col-sm-4 control-label">Category</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" name="category" value="" autocomplete="off" class="form-control" placeholder="Category" />
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@stop
|
||||
@section('scripts')
|
||||
|
||||
<script type="text/javascript" src="assets/javascript/withdrawal.js"></script>
|
||||
@stop
|
96
app/views/transactions/transfer.blade.php
Normal file
96
app/views/transactions/transfer.blade.php
Normal file
@ -0,0 +1,96 @@
|
||||
@extends('layouts.default')
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<h1>Firefly
|
||||
<small>Add a new transfer</small>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-12 col-sm-12">
|
||||
<p class="text-info">
|
||||
Technically speaking, withdrawals, deposits and transfers are all transactions, moving money from
|
||||
account <em>A</em> to account <em>B</em>.
|
||||
</p>
|
||||
<p class="text-info">
|
||||
A transfer moves money between your own accounts.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{Form::open(['class' => 'form-horizontal'])}}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-6 col-md-12 col-sm-12">
|
||||
<h4>Mandatory fields</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<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')}}}" autocomplete="off" class="form-control" placeholder="Description" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<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_to_id',$accounts,Input::old('account_from_id'),['class' => 'form-control'])}}
|
||||
</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_from_id',$accounts,Input::old('account_to_id'),['class' => 'form-control'])}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-group">
|
||||
<label for="amount" class="col-sm-4 control-label">Amount spent</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" name="amount" min="0.01" value="{{floatval(Input::old('amount'))}}" step="any" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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 transfer" class="btn btn-info" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-12 col-sm-12">
|
||||
<h4>Optional fields</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="category" class="col-sm-4 control-label">Category</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" name="category" value="" autocomplete="off" class="form-control" placeholder="Category" />
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@stop
|
||||
@section('scripts')
|
||||
|
||||
<script type="text/javascript" src="assets/javascript/withdrawal.js"></script>
|
||||
@stop
|
@ -52,7 +52,7 @@
|
||||
<div class="form-group">
|
||||
<label for="amount" class="col-sm-4 control-label">Amount spent</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" name="amount" min="0.01" step="any" class="form-control" />
|
||||
<input type="number" name="amount" min="0.01" value="{{Input::old('amount') or 0}}" step="any" class="form-control" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user