Update, edit and delete currencies.

This commit is contained in:
James Cole
2014-12-24 12:32:18 +01:00
parent fe1fb23e5b
commit cb670bb27d
9 changed files with 645 additions and 280 deletions

View File

@@ -1,5 +1,6 @@
<?php
use FireflyIII\Database\TransactionCurrency\TransactionCurrency as Repository;
/**
* Class CurrencyController
*/
@@ -9,18 +10,164 @@ class CurrencyController extends BaseController
/** @var Repository */
protected $_repository;
/**
* @param Repository $repository
*/
public function __construct(Repository $repository)
{
$this->_repository = $repository;
View::share('title', 'Currencies');
View::share('mainTitleIcon', 'fa-usd');
}
/**
* @return \Illuminate\View\View
*/
public function create()
{
$subTitleIcon = 'fa-plus';
$subTitle = 'Create a new currency';
return View::make('currency.create', compact('subTitleIcon', 'subTitle'));
}
/**
* @param TransactionCurrency $currency
*
* @return \Illuminate\Http\RedirectResponse
*/
public function defaultCurrency(TransactionCurrency $currency)
{
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
$currencyPreference = $preferences->get('currencyPreference', 'EUR');
$currencyPreference->data = $currency->code;
$currencyPreference->save();
Cache::forget('FFCURRENCYSYMBOL');
Cache::forget('FFCURRENCYCODE');
return Redirect::route('currency.index');
}
/**
* @param TransactionCurrency $currency
*/
public function delete(TransactionCurrency $currency)
{
if ($currency->transactionJournals()->count() > 0) {
Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.');
return Redirect::route('currency.index');
}
return View::make('currency.delete', compact('currency'));
}
public function destroy(TransactionCurrency $currency)
{
Session::flash('success', 'Currency "' . e($currency->name) . '" deleted');
$this->_repository->destroy($currency);
return Redirect::route('currency.index');
}
/**
* @param TransactionCurrency $currency
*
* @return \Illuminate\View\View
*/
public function edit(TransactionCurrency $currency)
{
$subTitleIcon = 'fa-pencil';
$subTitle = 'Edit currency "' . e($currency->name) . '"';
$currency->symbol = htmlentities($currency->symbol);
return View::make('currency.edit', compact('currency', 'subTitle', 'subTitleIcon'));
}
public function index()
{
$currencies = $this->_repository->get();
return View::make('currency.index',compact('currencies'));
/** @var \FireflyIII\Shared\Preferences\Preferences $preferences */
$preferences = App::make('FireflyIII\Shared\Preferences\Preferences');
$currencyPreference = $preferences->get('currencyPreference', 'EUR');
$defaultCurrency = $this->_repository->findByCode($currencyPreference->data);
return View::make('currency.index', compact('currencies', 'defaultCurrency'));
}
public function store()
{
$data = Input::except('_token');
// always validate:
$messages = $this->_repository->validate($data);
// flash messages:
Session::flash('warnings', $messages['warnings']);
Session::flash('successes', $messages['successes']);
Session::flash('errors', $messages['errors']);
if ($messages['errors']->count() > 0) {
Session::flash('error', 'Could not store currency: ' . $messages['errors']->first());
}
// return to create screen:
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
return Redirect::route('currency.create')->withInput();
}
// store:
$this->_repository->store($data);
Session::flash('success', 'Currency "' . e($data['name']) . '" stored.');
if ($data['post_submit_action'] == 'store') {
return Redirect::route('currency.index');
}
return Redirect::route('currency.create')->withInput();
}
public function update(TransactionCurrency $currency)
{
$data = Input::except('_token');
// always validate:
$messages = $this->_repository->validate($data);
// flash messages:
Session::flash('warnings', $messages['warnings']);
Session::flash('successes', $messages['successes']);
Session::flash('errors', $messages['errors']);
if ($messages['errors']->count() > 0) {
Session::flash('error', 'Could not update currency: ' . $messages['errors']->first());
}
// return to update screen:
if ($data['post_submit_action'] == 'validate_only' || $messages['errors']->count() > 0) {
return Redirect::route('currency.edit', $currency->id)->withInput();
}
// update
$this->_repository->update($currency, $data);
Session::flash('success', 'Currency "' . e($data['name']) . '" updated.');
// go back to list
if ($data['post_submit_action'] == 'update') {
return Redirect::route('currency.index');
}
return Redirect::route('currency.edit', $currency->id)->withInput(['post_submit_action' => 'return_to_edit']);
}
}

