First attempt at storing an account.

This commit is contained in:
James Cole 2015-02-09 07:23:39 +01:00
parent 169d1065cc
commit 3841259779
12 changed files with 258 additions and 111 deletions

View File

@ -1,10 +1,13 @@
<?php namespace FireflyIII\Http\Controllers; <?php namespace FireflyIII\Http\Controllers;
use Auth; use Auth;
use Carbon\Carbon;
use Config; use Config;
use FireflyIII\Http\Requests; use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\AccountFormRequest; use FireflyIII\Http\Requests\AccountFormRequest;
use Illuminate\Http\Request; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Redirect;
use Session;
use View; use View;
/** /**
@ -46,8 +49,24 @@ class AccountController extends Controller
return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts')); return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts'));
} }
public function store(AccountFormRequest $request) public function store(AccountFormRequest $request, AccountRepositoryInterface $repository)
{ {
$accountData = [
'name' => $request->input('name'),
'accountType' => Config::get('firefly.accountTypeByIdentifier.' . $request->input('what')),
'active' => true,
'user' => Auth::user()->id,
'accountRole' => $request->input('accountRole'),
'openingBalance' => floatval($request->input('openingBalance')),
'openingBalanceDate' => new Carbon($request->input('openingBalanceDate')),
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
];
$account = $repository->store($accountData);
Session::flash('success', 'New account "' . $account->name . '" stored!');
return Redirect::route('accounts.index', $request->input('what'));
} }

View File

@ -3,6 +3,7 @@
namespace FireflyIII\Http\Requests; namespace FireflyIII\Http\Requests;
use Auth; use Auth;
use Config;
/** /**
* Class AccountFormRequest * Class AccountFormRequest
@ -19,9 +20,17 @@ class AccountFormRequest extends Request
public function rules() public function rules()
{ {
$accountRoles = join(',', array_keys(Config::get('firefly.accountRoles')));
$types = join(',', array_keys(Config::get('firefly.subTitlesByIdentifier')));
return [ return [
'name' => 'required|between:1,100|uniqueForUser:accounts,name', 'name' => 'required|between:1,100|uniqueForUser:accounts,name',
'openingBalance' => 'required|numeric' 'openingBalance' => 'numeric',
'openingBalanceDate' => 'date',
'accountRole' => 'in:' . $accountRoles,
'active' => 'boolean',
'balance_currency_id' => 'required|exists:transaction_currencies,id',
'what' => 'in:' . $types
]; ];
} }
} }

View File

@ -3,6 +3,7 @@
use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
/** /**
* Class Account * Class Account
@ -11,7 +12,17 @@ use Illuminate\Database\Eloquent\SoftDeletes;
*/ */
class Account extends Model class Account extends Model
{ {
use SoftDeletes; use SoftDeletes, ValidatingTrait;
protected $rules
= [
'user_id' => 'required|exists:users,id',
'account_type_id' => 'required|exists:account_types,id',
'name' => 'required|between:1,100|uniqueForUser:accounts,name',
'active' => 'required|boolean'
];
protected $fillable = ['user_id','account_type_id','name','active'];
public function accountMeta() public function accountMeta()
{ {

View File

@ -47,6 +47,10 @@ class FireflyServiceProvider extends ServiceProvider
return new \FireflyIII\Support\ExpandedForm; return new \FireflyIII\Support\ExpandedForm;
} }
); );
// preferences
$this->app->bind('FireflyIII\Repositories\Account\AccountRepositoryInterface', 'FireflyIII\Repositories\Account\AccountRepository');
$this->app->bind('FireflyIII\Repositories\Journal\JournalRepositoryInterface', 'FireflyIII\Repositories\Journal\JournalRepository');
} }
} }

View File

