Compare commits

...

38 Commits
3.0.0 ... 3.0.2

Author SHA1 Message Date
James Cole
b8e07ac38e Removed another word wrap. 2014-09-09 10:46:35 +02:00
James Cole
c7273e4b60 Removed a chart wrap. 2014-09-09 10:45:51 +02:00
James Cole
33d4fd4af0 Small fix for the budget overview. 2014-09-09 10:43:12 +02:00
James Cole
71b11e26d2 Cleaned up the chart controller. 2014-09-09 10:42:58 +02:00
James Cole
77f4111b09 Fixed some bugs in the recurring transactions trigger 2014-09-09 07:10:37 +02:00
James Cole
9965297f36 Cleaning up the chart controller. 2014-09-09 07:10:16 +02:00
James Cole
5ca466a826 Update view. 2014-09-08 10:38:39 +02:00
James Cole
90f417facc Update model. 2014-09-08 10:38:26 +02:00
James Cole
eacbd038b7 Updated migration to include recurring transactions. 2014-09-08 10:38:14 +02:00
James Cole
5446e85424 New trigger for new journals. 2014-09-08 10:37:55 +02:00
James Cole
77b4942691 Uniform query. 2014-09-08 10:37:31 +02:00
James Cole
824cf71e0b Some re-alignment and catches for NULLs 2014-09-08 10:37:14 +02:00
James Cole
239bbd30c0 Fire some events. 2014-09-08 10:36:32 +02:00
James Cole
6f6b653d54 Removed some logging. 2014-09-08 10:36:19 +02:00
James Cole
e4155ce735 Moved a migration because of reasons. 2014-09-08 10:36:06 +02:00
James Cole
7eaf307834 Some code cleanup. 2014-09-04 09:02:54 +02:00
James Cole
7db7950415 Updated read-me. 2014-09-04 08:32:37 +02:00
James Cole
fcc184cd2a Removed ALL tests. Yes, I know. 2014-09-04 08:32:13 +02:00
James Cole
6423feff3a Cleaned up some models and controllers. 2014-09-04 08:31:45 +02:00
James Cole
e97da25d5a Cleaned up build files. 2014-09-04 08:31:07 +02:00
James Cole
f49a37a38e Removed unused classes. 2014-09-04 08:30:17 +02:00
James Cole
07e6b33095 Some tests fixed. But messy! [skip ci] 2014-09-03 21:12:51 +02:00
James Cole
9136b50e3c Slowly working my way "down" the list of controllers to fix and enhance. 2014-09-03 16:50:53 +02:00
James Cole
c3fd5c7136 Some new stuff that really doesn't belong here. I'm not good at this. 2014-09-03 07:11:35 +02:00
James Cole
98612dd253 Last changes to make the import routine work. 2014-09-02 19:12:57 +02:00
James Cole
4d7f5238dd Moar updates. 2014-09-02 17:27:28 +02:00
James Cole
f472a01a80 First attempt, trying to build an import stuff routine. 2014-09-02 08:58:56 +02:00
James Cole
420b5790e3 New ignore files [skip ci] 2014-08-31 15:26:51 +02:00
James Cole
2e342e47a7 Added unicity to AccountType model. Fixed some tests because of this. 2014-08-31 10:03:24 +02:00
James Cole
58b3334f05 Cleaned up some tests and moved some methods. 2014-08-31 08:59:43 +02:00
James Cole
4cd955e5cf Small text change in login. 2014-08-31 07:33:11 +02:00
James Cole
4dbf410cdf Removed codeception. 2014-08-31 07:32:59 +02:00
James Cole
074e6d52b1 Regenerated all model phpdocs. 2014-08-31 07:32:48 +02:00
James Cole
a0a36c5137 Ran model helper, added some new features. 2014-08-30 14:27:05 +02:00
James Cole
9db4137a1b Revamped the account controller. 2014-08-30 14:26:33 +02:00
James Cole
85f1e744b8 Added a new type of validation to be used for account names. 2014-08-30 14:25:52 +02:00
James Cole
8d90061d90 Included codeception for future use. 2014-08-30 14:25:21 +02:00
James Cole
b20d84e4b8 Fixed the accounts routes to be more strict about the types of accounts they accept. 2014-08-30 14:25:03 +02:00
138 changed files with 3381 additions and 5280 deletions

3
.gitignore vendored
View File

@@ -11,4 +11,5 @@ tests/_output/*
_ide_helper.php
/build/logs/clover.xml
index.html*
app/storage/firefly-export*
app/storage/firefly-export*
.vagrant

View File

@@ -2,7 +2,6 @@ firefly-iii
===========
[![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=master)](https://travis-ci.org/JC5/firefly-iii)
[![Coverage Status](https://coveralls.io/repos/JC5/firefly-iii/badge.png?branch=master)](https://coveralls.io/r/JC5/firefly-iii?branch=master)
![Still maintained?](http://stillmaintained.com/JC5/firefly-iii.png)
[![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)

View File

@@ -26,6 +26,9 @@ $(function () {
str += '<span style="color:' + colour + '">' + point.series.name + '</span>: € ' + Highcharts.numberFormat(point.y, 2) + '<br />';
}
if (x == 1) {
str += '<span style="color:' + colour + '">' + point.series.name + '</span>: € ' + Highcharts.numberFormat(point.y, 2) + '<br />';
}
if (x == 2) {
str += '<span style="color:' + colour + '">' + point.series.name + '</span>: ' + Highcharts.numberFormat(point.y, 1) + '%<br />';
}
}

View File

@@ -1,2 +1,3 @@
local/
laptop/
laptop/
vagrant/

View File

@@ -40,6 +40,7 @@ return [
# 'Barryvdh\Debugbar\ServiceProvider',
'Firefly\Storage\StorageServiceProvider',
'Firefly\Helper\HelperServiceProvider',
'Firefly\Validation\ValidationServiceProvider',
'Codesleeve\AssetPipeline\AssetPipelineServiceProvider',
],
'manifest' => storage_path() . '/meta',

View File

@@ -5,7 +5,11 @@ use Firefly\Storage\Account\AccountRepositoryInterface as ARI;
/**
* Class AccountController
*
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class AccountController extends \BaseController
{
@@ -14,11 +18,11 @@ class AccountController extends \BaseController
/**
* @param ARI $repository
* @param AI $accounts
* @param AI $accounts
*/
public function __construct(ARI $repository, AI $accounts)
{
$this->_accounts = $accounts;
$this->_accounts = $accounts;
$this->_repository = $repository;
}
@@ -27,47 +31,30 @@ class AccountController extends \BaseController
*/
public function create()
{
return View::make('accounts.create');
return View::make('accounts.create')->with('title', 'Create account');
}
/**
* @param Account $account
*
* @return \Illuminate\View\View
* @return $this
*/
public function delete(Account $account)
{
$accountType = $account->accountType()->first();
if ($accountType->description == 'Initial balance account' || $accountType->description == 'Cash account') {
return \View::make('error')->with(
'message', 'Cannot edit this account type (' . $accountType->description . ').'
);
}
return View::make('accounts.delete')->with('account', $account);
return View::make('accounts.delete')->with('account', $account)
->with('title', 'Delete account "' . $account->name . '"');
}
/**
* @param Account $account
*
* @return \Illuminate\Http\RedirectResponse
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function destroy(Account $account)
{
$accountType = $account->accountType()->first();
if ($accountType->description == 'Initial balance account' || $accountType->description == 'Cash account') {
return View::make('error')->with(
'message', 'Cannot edit this account type (' . $accountType->description . ').'
);
}
$result = $this->_repository->destroy($account);
if ($result === true) {
Session::flash('success', 'The account was deleted.');
} else {
Session::flash('error', 'Could not delete the account.');
}
$this->_repository->destroy($account);
Session::flash('success', 'The account was deleted.');
return Redirect::route('accounts.index');
@@ -76,54 +63,54 @@ class AccountController extends \BaseController
/**
* @param Account $account
*
* @return \Illuminate\View\View
* @return $this
*/
public function edit(Account $account)
{
$accountType = $account->accountType()->first();
if ($accountType->description == 'Initial balance account' || $accountType->description == 'Cash account') {
return View::make('error')->with(
'message', 'Cannot edit this account type (' . $accountType->description . ').'
);
}
$openingBalance = $this->_accounts->openingBalanceTransaction($account);
return View::make('accounts.edit')->with('account', $account)->with('openingBalance', $openingBalance);
return View::make('accounts.edit')->with('account', $account)->with('openingBalance', $openingBalance)
->with('title', 'Edit account "' . $account->name . '"');
}
/**
* @return \Illuminate\View\View
* @return $this
*/
public function index()
{
$accounts = $this->_repository->get();
$display = $this->_accounts->index($accounts);
$set = [
'personal' => [],
'beneficiaries' => []
];
foreach ($accounts as $account) {
switch ($account->accounttype->type) {
case 'Default account':
$set['personal'][] = $account;
break;
case 'Beneficiary account':
$set['beneficiaries'][] = $account;
break;
}
}
return View::make('accounts.index')->with('accounts', $display);
return View::make('accounts.index')->with('accounts', $set)->with('title', 'All your accounts');
}
/**
* @param Account $account
*
* @return \Illuminate\View\View
* @return $this
*/
public function show(Account $account)
{
$accountType = $account->accountType()->first();
if ($accountType->description == 'Initial balance account' || $accountType->description == 'Cash account') {
return View::make('error')->with(
'message', 'Cannot show this account type (' . $accountType->description . ').'
);
}
$data = $this->_accounts->show($account, 40);
$show = $this->_accounts->show($account, 40);
return View::make('accounts.show')->with('account', $account)->with('show', $show);
return View::make('accounts.show')->with('account', $account)->with('show', $data)->with('title',
'Details for account "' . $account->name . '"');
}
/**
* @return \Illuminate\Http\RedirectResponse
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function store()
{
@@ -133,14 +120,14 @@ class AccountController extends \BaseController
if ($account->validate()) {
// saved! return to wherever.
Session::flash('success', 'Account "' . $account->name . '" created!');
if (Input::get('create') == '1') {
if (intval(Input::get('create')) === 1) {
return Redirect::route('accounts.create')->withInput();
} else {
return Redirect::route('accounts.index');
}
} else {
// did not save, return with error:
Session::flash('error', 'Could not save the new account. Please check the form.');
Session::flash('error', 'Could not save the new account: ' . $account->errors()->first());
return Redirect::route('accounts.create')->withErrors($account->errors())->withInput();
@@ -150,16 +137,10 @@ class AccountController extends \BaseController
/**
* @param Account $account
*
* @return \Illuminate\Http\RedirectResponse
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function update(Account $account)
{
$accountType = $account->accountType()->first();
if ($accountType->description == 'Initial balance account' || $accountType->description == 'Cash account') {
return View::make('error')->with(
'message', 'Cannot show this account type (' . $accountType->description . ').'
);
}
$account = $this->_repository->update($account, Input::all());
if ($account->validate()) {
Session::flash('success', 'Account "' . $account->name . '" updated.');

View File

@@ -1,5 +1,7 @@
<?php
use \Illuminate\Routing\Controller;
/**
* Class BaseController
*/

View File