View File

@@ -1,26 +1,85 @@
<?php
namespace FireflyIII\Database\TransactionCurrency;
use FireflyIII\Database\CommonDatabaseCalls;
use Illuminate\Support\Collection;
use FireflyIII\Database\CUD;
use FireflyIII\Exception\NotImplementedException;
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Support\Collection;
use Illuminate\Support\MessageBag;
/**
* Class TransactionType
*
* @package FireflyIII\Database
*/
class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabaseCalls
class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabaseCalls, CUD
{
/**
* @param string $code
* @param Eloquent $model
*
* @return \TransactionCurrency|null
* @return bool
*/
public function findByCode($code)
public function destroy(Eloquent $model)
{
return \TransactionCurrency::whereCode($code)->first();
$model->delete();
}
/**
* @param array $data
*
* @return Eloquent
*/
public function store(array $data)
{
$currency = new \TransactionCurrency($data);
$currency->save();
return $currency;
}
/**
* @param Eloquent $model
* @param array $data
*
* @return bool
*/
public function update(Eloquent $model, array $data)
{
$model->symbol = $data['symbol'];
$model->code = $data['code'];
$model->name = $data['name'];
$model->save();
return true;
}
/**
* Validates an array. Returns an array containing MessageBags
* errors/warnings/successes.
*
* @param array $model
*
* @return array
*/
public function validate(array $model)
{
$warnings = new MessageBag;
$successes = new MessageBag;
$currency = new \TransactionCurrency($model);
$currency->isValid();
$errors = $currency->getErrors();
$fields = ['name', 'code', 'symbol'];
foreach ($fields as $field) {
if (!$errors->has($field)) {
$successes->add($field, 'OK');
}
}
return ['errors' => $errors, 'warnings' => $warnings, 'successes' => $successes];
}
/**
@@ -69,4 +128,14 @@ class TransactionCurrency implements TransactionCurrencyInterface, CommonDatabas
// TODO: Implement getByIds() method.
throw new NotImplementedException;
}
/**
* @param string $code
*
* @return \TransactionCurrency|null
*/
public function findByCode($code)
{
return \TransactionCurrency::whereCode($code)->first();
}
}

View File

@@ -2,6 +2,7 @@
use Illuminate\Database\Eloquent\Model as Eloquent;
use Illuminate\Database\Eloquent\SoftDeletingTrait;
use Watson\Validating\ValidatingTrait;
/**
* Class TransactionCurrency
*/
@@ -10,6 +11,23 @@ class TransactionCurrency extends Eloquent
use SoftDeletingTrait, ValidatingTrait;
protected $fillable = ['name', 'symbol', 'code'];
protected $rules
= [
'creating' => [
'code' => 'required|min:3|max:3|alpha|unique:transaction_currencies,code',
'name' => 'required|min:3|max:48|unique:transaction_currencies,name',
'symbol' => 'required|min:1|max:8|unique:transaction_currencies,symbol',
],
'updating' => [
'code' => 'required|min:3|max:3|alpha',
'name' => 'required|min:3|max:48',
'symbol' => 'required|min:1|max:8',
],
];
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/

View File

