mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2024-12-27 17:31:09 -06:00
Made big headway in preference management, accounts, importing stuff, etc. etc.
This commit is contained in:
parent
188105492c
commit
4192f2bc8f
@ -36,6 +36,7 @@ return [
|
||||
'Illuminate\Validation\ValidationServiceProvider',
|
||||
'Illuminate\View\ViewServiceProvider',
|
||||
'Illuminate\Workbench\WorkbenchServiceProvider',
|
||||
'Grumpydictator\Gchart\GchartServiceProvider',
|
||||
'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
|
||||
'Barryvdh\Debugbar\ServiceProvider',
|
||||
'Firefly\Storage\StorageServiceProvider',
|
||||
|
@ -1,23 +1,50 @@
|
||||
<?php
|
||||
|
||||
//use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
|
||||
use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
|
||||
|
||||
class AccountController extends \BaseController
|
||||
{
|
||||
|
||||
// public function __construct(ARI $accounts) {
|
||||
// $this->accounts = $accounts;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Display a listing of the resource.
|
||||
// *
|
||||
// * @return Response
|
||||
// */
|
||||
// public function index()
|
||||
// {
|
||||
//
|
||||
// }
|
||||
public function __construct(ARI $accounts) {
|
||||
$this->accounts = $accounts;
|
||||
|
||||
View::share('menu', 'accounts');
|
||||
}
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$all = $this->accounts->get();
|
||||
$list = [
|
||||
'personal' => [],
|
||||
'beneficiaries' => [],
|
||||
'initial' => [],
|
||||
'cash' => []
|
||||
];
|
||||
|
||||
foreach($all as $account) {
|
||||
switch($account->accounttype->description) {
|
||||
case 'Default account':
|
||||
$list['personal'][] = $account;
|
||||
break;
|
||||
case 'Cash account':
|
||||
$list['cash'][] = $account;
|
||||
break;
|
||||
case 'Initial balance account':
|
||||
$list['initial'][] = $account;
|
||||
break;
|
||||
case 'Beneficiary account':
|
||||
$list['beneficiaries'][] = $account;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return View::make('accounts.index')->with('accounts',$list);
|
||||
}
|
||||
//
|
||||
//
|
||||
/**
|
||||
@ -46,16 +73,16 @@ class AccountController extends \BaseController
|
||||
// }
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Display the specified resource.
|
||||
// *
|
||||
// * @param int $id
|
||||
// * @return Response
|
||||
// */
|
||||
// public function show($id)
|
||||
// {
|
||||
// //
|
||||
// }
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Account $account
|
||||
* @return Response
|
||||
*/
|
||||
public function show(Account $account)
|
||||
{
|
||||
|
||||
}
|
||||
//
|
||||
//
|
||||
// /**
|
||||
|
61
app/controllers/ChartController.php
Normal file
61
app/controllers/ChartController.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
use Carbon\Carbon as Carbon;
|
||||
use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
|
||||
|
||||
class ChartController extends BaseController
|
||||
{
|
||||
|
||||
public function __construct(ARI $accounts)
|
||||
{
|
||||
$this->accounts = $accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show home charts.
|
||||
*/
|
||||
public function home(Account $account = null)
|
||||
{
|
||||
// chart
|
||||
$chart = App::make('gchart');
|
||||
$chart->addColumn('Day of the month', 'date');
|
||||
|
||||
// date
|
||||
$today = new Carbon;
|
||||
$past = clone $today;
|
||||
$past->subMonth();
|
||||
$current = clone $past;
|
||||
|
||||
if (is_null($account)) {
|
||||
// get accounts:
|
||||
$accounts = $this->accounts->getActiveDefault();
|
||||
|
||||
foreach ($accounts as $account) {
|
||||
$chart->addColumn($account->name, 'number');
|
||||
}
|
||||
|
||||
while ($current <= $today) {
|
||||
$row = [clone $current];
|
||||
|
||||
// loop accounts:
|
||||
foreach ($accounts as $account) {
|
||||
$row[] = $account->balance(clone $current);
|
||||
}
|
||||
$current->addDay();
|
||||
$chart->addRowArray($row);
|
||||
}
|
||||
} else {
|
||||
$chart->addColumn($account->name, 'number');
|
||||
while ($current <= $today) {
|
||||
$row = [clone $current,$account->balance(clone $current)];
|
||||
$current->addDay();
|
||||
$chart->addRowArray($row);
|
||||
}
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
return $chart->getData();
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,19 +1,35 @@
|
||||
<?php
|
||||
use Carbon\Carbon as Carbon;
|
||||
use Firefly\Helper\Preferences\PreferencesHelperInterface as PHI;
|
||||
use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
|
||||
|
||||
class HomeController extends BaseController {
|
||||
|
||||
public function __construct(ARI $accounts) {
|
||||
class HomeController extends BaseController
|
||||
{
|
||||
protected $accounts;
|
||||
protected $preferences;
|
||||
|
||||
public function __construct(ARI $accounts, PHI $preferences)
|
||||
{
|
||||
$this->accounts = $accounts;
|
||||
$this->preferences = $preferences;
|
||||
View::share('menu', 'home');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
// get list setting:
|
||||
$pref = $this->preferences->get('frontpageAccounts', []);
|
||||
|
||||
// get the accounts to display on the home screen:
|
||||
$count = $this->accounts->count();
|
||||
if ($pref->data == []) {
|
||||
$list = $this->accounts->getActiveDefault();
|
||||
} else {
|
||||
$list = $this->accounts->getByIds($pref->data);
|
||||
}
|
||||
|
||||
|
||||
// build the home screen:
|
||||
|
||||
return View::make('index')->with('count',$count);
|
||||
}
|
||||
return View::make('index')->with('count', $count)->with('accounts', $list);
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ class MigrationController extends BaseController
|
||||
public function __construct(MHI $migration)
|
||||
{
|
||||
$this->migration = $migration;
|
||||
View::share('menu', 'home');
|
||||
|
||||
}
|
||||
|
||||
|
39
app/controllers/PreferencesController.php
Normal file
39
app/controllers/PreferencesController.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
use Firefly\Helper\Preferences\PreferencesHelperInterface as PHI;
|
||||
use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
|
||||
|
||||
class PreferencesController extends BaseController
|
||||
{
|
||||
protected $accounts;
|
||||
protected $preferences;
|
||||
|
||||
public function __construct(ARI $accounts, PHI $preferences)
|
||||
{
|
||||
|
||||
$this->accounts = $accounts;
|
||||
$this->preferences = $preferences;
|
||||
View::share('menu', 'home');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$accounts = $this->accounts->getDefault();
|
||||
|
||||
// pref:
|
||||
$frontpage = $this->preferences->get('frontpageAccounts', []);
|
||||
return View::make('preferences.index')->with('accounts', $accounts)->with('frontpageAccounts', $frontpage);
|
||||
}
|
||||
|
||||
public function postIndex()
|
||||
{
|
||||
$frontpageAccounts = [];
|
||||
foreach(Input::get('frontpageAccounts') as $id) {
|
||||
$frontpageAccounts[] = intval($id);
|
||||
}
|
||||
$this->preferences->set('frontpageAccounts',$frontpageAccounts);
|
||||
Session::flash('success', 'Preferences saved!');
|
||||
return Redirect::route('preferences');
|
||||
}
|
||||
|
||||
}
|
@ -7,6 +7,7 @@ class ProfileController extends BaseController
|
||||
|
||||
public function __construct(URI $user) {
|
||||
$this->user = $user;
|
||||
View::share('menu', 'home');
|
||||
}
|
||||
|
||||
public function index()
|
||||
|
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
|
||||
class CreatePreferencesTable extends Migration
|
||||
{
|
||||
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create(
|
||||
'preferences', function (Blueprint $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
$table->integer('user_id')->unsigned();
|
||||
$table->string('name');
|
||||
$table->text('data');
|
||||
|
||||
// connect preferences to users
|
||||
$table->foreign('user_id')
|
||||
->references('id')->on('users')
|
||||
->onDelete('cascade');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::drop('preferences');
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +1,5 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 03/07/14
|
||||
* Time: 21:06
|
||||
*/
|
||||
class DefaultUserSeeder extends Seeder
|
||||
{
|
||||
public function run()
|
||||
|
@ -1,10 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 04/07/14
|
||||
* Time: 13:58
|
||||
*/
|
||||
|
||||
namespace Firefly\Exception;
|
||||
|
||||
|
@ -1,10 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 04/07/14
|
||||
* Time: 13:55
|
||||
*/
|
||||
|
||||
namespace Firefly\Helper;
|
||||
|
||||
|
@ -21,6 +21,12 @@ class HelperServiceProvider extends ServiceProvider
|
||||
'Firefly\Helper\Migration\MigrationHelperInterface',
|
||||
'Firefly\Helper\Migration\MigrationHelper'
|
||||
);
|
||||
|
||||
// settings:
|
||||
$this->app->bind(
|
||||
'Firefly\Helper\Preferences\PreferencesHelperInterface',
|
||||
'Firefly\Helper\Preferences\PreferencesHelper'
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 03/07/14
|
||||
* Time: 21:34
|
||||
*/
|
||||
|
||||
namespace Firefly\Helper\Migration;
|
||||
|
||||
|
@ -1,10 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 03/07/14
|
||||
* Time: 21:33
|
||||
*/
|
||||
|
||||
namespace Firefly\Helper\Migration;
|
||||
|
||||
|
39
app/lib/Firefly/Helper/Preferences/PreferencesHelper.php
Normal file
39
app/lib/Firefly/Helper/Preferences/PreferencesHelper.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
namespace Firefly\Helper\Preferences;
|
||||
class PreferencesHelper implements PreferencesHelperInterface
|
||||
{
|
||||
|
||||
public function get($name, $default = null)
|
||||
{
|
||||
$pref = \Preference::where('user_id', \Auth::user()->id)->where('name', $name)->first();
|
||||
if (is_null($default) && is_null($pref)) {
|
||||
// return NULL
|
||||
return null;
|
||||
}
|
||||
if (!is_null($pref)) {
|
||||
return $pref;
|
||||
}
|
||||
if (!is_null($default) && is_null($pref)) {
|
||||
// create preference, return that:
|
||||
return $this->set($name, $default);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function set($name, $value)
|
||||
{
|
||||
$pref = \Preference::where('user_id', \Auth::user()->id)->where('name', $name)->first();
|
||||
if (is_null($pref)) {
|
||||
$pref = new \Preference;
|
||||
$pref->name = $name;
|
||||
$pref->user()->associate(\Auth::user());
|
||||
|
||||
}
|
||||
$pref->data = $value;
|
||||
$pref->save();
|
||||
|
||||
|
||||
return $pref;
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace Firefly\Helper\Preferences;
|
||||
interface PreferencesHelperInterface
|
||||
{
|
||||
|
||||
public function set($name,$value);
|
||||
public function get($name,$default = null);
|
||||
|
||||
}
|
@ -10,6 +10,9 @@ interface AccountRepositoryInterface
|
||||
public function count();
|
||||
|
||||
public function get();
|
||||
public function getByIds($ids);
|
||||
public function getDefault();
|
||||
public function getActiveDefault();
|
||||
|
||||
public function store($data);
|
||||
public function storeWithInitialBalance($data,\Carbon\Carbon $date, $amount = 0);
|
||||
|
@ -3,8 +3,6 @@
|
||||
|
||||
namespace Firefly\Storage\Account;
|
||||
|
||||
use Firefly\Helper\MigrationException;
|
||||
|
||||
class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
{
|
||||
public $validator;
|
||||
@ -13,8 +11,30 @@ class EloquentAccountRepository implements AccountRepositoryInterface
|
||||
{
|
||||
}
|
||||
|
||||
public function get() {
|
||||
return \Auth::user()->accounts()->get();
|
||||
public function get()
|
||||
{
|
||||
return \Auth::user()->accounts()->with('accounttype')->get();
|
||||
}
|
||||
|
||||
public function getByIds($ids)
|
||||
{
|
||||
return \Auth::user()->accounts()->with('accounttype')->whereIn('id', $ids)->get();
|
||||
}
|
||||
|
||||
public function getDefault()
|
||||
{
|
||||
return \Auth::user()->accounts()->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->where('account_types.description', 'Default account')
|
||||
|
||||
->get(['accounts.*']);
|
||||
}
|
||||
|
||||
public function getActiveDefault()
|
||||
{
|
||||
return \Auth::user()->accounts()->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->where('account_types.description', 'Default account')->where('accounts.active', 1)
|
||||
|
||||
->get(['accounts.*']);
|
||||
}
|
||||
|
||||
public function count()
|
||||
|
@ -1,10 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 03/07/14
|
||||
* Time: 15:24
|
||||
*/
|
||||
|
||||
|
||||
namespace Firefly\Storage\TransactionJournal;
|
||||
|
||||
@ -15,7 +10,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
||||
public function createSimpleJournal(\Account $from, \Account $to, $description, $amount, \Carbon\Carbon $date)
|
||||
{
|
||||
|
||||
\Log::debug('Creating tranaction "'.$description.'".');
|
||||
\Log::debug('Creating tranaction "' . $description . '".');
|
||||
/*
|
||||
* We're building this thinking the money goes from A to B.
|
||||
* If the amount is negative however, the money still goes
|
||||
@ -69,7 +64,10 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
|
||||
}
|
||||
|
||||
// some debug information:
|
||||
\Log::debug($journalType->type.': AccountFrom "'.$from->name.'" will gain/lose '.$amountFrom.' and AccountTo "'.$to->name.'" will gain/lose '.$amountTo);
|
||||
\Log::debug(
|
||||
$journalType->type . ': AccountFrom "' . $from->name . '" will gain/lose ' . $amountFrom
|
||||
. ' and AccountTo "' . $to->name . '" will gain/lose ' . $amountTo
|
||||
);
|
||||
|
||||
if (is_null($journalType)) {
|
||||
\Log::error('Could not figure out transacion type!');
|
||||
|
@ -1,15 +1,10 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 03/07/14
|
||||
* Time: 15:22
|
||||
*/
|
||||
|
||||
namespace Firefly\Storage\TransactionJournal;
|
||||
|
||||
|
||||
interface TransactionJournalRepositoryInterface {
|
||||
interface TransactionJournalRepositoryInterface
|
||||
{
|
||||
|
||||
public function createSimpleJournal(\Account $from, \Account $to, $description, $amount, \Carbon\Carbon $date);
|
||||
|
||||
|
@ -6,7 +6,7 @@ class Account extends Elegant
|
||||
|
||||
public static $rules
|
||||
= [
|
||||
'name' => 'required|between:1,100',
|
||||
'name' => 'required|between:1,100',
|
||||
'user_id' => 'required|exists:users,id'
|
||||
];
|
||||
|
||||
@ -15,17 +15,11 @@ class Account extends Elegant
|
||||
return $this->belongsTo('AccountType');
|
||||
}
|
||||
|
||||
public function transactions()
|
||||
{
|
||||
return $this->hasMany('Transaction');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('User');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get an accounts current balance.
|
||||
*
|
||||
@ -36,7 +30,15 @@ class Account extends Elegant
|
||||
public function balance(\Carbon\Carbon $date = null)
|
||||
{
|
||||
$date = is_null($date) ? new \Carbon\Carbon : $date;
|
||||
return floatval($this->transactions()->sum('amount'));
|
||||
|
||||
return $this->transactions()
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount');
|
||||
}
|
||||
|
||||
public function transactions()
|
||||
{
|
||||
return $this->hasMany('Transaction');
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 05/07/14
|
||||
* Time: 18:24
|
||||
*/
|
||||
|
||||
class Budget extends Component {
|
||||
protected $isSubclass = true;
|
||||
|
@ -4,21 +4,21 @@
|
||||
class Component extends Firefly\Database\SingleTableInheritanceEntity
|
||||
{
|
||||
|
||||
protected $table = 'components';
|
||||
protected $subclassField = 'class';
|
||||
|
||||
public static $rules
|
||||
= [
|
||||
'user_id' => 'exists:users,id|required',
|
||||
'name' => 'required|between:1,255',
|
||||
'class' => 'required',
|
||||
'component_type_id' => 'required|exists:component_types,id'
|
||||
];
|
||||
|
||||
protected $table = 'components';
|
||||
protected $subclassField = 'class';
|
||||
|
||||
public function transactions()
|
||||
{
|
||||
return $this->belongsToMany('Transaction');
|
||||
}
|
||||
|
||||
public function transactionjournals()
|
||||
{
|
||||
return $this->belongsToMany('TransactionJournal');
|
||||
|
27
app/models/Preference.php
Normal file
27
app/models/Preference.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
class Preference extends Elegant
|
||||
{
|
||||
public static $rules
|
||||
= [
|
||||
'user_id' => 'required|exists:user,id',
|
||||
'name' => 'required|between:1,255',
|
||||
'data' => 'required'
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('User');
|
||||
}
|
||||
|
||||
public function setDataAttribute($value)
|
||||
{
|
||||
$this->attributes['data'] = json_encode($value);
|
||||
}
|
||||
|
||||
public function getDataAttribute($value)
|
||||
{
|
||||
return json_decode($value);
|
||||
}
|
||||
|
||||
}
|
@ -36,4 +36,9 @@ class User extends Elegant implements UserInterface, RemindableInterface
|
||||
return $this->hasMany('Account');
|
||||
}
|
||||
|
||||
public function preferences()
|
||||
{
|
||||
return $this->hasMany('Preference');
|
||||
}
|
||||
|
||||
}
|
@ -1,4 +1,13 @@
|
||||
<?php
|
||||
Route::bind('account', function ($value, $route) {
|
||||
if(Auth::user()) {
|
||||
return Auth::user()->accounts()->find($value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// protected routes:
|
||||
Route::group(['before' => 'auth'], function () {
|
||||
@ -6,6 +15,12 @@ Route::group(['before' => 'auth'], function () {
|
||||
// home controller
|
||||
Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index']);
|
||||
|
||||
// chart controller
|
||||
Route::get('/chart/home/{account?}', ['uses' => 'ChartController@home', 'as' => 'chart.home']);
|
||||
|
||||
// preferences controller
|
||||
Route::get('/preferences', ['uses' => 'PreferencesController@index', 'as' => 'preferences']);
|
||||
|
||||
// user controller
|
||||
Route::get('/logout', ['uses' => 'UserController@logout', 'as' => 'logout']);
|
||||
|
||||
@ -13,11 +28,14 @@ Route::group(['before' => 'auth'], function () {
|
||||
Route::get('/profile', ['uses' => 'ProfileController@index', 'as' => 'profile']);
|
||||
Route::get('/profile/change-password',['uses' => 'ProfileController@changePassword', 'as' => 'change-password']);
|
||||
|
||||
// account controller:
|
||||
Route::get('/accounts', ['uses' => 'AccountController@index', 'as' => 'accounts.index']);
|
||||
Route::get('/accounts/create', ['uses' => 'AccountController@create', 'as' => 'accounts.create']);
|
||||
Route::get('/accounts/{account}', ['uses' => 'AccountController@show', 'as' => 'accounts.show']);
|
||||
|
||||
// migration controller
|
||||
Route::get('/migrate', ['uses' => 'MigrationController@index', 'as' => 'migrate']);
|
||||
|
||||
// account controller:
|
||||
Route::get('/accounts/create', ['uses' => 'AccountController@create', 'as' => 'accounts.create']);
|
||||
}
|
||||
);
|
||||
|
||||
@ -29,6 +47,9 @@ Route::group(['before' => 'csrf|auth'], function () {
|
||||
// migration controller
|
||||
Route::post('/migrate', ['uses' => 'MigrationController@postIndex']);
|
||||
|
||||
// preferences controller
|
||||
Route::post('/preferences', ['uses' => 'PreferencesController@postIndex']);
|
||||
|
||||
// account controller:
|
||||
Route::get('/accounts/store', ['uses' => 'AccountController@store', 'as' => 'accounts.store']);
|
||||
|
||||
|
1
app/storage/firefly-export-2014-07-03.json
Normal file
1
app/storage/firefly-export-2014-07-03.json
Normal file
File diff suppressed because one or more lines are too long
@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
class ExampleTest extends TestCase {
|
||||
|
||||
/**
|
||||
* A basic functional test example.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testBasicExample()
|
||||
{
|
||||
$crawler = $this->client->request('GET', '/login');
|
||||
|
||||
$this->assertTrue($this->client->getResponse()->isOk());
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
<?php
|
||||
class AccountControllerTest extends TestCase {
|
||||
|
||||
class AccountControllerTest extends TestCase
|
||||
{
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
@ -8,6 +10,7 @@ class AccountControllerTest extends TestCase {
|
||||
public function testCreate()
|
||||
{
|
||||
// mock:
|
||||
View::shouldReceive('share');
|
||||
View::shouldReceive('make')->with('accounts.create');
|
||||
|
||||
// call
|
||||
@ -16,4 +19,11 @@ class AccountControllerTest extends TestCase {
|
||||
// test
|
||||
$this->assertResponseOk();
|
||||
}
|
||||
|
||||
public function testShow()
|
||||
{
|
||||
|
||||
// the route filters on accounts using Eloquent, maybe fix that instead?
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
@ -10,13 +10,25 @@ class HomeControllerTest extends TestCase
|
||||
public function testIndex()
|
||||
{
|
||||
// mock:
|
||||
View::shouldReceive('share');
|
||||
View::shouldReceive('make')->with('index')->once()->andReturn(\Mockery::self())
|
||||
->shouldReceive('with')->once() // Pass a 'with' parameter
|
||||
->with('count', 0)
|
||||
;
|
||||
->andReturn(Mockery::self())
|
||||
->shouldReceive('with')->once() // another 'with' parameter.
|
||||
->with('accounts',[])
|
||||
->andReturn(Mockery::self())
|
||||
;
|
||||
Auth::shouldReceive('check')->andReturn(true);
|
||||
|
||||
// mock account repository
|
||||
$accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
|
||||
$accounts->shouldReceive('count')->andReturn(0);
|
||||
$accounts->shouldReceive('getActiveDefault')->andReturn([]);
|
||||
|
||||
// mock preferences helper:
|
||||
$preferences = $this->mock('Firefly\Helper\Preferences\PreferencesHelperInterface');
|
||||
$preferences->shouldReceive('get')->with('frontpageAccounts',[])->andReturn(new \Preference)->once();
|
||||
|
||||
// call
|
||||
$this->call('GET', '/');
|
||||
|
@ -10,6 +10,7 @@ class MigrationControllerTest extends TestCase
|
||||
public function testIndex()
|
||||
{
|
||||
// mock:
|
||||
View::shouldReceive('share');
|
||||
View::shouldReceive('make')->with('migrate.index');
|
||||
|
||||
// call
|
||||
|
@ -6,6 +6,7 @@ class ProfileControllerTest extends TestCase
|
||||
public function testIndex()
|
||||
{
|
||||
// mock:
|
||||
View::shouldReceive('share');
|
||||
View::shouldReceive('make')->with('profile.index');
|
||||
|
||||
// call
|
||||
@ -18,6 +19,7 @@ class ProfileControllerTest extends TestCase
|
||||
public function testChangePassword()
|
||||
{
|
||||
// mock:
|
||||
View::shouldReceive('share');
|
||||
View::shouldReceive('make')->with('profile.change-password');
|
||||
|
||||
// call
|
||||
|
30
app/tests/models/TransactionJournalTest.php
Normal file
30
app/tests/models/TransactionJournalTest.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
class TransactionJournalTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Default preparation for each test
|
||||
*/
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->prepareForTests();
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate the database
|
||||
*/
|
||||
private function prepareForTests()
|
||||
{
|
||||
Artisan::call('migrate');
|
||||
}
|
||||
|
||||
/**
|
||||
* Test accounts
|
||||
*/
|
||||
public function testJournal()
|
||||
{
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
}
|
@ -68,11 +68,8 @@ class UserTest extends TestCase
|
||||
|
||||
$account->save();
|
||||
|
||||
|
||||
|
||||
$this->assertCount(1,$user->accounts()->get());
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
53
app/views/accounts/index.blade.php
Normal file
53
app/views/accounts/index.blade.php
Normal file
@ -0,0 +1,53 @@
|
||||
@extends('layouts.default')
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<h1>Firefly
|
||||
<small>Accounts</small>
|
||||
</h1>
|
||||
<h2>Index</h2>
|
||||
<p style="width:50%;" class="text-info">
|
||||
In a double-entry bookkeeping system almost <em>everything</em> is an account. Your own personal
|
||||
bank accounts are representated as accounts (naturally), but the stores you buy stuff at are also
|
||||
represented as accounts. Likewise, if you have a job, your salary is drawn from their account.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<h3>Your accounts</h3>
|
||||
<p style="width:50%;" class="text-info">
|
||||
These are your personal accounts.
|
||||
</p>
|
||||
|
||||
@include('accounts.list',['accounts' => $accounts['personal']])
|
||||
|
||||
<h3>Beneficiaries</h3>
|
||||
<p style="width:50%;" class="text-info">
|
||||
These are beneficiaries; places where you spend money or people who pay you.
|
||||
</p>
|
||||
|
||||
@include('accounts.list',['accounts' => $accounts['beneficiaries']])
|
||||
|
||||
<h3>Initial balances</h3>
|
||||
<p style="width:50%;" class="text-info">
|
||||
These are system accounts; created to add balance to the books when you add a personal account
|
||||
which already has money in it. That money has to come from somewhere.
|
||||
</p>
|
||||
@include('accounts.list',['accounts' => $accounts['initial']])
|
||||
|
||||
<h3>Cash</h3>
|
||||
<p style="width:50%;" class="text-info">
|
||||
This is a system account. When you don't specify a beneficiary or draw many from an ATM (or put cash in your
|
||||
personal accounts) it gets added or drawn from this account.
|
||||
</p>
|
||||
@include('accounts.list',['accounts' => $accounts['cash']])
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@stop
|
||||
@section('scripts')
|
||||
<script src="https://www.google.com/jsapi"></script>
|
||||
<!-- <script src="assets/javascript/charts.js"></script>-->
|
||||
<!-- <script src="assets/javascript/index.js"></script>-->
|
||||
@stop
|
19
app/views/accounts/list.blade.php
Normal file
19
app/views/accounts/list.blade.php
Normal file
@ -0,0 +1,19 @@
|
||||
<table class="table table-bordered table-striped">
|
||||
<tr>
|
||||
<th style="width:25px;"> </th>
|
||||
<th style="width:30%;">Name</th>
|
||||
<th>Current balance</th>
|
||||
</tr>
|
||||
@foreach($accounts as $account)
|
||||
<tr>
|
||||
<td>
|
||||
@if($account->active == 0)
|
||||
<span title="This account is inactive." class="glyphicon glyphicon-ban-circle"></span>
|
||||
@endif
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{route('accounts.show',$account->id)}}" title="Overview for account {{{$account->name}}}">{{{$account->name}}}</a></td>
|
||||
<td>{{mf($account->balance())}}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</table>
|
@ -4,7 +4,6 @@
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<h1>Firefly
|
||||
@if($count > 0)
|
||||
<br/>
|
||||
<small>What's playing?</small>
|
||||
@endif
|
||||
</h1>
|
||||
@ -33,10 +32,27 @@
|
||||
</p>
|
||||
</div>
|
||||
@else
|
||||
<div class="row" style="border-top:1px #eee solid;">
|
||||
@foreach($accounts as $index => $account)
|
||||
<div class="col-lg-6">
|
||||
<div id="chart_{{{$account->id}}}" data-id="{{{$account->id}}}" class="homeChart" data-title="{{{$account->name}}}"></div>
|
||||
<p>
|
||||
Go to <a href="#" title="Overview for {{{$account->name}}}">{{{$account->name}}}</a>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
@if($index % 2 == 1)
|
||||
</div><div class="row" style="border-top:1px #eee solid;">
|
||||
@endif
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
|
||||
@endif
|
||||
|
||||
@stop
|
||||
@section('scripts')
|
||||
<script src="https://www.google.com/jsapi"></script>
|
||||
<script src="assets/javascript/charts.js"></script>
|
||||
<script src="assets/javascript/index.js"></script>
|
||||
@stop
|
@ -19,7 +19,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
@include('partials.menu')
|
||||
@include('partials.menu.'.$menu)
|
||||
@include('partials.flashes')
|
||||
@yield('content')
|
||||
</div>
|
||||
|
27
app/views/partials/menu/accounts.blade.php
Normal file
27
app/views/partials/menu/accounts.blade.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
$r = Route::current()->getName();
|
||||
?>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="{{route('index')}}">Firefly III</a>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li @if($r=='index')class="active"@endif><a href="{{route('index')}}">Home</a></li>
|
||||
<li @if($r=='accounts.index')class="active"@endif><a href="{{route('accounts.index')}}">Accounts</a></li>
|
||||
<li @if($r=='accounts.create')class="active"@endif><a href="{{route('accounts.create')}}"><span class="glyphicon glyphicon-plus"></span> Create</a></li>
|
||||
</ul>
|
||||
@include('partials.menu.shared')
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
@ -1,3 +1,6 @@
|
||||
<?php
|
||||
$r = Route::current()->getName();
|
||||
?>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
@ -14,12 +17,11 @@
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Link</a></li>
|
||||
<li><a href="#">Link</a></li>
|
||||
<li @if($r=='index')class="active"@endif><a href="{{route('index')}}">Home</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <span class="caret"></span></a>
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Go to...<span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="{{route('accounts.index')}}">Accounts</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li class="divider"></li>
|
||||
@ -29,23 +31,7 @@
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<form class="navbar-form navbar-left" role="search">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" placeholder="Search">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-default">Submit</button>
|
||||
</form>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="#">Link</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{{{Auth::user()->email}}} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="{{route('profile')}}"><span class="glyphicon glyphicon-user"></span> Profile</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="{{route('logout')}}"><span class="glyphicon glyphicon-arrow-right"></span> Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@include('partials.menu.shared')
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
</nav>
|
11
app/views/partials/menu/shared.blade.php
Normal file
11
app/views/partials/menu/shared.blade.php
Normal file
@ -0,0 +1,11 @@
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li @if($r=='settings')class="active"@endif><a href="{{route('preferences')}}"><span class="glyphicon glyphicon-cog"></span> Preferences</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{{{Auth::user()->email}}} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="{{route('profile')}}"><span class="glyphicon glyphicon-user"></span> Profile</a></li>
|
||||
<li class="divider"></li>
|
||||
<li><a href="{{route('logout')}}"><span class="glyphicon glyphicon-arrow-right"></span> Logout</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
45
app/views/preferences/index.blade.php
Normal file
45
app/views/preferences/index.blade.php
Normal file
@ -0,0 +1,45 @@
|
||||
@extends('layouts.default')
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<h1>Firefly
|
||||
<small>Preferences</small>
|
||||
</h1>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- home screen accounts -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
||||
<h3>Home screen accounts</h3>
|
||||
<p class="text-info">Which accounts should be displayed on the home page?</p>
|
||||
<!-- form -->
|
||||
{{Form::open(['class' => 'form-horizontal'])}}
|
||||
@foreach($accounts as $account)
|
||||
<div class="form-group">
|
||||
<div class="col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
@if(in_array($account->id,$frontpageAccounts->data) || count($frontpageAccounts->data) == 0)
|
||||
<input type="checkbox" name="frontpageAccounts[]" value="{{$account->id}}" checked> {{{$account->name}}}
|
||||
@else
|
||||
<input type="checkbox" name="frontpageAccounts[]" value="{{$account->id}}"> {{{$account->name}}}
|
||||
@endif
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-default">Save accounts</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@stop
|
||||
@section('scripts')
|
||||
@stop
|
@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
if (!function_exists('mf')) {
|
||||
function mf($n, $coloured = false)
|
||||
function mf($n, $coloured = true)
|
||||
{
|
||||
|
||||
$n = floatval($n);
|
||||
|
10
public/assets/javascript/Chart.min.js
vendored
10
public/assets/javascript/Chart.min.js
vendored
File diff suppressed because one or more lines are too long
21
public/assets/javascript/charts.js
Normal file
21
public/assets/javascript/charts.js
Normal file
@ -0,0 +1,21 @@
|
||||
function drawChart(id,URL,opt) {
|
||||
$.getJSON(URL).success(function (data) {
|
||||
$(id).removeClass('loading');
|
||||
|
||||
// actually draw chart.
|
||||
var gdata = new google.visualization.DataTable(data);
|
||||
var money = new google.visualization.NumberFormat({decimalSymbol: ',', groupingSymbol: '.', prefix: '€ '});
|
||||
money.format(gdata, 1);
|
||||
var gID = id.substring(1);
|
||||
var chart = new google.visualization.LineChart(document.getElementById(gID));
|
||||
|
||||
chart.draw(gdata, opt);
|
||||
|
||||
|
||||
}).fail(function() {
|
||||
console.log('Could not load chart for URL ' + URL);
|
||||
$(id).addClass('load-error');
|
||||
|
||||
});
|
||||
}
|
||||
|
@ -1,34 +1,38 @@
|
||||
// Get context with jQuery - using jQuery's .get() method.
|
||||
var ctx = $("#myChart").get(0).getContext("2d");
|
||||
// This will get the first returned node in the jQuery collection.
|
||||
google.load('visualization', '1.0', {'packages': ['corechart']});
|
||||
google.setOnLoadCallback(chartCallback);
|
||||
|
||||
// grab data from JSON point somewhere?
|
||||
function chartCallback() {
|
||||
drawAccountChart();
|
||||
}
|
||||
|
||||
function drawAccountChart() {
|
||||
|
||||
var data = {
|
||||
labels: ["January", "February", "March", "April", "May", "June", "July"],
|
||||
datasets: [
|
||||
{
|
||||
label: "My First dataset",
|
||||
fillColor: "rgba(220,220,220,0.2)",
|
||||
strokeColor: "rgba(220,220,220,1)",
|
||||
pointColor: "rgba(220,220,220,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(220,220,220,1)",
|
||||
data: [65, 59, 80, 81, 56, 55, 40]
|
||||
var opt = {
|
||||
curveType: 'function',
|
||||
legend: {
|
||||
position: 'none'
|
||||
},
|
||||
{
|
||||
label: "My Second dataset",
|
||||
fillColor: "rgba(151,187,205,0.2)",
|
||||
strokeColor: "rgba(151,187,205,1)",
|
||||
pointColor: "rgba(151,187,205,1)",
|
||||
pointStrokeColor: "#fff",
|
||||
pointHighlightFill: "#fff",
|
||||
pointHighlightStroke: "rgba(151,187,205,1)",
|
||||
data: [28, 48, 40, 19, 86, 27, 90]
|
||||
}
|
||||
]
|
||||
};
|
||||
options = [];
|
||||
var myLineChart = new Chart(ctx).Line(data, options);
|
||||
chartArea: {
|
||||
left: 50,
|
||||
top: 10,
|
||||
width: '90%',
|
||||
height: 180
|
||||
},
|
||||
height: 230
|
||||
};
|
||||
|
||||
$.each($('.homeChart'), function (i, v) {
|
||||
var obj = $(v);
|
||||
var accountID = obj.data('id').toString();
|
||||
var holderID = $(v).attr('id').toString();
|
||||
console.log('AccountID: ' + accountID + ', ' + 'holderID ' + holderID);
|
||||
var URL = 'chart/home/' + accountID;
|
||||
console.log('URL: ' + URL);
|
||||
|
||||
// draw it!
|
||||
drawChart('#' + holderID,URL, opt);
|
||||
});
|
||||
|
||||
//var URL = 'chart/home';
|
||||
//drawChart('#chart',URL,opt);
|
||||
}
|
Loading…
Reference in New Issue
Block a user