@ -0,0 +1,63 @@
<?php
namespace FireflyIII\Repositories\Account;
use App;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
/**
* Class AccountRepository
*
* @package FireflyIII\Repositories\Account
*/
class AccountRepository implements AccountRepositoryInterface
{
/**
* @param array $data
*
* @return Account;
*/
public function store(array $data)
{
$newAccount = $this->_store($data);
// continue with the opposing account:
if ($data['openingBalance'] != 0) {
$type = $data['openingBalance'] < 0 ? 'expense' : 'revenue';
$opposing = [
'user' => $data['user'],
'accountType' => $type,
'name' => $data['name'] . ' initial balance',
'active' => false,
];
$this->_store($opposing);
}
return $newAccount;
}
/**
* @param array $data
*/
protected function _store(array $data)
{
$accountType = AccountType::whereType($data['accountType'])->first();
$newAccount = new Account(
[
'user_id' => $data['user'],
'account_type_id' => $accountType->id,
'name' => $data['name'],
'active' => $data['active'] === true ? true : false,
]
);
if (!$newAccount->isValid()) {
App::abort(500);
}
$newAccount->save();
}
}

View File

@ -0,0 +1,9 @@
<?php
namespace FireflyIII\Repositories\Account;
interface AccountRepositoryInterface
{
public function store(array $data);
}

View File

@ -0,0 +1,8 @@
<?php
namespace FireflyIII\Repositories\Journal;
class JournalRepository implements JournalRepositoryInterface {
}

View File

@ -0,0 +1,14 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 08/02/15
* Time: 18:15
*/
namespace FireflyIII\Repositories\Journal;
interface JournalRepositoryInterface {
}

View File

@ -70,4 +70,10 @@ return [
'expense' => ['Expense account', 'Beneficiary account'], 'expense' => ['Expense account', 'Beneficiary account'],
'revenue' => ['Revenue account'], 'revenue' => ['Revenue account'],
], ],
'accountTypeByIdentifier' =>
[
'asset' => 'Asset account',
'expense' => 'Expense account',
'revenue' => 'Revenue account',
],
]; ];

View File