@@ -95,6 +95,12 @@ Route::bind(
}
);
Route::bind(
'currency', function ($value, $route) {
return TransactionCurrency::find($value);
}
);
Route::bind(
'limitrepetition', function ($value, $route) {
if (Auth::check()) {
@@ -174,6 +180,10 @@ Route::group(
// currency controller
Route::get('/currency', ['uses' => 'CurrencyController@index', 'as' => 'currency.index']);
Route::get('/currency/create', ['uses' => 'CurrencyController@create', 'as' => 'currency.create']);
Route::get('/currency/edit/{currency}', ['uses' => 'CurrencyController@edit', 'as' => 'currency.edit']);
Route::get('/currency/delete/{currency}', ['uses' => 'CurrencyController@delete', 'as' => 'currency.delete']);
Route::get('/currency/default/{currency}', ['uses' => 'CurrencyController@defaultCurrency', 'as' => 'currency.default']);
// google chart controller
Route::get('/chart/home/account', ['uses' => 'GoogleChartController@allAccountsBalanceChart']);
@@ -292,6 +302,11 @@ Route::group(
Route::post('/categories/update/{category}', ['uses' => 'CategoryController@update', 'as' => 'categories.update']);
Route::post('/categories/destroy/{category}', ['uses' => 'CategoryController@destroy', 'as' => 'categories.destroy']);
// currency controller
Route::post('/currency/store', ['uses' => 'CurrencyController@store', 'as' => 'currency.store']);
Route::post('/currency/update/{currency}', ['uses' => 'CurrencyController@update', 'as' => 'currency.update']);
Route::post('/currency/destroy/{currency}', ['uses' => 'CurrencyController@destroy', 'as' => 'currency.destroy']);
// piggy bank controller
Route::post('/piggybanks/store', ['uses' => 'PiggybankController@store', 'as' => 'piggybanks.store']);
Route::post('/piggybanks/update/{piggybank}', ['uses' => 'PiggybankController@update', 'as' => 'piggybanks.update']);

View File

@@ -0,0 +1,40 @@
@extends('layouts.default')
@section('content')
{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) }}
{{Form::open(['class' => 'form-horizontal','id' => 'store','route' => 'currency.store'])}}
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa {{{$subTitleIcon}}}"></i> Mandatory fields
</div>
<div class="panel-body">
{{Form::ffText('name',null,['maxlength' => 48])}}
{{Form::ffText('symbol',null,['maxlength' => 8])}}
{{Form::ffText('code',null,['maxlength' => 3])}}
</div>
</div>
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Store new currency
</button>
</p>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{Form::ffOptionsList('create','currency')}}
</div>
</div>
</div>
</div>
{{Form::close()}}
@stop

View File

@@ -0,0 +1,25 @@
@extends('layouts.default')
@section('content')
{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName(), $currency) }}
{{Form::open(['class' => 'form-horizontal','id' => 'destroy','url' => route('currency.destroy',$currency->id)])}}
<div class="row">
<div class="col-lg-6 col-md-12 col-sm-12">
<div class="panel panel-red">
<div class="panel-heading">
Delete currency "{{{$currency->name}}}"
</div>
<div class="panel-body">
<p>
Are you sure?
</p>
<p>
<button type="submit" class="btn btn-default btn-danger">Delete permanently</button>
<a href="{{URL::previous()}}" class="btn-default btn">Cancel</a >
</p>
</div>
</div>
</div>
</div>
{{Form::close()}}
@stop

View File

@@ -0,0 +1,40 @@
@extends('layouts.default')
@section('content')
{{ Breadcrumbs::renderIfExists(Route::getCurrentRoute()->getName()) }}
{{Form::model($currency, ['class' => 'form-horizontal','id' => 'store','url' => route('currency.update',$currency->id)])}}
<div class="row">
<div class="col-lg-6 col-md-6 col-sm-12">
<div class="panel panel-primary">
<div class="panel-heading">
<i class="fa {{{$subTitleIcon}}}"></i> Mandatory fields
</div>
<div class="panel-body">
{{Form::ffText('name',null,['maxlength' => 48])}}
{{Form::ffText('symbol',null,['maxlength' => 8])}}
{{Form::ffText('code',null,['maxlength' => 3])}}
</div>
</div>
<p>
<button type="submit" class="btn btn-lg btn-success">
<i class="fa fa-plus-circle"></i> Update currency
</button>
</p>
</div>
<div class="col-lg-6 col-md-6 col-sm-12">
<!-- panel for options -->
<div class="panel panel-default">
<div class="panel-heading">
<i class="fa fa-bolt"></i> Options
</div>
<div class="panel-body">
{{Form::ffOptionsList('update','currency')}}
</div>
</div>
</div>
</div>
{{Form::close()}}
@stop