@@ -6,6 +6,9 @@ use Firefly\Storage\Budget\BudgetRepositoryInterface as BRI;
/**
* Class BudgetController
*
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*
*/
class BudgetController extends BaseController
{
@@ -14,12 +17,12 @@ class BudgetController extends BaseController
protected $_repository;
/**
* @param BI $budgets
* @param BI $budgets
* @param BRI $repository
*/
public function __construct(BI $budgets, BRI $repository)
{
$this->_budgets = $budgets;
$this->_budgets = $budgets;
$this->_repository = $repository;
}
@@ -30,7 +33,7 @@ class BudgetController extends BaseController
{
$periods = \Config::get('firefly.periods_to_text');
return View::make('budgets.create')->with('periods', $periods);
return View::make('budgets.create')->with('periods', $periods)->with('title', 'Create a new budget');
}
/**
@@ -40,7 +43,8 @@ class BudgetController extends BaseController
*/
public function delete(Budget $budget)
{
return View::make('budgets.delete')->with('budget', $budget);
return View::make('budgets.delete')->with('budget', $budget)
->with('title', 'Delete budget "' . $budget->name . '"');
}
/**
@@ -50,20 +54,16 @@ class BudgetController extends BaseController
*/
public function destroy(Budget $budget)
{
// remove budget
Event::fire('budgets.destroy', [$budget]); // just before deletion.
$result = $this->_repository->destroy($budget);
if ($result === true) {
Session::flash('success', 'The budget was deleted.');
if (Input::get('from') == 'date') {
return Redirect::route('budgets.index');
} else {
return Redirect::route('budgets.index.budget');
}
} else {
Session::flash('error', 'Could not delete the budget. Check the logs to be sure.');
}
$this->_repository->destroy($budget);
Session::flash('success', 'The budget was deleted.');
return Redirect::route('budgets.index');
// redirect:
if (Input::get('from') == 'date') {
return Redirect::route('budgets.index');
}
return Redirect::route('budgets.index.budget');
}
@@ -74,7 +74,8 @@ class BudgetController extends BaseController
*/
public function edit(Budget $budget)
{
return View::make('budgets.edit')->with('budget', $budget);
return View::make('budgets.edit')->with('budget', $budget)
->with('title', 'Edit budget "' . $budget->name . '"');
}
@@ -84,62 +85,71 @@ class BudgetController extends BaseController
public function indexByBudget()
{
$budgets = $this->_repository->get();
$today = new Carbon;
return View::make('budgets.indexByBudget')->with('budgets', $budgets)->with('today', $today);
return View::make('budgets.indexByBudget')->with('budgets', $budgets)->with('today', new Carbon)
->with('title', 'All your budgets grouped by budget');
}
/**
* @return $this|\Illuminate\View\View
* @throws Firefly\Exception\FireflyException
* @return $this
*/
public function indexByDate()
{
// get a list of dates by getting all repetitions:
$set = $this->_repository->get();
$set = $this->_repository->get();
$budgets = $this->_budgets->organizeByDate($set);
return View::make('budgets.indexByDate')->with('budgets', $budgets);
return View::make('budgets.indexByDate')->with('budgets', $budgets)
->with('title', 'All your budgets grouped by date');
}
/**
* Three use cases for this view:
*
* - Show everything.
* - Show a specific repetition.
* - Show everything shows NO repetition.
*
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return int
*/
public function show(Budget $budget)
public function show(Budget $budget, \LimitRepetition $repetition = null)
{
/**
* Use the
*/
$useSessionDates = Input::get('useSession') == 'true' ? true : false;
$filters = [];
if (!is_null(Input::get('rep'))) {
$repetitionId = intval(Input::get('rep'));
$repetitions = $this->_budgets->organizeRepetition($repetitionId);
$filters[] = $repetitions[0]['limit'];
$filters[] = $repetitions[0]['limitrepetition'];
} else {
if (Input::get('noenvelope') == 'true') {
$repetitions = $this->_budgets->outsideRepetitions($budget);
$filters[] = 'no_envelope';
} else {
// grab all limit repetitions, order them, show them:
$repetitions = $this->_budgets->organizeRepetitions($budget, $useSessionDates);
}
$view = null;
$title = null;
\Log::debug('Is envelope true? ' . (Input::get('noenvelope') == 'true'));
switch (true) {
case (!is_null($repetition)):
$data = $this->_budgets->organizeRepetition($repetition);
$view = 1;
$title = $budget->name . ', ' . $repetition->periodShow() . ', ' . mf($repetition->limit->amount,
false);
break;
case (Input::get('noenvelope') == 'true'):
$data = $this->_budgets->outsideRepetitions($budget);
$view = 2;
$title = $budget->name . ', transactions outside an envelope';
break;
default:
$data = $this->_budgets->organizeRepetitions($budget, $useSessionDates);
$view = $useSessionDates ? 3 : 4;
$title = $useSessionDates ? $budget->name . ' in session period' : $budget->name;
break;
}
return View::make('budgets.show')->with('budget', $budget)->with('repetitions', $repetitions)->with(
'filters', $filters
)->with('highlight', Input::get('highlight'))->with('useSessionDates', $useSessionDates);
return View::make('budgets.show')
->with('budget', $budget)
->with('repetitions', $data)
->with('view', $view)
->with('highlight', Input::get('highlight'))
->with('useSessionDates', $useSessionDates)
->with('title', $title);
}
/**

View File

@@ -13,12 +13,12 @@ class CategoryController extends BaseController
/**
* @param CRI $repository
* @param CI $category
* @param CI $category
*/
public function __construct(CRI $repository, CI $category)
{
$this->_repository = $repository;
$this->_category = $category;
$this->_category = $category;
}
/**
@@ -26,7 +26,7 @@ class CategoryController extends BaseController
*/
public function create()
{
return View::make('categories.create');
return View::make('categories.create')->with('title', 'Create a new category');
}
/**
@@ -36,7 +36,8 @@ class CategoryController extends BaseController
*/
public function delete(Category $category)
{
return View::make('categories.delete')->with('category', $category);
return View::make('categories.delete')->with('category', $category)
->with('title', 'Delete category "' . $category->name . '"');
}
/**
@@ -46,13 +47,8 @@ class CategoryController extends BaseController
*/
public function destroy(Category $category)
{
$result = $this->_repository->destroy($category);
if ($result === true) {
Session::flash('success', 'The category was deleted.');
} else {
Session::flash('error', 'Could not delete the category. Check the logs to be sure.');
}
$this->_repository->destroy($category);
Session::flash('success', 'The category was deleted.');
return Redirect::route('categories.index');
}
@@ -63,7 +59,8 @@ class CategoryController extends BaseController
*/
public function edit(Category $category)
{
return View::make('categories.edit')->with('category', $category);
return View::make('categories.edit')->with('category', $category)
->with('title', 'Edit category "' . $category->name . '"');
}
/**
@@ -73,7 +70,8 @@ class CategoryController extends BaseController
{
$categories = $this->_repository->get();
return View::make('categories.index')->with('categories', $categories);
return View::make('categories.index')->with('categories', $categories)
->with('title', 'All your categories');
}
/**
@@ -84,14 +82,14 @@ class CategoryController extends BaseController
public function show(Category $category)
{
$start = \Session::get('start');
$end = \Session::get('end');
$end = \Session::get('end');
$journals = $this->_category->journalsInRange($category, $start, $end);
return View::make('categories.show')->with('category', $category)->with('journals', $journals)->with(
'highlight', Input::get('highlight')
);
'highlight', Input::get('highlight')
)->with('title', 'Overview for category "'.$category->name.'"');;
}
/**

View File

@@ -20,42 +20,35 @@ class ChartController extends BaseController
*/
public function __construct(ChartInterface $chart, AccountRepositoryInterface $accounts)
{
$this->_chart = $chart;
$this->_chart = $chart;
$this->_accounts = $accounts;
}
/**
* This method takes a budget, all limits and all their repetitions and displays three numbers per repetition:
* the amount of money in the repetition (represented as "an envelope"), the amount spent and the spent percentage.
*
* @param Budget $budget
*
* @return \Illuminate\Http\JsonResponse
*/
public function budgetDefault(\Budget $budget)
{
$expense = [];
$left = [];
$expense = [];
$left = [];
$envelope = [];
// get all limit repetitions for this budget.
/** @var \Limit $limit */
foreach ($budget->limits as $limit) {
/** @var \LimitRepetition $rep */
foreach ($limit->limitrepetitions as $rep) {
$spentInRep = \Transaction::
leftJoin(
'transaction_journals', 'transaction_journals.id', '=',
'transactions.transaction_journal_id'
)
->leftJoin(
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id',
'=',
'transaction_journals.id'
)->where('component_transaction_journal.component_id', '=', $budget->id)->where(
'transaction_journals.date', '>=', $rep->startdate->format('Y-m-d')
)->where('transaction_journals.date', '<=', $rep->enddate->format('Y-m-d'))->where(
'amount', '>', 0
)->sum('amount');
$pct = round(($spentInRep / $limit->amount) * 100, 2);
$name = $rep->periodShow();
$expense[] = [$name, floatval($spentInRep)];
$left[] = [$name, $pct];
// get the amount of money spent in this period on this budget.
$spentInRep = $rep->amount - $rep->left();
$pct = round((floatval($spentInRep) / floatval($limit->amount)) * 100, 2);
$name = $rep->periodShow();
$envelope[] = [$name, floatval($limit->amount)];
$expense[] = [$name, floatval($spentInRep)];
$left[] = [$name, $pct];
}
}
@@ -63,6 +56,12 @@ class ChartController extends BaseController
'chart_title' => 'Overview for budget ' . $budget->name,
'subtitle' => 'All envelopes',
'series' => [
[
'type' => 'line',
'yAxis' => 1,
'name' => 'Amount in envelope',
'data' => $envelope
],
[
'type' => 'column',
'name' => 'Expenses in envelope',
@@ -75,6 +74,7 @@ class ChartController extends BaseController
'data' => $left
]
]
];
@@ -82,29 +82,27 @@ class ChartController extends BaseController
}
/**
* This method takes a single limit repetition (so a single "envelope") and displays the amount of money spent
* per day and subsequently how much money is left.
*
* @param LimitRepetition $rep
*
* @return \Illuminate\Http\JsonResponse
*/
public function budgetLimit(\LimitRepetition $rep)
{
$budget = $rep->limit->budget;
$current = clone $rep->startdate;
$expense = [];
$leftInLimit = [];
$budget = $rep->limit->budget;
$current = clone $rep->startdate;
$expense = [];
$leftInLimit = [];
$currentLeftInLimit = floatval($rep->limit->amount);
while ($current <= $rep->enddate) {
$spent = \Transaction::
leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin(
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
'transaction_journals.id'
)->where('component_transaction_journal.component_id', '=', $budget->id)->where(
'transaction_journals.date', $current->format('Y-m-d')
)->where('amount', '>', 0)->sum('amount');
$spent = floatval($spent) == 0 ? null : floatval($spent);
$entry = [$current->timestamp * 1000, $spent];
$expense[] = $entry;
$spent = $this->_chart->spentOnDay($budget, $current);
$spent = floatval($spent) == 0 ? null : floatval($spent);
$entry = [$current->timestamp * 1000, $spent];
$expense[] = $entry;
$currentLeftInLimit = $currentLeftInLimit - $spent;
$leftInLimit[] = [$current->timestamp * 1000, $currentLeftInLimit];
$leftInLimit[] = [$current->timestamp * 1000, $currentLeftInLimit];
$current->addDay();
}
@@ -132,53 +130,44 @@ class ChartController extends BaseController
}
/**
* This method takes a budget and gets all transactions in it which haven't got an envelope (limit).
*
* Usually this means that very old and unorganized or very NEW transactions get displayed; there was never an
* envelope or it hasn't been created (yet).
*
*
* @param Budget $budget
*
* @return \Illuminate\Http\JsonResponse
*/
public function budgetNoLimits(\Budget $budget)
{
$inRepetitions = [];
foreach ($budget->limits as $limit) {
foreach ($limit->limitrepetitions as $repetition) {
$set = $budget->transactionjournals()->leftJoin(
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
)->where('transaction_types.type', 'Withdrawal')->where(
'date', '>=', $repetition->startdate->format('Y-m-d')
)->where('date', '<=', $repetition->enddate->format('Y-m-d'))->orderBy('date', 'DESC')->get(
['transaction_journals.id']
);
foreach ($set as $item) {
$inRepetitions[] = $item->id;
}
}
/*
* We can go about this two ways. Either we find all transactions which definitely are IN an envelope
* and exclude them or we search for transactions outside of the range of any of the envelopes we have.
*
* Since either is shitty we go with the first one because it's easier to build.
*/
$inRepetitions = $this->_chart->allJournalsInBudgetEnvelope($budget);
}
$query = $budget->transactionjournals()->whereNotIn(
'transaction_journals.id', $inRepetitions
)->orderBy('date', 'DESC')->orderBy(
'transaction_journals.id', 'DESC'
);
/*
* With this set of id's, we can search for all journals NOT in that set.
* BUT they have to be in the budget (duh).
*/
$set = $this->_chart->journalsNotInSet($budget, $inRepetitions);
/*
* Next step: get all transactions for those journals.
*/
$transactions = $this->_chart->transactionsByJournals($set);
$result = $query->get(['transaction_journals.id']);
$set = [];
foreach ($result as $entry) {
$set[] = $entry->id;
}
// all transactions for these journals, grouped by date and SUM
$transactions = \Transaction::whereIn('transaction_journal_id', $set)->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)
->groupBy('transaction_journals.date')->where('amount', '>', 0)->get(
['transaction_journals.date', DB::Raw('SUM(`amount`) as `aggregate`')]
);
// this set builds the chart:
/*
* this set builds the chart:
*/
$expense = [];
foreach ($transactions as $t) {
$date = new Carbon($t->date);
$date = new Carbon($t->date);
$expense[] = [$date->timestamp * 1000, floatval($t->aggregate)];
}
$return = [
@@ -186,126 +175,104 @@ class ChartController extends BaseController
'subtitle' => 'Not organized by an envelope',
'series' => [
[
'type' => 'spline',
'type' => 'column',
'name' => 'Expenses per day',
'data' => $expense
]
]
];
return Response::json($return);
}
/**
* This method gets all transactions within a budget within the period set by the current session
* start and end date. It also includes any envelopes which might exist within this period.
*
* @param Budget $budget
*
* @return \Illuminate\Http\JsonResponse
*/
public function budgetSession(\Budget $budget)
{
$expense = [];
$repetitionSeries = [];
$current = clone Session::get('start');
$end = clone Session::get('end');
while ($current <= $end) {
$spent = \Transaction::
leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin(
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
'transaction_journals.id'
)->where('component_transaction_journal.component_id', '=', $budget->id)->where(
'transaction_journals.date', $current->format('Y-m-d')
)->where('amount', '>', 0)->sum('amount');
$spent = floatval($spent) == 0 ? null : floatval($spent);
if (!is_null($spent)) {
$expense[] = [$current->timestamp * 1000, $spent];
}
$series = [];
$end = clone Session::get('end');
$start = clone Session::get('start');
/*
* Expenses per day in the session's period. That's easy.
*/
$expense = [];
$current = clone Session::get('start');
while ($current <= $end) {
$spent = $this->_chart->spentOnDay($budget, $current);
$spent = floatval($spent) == 0 ? null : floatval($spent);
$expense[] = [$current->timestamp * 1000, $spent];
$current->addDay();
}
// find all limit repetitions (for this budget) between start and end.
$start = clone Session::get('start');
$repetitionSeries[] = [
$series[] = [
'type' => 'column',
'name' => 'Expenses per day',
'data' => $expense
];
unset($expense, $spent, $current);
/*
* Find all limit repetitions (for this budget) between start and end. This is
* quite a complex query.
*/
$reps = $this->_chart->limitsInRange($budget, $start, $end);
/** @var \Limit $limit */
foreach ($budget->limits as $limit) {
$reps = $limit->limitrepetitions()->where(
function ($q) use ($start, $end) {
// startdate is between range
$q->where(
function ($q) use ($start, $end) {
$q->where('startdate', '>=', $start->format('Y-m-d'));
$q->where('startdate', '<=', $end->format('Y-m-d'));
}
/*
* For each limitrepetition we create a serie that contains the amount left in
* the limitrepetition for its entire date-range. Entries are only actually included when they
* fall into the charts date range.
*
* So example: we have a session date from Jan 15 to Jan 30. The limitrepetition starts at 1 Jan until 1 Feb.
*
* We loop from 1 Jan to 1 Feb but only include Jan 15 / Jan 30. But we do keep count of the amount outside
* of these dates because otherwise the line might be wrong.
*/
/** @var \LimitRepetition $repetition */
foreach ($reps as $repetition) {
$limitAmount = $repetition->limit->amount;
// create a serie for the repetition.
$currentSerie = [
'type' => 'spline',
'id' => 'rep-' . $repetition->id,
'yAxis' => 1,
'name' => 'Envelope #'.$repetition->id.' in ' . $repetition->periodShow(),
'data' => []
];
$current = clone $repetition->startdate;
while ($current <= $repetition->enddate) {
if ($current >= $start && $current <= $end) {
// spent on limit:
$spentSoFar = $this->_chart->spentOnLimitRepetitionBetweenDates(
$repetition, $repetition->startdate, $current
);
$leftInLimit = floatval($limitAmount) - floatval($spentSoFar);
// or enddate is between range.
$q->orWhere(
function ($q) use ($start, $end) {
$q->where('enddate', '>=', $start->format('Y-m-d'));
$q->where('enddate', '<=', $end->format('Y-m-d'));
}
);
$currentSerie['data'][] = [$current->timestamp * 1000, $leftInLimit];
}
)
->get();
$currentLeftInLimit = floatval($limit->amount);
/** @var \LimitRepetition $repetition */
foreach ($reps as $repetition) {
// create a serie for the repetition.
$currentSerie = [
'type' => 'spline',
'id' => 'rep-' . $repetition->id,
'yAxis' => 1,
'name' => 'Envelope in ' . $repetition->periodShow(),
'data' => []
];
$current = clone $repetition->startdate;
while ($current <= $repetition->enddate) {
if ($current >= Session::get('start') && $current <= Session::get('end')) {
// spent on limit:
$spentSoFar = \Transaction::
leftJoin(
'transaction_journals', 'transaction_journals.id', '=',
'transactions.transaction_journal_id'
)
->leftJoin(
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id',
'=',
'transaction_journals.id'
)->where('component_transaction_journal.component_id', '=', $budget->id)->where(
'transaction_journals.date', '>=', $repetition->startdate->format('Y-m-d')
)->where('transaction_journals.date', '<=', $current->format('Y-m-d'))->where(
'amount', '>', 0
)->sum('amount');
$spent = floatval($spent) == 0 ? null : floatval($spent);
$currentLeftInLimit = floatval($limit->amount) - floatval($spentSoFar);
$currentSerie['data'][] = [$current->timestamp * 1000, $currentLeftInLimit];
}
$current->addDay();
}
// do something here.
$repetitionSeries[] = $currentSerie;
$current->addDay();
}
// do something here.
$series[] = $currentSerie;
}
$return = [
'chart_title' => 'Overview for budget ' . $budget->name,
'subtitle' =>
'Between ' . Session::get('start')->format('M jS, Y') . ' and ' . Session::get('end')->format(
'M jS, Y'
),
'series' => $repetitionSeries
'series' => $series
];
return Response::json($return);
@@ -320,11 +287,11 @@ class ChartController extends BaseController
public function categoryShowChart(Category $category)
{
$start = Session::get('start');
$end = Session::get('end');
$end = Session::get('end');
$range = Session::get('range');
$serie = $this->_chart->categoryShowChart($category, $range, $start, $end);
$data = [
$data = [
'chart_title' => $category->name,
'subtitle' => '<a href="' . route('categories.show', [$category->id]) . '">View more</a>',
'series' => $serie
@@ -344,23 +311,23 @@ class ChartController extends BaseController
{
// get preferences and accounts (if necessary):
$start = Session::get('start');
$end = Session::get('end');
$end = Session::get('end');
if (is_null($account)) {
// get, depending on preferences:
/** @var \Firefly\Helper\Preferences\PreferencesHelperInterface $prefs */
$prefs = \App::make('Firefly\Helper\Preferences\PreferencesHelperInterface');
$pref = $prefs->get('frontpageAccounts', []);
$pref = $prefs->get('frontpageAccounts', []);
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $acct */
$acct = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
$acct = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
$accounts = $acct->getByIds($pref->data);
} else {
$accounts = [$account];
}
// loop and get array data.
$url = count($accounts) == 1 && is_array($accounts)
$url = count($accounts) == 1 && is_array($accounts)
? '<a href="' . route('accounts.show', [$account->id]) . '">View more</a>'
:
'<a href="' . route('accounts.index') . '">View more</a>';
@@ -371,7 +338,6 @@ class ChartController extends BaseController
];
foreach ($accounts as $account) {
\Log::debug('Now building series for ' . $account->name);
$data['series'][] = $this->_chart->account($account, $start, $end);
}
@@ -390,7 +356,7 @@ class ChartController extends BaseController
{
$account = $this->_accounts->findByName($name);
$date = Carbon::createFromDate($year, $month, $day);
$date = Carbon::createFromDate($year, $month, $day);
$result = $this->_chart->accountDailySummary($account, $date);
return View::make('charts.info')->with('rows', $result['rows'])->with('sum', $result['sum'])->with(
@@ -414,7 +380,7 @@ class ChartController extends BaseController
public function homeCategories()
{
$start = Session::get('start');
$end = Session::get('end');
$end = Session::get('end');
return Response::json($this->_chart->categories($start, $end));

View File

@@ -38,6 +38,10 @@ class HomeController extends BaseController
*/
public function index()
{
// Queue::push(function($job)
// {
// Log::debug('This is a job!');
// });
\Event::fire('limits.check');
\Event::fire('piggybanks.check');

View File

@@ -0,0 +1,46 @@
<?php
/**
* Class MigrateController
*/
class MigrateController extends BaseController
{
/**
* @return $this
*/
public function index()
{
return View::make('migrate.index')->with('index', 'Migration');
}
/**
*
*/
public function upload()
{
if (Input::hasFile('file') && Input::file('file')->isValid()) {
// move file to storage:
// ->move($destinationPath, $fileName);
$path = storage_path();
$fileName = 'firefly-iii-import-' . date('Y-m-d-H-i') . '.json';
$fullName = $path . DIRECTORY_SEPARATOR . $fileName;
if (is_writable($path)) {
Input::file('file')->move($path, $fileName);
// so now we push something in a queue and do something with it! Yay!
\Log::debug('Pushed a job to start the import.');
Queue::push('Firefly\Queue\Import@start', ['file' => $fullName, 'user' => \Auth::user()->id]);
Session::flash('success', 'The import job has been queued. Please be patient. Data will appear');
return Redirect::route('index');
}
Session::flash('error', 'Could not save file to storage.');
return Redirect::route('migrate.index');
} else {
Session::flash('error', 'Please upload a file.');
return Redirect::route('migrate.index');
}
}
}

View File

@@ -197,6 +197,7 @@ class TransactionController extends BaseController
}
// trigger the creation for recurring transactions.
Event::fire('journals.store',[$journal]);
if (Input::get('create') == '1') {
return Redirect::route('transactions.create', [$what])->withInput();
@@ -225,6 +226,7 @@ class TransactionController extends BaseController
if ($journal->validate()) {
// has been saved, return to index:
Session::flash('success', 'Transaction updated!');
Event::fire('journals.update',[$journal]);
return Redirect::route('transactions.index');
} else {

View File

@@ -11,22 +11,6 @@ use Illuminate\Database\Schema\Blueprint;
class CreateAccountTypesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(
'account_types', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('description', 50);
}
);
}
/**
* Reverse the migrations.
*
@@ -37,4 +21,23 @@ class CreateAccountTypesTable extends Migration
Schema::drop('account_types');
}
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(
'account_types', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->string('type', 50);
$table->boolean('editable');
$table->unique('type');
}
);
}
}

View File

@@ -25,8 +25,8 @@ class CreateRecurringTransactionsTable extends Migration
$table->integer('user_id')->unsigned();
$table->string('name', 50);
$table->string('match', 255);
$table->decimal('amount_max', 10, 2);
$table->decimal('amount_min', 10, 2);
$table->decimal('amount_max', 10, 2);
$table->date('date');
$table->boolean('active');

View File

@@ -24,6 +24,7 @@ class CreateTransactionJournalsTable extends Migration
$table->timestamps();
$table->integer('user_id')->unsigned();
$table->integer('transaction_type_id')->unsigned();
$table->integer('recurring_transaction_id')->unsigned()->nullable();
$table->integer('transaction_currency_id')->unsigned();
$table->string('description', 255)->nullable();
$table->boolean('completed');
@@ -34,6 +35,11 @@ class CreateTransactionJournalsTable extends Migration
->references('id')->on('transaction_types')
->onDelete('cascade');
// connect transaction journals to recurring transactions
$table->foreign('recurring_transaction_id')
->references('id')->on('recurring_transactions')
->onDelete('set null');
// connect transaction journals to transaction currencies
$table->foreign('transaction_currency_id')
->references('id')->on('transaction_currencies')

View File

@@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateImportmapsTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('importmaps', function(Blueprint $table)
{
$table->increments('id');
$table->timestamps();
$table->integer('user_id')->unsigned();
$table->string('file',500);
// connect maps to users
$table->foreign('user_id')
->references('id')->on('users')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('importmaps');
}
}

View File

@@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateImportentriesTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('importentries', function(Blueprint $table)
{
$table->increments('id');
$table->timestamps();
$table->string('class',200);
$table->integer('importmap_id')->unsigned();
$table->integer('old')->unsigned();
$table->integer('new')->unsigned();
// map import entries to import map.
// connect accounts to account_types
$table->foreign('importmap_id')
->references('id')->on('importmaps')
->onDelete('cascade');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('importentries');
}
}

View File

@@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateFailedJobsTable extends Migration
{
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('failed_jobs');
}
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('failed_jobs', function (Blueprint $table) {
$table->increments('id');
$table->text('connection');
$table->text('queue');
$table->text('payload');
$table->timestamp('failed_at');
});
}
}

View File

@@ -11,16 +11,20 @@ class AccountTypeSeeder extends Seeder
DB::table('account_types')->delete();
AccountType::create(
['description' => 'Default account']
['type' => 'Default account', 'editable' => true]
);
AccountType::create(
['description' => 'Cash account']
['type' => 'Cash account', 'editable' => false]
);
AccountType::create(
['description' => 'Initial balance account']
['type' => 'Initial balance account', 'editable' => false]
);
AccountType::create(
['description' => 'Beneficiary account']
['type' => 'Beneficiary account', 'editable' => true]
);
AccountType::create(
['type' => 'Import account', 'editable' => false]
);
}

View File

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

View File

@@ -2,8 +2,6 @@
namespace Firefly\Helper\Controllers;
use Illuminate\Database\Eloquent\Collection;
/**
* Class Account
*
@@ -11,166 +9,126 @@ use Illuminate\Database\Eloquent\Collection;
*/
class Account implements AccountInterface
{
/**
* @param Collection $accounts
*
* @return array|mixed
*/
public function index(Collection $accounts)
{
$list = [
'personal' => [],
'beneficiaries' => [],
'initial' => [],
'cash' => []
];
foreach ($accounts 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 $list;
}
/**
* @param \Account $account
*
* @return mixed
* @return \TransactionJournal|null
*/
public function openingBalanceTransaction(\Account $account)
{
$transactionType = \TransactionType::where('type', 'Opening balance')->first();
return \TransactionJournal::
with(
['transactions' => function ($q) {
$q->orderBy('amount', 'ASC');
}]
)->where('transaction_type_id', $transactionType->id)
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.account_id', $account->id)->first(['transaction_journals.*']);
return \TransactionJournal::withRelevantData()
->account($account)
->leftJoin('transaction_types', 'transaction_types.id', '=',
'transaction_journals.transaction_type_id')
->where('transaction_types.type', 'Opening balance')
->first(['transaction_journals.*']);
}
/**
* @param \Account $account
* @param $perPage
* Since it is entirely possible the database is messed up somehow it might be that a transaction
* journal has only one transaction. This is mainly caused by wrong deletions and other artefacts from the past.
*
* @return mixed|void
* If it is the case, we remove $item and continue like nothing ever happened. This will however,
* mess up some statisics but we can live with that. We might be needing some cleanup routine in the future.
*
* For now, we simply warn the user of this.
*
* @param \Account $account
* @param $perPage
* @return array|mixed
* @throws \Firefly\Exception\FireflyException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function show(\Account $account, $perPage)
{
$start = \Session::get('start');
$end = \Session::get('end');
$end = \Session::get('end');
$stats = [
'budgets' => [],
'categories' => [],
'accounts' => []
'accounts' => []
];
$items = [];
// build a query:
$query = \TransactionJournal::with(
['transactions' => function ($q) {
$q->orderBy('amount', 'ASC');
}, 'transactiontype', 'components' => function ($q) {
$q->orderBy('class');
}, 'transactions.account.accounttype']
)->orderBy('date', 'DESC')->leftJoin(
'transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
)->where('transactions.account_id', $account->id)->where('date', '>=', $start->format('Y-m-d'))->where(
'date', '<=', $end->format('Y-m-d')
)->orderBy('transaction_journals.id', 'DESC');
$query = \TransactionJournal::withRelevantData()
->defaultSorting()
->account($account)
->after($start)
->before($end);
// filter some:
switch (\Input::get('type')) {
case 'transactions':
$query->transactionTypes(['Deposit', 'Withdrawal']);
break;
case 'transfers':
$query->transactionTypes(['Transfer']);
break;
}
switch (\Input::get('show')) {
case 'expenses':
case 'out':
$query->lessThan(0);
break;
case 'income':
case 'in':
$query->moreThan(0);
break;
}
// build paginator:
$totalItems = $query->count();
$page = intval(\Input::get('page')) > 1 ? intval(\Input::get('page')) : 1;
$skip = ($page - 1) * $perPage;
$result = $query->skip($skip)->take($perPage)->get(['transaction_journals.*']);
// in the mean time, build list of categories, budgets and other accounts:
$page = max(1, intval(\Input::get('page')));
$skip = ($page - 1) * $perPage;
$result = $query->skip($skip)->take($perPage)->get(['transaction_journals.*']);
// get the relevant budgets, categories and accounts from this list:
/** @var $item \TransactionJournal */
foreach ($result as $item) {
$items[] = $item;
foreach ($result as $index => $item) {
foreach ($item->components as $component) {
if ($component->class == 'Budget') {
$stats['budgets'][$component->id] = $component;
}
if ($component->class == 'Category') {
$stats['categories'][$component->id] = $component;
}
$stats[$component->class][$component->id] = $component;
}
$fromAccount = $item->transactions[0]->account;
$toAccount = $item->transactions[1]->account;
if (count($item->transactions) < 2) {
\Session::flash('warning', 'Some transactions are incomplete; they will not be shown.');
unset($result[$index]);
continue;
}
$items[] = $item;
$fromAccount = $item->transactions[0]->account;
$toAccount = $item->transactions[1]->account;
$stats['accounts'][$fromAccount->id] = $fromAccount;
$stats['accounts'][$toAccount->id] = $toAccount;
$stats['accounts'][$toAccount->id] = $toAccount;
}
unset($result, $page);
$paginator = \Paginator::make($items, $totalItems, $perPage);
// statistics
$stats['period']['in'] = floatval(
\Transaction::where('account_id', $account->id)->where('amount', '>', 0)->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)->leftJoin(
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
)->whereIn('transaction_types.type', ['Deposit', 'Withdrawal'])->where(
'transaction_journals.date', '>=', $start->format('Y-m-d')
)->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount')
);
unset($result, $page, $item, $fromAccount, $toAccount);
$stats['period']['out'] = floatval(
\Transaction::where('account_id', $account->id)->where('amount', '<', 0)->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)->leftJoin(
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
)->whereIn('transaction_types.type', ['Deposit', 'Withdrawal'])->where(
'transaction_journals.date', '>=', $start->format('Y-m-d')
)->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount')
);
$stats['period']['diff'] = $stats['period']['in'] + $stats['period']['out'];
// statistics (transactions)
$trIn = floatval(\Transaction::before($end)->after($start)->account($account)->moreThan(0)
->transactionTypes(['Deposit', 'Withdrawal'])->sum('transactions.amount'));
$trOut = floatval(\Transaction::before($end)->after($start)->account($account)->lessThan(0)
->transactionTypes(['Deposit', 'Withdrawal'])->sum('transactions.amount'));
$trDiff = $trIn + $trOut;
$stats['period']['t_in'] = floatval(
\Transaction::where('account_id', $account->id)->where('amount', '>', 0)->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)->leftJoin(
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
)->where('transaction_types.type', 'Transfer')->where(
'transaction_journals.date', '>=', $start->format('Y-m-d')
)->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount')
);
// statistics (transfers)
$trfIn = floatval(\Transaction::before($end)->after($start)->account($account)->moreThan(0)
->transactionTypes(['Transfer'])->sum('transactions.amount'));
$trfOut = floatval(\Transaction::before($end)->after($start)->account($account)->lessThan(0)
->transactionTypes(['Transfer'])->sum('transactions.amount'));
$trfDiff = $trfIn + $trfOut;
$stats['period']['t_out'] = floatval(
\Transaction::where('account_id', $account->id)->where('amount', '<', 0)->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)->leftJoin(
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
)->where('transaction_types.type', 'Transfer')->where(
'transaction_journals.date', '>=', $start->format('Y-m-d')
)->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->sum('amount')
);
$stats['period']['t_diff'] = $stats['period']['t_in'] + $stats['period']['t_out'];
$stats['period'] = [
'in' => $trIn,
'out' => $trOut,
'diff' => $trDiff,
't_in' => $trfIn,
't_out' => $trfOut,
't_diff' => $trfDiff
];
$return = [
'journals' => $paginator,
@@ -178,7 +136,5 @@ class Account implements AccountInterface
];
return $return;
}
}

View File

@@ -12,15 +12,6 @@ use Illuminate\Database\Eloquent\Collection;
interface AccountInterface
{
/**
* Build the index:
*
* @param Collection $accounts
*
* @return mixed
*/
public function index(Collection $accounts);
/**
* @param \Account $account
*

View File

@@ -13,6 +13,11 @@ class Budget implements BudgetInterface
{
/**
* First, loop all budgets, all of their limits and all repetitions to get an overview per period
* and some basic information about that repetition's data.
*
*
*
* @param Collection $budgets
*
* @return mixed|void
@@ -21,32 +26,30 @@ class Budget implements BudgetInterface
{
$return = [];
/** @var \Budget $budget */
foreach ($budgets as $budget) {
/** @var \Limit $limit */
foreach ($budget->limits as $limit) {
/** @var \LimitRepetition $rep */
foreach ($limit->limitrepetitions as $rep) {
$periodOrder = $rep->periodOrder();
$period = $rep->periodShow();
$return[$periodOrder] = isset($return[$periodOrder])
? $return[$periodOrder]
: ['date' => $period,
'dateObject' => $rep->startdate,
'start' => $rep->startdate,
'end' => $rep->enddate,
'budget_id' => $limit->budget_id];
/** @var \LimitRepetition $repetition */
foreach ($limit->limitrepetitions as $repetition) {
$repetition->left = $repetition->left();
$periodOrder = $repetition->periodOrder();
$period = $repetition->periodShow();
if (!isset($return[$periodOrder])) {
}
}
}
// put all the budgets under their respective date:
foreach ($budgets as $budget) {
foreach ($budget->limits as $limit) {
foreach ($limit->limitrepetitions as $rep) {
$rep->left = $rep->left();
$return[$periodOrder] = [
'date' => $period,
'start' => $repetition->startdate,
'end' => $repetition->enddate,
'budget_id' => $budget->id,
'limitrepetitions' => [$repetition]
];
} else {
$return[$periodOrder]['limitrepetitions'][] = $repetition;
}
$month = $rep->periodOrder();
$return[$month]['limitrepetitions'][] = $rep;
}
}
}
@@ -56,30 +59,24 @@ class Budget implements BudgetInterface
}
/**
* Get a repetition (complex because of user check)
* and then get the transactions in it.
* @param $repetitionId
*
* @return array
*/
public function organizeRepetition($repetitionId)
public function organizeRepetition(\LimitRepetition $repetition)
{
$result = [];
$repetition = \LimitRepetition::with('limit', 'limit.budget')->leftJoin(
'limits', 'limit_repetitions.limit_id', '=', 'limits.id'
)->leftJoin('components', 'limits.component_id', '=', 'components.id')->where(
'components.user_id', \Auth::user()->id
)
->where('limit_repetitions.id', $repetitionId)->first(['limit_repetitions.*']);
// get transactions:
$set = $repetition->limit->budget->transactionjournals()->with(
'transactions', 'transactions.account', 'components', 'transactiontype'
)->leftJoin(
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
)->where('transaction_types.type', 'Withdrawal')->where(
'date', '>=', $repetition->startdate->format('Y-m-d')
)->where('date', '<=', $repetition->enddate->format('Y-m-d'))->orderBy('date', 'DESC')->orderBy(
'id', 'DESC'
)->get(['transaction_journals.*']);
$set = $repetition->limit->budget
->transactionjournals()
->withRelevantData()
->transactionTypes(['Withdrawal'])
->after($repetition->startdate)
->before($repetition->enddate)
->defaultSorting()
->get(['transaction_journals.*']);
$result[0] = [
'date' => $repetition->periodShow(),
@@ -93,8 +90,10 @@ class Budget implements BudgetInterface
}
/**
*
*
* @param \Budget $budget
* @param bool $useSessionDates
* @param bool $useSessionDates
*
* @return array|mixed
* @throws \Firefly\Exception\FireflyException
@@ -102,15 +101,15 @@ class Budget implements BudgetInterface
public function organizeRepetitions(\Budget $budget, $useSessionDates = false)
{
$sessionStart = \Session::get('start');
$sessionEnd = \Session::get('end');
$sessionEnd = \Session::get('end');
$result = [];
$result = [];
$inRepetition = [];
// get the limits:
if ($useSessionDates) {
$limits = $budget->limits()->where('startdate', '>=', $sessionStart->format('Y-m-d'))->where(
'startdate', '<=', $sessionEnd->format('Y-m-d')
'startdate', '<=', $sessionEnd->format('Y-m-d')
)->get();
} else {
$limits = $budget->limits;
@@ -119,7 +118,7 @@ class Budget implements BudgetInterface
/** @var \Limit $limit */
foreach ($limits as $limit) {
foreach ($limit->limitrepetitions as $repetition) {
$order = $repetition->periodOrder();
$order = $repetition->periodOrder();
$result[$order] = [
'date' => $repetition->periodShow(),
'limitrepetition' => $repetition,
@@ -127,16 +126,14 @@ class Budget implements BudgetInterface
'journals' => [],
'paginated' => false
];
$transactions = [];
$set = $budget->transactionjournals()->with(
'transactions', 'transactions.account', 'components', 'transactiontype'
)->leftJoin(
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
)->where('transaction_types.type', 'Withdrawal')->where(
'date', '>=', $repetition->startdate->format('Y-m-d')
)->where('date', '<=', $repetition->enddate->format('Y-m-d'))->orderBy('date', 'DESC')->orderBy(
'id', 'DESC'
)->get(['transaction_journals.*']);
$transactions = [];
$set = $budget->transactionjournals()
->withRelevantData()
->transactionTypes(['Withdrawal'])
->after($repetition->startdate)
->before($repetition->enddate)
->defaultSorting()
->get(['transaction_journals.*']);
foreach ($set as $entry) {
$transactions[] = $entry;
$inRepetition[] = $entry->id;
@@ -146,30 +143,17 @@ class Budget implements BudgetInterface
}
if ($useSessionDates === false) {
$query = $budget->transactionjournals()->withRelevantData()->defaultSorting();
if (count($inRepetition) > 0) {
$query = $budget->transactionjournals()->with(
'transactions', 'transactions.account', 'components', 'transactiontype',
'transactions.account.accounttype'
)->whereNotIn(
'transaction_journals.id', $inRepetition
)->orderBy('date', 'DESC')->orderBy(
'transaction_journals.id', 'DESC'
);
} else {
$query = $budget->transactionjournals()->with(
'transactions', 'transactions.account', 'components', 'transactiontype',
'transactions.account.accounttype'
)->orderBy('date', 'DESC')->orderBy(
'transaction_journals.id', 'DESC'
);
$query->whereNotIn('transaction_journals.id', $inRepetition);
}
// build paginator:
$perPage = 25;
$perPage = 25;
$totalItems = $query->count();
$page = intval(\Input::get('page')) > 1 ? intval(\Input::get('page')) : 1;
$skip = ($page - 1) * $perPage;
$set = $query->skip($skip)->take($perPage)->get();
$page = intval(\Input::get('page')) > 1 ? intval(\Input::get('page')) : 1;
$skip = ($page - 1) * $perPage;
$set = $query->skip($skip)->take($perPage)->get();
// stupid paginator!
$items = [];
@@ -177,9 +161,12 @@ class Budget implements BudgetInterface
foreach ($set as $item) {
$items[] = $item;
}
$paginator = \Paginator::make($items, $totalItems, $perPage);
$result['0000'] = ['date' => 'Not in an envelope', 'limit' => null, 'paginated' => true,
'journals' => $paginator];
$paginator = \Paginator::make($items, $totalItems, $perPage);
$result['0000'] = [
'date' => 'Not in an envelope',
'limit' => null,
'paginated' => true,
'journals' => $paginator];
}
krsort($result);
@@ -196,13 +183,12 @@ class Budget implements BudgetInterface
$inRepetitions = [];
foreach ($budget->limits as $limit) {
foreach ($limit->limitrepetitions as $repetition) {
$set = $budget->transactionjournals()->leftJoin(
'transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'
)->where('transaction_types.type', 'Withdrawal')->where(
'date', '>=', $repetition->startdate->format('Y-m-d')
)->where('date', '<=', $repetition->enddate->format('Y-m-d'))->orderBy('date', 'DESC')->get(
['transaction_journals.id']
);
$set = $budget->transactionjournals()
->transactionTypes(['Withdrawal'])
->after($repetition->startdate)
->before($repetition->enddate)
->defaultSorting()
->get(['transaction_journals.id']);
foreach ($set as $item) {
$inRepetitions[] = $item->id;
}
@@ -210,21 +196,17 @@ class Budget implements BudgetInterface
}
$query = $budget->transactionjournals()->with(
'transactions', 'transactions.account', 'components', 'transactiontype',
'transactions.account.accounttype'
)->whereNotIn(
'transaction_journals.id', $inRepetitions
)->orderBy('date', 'DESC')->orderBy(
'transaction_journals.id', 'DESC'
);
$query = $budget->transactionjournals()
->withRelevantData()
->whereNotIn('transaction_journals.id', $inRepetitions)
->defaultSorting();
// build paginator:
$perPage = 25;
$perPage = 25;
$totalItems = $query->count();
$page = intval(\Input::get('page')) > 1 ? intval(\Input::get('page')) : 1;
$skip = ($page - 1) * $perPage;
$set = $query->skip($skip)->take($perPage)->get();
$page = intval(\Input::get('page')) > 1 ? intval(\Input::get('page')) : 1;
$skip = ($page - 1) * $perPage;
$set = $query->skip($skip)->take($perPage)->get();
// stupid paginator!
$items = [];
@@ -233,8 +215,12 @@ class Budget implements BudgetInterface
$items[] = $item;
}
$paginator = \Paginator::make($items, $totalItems, $perPage);
$result = [0 => ['date' => 'Not in an envelope', 'limit' => null, 'paginated' => true,
'journals' => $paginator]];
$result = [0 => [
'date' => 'Not in an envelope',
'limit' => null,
'paginated' => true,
'journals' => $paginator
]];
return $result;
}

View File

@@ -23,7 +23,7 @@ interface BudgetInterface
*
* @return mixed
*/
public function organizeRepetition($repetitionId);
public function organizeRepetition(\LimitRepetition $repetition);
/**

View File

@@ -4,6 +4,7 @@ namespace Firefly\Helper\Controllers;
use Carbon\Carbon;
use Firefly\Exception\FireflyException;
use Illuminate\Support\Collection;
/**
* Class Chart
@@ -23,8 +24,8 @@ class Chart implements ChartInterface
public function account(\Account $account, Carbon $start, Carbon $end)
{
$current = clone $start;
$today = new Carbon;
$return = ['name' => $account->name, 'id' => $account->id, 'data' => []];
$today = new Carbon;
$return = ['name' => $account->name, 'id' => $account->id, 'data' => []];
while ($current <= $end) {
if ($current > $today) {
@@ -106,7 +107,7 @@ class Chart implements ChartInterface
$data = [];
$budgets = \Auth::user()->budgets()->with(
$budgets = \Auth::user()->budgets()->with(
['limits' => function ($q) {
$q->orderBy('limits.startdate', 'ASC');
}, 'limits.limitrepetitions' => function ($q) use ($start) {
@@ -117,6 +118,7 @@ class Chart implements ChartInterface
$limitInPeriod = '';
$spentInPeriod = '';
/** @var \Budget $budget */
foreach ($budgets as $budget) {
$budget->count = 0;
foreach ($budget->limits as $limit) {
@@ -129,21 +131,38 @@ class Chart implements ChartInterface
$rep->left = $rep->left();
// overspent:
if ($rep->left < 0) {
$rep->spent = ($rep->left * -1) + $rep->amount;
$rep->overspent = $rep->left * -1;
$total = $rep->spent + $rep->overspent;
$rep->spent_pct = round(($rep->spent / $total) * 100);
$rep->spent = ($rep->left * -1) + $rep->amount;
$rep->overspent = $rep->left * -1;
$total = $rep->spent + $rep->overspent;
$rep->spent_pct = round(($rep->spent / $total) * 100);
$rep->overspent_pct = 100 - $rep->spent_pct;
} else {
$rep->spent = $rep->amount - $rep->left;
$rep->spent = $rep->amount - $rep->left;
$rep->spent_pct = round(($rep->spent / $rep->amount) * 100);
$rep->left_pct = 100 - $rep->spent_pct;
$rep->left_pct = 100 - $rep->spent_pct;
}
}
$budget->count += count($limit->limitrepetitions);
}
if ($budget->count == 0) {
// get expenses in period until today, starting at $start.
$end = \Session::get('end');
$expenses = $budget->transactionjournals()->after($start)->before($end)
->transactionTypes(
['Withdrawal']
)->get();
$budget->spentInPeriod = 0;
/** @var \TransactionJournal $expense */
foreach ($expenses as $expense) {
$transaction = $expense->transactions[1];
if (!is_null($transaction)) {
$budget->spentInPeriod += floatval($transaction->amount);
}
}
}
}
@@ -161,16 +180,25 @@ class Chart implements ChartInterface
foreach ($budgets as $budget) {
if ($budget->count > 0) {
$data['labels'][] = wordwrap($budget->name, 12, "<br>");
}
foreach ($budget->limits as $limit) {
foreach ($limit->limitrepetitions as $rep) {
//0: envelope for period:
$amount = floatval($rep->amount);
$spent = $rep->spent;
$color = $spent > $amount ? '#FF0000' : null;
$data['series'][0]['data'][] = ['y' => $amount, 'id' => 'amount-' . $rep->id];
$data['series'][1]['data'][] = ['y' => $rep->spent, 'color' => $color, 'id' => 'spent-' . $rep->id];
$data['labels'][] = $budget->name;
foreach ($budget->limits as $limit) {
foreach ($limit->limitrepetitions as $rep) {
//0: envelope for period:
$amount = floatval($rep->amount);
$spent = $rep->spent;
$color = $spent > $amount ? '#FF0000' : null;
$data['series'][0]['data'][] = ['y' => $amount, 'id' => 'amount-' . $rep->id];
$data['series'][1]['data'][] = ['y' => $rep->spent, 'color' => $color,
'id' => 'spent-' . $rep->id];
}
}
} else {
// add for "empty" budget:
if ($budget->spentInPeriod > 0) {
$data['labels'][] = $budget->name;
$data['series'][0]['data'][] = ['y' => null, 'id' => 'amount-norep-' . $budget->id];
$data['series'][1]['data'][] = ['y' => $budget->spentInPeriod,
'id' => 'spent-norep-' . $budget->id];
}
}
@@ -211,10 +239,10 @@ class Chart implements ChartInterface
. ' transactions!');
}
$transaction = $journal->transactions[0];
$amount = floatval($transaction->amount);
$amount = floatval($transaction->amount);
// get budget from journal:
$category = $journal->categories()->first();
$category = $journal->categories()->first();
$categoryName = is_null($category) ? '(no category)' : $category->name;
$result[$categoryName] = isset($result[$categoryName]) ? $result[$categoryName] + floatval($amount)
@@ -335,7 +363,7 @@ class Chart implements ChartInterface
// get sum for current range:
$journals = \TransactionJournal::
$journals = \TransactionJournal::
with(
['transactions' => function ($q) {
$q->where('amount', '>', 0);
@@ -360,7 +388,7 @@ class Chart implements ChartInterface
. ' transactions!');
}
$transaction = $journal->transactions[0];
$amount = floatval($transaction->amount);
$amount = floatval($transaction->amount);
$currentSum += $amount;
}
@@ -401,4 +429,150 @@ class Chart implements ChartInterface
}
/**
* @param \Budget $budget
* @param Carbon $date
*
* @return float|null
*/
public function spentOnDay(\Budget $budget, Carbon $date)
{
return floatval(
\Transaction::
leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin(
'component_transaction_journal', 'component_transaction_journal.transaction_journal_id', '=',
'transaction_journals.id'
)->where('component_transaction_journal.component_id', '=', $budget->id)->where(
'transaction_journals.date', $date->format('Y-m-d')
)->where('amount', '>', 0)->sum('amount')
);
}
/**
* @param \Budget $budget
*
* @return int[]
*/
public function allJournalsInBudgetEnvelope(\Budget $budget)
{
$inRepetitions = [];
foreach ($budget->limits as $limit) {
foreach ($limit->limitrepetitions as $repetition) {
$set = $budget
->transactionjournals()
->transactionTypes(['Withdrawal'])
->after($repetition->startdate)
->before($repetition->enddate)
->get(['transaction_journals.id']);
foreach ($set as $item) {
$inRepetitions[] = $item->id;
}
}
}
return $inRepetitions;
}
/**
* @param \Budget $budget
* @param array $ids
*
* @return mixed|void
*/
public function journalsNotInSet(\Budget $budget, array $ids)
{
$query = $budget->transactionjournals()
->whereNotIn('transaction_journals.id', $ids)
->orderBy('date', 'DESC')
->orderBy('transaction_journals.id', 'DESC');
$result = $query->get(['transaction_journals.id']);
$set = [];
foreach ($result as $entry) {
$set[] = $entry->id;
}
return $set;
}
/**
* @param array $set
*
* @return mixed
*/
public function transactionsByJournals(array $set)
{
$transactions = \Transaction::whereIn('transaction_journal_id', $set)
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->groupBy('transaction_journals.date')
->where('amount', '>', 0)->get(['transaction_journals.date', \DB::Raw('SUM(`amount`) as `aggregate`')]);
return $transactions;
}
/**
* Get all limit (LimitRepetitions) for a budget falling in a certain date range.
*
* @param \Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function limitsInRange(\Budget $budget, Carbon $start, Carbon $end)
{
$reps = new Collection;
/** @var \Limit $limit */
foreach ($budget->limits as $limit) {
$set = $limit->limitrepetitions()->where(
function ($q) use ($start, $end) {
// startdate is between range
$q->where(
function ($q) use ($start, $end) {
$q->where('startdate', '>=', $start->format('Y-m-d'));
$q->where('startdate', '<=', $end->format('Y-m-d'));
}
);
// or enddate is between range.
$q->orWhere(
function ($q) use ($start, $end) {
$q->where('enddate', '>=', $start->format('Y-m-d'));
$q->where('enddate', '<=', $end->format('Y-m-d'));
}
);
}
)->get();
$reps = $reps->merge($set);
}
return $reps;
}
/**
* We check how much money has been spend on the limitrepetition (aka: the current envelope) in the period denoted.
* Aka, we have a certain amount of money in an envelope and we wish to know how much we've spent between the dates
* entered. This can be a partial match with the date range of the envelope or no match at all.
*
* @param \LimitRepetition $repetition
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
public function spentOnLimitRepetitionBetweenDates(\LimitRepetition $repetition, Carbon $start, Carbon $end) {
return floatval(
\Transaction::
leftJoin('transaction_journals', 'transaction_journals.id', '=','transactions.transaction_journal_id')
->leftJoin('component_transaction_journal', 'component_transaction_journal.transaction_journal_id','=',
'transaction_journals.id'
)->where('component_transaction_journal.component_id', '=', $repetition->limit->budget->id)->where(
'transaction_journals.date', '>=', $start->format('Y-m-d')
)->where('transaction_journals.date', '<=', $end->format('Y-m-d'))->where(
'amount', '>', 0
)->sum('amount')) ;
}
}

View File

@@ -54,4 +54,61 @@ interface ChartInterface
* @return mixed
*/
public function categoryShowChart(\Category $category, $range, Carbon $start, Carbon $end);
/**
* @param \Budget $budget
* @param Carbon $date
*
* @return float|null
*/
public function spentOnDay(\Budget $budget, Carbon $date);
/**
* @param \Budget $budget
*
* @return int[]
*/
public function allJournalsInBudgetEnvelope(\Budget $budget);
/**
* @param \Budget $budget
* @param array $ids
*
* @return mixed
*/
public function journalsNotInSet(\Budget $budget, array $ids);
/**
* @param array $set
*
* @return mixed
*/
public function transactionsByJournals(array $set);
/**
* Get all limit (LimitRepetitions) for a budget falling in a certain date range.
*
* @param \Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function limitsInRange(\Budget $budget, Carbon $start, Carbon $end);
/**
* We check how much money has been spend on the limitrepetition (aka: the current envelope) in the period denoted.
* Aka, we have a certain amount of money in an envelope and we wish to know how much we've spent between the dates
* entered. This can be a partial match with the date range of the envelope or no match at all.
*
* @param \LimitRepetition $repetition
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
public function spentOnLimitRepetitionBetweenDates(\LimitRepetition $repetition, Carbon $start, Carbon $end);
}

View File

@@ -1,47 +0,0 @@
<?php
namespace Firefly\Helper\Form;
/**
* Class FormHelper
*
* @package Firefly\Form
*/
class FormHelper
{
/**
* @param null $value
*
* @return string
*/
public function budget($value = null)
{
$str = '<select name="budget_id" class="form-control">';
$str .= '<option value="0" label="(no budget)"';
if (is_null($value) || intval($value) == 0) {
$str .= ' selected="selected"';
}
$str .= '</option>';
/** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budgets */
$budgets = \App::make('Firefly\Storage\Budget\BudgetRepositoryInterface');
$list = $budgets->getAsSelectList();
foreach ($list as $id => $name) {
$str .= '<option value="' . e($id) . '" label="' . e($name) . '"';
if ($id == intval($value)) {
$str .= ' selected="selected"';
}
$str .= '>' . e($name) . '</option>';
}
$str .= '</select>';
return $str;
}
}

View File

@@ -1,35 +0,0 @@
<?php
namespace Firefly\Helper\Form;
use Illuminate\Events\Dispatcher;
/**
* Class FormTrigger
*
* @package Firefly\Helper\Form
*/
class FormTrigger
{
public function registerFormExtensions()
{
\Form::macro(
'budget', function () {
$helper = new FormHelper;
return $helper->budget();
}
);
}
/**
* @param Dispatcher $events
*/
public function subscribe(Dispatcher $events)
{
$events->listen('laravel.booted', 'Firefly\Helper\Form\FormTrigger@registerFormExtensions');
}
}

View File

@@ -1,327 +0,0 @@
<?php
namespace Firefly\Helper\Migration;
use Carbon\Carbon;
use Firefly\Exception\FireflyException;
/**
* Class MigrationHelper
*
* @package Firefly\Helper\Migration
*/
class MigrationHelper implements MigrationHelperInterface
{
protected $path;
protected $JSON;
protected $map = [];
/**
* @param $path
*
* @return mixed|void
*/
public function loadFile($path)
{
$this->path = $path;
}
/**
* @return bool
*/
public function validFile()
{
// file does not exist:
if (!file_exists($this->path)) {
\Log::error('Migration file ' . $this->path . ' does not exist!');
return false;
}
// load the content:
$content = file_get_contents($this->path);
if ($content === false) {
return false;
}
// parse the content
$this->JSON = json_decode($content);
if (is_null($this->JSON)) {
return false;
}
\Log::info('Migration file ' . $this->path . ' is valid!');
return true;
}
/**
* @return bool
*/
public function migrate()
{
\Log::info('Start of migration.');
\DB::beginTransaction();
try {
// create cash account:
$this->_createCashAccount();
$this->_importAccounts();
$this->_importComponents();
//$this->_importPiggybanks();
// create transactions:
$this->_importTransactions();
// create transfers:
$this->_importTransfers();
// create limits:
$this->_importLimits();
} catch (FireflyException $e) {
\DB::rollBack();
\Log::error('Rollback because of error!');
\Log::error($e->getMessage());
return false;
}
\DB::commit();
\Log::info('Done!');
return true;
}
/**
*
*/
protected function _createCashAccount()
{
$cashAT = \AccountType::where('description', 'Cash account')->first();
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
$cash = $accounts->store(['name' => 'Cash account', 'account_type' => $cashAT, 'active' => 0]);
\Log::info('Created cash account (#' . $cash->id . ')');
$this->map['cash'] = $cash;
}
/**
*
*/
protected function _importAccounts()
{
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
\Log::info('Going to import ' . count($this->JSON->accounts) . ' accounts.');
foreach ($this->JSON->accounts as $entry) {
// create account:
if ($entry->openingbalance == 0) {
$account = $accounts->store(['name' => $entry->name]);
} else {
$account = $accounts->storeWithInitialBalance(
['name' => $entry->name],
new Carbon($entry->openingbalancedate),
floatval($entry->openingbalance)
);
}
$this->map['accounts'][$entry->id] = $account;
\Log::info('Imported account "' . $entry->name . '" with balance ' . $entry->openingbalance);
}
}
/**
*
*/
protected function _importComponents()
{
$beneficiaryAT = \AccountType::where('description', 'Beneficiary account')->first();
foreach ($this->JSON->components as $entry) {
switch ($entry->type->type) {
case 'beneficiary':
/** @noinspection PhpParamsInspection */
$beneficiary = $this->_importBeneficiary($entry, $beneficiaryAT);
$this->map['accounts'][$entry->id] = $beneficiary;
break;
case 'category':
$component = $this->_importCategory($entry);
$this->map['categories'][$entry->id] = $component;
break;
case 'budget':
$component = $this->_importBudget($entry);
$this->map['budgets'][$entry->id] = $component;
break;
}
}
}
/**
* @param $component
* @param \AccountType $beneficiaryAT
*
* @return mixed
*/
protected function _importBeneficiary($component, \AccountType $beneficiaryAT)
{
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
return $accounts->store(
[
'name' => $component->name,
'account_type' => $beneficiaryAT
]
);
}
/**
* @param $component
*
* @return mixed
*/
protected function _importCategory($component)
{
/** @var \Firefly\Storage\Component\ComponentRepositoryInterface $components */
$components = \App::make('Firefly\Storage\Component\ComponentRepositoryInterface');
return $components->store(['name' => $component->name, 'class' => 'Category']);
}
/**
* @param $component
*
* @return mixed
*/
protected function _importBudget($component)
{
/** @var \Firefly\Storage\Component\ComponentRepositoryInterface $components */
$components = \App::make('Firefly\Storage\Component\ComponentRepositoryInterface');
return $components->store(['name' => $component->name, 'class' => 'Budget']);
}
/**
*
*/
protected function _importTransactions()
{
/** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $journals */
$journals = \App::make('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
// loop component_transaction to find beneficiaries, categories and budgets:
$beneficiaries = [];
$categories = [];
$budgets = [];
foreach ($this->JSON->component_transaction as $entry) {
// beneficiaries
if (isset($this->map['accounts'][$entry->component_id])) {
$beneficiaries[$entry->transaction_id] = $this->map['accounts'][$entry->component_id];
}
// categories
if (isset($this->map['categories'][$entry->component_id])) {
$categories[$entry->transaction_id] = $this->map['categories'][$entry->component_id];
}
// budgets:
if (isset($this->map['budgets'][$entry->component_id])) {
$budgets[$entry->transaction_id] = $this->map['budgets'][$entry->component_id];
}
}
foreach ($this->JSON->transactions as $entry) {
// to properly save the amount, do it times -1:
$amount = $entry->amount * -1;
/** @var \Account $fromAccount */
$fromAccount = isset($this->map['accounts'][$entry->account_id])
? $this->map['accounts'][$entry->account_id] : false;
/** @var \Account $toAccount */
$toAccount = isset($beneficiaries[$entry->id]) ? $beneficiaries[$entry->id] : $this->map['cash'];
$date = new Carbon($entry->date);
$journal = $journals->createSimpleJournal($fromAccount, $toAccount, $entry->description, $amount, $date);
// save budgets and categories, on the journal
if (isset($budgets[$entry->id])) {
$budget = $budgets[$entry->id];
$journal->budgets()->save($budget);
}
if (isset($categories[$entry->id])) {
$category = $categories[$entry->id];
$journal->categories()->save($category);
}
}
}
/**
*
*/
protected function _importTransfers()
{
/** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $journals */
$journals = \App::make('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
foreach ($this->JSON->transfers as $entry) {
// to properly save the amount, do it times 1 (?):
$amount = $entry->amount * -1;
/** @var \Account $fromAccount */
$fromAccount = isset($this->map['accounts'][$entry->accountfrom_id])
? $this->map['accounts'][$entry->accountto_id] : false;
/** @var \Account $toAccount */
$toAccount = isset($this->map['accounts'][$entry->accountto_id])
? $this->map['accounts'][$entry->accountfrom_id] : false;
$date = new Carbon($entry->date);
$journals->createSimpleJournal($fromAccount, $toAccount, $entry->description, $amount, $date);
}
}
/**
*
*/
protected function _importLimits()
{
\Log::info('Importing limits');
foreach ($this->JSON->limits as $entry) {
\Log::debug(
'Now at #' . $entry->id . ': EUR ' . $entry->amount . ' for month ' . $entry->date
. ' and componentID: ' . $entry->component_id
);
$budget = isset($this->map['budgets'][$entry->component_id]) ? $this->map['budgets'][$entry->component_id]
: null;
if (!is_null($budget)) {
\Log::debug('Found budget for this limit: #' . $budget->id . ', ' . $budget->name);
$limit = new \Limit;
$limit->budget()->associate($budget);
$limit->startdate = new Carbon($entry->date);
$limit->amount = floatval($entry->amount);
$limit->repeats = 0;
$limit->repeat_freq = 'monthly';
try {
$limit->save();
} catch (\Exception $e) {
}
} else {
\Log::warning('No budget for this limit!');
}
// create repeat thing should not be necessary.
}
}
}

View File

@@ -1,29 +0,0 @@
<?php
namespace Firefly\Helper\Migration;
/**
* Interface MigrationHelperInterface
*
* @package Firefly\Helper\Migration
*/
interface MigrationHelperInterface
{
/**
* @param $path
*
* @return mixed
*/
public function loadFile($path);
/**
* @return mixed
*/
public function validFile();
/**
* @return mixed
*/
public function migrate();
}

View File

@@ -0,0 +1,674 @@
<?php
namespace Firefly\Queue;
use Carbon\Carbon;
use Illuminate\Queue\Jobs\Job;
/**
* Class Import
*
* @package Firefly\Queue
*/
class Import
{
/** @var \Firefly\Storage\Account\AccountRepositoryInterface */
protected $_accounts;
/** @var \Firefly\Storage\Import\ImportRepositoryInterface */
protected $_repository;
/** @var \Firefly\Storage\Budget\BudgetRepositoryInterface */
protected $_budgets;
/** @var \Firefly\Storage\Category\CategoryRepositoryInterface */
protected $_categories;
/** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface */
protected $_journals;
/** @var \Firefly\Storage\Limit\LimitRepositoryInterface */
protected $_limits;
/** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface */
protected $_piggybanks;
/** @var \Firefly\Storage\RecurringTransaction\RecurringTransactionRepositoryInterface */
protected $_recurring;
/**
*
*/
public function __construct()
{
$this->_accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
$this->_repository = \App::make('Firefly\Storage\Import\ImportRepositoryInterface');
$this->_budgets = \App::make('Firefly\Storage\Budget\BudgetRepositoryInterface');
$this->_categories = \App::make('Firefly\Storage\Category\CategoryRepositoryInterface');
$this->_journals = \App::make('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
$this->_limits = \App::make('Firefly\Storage\Limit\LimitRepositoryInterface');
$this->_piggybanks = \App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
$this->_recurring = \App::make('Firefly\Storage\RecurringTransaction\RecurringTransactionRepositoryInterface');
}
/**
* @param Job $job
* @param array $payload
*/
public function cleanImportAccount(Job $job, array $payload)
{
$importAccountType = $this->_accounts->findAccountType('Import account');
$importAccounts = $this->_accounts->getByAccountType($importAccountType);
if (count($importAccounts) == 0) {
$job->delete();
} else if (count($importAccounts) == 1) {
/** @var \Account $importAccount */
$importAccount = $importAccounts[0];
$transactions = $importAccount->transactions()->get();
/** @var \Transaction $transaction */
foreach ($transactions as $transaction) {
$transaction->account()->associate($importAccount);
$transaction->save();
}
\Log::debug('Updated ' . count($transactions) . ' transactions from Import Account to cash.');
}
$job->delete();
}
/**
* @param Job $job
* @param array $payload
*
* @throws \Firefly\Exception\FireflyException
*/
public function importComponent(Job $job, array $payload)
{
\Log::debug('Going to import component "' . $payload['data']['name'] . '".');
switch ($payload['data']['type']['type']) {
case 'beneficiary':
$payload['class'] = 'Account';
$payload['data']['account_type'] = 'Beneficiary account';
$this->importAccount($job, $payload);
break;
case 'budget':
$this->importBudget($job, $payload);
break;
case 'category':
$this->importCategory($job, $payload);
break;
case 'payer':
$job->delete();
break;
default:
$job->delete();
break;
}
}
/**
* Import a personal account or beneficiary as a new account.
*
* @param Job $job
* @param array $payload
*/
public function importAccount(Job $job, array $payload)
{
/** @var \Importmap $importMap */
$importMap = $this->_repository->findImportmap($payload['mapID']);
$user = $importMap->user;
$this->overruleUser($user);
// maybe we've already imported this account:
$importEntry = $this->_repository->findImportEntry($importMap, 'Account', intval($payload['data']['id']));
// if so, delete job and return:
if (!is_null($importEntry)) {
$job->delete();
return;
}
// if we try to import a beneficiary, Firefly will "merge" already,
// so we don't care:
if (isset($payload['data']['account_type']) && $payload['data']['account_type'] == 'Beneficiary account') {
// store beneficiary
$acct = $this->_accounts->createOrFindBeneficiary($payload['data']['name']);
\Log::debug('Imported ' . $payload['class'] . ' "' . $payload['data']['name'] . '".');
$this->_repository->store($importMap, 'Account', $payload['data']['id'], $acct->id);
$job->delete();
return;
}
// but we cannot merge accounts, so we need to search first:
$acct = $this->_accounts->findByName($payload['data']['name']);
if (is_null($acct)) {
// store new one!
$acct = $this->_accounts->store((array)$payload['data']);
\Log::debug('Imported ' . $payload['class'] . ' "' . $payload['data']['name'] . '".');
$this->_repository->store($importMap, 'Account', $payload['data']['id'], $acct->id);
} else {
// use previous one!
\Log::debug('Already imported ' . $payload['class'] . ' "' . $payload['data']['name'] . '".');
$this->_repository->store($importMap, 'Account', $payload['data']['id'], $acct->id);
}
// and delete the job
$job->delete();
}
/**
* @param \User $user
*/
protected function overruleUser(\User $user)
{
$this->_accounts->overruleUser($user);
$this->_budgets->overruleUser($user);
$this->_categories->overruleUser($user);
$this->_journals->overruleUser($user);
$this->_limits->overruleUser($user);
$this->_repository->overruleUser($user);
$this->_piggybanks->overruleUser($user);
$this->_recurring->overruleUser($user);
}
/**
* Import a budget into Firefly.
*
* @param Job $job
* @param array $payload
*/
public function importBudget(Job $job, array $payload)
{
/** @var \Importmap $importMap */
$importMap = $this->_repository->findImportmap($payload['mapID']);
$user = $importMap->user;
$this->overruleUser($user);
// maybe we've already imported this budget:
$bdg = $this->_budgets->findByName($payload['data']['name']);
if (is_null($bdg)) {
// we have not!
$bdg = $this->_budgets->store((array)$payload['data']);
$this->_repository->store($importMap, 'Budget', $payload['data']['id'], $bdg->id);
\Log::debug('Imported budget "' . $payload['data']['name'] . '".');
} else {
// we have!
$this->_repository->store($importMap, 'Budget', $payload['data']['id'], $bdg->id);
\Log::debug('Already had budget "' . $payload['data']['name'] . '".');
}
// delete job.
$job->delete();
}
/**
* Import a category into Firefly.
*
* @param Job $job
* @param array $payload
*/
public function importCategory(Job $job, array $payload)
{
/** @var \Importmap $importMap */
$importMap = $this->_repository->findImportmap($payload['mapID']);
$user = $importMap->user;
$this->overruleUser($user);
// try to find budget:
$current = $this->_categories->findByName($payload['data']['name']);
if (is_null($current)) {
$cat = $this->_categories->store((array)$payload['data']);
$this->_repository->store($importMap, 'Category', $payload['data']['id'], $cat->id);
\Log::debug('Imported category "' . $payload['data']['name'] . '".');
} else {
$this->_repository->store($importMap, 'Category', $payload['data']['id'], $current->id);
\Log::debug('Already had category "' . $payload['data']['name'] . '".');
}
$job->delete();
}
/**
* @param Job $job
* @param array $payload
*/
public function importComponentTransaction(Job $job, array $payload)
{
if ($job->attempts() > 1) {
\Log::info('importComponentTransaction Job running for ' . $job->attempts() . 'th time!');
}
if ($job->attempts() > 30) {
\Log::error('importComponentTransaction Job running for ' . $job->attempts() . 'th time, so KILL!');
$job->delete();
return;
}
$oldComponentId = intval($payload['data']['component_id']);
$oldTransactionId = intval($payload['data']['transaction_id']);
/** @var \Importmap $importMap */
$importMap = $this->_repository->findImportmap($payload['mapID']);
$user = $importMap->user;
$this->overruleUser($user);
$oldTransactionMap = $this->_repository->findImportEntry($importMap, 'Transaction', $oldTransactionId);
// we don't know what the component is, so we need to search for it in a set
// of possible types (Account / Beneficiary, Budget, Category)
/** @var \Importentry $oldComponentMap */
$oldComponentMap = $this->_repository->findImportComponentMap($importMap, $oldComponentId);
if (is_null($oldComponentMap)) {
\Log::debug('importComponentTransaction Could not run this one, waiting for five minutes...');
$job->release(300);
return;
}
$journal = $this->_journals->find($oldTransactionMap->new);
\Log::debug('Going to update ' . $journal->description);
// find the cash account:
switch ($oldComponentMap->class) {
case 'Budget':
// budget thing link:
$budget = $this->_budgets->find($oldComponentMap->new);
\Log::debug('Updating transactions budget.');
$journal->budgets()->save($budget);
$journal->save();
\Log::debug('Updated transactions budget.');
break;
case 'Category':
$category = $this->_categories->find($oldComponentMap->new);
$journal = $this->_journals->find($oldTransactionMap->new);
\Log::info('Updating transactions category (old id is #' . $oldComponentMap->old . ').');
if (!is_null($category)) {
$journal->categories()->save($category);
$journal->save();
\Log::info('Updated transactions category.');
} else {
\Log::error('No category mapping to old id #' . $oldComponentMap->old . ' found. Release for 5m!');
$job->release(300);
return;
}
break;
case 'Account':
\Log::info('Updating transactions Account.');
$account = $this->_accounts->find($oldComponentMap->new);
$journal = $this->_journals->find($oldTransactionMap->new);
if (is_null($account)) {
\Log::debug('Cash account is needed.');
$account = $this->_accounts->getCashAccount();
\Log::info($account);
}
foreach ($journal->transactions as $transaction) {
if ($transaction->account()->first()->account_type_id == 5) {
$transaction->account()->associate($account);
$transaction->save();
\Log::debug(
'Updated transactions (#' . $journal->id . '), #' . $transaction->id . '\'s Account.'
);
}
}
break;
}
$job->delete();
}
/**
* @param Job $job
* @param array $payload
*/
public function importLimit(Job $job, array $payload)
{
if ($job->attempts() > 30) {
\Log::error('importLimit Job running for ' . $job->attempts() . 'th time, so KILL!');
$job->delete();
return;
}
/** @var \Importmap $importMap */
$importMap = $this->_repository->findImportmap($payload['mapID']);
$user = $importMap->user;
$this->overruleUser($user);
// find the budget this limit is part of:
$importEntry = $this->_repository->findImportEntry(
$importMap, 'Budget',
intval($payload['data']['component_id'])
);
// budget is not yet imported:
if (is_null($importEntry)) {
\Log::debug(
'importLimit Cannot import limit #' . $payload['data']['id'] .
' because the budget is not here yet. #' . $job->attempts()
);
$job->release(300);
return;
}
// find similar limit:
\Log::debug('Trying to find budget with ID #' . $importEntry->new . ', based on entry #' . $importEntry->id);
$budget = $this->_budgets->find($importEntry->new);
if (!is_null($budget)) {
$current = $this->_limits->findByBudgetAndDate($budget, new Carbon($payload['data']['date']));
if (is_null($current)) {
// create it!
$payload['data']['budget_id'] = $budget->id;
$payload['data']['startdate'] = $payload['data']['date'];
$payload['data']['period'] = 'monthly';
$lim = $this->_limits->store((array)$payload['data']);
$this->_repository->store($importMap, 'Limit', $payload['data']['id'], $lim->id);
\Event::fire('limits.store', [$lim]);
\Log::debug('Imported ' . $payload['class'] . ', for ' . $budget->name . ' (' . $lim->startdate . ').');
} else {
// already has!
$this->_repository->store($importMap, 'Budget', $payload['data']['id'], $current->id);
\Log::debug(
'Already had ' . $payload['class'] . ', for ' . $budget->name . ' (' . $current->startdate . ').'
);
}
} else {
// cannot import component limit, no longer supported.
\Log::error('Cannot import limit for other than budget!');
}
$job->delete();
}
/**
* @param Job $job
* @param array $payload
*/
public function importPiggybank(Job $job, array $payload)
{
/** @var \Importmap $importMap */
$importMap = $this->_repository->findImportmap($payload['mapID']);
$user = $importMap->user;
$this->overruleUser($user);
// try to find related piggybank:
$current = $this->_piggybanks->findByName($payload['data']['name']);
// we need an account to go with this piggy bank:
$set = $this->_accounts->getActiveDefault();
if (count($set) > 0) {
$account = $set[0];
$payload['data']['account_id'] = $account->id;
} else {
\Log::debug('Released job for work in five minutes...');
$job->release(300);
return;
}
if (is_null($current)) {
$payload['data']['targetamount'] = floatval($payload['data']['target']);
$payload['data']['repeats'] = 0;
$payload['data']['rep_every'] = 1;
$payload['data']['reminder_skip'] = 1;
$payload['data']['rep_times'] = 1;
$piggy = $this->_piggybanks->store((array)$payload['data']);
$this->_repository->store($importMap, 'Piggybank', $payload['data']['id'], $piggy->id);
\Log::debug('Imported ' . $payload['class'] . ' "' . $payload['data']['name'] . '".');
\Event::fire('piggybanks.store', [$piggy]);
} else {
$this->_repository->store($importMap, 'Piggybank', $payload['data']['id'], $current->id);
\Log::debug('Already had ' . $payload['class'] . ' "' . $payload['data']['name'] . '".');
}
$job->delete();
}
/**
* @param Job $job
* @param array $payload
*/
public function importPredictable(Job $job, array $payload)
{
/** @var \Importmap $importMap */
$importMap = $this->_repository->findImportmap($payload['mapID']);
$user = $importMap->user;
$this->overruleUser($user);
// try to find related recurring transaction:
$current = $this->_recurring->findByName($payload['data']['description']);
if (is_null($current)) {
$payload['data']['name'] = $payload['data']['description'];
$payload['data']['match'] = join(',', explode(' ', $payload['data']['description']));
$pct = intval($payload['data']['pct']);
$payload['data']['amount_min'] = floatval($payload['data']['amount']) * ($pct / 100) * -1;
$payload['data']['amount_max'] = floatval($payload['data']['amount']) * (1 + ($pct / 100)) * -1;
$payload['data']['date'] = date('Y-m-') . $payload['data']['dom'];
$payload['data']['repeat_freq'] = 'monthly';
$payload['data']['active'] = intval($payload['data']['inactive']) == 1 ? 0 : 1;
$payload['data']['automatch'] = 1;
$recur = $this->_recurring->store((array)$payload['data']);
$this->_repository->store($importMap, 'RecurringTransaction', $payload['data']['id'], $recur->id);
\Log::debug('Imported ' . $payload['class'] . ' "' . $payload['data']['name'] . '".');
} else {
$this->_repository->store($importMap, 'RecurringTransaction', $payload['data']['id'], $current->id);
\Log::debug('Already had ' . $payload['class'] . ' "' . $payload['data']['description'] . '".');
}
$job->delete();
}
/**
* @param Job $job
* @param array $payload
*/
public function importSetting(Job $job, array $payload)
{
switch ($payload['data']['name']) {
default:
$job->delete();
return;
break;
case 'piggyAccount':
// if we have this account, update all piggy banks:
$accountID = intval($payload['data']['value']);
/** @var \Importmap $importMap */
$importMap = $this->_repository->findImportmap($payload['mapID']);
$user = $importMap->user;
$this->overruleUser($user);
$importEntry = $this->_repository->findImportEntry($importMap, 'Account', $accountID);
if ($importEntry) {
$all = $this->_piggybanks->get();
$account = $this->_accounts->find($importEntry->new);
\Log::debug('Updating all piggybanks, found the right setting.');
foreach ($all as $piggy) {
$piggy->account()->associate($account);
unset($piggy->leftInAccount); //??
$piggy->save();
}
} else {
\Log::debug('importSetting wait five minutes and try again...');
$job->release(300);
}
break;
}
$job->delete();
}
/**
* @param Job $job
* @param array $payload
*/
public function importTransaction(Job $job, array $payload)
{
/** @var \Importmap $importMap */
$importMap = $this->_repository->findImportmap($payload['mapID']);
$user = $importMap->user;
$this->overruleUser($user);
// find or create the account type for the import account.
// find or create the account for the import account.
$accountType = $this->_accounts->findAccountType('Import account');
$importAccount = $this->_accounts->createOrFind('Import account', $accountType);
// if amount is more than zero, move from $importAccount
$amount = floatval($payload['data']['amount']);
$accountEntry = $this->_repository->findImportEntry(
$importMap, 'Account',
intval($payload['data']['account_id'])
);
$personalAccount = $this->_accounts->find($accountEntry->new);
if ($amount < 0) {
// if amount is less than zero, move to $importAccount
$accountFrom = $personalAccount;
$accountTo = $importAccount;
} else {
$accountFrom = $importAccount;
$accountTo = $personalAccount;
}
$amount = $amount < 0 ? $amount * -1 : $amount;
$date = new Carbon($payload['data']['date']);
// find a journal?
$current = $this->_repository->findImportEntry($importMap, 'Transaction', intval($payload['data']['id']));
if (is_null($current)) {
$journal = $this->_journals->createSimpleJournal(
$accountFrom, $accountTo,
$payload['data']['description'], $amount, $date
);
$this->_repository->store($importMap, 'Transaction', $payload['data']['id'], $journal->id);
\Log::debug(
'Imported transaction "' . $payload['data']['description'] . '" (' . $journal->date->format('Y-m-d')
. ').'
);
} else {
// do nothing.
\Log::debug('ALREADY imported transaction "' . $payload['data']['description'] . '".');
}
$job->delete();
}
/**
* @param Job $job
* @param array $payload
*/
public function importTransfer(Job $job, array $payload)
{
/** @var \Importmap $importMap */
$importMap = $this->_repository->findImportmap($payload['mapID']);
$user = $importMap->user;
$this->overruleUser($user);
// from account:
$oldFromAccountID = intval($payload['data']['accountfrom_id']);
$oldFromAccountEntry = $this->_repository->findImportEntry($importMap, 'Account', $oldFromAccountID);
$accountFrom = $this->_accounts->find($oldFromAccountEntry->new);
// to account:
$oldToAccountID = intval($payload['data']['accountto_id']);
$oldToAccountEntry = $this->_repository->findImportEntry($importMap, 'Account', $oldToAccountID);
$accountTo = $this->_accounts->find($oldToAccountEntry->new);
if (!is_null($accountFrom) && !is_null($accountTo)) {
$amount = floatval($payload['data']['amount']);
$date = new Carbon($payload['data']['date']);
$journal = $this->_journals->createSimpleJournal(
$accountFrom, $accountTo, $payload['data']['description'],
$amount, $date
);
\Log::debug('Imported transfer "' . $payload['data']['description'] . '".');
$job->delete();
} else {
$job->release(5);
}
}
/**
* @param Job $job
* @param $payload
*/
public function start(Job $job, array $payload)
{
\Log::debug('Start with job "start"');
$user = \User::find($payload['user']);
$filename = $payload['file'];
if (file_exists($filename)) {
// we are able to process the file!
// make an import map. Which is some kind of object because we use queues.
$importMap = new \Importmap;
$importMap->user()->associate($user);
$importMap->file = $filename;
$importMap->save();
// we can now launch a billion jobs importing every little thing into Firefly III
$raw = file_get_contents($filename);
$JSON = json_decode($raw);
$classes = ['accounts', 'components', 'limits', 'piggybanks',
'predictables', 'settings', 'transactions', 'transfers'];
foreach ($classes as $classes_plural) {
$class = ucfirst(\Str::singular($classes_plural));
\Log::debug('Create job to import all ' . $classes_plural);
foreach ($JSON->$classes_plural as $entry) {
\Log::debug('Create job to import single ' . $class);
$fn = 'import' . $class;
$jobFunction = 'Firefly\Queue\Import@' . $fn;
\Queue::push($jobFunction, ['data' => $entry, 'class' => $class, 'mapID' => $importMap->id]);
}
}
// , components, limits, piggybanks, predictables, settings, transactions, transfers
// component_predictables, component_transactions, component_transfers
$count = count($JSON->component_transaction);
foreach ($JSON->component_transaction as $index => $entry) {
\Log::debug('Create job to import components_transaction! Yay! (' . $index . '/' . $count . ') ');
$fn = 'importComponentTransaction';
$jobFunction = 'Firefly\Queue\Import@' . $fn;
\Queue::push($jobFunction, ['data' => $entry, 'mapID' => $importMap->id]);
}
// queue a job to clean up the "import account", it should properly fall back
// to the cash account (which it doesn't always do for some reason).
\Queue::push('Firefly\Queue\Import@cleanImportAccount', ['mapID' => $importMap->id]);
}
\Log::debug('Done with job "start"');
// this is it, close the job:
$job->delete();
}
}

View File

@@ -46,11 +46,23 @@ interface AccountRepositoryInterface
public function find($accountId);
/**
* @param $name
*
* @param $type
* @return mixed
*/
public function findByName($name);
public function findAccountType($type);
/**
* @param $name
* @param \AccountType $type
* @return mixed
*/
public function findByName($name, \AccountType $type = null);
/**
* @param $name
* @return mixed
*/
public function findByNameAny($name);
/**
* @return mixed
@@ -89,6 +101,18 @@ interface AccountRepositoryInterface
*/
public function getDefault();
/**
* @param \AccountType $type
* @return mixed
*/
public function getByAccountType(\AccountType $type);
/**
* @param \User $user
* @return mixed
*/
public function overruleUser(\User $user);
/**
* @param $data
*

View File

@@ -12,11 +12,15 @@ use Carbon\Carbon;
*/
class EloquentAccountRepository implements AccountRepositoryInterface
{
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
/**
@@ -24,7 +28,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function count()
{
return \Auth::user()->accounts()->count();
return $this->_user->accounts()->count();
}
@@ -36,7 +40,6 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function createOrFind($name, \AccountType $type = null)
{
$account = $this->findByName($name, $type);
if (!$account) {
$data = [
@@ -60,10 +63,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
if (is_null($name) || strlen($name) == 0) {
return null;
}
$type = \AccountType::where('description', 'Beneficiary account')->first();
/** @noinspection PhpParamsInspection */
$type = \AccountType::where('type', 'Beneficiary account')->first();
return $this->createOrFind($name, $type);
}
@@ -74,38 +74,29 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function destroy(\Account $account)
{
// find the oldest transaction which also is a "Opening balance"
$first = \Transaction::
leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where('transaction_journals.user_id', \Auth::user()->id)
->where('transaction_types.type', 'Opening balance')
->where('account_id', '!=', $account->id)
->orderBy('transactions.id', 'DESC')->first(['transactions.*']);
// find all transaction journals related to this account:
$journals = \TransactionJournal::withRelevantData()->account($account)->get(['transaction_journals.*']);
$accountIDs = [];
$initialbalanceAccount = null;
if (!is_null($first)) {
$initialbalanceAccount = $first->account()->first();
}
// loop the account, find all transaction journals, and delete them:
$transactions = $account->transactions()->with('transactionjournal')->get();
$journals = [];
/** @var \Transaction $transaction */
foreach ($transactions as $transaction) {
$journals[$transaction->transaction_journal_id] = $transaction->transactionJournal;
}
/** @var \TransactionJournal $journal */
foreach ($journals as $journal) {
// remember the account id's of the transactions involved:
foreach ($journal->transactions as $t) {
$accountIDs[] = $t->account_id;
}
$journal->delete();
}
if (!is_null($initialbalanceAccount)) {
$initialbalanceAccount->delete();
$accountIDs = array_unique($accountIDs);
if (count($accountIDs) > 0) {
// find the "initial balance" type accounts in this list. Should be just 1.
$query = $this->_user->accounts()->accountTypeIn(['Initial balance account'])
->whereIn('accounts.id', $accountIDs);
if ($query->count() == 1) {
$iba = $query->first(['accounts.*']);
$iba->delete();
}
}
$account->delete();
/**
@@ -124,7 +115,16 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function find($accountId)
{
return \Auth::user()->accounts()->where('id', $accountId)->first();
return $this->_user->accounts()->where('id', $accountId)->first();
}
/**
* @param $type
* @return mixed
*/
public function findAccountType($type)
{
return \AccountType::where('type', $type)->first();
}
/**
@@ -135,10 +135,25 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function findByName($name, \AccountType $type = null)
{
$type = is_null($type) ? \AccountType::where('description', 'Default account')->first() : $type;
$type = is_null($type) ? \AccountType::where('type', 'Default account')->first() : $type;
return \Auth::user()->accounts()->where('account_type_id', $type->id)->where('name', 'like', '%' . $name . '%')
->first();
return $this->_user->accounts()->where('account_type_id', $type->id)
->where('name', 'like', '%' . $name . '%')
->first();
}
/**
* Used for import
*
* @param $name
*
* @return mixed
*/
public function findByNameAny($name)
{
return $this->_user->accounts()
->where('name', 'like', '%' . $name . '%')
->first();
}
/**
@@ -146,7 +161,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function get()
{
return \Auth::user()->accounts()->with('accounttype')->orderBy('name', 'ASC')->get();
return $this->_user->accounts()->with('accounttype')->orderBy('name', 'ASC')->get();
}
/**
@@ -154,10 +169,10 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
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)
return $this->_user->accounts()->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.type', 'Default account')->where('accounts.active', 1)
->get(['accounts.*']);
->get(['accounts.*']);
}
/**
@@ -165,12 +180,12 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function getActiveDefaultAsSelectList()
{
$list = \Auth::user()->accounts()->leftJoin(
'account_types', 'account_types.id', '=', 'accounts.account_type_id'
$list = $this->_user->accounts()->leftJoin(
'account_types', 'account_types.id', '=', 'accounts.account_type_id'
)
->where('account_types.description', 'Default account')->where('accounts.active', 1)
->where('account_types.type', 'Default account')->where('accounts.active', 1)
->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
$return = [];
foreach ($list as $entry) {
$return[intval($entry->id)] = $entry->name;
@@ -184,16 +199,22 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function getBeneficiaries()
{
$list = \Auth::user()->accounts()->leftJoin(
'account_types', 'account_types.id', '=', 'accounts.account_type_id'
$list = $this->_user->accounts()->leftJoin(
'account_types', 'account_types.id', '=', 'accounts.account_type_id'
)
->where('account_types.description', 'Beneficiary account')->where('accounts.active', 1)
->where('account_types.type', 'Beneficiary account')->where('accounts.active', 1)
->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
return $list;
}
public function getByAccountType(\AccountType $type)
{
return $this->_user->accounts()->with('accounttype')->orderBy('name', 'ASC')
->where('account_type_id', $type->id)->get();
}
/**
* @param $ids
*
@@ -202,7 +223,7 @@ class EloquentAccountRepository implements AccountRepositoryInterface
public function getByIds(array $ids)
{
if (count($ids) > 0) {
return \Auth::user()->accounts()->with('accounttype')->whereIn('id', $ids)->orderBy('name', 'ASC')->get();
return $this->_user->accounts()->with('accounttype')->whereIn('id', $ids)->orderBy('name', 'ASC')->get();
} else {
return $this->getActiveDefault();
}
@@ -213,8 +234,16 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function getCashAccount()
{
$type = \AccountType::where('description', 'Cash account')->first();
$cash = \Auth::user()->accounts()->where('account_type_id', $type->id)->first();
$type = \AccountType::where('type', 'Cash account')->first();
$cash = $this->_user->accounts()->where('account_type_id', $type->id)->first();
if (is_null($cash)) {
$cash = new \Account;
$cash->accountType()->associate($type);
$cash->user()->associate($this->_user);
$cash->name = 'Cash account';
$cash->active = 1;
$cash->save();
}
return $cash;
@@ -225,10 +254,20 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function getDefault()
{
return \Auth::user()->accounts()->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.description', 'Default account')
return $this->_user->accounts()->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.type', 'Default account')
->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
}
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
/**
@@ -239,16 +278,30 @@ class EloquentAccountRepository implements AccountRepositoryInterface
*/
public function store($data)
{
$defaultAccountType = \AccountType::where('description', 'Default account')->first();
$accountType = isset($data['account_type']) ? $data['account_type'] : $defaultAccountType;
/**
* If the AccountType has been passed through, use it:
*/
if (isset($data['account_type']) && is_object($data['account_type'])
&& get_class($data['account_type']) == 'AccountType'
) {
$accountType = $data['account_type'];
} else if (isset($data['account_type']) && is_string($data['account_type'])) {
$accountType = \AccountType::where('type', $data['account_type'])->first();
// create Account:
} else {
$accountType = \AccountType::where('type', 'Default account')->first();
}
/**
* Create new account:
*/
$account = new \Account;
$account->accountType()->associate($accountType);
$account->user()->associate(\Auth::user());
$account->user()->associate($this->_user);
$account->name = $data['name'];
$account->active
= isset($data['active']) && intval($data['active']) >= 0 && intval($data['active']) <= 1 ? intval(
= isset($data['active']) && intval($data['active']) >= 0 && intval($data['active']) <= 1 ? intval(
$data['active']
) : 1;
@@ -257,8 +310,10 @@ class EloquentAccountRepository implements AccountRepositoryInterface
// create initial balance, if necessary:
if (isset($data['openingbalance']) && isset($data['openingbalancedate'])) {
$amount = floatval($data['openingbalance']);
$date = new Carbon($data['openingbalancedate']);
$this->_createInitialBalance($account, $amount, $date);
$date = new Carbon($data['openingbalancedate']);
if ($amount != 0) {
$this->_createInitialBalance($account, $amount, $date);
}
}
}
@@ -286,12 +341,12 @@ class EloquentAccountRepository implements AccountRepositoryInterface
/** @var \Firefly\Helper\Controllers\AccountInterface $interface */
$interface = \App::make('Firefly\Helper\Controllers\AccountInterface');
if ($account->accounttype->description == 'Default account') {
if ($account->accounttype->type == 'Default account') {
$journal = $interface->openingBalanceTransaction($account);
if ($journal) {
$journal->date = new Carbon($data['openingbalancedate']);
$journal->date = new Carbon($data['openingbalancedate']);
$journal->transactions[0]->amount = floatval($data['openingbalance']) * -1;
$journal->transactions[1]->amount = floatval($data['openingbalance']);
$journal->transactions[0]->save();
@@ -306,8 +361,8 @@ class EloquentAccountRepository implements AccountRepositoryInterface
/**
* @param \Account $account
* @param int $amount
* @param Carbon $date
* @param int $amount
* @param Carbon $date
*
* @return bool
* @SuppressWarnings(PHPMD.CamelCaseMethodName)
@@ -315,24 +370,25 @@ class EloquentAccountRepository implements AccountRepositoryInterface
protected function _createInitialBalance(\Account $account, $amount = 0, Carbon $date)
{
// get account type:
$initialBalanceAT = \AccountType::where('description', 'Initial balance account')->first();
$initialBalanceAT = \AccountType::where('type', 'Initial balance account')->first();
// create new account:
$initial = new \Account;
$initial->accountType()->associate($initialBalanceAT);
$initial->user()->associate(\Auth::user());
$initial->name = $account->name . ' initial balance';
$initial->user()->associate($this->_user);
$initial->name = $account->name . ' initial balance';
$initial->active = 0;
if ($initial->validate()) {
$initial->save();
// create new transaction journal (and transactions):
/** @var \Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface $transactionJournal */
$transactionJournal = \App::make(
'Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'
'Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface'
);
$transactionJournal->overruleUser($this->_user);
$transactionJournal->createSimpleJournal(
$initial, $account, 'Initial Balance for ' . $account->name, $amount, $date
$initial, $account, 'Initial Balance for ' . $account->name, $amount, $date
);
return true;

View File

@@ -23,6 +23,19 @@ interface BudgetRepositoryInterface
*/
public function find($budgetId);
/**
* @param $budgetName
* @return mixed
*/
public function findByName($budgetName);
/**
* @param \User $user
* @return mixed
*/
public function overruleUser(\User $user);
/**
* @return mixed
*/

View File

@@ -3,19 +3,32 @@
namespace Firefly\Storage\Budget;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
/**
* Class EloquentBudgetRepository
*
* @package Firefly\Storage\Budget
*
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*
*/
class EloquentBudgetRepository implements BudgetRepositoryInterface
{
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
/**
* @param \Budget $budget
*
* @return bool|mixed
* @return bool
*/
public function destroy(\Budget $budget)
{
@@ -27,25 +40,35 @@ class EloquentBudgetRepository implements BudgetRepositoryInterface
/**
* @param $budgetId
*
* @return mixed
* @return \Budget|null
*/
public function find($budgetId)
{
return \Auth::user()->budgets()->find($budgetId);
return $this->_user->budgets()->find($budgetId);
}
/**
* @return mixed
* @param $budgetName
* @return \Budget|null
*/
public function findByName($budgetName)
{
return $this->_user->budgets()->whereName($budgetName)->first();
}
/**
* @return Collection
*/
public function get()
{
$set = \Auth::user()->budgets()->with(
['limits' => function ($q) {
$q->orderBy('limits.startdate', 'DESC');
}, 'limits.limitrepetitions' => function ($q) {
$q->orderBy('limit_repetitions.startdate', 'ASC');
}]
$set = $this->_user->budgets()->with(
['limits' => function ($q) {
$q->orderBy('limits.startdate', 'DESC');
}, 'limits.limitrepetitions' => function ($q) {
$q->orderBy('limit_repetitions.startdate', 'ASC');
}]
)->orderBy('name', 'ASC')->get();
foreach ($set as $budget) {
foreach ($budget->limits as $limit) {
@@ -59,12 +82,12 @@ class EloquentBudgetRepository implements BudgetRepositoryInterface
}
/**
* @return array|mixed
* @return array
*/
public function getAsSelectList()
{
$list = \Auth::user()->budgets()->with(
['limits', 'limits.limitrepetitions']
$list = $this->_user->budgets()->with(
['limits', 'limits.limitrepetitions']
)->orderBy('name', 'ASC')->get();
$return = [];
foreach ($list as $entry) {
@@ -74,56 +97,45 @@ class EloquentBudgetRepository implements BudgetRepositoryInterface
return $return;
}
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
/**
* @param $data
*
* @return \Budget|mixed
* @return \Budget
*/
public function store($data)
{
$budget = new \Budget;
$budget = new \Budget;
$budget->name = $data['name'];
$budget->user()->associate(\Auth::user());
$budget->user()->associate($this->_user);
$budget->save();
// if limit, create limit (repetition itself will be picked up elsewhere).
if (floatval($data['amount']) > 0) {
$limit = new \Limit;
$limit->budget()->associate($budget);
if (isset($data['amount']) && floatval($data['amount']) > 0) {
$startDate = new Carbon;
switch ($data['repeat_freq']) {
case 'daily':
$startDate->startOfDay();
break;
case 'weekly':
$startDate->startOfWeek();
break;
case 'monthly':
$startDate->startOfMonth();
break;
case 'quarterly':
$startDate->firstOfQuarter();
break;
case 'half-year':
$startDate->startOfYear();
if (intval($startDate->format('m')) >= 7) {
$startDate->addMonths(6);
}
break;
case 'yearly':
$startDate->startOfYear();
break;
}
$limit->startdate = $startDate;
$limit->amount = $data['amount'];
$limit->repeats = isset($data['repeats']) ? $data['repeats'] : 0;
$limit->repeat_freq = $data['repeat_freq'];
if ($limit->validate()) {
$limit->save();
\Event::fire('limits.store', [$limit]);
}
$limitData = [
'budget_id' => $budget->id,
'startdate' => $startDate->format('Y-m-d'),
'period' => $data['repeat_freq'],
'amount' => floatval($data['amount']),
'repeats' => 0
];
/** @var \Firefly\Storage\Limit\LimitRepositoryInterface $limitRepository */
$limitRepository = \App::make('Firefly\Storage\Limit\LimitRepositoryInterface');
$limitRepository->overruleUser($this->_user);
$limit = $limitRepository->store($limitData);
\Event::fire('limits.store', [$limit]);
}
if ($budget->validate()) {
$budget->save();
}

View File

@@ -29,6 +29,12 @@ interface CategoryRepositoryInterface
*/
public function createOrFind($name);
/**
* @param \User $user
* @return mixed
*/
public function overruleUser(\User $user);
/**
* @param $name
*

View File

@@ -9,6 +9,16 @@ namespace Firefly\Storage\Category;
*/
class EloquentCategoryRepository implements CategoryRepositoryInterface
{
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
/**
* @param $name
*
@@ -48,7 +58,7 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
*/
public function find($categoryId)
{
return \Auth::user()->categories()->find($categoryId);
return $this->_user->categories()->find($categoryId);
}
/**
@@ -62,7 +72,7 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
return null;
}
return \Auth::user()->categories()->where('name', 'LIKE', '%' . $name . '%')->first();
return $this->_user->categories()->where('name', 'LIKE', '%' . $name . '%')->first();
}
@@ -71,7 +81,7 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
*/
public function get()
{
return \Auth::user()->categories()->orderBy('name', 'ASC')->get();
return $this->_user->categories()->orderBy('name', 'ASC')->get();
}
/**
@@ -81,10 +91,10 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
*/
public function store($data)
{
$category = new \Category;
$category = new \Category;
$category->name = $data['name'];
$category->user()->associate(\Auth::user());
$category->user()->associate($this->_user);
$category->save();
return $category;
@@ -106,4 +116,14 @@ class EloquentCategoryRepository implements CategoryRepositoryInterface
return $category;
}
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
}

View File

@@ -28,4 +28,10 @@ interface ComponentRepositoryInterface
*/
public function store($data);
/**
* @param \User $user
* @return mixed
*/
public function overruleUser(\User $user);
}

View File

@@ -14,12 +14,14 @@ use Illuminate\Database\QueryException;
class EloquentComponentRepository implements ComponentRepositoryInterface
{
public $validator;
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
/**
@@ -27,7 +29,7 @@ class EloquentComponentRepository implements ComponentRepositoryInterface
*/
public function count()
{
return \Auth::user()->components()->count();
return $this->_user->components()->count();
}
@@ -40,6 +42,16 @@ class EloquentComponentRepository implements ComponentRepositoryInterface
throw new FireflyException('No implementation.');
}
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
/**
* @param $data
*
@@ -62,7 +74,7 @@ class EloquentComponentRepository implements ComponentRepositoryInterface
}
$component->name = $data['name'];
$component->user()->associate(\Auth::user());
$component->user()->associate($this->_user);
try {
$component->save();
} catch (QueryException $e) {

View File

@@ -0,0 +1,58 @@
<?php
namespace Firefly\Storage\Import;
class EloquentImportRepository implements ImportRepositoryInterface
{
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
public function findImportComponentMap(\Importmap $map, $oldComponentId)
{
$entry = \Importentry::where('importmap_id', $map->id)
->whereIn('class', ['Budget', 'Category', 'Account', 'Component'])
->where('old', intval($oldComponentId))->first();
return $entry;
}
public function findImportEntry(\Importmap $map, $class, $oldID)
{
return \Importentry::where('importmap_id', $map->id)->where('class', $class)->where('old', $oldID)->first();
}
public function findImportMap($id)
{
return \Importmap::find($id);
}
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
public function store(\Importmap $map, $class, $oldID, $newID)
{
$entry = new \Importentry;
$entry->importmap()->associate($map);
$entry->class = $class;
$entry->old = intval($oldID);
$entry->new = intval($newID);
$entry->save();
}
}

View File

@@ -0,0 +1,33 @@
<?php
namespace Firefly\Storage\Import;
/**
* Interface ImportRepositoryInterface
* @package Firefly\Storage\Import
*/
interface ImportRepositoryInterface
{
/**
* @param \Importmap $map
* @param $class
* @param $oldID
* @param $newID
* @return mixed
*/
public function store(\Importmap $map, $class, $oldID, $newID);
public function findImportMap($id);
public function findImportEntry(\Importmap $map, $class, $oldID);
public function findImportComponentMap(\Importmap $map, $oldComponentId);
/**
* @param \User $user
* @return mixed
*/
public function overruleUser(\User $user);
}

View File

@@ -12,7 +12,15 @@ use Carbon\Carbon;
*/
class EloquentLimitRepository implements LimitRepositoryInterface
{
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
/**
* @param \Limit $limit
@@ -26,24 +34,6 @@ class EloquentLimitRepository implements LimitRepositoryInterface
return true;
}
/**
* @param \Limit $limit
* @param $data
*
* @return mixed|void
*/
public function update(\Limit $limit, $data)
{
$limit->startdate = new Carbon($data['startdate']);
$limit->repeat_freq = $data['period'];
$limit->repeats = isset($data['repeats']) && $data['repeats'] == '1' ? 1 : 0;
$limit->amount = floatval($data['amount']);
$limit->save();
return $limit;
}
/**
* @param $limitId
*
@@ -52,15 +42,20 @@ class EloquentLimitRepository implements LimitRepositoryInterface
public function find($limitId)
{
return \Limit::with('limitrepetitions')->where('limits.id', $limitId)->leftJoin(
'components', 'components.id', '=', 'limits.component_id'
'components', 'components.id', '=', 'limits.component_id'
)
->where('components.user_id', \Auth::user()->id)->first(['limits.*']);
->where('components.user_id', $this->_user->id)->first(['limits.*']);
}
public function findByBudgetAndDate(\Budget $budget, Carbon $date)
{
return \Limit::whereComponentId($budget->id)->where('startdate', $date->format('Y-m-d'))->first();
}
/**
* @param \Budget $budget
* @param Carbon $start
* @param Carbon $end
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
@@ -72,6 +67,16 @@ class EloquentLimitRepository implements LimitRepositoryInterface
}
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
/**
* @param $data
*
@@ -116,9 +121,9 @@ class EloquentLimitRepository implements LimitRepositoryInterface
// find existing:
$count = \Limit::
leftJoin('components', 'components.id', '=', 'limits.component_id')->where(
'components.user_id', \Auth::user()->id
'components.user_id', $this->_user->id
)->where('startdate', $date->format('Y-m-d'))->where('component_id', $data['budget_id'])->where(
'repeat_freq', $data['period']
'repeat_freq', $data['period']
)->count();
if ($count > 0) {
\Session::flash('error', 'There already is an entry for these parameters.');
@@ -128,9 +133,9 @@ class EloquentLimitRepository implements LimitRepositoryInterface
// create new limit:
$limit = new \Limit;
$limit->budget()->associate($budget);
$limit->startdate = $date;
$limit->amount = floatval($data['amount']);
$limit->repeats = isset($data['repeats']) ? intval($data['repeats']) : 0;
$limit->startdate = $date;
$limit->amount = floatval($data['amount']);
$limit->repeats = isset($data['repeats']) ? intval($data['repeats']) : 0;
$limit->repeat_freq = $data['period'];
if (!$limit->save()) {
\Session::flash('error', 'Could not save: ' . $limit->errors()->first());
@@ -139,4 +144,22 @@ class EloquentLimitRepository implements LimitRepositoryInterface
return $limit;
}
/**
* @param \Limit $limit
* @param $data
*
* @return mixed|void
*/
public function update(\Limit $limit, $data)
{
$limit->startdate = new Carbon($data['startdate']);
$limit->repeat_freq = $data['period'];
$limit->repeats = isset($data['repeats']) && $data['repeats'] == '1' ? 1 : 0;
$limit->amount = floatval($data['amount']);
$limit->save();
return $limit;
}
}

View File

@@ -12,6 +12,36 @@ use Carbon\Carbon;
interface LimitRepositoryInterface
{
/**
* @param \Limit $limit
*
* @return mixed
*/
public function destroy(\Limit $limit);
/**
* @param $limitId
*
* @return mixed
*/
public function find($limitId);
/**
* @param \Budget $budget
* @param Carbon $date
* @return mixed
*/
public function findByBudgetAndDate(\Budget $budget, Carbon $date);
/**
* @param \Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
public function getTJByBudgetAndDateRange(\Budget $budget, Carbon $start, Carbon $end);
/**
* @param $data
*
@@ -28,25 +58,8 @@ interface LimitRepositoryInterface
public function update(\Limit $limit, $data);
/**
* @param \Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @param \User $user
* @return mixed
*/
public function getTJByBudgetAndDateRange(\Budget $budget, Carbon $start, Carbon $end);
/**
* @param $limitId
*
* @return mixed
*/
public function find($limitId);
/**
* @param \Limit $limit
*
* @return mixed
*/
public function destroy(\Limit $limit);
public function overruleUser(\User $user);
}

View File

@@ -14,6 +14,15 @@ use Firefly\Exception\FireflyException;
class EloquentPiggybankRepository implements PiggybankRepositoryInterface
{
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
/**
* @return mixed
@@ -21,14 +30,14 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
public function count()
{
return \Piggybank::leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where(
'accounts.user_id', \Auth::user()->id
'accounts.user_id', $this->_user->id
)->count();
}
public function countNonrepeating()
{
return \Piggybank::leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where(
'accounts.user_id', \Auth::user()->id
'accounts.user_id', $this->_user->id
)->where('repeats', 0)->count();
}
@@ -36,7 +45,7 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
public function countRepeating()
{
return \Piggybank::leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where(
'accounts.user_id', \Auth::user()->id
'accounts.user_id', $this->_user->id
)->where('repeats', 1)->count();
}
@@ -60,16 +69,23 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
public function find($piggyBankId)
{
return \Piggybank::leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where(
'accounts.user_id', \Auth::user()->id
'accounts.user_id', $this->_user->id
)->where('piggybanks.id', $piggyBankId)->first(['piggybanks.*']);
}
public function findByName($piggyBankName)
{
return \Piggybank::leftJoin('accounts', 'accounts.id', '=', 'piggybanks.account_id')->where(
'accounts.user_id', $this->_user->id
)->where('piggybanks.name', $piggyBankName)->first(['piggybanks.*']);
}
/**
* @return mixed
*/
public function get()
{
$piggies = \Auth::user()->piggybanks()->with(['account', 'piggybankrepetitions'])->get();
$piggies = $this->_user->piggybanks()->with(['account', 'piggybankrepetitions'])->get();
foreach ($piggies as $pig) {
$pig->leftInAccount = $this->leftOnAccount($pig->account);
@@ -95,7 +111,6 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
}
/**
* @param \Piggybank $piggyBank
* @param $amount
@@ -115,6 +130,16 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
}
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
/**
* @param $data
*
@@ -122,19 +147,20 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
*/
public function store($data)
{
if ($data['targetdate'] == '') {
if (isset($data['targetdate']) && $data['targetdate'] == '') {
unset($data['targetdate']);
}
if ($data['reminder'] == 'none') {
if (isset($data['reminder']) && $data['reminder'] == 'none') {
unset($data['reminder']);
}
if ($data['startdate'] == '') {
if (isset($data['startdate']) && $data['startdate'] == '') {
unset($data['startdate']);
}
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
$account = isset($data['account_id']) ? $accounts->find($data['account_id']) : null;
$accounts->overruleUser($this->_user);
$account = isset($data['account_id']) ? $accounts->find($data['account_id']) : null;
$piggyBank = new \Piggybank($data);
@@ -142,7 +168,7 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
if (!is_null($piggyBank->reminder) && is_null($piggyBank->startdate) && is_null($piggyBank->targetdate)) {
$piggyBank->errors()->add('reminder', 'Cannot create reminders without start ~ AND target date.');
\Log::error('PiggyBank create-error: ' . $piggyBank->errors()->first());
return $piggyBank;
}
@@ -150,6 +176,7 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
if ($piggyBank->repeats && !isset($data['targetdate'])) {
$piggyBank->errors()->add('targetdate', 'Target date is mandatory!');
\Log::error('PiggyBank create-error: ' . $piggyBank->errors()->first());
return $piggyBank;
}
@@ -161,13 +188,14 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
if ($piggyBank->validate()) {
if (!is_null($piggyBank->targetdate) && $piggyBank->targetdate < $today) {
$piggyBank->errors()->add('targetdate', 'Target date cannot be in the past.');
\Log::error('PiggyBank create-error: ' . $piggyBank->errors()->first());
return $piggyBank;
}
if (!is_null($piggyBank->reminder) && !is_null($piggyBank->targetdate)) {
// first period for reminder is AFTER target date.
$reminderSkip = $piggyBank->reminder_skip < 1 ? 1 : intval($piggyBank->reminder_skip);
$reminderSkip = $piggyBank->reminder_skip < 1 ? 1 : intval($piggyBank->reminder_skip);
$firstReminder = new Carbon;
switch ($piggyBank->reminder) {
case 'day':
@@ -188,8 +216,9 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
}
if ($firstReminder > $piggyBank->targetdate) {
$piggyBank->errors()->add(
'reminder', 'The reminder has been set to remind you after the piggy bank will expire.'
'reminder', 'The reminder has been set to remind you after the piggy bank will expire.'
);
\Log::error('PiggyBank create-error: ' . $piggyBank->errors()->first());
return $piggyBank;
}
@@ -197,6 +226,7 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
$piggyBank->save();
}
return $piggyBank;
}
@@ -210,19 +240,20 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
{
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accounts */
$accounts = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
$account = isset($data['account_id']) ? $accounts->find($data['account_id']) : null;
$accounts->overruleUser($this->_user);
$account = isset($data['account_id']) ? $accounts->find($data['account_id']) : null;
if (!is_null($account)) {
$piggy->account()->associate($account);
}
$piggy->name = $data['name'];
$piggy->targetamount = floatval($data['targetamount']);
$piggy->reminder = isset($data['reminder']) && $data['reminder'] != 'none' ? $data['reminder'] : null;
$piggy->name = $data['name'];
$piggy->targetamount = floatval($data['targetamount']);
$piggy->reminder = isset($data['reminder']) && $data['reminder'] != 'none' ? $data['reminder'] : null;
$piggy->reminder_skip = $data['reminder_skip'];
$piggy->targetdate = strlen($data['targetdate']) > 0 ? new Carbon($data['targetdate']) : null;
$piggy->targetdate = strlen($data['targetdate']) > 0 ? new Carbon($data['targetdate']) : null;
$piggy->startdate
= isset($data['startdate']) && strlen($data['startdate']) > 0 ? new Carbon($data['startdate']) : null;
= isset($data['startdate']) && strlen($data['startdate']) > 0 ? new Carbon($data['startdate']) : null;
foreach ($piggy->piggybankrepetitions()->get() as $rep) {
@@ -230,7 +261,7 @@ class EloquentPiggybankRepository implements PiggybankRepositoryInterface
}
if ($piggy->repeats == 1) {
$piggy->rep_every = intval($data['rep_every']);
$piggy->rep_every = intval($data['rep_every']);
$piggy->rep_length = $data['rep_length'];
}

View File

@@ -40,6 +40,8 @@ interface PiggybankRepositoryInterface
*/
public function find($piggyBankId);
public function findByName($piggyBankName);
/**
* @return mixed
*/
@@ -77,5 +79,11 @@ interface PiggybankRepositoryInterface
*/
public function update(\Piggybank $piggy, $data);
/**
* @param \User $user
* @return mixed
*/
public function overruleUser(\User $user);
}

View File

@@ -12,6 +12,27 @@ use Carbon\Carbon;
*/
class EloquentRecurringTransactionRepository implements RecurringTransactionRepositoryInterface
{
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
/**
* @param \RecurringTransaction $recurringTransaction
*
@@ -24,12 +45,17 @@ class EloquentRecurringTransactionRepository implements RecurringTransactionRepo
return true;
}
public function findByName($name)
{
return $this->_user->recurringtransactions()->where('name', 'LIKE', '%' . $name . '%')->first();
}
/**
* @return mixed
*/
public function get()
{
return \Auth::user()->recurringtransactions()->get();
return $this->_user->recurringtransactions()->get();
}
/**
@@ -40,9 +66,9 @@ class EloquentRecurringTransactionRepository implements RecurringTransactionRepo
public function store($data)
{
$recurringTransaction = new \RecurringTransaction;
$recurringTransaction->user()->associate(\Auth::user());
$recurringTransaction->name = $data['name'];
$recurringTransaction->match = join(' ', explode(',', $data['match']));
$recurringTransaction->user()->associate($this->_user);
$recurringTransaction->name = $data['name'];
$recurringTransaction->match = join(' ', explode(',', $data['match']));
$recurringTransaction->amount_max = floatval($data['amount_max']);
$recurringTransaction->amount_min = floatval($data['amount_min']);
@@ -53,10 +79,10 @@ class EloquentRecurringTransactionRepository implements RecurringTransactionRepo
return $recurringTransaction;
}
$recurringTransaction->date = new Carbon($data['date']);
$recurringTransaction->active = isset($data['active']) ? intval($data['active']) : 0;
$recurringTransaction->automatch = isset($data['automatch']) ? intval($data['automatch']) : 0;
$recurringTransaction->skip = isset($data['skip']) ? intval($data['skip']) : 0;
$recurringTransaction->date = new Carbon($data['date']);
$recurringTransaction->active = isset($data['active']) ? intval($data['active']) : 0;
$recurringTransaction->automatch = isset($data['automatch']) ? intval($data['automatch']) : 0;
$recurringTransaction->skip = isset($data['skip']) ? intval($data['skip']) : 0;
$recurringTransaction->repeat_freq = $data['repeat_freq'];
if ($recurringTransaction->validate()) {
@@ -74,8 +100,8 @@ class EloquentRecurringTransactionRepository implements RecurringTransactionRepo
*/
public function update(\RecurringTransaction $recurringTransaction, $data)
{
$recurringTransaction->name = $data['name'];
$recurringTransaction->match = join(' ', explode(',', $data['match']));
$recurringTransaction->name = $data['name'];
$recurringTransaction->match = join(' ', explode(',', $data['match']));
$recurringTransaction->amount_max = floatval($data['amount_max']);
$recurringTransaction->amount_min = floatval($data['amount_min']);
@@ -85,10 +111,10 @@ class EloquentRecurringTransactionRepository implements RecurringTransactionRepo
return $recurringTransaction;
}
$recurringTransaction->date = new Carbon($data['date']);
$recurringTransaction->active = isset($data['active']) ? intval($data['active']) : 0;
$recurringTransaction->automatch = isset($data['automatch']) ? intval($data['automatch']) : 0;
$recurringTransaction->skip = isset($data['skip']) ? intval($data['skip']) : 0;
$recurringTransaction->date = new Carbon($data['date']);
$recurringTransaction->active = isset($data['active']) ? intval($data['active']) : 0;
$recurringTransaction->automatch = isset($data['automatch']) ? intval($data['automatch']) : 0;
$recurringTransaction->skip = isset($data['skip']) ? intval($data['skip']) : 0;
$recurringTransaction->repeat_freq = $data['repeat_freq'];
if ($recurringTransaction->validate()) {

View File

@@ -16,6 +16,12 @@ interface RecurringTransactionRepositoryInterface
*/
public function get();
/**
* @param $name
* @return mixed
*/
public function findByName($name);
/**
* @param $data
*
@@ -38,5 +44,11 @@ interface RecurringTransactionRepositoryInterface
*/
public function update(\RecurringTransaction $recurringTransaction, $data);
/**
* @param \User $user
* @return mixed
*/
public function overruleUser(\User $user);
}

View File

@@ -12,6 +12,26 @@ use Carbon\Carbon;
*/
class EloquentReminderRepository implements ReminderRepositoryInterface
{
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
/**
* @param \Reminder $reminder
*
@@ -42,7 +62,7 @@ class EloquentReminderRepository implements ReminderRepositoryInterface
{
$today = new Carbon;
return \Auth::user()->reminders()->validOn($today)->get();
return $this->_user->reminders()->validOn($today)->get();
}
/**
@@ -52,8 +72,8 @@ class EloquentReminderRepository implements ReminderRepositoryInterface
{
$today = new Carbon;
return \Auth::user()->reminders()->with('recurringtransaction')->validOn($today)->where(
'class', 'RecurringTransactionReminder'
return $this->_user->reminders()->with('recurringtransaction')->validOn($today)->where(
'class', 'RecurringTransactionReminder'
)->get();
}

View File

@@ -39,4 +39,10 @@ interface ReminderRepositoryInterface
public function getCurrentRecurringReminders();
/**
* @param \User $user
* @return mixed
*/
public function overruleUser(\User $user);
}

View File

@@ -18,55 +18,60 @@ class StorageServiceProvider extends ServiceProvider
public function register()
{
$this->app->bind(
'Firefly\Storage\User\UserRepositoryInterface',
'Firefly\Storage\User\EloquentUserRepository'
'Firefly\Storage\User\UserRepositoryInterface',
'Firefly\Storage\User\EloquentUserRepository'
);
$this->app->bind(
'Firefly\Storage\Transaction\TransactionRepositoryInterface',
'Firefly\Storage\Transaction\EloquentTransactionRepository'
'Firefly\Storage\Transaction\TransactionRepositoryInterface',
'Firefly\Storage\Transaction\EloquentTransactionRepository'
);
$this->app->bind(
'Firefly\Storage\Import\ImportRepositoryInterface',
'Firefly\Storage\Import\EloquentImportRepository'
);
$this->app->bind(
'Firefly\Storage\Piggybank\PiggybankRepositoryInterface',
'Firefly\Storage\Piggybank\EloquentPiggybankRepository'
);
$this->app->bind(
'Firefly\Storage\Piggybank\PiggybankRepositoryInterface',
'Firefly\Storage\Piggybank\EloquentPiggybankRepository'
'Firefly\Storage\RecurringTransaction\RecurringTransactionRepositoryInterface',
'Firefly\Storage\RecurringTransaction\EloquentRecurringTransactionRepository'
);
$this->app->bind(
'Firefly\Storage\RecurringTransaction\RecurringTransactionRepositoryInterface',
'Firefly\Storage\RecurringTransaction\EloquentRecurringTransactionRepository'
'Firefly\Storage\Reminder\ReminderRepositoryInterface',
'Firefly\Storage\Reminder\EloquentReminderRepository'
);
$this->app->bind(
'Firefly\Storage\Reminder\ReminderRepositoryInterface',
'Firefly\Storage\Reminder\EloquentReminderRepository'
'Firefly\Storage\Account\AccountRepositoryInterface',
'Firefly\Storage\Account\EloquentAccountRepository'
);
$this->app->bind(
'Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface',
'Firefly\Storage\TransactionJournal\EloquentTransactionJournalRepository'
);
$this->app->bind(
'Firefly\Storage\Account\AccountRepositoryInterface',
'Firefly\Storage\Account\EloquentAccountRepository'
);
$this->app->bind(
'Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface',
'Firefly\Storage\TransactionJournal\EloquentTransactionJournalRepository'
'Firefly\Storage\Component\ComponentRepositoryInterface',
'Firefly\Storage\Component\EloquentComponentRepository'
);
$this->app->bind(
'Firefly\Storage\Component\ComponentRepositoryInterface',
'Firefly\Storage\Component\EloquentComponentRepository'
'Firefly\Storage\Limit\LimitRepositoryInterface',
'Firefly\Storage\Limit\EloquentLimitRepository'
);
$this->app->bind(
'Firefly\Storage\Limit\LimitRepositoryInterface',
'Firefly\Storage\Limit\EloquentLimitRepository'
);
$this->app->bind(
'Firefly\Storage\Budget\BudgetRepositoryInterface',
'Firefly\Storage\Budget\EloquentBudgetRepository'
'Firefly\Storage\Budget\BudgetRepositoryInterface',
'Firefly\Storage\Budget\EloquentBudgetRepository'
);
$this->app->bind(
'Firefly\Storage\Category\CategoryRepositoryInterface',
'Firefly\Storage\Category\EloquentCategoryRepository'
'Firefly\Storage\Category\CategoryRepositoryInterface',
'Firefly\Storage\Category\EloquentCategoryRepository'
);
}

View File

@@ -9,5 +9,24 @@ namespace Firefly\Storage\Transaction;
*/
class EloquentTransactionRepository implements TransactionRepositoryInterface
{
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
}

View File

@@ -9,6 +9,11 @@ namespace Firefly\Storage\Transaction;
*/
interface TransactionRepositoryInterface
{
/**
* @param \User $user
* @return mixed
*/
public function overruleUser(\User $user);
}

View File

@@ -14,6 +14,16 @@ use Firefly\Exception\FireflyException;
class EloquentTransactionJournalRepository implements TransactionJournalRepositoryInterface
{
protected $_user = null;
/**
*
*/
public function __construct()
{
$this->_user = \Auth::user();
}
/**
*
* We're building this thinking the money goes from A to B.
@@ -34,8 +44,8 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
* A gains 200 (200). * -1
* B loses 200 (-200). * 1
*
* @param \Account $from
* @param \Account $toAccount
* @param \Account $from
* @param \Account $toAccount
* @param $description
* @param $amount
* @param \Carbon\Carbon $date
@@ -48,7 +58,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
$journal = new \TransactionJournal;
$amountFrom = $amount * -1;
$amountTo = $amount;
$amountTo = $amount;
if (round(floatval($amount), 2) == 0.00) {
$journal->errors()->add('amount', 'Amount must not be zero.');
@@ -64,8 +74,8 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
}
// account types for both:
$toAT = $toAccount->accountType->description;
$fromAT = $from->accountType->description;
$toAT = $toAccount->accountType->type;
$fromAT = $from->accountType->type;
$journalType = null;
@@ -105,10 +115,10 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
$journal->transactionType()->associate($journalType);
$journal->transactionCurrency()->associate($currency);
$journal->user()->associate(\Auth::user());
$journal->completed = false;
$journal->user()->associate($this->_user);
$journal->completed = false;
$journal->description = $description;
$journal->date = $date;
$journal->date = $date;
if (!$journal->validate()) {
return $journal;
}
@@ -119,10 +129,10 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
$fromTransaction->account()->associate($from);
$fromTransaction->transactionJournal()->associate($journal);
$fromTransaction->description = null;
$fromTransaction->amount = $amountFrom;
$fromTransaction->amount = $amountFrom;
if (!$fromTransaction->validate()) {
throw new FireflyException('Cannot create valid transaction (from): ' . $fromTransaction->errors()->first(
));
throw new FireflyException('Cannot create valid transaction (from): ' . $fromTransaction->errors()
->first());
}
$fromTransaction->save();
@@ -130,7 +140,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
$toTransaction->account()->associate($toAccount);
$toTransaction->transactionJournal()->associate($journal);
$toTransaction->description = null;
$toTransaction->amount = $amountTo;
$toTransaction->amount = $amountTo;
if (!$toTransaction->validate()) {
throw new FireflyException('Cannot create valid transaction (to): ' . $toTransaction->errors()->first());
}
@@ -149,13 +159,13 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
*/
public function find($journalId)
{
return \Auth::user()->transactionjournals()->with(
['transactions' => function ($q) {
return $q->orderBy('amount', 'ASC');
}, 'transactioncurrency', 'transactiontype', 'components', 'transactions.account',
'transactions.account.accounttype']
return $this->_user->transactionjournals()->with(
['transactions' => function ($q) {
return $q->orderBy('amount', 'ASC');
}, 'transactioncurrency', 'transactiontype', 'components', 'transactions.account',
'transactions.account.accounttype']
)
->where('id', $journalId)->first();
->where('id', $journalId)->first();
}
/**
@@ -168,64 +178,76 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
/**
* @param \Account $account
* @param Carbon $date
* @param Carbon $date
*
* @return mixed
*/
public function getByAccountAndDate(\Account $account, Carbon $date)
{
$accountID = $account->id;
$query = \Auth::user()->transactionjournals()->with(
[
'transactions',
'transactions.account',
'transactioncurrency',
'transactiontype'
]
$query = $this->_user->transactionjournals()->with(
[
'transactions',
'transactions.account',
'transactioncurrency',
'transactiontype'
]
)
->distinct()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->where('transactions.account_id', $accountID)
->where('transaction_journals.date', $date->format('Y-m-d'))
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.id', 'DESC')
->get(['transaction_journals.*']);
->distinct()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=',
'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->where('transactions.account_id', $accountID)
->where('transaction_journals.date', $date->format('Y-m-d'))
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.id', 'DESC')
->get(['transaction_journals.*']);
return $query;
}
/**
* @param \Account $account
* @param int $count
* @param Carbon $start
* @param Carbon $end
* @param int $count
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
public function getByAccountInDateRange(\Account $account, $count = 25, Carbon $start, Carbon $end)
{
$accountID = $account->id;
$query = \Auth::user()->transactionjournals()->with(
[
'transactions',
'transactioncurrency',
'transactiontype'
]
$query = $this->_user->transactionjournals()->with(
[
'transactions',
'transactioncurrency',
'transactiontype'
]
)
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->where('accounts.id', $accountID)
->where('date', '>=', $start->format('Y-m-d'))
->where('date', '<=', $end->format('Y-m-d'))
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.id', 'DESC')
->take($count)
->get(['transaction_journals.*']);
->leftJoin('transactions', 'transactions.transaction_journal_id', '=',
'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->where('accounts.id', $accountID)
->where('date', '>=', $start->format('Y-m-d'))
->where('date', '<=', $end->format('Y-m-d'))
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.id', 'DESC')
->take($count)
->get(['transaction_journals.*']);
return $query;
}
/**
* @param \User $user
* @return mixed|void
*/
public function overruleUser(\User $user)
{
$this->_user = $user;
return true;
}
/**
* @param int $count
*
@@ -233,19 +255,9 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
*/
public function paginate($count = 25, Carbon $start = null, Carbon $end = null)
{
$query = \Auth::user()->transactionjournals()->with(
[
'transactions' => function ($q) {
return $q->orderBy('amount', 'ASC');
},
'transactions.account',
'transactions.account.accounttype',
'transactioncurrency',
'transactiontype'
]
)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.id', 'DESC');
$query = $this->_user->transactionjournals()->WithRelevantData()
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.id', 'DESC');
if (!is_null($start)) {
$query->where('transaction_journals.date', '>=', $start->format('Y-m-d'));
}
@@ -270,37 +282,40 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
// depending on the $what
$fromAccount = null;
$toAccount = null;
$toAccount = null;
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */
$accountRepository = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
$accountRepository->overruleUser($this->_user);
/** @var \Firefly\Storage\Category\CategoryRepositoryInterface $catRepository */
$catRepository = \App::make('Firefly\Storage\Category\CategoryRepositoryInterface');
$catRepository->overruleUser($this->_user);
/** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budRepository */
$budRepository = \App::make('Firefly\Storage\Budget\BudgetRepositoryInterface');
$budRepository->overruleUser($this->_user);
switch ($what) {
case 'withdrawal':
$fromAccount = $accountRepository->find(intval($data['account_id']));
$toAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']);
$toAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']);
break;
case 'deposit':
$fromAccount = $accountRepository->createOrFindBeneficiary($data['beneficiary']);
$toAccount = $accountRepository->find(intval($data['account_id']));
$toAccount = $accountRepository->find(intval($data['account_id']));
break;
case 'transfer':
$fromAccount = $accountRepository->find(intval($data['account_from_id']));
$toAccount = $accountRepository->find(intval($data['account_to_id']));
$toAccount = $accountRepository->find(intval($data['account_to_id']));
break;
}
// fall back to cash if necessary:
$fromAccount = is_null($fromAccount) ? $fromAccount = $accountRepository->getCashAccount() : $fromAccount;
$toAccount = is_null($toAccount) ? $toAccount = $accountRepository->getCashAccount() : $toAccount;
$toAccount = is_null($toAccount) ? $toAccount = $accountRepository->getCashAccount() : $toAccount;
// create or find category:
$category = isset($data['category']) ? $catRepository->createOrFind($data['category']) : null;
@@ -309,8 +324,8 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
$budget = isset($data['budget_id']) ? $budRepository->find(intval($data['budget_id'])) : null;
// find amount & description:
$description = trim($data['description']);
$amount = floatval($data['amount']);
$date = new Carbon($data['date']);
$amount = floatval($data['amount']);
$date = new Carbon($data['date']);
// try to create a journal:
$transactionJournal = $this->createSimpleJournal($fromAccount, $toAccount, $description, $amount, $date);
@@ -323,6 +338,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
if ($what == 'transfer') {
/** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $piggyRepository */
$piggyRepository = \App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
$piggyRepository->overruleUser($this->_user);
if (isset($data['piggybank_id'])) {
/** @var \Piggybank $piggyBank */
@@ -337,15 +353,15 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
$transaction->piggybank()->associate($piggyBank);
$transaction->save();
\Event::fire(
'piggybanks.createRelatedTransfer', [$piggyBank, $transactionJournal, $transaction]
'piggybanks.createRelatedTransfer', [$piggyBank, $transactionJournal, $transaction]
);
break;
}
}
if ($connected === false) {
\Session::flash(
'warning', 'Piggy bank "' . e($piggyBank->name)
. '" is not set to draw money from any of the accounts in this transfer'
'warning', 'Piggy bank "' . e($piggyBank->name)
. '" is not set to draw money from any of the accounts in this transfer'
);
}
}
@@ -375,18 +391,21 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
{
/** @var \Firefly\Storage\Category\CategoryRepositoryInterface $catRepository */
$catRepository = \App::make('Firefly\Storage\Category\CategoryRepositoryInterface');
$catRepository->overruleUser($this->_user);
/** @var \Firefly\Storage\Budget\BudgetRepositoryInterface $budgetRepository */
$budRepository = \App::make('Firefly\Storage\Budget\BudgetRepositoryInterface');
$budRepository->overruleUser($this->_user);
/** @var \Firefly\Storage\Account\AccountRepositoryInterface $accountRepository */
$accountRepository = \App::make('Firefly\Storage\Account\AccountRepositoryInterface');
$accountRepository->overruleUser($this->_user);
// update basics first:
$journal->description = $data['description'];
$journal->date = $data['date'];
$amount = floatval($data['amount']);
$journal->date = $data['date'];
$amount = floatval($data['amount']);
// remove previous category, if any:
if (!is_null($journal->categories()->first())) {
@@ -424,7 +443,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
switch ($journal->transactiontype->type) {
case 'Withdrawal':
// means transaction[0] is the users account.
$account = $accountRepository->find($data['account_id']);
$account = $accountRepository->find($data['account_id']);
$beneficiary = $accountRepository->createOrFindBeneficiary($data['beneficiary']);
$transactions[0]->account()->associate($account);
$transactions[1]->account()->associate($beneficiary);
@@ -438,7 +457,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
break;
case 'Deposit':
// means transaction[0] is the beneficiary.
$account = $accountRepository->find($data['account_id']);
$account = $accountRepository->find($data['account_id']);
$beneficiary = $accountRepository->createOrFindBeneficiary($data['beneficiary']);
$journal->transactions[0]->account()->associate($beneficiary);
$journal->transactions[1]->account()->associate($account);
@@ -455,6 +474,7 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
// attach the new piggy bank, if valid:
/** @var \Firefly\Storage\Piggybank\PiggybankRepositoryInterface $piggyRepository */
$piggyRepository = \App::make('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
$piggyRepository->overruleUser($this->_user);
if (isset($data['piggybank_id'])) {
/** @var \Piggybank $piggyBank */
@@ -476,8 +496,8 @@ class EloquentTransactionJournalRepository implements TransactionJournalReposito
}
if ($connected === false) {
\Session::flash(
'warning', 'Piggy bank "' . e($piggyBank->name)
. '" is not set to draw money from any of the accounts in this transfer'
'warning', 'Piggy bank "' . e($piggyBank->name)
. '" is not set to draw money from any of the accounts in this transfer'
);
}
}

View File

@@ -16,7 +16,7 @@ interface TransactionJournalRepositoryInterface
* @param \Account $toAccount
* @param $description
* @param $amount
* @param Carbon $date
* @param Carbon $date
*
* @return mixed
*/
@@ -27,6 +27,12 @@ interface TransactionJournalRepositoryInterface
*/
public function get();
/**
* @param \User $user
* @return mixed
*/
public function overruleUser(\User $user);
/**
* @param $what
* @param $data
@@ -52,9 +58,9 @@ interface TransactionJournalRepositoryInterface
/**
* @param \Account $account
* @param int $count
* @param Carbon $start
* @param Carbon $end
* @param int $count
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
@@ -62,7 +68,7 @@ interface TransactionJournalRepositoryInterface
/**
* @param \Account $account
* @param Carbon $date
* @param Carbon $date
*
* @return mixed
*/

View File

@@ -60,10 +60,10 @@ class EloquentUserRepository implements UserRepositoryInterface
*/
public function register($array)
{
$user = new \User;
$user->email = isset($array['email']) ? $array['email'] : null;
$user = new \User;
$user->email = isset($array['email']) ? $array['email'] : null;
$user->migrated = 0;
$user->reset = \Str::random(32);
$user->reset = \Str::random(32);
$user->password = \Hash::make(\Str::random(12));
if (!$user->save()) {

View File

@@ -0,0 +1,96 @@
<?php
namespace Firefly\Trigger\Journals;
use Carbon\Carbon;
use Illuminate\Events\Dispatcher;
/**
* Class EloquentJournalTrigger
*
* @package Firefly\Trigger\Journals
*/
class EloquentJournalTrigger
{
/**
* @param \TransactionJournal $journal
*
* @return bool
*/
public function store(\TransactionJournal $journal)
{
// select all reminders for recurring transactions:
if ($journal->transaction_type->type == 'Withdrawal') {
\Log::debug('Trigger on the creation of a withdrawal');
$transaction = $journal->transactions()->orderBy('amount', 'DESC')->first();
$amount = floatval($transaction->amount);
$description = strtolower($journal->description);
$beneficiary = strtolower($transaction->account->name);
// make an array of parts:
$parts = explode(' ', $description);
$parts[] = $beneficiary;
$today = new Carbon;
$set = \RecurringTransactionReminder::
leftJoin(
'recurring_transactions', 'recurring_transactions.id', '=', 'reminders.recurring_transaction_id'
)
->where('startdate', '<', $today->format('Y-m-d'))
->where('enddate', '>', $today->format('Y-m-d'))
->where('amount_min', '<=', $amount)
->where('amount_max', '>=', $amount)->get(['reminders.*']);
/** @var \RecurringTransctionReminder $reminder */
\Log::debug('Have these parts to search for: ' . join('/',$parts));
\Log::debug('Found ' . count($set).' possible matching recurring transactions');
foreach ($set as $index => $reminder) {
/** @var \RecurringTransaction $RT */
$RT = $reminder->recurring_transaction;
$matches = explode(' ', strtolower($RT->match));
\Log::debug($index.': ' . join('/',$matches));
$matchCount = 0;
foreach ($parts as $part) {
if (in_array($part, $matches)) {
$matchCount++;
}
}
if ($matchCount >= count($matches)) {
// we have a match!
\Log::debug(
'Match between new journal "' . join('/', $parts) . '" and RT ' . join('/', $matches) . '.'
);
$journal->recurringTransaction()->associate($RT);
$journal->save();
// also update the reminder.
$reminder->active = 0;
$reminder->save();
return true;
}
}
}
return true;
}
/**
* @param Dispatcher $events
*/
public function subscribe(Dispatcher $events)
{
$events->listen('journals.store', 'Firefly\Trigger\Journals\EloquentJournalTrigger@store');
$events->listen('journals.update', 'Firefly\Trigger\Journals\EloquentJournalTrigger@update');
}
/**
* @param \TransactionJournal $journal
*
* @return bool
*/
public function update(\TransactionJournal $journal)
{
return true;
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Firefly\Validation;
use Illuminate\Validation\Validator;
/**
* Class FireflyValidator
*
* @package Firefly\Validation
*/
class FireflyValidator extends Validator
{
public function validateAlphabasic($attribute, $value, $parameters)
{
$pattern = '/[^a-z_\-0-9 ]/i';
if (preg_match($pattern, $value)) {
return false;
} else {
return true;
}
}
}

View File

@@ -0,0 +1,22 @@
<?php
namespace Firefly\Validation;
use Illuminate\Support\ServiceProvider;
class ValidationServiceProvider extends ServiceProvider
{
public function boot()
{
$this->app->validator->resolver(
function ($translator, $data, $rules, $messages) {
return new FireflyValidator($translator, $data, $rules, $messages);
}
);
}
public function register()
{
}
}

View File

@@ -1,20 +1,21 @@
<?php
use LaravelBook\Ardent\Ardent as Ardent;
use LaravelBook\Ardent\Builder;
/**
* Account
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property integer $account_type_id
* @property string $name
* @property boolean $active
* @property-read \AccountType $accountType
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property integer $account_type_id
* @property string $name
* @property boolean $active
* @property-read \AccountType $accountType
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \Illuminate\Database\Eloquent\Collection|\Piggybank[] $piggybanks
* @property-read \User $user
* @property-read \Illuminate\Database\Eloquent\Collection|\Piggybank[] $piggybanks
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Account whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Account whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Account whereUpdatedAt($value)
@@ -22,6 +23,7 @@ use LaravelBook\Ardent\Ardent as Ardent;
* @method static \Illuminate\Database\Query\Builder|\Account whereAccountTypeId($value)
* @method static \Illuminate\Database\Query\Builder|\Account whereName($value)
* @method static \Illuminate\Database\Query\Builder|\Account whereActive($value)
* @method static \Account accountTypeIn($types)
*/
class Account extends Ardent
{
@@ -33,7 +35,7 @@ class Account extends Ardent
*/
public static $rules
= [
'name' => 'required|between:1,100',
'name' => ['required', 'between:1,100', 'alphabasic'],
'user_id' => 'required|exists:users,id',
'account_type_id' => 'required|exists:account_types,id',
'active' => 'required|boolean'
@@ -63,10 +65,10 @@ class Account extends Ardent
return floatval(
$this->transactions()
->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
->leftJoin(
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
)
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount')
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))->sum('transactions.amount')
);
}
@@ -96,7 +98,8 @@ class Account extends Ardent
public function predict(
/** @noinspection PhpUnusedParameterInspection */
\Carbon\Carbon $date
) {
)
{
return null;
}
@@ -110,4 +113,13 @@ class Account extends Ardent
return $this->belongsTo('User');
}
}
public function scopeAccountTypeIn(Builder $query, array $types) {
if(is_null($this->joinedAccountTypes)) {
$query->leftJoin('account_types','account_types.id','=','accounts.account_type_id');
$this->joinedAccountTypes = true;
}
$query->whereIn('account_types.type',$types);
}
}

View File

@@ -1,21 +1,30 @@
<?php
use Illuminate\Database\Eloquent\Model as Eloquent;
/**
* AccountType
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $description
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $type
* @property boolean $editable
* @property-read \Illuminate\Database\Eloquent\Collection|\Account[] $accounts
* @method static \Illuminate\Database\Query\Builder|\AccountType whereId($value)
* @method static \Illuminate\Database\Query\Builder|\AccountType whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\AccountType whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\AccountType whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\AccountType whereType($value)
* @method static \Illuminate\Database\Query\Builder|\AccountType whereEditable($value)
*/
class AccountType extends Eloquent
{
public static $rules
= [
'type' => ['required', 'between:1,50', 'alphabasic'],
'editable' => 'required|boolean',
];
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany

View File

@@ -3,16 +3,16 @@
/**
* Budget
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $name
* @property integer $user_id
* @property string $class
* @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $name
* @property integer $user_id
* @property string $class
* @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Budget whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Budget whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Budget whereUpdatedAt($value)
@@ -33,7 +33,7 @@ class Budget extends Component
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany|\TransactionJournal
*/
public function transactionjournals()
{

View File

@@ -3,16 +3,16 @@
/**
* Category
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $name
* @property integer $user_id
* @property string $class
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $name
* @property integer $user_id
* @property string $class
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user
* @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Category whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Category whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Category whereUpdatedAt($value)

View File

@@ -4,16 +4,16 @@ use Firefly\Database\SingleTableInheritanceEntity;
/**
* Component
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $name
* @property integer $user_id
* @property string $class
* @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $name
* @property integer $user_id
* @property string $class
* @property-read \Illuminate\Database\Eloquent\Collection|\Limit[] $limits
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Component whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Component whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Component whereUpdatedAt($value)
@@ -27,7 +27,7 @@ class Component extends SingleTableInheritanceEntity
public static $rules
= [
'user_id' => 'exists:users,id|required',
'name' => 'required|between:1,255',
'name' => ['required', 'between:1,100', 'alphabasic'],
'class' => 'required',
];
protected $table = 'components';

View File

@@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Eloquent\Model as Eloquent;
/**
* Importentry
*
* @property-read \Importmap $importmap
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $class
* @property integer $importmap_id
* @property integer $old
* @property integer $new
* @method static \Illuminate\Database\Query\Builder|\Importentry whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Importentry whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Importentry whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Importentry whereClass($value)
* @method static \Illuminate\Database\Query\Builder|\Importentry whereImportmapId($value)
* @method static \Illuminate\Database\Query\Builder|\Importentry whereOld($value)
* @method static \Illuminate\Database\Query\Builder|\Importentry whereNew($value)
*/
class Importentry extends Eloquent {
public function importmap()
{
return $this->belongsTo('Importmap');
}
}

29
app/models/Importmap.php Normal file
View File

@@ -0,0 +1,29 @@
<?php
use Illuminate\Database\Eloquent\Model as Eloquent;
/**
* Class Importmap
*
* @property-read \User $user
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property string $file
* @method static \Illuminate\Database\Query\Builder|\Importmap whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Importmap whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Importmap whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Importmap whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\Importmap whereFile($value)
*/
class Importmap extends Eloquent
{
/**
* User
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo('User');
}
}

View File

@@ -7,16 +7,16 @@ use LaravelBook\Ardent\Ardent as Ardent;
/**
* Limit
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $component_id
* @property \Carbon\Carbon $startdate
* @property float $amount
* @property boolean $repeats
* @property string $repeat_freq
* @property-read \Budget $budget
* @property-read \Component $component
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $component_id
* @property \Carbon\Carbon $startdate
* @property float $amount
* @property boolean $repeats
* @property string $repeat_freq
* @property-read \Budget $budget
* @property-read \Component $component
* @property-read \Illuminate\Database\Eloquent\Collection|\LimitRepetition[] $limitrepetitions
* @method static \Illuminate\Database\Query\Builder|\Limit whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Limit whereCreatedAt($value)

View File

@@ -5,14 +5,14 @@ use LaravelBook\Ardent\Ardent as Ardent;
/**
* LimitRepetition
*
* @property integer $id
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $limit_id
* @property integer $limit_id
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $enddate
* @property float $amount
* @property-read \Limit $limit
* @property float $amount
* @property-read \Limit $limit
* @method static \Illuminate\Database\Query\Builder|\LimitRepetition whereId($value)
* @method static \Illuminate\Database\Query\Builder|\LimitRepetition whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\LimitRepetition whereUpdatedAt($value)

View File

@@ -5,25 +5,26 @@ use LaravelBook\Ardent\Ardent as Ardent;
/**
* Piggybank
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $account_id
* @property string $name
* @property float $targetamount
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $targetdate
* @property boolean $repeats
* @property string $rep_length
* @property integer $rep_every
* @property integer $rep_times
* @property string $reminder
* @property integer $reminder_skip
* @property integer $order
* @property-read \Account $account
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $account_id
* @property string $name
* @property float $targetamount
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $targetdate
* @property boolean $repeats
* @property string $rep_length
* @property integer $rep_every
* @property integer $rep_times
* @property string $reminder
* @property integer $reminder_skip
* @property integer $order
* @property-read \Account $account
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankRepetition[] $piggybankrepetitions
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankEvent[] $piggybankevents
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankEvent[] $piggybankevents
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankReminder[] $piggybankreminders
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereUpdatedAt($value)
@@ -39,7 +40,6 @@ use LaravelBook\Ardent\Ardent as Ardent;
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereReminder($value)
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereReminderSkip($value)
* @method static \Illuminate\Database\Query\Builder|\Piggybank whereOrder($value)
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankReminder[] $piggybankreminders
*/
class Piggybank extends Ardent
{

View File

@@ -5,12 +5,12 @@ use LaravelBook\Ardent\Ardent as Ardent;
/**
* PiggybankEvent
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $piggybank_id
* @property \Carbon\Carbon $date
* @property float $amount
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $piggybank_id
* @property \Carbon\Carbon $date
* @property float $amount
* @property-read \Piggybank $piggybank
* @method static \Illuminate\Database\Query\Builder|\PiggybankEvent whereId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankEvent whereCreatedAt($value)

View File

@@ -2,7 +2,7 @@
use Carbon\Carbon;
/**
* Class PiggybankReminder
* PiggybankReminder
*
* @property integer $id
* @property \Carbon\Carbon $created_at
@@ -17,18 +17,18 @@ use Carbon\Carbon;
* @property-read \Piggybank $piggybank
* @property-read \RecurringTransaction $recurringTransaction
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereClass($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder wherePiggybankId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereRecurringTransactionId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereActive($value)
* @method static \Reminder validOn($date)
* @method static \Reminder validOnOrAfter($date)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereClass($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder wherePiggybankId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereRecurringTransactionId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankReminder whereActive($value)
* @method static \Reminder validOn($date)
* @method static \Reminder validOnOrAfter($date)
*/
class PiggybankReminder extends Reminder
{

View File

@@ -1,17 +1,16 @@
<?php
use LaravelBook\Ardent\Ardent as Ardent;
/**
* PiggybankRepetition
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $piggybank_id
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $targetdate
* @property float $currentamount
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $piggybank_id
* @property \Carbon\Carbon $startdate
* @property \Carbon\Carbon $targetdate
* @property float $currentamount
* @property-read \Piggybank $piggybank
* @method static \Illuminate\Database\Query\Builder|\PiggybankRepetition whereId($value)
* @method static \Illuminate\Database\Query\Builder|\PiggybankRepetition whereCreatedAt($value)

View File

@@ -2,17 +2,16 @@
use LaravelBook\Ardent\Ardent;
/**
* Preference
*
* @property integer $id
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property string $name
* @property string $data
* @property-read \User $user
* @property integer $user_id
* @property string $name
* @property string $data
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Preference whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Preference whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Preference whereUpdatedAt($value)

View File

@@ -5,20 +5,21 @@ use LaravelBook\Ardent\Ardent;
/**
* RecurringTransaction
*
* @property integer $id
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property string $name
* @property string $match
* @property float $amount_max
* @property float $amount_min
* @property integer $user_id
* @property string $name
* @property string $match
* @property float $amount_max
* @property float $amount_min
* @property \Carbon\Carbon $date
* @property boolean $active
* @property boolean $automatch
* @property string $repeat_freq
* @property integer $skip
* @property-read \User $user
* @property boolean $active
* @property boolean $automatch
* @property string $repeat_freq
* @property integer $skip
* @property-read \Illuminate\Database\Eloquent\Collection|\RecurringTransactionReminder[] $reminders
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereUpdatedAt($value)
@@ -32,7 +33,6 @@ use LaravelBook\Ardent\Ardent;
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereAutomatch($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereRepeatFreq($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransaction whereSkip($value)
* @property-read \Illuminate\Database\Eloquent\Collection|\RecurringTransactionReminder[] $reminders
*/
class RecurringTransaction extends Ardent
{

View File

@@ -1,7 +1,7 @@
<?php
/**
* Class RecurringTransactionReminder
* RecurringTransactionReminder
*
* @property integer $id
* @property \Carbon\Carbon $created_at
@@ -16,18 +16,18 @@
* @property-read \Piggybank $piggybank
* @property-read \RecurringTransaction $recurringTransaction
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereClass($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder wherePiggybankId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereRecurringTransactionId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereActive($value)
* @method static \Reminder validOn($date)
* @method static \Reminder validOnOrAfter($date)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereClass($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder wherePiggybankId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereRecurringTransactionId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\RecurringTransactionReminder whereActive($value)
* @method static \Reminder validOn($date)
* @method static \Reminder validOnOrAfter($date)
*/
class RecurringTransactionReminder extends Reminder
{

View File

@@ -3,10 +3,8 @@
use Carbon\Carbon;
use Firefly\Database\SingleTableInheritanceEntity;
/**
* Class Reminder
* // reminder for: recurring, piggybank.
* Reminder
*
* @property integer $id
* @property \Carbon\Carbon $created_at
@@ -21,18 +19,18 @@ use Firefly\Database\SingleTableInheritanceEntity;
* @property-read \Piggybank $piggybank
* @property-read \RecurringTransaction $recurringTransaction
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\Reminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereClass($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder wherePiggybankId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereRecurringTransactionId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereActive($value)
* @method static \Reminder validOn($date)
* @method static \Reminder validOnOrAfter($date)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereUpdatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereClass($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder wherePiggybankId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereRecurringTransactionId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereStartdate($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereEnddate($value)
* @method static \Illuminate\Database\Query\Builder|\Reminder whereActive($value)
* @method static \Reminder validOn($date)
* @method static \Reminder validOnOrAfter($date)
*/
class Reminder extends SingleTableInheritanceEntity
{

View File

@@ -1,25 +1,27 @@
<?php
use Carbon\Carbon;
use LaravelBook\Ardent\Ardent;
use LaravelBook\Ardent\Builder;
/**
* Transaction
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $account_id
* @property integer $piggybank_id
* @property integer $transaction_journal_id
* @property string $description
* @property float $amount
* @property-read \Account $account
* @property-read \Illuminate\Database\Eloquent\Collection|\Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\Category[] $categories
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $account_id
* @property integer $piggybank_id
* @property integer $transaction_journal_id
* @property string $description
* @property float $amount
* @property-read \Account $account
* @property-read \Illuminate\Database\Eloquent\Collection|\Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
* @property-read \Piggybank $piggybank
* @property-read \TransactionJournal $transactionJournal
* @property-read \Piggybank $piggybank
* @property-read \TransactionJournal $transactionJournal
* @method static \Illuminate\Database\Query\Builder|\Transaction whereId($value)
* @method static \Illuminate\Database\Query\Builder|\Transaction whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\Transaction whereUpdatedAt($value)
@@ -28,6 +30,12 @@ use LaravelBook\Ardent\Ardent;
* @method static \Illuminate\Database\Query\Builder|\Transaction whereTransactionJournalId($value)
* @method static \Illuminate\Database\Query\Builder|\Transaction whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\Transaction whereAmount($value)
* @method static \Transaction account($account)
* @method static \Transaction after($date)
* @method static \Transaction before($date)
* @method static \Transaction lessThan($amount)
* @method static \Transaction moreThan($amount)
* @method static \Transaction transactionTypes($types)
*/
class Transaction extends Ardent
{
@@ -81,6 +89,56 @@ class Transaction extends Ardent
return $this->belongsTo('Piggybank');
}
public function scopeAccount(Builder $query, Account $account)
{
$query->where('transactions.account_id', $account->id);
}
public function scopeAfter(Builder $query, Carbon $date)
{
if (is_null($this->joinedJournals)) {
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=',
'transactions.transaction_journal_id');
$this->joinedJournals = true;
}
$query->where('transaction_journals.date', '>=', $date->format('Y-m-d'));
}
public function scopeBefore(Builder $query, Carbon $date)
{
if (is_null($this->joinedJournals)) {
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=',
'transactions.transaction_journal_id');
$this->joinedJournals = true;
}
$query->where('transaction_journals.date', '<=', $date->format('Y-m-d'));
}
public function scopeLessThan(Builder $query, $amount)
{
$query->where('amount', '<', $amount);
}
public function scopeMoreThan(Builder $query, $amount)
{
$query->where('amount', '>', $amount);
}
public function scopeTransactionTypes(Builder $query, array $types)
{
if (is_null($this->joinedJournals)) {
$query->leftJoin('transaction_journals', 'transaction_journals.id', '=',
'transactions.transaction_journal_id');
$this->joinedJournals = true;
}
if (is_null($this->joinedTransactionTypes)) {
$query->leftJoin('transaction_types', 'transaction_types.id', '=',
'transaction_journals.transaction_type_id');
$this->joinedTransactionTypes = true;
}
$query->whereIn('transaction_types.type', $types);
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/

View File

@@ -1,12 +1,12 @@
<?php
use Illuminate\Database\Eloquent\Model as Eloquent;
/**
* TransactionCurrency
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $code
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $code
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @method static \Illuminate\Database\Query\Builder|\TransactionCurrency whereId($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionCurrency whereCreatedAt($value)

View File

@@ -2,29 +2,29 @@
use Carbon\Carbon;
use LaravelBook\Ardent\Ardent;
use LaravelBook\Ardent\Builder;
/**
* TransactionJournal
*
* @property integer $id
* @property Carbon $created_at
* @property Carbon $updated_at
* @property integer $user_id
* @property integer $transaction_type_id
* @property integer $transaction_currency_id
* @property string $description
* @property boolean $completed
* @property Carbon $date
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property integer $user_id
* @property integer $transaction_type_id
* @property integer $transaction_currency_id
* @property string $description
* @property boolean $completed
* @property \Carbon\Carbon $date
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
* @property-read \TransactionCurrency $transactionCurrency
* @property-read \TransactionType $transactionType
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
* @property-read \TransactionCurrency $transactionCurrency
* @property-read \TransactionType $transactionType
* @property-read \Illuminate\Database\Eloquent\Collection|\Transaction[] $transactions
* @property-read \User $user
* @property-read \User $user
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereId($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereUpdatedAt($value)
@@ -34,13 +34,67 @@ use LaravelBook\Ardent\Ardent;
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDescription($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereCompleted($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionJournal whereDate($value)
* @method static \TransactionJournal account($account)
* @method static \TransactionJournal after($date)
* @method static \TransactionJournal before($date)
* @method static \TransactionJournal defaultSorting()
* @method static \TransactionJournal moreThan($amount)
* @method static \TransactionJournal lessThan($amount)
* @method static \TransactionJournal onDate($date)
* @method static \TransactionJournal transactionTypes($types)
* @method static \TransactionJournal withRelevantData()
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @method static \TransactionJournal onDate($date)
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\
* 'Category[] $categories
*/
class TransactionJournal extends Ardent
{
@@ -61,7 +115,7 @@ class TransactionJournal extends Ardent
public function budgets()
{
return $this->belongsToMany(
'Budget', 'component_transaction_journal', 'transaction_journal_id', 'component_id'
'Budget', 'component_transaction_journal', 'transaction_journal_id', 'component_id'
);
}
@@ -71,7 +125,7 @@ class TransactionJournal extends Ardent
public function categories()
{
return $this->belongsToMany(
'Category', 'component_transaction_journal', 'transaction_journal_id', 'component_id'
'Category', 'component_transaction_journal', 'transaction_journal_id', 'component_id'
);
}
@@ -83,6 +137,14 @@ class TransactionJournal extends Ardent
return $this->belongsToMany('Component');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function recurringTransaction()
{
return $this->belongsTo('RecurringTransaction');
}
/**
* @return array
*/
@@ -91,9 +153,18 @@ class TransactionJournal extends Ardent
return ['created_at', 'updated_at', 'date'];
}
public function scopeAccount(Builder $query, \Account $account)
{
if (!isset($this->joinedTransactions)) {
$query->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id');
$this->joinedTransactions = true;
}
$query->where('transactions.account_id', $account->id);
}
/**
* @param $query
* @param Carbon $date
* @param Carbon $date
*
* @return mixed
*/
@@ -104,7 +175,7 @@ class TransactionJournal extends Ardent
/**
* @param $query
* @param Carbon $date
* @param Carbon $date
*
* @return mixed
*/
@@ -113,6 +184,33 @@ class TransactionJournal extends Ardent
return $query->where('date', '<=', $date->format('Y-m-d'));
}
public function scopeDefaultSorting(Builder $query)
{
$query->orderBy('date', 'DESC')->orderBy('transaction_journals.id', 'DESC');
}
public function scopeMoreThan(Builder $query, $amount)
{
if (is_null($this->joinedTransactions)) {
$query->leftJoin('transactions', 'transactions.transaction_journal_id', '=',
'transaction_journals.id');
$this->joinedTransactions = true;
}
$query->where('transactions.amount', '>=', $amount);
}
public function scopeLessThan(Builder $query, $amount)
{
if (is_null($this->joinedTransactions)) {
$query->leftJoin('transactions', 'transactions.transaction_journal_id', '=',
'transaction_journals.id');
$this->joinedTransactions = true;
}
$query->where('transactions.amount', '<=', $amount);
}
/**
* @param $query
* @param Carbon $date
@@ -124,6 +222,33 @@ class TransactionJournal extends Ardent
return $query->where('date', '=', $date->format('Y-m-d'));
}
public function scopeTransactionTypes(Builder $query, array $types)
{
if (is_null($this->joinedTransactionTypes)) {
$query->leftJoin('transaction_types', 'transaction_types.id', '=',
'transaction_journals.transaction_type_id');
$this->joinedTransactionTypes = true;
}
$query->whereIn('transaction_types.type', $types);
}
/**
* Automatically includes the 'with' parameters to get relevant related
* objects.
*
* @param $query
*/
public function scopeWithRelevantData(Builder $query)
{
$query->with(
['transactions' => function ($q) {
$q->orderBy('amount', 'ASC');
}, 'transactiontype', 'components' => function ($q) {
$q->orderBy('class');
}, 'transactions.account.accounttype','recurringTransaction']
);
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
@@ -158,4 +283,4 @@ class TransactionJournal extends Ardent
return $this->belongsTo('User');
}
}
}

View File

@@ -5,10 +5,10 @@ use LaravelBook\Ardent\Ardent;
/**
* TransactionType
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $type
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $type
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionJournals
* @method static \Illuminate\Database\Query\Builder|\TransactionType whereId($value)
* @method static \Illuminate\Database\Query\Builder|\TransactionType whereCreatedAt($value)

View File

@@ -10,21 +10,23 @@ use LaravelBook\Ardent\Ardent;
/**
* User
*
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $email
* @property string $password
* @property string $reset
* @property string $remember_token
* @property boolean $migrated
* @property-read \Illuminate\Database\Eloquent\Collection|\Account[] $accounts
* @property-read \Illuminate\Database\Eloquent\Collection|\Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
* @property-read \Illuminate\Database\Eloquent\Collection|\Preference[] $preferences
* @property integer $id
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property string $email
* @property string $password
* @property string $reset
* @property string $remember_token
* @property boolean $migrated
* @property-read \Illuminate\Database\Eloquent\Collection|\Account[] $accounts
* @property-read \Illuminate\Database\Eloquent\Collection|\Budget[] $budgets
* @property-read \Illuminate\Database\Eloquent\Collection|\Reminder[] $reminders
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankReminder[] $piggybankreminders
* @property-read \Illuminate\Database\Eloquent\Collection|\Category[] $categories
* @property-read \Illuminate\Database\Eloquent\Collection|\Component[] $components
* @property-read \Illuminate\Database\Eloquent\Collection|\Preference[] $preferences
* @property-read \Illuminate\Database\Eloquent\Collection|\RecurringTransaction[] $recurringtransactions
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @property-read \Illuminate\Database\Eloquent\Collection|\TransactionJournal[] $transactionjournals
* @method static \Illuminate\Database\Query\Builder|\User whereId($value)
* @method static \Illuminate\Database\Query\Builder|\User whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\User whereUpdatedAt($value)
@@ -33,8 +35,6 @@ use LaravelBook\Ardent\Ardent;
* @method static \Illuminate\Database\Query\Builder|\User whereReset($value)
* @method static \Illuminate\Database\Query\Builder|\User whereRememberToken($value)
* @method static \Illuminate\Database\Query\Builder|\User whereMigrated($value)
* @property-read \Illuminate\Database\Eloquent\Collection|\Reminder[] $reminders
* @property-read \Illuminate\Database\Eloquent\Collection|\PiggybankReminder[] $piggybankreminders
*/
class User extends Ardent implements UserInterface, RemindableInterface
{

View File

@@ -1,23 +1,33 @@
<?php
//use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
// models:
Route::bind('account', function($value, $route)
{
if(Auth::check()) {
return Account::
where('id', $value)->
where('user_id',Auth::user()->id)->first();
$account = Account::
leftJoin('account_types','account_types.id','=','accounts.account_type_id')->
where('account_types.editable',1)->
where('accounts.id', $value)->
where('user_id',Auth::user()->id)->
first(['accounts.*']);
if($account) {
return $account;
}
}
return null;
App::abort(404);
});
Route::bind('accountname', function($value, $route)
{
if(Auth::check()) {
$type = AccountType::where('description','Default account')->first();
return Account::
leftJoin('account_types','account_types.id','=','accounts.account_type_id')->
where('account_types.editable',1)->
where('name', $value)->
where('account_type_id',$type->id)->
where('user_id',Auth::user()->id)->first();
}
return null;
@@ -124,7 +134,7 @@ Route::group(['before' => 'auth'], function () {
Route::get('/budgets',['uses' => 'BudgetController@indexByDate','as' => 'budgets.index']);
Route::get('/budgets/create',['uses' => 'BudgetController@create', 'as' => 'budgets.create']);
Route::get('/budgets/budget',['uses' => 'BudgetController@indexByBudget','as' => 'budgets.index.budget']);
Route::get('/budgets/show/{budget}',['uses' => 'BudgetController@show', 'as' => 'budgets.show']);
Route::get('/budgets/show/{budget}/{limitrepetition?}',['uses' => 'BudgetController@show', 'as' => 'budgets.show']);
Route::get('/budgets/edit/{budget}',['uses' => 'BudgetController@edit', 'as' => 'budgets.edit']);
Route::get('/budgets/delete/{budget}',['uses' => 'BudgetController@delete', 'as' => 'budgets.delete']);
@@ -147,8 +157,6 @@ Route::group(['before' => 'auth'], function () {
Route::get('chart/budget/{budget}/session', ['uses' => 'ChartController@budgetSession', 'as' => 'chart.budget.session']);
Route::get('chart/budget/envelope/{limitrepetition}', ['uses' => 'ChartController@budgetLimit', 'as' => 'chart.budget.limit']);
// home controller
Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index']);
Route::get('/flush', ['uses' => 'HomeController@flush', 'as' => 'flush']);
@@ -162,20 +170,19 @@ Route::group(['before' => 'auth'], function () {
Route::get('/budgets/limits/delete/{limit}',['uses' => 'LimitController@delete','as' => 'budgets.limits.delete']);
Route::get('/budgets/limits/edit/{limit}',['uses' => 'LimitController@edit','as' => 'budgets.limits.edit']);
Route::get('/migrate',['uses' => 'MigrateController@index', 'as' => 'migrate.index']);
// piggy bank controller
Route::get('/piggybanks',['uses' => 'PiggybankController@index','as' => 'piggybanks.index']);
Route::get('/piggybanks/create/piggybank', ['uses' => 'PiggybankController@createPiggybank','as' => 'piggybanks.create.piggybank']);
Route::get('/piggybanks/create/repeated', ['uses' => 'PiggybankController@createRepeated','as' => 'piggybanks.create.repeated']);
Route::get('/piggybanks/addMoney/{piggybank}', ['uses' => 'PiggybankController@addMoney','as' => 'piggybanks.amount.add']);
Route::get('/piggybanks/removeMoney/{piggybank}', ['uses' => 'PiggybankController@removeMoney','as' => 'piggybanks.amount.remove']);
Route::get('/piggybanks/show/{piggybank}', ['uses' => 'PiggybankController@show','as' => 'piggybanks.show']);
Route::get('/piggybanks/edit/{piggybank}', ['uses' => 'PiggybankController@edit','as' => 'piggybanks.edit']);
Route::get('/piggybanks/delete/{piggybank}', ['uses' => 'PiggybankController@delete','as' => 'piggybanks.delete']);
Route::post('/piggybanks/updateAmount/{piggybank}',['uses' => 'PiggybankController@updateAmount','as' => 'piggybanks.updateAmount']);
// preferences controller
Route::get('/preferences', ['uses' => 'PreferencesController@index', 'as' => 'preferences']);
@@ -237,6 +244,8 @@ Route::group(['before' => 'csrf|auth'], function () {
Route::post('/budgets/limits/destroy/{limit}',['uses' => 'LimitController@destroy','as' => 'budgets.limits.destroy']);
Route::post('/budgets/limits/update/{limit}',['uses' => 'LimitController@update','as' => 'budgets.limits.update']);
Route::post('/migrate/upload',['uses' => 'MigrateController@upload', 'as' => 'migrate.upload']);
// piggy bank controller
Route::post('/piggybanks/store/piggybank',['uses' => 'PiggybankController@storePiggybank','as' => 'piggybanks.store.piggybank']);

View File

@@ -1,452 +0,0 @@
<?php
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class AccountControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
* @coversDefaultClass \AccountController
*/
class AccountControllerTest extends TestCase
{
protected $_repository;
protected $_user;
protected $_accounts;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_repository = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
$this->_accounts = $this->mock('Firefly\Helper\Controllers\AccountInterface');
$this->_user = m::mock('User', 'Eloquent');
}
public function tearDown()
{
Mockery::close();
}
/**
* @covers ::create
*/
public function testCreate()
{
View::shouldReceive('make')->with('accounts.create')->once();
$this->action('GET', 'AccountController@create');
$this->assertResponseOk();
}
/**
* @covers ::delete
*/
public function testDelete()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'AccountController@delete', $account->id);
$this->assertViewHas('account');
$this->assertResponseOk();
}
/**
* @covers ::delete
*/
public function testDeleteWrongType()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Initial balance account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'AccountController@delete', $account->id);
$this->assertViewHas('message');
$this->assertResponseOk();
}
/**
* @covers ::destroy
*/
public function testDestroy()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->once()->andReturn($this->_user);
Auth::shouldReceive('check')->once()->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_repository->shouldReceive('destroy')->once()->andReturn(true);
$this->action('POST', 'AccountController@destroy', $account->id);
$this->assertRedirectedToRoute('accounts.index');
$this->assertSessionHas('success');
}
/**
* @covers ::destroy
*/
public function testDestroyWrongType()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Initial balance account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->once()->andReturn($this->_user);
Auth::shouldReceive('check')->once()->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->action('POST', 'AccountController@destroy', $account->id);
$this->assertViewHas('message');
$this->assertResponseOk();
}
/**
* @covers ::destroy
*/
public function testDestroyFails()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->once()->andReturn($this->_user);
Auth::shouldReceive('check')->once()->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_repository->shouldReceive('destroy')->once()->andReturn(false);
$this->action('POST', 'AccountController@destroy', $account->id);
$this->assertRedirectedToRoute('accounts.index');
$this->assertSessionHas('error');
}
public function testEdit()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_accounts->shouldReceive('openingBalanceTransaction')->once()->andReturn(null);
// test if the view works:
View::shouldReceive('make')->with('accounts.edit')->once()->andReturn(m::self())->shouldReceive('with')->with(
'account', m::any()
)
->andReturn(m::self())->shouldReceive('with')->with('openingBalance', null)->andReturn(m::self());
$this->action('GET', 'AccountController@edit', $account->id);
$this->assertResponseOk();
}
public function testEditWrongType()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Initial balance account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'AccountController@edit', $account->id);
$this->assertViewHas('message');
$this->assertResponseOk();
}
public function testIndex()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
$collection = new Collection();
$collection->add($account);
$list = [
'personal' => [],
'beneficiaries' => [],
'initial' => [],
'cash' => []
];
$this->_repository->shouldReceive('get')->once()->andReturn($collection);
$this->_accounts->shouldReceive('index')->with($collection)->once()->andReturn($list);
$this->action('GET', 'AccountController@index');
$this->assertResponseOk();
}
public function testShow()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn($account->email);
$this->session(['start' => new Carbon, 'end' => new Carbon]);
// some more mockery
$paginator = \Paginator::make([], 0, 10);
$data = [
'statistics' => [
'period' => [
'in' => 0,
'out' => 0,
'diff' => 0,
't_in' => 0,
't_out' => 0,
't_diff' => 0
],
'categories' => [],
'budgets' => [],
'accounts' => []
],
'journals' => $paginator,
];
$this->_accounts->shouldReceive('show')->once()->andReturn($data);
$this->action('GET', 'AccountController@show', $account->id);
$this->assertResponseOk();
}
public function testShowWrongType()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Initial balance account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn($account->email);
$this->action('GET', 'AccountController@show', $account->id);
$this->assertViewHas('message');
$this->assertResponseOk();
}
public function testStore()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
$this->_repository->shouldReceive('store')->andReturn($account);
$this->action('POST', 'AccountController@store');
$this->assertRedirectedToRoute('accounts.index');
}
public function testStoreFails()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
unset($account->name);
$this->_repository->shouldReceive('store')->andReturn($account);
$this->action('POST', 'AccountController@store');
$this->assertRedirectedToRoute('accounts.create');
}
public function testStoreRecreate()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
$this->_repository->shouldReceive('store')->andReturn($account);
$this->action('POST', 'AccountController@store', ['create' => '1']);
$this->assertRedirectedToRoute('accounts.create');
}
public function testUpdate()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_repository->shouldReceive('update')->andReturn($account);
$this->action('POST', 'AccountController@update', $account->id);
$this->assertRedirectedToRoute('accounts.index');
}
public function testUpdateWrongType()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Initial balance account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_repository->shouldReceive('update')->andReturn($account);
$this->action('POST', 'AccountController@update', $account->id);
$this->assertViewHas('message');
$this->assertResponseOk();
}
public function testUpdateFails()
{
/** @var \Account $account */
$account = f::create('Account');
/** @var \AccountType $accountType */
$accountType = f::create('AccountType');
$accountType->description = 'Default account';
$accountType->save();
$account->accountType()->associate($accountType);
$account->save();
unset($account->name);
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($account->user_id);
$this->_repository->shouldReceive('update')->andReturn($account);
$this->action('POST', 'AccountController@update', $account->id);
$this->assertRedirectedToRoute('accounts.edit', $account->id);
}
}

View File

@@ -1,274 +0,0 @@
<?php
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class BudgetControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class BudgetControllerTest extends TestCase
{
protected $_repository;
protected $_user;
protected $_budgets;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_repository = $this->mock('Firefly\Storage\Budget\BudgetRepositoryInterface');
$this->_budgets = $this->mock('Firefly\Helper\Controllers\BudgetInterface');
$this->_user = m::mock('User', 'Eloquent');
}
public function tearDown()
{
Mockery::close();
}
public function testCreate()
{
$this->action('GET', 'BudgetController@create');
$this->assertResponseOk();
}
public function testDelete()
{
$budget = f::create('Budget');
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn('some@email');
$this->action('GET', 'BudgetController@delete', $budget->id);
$this->assertResponseOk();
}
public function testDestroy()
{
$budget = f::create('Budget');
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
Event::shouldReceive('fire')->once()->with('budgets.destroy', [$budget]);
$this->_repository->shouldReceive('destroy')->once()->andReturn(true);
$this->action('POST', 'BudgetController@destroy', $budget->id);
$this->assertRedirectedToRoute('budgets.index.budget');
$this->assertSessionHas('success');
}
public function testDestroyByDate()
{
$budget = f::create('Budget');
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
Event::shouldReceive('fire')->once()->with('budgets.destroy', [$budget]);
$this->_repository->shouldReceive('destroy')->once()->andReturn(true);
$this->action('POST', 'BudgetController@destroy', [$budget->id, 'from' => 'date']);
$this->assertRedirectedToRoute('budgets.index');
$this->assertSessionHas('success');
}
public function testDestroyFails()
{
$budget = f::create('Budget');
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
Event::shouldReceive('fire')->once()->with('budgets.destroy', [$budget]);
$this->_repository->shouldReceive('destroy')->once()->andReturn(false);
$this->action('POST', 'BudgetController@destroy', $budget->id);
$this->assertRedirectedToRoute('budgets.index');
$this->assertSessionHas('error');
}
public function testEdit()
{
$budget = f::create('Budget');
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn('some@email');
$this->action('GET', 'BudgetController@edit', $budget->id);
$this->assertResponseOk();
}
public function testIndexByBudget()
{
$this->_repository->shouldReceive('get')->once()->andReturn([]);
$this->action('GET', 'BudgetController@indexByBudget');
$this->assertResponseOk();
}
public function testIndexByDate()
{
$collection = new Collection();
$this->_repository->shouldReceive('get')->once()->andReturn($collection);
$this->_budgets->shouldReceive('organizeByDate')->with($collection)->andReturn([]);
$this->action('GET', 'BudgetController@indexByDate');
$this->assertResponseOk();
}
public function testShow()
{
$budget = f::create('Budget');
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn($budget->email);
$this->session(['start' => new Carbon, 'end' => new Carbon]);
$this->_budgets->shouldReceive('organizeRepetitions')->once()->andReturn([]);
$this->action('GET', 'BudgetController@show', $budget->id);
$this->assertResponseOk();
}
public function testShowNoEnvelope()
{
$budget = f::create('Budget');
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn($budget->email);
$this->session(['start' => new Carbon, 'end' => new Carbon]);
$this->_budgets->shouldReceive('outsideRepetitions')->once()->andReturn([]);
$this->action('GET', 'BudgetController@show', [$budget->id, 'noenvelope' => 'true']);
$this->assertResponseOk();
}
public function testShowWithRep()
{
$budget = f::create('Budget');
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn($budget->email);
$this->session(['start' => new Carbon, 'end' => new Carbon]);
// $this->_budgets->shouldReceive('show')->once()->andReturn([]);
$arr = [0 => ['limitrepetition' => null, 'limit' => null, 'date' => '']];
$this->_budgets->shouldReceive('organizeRepetition')->once()->andReturn($arr);
$this->action('GET', 'BudgetController@show', [$budget->id, 'rep' => '1']);
$this->assertResponseOk();
}
public function testStore()
{
$budget = f::create('Budget');
$this->_repository->shouldReceive('store')->andReturn($budget);
$this->action('POST', 'BudgetController@store');
$this->assertRedirectedToRoute('budgets.index.budget');
}
public function testStoreFromDate()
{
$budget = f::create('Budget');
$this->_repository->shouldReceive('store')->andReturn($budget);
$this->action('POST', 'BudgetController@store', ['from' => 'date']);
$this->assertRedirectedToRoute('budgets.index');
}
public function testStoreFails()
{
$budget = f::create('Budget');
unset($budget->name);
$this->_repository->shouldReceive('store')->andReturn($budget);
$this->action('POST', 'BudgetController@store', ['from' => 'budget']);
$this->assertRedirectedToRoute('budgets.create');
}
public function testStoreRecreate()
{
$budget = f::create('Budget');
$this->_repository->shouldReceive('store')->andReturn($budget);
$this->action('POST', 'BudgetController@store', ['from' => 'budget', 'create' => '1']);
$this->assertRedirectedToRoute('budgets.create', ['from' => 'budget']);
}
public function testUpdate()
{
$budget = f::create('Budget');
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
$this->_repository->shouldReceive('update')->andReturn($budget);
Event::shouldReceive('fire')->with('budgets.update', [$budget]);
$this->action('POST', 'BudgetController@update', $budget->id);
$this->assertRedirectedToRoute('budgets.index.budget');
}
public function testUpdateFromDate()
{
$budget = f::create('Budget');
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
$this->_repository->shouldReceive('update')->andReturn($budget);
Event::shouldReceive('fire')->with('budgets.update', [$budget]);
//$this->_user->shouldReceive('budgets')->andReturn([]); // trigger
$this->action('POST', 'BudgetController@update', [$budget->id, 'from' => 'date']);
$this->assertRedirectedToRoute('budgets.index');
}
public function testUpdateFails()
{
$budget = f::create('Budget');
unset($budget->name);
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($budget->user_id);
$this->_repository->shouldReceive('update')->andReturn($budget);
$this->action('POST', 'BudgetController@update', $budget->id);
$this->assertRedirectedToRoute('budgets.edit', $budget->id);
}
}

View File

@@ -1,183 +0,0 @@
<?php
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class CategoryControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class CategoryControllerTest extends TestCase
{
protected $_repository;
protected $_user;
protected $_category;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_repository = $this->mock('Firefly\Storage\Category\CategoryRepositoryInterface');
$this->_category = $this->mock('Firefly\Helper\Controllers\CategoryInterface');
$this->_user = m::mock('User', 'Eloquent');
}
public function tearDown()
{
Mockery::close();
}
public function testCreate()
{
$this->action('GET', 'CategoryController@create');
$this->assertResponseOk();
}
public function testDelete()
{
$category = f::create('Category');
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($category->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn('some@email');
$this->action('GET', 'CategoryController@delete', $category->id);
$this->assertResponseOk();
}
public function testDestroy()
{
$category = f::create('Category');
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($category->user_id);
$this->_repository->shouldReceive('destroy')->once()->andReturn(true);
$this->action('POST', 'CategoryController@destroy', $category->id);
$this->assertRedirectedToRoute('categories.index');
$this->assertSessionHas('success');
}
public function testDestroyFails()
{
$category = f::create('Category');
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($category->user_id);
$this->_repository->shouldReceive('destroy')->once()->andReturn(false);
$this->action('POST', 'CategoryController@destroy', $category->id);
$this->assertRedirectedToRoute('categories.index');
$this->assertSessionHas('error');
}
public function testEdit()
{
$category = f::create('Category');
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($category->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn('some@email');
$this->action('GET', 'CategoryController@edit', $category->id);
$this->assertResponseOk();
}
public function testIndex()
{
$category = f::create('Category');
$collection = new Collection();
$collection->add($category);
$this->_repository->shouldReceive('get')->with()->once()->andReturn($collection);
$this->action('GET', 'CategoryController@index');
$this->assertResponseOk();
}
public function testShow()
{
$category = f::create('Category');
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($category->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn($category->email);
$this->session(['start' => new Carbon, 'end' => new Carbon]);
$this->_category->shouldReceive('journalsInRange')->once()->andReturn([]);
$this->action('GET', 'CategoryController@show', $category->id);
$this->assertResponseOk();
}
public function testStore()
{
$category = f::create('Category');
$this->_repository->shouldReceive('store')->andReturn($category);
$this->action('POST', 'CategoryController@store');
$this->assertRedirectedToRoute('categories.index');
}
public function testStoreFails()
{
$category = f::create('Category');
unset($category->name);
$this->_repository->shouldReceive('store')->andReturn($category);
$this->action('POST', 'CategoryController@store');
$this->assertRedirectedToRoute('categories.create');
}
public function testStoreRecreate()
{
$category = f::create('Category');
$this->_repository->shouldReceive('store')->andReturn($category);
$this->action('POST', 'CategoryController@store', ['create' => '1']);
$this->assertRedirectedToRoute('categories.create');
}
public function testUpdate()
{
$category = f::create('Category');
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($category->user_id);
$this->_repository->shouldReceive('update')->andReturn($category);
$this->action('POST', 'CategoryController@update', $category->id);
$this->assertRedirectedToRoute('categories.index');
}
public function testUpdateFails()
{
$category = f::create('Category');
unset($category->name);
// for successful binding.
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($category->user_id);
$this->_repository->shouldReceive('update')->andReturn($category);
$this->action('POST', 'CategoryController@update', [$category->id]);
$this->assertResponseStatus(302);
}
}

View File

@@ -1,140 +0,0 @@
<?php
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class ChartControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class ChartControllerTest extends TestCase
{
protected $_user;
// protected $_repository;
protected $_accounts;
protected $_charts;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
$this->_charts = $this->mock('Firefly\Helper\Controllers\ChartInterface');
// $this->_category = $this->mock('Firefly\Helper\Controllers\CategoryInterface');
$this->_user = m::mock('User', 'Eloquent');
}
public function tearDown()
{
Mockery::close();
}
public function testCategoryShowChart()
{
$this->session(['start' => new Carbon, 'end' => new Carbon, 'range' => '1M']);
$category = f::create('Category');
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($category->user_id);
$this->_charts->shouldReceive('categoryShowChart')->once()->andReturn([]);
$this->action('GET', 'ChartController@categoryShowChart', $category->id);
$this->assertResponseOk();
}
public function testHomeAccount()
{
$account = f::create('Account');
$collection = new Collection();
$collection->add($account);
$this->session(['start' => new Carbon, 'end' => new Carbon, 'range' => '1M']);
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('bla@bla');
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn(1);
$this->_accounts->shouldReceive('getByIds')->andReturn($collection);
$this->_charts->shouldReceive('account')->once()->andReturn([]);
$this->action('GET', 'ChartController@homeAccount');
$this->assertResponseOk();
}
public function testHomeAccountInfo()
{
$account = f::create('Account');
$type = f::create('AccountType');
$type->description = 'Default account';
$type->save();
$account->accounttype()->associate($type);
$account->save();
// for successful binding:
Auth::shouldReceive('user')->andReturn($account->user()->first());
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('bla@bla');
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($account->user_id);
$this->_accounts->shouldReceive('findByName')->andReturn($account);
$this->_charts->shouldReceive('accountDailySummary')->once()->andReturn(['rows' => [], 'sum' => 0]);
$this->call('GET', 'chart/home/info/' . $account->name . '/01/08/2014');
$this->assertResponseOk();
}
public function testHomeAccountWithAccount()
{
$account = f::create('Account');
$this->session(['start' => new Carbon, 'end' => new Carbon, 'range' => '1M']);
// for successful binding:
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('bla@bla');
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($account->user_id);
$this->_charts->shouldReceive('account')->once()->andReturn([]);
$this->action('GET', 'ChartController@homeAccount', $account->id);
$this->assertResponseOk();
}
public function testHomeBudgets()
{
$date = new Carbon;
$this->session(['start' => $date]);
$this->_charts->shouldReceive('budgets')->once()->with($date)->andReturn([]);
$this->action('GET', 'ChartController@homeBudgets');
$this->assertResponseOk();
}
public function testHomeCategories()
{
$start = new Carbon;
$end = new Carbon;
$this->_charts->shouldReceive('categories')->once()->with($start, $end)->andReturn([]);
$this->session(['start' => $start, 'end' => $end]);
$this->action('GET', 'ChartController@homeCategories');
$this->assertResponseOk();
}
}

View File

@@ -1,142 +0,0 @@
<?php
use Carbon\Carbon as Carbon;
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class HomeControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class HomeControllerTest extends TestCase
{
protected $_accounts;
protected $_repository;
protected $_preferences;
protected $_journals;
protected $_reminders;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_accounts = $this->mock('Firefly\Helper\Controllers\AccountInterface');
$this->_repository = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
$this->_preferences = $this->mock('Firefly\Helper\Preferences\PreferencesHelperInterface');
$this->_journals = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
$this->_reminders = $this->mock('Firefly\Storage\Reminder\ReminderRepositoryInterface');
}
public function tearDown()
{
Mockery::close();
}
public function testFlush()
{
$this->action('GET', 'HomeController@flush');
$this->assertRedirectedToRoute('index');
}
public function testIndex()
{
// mock preference:
$preference = $this->mock('Preference');
$preference->shouldReceive('getAttribute')->with('data')->andReturn([]);
Event::shouldReceive('fire')->with('limits.check');
Event::shouldReceive('fire')->with('piggybanks.check');
Event::shouldReceive('fire')->with('recurring.check');
$this->_reminders->shouldReceive('getCurrentRecurringReminders')->once()->andReturn([]);
// mock accounts:
$this->_repository->shouldReceive('count')->once()->andReturn(0);
$this->_repository->shouldReceive('getActiveDefault')->once()->andReturn([]);
// mock preferences:
$this->_preferences->shouldReceive('get')->with('frontpageAccounts', [])->andReturn($preference);
$this->action('GET', 'HomeController@index');
$this->assertResponseOk();
}
public function testIndexWithAccount()
{
$account = f::create('Account');
$start = new Carbon;
$end = new Carbon;
$this->session(['start' => $start, 'end' => $end]);
// mock preference:
$preference = $this->mock('Preference');
$preference->shouldReceive('getAttribute')->with('data')->andReturn([$account->id]);
Event::shouldReceive('fire')->with('limits.check');
Event::shouldReceive('fire')->with('piggybanks.check');
Event::shouldReceive('fire')->with('recurring.check');
$this->_reminders->shouldReceive('getCurrentRecurringReminders')->once()->andReturn([]);
// mock accounts:
$this->_repository->shouldReceive('count')->once()->andReturn(0);
$this->_repository->shouldReceive('getByIds')->with([$account->id])->once()->andReturn([$account]);
// mock preferences:
$this->_preferences->shouldReceive('get')->with('frontpageAccounts', [])->andReturn($preference);
// mock journals:
$this->_journals->shouldReceive('getByAccountInDateRange')->once()->with($account, 10, $start, $end)->andReturn(
[1, 2]
);
$this->action('GET', 'HomeController@index');
$this->assertResponseOk();
}
public function testIndexWithAccounts()
{
$accountOne = f::create('Account');
$accountTwo = f::create('Account');
$accounThree = f::create('Account');
$set = [$accountOne, $accountTwo, $accounThree];
$ids = [$accountOne->id, $accountTwo->id, $accounThree->id];
$start = new Carbon;
$end = new Carbon;
$this->session(['start' => $start, 'end' => $end]);
// mock preference:
$preference = $this->mock('Preference');
$preference->shouldReceive('getAttribute')->with('data')->andReturn($ids);
Event::shouldReceive('fire')->with('limits.check');
Event::shouldReceive('fire')->with('piggybanks.check');
Event::shouldReceive('fire')->with('recurring.check');
$this->_reminders->shouldReceive('getCurrentRecurringReminders')->once()->andReturn([]);
// mock accounts:
$this->_repository->shouldReceive('count')->once()->andReturn(0);
$this->_repository->shouldReceive('getByIds')->with($ids)->once()->andReturn(
$set
);
// mock preferences:
$this->_preferences->shouldReceive('get')->with('frontpageAccounts', [])->andReturn($preference);
// mock journals:
$this->_journals->shouldReceive('getByAccountInDateRange')->andReturn([1, 2]);
$this->action('GET', 'HomeController@index');
$this->assertResponseOk();
}
}

View File

@@ -1,45 +0,0 @@
<?php
use League\FactoryMuffin\Facade as f;
/**
* Class JsonControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class JsonControllerTest extends TestCase
{
protected $_accounts;
protected $_categories;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
$this->_categories = $this->mock('Firefly\Storage\Category\CategoryRepositoryInterface');
}
public function tearDown()
{
Mockery::close();
}
public function testBeneficiaries()
{
$beneficiary = f::create('Account');
$this->_accounts->shouldReceive('getBeneficiaries')->once()->andReturn([$beneficiary]);
$this->action('GET', 'JsonController@beneficiaries');
$this->assertResponseOk();
}
public function testCategories()
{
$category = f::create('Category');
$this->_categories->shouldReceive('get')->once()->andReturn([$category]);
$this->action('GET', 'JsonController@categories');
$this->assertResponseOk();
}
}

View File

@@ -1,245 +0,0 @@
<?php
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class LimitControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class LimitControllerTest extends TestCase
{
protected $_budgets;
protected $_limits;
protected $_user;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_user = m::mock('User', 'Eloquent');
$this->_budgets = $this->mock('Firefly\Storage\Budget\BudgetRepositoryInterface');
$this->_limits = $this->mock('Firefly\Storage\Limit\LimitRepositoryInterface');
}
public function tearDown()
{
Mockery::close();
}
public function testCreate()
{
$this->_budgets->shouldReceive('getAsSelectList')->andReturn([]);
$this->action('GET', 'LimitController@create');
$this->assertResponseOk();
}
public function testDelete()
{
$limit = f::create('Limit');
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($limit->budget()->first()->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn('some@email');
$this->action('GET', 'LimitController@delete', $limit->id);
$this->assertResponseOk();
}
public function testDestroy()
{
$limit = f::create('Limit');
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($limit->budget()->first()->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_limits->shouldReceive('destroy')->once()->andReturn(true);
$this->action('POST', 'LimitController@destroy', $limit->id);
$this->assertResponseStatus(302);
}
public function testDestroyFails()
{
$limit = f::create('Limit');
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($limit->budget()->first()->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_limits->shouldReceive('destroy')->once()->andReturn(false);
$this->action('POST', 'LimitController@destroy', $limit->id);
$this->assertResponseStatus(302);
}
public function testDestroyRedirect()
{
$limit = f::create('Limit');
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($limit->budget()->first()->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_limits->shouldReceive('destroy')->once()->andReturn(true);
$this->action('POST', 'LimitController@destroy', [$limit->id, 'from' => 'date']);
$this->assertResponseStatus(302);
}
public function testEdit()
{
$limit = f::create('Limit');
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
$this->_budgets->shouldReceive('getAsSelectList')->andReturn([]);
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($limit->budget()->first()->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'LimitController@edit', $limit->id);
$this->assertResponseOk();
}
public function testStore()
{
$limit = f::create('Limit');
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
$this->_limits->shouldReceive('store')->once()->andReturn($limit);
$this->action('POST', 'LimitController@store');
$this->assertRedirectedToRoute('budgets.index.budget');
$this->assertResponseStatus(302);
}
public function testStoreFails()
{
$budget = f::create('Budget');
$limit = f::create('Limit');
$limit->budget()->associate($budget);
$limit->save();
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
unset($limit->startdate);
unset($limit->component_id);
$this->_limits->shouldReceive('store')->once()->andReturn($limit);
$this->action('POST', 'LimitController@store', $budget->id);
$this->assertResponseStatus(302);
}
public function testStoreRedirect()
{
$budget = f::create('Budget');
$limit = f::create('Limit');
$limit->budget()->associate($budget);
$limit->save();
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
$this->_limits->shouldReceive('store')->once()->andReturn($limit);
$this->action('POST', 'LimitController@store', [$budget->id, 'from' => 'date']);
$this->assertResponseStatus(302);
}
public function testUpdate()
{
$limit = f::create('Limit');
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($limit->budget()->first()->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_limits->shouldReceive('update')->once()->andReturn($limit);
$this->action(
'POST', 'LimitController@update',
[$limit->id,
'date' => '02-02-2012',
'period' => 'monthly',
'repeats' => 0,
'amount' => '0.01'
]
);
$this->assertResponseStatus(302);
}
public function testUpdateFails()
{
$limit = f::create('Limit');
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($limit->budget()->first()->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
unset($limit->amount);
$this->_limits->shouldReceive('update')->once()->andReturn($limit);
$this->action(
'POST', 'LimitController@update',
$limit->id
);
$this->assertResponseStatus(302);
}
public function testUpdateRedirect()
{
$limit = f::create('Limit');
$limitrepetition = f::create('LimitRepetition');
$limit->limitrepetitions()->save($limitrepetition);
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($limit->budget()->first()->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_limits->shouldReceive('update')->once()->andReturn($limit);
$this->action(
'POST', 'LimitController@update',
[$limit->id,
'date' => '02-02-2012',
'period' => 'monthly',
'repeats' => 0,
'amount' => '0.01',
'from' => 'date'
]
);
$this->assertResponseStatus(302);
}
}

View File

@@ -1,440 +0,0 @@
<?php
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class PiggybankControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class PiggybankControllerTest extends TestCase
{
protected $_accounts;
protected $_piggybanks;
protected $_user;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_user = m::mock('User', 'Eloquent');
$this->_accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
$this->_piggybanks = $this->mock('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
}
public function tearDown()
{
m::close();
}
public function testAddMoneyGET()
{
$piggyBank = f::create('Piggybank');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn(
$piggyBank->account()->first()->user_id
);
$this->_piggybanks->shouldReceive('leftOnAccount')->andReturn(1);
$this->action('GET', 'PiggybankController@addMoney', $piggyBank->id);
$this->assertResponseOk();
}
public function testCreatePiggybank()
{
$this->_accounts->shouldReceive('getActiveDefaultAsSelectList')->once()->andReturn([]);
$this->action('GET', 'PiggybankController@createPiggybank');
$this->assertResponseOk();
}
public function testCreateRepeated()
{
$this->_accounts->shouldReceive('getActiveDefaultAsSelectList')->once()->andReturn([]);
$this->action('GET', 'PiggybankController@createRepeated');
$this->assertResponseOk();
}
public function testDelete()
{
$piggyBank = f::create('Piggybank');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn(
$piggyBank->account()->first()->user_id
);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn('some@email');
$this->action('GET', 'PiggybankController@delete', $piggyBank->id);
$this->assertResponseOk();
}
public function testDestroy()
{
$piggyBank = f::create('Piggybank');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn(
$piggyBank->account()->first()->user_id
);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_piggybanks->shouldReceive('destroy')->andReturn(true);
Event::shouldReceive('fire')->with('piggybanks.destroy', [$piggyBank]);
$this->action('POST', 'PiggybankController@destroy', $piggyBank->id);
$this->assertResponseStatus(302);
}
public function testEdit()
{
$piggyBank = f::create('Piggybank');
$this->_accounts->shouldReceive('getActiveDefaultAsSelectList')->once()->andReturn([]);
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn(
$piggyBank->account()->first()->user_id
);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn('some@email');
$this->action('GET', 'PiggybankController@edit', $piggyBank->id);
$this->assertResponseOk();
}
public function testEditRepeated()
{
$piggyBank = f::create('Piggybank');
$piggyBank->repeats = 1;
$piggyBank->save();
$this->_accounts->shouldReceive('getActiveDefaultAsSelectList')->once()->andReturn([]);
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn(
$piggyBank->account()->first()->user_id
);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn('some@email');
$this->action('GET', 'PiggybankController@edit', $piggyBank->id);
$this->assertResponseOk();
}
public function testIndex()
{
$aOne = f::create('Account');
$aTwo = f::create('Account');
$one = f::create('Piggybank');
$one->account()->associate($aOne);
$two = f::create('Piggybank');
$two->account()->associate($aOne);
$three = f::create('Piggybank');
$three->account()->associate($aTwo);
$this->_piggybanks->shouldReceive('get')->andReturn([$one, $two, $three]);
$this->_piggybanks->shouldReceive('countRepeating')->andReturn(0);
$this->_piggybanks->shouldReceive('leftOnAccount')->andReturn(0);
$this->_piggybanks->shouldReceive('countNonrepeating')->andReturn(0);
Event::shouldReceive('fire')->with('piggybanks.change');
$this->action('GET', 'PiggybankController@index');
$this->assertResponseOk();
}
public function testModifyMoneyAddPOST()
{
$piggyBank = f::create('Piggybank');
$piggyBank->targetamount = 200;
$piggyBank->save();
$input = [
$piggyBank->id,
'amount' => 10.0,
'what' => 'add'
];
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn(
$piggyBank->account()->first()->user_id
);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
Event::shouldReceive('fire'); //->with('piggybanks.modifyAmountAdd', [$piggyBank, 10.0]);
$this->_piggybanks->shouldReceive('modifyAmount')->once();
$this->_piggybanks->shouldReceive('leftOnAccount')->once()->andReturn(200);
$this->action('POST', 'PiggybankController@modMoney', $input);
$this->assertSessionHas('success');
$this->assertResponseStatus(302);
}
public function testModifyMoneyAddPOSTFails()
{
$piggyBank = f::create('Piggybank');
$piggyBank->targetamount = 200;
$piggyBank->save();
$input = [
$piggyBank->id,
'amount' => 10.0,
'what' => 'add'
];
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($piggyBank->account()->first()->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
Event::shouldReceive('fire')->with('piggybanks.modifyAmountAdd', [$piggyBank, -10.0]);
$this->_piggybanks->shouldReceive('leftOnAccount')->once()->andReturn(5);
$this->action('POST', 'PiggybankController@modMoney', $input);
$this->assertSessionHas('warning');
$this->assertResponseStatus(302);
}
/**
* @expectedException \Firefly\Exception\FireflyException
*/
public function testModifyMoneyPOSTException()
{
$piggyBank = f::create('Piggybank');
$piggyBank->targetamount = 200;
$piggyBank->save();
$input = [
$piggyBank->id,
'amount' => 10.0,
'what' => 'yomoma'
];
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($piggyBank->account()->first()->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('POST', 'PiggybankController@modMoney', $input);
$this->assertSessionHas('warning');
$this->assertResponseStatus(302);
}
public function testModifyMoneyRemovePOST()
{
$pig = $this->mock('Piggybank');
$piggybank = f::create('Piggybank');
$rep = f::create('PiggybankRepetition');
$rep->piggybank_id = $piggybank->id;
$rep->save();
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn(
$rep->piggybank()->first()->account()->first()->user_id
);
$pig->shouldReceive('currentRelevantRep')->andReturn($rep);
$this->_piggybanks->shouldReceive('leftOnAccount')->andReturn(11);
$this->_piggybanks->shouldReceive('modifyAmount')->once();
$input = [
$rep->piggybank()->first()->id,
'amount' => 10.0,
'what' => 'remove'
];
$this->action('POST', 'PiggybankController@modMoney', $input);
$this->assertSessionHas('success');
$this->assertResponseStatus(302);
}
public function testModifyMoneyRemovePOSTFails()
{
$pig = $this->mock('Piggybank');
$piggybank = f::create('Piggybank');
$rep = f::create('PiggybankRepetition');
$rep->piggybank_id = $piggybank->id;
$rep->currentAmount = 5;
$rep->save();
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn(
$rep->piggybank()->first()->account()->first()->user_id
);
$pig->shouldReceive('currentRelevantRep')->andReturn($rep);
$input = [
$rep->piggybank()->first()->id,
'amount' => 10.0,
'what' => 'remove'
];
$this->action('POST', 'PiggybankController@modMoney', $input);
$this->assertSessionHas('warning');
$this->assertResponseStatus(302);
}
public function testRemoveMoneyGET()
{
$pig = $this->mock('Piggybank');
$piggybank = f::create('Piggybank');
$rep = f::create('PiggybankRepetition');
$rep->piggybank_id = $piggybank->id;
$rep->save();
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn(
$rep->piggybank()->first()->account()->first()->user_id
);
$pig->shouldReceive('currentRelevantRep')->andReturn($rep);
$this->_piggybanks->shouldReceive('leftOnAccount')->andReturn(1)->once();
$this->action('GET', 'PiggybankController@removeMoney', $piggybank->id);
$this->assertResponseOk();
}
public function testShow()
{
$pig = $this->mock('Piggybank');
$piggybank = f::create('Piggybank');
$rep = f::create('PiggybankRepetition');
$rep->piggybank_id = $piggybank->id;
$rep->save();
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn(
$piggybank->account()->first()->user_id
);
$this->_user->shouldReceive('getAttribute')->andReturn('some@email');
$pig->shouldReceive('currentRelevantRep')->andReturn($rep);
// repos:
$this->_piggybanks->shouldReceive('leftOnAccount');
$this->action('GET', 'PiggybankController@show', $piggybank->id);
$this->assertResponseOk();
}
public function testStoreRepeated()
{
$piggy = f::create('Piggybank');
$piggy->repeats = 1;
$piggy->save();
Event::shouldReceive('fire')->with('piggybanks.store', [$piggy])->once();
$this->_piggybanks->shouldReceive('store')->once()->andReturn($piggy);
$this->action('POST', 'PiggybankController@storeRepeated');
$this->assertResponseStatus(302);
}
public function testStoreRepeatedFails()
{
$piggy = f::create('Piggybank');
unset($piggy->id);
$this->_piggybanks->shouldReceive('store')->once()->andReturn($piggy);
$this->action('POST', 'PiggybankController@storeRepeated');
$this->assertResponseStatus(302);
}
public function testUpdate()
{
$piggyBank = f::create('Piggybank');
$this->_piggybanks->shouldReceive('update')->andReturn($piggyBank);
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn(
$piggyBank->account()->first()->user_id
);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
Event::shouldReceive('fire')->with('piggybanks.update', [$piggyBank]);
$this->action('POST', 'PiggybankController@update', $piggyBank->id);
$this->assertResponseStatus(302);
}
public function testUpdateFails()
{
$piggyBank = f::create('Piggybank');
unset($piggyBank->name);
$this->_piggybanks->shouldReceive('update')->andReturn($piggyBank);
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn(
$piggyBank->account()->first()->user_id
);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
Event::shouldReceive('fire')->with('piggybanks.change');
$this->action('POST', 'PiggybankController@update', $piggyBank->id);
$this->assertResponseStatus(302);
}
public function teststorePiggybank()
{
$piggy = f::create('Piggybank');
$piggy->repeats = 0;
$piggy->save();
Event::shouldReceive('fire')->with('piggybanks.store', [$piggy])->once();
$this->_piggybanks->shouldReceive('store')->once()->andReturn($piggy);
$this->action('POST', 'PiggybankController@storePiggybank');
$this->assertResponseStatus(302);
}
public function teststorePiggybankFails()
{
$piggy = f::create('Piggybank');
unset($piggy->id);
$this->_piggybanks->shouldReceive('store')->once()->andReturn($piggy);
$this->action('POST', 'PiggybankController@storePiggybank');
$this->assertResponseStatus(302);
}
}

View File

@@ -1,56 +0,0 @@
<?php
use Mockery as m;
/**
* Class PreferencesControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class PreferencesControllerTest extends TestCase
{
protected $_user;
protected $_helper;
protected $_accounts;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_user = m::mock('User', 'Eloquent');
$this->_helper = $this->mock('Firefly\Helper\Preferences\PreferencesHelperInterface');
$this->_accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
}
public function tearDown()
{
m::close();
}
public function testIndex()
{
$viewRange = $this->mock('Preference');
$viewRange->shouldReceive('getAttribute')->with('data')->andReturn('1M');
$this->_accounts->shouldReceive('getDefault')->andReturn([]);
$this->_helper->shouldReceive('get')->with('viewRange', '1M')->andReturn($viewRange);
$this->_helper->shouldReceive('get')->with('frontpageAccounts', [])->andReturn([]);
$this->action('GET', 'PreferencesController@index');
$this->assertResponseOk();
}
public function testPostIndex()
{
$this->_helper->shouldReceive('set')->with('frontpageAccounts', [1]);
$this->_helper->shouldReceive('set')->with('viewRange', '1M');
$this->action('POST', 'PreferencesController@postIndex', ['frontpageAccounts' => [1], 'viewRange' => '1M']);
$this->assertResponseStatus(302);
}
}

View File

@@ -1,135 +0,0 @@
<?php
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class ProfileControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class ProfileControllerTest extends TestCase
{
protected $_user;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_user = m::mock('User', 'Eloquent');
}
public function tearDown()
{
m::close();
}
public function testChangePassword()
{
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($this->_user->id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'ProfileController@changePassword');
$this->assertResponseOk();
}
public function testIndex()
{
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($this->_user->id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'ProfileController@index');
$this->assertResponseOk();
}
public function testPostChangePasswordDifferentNew()
{
$user = f::create('User');
// for binding
Auth::shouldReceive('user')->andReturn($user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($user->id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn($user->email);
$this->_user->shouldReceive('getAttribute')->with('password')->andReturn($user->password);
$this->action(
'POST', 'ProfileController@postChangePassword',
['old' => 'sander', 'new1' => 'sander1', 'new2' => 'sander2']
);
$this->assertResponseOk();
}
public function testPostChangePasswordOK()
{
$user = f::create('User');
$user->password = 'sander';
$user->save();
// for binding
Auth::shouldReceive('user')->andReturn($user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($user->id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn($user->email);
$this->_user->shouldReceive('getAttribute')->with('password')->andReturn($user->password);
$this->action(
'POST', 'ProfileController@postChangePassword',
['old' => 'sander', 'new1' => 'sander2', 'new2' => 'sander2']
);
$this->assertSessionHas('success');
$this->assertResponseStatus(302);
}
public function testPostChangePasswordNoCurrent()
{
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($this->_user->id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_user->shouldReceive('getAttribute')->with('password')->andReturn('Blablabla');
$this->action('POST', 'ProfileController@postChangePassword', ['old' => '']);
$this->assertResponseOk();
}
public function testPostChangePasswordNoMatchNew()
{
$user = f::create('User');
// for binding
Auth::shouldReceive('user')->andReturn($user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($user->id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn($user->email);
$this->_user->shouldReceive('getAttribute')->with('password')->andReturn($user->password);
$this->action(
'POST', 'ProfileController@postChangePassword', ['old' => 'sander', 'new1' => 'sander', 'new2' => 'sander']
);
$this->assertResponseOk();
}
public function testPostChangePasswordSame()
{
$user = f::create('User');
// for binding
Auth::shouldReceive('user')->andReturn($user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($user->id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn($user->email);
$this->_user->shouldReceive('getAttribute')->with('password')->andReturn($user->password);
$this->action('POST', 'ProfileController@postChangePassword', ['old' => 'sander']);
$this->assertResponseOk();
}
}

View File

@@ -1,178 +0,0 @@
<?php
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class RecurringControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class RecurringControllerTest extends TestCase
{
protected $_user;
protected $_repository;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_user = m::mock('User', 'Eloquent');
$this->_repository = $this->mock(
'Firefly\Storage\RecurringTransaction\RecurringTransactionRepositoryInterface'
);
}
public function tearDown()
{
m::close();
}
public function testCreate()
{
$this->action('GET', 'RecurringController@create');
$this->assertResponseOk();
}
public function testDelete()
{
$recurringTransaction = f::create('RecurringTransaction');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($recurringTransaction->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn('some@email');
$this->action('GET', 'RecurringController@delete', $recurringTransaction->id);
$this->assertResponseOk();
}
public function testDestroy()
{
$recurringTransaction = f::create('RecurringTransaction');
Event::shouldReceive('fire')->with('recurring.destroy',m::any());
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($recurringTransaction->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_repository->shouldReceive('destroy')->andReturn(true);
$this->action('POST', 'RecurringController@destroy', $recurringTransaction->id);
$this->assertResponseStatus(302);
}
public function testDestroyFails()
{
$recurringTransaction = f::create('RecurringTransaction');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
Event::shouldReceive('fire')->with('recurring.destroy',m::any());
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($recurringTransaction->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_repository->shouldReceive('destroy')->andReturn(false);
$this->action('POST', 'RecurringController@destroy', $recurringTransaction->id);
$this->assertResponseStatus(302);
}
public function testEdit()
{
$recurringTransaction = f::create('RecurringTransaction');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($recurringTransaction->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->once()->andReturn('some@email');
$this->action('GET', 'RecurringController@edit', $recurringTransaction->id);
$this->assertResponseOk();
}
public function testIndex()
{
$this->_repository->shouldReceive('get')->andReturn([]);
$this->action('GET', 'RecurringController@index');
$this->assertResponseOk();
}
public function testShow()
{
$recurringTransaction = f::create('RecurringTransaction');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($recurringTransaction->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'RecurringController@show', $recurringTransaction->id);
$this->assertResponseOk();
}
public function testStore()
{
$recurringTransaction = f::create('RecurringTransaction');
Event::shouldReceive('fire')->with('recurring.store',m::any());
$this->_repository->shouldReceive('store')->andReturn($recurringTransaction);
$this->action('POST', 'RecurringController@store');
$this->assertResponseStatus(302);
}
public function testStoreRedirect()
{
$recurringTransaction = f::create('RecurringTransaction');
Event::shouldReceive('fire')->with('recurring.store',m::any());
$this->_repository->shouldReceive('store')->andReturn($recurringTransaction);
$this->action('POST', 'RecurringController@store', ['create' => '1']);
$this->assertResponseStatus(302);
}
public function testStoreFails()
{
$recurringTransaction = f::create('RecurringTransaction');
unset($recurringTransaction->active);
unset($recurringTransaction->automatch);
$this->_repository->shouldReceive('store')->andReturn($recurringTransaction);
$this->action('POST', 'RecurringController@store', ['create' => '1']);
$this->assertResponseStatus(302);
}
public function testUpdate()
{
$recurringTransaction = f::create('RecurringTransaction');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->andReturn($recurringTransaction->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
Event::shouldReceive('fire')->with('recurring.update',m::any());
$this->_repository->shouldReceive('update')->andReturn($recurringTransaction);
$this->action('POST', 'RecurringController@update', $recurringTransaction->id);
$this->assertResponseStatus(302);
}
}

View File

@@ -1,30 +0,0 @@
<?php
use Mockery as m;
/**
* Class ReportControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class ReportControllerTest extends TestCase
{
public function setUp()
{
parent::setUp();
}
public function tearDown()
{
m::close();
}
public function testIndex()
{
$this->action('GET', 'ReportController@index');
$this->assertResponseOk();
}
}

View File

@@ -1,30 +0,0 @@
<?php
use Mockery as m;
/**
* Class SearchControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class SearchControllerTest extends TestCase
{
public function setUp()
{
parent::setUp();
}
public function tearDown()
{
m::close();
}
public function testIndex()
{
$this->action('GET', 'SearchController@index');
$this->assertResponseOk();
}
}

View File

@@ -1,312 +0,0 @@
<?php
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class TransactionControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class TransactionControllerTest extends TestCase
{
protected $_user;
protected $_repository;
protected $_accounts;
protected $_budgets;
protected $_piggies;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_user = m::mock('User', 'Eloquent');
$this->_repository = $this->mock('Firefly\Storage\TransactionJournal\TransactionJournalRepositoryInterface');
$this->_accounts = $this->mock('Firefly\Storage\Account\AccountRepositoryInterface');
$this->_budgets = $this->mock('Firefly\Storage\Budget\BudgetRepositoryInterface');
$this->_piggies = $this->mock('Firefly\Storage\Piggybank\PiggybankRepositoryInterface');
}
public function tearDown()
{
m::close();
}
public function testCreateDeposit()
{
$this->_accounts->shouldReceive('getActiveDefaultAsSelectList')->andReturn([]);
$this->_budgets->shouldReceive('getAsSelectList')->andReturn([]);
$this->_piggies->shouldReceive('get')->andReturn([]);
$this->action('GET', 'TransactionController@create', ['what' => 'deposit']);
$this->assertResponseOk();
}
public function testCreateTransfer()
{
$this->_accounts->shouldReceive('getActiveDefaultAsSelectList')->andReturn([]);
$this->_budgets->shouldReceive('getAsSelectList')->andReturn([]);
$this->_piggies->shouldReceive('get')->andReturn([]);
$this->action('GET', 'TransactionController@create', ['what' => 'transfer']);
$this->assertResponseOk();
}
public function testCreateWithdrawal()
{
$this->_accounts->shouldReceive('getActiveDefaultAsSelectList')->andReturn([]);
$this->_budgets->shouldReceive('getAsSelectList')->andReturn([]);
$this->_piggies->shouldReceive('get')->andReturn([]);
$this->action('GET', 'TransactionController@create', ['what' => 'withdrawal']);
$this->assertResponseOk();
}
public function testDelete()
{
$journal = f::create('TransactionJournal');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($journal->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'TransactionController@delete', $journal->id);
$this->assertResponseOk();
}
public function testDestroy()
{
$journal = f::create('TransactionJournal');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($journal->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('POST', 'TransactionController@destroy', $journal->id);
$this->assertResponseStatus(302);
}
public function testEdit()
{
$journal = f::create('TransactionJournal');
$type = f::create('TransactionType');
$type->type = 'Withdrawal';
$type->save();
$journal->transactiontype()->associate($type);
$journal->save();
$category = f::create('Category');
$journal->categories()->save($category);
$budget = f::create('Budget');
$journal->budgets()->save($budget);
$one = f::create('Transaction');
$two = f::create('Transaction');
$one->transactionjournal()->associate($journal);
$two->transactionjournal()->associate($journal);
$one->save();
$two->save();
$this->_accounts->shouldReceive('getActiveDefaultAsSelectList')->andReturn([]);
$this->_budgets->shouldReceive('getAsSelectList')->andReturn([]);
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($journal->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_piggies->shouldReceive('get')->once()->andReturn([]);
$this->action('GET', 'TransactionController@edit', $journal->id);
$this->assertResponseOk();
}
public function testEditDeposit()
{
$journal = f::create('TransactionJournal');
$type = f::create('TransactionType');
$type->type = 'Deposit';
$type->save();
$journal->transactiontype()->associate($type);
$journal->save();
$category = f::create('Category');
$journal->categories()->save($category);
$budget = f::create('Budget');
$journal->budgets()->save($budget);
$one = f::create('Transaction');
$two = f::create('Transaction');
$one->transactionjournal()->associate($journal);
$two->transactionjournal()->associate($journal);
$one->save();
$two->save();
$this->_accounts->shouldReceive('getActiveDefaultAsSelectList')->andReturn([]);
$this->_budgets->shouldReceive('getAsSelectList')->andReturn([]);
$this->_piggies->shouldReceive('get')->once()->andReturn([]);
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($journal->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'TransactionController@edit', $journal->id);
$this->assertResponseOk();
}
public function testEditTransfer()
{
$journal = f::create('TransactionJournal');
$type = f::create('TransactionType');
$type->type = 'Transfer';
$type->save();
$journal->transactiontype()->associate($type);
$journal->save();
$category = f::create('Category');
$journal->categories()->save($category);
$budget = f::create('Budget');
$journal->budgets()->save($budget);
$one = f::create('Transaction');
$two = f::create('Transaction');
$one->transactionjournal()->associate($journal);
$two->transactionjournal()->associate($journal);
$one->save();
$two->save();
$this->_accounts->shouldReceive('getActiveDefaultAsSelectList')->andReturn([]);
$this->_budgets->shouldReceive('getAsSelectList')->andReturn([]);
$this->_piggies->shouldReceive('get')->once()->andReturn([]);
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($journal->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'TransactionController@edit', $journal->id);
$this->assertResponseOk();
}
public function testIndex()
{
$journal = f::create('TransactionJournal');
$type = f::create('TransactionType');
$type->type = 'Withdrawal';
$type->save();
$journal->transactiontype()->associate($type);
$journal->save();
$one = f::create('Transaction');
$two = f::create('Transaction');
$one->transactionjournal()->associate($journal);
$two->transactionjournal()->associate($journal);
$one->save();
$two->save();
// make a paginator
$paginator = Paginator::make([$journal], 1, 1);
$this->_repository->shouldReceive('paginate')->with(25)->andReturn($paginator);
$this->_repository->shouldReceive('get')->andReturn([]);
$this->action('GET', 'TransactionController@index');
$this->assertResponseOk();
}
public function testShow()
{
$journal = f::create('TransactionJournal');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($journal->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->action('GET', 'TransactionController@show', $journal->id);
$this->assertResponseOk();
}
public function testStore()
{
$journal = f::create('TransactionJournal');
$this->_repository->shouldReceive('store')->andReturn($journal);
$this->action('POST', 'TransactionController@store', ['what' => 'deposit']);
$this->assertResponseStatus(302);
}
public function testStoreFails()
{
$journal = f::create('TransactionJournal');
unset($journal->description);
$this->_repository->shouldReceive('store')->andReturn($journal);
$this->action('POST', 'TransactionController@store', ['what' => 'deposit', 'create' => '1']);
$this->assertResponseStatus(302);
}
public function testStoreRedirect()
{
$journal = f::create('TransactionJournal');
$this->_repository->shouldReceive('store')->andReturn($journal);
$this->action('POST', 'TransactionController@store', ['what' => 'deposit', 'create' => '1']);
$this->assertResponseStatus(302);
}
public function testUpdate()
{
$journal = f::create('TransactionJournal');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($journal->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$this->_repository->shouldReceive('update')->andReturn($journal);
$this->action('POST', 'TransactionController@update', $journal->id);
$this->assertResponseStatus(302);
}
public function testUpdateFailed()
{
$journal = f::create('TransactionJournal');
// for binding
Auth::shouldReceive('user')->andReturn($this->_user);
Auth::shouldReceive('check')->andReturn(true);
$this->_user->shouldReceive('getAttribute')->with('id')->once()->andReturn($journal->user_id);
$this->_user->shouldReceive('getAttribute')->with('email')->andReturn('some@email');
$journal->description = null;
$this->_repository->shouldReceive('update')->andReturn($journal);
$this->action('POST', 'TransactionController@update', $journal->id);
$this->assertResponseStatus(302);
}
}

View File

@@ -1,167 +0,0 @@
<?php
use League\FactoryMuffin\Facade as f;
use Mockery as m;
/**
* Class UserControllerTest
*
* @SuppressWarnings(PHPMD.TooManyMethods)
* @SuppressWarnings(PHPMD.CamelCasePropertyName)
*/
class UserControllerTest extends TestCase
{
protected $_user;
protected $_users;
protected $_email;
public function setUp()
{
parent::setUp();
Artisan::call('migrate');
Artisan::call('db:seed');
$this->_user = m::mock('User', 'Eloquent');
$this->_users = $this->mock('Firefly\Storage\User\UserRepositoryInterface');
$this->_email = $this->mock('Firefly\Helper\Email\EmailHelperInterface');
}
public function tearDown()
{
m::close();
}
public function testLogin()
{
$this->action('GET', 'UserController@login');
$this->assertResponseOk();
}
public function testLogout()
{
$this->action('GET', 'UserController@logout');
$this->assertResponseStatus(302);
}
public function testPostLogin()
{
$input = [
'email' => 'bla@bla',
'password' => 'something',
];
Auth::shouldReceive('attempt')->with($input, false)->andReturn(true);
$this->action('POST', 'UserController@postLogin', $input);
$this->assertResponseStatus(302);
}
public function testPostLoginFails()
{
$this->action('POST', 'UserController@postLogin');
$this->assertResponseOk();
}
public function testPostRegister()
{
Config::set('auth.allow_register', true);
$user = f::create('User');
$this->_users->shouldReceive('register')->andReturn($user);
$this->_email->shouldReceive('sendPasswordMail')->with($user);
$this->action('POST', 'UserController@postRegister');
$this->assertResponseOk();
}
public function testPostRegisterFails()
{
Config::set('auth.allow_register', true);
$this->_users->shouldReceive('register')->andReturn(false);
$this->action('POST', 'UserController@postRegister');
$this->assertResponseOk();
}
public function testPostRegisterNotAllowed()
{
Config::set('auth.allow_register', false);
$this->action('POST', 'UserController@postRegister');
$this->assertResponseOk();
}
public function testPostRegisterVerify()
{
Config::set('auth.allow_register', true);
Config::set('auth.verify_mail', true);
$user = f::create('User');
$this->_users->shouldReceive('register')->andReturn($user);
$this->_email->shouldReceive('sendVerificationMail')->with($user);
$this->action('POST', 'UserController@postRegister');
$this->assertResponseOk();
}
public function testPostRemindme()
{
$user = f::create('User');
Config::set('auth.verify_reset', true);
$this->_users->shouldReceive('findByEmail')->andReturn($user);
$this->_email->shouldReceive('sendResetVerification');
$this->action('POST', 'UserController@postRemindme');
$this->assertResponseOk();
}
public function testPostRemindmeNoVerify()
{
$user = f::create('User');
Config::set('auth.verify_reset', false);
$this->_users->shouldReceive('findByEmail')->andReturn($user);
$this->_email->shouldReceive('sendPasswordMail');
$this->action('POST', 'UserController@postRemindme');
$this->assertResponseOk();
}
public function testPostRemindmeFails()
{
Config::set('auth.verify_reset', true);
$this->_users->shouldReceive('findByEmail')->andReturn(false);
$this->action('POST', 'UserController@postRemindme');
$this->assertResponseOk();
}
public function testRegister()
{
$this->action('GET', 'UserController@register');
$this->assertResponseOk();
}
public function testRegisterNotAllowed()
{
Config::set('auth.allow_register', false);
$this->action('GET', 'UserController@register');
$this->assertResponseOk();
}
public function testRemindme()
{
$this->action('GET', 'UserController@remindme');
$this->assertResponseOk();
}
public function testReset()
{
$user = f::create('User');
$this->_users->shouldReceive('findByReset')->andReturn($user);
$this->_email->shouldReceive('sendPasswordMail');
$this->action('GET', 'UserController@reset');
$this->assertResponseOk();
}
public function testResetNoUser()
{
$this->_users->shouldReceive('findByReset')->andReturn(false);
$this->action('GET', 'UserController@reset');
$this->assertResponseOk();
}
}

View File

@@ -1,12 +0,0 @@
<?php
use League\FactoryMuffin\Facade;
Facade::define(
'Account',
[
'user_id' => 'factory|User',
'account_type_id' => 'factory|AccountType',
'name' => 'word',
'active' => 'boolean'
]
);

View File

@@ -1,18 +0,0 @@
<?php
use League\FactoryMuffin\Facade;
Facade::define(
'AccountType',
[
'description' => function () {
$types = [
'Default account',
'Cash account',
'Initial balance account',
'Beneficiary account'
];
return $types[rand(0, 3)];
}
]
);

View File

@@ -1,11 +0,0 @@
<?php
use League\FactoryMuffin\Facade;
Facade::define(
'Budget',
[
'name' => 'word',
'user_id' => 'factory|User',
'class' => 'Budget'
]
);

Some files were not shown because too many files have changed in this diff Show More