@ -2,106 +2,107 @@
return [ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Validation Language Lines | Validation Language Lines
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The following language lines contain the default error messages used by | The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such | the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here. | as the size rules. Feel free to tweak each of these messages here.
| |
*/ */
"accepted" => "The :attribute must be accepted.", "accepted" => "The :attribute must be accepted.",
"active_url" => "The :attribute is not a valid URL.", "active_url" => "The :attribute is not a valid URL.",
"after" => "The :attribute must be a date after :date.", "after" => "The :attribute must be a date after :date.",
"alpha" => "The :attribute may only contain letters.", "alpha" => "The :attribute may only contain letters.",
"alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.", "alpha_dash" => "The :attribute may only contain letters, numbers, and dashes.",
"alpha_num" => "The :attribute may only contain letters and numbers.", "alpha_num" => "The :attribute may only contain letters and numbers.",
"array" => "The :attribute must be an array.", "array" => "The :attribute must be an array.",
"before" => "The :attribute must be a date before :date.", "unique_for_user" => "There already is an entry with this :attribute.",
"between" => [ "before" => "The :attribute must be a date before :date.",
"numeric" => "The :attribute must be between :min and :max.", "between" => [
"file" => "The :attribute must be between :min and :max kilobytes.", "numeric" => "The :attribute must be between :min and :max.",
"string" => "The :attribute must be between :min and :max characters.", "file" => "The :attribute must be between :min and :max kilobytes.",
"array" => "The :attribute must have between :min and :max items.", "string" => "The :attribute must be between :min and :max characters.",
], "array" => "The :attribute must have between :min and :max items.",
"boolean" => "The :attribute field must be true or false.", ],
"confirmed" => "The :attribute confirmation does not match.", "boolean" => "The :attribute field must be true or false.",
"date" => "The :attribute is not a valid date.", "confirmed" => "The :attribute confirmation does not match.",
"date_format" => "The :attribute does not match the format :format.", "date" => "The :attribute is not a valid date.",
"different" => "The :attribute and :other must be different.", "date_format" => "The :attribute does not match the format :format.",
"digits" => "The :attribute must be :digits digits.", "different" => "The :attribute and :other must be different.",
"digits_between" => "The :attribute must be between :min and :max digits.", "digits" => "The :attribute must be :digits digits.",
"email" => "The :attribute must be a valid email address.", "digits_between" => "The :attribute must be between :min and :max digits.",
"filled" => "The :attribute field is required.", "email" => "The :attribute must be a valid email address.",
"exists" => "The selected :attribute is invalid.", "filled" => "The :attribute field is required.",
"image" => "The :attribute must be an image.", "exists" => "The selected :attribute is invalid.",
"in" => "The selected :attribute is invalid.", "image" => "The :attribute must be an image.",
"integer" => "The :attribute must be an integer.", "in" => "The selected :attribute is invalid.",
"ip" => "The :attribute must be a valid IP address.", "integer" => "The :attribute must be an integer.",
"max" => [ "ip" => "The :attribute must be a valid IP address.",
"numeric" => "The :attribute may not be greater than :max.", "max" => [
"file" => "The :attribute may not be greater than :max kilobytes.", "numeric" => "The :attribute may not be greater than :max.",
"string" => "The :attribute may not be greater than :max characters.", "file" => "The :attribute may not be greater than :max kilobytes.",
"array" => "The :attribute may not have more than :max items.", "string" => "The :attribute may not be greater than :max characters.",
], "array" => "The :attribute may not have more than :max items.",
"mimes" => "The :attribute must be a file of type: :values.", ],
"min" => [ "mimes" => "The :attribute must be a file of type: :values.",
"numeric" => "The :attribute must be at least :min.", "min" => [
"file" => "The :attribute must be at least :min kilobytes.", "numeric" => "The :attribute must be at least :min.",
"string" => "The :attribute must be at least :min characters.", "file" => "The :attribute must be at least :min kilobytes.",
"array" => "The :attribute must have at least :min items.", "string" => "The :attribute must be at least :min characters.",
], "array" => "The :attribute must have at least :min items.",
"not_in" => "The selected :attribute is invalid.", ],
"numeric" => "The :attribute must be a number.", "not_in" => "The selected :attribute is invalid.",
"regex" => "The :attribute format is invalid.", "numeric" => "The :attribute must be a number.",
"required" => "The :attribute field is required.", "regex" => "The :attribute format is invalid.",
"required_if" => "The :attribute field is required when :other is :value.", "required" => "The :attribute field is required.",
"required_with" => "The :attribute field is required when :values is present.", "required_if" => "The :attribute field is required when :other is :value.",
"required_with_all" => "The :attribute field is required when :values is present.", "required_with" => "The :attribute field is required when :values is present.",
"required_without" => "The :attribute field is required when :values is not present.", "required_with_all" => "The :attribute field is required when :values is present.",
"required_without_all" => "The :attribute field is required when none of :values are present.", "required_without" => "The :attribute field is required when :values is not present.",
"same" => "The :attribute and :other must match.", "required_without_all" => "The :attribute field is required when none of :values are present.",
"size" => [ "same" => "The :attribute and :other must match.",
"numeric" => "The :attribute must be :size.", "size" => [
"file" => "The :attribute must be :size kilobytes.", "numeric" => "The :attribute must be :size.",
"string" => "The :attribute must be :size characters.", "file" => "The :attribute must be :size kilobytes.",
"array" => "The :attribute must contain :size items.", "string" => "The :attribute must be :size characters.",
], "array" => "The :attribute must contain :size items.",
"unique" => "The :attribute has already been taken.", ],
"url" => "The :attribute format is invalid.", "unique" => "The :attribute has already been taken.",
"timezone" => "The :attribute must be a valid zone.", "url" => "The :attribute format is invalid.",
"timezone" => "The :attribute must be a valid zone.",
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Custom Validation Language Lines | Custom Validation Language Lines
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| Here you may specify custom validation messages for attributes using the | Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to | convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule. | specify a specific custom language line for a given attribute rule.
| |
*/ */
'custom' => [ 'custom' => [
'attribute-name' => [ 'attribute-name' => [
'rule-name' => 'custom-message', 'rule-name' => 'custom-message',
], ],
], ],
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Custom Validation Attributes | Custom Validation Attributes
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| The following language lines are used to swap attribute place-holders | The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead | with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner. | of "email". This simply helps us make messages a little cleaner.
| |
*/ */
'attributes' => [], 'attributes' => [],
]; ];