View File

@@ -16,12 +16,19 @@
@if(count($currencies) > 0)
@foreach($currencies as $currency)
<li>
<a href="#"><i class="fa fa-fw fa-pencil"></i></a>
<a href="#"><i class="fa fa-fw fa-trash"></i></a>
{{{$currency->name}}} ({{{$currency->code}}}) ({{{$currency->symbol}}})</li>
<a href="{{route('currency.edit',$currency->id)}}"><i class="fa fa-fw fa-pencil"></i></a>
<a href="{{route('currency.delete',$currency->id)}}"><i class="fa fa-fw fa-trash"></i></a>
{{{$currency->name}}} ({{{$currency->code}}}) ({{{$currency->symbol}}})
@if($currency->id == $defaultCurrency->id)
<span class="label label-success">default</span>
@else
<span class="label label-default"><a style="color:#fff" href="{{route('currency.default',$currency->id)}}">make default</a></span>
@endif
</li>
@endforeach
@endif
<li><a href="#"><i class="fa fa-fw fa-plus-circle"></i> Add another currency</a></li>
<li><a href="{{route('currency.create')}}"><i class="fa fa-fw fa-plus-circle"></i> Add another currency</a></li>
</ul>
</div>
</div>

96
composer.lock generated
View File

@@ -324,16 +324,16 @@
},
{
"name": "laravel/framework",
"version": "v4.2.12",
"version": "v4.2.16",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "70a60f2ff9b96b3fcd88a68ef5382557733fe671"
"reference": "31fe6a5747bbe3c2df21dc4cc8f291e75ab6144f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/70a60f2ff9b96b3fcd88a68ef5382557733fe671",
"reference": "70a60f2ff9b96b3fcd88a68ef5382557733fe671",
"url": "https://api.github.com/repos/laravel/framework/zipball/31fe6a5747bbe3c2df21dc4cc8f291e75ab6144f",
"reference": "31fe6a5747bbe3c2df21dc4cc8f291e75ab6144f",
"shasum": ""
},
"require": {
@@ -435,7 +435,7 @@
"framework",
"laravel"
],
"time": "2014-12-11 17:14:36"
"time": "2014-12-22 20:56:10"
},
{
"name": "michelf/php-markdown",
@@ -1984,16 +1984,16 @@
},
{
"name": "codeception/codeception",
"version": "2.0.8",
"version": "2.0.9",
"source": {
"type": "git",
"url": "https://github.com/Codeception/Codeception.git",
"reference": "0f9de6de9788912a289214a020193eac0a9a05e8"
"reference": "0094191ac0d6e87821fba41de002103ebe79a279"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/0f9de6de9788912a289214a020193eac0a9a05e8",
"reference": "0f9de6de9788912a289214a020193eac0a9a05e8",
"url": "https://api.github.com/repos/Codeception/Codeception/zipball/0094191ac0d6e87821fba41de002103ebe79a279",
"reference": "0094191ac0d6e87821fba41de002103ebe79a279",
"shasum": ""
},
"require": {
@@ -2015,6 +2015,7 @@
"codeception/specify": "~0.3",
"codegyre/robo-ci": "@dev",
"facebook/php-sdk": "~3.2",
"flow/jsonpath": "~0.1",
"monolog/monolog": "~1.8",
"pda/pheanstalk": "~2.0",
"phpseclib/phpseclib": "~0.3.6",
@@ -2061,7 +2062,7 @@
"functional testing",
"unit testing"
],
"time": "2014-11-18 00:48:50"
"time": "2014-12-19 23:54:20"
},
{
"name": "codeception/phpbuiltinserver",
@@ -2105,16 +2106,16 @@
},
{
"name": "doctrine/annotations",
"version": "v1.2.1",
"version": "v1.2.3",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
"reference": "6a6bec0670bb6e71a263b08bc1b98ea242928633"
"reference": "eeda578cbe24a170331a1cfdf78be723412df7a4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/6a6bec0670bb6e71a263b08bc1b98ea242928633",
"reference": "6a6bec0670bb6e71a263b08bc1b98ea242928633",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/eeda578cbe24a170331a1cfdf78be723412df7a4",
"reference": "eeda578cbe24a170331a1cfdf78be723412df7a4",
"shasum": ""
},
"require": {
@@ -2169,7 +2170,7 @@
"docblock",
"parser"
],
"time": "2014-09-25 16:45:30"
"time": "2014-12-20 20:49:38"
},
{
"name": "doctrine/cache",
@@ -2459,22 +2460,30 @@
},
{
"name": "doctrine/inflector",
"version": "v1.0",
"version": "v1.0.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "54b8333d2a5682afdc690060c1cf384ba9f47f08"
"reference": "0bcb2e79d8571787f18b7eb036ed3d004908e604"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/54b8333d2a5682afdc690060c1cf384ba9f47f08",
"reference": "54b8333d2a5682afdc690060c1cf384ba9f47f08",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/0bcb2e79d8571787f18b7eb036ed3d004908e604",
"reference": "0bcb2e79d8571787f18b7eb036ed3d004908e604",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "4.*"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-0": {
"Doctrine\\Common\\Inflector\\": "lib/"
@@ -2485,17 +2494,6 @@
"MIT"
],
"authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
@@ -2504,22 +2502,28 @@
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com",
"homepage": "https://github.com/schmittjoh",
"role": "Developer of wrapped JMSSerializerBundle"
"email": "schmittjoh@gmail.com"
}
],
"description": "Common String Manipulations with regard to casing and singular/plural rules.",
"homepage": "http://www.doctrine-project.org",
"keywords": [
"inflection",
"pluarlize",
"singuarlize",
"pluralize",
"singularize",
"string"
],
"time": "2013-01-10 21:49:15"
"time": "2014-12-20 21:24:13"
},
{
"name": "doctrine/instantiator",
@@ -2810,16 +2814,16 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "5.0.3",
"version": "5.1.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "6c72627de1d66832e4270e36e56acdb0d1d8f282"
"reference": "f1085bb4e023766a66b7b051914ec73bdf7202b5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/6c72627de1d66832e4270e36e56acdb0d1d8f282",
"reference": "6c72627de1d66832e4270e36e56acdb0d1d8f282",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/f1085bb4e023766a66b7b051914ec73bdf7202b5",
"reference": "f1085bb4e023766a66b7b051914ec73bdf7202b5",
"shasum": ""
},
"require": {
@@ -2864,7 +2868,7 @@
"rest",
"web service"
],
"time": "2014-11-04 07:09:15"
"time": "2014-12-19 20:27:15"
},
{
"name": "guzzlehttp/ringphp",
@@ -3085,16 +3089,16 @@
},
{
"name": "mockery/mockery",
"version": "0.9.2",
"version": "0.9.3",
"source": {
"type": "git",
"url": "https://github.com/padraic/mockery.git",
"reference": "95a4855380dc70176c51807c678fb3bd6198529a"
"reference": "686f85fa5b3b079cc0157d7cd3e9adb97f0b41e1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/padraic/mockery/zipball/95a4855380dc70176c51807c678fb3bd6198529a",
"reference": "95a4855380dc70176c51807c678fb3bd6198529a",
"url": "https://api.github.com/repos/padraic/mockery/zipball/686f85fa5b3b079cc0157d7cd3e9adb97f0b41e1",
"reference": "686f85fa5b3b079cc0157d7cd3e9adb97f0b41e1",
"shasum": ""
},
"require": {
@@ -3147,7 +3151,7 @@
"test double",
"testing"
],
"time": "2014-09-03 10:11:10"
"time": "2014-12-22 10:06:19"
},
{
"name": "phpdocumentor/reflection-docblock",