View File

@ -27,21 +27,20 @@
<div class="col-lg-6 col-md-6 col-sm-12"> <div class="col-lg-6 col-md-6 col-sm-12">
@if($what == 'asset')
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
<i class="fa fa-smile-o"></i> Optional fields <i class="fa fa-smile-o"></i> Optional fields
</div> </div>
<div class="panel-body"> <div class="panel-body">
@if($what == 'asset')
{!! ExpandedForm::balance('openingBalance') !!} {!! ExpandedForm::balance('openingBalance') !!}
{!! ExpandedForm::date('openingBalanceDate', date('Y-m-d')) !!} {!! ExpandedForm::date('openingBalanceDate', date('Y-m-d')) !!}
{!! ExpandedForm::select('account_role',Config::get('firefly.accountRoles')) !!} {!! ExpandedForm::select('accountRole',Config::get('firefly.accountRoles')) !!}
@endif
{!! ExpandedForm::checkbox('active','1',true) !!}
</div> </div>
</div> </div>
@endif
<!-- panel for options --> <!-- panel for options -->
<div class="panel panel-default"> <div class="panel panel-default">

View File

@ -1,4 +1,5 @@
@if($type == 'create') @if($type == 'create')
<!--
<div class="form-group"> <div class="form-group">
<label for="{{{$name}}}_store" class="col-sm-4 control-label">Store</label> <label for="{{{$name}}}_store" class="col-sm-4 control-label">Store</label>
<div class="col-sm-8"> <div class="col-sm-8">
@ -10,8 +11,10 @@
</div> </div>
</div> </div>
</div> </div>
-->
@endif @endif
@if($type == 'update') @if($type == 'update')
<!--
<div class="form-group"> <div class="form-group">
<label for="{{{$name}}}_update" class="col-sm-4 control-label">Update</label> <label for="{{{$name}}}_update" class="col-sm-4 control-label">Update</label>
<div class="col-sm-8"> <div class="col-sm-8">
@ -23,8 +26,9 @@
</div> </div>
</div> </div>
</div> </div>
-->
@endif @endif
<!--
<div class="form-group"> <div class="form-group">
<label for="{{{$name}}}_validate_only" class="col-sm-4 control-label">Validate only</label> <label for="{{{$name}}}_validate_only" class="col-sm-4 control-label">Validate only</label>
<div class="col-sm-8"> <div class="col-sm-8">
@ -36,7 +40,7 @@
</div> </div>
</div> </div>
</div> </div>
-->
@if($type == 'create') @if($type == 'create')
<div class="form-group"> <div class="form-group">
<label for="{{{$name}}}_return_to_form" class="col-sm-4 control-label"> <label for="{{{$name}}}_return_to_form" class="col-sm-4 control-label">
@ -45,7 +49,7 @@
<div class="col-sm-8"> <div class="col-sm-8">
<div class="radio"> <div class="radio">
<label> <label>
{!! Form::radio('post_submit_action', 'create_another', $previousValue == 'create_another', ['id' => $name . '_create_another']) !!} {!! Form::checkbox('create_another', '1') !!}
After storing, return here to create another one. After storing, return here to create another one.
</label> </label>
</div> </div>
@ -60,7 +64,7 @@
</label> </label>
<div class="col-sm-8"> <div class="col-sm-8">
<div class="radio"><label> <div class="radio"><label>
{!! Form::radio('post_submit_action', 'return_to_edit', $previousValue == 'return_to_edit', ['id' => $name . '_return_to_edit']) !!} {!! Form::checkbox('return_to_edit', '1') !!}
After updating, return here. After updating, return here.
</label> </label>
</div> </div>