diff --git a/README.md b/README.md index f907bedc14..493b3745d3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Firefly III (v3.3.6) +Firefly III (v3.3.7) =========== [![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=develop)](https://travis-ci.org/JC5/firefly-iii) diff --git a/app/Console/Commands/Inspire.php b/app/Console/Commands/Inspire.php deleted file mode 100644 index ddd55093b5..0000000000 --- a/app/Console/Commands/Inspire.php +++ /dev/null @@ -1,37 +0,0 @@ -comment(PHP_EOL . Inspiring::quote() . PHP_EOL); - } - -} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index f740d7abbc..b8ebcaae70 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -18,7 +18,6 @@ class Kernel extends ConsoleKernel */ protected $commands = [ - 'FireflyIII\Console\Commands\Inspire', ]; /** @@ -30,8 +29,6 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { - $schedule->command('inspire') - ->hourly(); } } diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index b671775f0c..afacfa1b23 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -1,5 +1,6 @@ accounts()->with( - ['accountmeta' => function (HasMany $query) { - $query->where('name', 'accountRole'); - }] - )->accountTypeIn($types)->take($size)->offset($offset)->orderBy('accounts.name', 'ASC')->get(['accounts.*']); - $total = Auth::user()->accounts()->accountTypeIn($types)->count(); + $set = $repository->getAccounts($types, $page); + $total = $repository->countAccounts($types); // last activity: + /** + * HERE WE ARE + */ $start = clone Session::get('start', Carbon::now()->startOfMonth()); $start->subDay(); $set->each( - function (Account $account) use ($start) { - $lastTransaction = $account->transactions()->leftJoin( - 'transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id' - )->orderBy('transaction_journals.date', 'DESC')->first(['transactions.*', 'transaction_journals.date']); - if ($lastTransaction) { - $account->lastActivityDate = $lastTransaction->transactionjournal->date; - } else { - $account->lastActivityDate = null; - } - $account->startBalance = Steam::balance($account, $start); - $account->endBalance = Steam::balance($account, clone Session::get('end')); + function (Account $account) use ($start, $repository) { + $account->lastActivityDate = $repository->getLastActivity($account); + $account->startBalance = Steam::balance($account, $start); + $account->endBalance = Steam::balance($account, clone Session::get('end', Carbon::now()->endOfMonth())); } ); @@ -176,6 +165,8 @@ class AccountController extends Controller $subTitle = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'; $journals->setPath('accounts/show/' . $account->id); + + return view('accounts.show', compact('account', 'what', 'subTitleIcon', 'journals', 'subTitle')); } @@ -201,7 +192,7 @@ class AccountController extends Controller ]; $account = $repository->store($accountData); - Session::flash('success', 'New account "' . $account->name . '" stored!'); + Session::flash('success', 'New account "' . $account->name . '" stored!'); if (intval(Input::get('create_another')) === 1) { return Redirect::route('accounts.create', $request->input('what'))->withInput(); diff --git a/app/Http/Controllers/BillController.php b/app/Http/Controllers/BillController.php index 1535577102..6a78a4718f 100644 --- a/app/Http/Controllers/BillController.php +++ b/app/Http/Controllers/BillController.php @@ -1,6 +1,6 @@ match); $description = []; $expense = null; // get users expense accounts: - $type = AccountType::where('type', 'Expense account')->first(); - $accounts = Auth::user()->accounts()->where('account_type_id', $type->id)->get(); + $accounts = $repository->getAccounts(Config::get('firefly.accountTypesByIdentifier.expense'), -1); foreach ($matches as $match) { $match = strtolower($match); @@ -81,7 +81,7 @@ class BillController extends Controller */ public function create() { - $periods = \Config::get('firefly.periods_to_text'); + $periods = Config::get('firefly.periods_to_text'); return view('bills.create')->with('periods', $periods)->with('subTitle', 'Create new'); } @@ -101,9 +101,10 @@ class BillController extends Controller * * @return \Illuminate\Http\RedirectResponse */ - public function destroy(Bill $bill) + public function destroy(Bill $bill, BillRepositoryInterface $repository) { - $bill->delete(); + $repository->destroy($bill); + Session::flash('success', 'The bill was deleted.'); return Redirect::route('bills.index'); @@ -117,7 +118,7 @@ class BillController extends Controller */ public function edit(Bill $bill) { - $periods = \Config::get('firefly.periods_to_text'); + $periods = Config::get('firefly.periods_to_text'); return view('bills.edit')->with('periods', $periods)->with('bill', $bill)->with('subTitle', 'Edit "' . e($bill->name) . '"'); } @@ -129,15 +130,11 @@ class BillController extends Controller */ public function index(BillRepositoryInterface $repository) { - $bills = Auth::user()->bills()->orderBy('name', 'ASC')->get(); + $bills = $repository->getBills(); $bills->each( function (Bill $bill) use ($repository) { $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill); - $last = $bill->transactionjournals()->orderBy('date', 'DESC')->first(); - $bill->lastFoundMatch = null; - if ($last) { - $bill->lastFoundMatch = $last->date; - } + $bill->lastFoundMatch = $repository->lastFoundMatch($bill); } ); @@ -154,25 +151,15 @@ class BillController extends Controller if (intval($bill->active) == 0) { Session::flash('warning', 'Inactive bills cannot be scanned.'); - return Redirect::intended('/'); + return Redirect::to(URL::previous()); } - $set = \DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max)->get( - ['transaction_journal_id'] - ); - $ids = []; + $journals = $repository->getPossiblyRelatedJournals($bill); + /** @var TransactionJournal $journal */ + foreach ($journals as $journal) { + $repository->scan($bill, $journal); + } - /** @var Transaction $entry */ - foreach ($set as $entry) { - $ids[] = intval($entry->transaction_journal_id); - } - if (count($ids) > 0) { - $journals = Auth::user()->transactionjournals()->whereIn('id', $ids)->get(); - /** @var TransactionJournal $journal */ - foreach ($journals as $journal) { - $repository->scan($bill, $journal); - } - } Session::flash('success', 'Rescanned everything.'); @@ -186,15 +173,10 @@ class BillController extends Controller */ public function show(Bill $bill, BillRepositoryInterface $repository) { - $journals = $bill->transactionjournals()->withRelevantData() - ->orderBy('transaction_journals.date', 'DESC') - ->orderBy('transaction_journals.order', 'ASC') - ->orderBy('transaction_journals.id', 'DESC') - ->get(); + $journals = $repository->getJournals($bill); $bill->nextExpectedMatch = $repository->nextExpectedMatch($bill); $hideBill = true; - return view('bills.show', compact('journals', 'hideBill', 'bill'))->with('subTitle', e($bill->name)); } diff --git a/app/Http/Controllers/BudgetController.php b/app/Http/Controllers/BudgetController.php index a4862219a6..92078806b0 100644 --- a/app/Http/Controllers/BudgetController.php +++ b/app/Http/Controllers/BudgetController.php @@ -13,8 +13,9 @@ use Preferences; use Redirect; use Response; use Session; -use View; use URL; +use View; + /** * Class BudgetController * @@ -88,7 +89,6 @@ class BudgetController extends Controller $repository->destroy($budget); - Session::flash('success', 'The budget "' . e($name) . '" was deleted.'); return Redirect::to(Session::get('budgets.delete.url')); @@ -118,8 +118,8 @@ class BudgetController extends Controller */ public function index(BudgetRepositoryInterface $repository) { - $budgets = Auth::user()->budgets()->where('active', 1)->get(); - $inactive = Auth::user()->budgets()->where('active', 0)->get(); + $budgets = $repository->getActiveBudgets(); + $inactive = $repository->getInactiveBudgets(); /** * Do some cleanup: @@ -127,19 +127,18 @@ class BudgetController extends Controller $repository->cleanupBudgets(); - // loop the budgets: $budgets->each( function (Budget $budget) use ($repository) { $date = Session::get('start', Carbon::now()->startOfMonth()); $budget->spent = $repository->spentInMonth($budget, $date); - $budget->currentRep = $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']); + $budget->currentRep = $repository->getCurrentRepetition($budget, $date); } ); - $date = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); + $dateAsString = Session::get('start', Carbon::now()->startOfMonth())->format('FY'); $spent = $budgets->sum('spent'); - $amount = Preferences::get('budgetIncomeTotal' . $date, 1000)->data; + $amount = Preferences::get('budgetIncomeTotal' . $dateAsString, 1000)->data; $overspent = $spent > $amount; $spentPCT = $overspent ? ceil($amount / $spent * 100) : ceil($spent / $amount * 100); $budgetMax = Preferences::get('budgetMaximum', 1000); @@ -151,21 +150,12 @@ class BudgetController extends Controller /** * @return \Illuminate\View\View */ - public function noBudget() + public function noBudget(BudgetRepositoryInterface $repository) { - $start = \Session::get('start', Carbon::now()->startOfMonth()); - $end = \Session::get('end', Carbon::now()->startOfMonth()); - $list = Auth::user() - ->transactionjournals() - ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') - ->whereNull('budget_transaction_journal.id') - ->before($end) - ->after($start) - ->orderBy('transaction_journals.date', 'DESC') - ->orderBy('transaction_journals.order', 'ASC') - ->orderBy('transaction_journals.id', 'DESC') - ->get(['transaction_journals.*']); - $subTitle = 'Transactions without a budget in ' . $start->format('F Y'); + $start = Session::get('start', Carbon::now()->startOfMonth()); + $end = Session::get('end', Carbon::now()->startOfMonth()); + $list = $repository->getWithoutBudget($start, $end); + $subTitle = 'Transactions without a budget between ' . $start->format('jS F Y') . ' and ' . $end->format('jS F Y'); return view('budgets.noBudget', compact('list', 'subTitle')); } @@ -182,6 +172,27 @@ class BudgetController extends Controller return Redirect::route('budgets.index'); } + /** + * + * @param Budget $budget + * @param LimitRepetition $repetition + * + * @return \Illuminate\View\View + */ + public function show(Budget $budget, LimitRepetition $repetition = null, BudgetRepositoryInterface $repository) + { + if (!is_null($repetition->id) && $repetition->budgetLimit->budget->id != $budget->id) { + return view('error')->with('message', 'Invalid selection.'); + } + + $hideBudget = true; // used in transaction list. + $journals = $repository->getJournals($budget, $repetition); + $limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $repository->getBudgetLimits($budget); + $subTitle = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name); + + return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget')); + } + /** * @param BudgetFormRequest $request * @param BudgetRepositoryInterface $repository @@ -201,6 +212,7 @@ class BudgetController extends Controller if (intval(Input::get('create_another')) === 1) { // set value so create routine will not overwrite URL: Session::put('budgets.create.fromStore', true); + return Redirect::route('budgets.create')->withInput(); } @@ -209,27 +221,6 @@ class BudgetController extends Controller } - /** - * - * @param Budget $budget - * @param LimitRepetition $repetition - * - * @return \Illuminate\View\View - */ - public function show(Budget $budget, LimitRepetition $repetition = null, BudgetRepositoryInterface $repository) - { - if (!is_null($repetition->id) && $repetition->budgetLimit->budget->id != $budget->id) { - return view('error')->with('message', 'Invalid selection.'); - } - - $hideBudget = true; // used in transaction list. - $journals = $repository->getJournals($budget, $repetition); - $limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $budget->budgetLimits()->orderBy('startdate', 'DESC')->get(); - $subTitle = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name); - - return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget')); - } - /** * @param Budget $budget * @param BudgetFormRequest $request @@ -251,6 +242,7 @@ class BudgetController extends Controller if (intval(Input::get('return_to_edit')) === 1) { // set value so edit routine will not overwrite URL: Session::put('budgets.edit.fromUpdate', true); + return Redirect::route('budgets.edit', $budget->id)->withInput(['return_to_edit' => 1]); } diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index b664ec6566..105959bc54 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -10,8 +10,8 @@ use Illuminate\Pagination\LengthAwarePaginator; use Input; use Redirect; use Session; -use View; use URL; +use View; /** * Class CategoryController @@ -96,21 +96,15 @@ class CategoryController extends Controller /** * @return $this + * */ - public function index() + public function index(CategoryRepositoryInterface $repository) { - $categories = Auth::user()->categories()->orderBy('name', 'ASC')->get(); + $categories = $repository->getCategories(); $categories->each( - function (Category $category) { - $latest = $category->transactionjournals() - ->orderBy('transaction_journals.date', 'DESC') - ->orderBy('transaction_journals.order', 'ASC') - ->orderBy('transaction_journals.id', 'DESC') - ->first(); - if ($latest) { - $category->lastActivity = $latest->date; - } + function (Category $category) use ($repository) { + $category->lastActivity = $repository->getLatestActivity($category); } ); @@ -120,21 +114,11 @@ class CategoryController extends Controller /** * @return \Illuminate\View\View */ - public function noCategory() + public function noCategory(CategoryRepositoryInterface $repository) { - $start = Session::get('start', Carbon::now()->startOfMonth()); - $end = Session::get('end', Carbon::now()->startOfMonth()); - $list = Auth::user() - ->transactionjournals() - ->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') - ->whereNull('category_transaction_journal.id') - ->before($end) - ->after($start) - ->orderBy('transaction_journals.date', 'DESC') - ->orderBy('transaction_journals.order', 'ASC') - ->orderBy('transaction_journals.id', 'DESC') - ->get(['transaction_journals.*']); - + $start = Session::get('start', Carbon::now()->startOfMonth()); + $end = Session::get('end', Carbon::now()->startOfMonth()); + $list = $repository->getWithoutCategory($start, $end); $subTitle = 'Transactions without a category between ' . $start->format('jS F Y') . ' and ' . $end->format('jS F Y'); return view('categories.noCategory', compact('list', 'subTitle')); @@ -149,17 +133,9 @@ class CategoryController extends Controller { $hideCategory = true; // used in list. $page = intval(Input::get('page')); - $offset = $page > 0 ? $page * 50 : 0; - $set = $category->transactionJournals()->withRelevantData()->take(50)->offset($offset) - ->orderBy('transaction_journals.date', 'DESC') - ->orderBy('transaction_journals.order', 'ASC') - ->orderBy('transaction_journals.id', 'DESC') - ->get( - ['transaction_journals.*'] - ); - $count = $category->transactionJournals()->count(); - - $journals = new LengthAwarePaginator($set, $count, 50, $page); + $set = $repository->getJournals($category, $page); + $count = $repository->countJournals($category); + $journals = new LengthAwarePaginator($set, $count, 50, $page); return view('categories.show', compact('category', 'journals', 'hideCategory')); } @@ -182,11 +158,8 @@ class CategoryController extends Controller if (intval(Input::get('create_another')) === 1) { Session::put('categories.create.fromStore', true); - return Redirect::route('categories.create')->withInput(); - } - if (intval(Input::get('create_another')) === 1) { - return Redirect::route('categories.create'); + return Redirect::route('categories.create')->withInput(); } return Redirect::route('categories.index'); @@ -212,6 +185,7 @@ class CategoryController extends Controller if (intval(Input::get('return_to_edit')) === 1) { Session::put('categories.edit.fromUpdate', true); + return Redirect::route('categories.edit', $category->id); } diff --git a/app/Http/Controllers/CurrencyController.php b/app/Http/Controllers/CurrencyController.php index a88eeb65d0..c0b2fd4258 100644 --- a/app/Http/Controllers/CurrencyController.php +++ b/app/Http/Controllers/CurrencyController.php @@ -5,12 +5,13 @@ use FireflyIII\Http\Requests; use FireflyIII\Http\Requests\CurrencyFormRequest; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use Input; use Preferences; use Redirect; use Session; -use View; use URL; +use View; /** * Class CurrencyController @@ -56,9 +57,7 @@ class CurrencyController extends Controller public function defaultCurrency(TransactionCurrency $currency) { - $currencyPreference = Preferences::get('currencyPreference', 'EUR'); - $currencyPreference->data = $currency->code; - $currencyPreference->save(); + Preferences::set('currencyPreference', $currency->code); Session::flash('success', $currency->name . ' is now the default currency.'); Cache::forget('FFCURRENCYSYMBOL'); @@ -73,17 +72,18 @@ class CurrencyController extends Controller * * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View */ - public function delete(TransactionCurrency $currency) + public function delete(TransactionCurrency $currency, CurrencyRepositoryInterface $repository) { - if ($currency->transactionJournals()->count() > 0) { - Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.'); - // put previous url in session - Session::put('currency.delete.url', URL::previous()); + if ($repository->countJournals($currency) > 0) { + Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.'); return Redirect::route('currency.index'); } + // put previous url in session + Session::put('currency.delete.url', URL::previous()); + return view('currency.delete', compact('currency')); } @@ -93,10 +93,10 @@ class CurrencyController extends Controller * * @return \Illuminate\Http\RedirectResponse */ - public function destroy(TransactionCurrency $currency) + public function destroy(TransactionCurrency $currency, CurrencyRepositoryInterface $repository) { - if ($currency->transactionJournals()->count() > 0) { - Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.'); + if ($repository->countJournals($currency) > 0) { + Session::flash('error', 'Cannot destroy ' . e($currency->name) . ' because there are still transactions attached to it.'); return Redirect::route('currency.index'); } @@ -132,12 +132,10 @@ class CurrencyController extends Controller /** * @return \Illuminate\View\View */ - public function index() + public function index(CurrencyRepositoryInterface $repository) { - $currencies = TransactionCurrency::get(); - $currencyPreference = Preferences::get('currencyPreference', 'EUR'); - $defaultCurrency = TransactionCurrency::whereCode($currencyPreference->data)->first(); - + $currencies = $repository->get(); + $defaultCurrency = $repository->getCurrencyByPreference(Preferences::get('currencyPreference', 'EUR')); return view('currency.index', compact('currencies', 'defaultCurrency')); } @@ -147,28 +145,22 @@ class CurrencyController extends Controller * * @return $this|\Illuminate\Http\RedirectResponse */ - public function store(CurrencyFormRequest $request) + public function store(CurrencyFormRequest $request, CurrencyRepositoryInterface $repository) { + $data = $request->getCurrencyData(); + $currency = $repository->store($data); - // no repository, because the currency controller is relatively simple. - $currency = TransactionCurrency::create( - [ - 'name' => $request->get('name'), - 'code' => $request->get('code'), - 'symbol' => $request->get('symbol'), - ] - ); - Session::flash('success', 'Currency "' . $currency->name . '" created'); if (intval(Input::get('create_another')) === 1) { Session::put('currency.create.fromStore', true); + return Redirect::route('currency.create')->withInput(); } // redirect to previous URL. - return Redirect::to(Session::get('categories.create.url')); + return Redirect::to(Session::get('currency.create.url')); } @@ -178,19 +170,17 @@ class CurrencyController extends Controller * * @return $this|\Illuminate\Http\RedirectResponse */ - public function update(TransactionCurrency $currency, CurrencyFormRequest $request) + public function update(TransactionCurrency $currency, CurrencyFormRequest $request, CurrencyRepositoryInterface $repository) { - - $currency->code = $request->get('code'); - $currency->symbol = $request->get('symbol'); - $currency->name = $request->get('name'); - $currency->save(); + $data = $request->getCurrencyData(); + $currency = $repository->update($currency, $data); Session::flash('success', 'Currency "' . e($currency->name) . '" updated.'); if (intval(Input::get('return_to_edit')) === 1) { Session::put('currency.edit.fromUpdate', true); + return Redirect::route('currency.edit', $currency->id); } diff --git a/app/Http/Controllers/GoogleChartController.php b/app/Http/Controllers/GoogleChartController.php index 6072e490e1..0c0ce8138b 100644 --- a/app/Http/Controllers/GoogleChartController.php +++ b/app/Http/Controllers/GoogleChartController.php @@ -89,7 +89,7 @@ class GoogleChartController extends Controller $index = 1; /** @var Account $account */ foreach ($accounts as $account) { - $accountName = iconv('UTF-8', 'ASCII//TRANSLIT', $account->name); + $accountName = $account->name; $chart->addColumn('Balance for ' . $accountName, 'number'); $chart->addCertainty($index); $index++; @@ -108,7 +108,7 @@ class GoogleChartController extends Controller $current->addDay(); } $chart->generate(); - + //header('Content-Type: application/json; charset=utf-8'); return Response::json($chart->getData()); } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 76b41d0bc9..2f029fde65 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -7,6 +7,7 @@ use Input; use Preferences; use Session; use Redirect; +use Config; /** * Class HomeController * @@ -41,7 +42,8 @@ class HomeController extends Controller public function index(AccountRepositoryInterface $repository) { - $count = $repository->countAssetAccounts(); + $types = Config::get('firefly.accountTypesByIdentifier.asset'); + $count = $repository->countAccounts($types); $title = 'Firefly'; $subTitle = 'What\'s playing?'; $mainTitleIcon = 'fa-fire'; diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index e8300109ad..4d850ef7bb 100644 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -88,7 +88,7 @@ class TransactionController extends Controller // put previous url in session Session::put('transactions.delete.url', URL::previous()); - return View::make('transactions.delete', compact('journal', 'subTitle')); + return view('transactions.delete', compact('journal', 'subTitle')); } diff --git a/app/Http/Requests/AccountFormRequest.php b/app/Http/Requests/AccountFormRequest.php index f5c03fd7d7..370415f26f 100644 --- a/app/Http/Requests/AccountFormRequest.php +++ b/app/Http/Requests/AccountFormRequest.php @@ -32,11 +32,11 @@ class AccountFormRequest extends Request $types = join(',', array_keys(Config::get('firefly.subTitlesByIdentifier'))); $ccPaymentTypes = join(',', array_keys(Config::get('firefly.ccTypes'))); - $nameRule = 'required|between:1,100|uniqueAccountForUser'; + $nameRule = 'required|min:1|uniqueAccountForUser'; $idRule = ''; if (Account::find(Input::get('id'))) { $idRule = 'belongsToUser:accounts'; - $nameRule = 'required|between:1,100|uniqueAccountForUser:' . Input::get('id'); + $nameRule = 'required|min:1|uniqueAccountForUser:' . Input::get('id'); } return [ diff --git a/app/Http/Requests/CurrencyFormRequest.php b/app/Http/Requests/CurrencyFormRequest.php index d45716d6d4..96b471790e 100644 --- a/app/Http/Requests/CurrencyFormRequest.php +++ b/app/Http/Requests/CurrencyFormRequest.php @@ -21,6 +21,18 @@ class CurrencyFormRequest extends Request return Auth::check(); } + /** + * @return array + */ + public function getCurrencyData() + { + return [ + 'name' => $this->get('name'), + 'code' => $this->get('code'), + 'symbol' => $this->get('symbol'), + ]; + } + /** * @return array */ diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php index 923012a4dc..113a25c433 100644 --- a/app/Providers/FireflyServiceProvider.php +++ b/app/Providers/FireflyServiceProvider.php @@ -62,6 +62,7 @@ class FireflyServiceProvider extends ServiceProvider $this->app->bind('FireflyIII\Repositories\Journal\JournalRepositoryInterface', 'FireflyIII\Repositories\Journal\JournalRepository'); $this->app->bind('FireflyIII\Repositories\Bill\BillRepositoryInterface', 'FireflyIII\Repositories\Bill\BillRepository'); $this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository'); + $this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository'); $this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search'); diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 4d580a848e..b09f53bdae 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -14,6 +14,7 @@ use FireflyIII\Models\Preference; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; +use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Log; @@ -29,11 +30,13 @@ class AccountRepository implements AccountRepositoryInterface { /** + * @param array $types + * * @return int */ - public function countAssetAccounts() + public function countAccounts(array $types) { - return Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->count(); + return Auth::user()->accounts()->accountTypeIn($types)->count(); } /** @@ -48,6 +51,30 @@ class AccountRepository implements AccountRepositoryInterface return true; } + /** + * @param array $types + * @param int $page + * + * @return Collection + */ + public function getAccounts(array $types, $page) + { + $query = Auth::user()->accounts()->with( + ['accountmeta' => function (HasMany $query) { + $query->where('name', 'accountRole'); + }] + )->accountTypeIn($types)->orderBy('accounts.name', 'ASC'); + + if ($page == -1) { + return $query->get(['accounts.*']); + } else { + $size = 50; + $offset = ($page - 1) * $size; + + return $query->take($size)->offset($offset)->get(['accounts.*']); + } + } + /** * @param TransactionJournal $journal * @param Account $account @@ -133,6 +160,23 @@ class AccountRepository implements AccountRepositoryInterface } + /** + * @param Account $account + * + * @return Carbon|null + */ + public function getLastActivity(Account $account) + { + $lastTransaction = $account->transactions()->leftJoin( + 'transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id' + )->orderBy('transaction_journals.date', 'DESC')->first(['transactions.*', 'transaction_journals.date']); + if ($lastTransaction) { + return $lastTransaction->transactionjournal->date; + } + + return null; + } + /** * Get savings accounts and the balance difference in the period. * diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index 8d00441a22..d064db673a 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -16,6 +16,13 @@ use Illuminate\Support\Collection; */ interface AccountRepositoryInterface { + /** + * @param array $types + * + * @return int + */ + public function countAccounts(array $types); + /** * @param Account $account * @@ -24,9 +31,20 @@ interface AccountRepositoryInterface public function destroy(Account $account); /** - * @return int + * @param array $types + * @param int $page + * + * @return mixed */ - public function countAssetAccounts(); + public function getAccounts(array $types, $page); + + /** + * @param TransactionJournal $journal + * @param Account $account + * + * @return Transaction + */ + public function getFirstTransaction(TransactionJournal $journal, Account $account); /** * @param Preference $preference @@ -52,6 +70,27 @@ interface AccountRepositoryInterface */ public function getJournals(Account $account, $page); + /** + * @param Account $account + * + * @return Carbon|null + */ + public function getLastActivity(Account $account); + + /** + * Get savings accounts and the balance difference in the period. + * + * @return Collection + */ + public function getSavingsAccounts(); + + /** + * @param Account $account + * + * @return float + */ + public function leftOnAccount(Account $account); + /** * @param Account $account * @@ -73,27 +112,4 @@ interface AccountRepositoryInterface * @return Account */ public function update(Account $account, array $data); - - /** - * @param Account $account - * - * @return float - */ - public function leftOnAccount(Account $account); - - /** - * Get savings accounts and the balance difference in the period. - * - * @return Collection - */ - public function getSavingsAccounts(); - - - /** - * @param TransactionJournal $journal - * @param Account $account - * - * @return Transaction - */ - public function getFirstTransaction(TransactionJournal $journal, Account $account); } diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index 9f928cabb4..049634ac40 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -2,9 +2,12 @@ namespace FireflyIII\Repositories\Bill; +use Auth; use Carbon\Carbon; use FireflyIII\Models\Bill; +use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; +use Illuminate\Support\Collection; use Log; use Navigation; @@ -15,6 +18,62 @@ use Navigation; */ class BillRepository implements BillRepositoryInterface { + /** + * @param Bill $bill + * + * @return mixed + */ + public function destroy(Bill $bill) + { + return $bill->delete(); + } + + /** + * @return Collection + */ + public function getBills() + { + return Auth::user()->bills()->orderBy('name', 'ASC')->get(); + } + + /** + * @param Bill $bill + * + * @return Collection + */ + public function getJournals(Bill $bill) + { + return $bill->transactionjournals()->withRelevantData() + ->orderBy('transaction_journals.date', 'DESC') + ->orderBy('transaction_journals.order', 'ASC') + ->orderBy('transaction_journals.id', 'DESC') + ->get(); + } + + /** + * @param Bill $bill + * + * @return Collection + */ + public function getPossiblyRelatedJournals(Bill $bill) + { + $set = \DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max)->get( + ['transaction_journal_id'] + ); + $ids = []; + + /** @var Transaction $entry */ + foreach ($set as $entry) { + $ids[] = intval($entry->transaction_journal_id); + } + $journals = new Collection; + if (count($ids) > 0) { + $journals = Auth::user()->transactionjournals()->whereIn('id', $ids)->get(); + } + + return $journals; + } + /** * Every bill repeats itself weekly, monthly or yearly (or whatever). This method takes a date-range (usually the view-range of Firefly itself) * and returns date ranges that fall within the given range; those ranges are the bills expected. When a bill is due on the 14th of the month and @@ -58,6 +117,21 @@ class BillRepository implements BillRepositoryInterface return $validRanges; } + /** + * @param Bill $bill + * + * @return Carbon|null + */ + public function lastFoundMatch(Bill $bill) + { + $last = $bill->transactionjournals()->orderBy('date', 'DESC')->first(); + if ($last) { + return $last->date; + } + + return null; + } + /** * @param Bill $bill * diff --git a/app/Repositories/Bill/BillRepositoryInterface.php b/app/Repositories/Bill/BillRepositoryInterface.php index 34142fcc37..134d275f00 100644 --- a/app/Repositories/Bill/BillRepositoryInterface.php +++ b/app/Repositories/Bill/BillRepositoryInterface.php @@ -5,6 +5,7 @@ namespace FireflyIII\Repositories\Bill; use Carbon\Carbon; use FireflyIII\Models\Bill; use FireflyIII\Models\TransactionJournal; +use Illuminate\Support\Collection; /** * Interface BillRepositoryInterface @@ -17,9 +18,28 @@ interface BillRepositoryInterface /** * @param Bill $bill * - * @return Carbon|null + * @return mixed */ - public function nextExpectedMatch(Bill $bill); + public function destroy(Bill $bill); + + /** + * @return Collection + */ + public function getBills(); + + /** + * @param Bill $bill + * + * @return Collection + */ + public function getPossiblyRelatedJournals(Bill $bill); + + /** + * @param Bill $bill + * + * @return Collection + */ + public function getJournals(Bill $bill); /** * Every bill repeats itself weekly, monthly or yearly (or whatever). This method takes a date-range (usually the view-range of Firefly itself) @@ -34,6 +54,28 @@ interface BillRepositoryInterface */ public function getRanges(Bill $bill, Carbon $start, Carbon $end); + /** + * @param Bill $bill + * + * @return Carbon|null + */ + public function lastFoundMatch(Bill $bill); + + /** + * @param Bill $bill + * + * @return Carbon|null + */ + public function nextExpectedMatch(Bill $bill); + + /** + * @param Bill $bill + * @param TransactionJournal $journal + * + * @return bool + */ + public function scan(Bill $bill, TransactionJournal $journal); + /** * @param array $data * @@ -49,12 +91,4 @@ interface BillRepositoryInterface */ public function update(Bill $bill, array $data); - /** - * @param Bill $bill - * @param TransactionJournal $journal - * - * @return bool - */ - public function scan(Bill $bill, TransactionJournal $journal); - } diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index bfd2655e46..5d614286bd 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -2,11 +2,13 @@ namespace FireflyIII\Repositories\Budget; +use Auth; use Carbon\Carbon; use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\LimitRepetition; use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Support\Collection; /** * Class BudgetRepository @@ -37,7 +39,7 @@ class BudgetRepository implements BudgetRepositoryInterface } // delete limits with amount 0: - BudgetLimit::where('amount',0)->delete(); + BudgetLimit::where('amount', 0)->delete(); } @@ -53,6 +55,33 @@ class BudgetRepository implements BudgetRepositoryInterface return true; } + /** + * @return Collection + */ + public function getActiveBudgets() + { + return Auth::user()->budgets()->where('active', 1)->get(); + } + + /** + * @param Budget $budget + * @param Carbon $date + * + * @return LimitRepetition|null + */ + public function getCurrentRepetition(Budget $budget, Carbon $date) + { + return $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']); + } + + /** + * @return Collection + */ + public function getInactiveBudgets() + { + return Auth::user()->budgets()->where('active', 1)->get(); + } + /** * Returns all the transaction journals for a limit, possibly limited by a limit repetition. * @@ -86,6 +115,26 @@ class BudgetRepository implements BudgetRepositoryInterface return new LengthAwarePaginator($set, $count, $take, $offset); } + /** + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getWithoutBudget(Carbon $start, Carbon $end) + { + return Auth::user() + ->transactionjournals() + ->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->whereNull('budget_transaction_journal.id') + ->before($end) + ->after($start) + ->orderBy('transaction_journals.date', 'DESC') + ->orderBy('transaction_journals.order', 'ASC') + ->orderBy('transaction_journals.id', 'DESC') + ->get(['transaction_journals.*']); + } + /** * @param Budget $budget * @param Carbon $date @@ -175,4 +224,14 @@ class BudgetRepository implements BudgetRepositoryInterface } + + /** + * @param Budget $budget + * + * @return Collection + */ + public function getBudgetLimits(Budget $budget) + { + return $budget->budgetLimits()->orderBy('startdate', 'DESC')->get(); + } } diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index 9b5eef9229..38cdc43532 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -5,6 +5,7 @@ namespace FireflyIII\Repositories\Budget; use Carbon\Carbon; use FireflyIII\Models\Budget; use FireflyIII\Models\LimitRepetition; +use Illuminate\Support\Collection; /** * Interface BudgetRepositoryInterface @@ -20,6 +21,16 @@ interface BudgetRepositoryInterface */ public function destroy(Budget $budget); + /** + * @return Collection + */ + public function getActiveBudgets(); + + /** + * @return Collection + */ + public function getInactiveBudgets(); + /** * @return void */ @@ -33,6 +44,29 @@ interface BudgetRepositoryInterface */ public function spentInMonth(Budget $budget, Carbon $date); + /** + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getWithoutBudget(Carbon $start, Carbon $end); + + /** + * @param Budget $budget + * + * @return Collection + */ + public function getBudgetLimits(Budget $budget); + + /** + * @param Budget $budget + * @param Carbon $date + * + * @return LimitRepetition|null + */ + public function getCurrentRepetition(Budget $budget, Carbon $date); + /** * @param Budget $budget * @param Carbon $date diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index 437fb2da69..3b8710a3f4 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -2,7 +2,10 @@ namespace FireflyIII\Repositories\Category; +use Auth; +use Carbon\Carbon; use FireflyIII\Models\Category; +use Illuminate\Support\Collection; /** * Class CategoryRepository @@ -12,6 +15,17 @@ use FireflyIII\Models\Category; class CategoryRepository implements CategoryRepositoryInterface { + /** + * @param Category $category + * + * @return int + */ + public function countJournals(Category $category) + { + return $category->transactionJournals()->count(); + + } + /** * @param Category $category * @@ -24,6 +38,72 @@ class CategoryRepository implements CategoryRepositoryInterface return true; } + /** + * @return Collection + */ + public function getCategories() + { + return Auth::user()->categories()->orderBy('name', 'ASC')->get(); + } + + /** + * @param Category $category + * @param int $page + * + * @return Collection + */ + public function getJournals(Category $category, $page) + { + $offset = $page > 0 ? $page * 50 : 0; + + return $category->transactionJournals()->withRelevantData()->take(50)->offset($offset) + ->orderBy('transaction_journals.date', 'DESC') + ->orderBy('transaction_journals.order', 'ASC') + ->orderBy('transaction_journals.id', 'DESC') + ->get( + ['transaction_journals.*'] + ); + + } + + /** + * @param Category $category + * + * @return Carbon|null + */ + public function getLatestActivity(Category $category) + { + $latest = $category->transactionjournals() + ->orderBy('transaction_journals.date', 'DESC') + ->orderBy('transaction_journals.order', 'ASC') + ->orderBy('transaction_journals.id', 'DESC') + ->first(); + if ($latest) { + return $latest->date; + } + + return null; + } + + /** + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getWithoutCategory(Carbon $start, Carbon $end) + { + return Auth::user() + ->transactionjournals() + ->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id') + ->whereNull('category_transaction_journal.id') + ->before($end) + ->after($start) + ->orderBy('transaction_journals.date', 'DESC') + ->orderBy('transaction_journals.order', 'ASC') + ->orderBy('transaction_journals.id', 'DESC') + ->get(['transaction_journals.*']); + } /** * @param array $data @@ -57,5 +137,4 @@ class CategoryRepository implements CategoryRepositoryInterface return $category; } - } diff --git a/app/Repositories/Category/CategoryRepositoryInterface.php b/app/Repositories/Category/CategoryRepositoryInterface.php index 7e4871a378..33ba5cc1d1 100644 --- a/app/Repositories/Category/CategoryRepositoryInterface.php +++ b/app/Repositories/Category/CategoryRepositoryInterface.php @@ -2,7 +2,9 @@ namespace FireflyIII\Repositories\Category; +use Carbon\Carbon; use FireflyIII\Models\Category; +use Illuminate\Support\Collection; /** * Interface CategoryRepositoryInterface @@ -11,6 +13,13 @@ use FireflyIII\Models\Category; */ interface CategoryRepositoryInterface { + /** + * @param Category $category + * + * @return int + */ + public function countJournals(Category $category); + /** * @param Category $category * @@ -18,6 +27,34 @@ interface CategoryRepositoryInterface */ public function destroy(Category $category); + /** + * @return Collection + */ + public function getCategories(); + + /** + * @param Category $category + * @param int $page + * + * @return Collection + */ + public function getJournals(Category $category, $page); + + /** + * @param Category $category + * + * @return Carbon|null + */ + public function getLatestActivity(Category $category); + + /** + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getWithoutCategory(Carbon $start, Carbon $end); + /** * @param array $data * diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php new file mode 100644 index 0000000000..bffdc88c94 --- /dev/null +++ b/app/Repositories/Currency/CurrencyRepository.php @@ -0,0 +1,84 @@ +transactionJournals()->count(); + } + + /** + * @return Collection + */ + public function get() + { + return TransactionCurrency::get(); + } + + /** + * @param Preference $preference + * + * @return TransactionCurrency + */ + public function getCurrencyByPreference(Preference $preference) + { + $preferred = TransactionCurrency::whereCode($preference->data)->first(); + if (is_null($preferred)) { + $preferred = TransactionCurrency::first(); + } + + return $preferred; + } + + /** + * @param array $data + * + * @return TransactionCurrency + */ + public function store(array $data) + { + $currency = TransactionCurrency::create( + [ + 'name' => $data['name'], + 'code' => $data['code'], + 'symbol' => $data['symbol'], + ] + ); + + return $currency; + } + + /** + * @param TransactionCurrency $currency + * @param array $data + * + * @return TransactionCurrency + */ + public function update(TransactionCurrency $currency, array $data) + { + $currency->code = $data['code']; + $currency->symbol = $data['symbol']; + $currency->name = $data['name']; + $currency->save(); + + return $currency; + } +} \ No newline at end of file diff --git a/app/Repositories/Currency/CurrencyRepositoryInterface.php b/app/Repositories/Currency/CurrencyRepositoryInterface.php new file mode 100644 index 0000000000..cfb72467ba --- /dev/null +++ b/app/Repositories/Currency/CurrencyRepositoryInterface.php @@ -0,0 +1,52 @@ +assertTrue(true); - } - -} diff --git a/tests/TestCase.php b/tests/TestCase.php index c7be516d16..9ceb86ea36 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -29,7 +29,7 @@ class TestCase extends Illuminate\Foundation\Testing\TestCase */ public static function setUpBeforeClass() { - + parent::setUpBeforeClass(); } /** diff --git a/tests/controllers/AccountControllerTest.php b/tests/controllers/AccountControllerTest.php index 07da123560..be21d77d87 100644 --- a/tests/controllers/AccountControllerTest.php +++ b/tests/controllers/AccountControllerTest.php @@ -1,14 +1,19 @@ createAccount(); } + /** + * This method is called before the first test of this test class is run. + * + * @since Method available since Release 3.4.0 + */ + public static function setUpBeforeClass() + { + parent::setUpBeforeClass(); + } /** * Tears down the fixture, for example, closes a network connection. @@ -28,8 +42,18 @@ class AccountControllerTest extends TestCase public function tearDown() { parent::tearDown(); + } + public function createAccount() + { + if (is_null($this->account)) { + $this->account = FactoryMuffin::create('FireflyIII\Models\Account'); + Log::debug('Created a new account.'); + //$this->account->accountType->type = 'Asset account'; + //$this->account->accountType->save(); + } + } public function testCreate() { @@ -57,24 +81,18 @@ class AccountControllerTest extends TestCase public function testDelete() { - // fake an account. - $account = FactoryMuffin::create('FireflyIII\Models\Account'); - $account->accountType->type = 'Asset account'; - $account->accountType->save(); - $this->be($account->user); - $this->call('GET', '/accounts/delete/' . $account->id); + $this->be($this->account->user); + $this->call('GET', '/accounts/delete/' . $this->account->id); $this->assertResponseOk(); - $this->assertViewHas('subTitle', 'Delete ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'); + $this->assertViewHas('subTitle', 'Delete ' . strtolower(e($this->account->accountType->type)) . ' "' . e($this->account->name) . '"'); } public function testDestroy() { // fake an account. - $account = FactoryMuffin::create('FireflyIII\Models\Account'); - $account->accountType->type = 'Asset account'; - $account->accountType->save(); + $account = FactoryMuffin::create('FireflyIII\Models\Account'); $this->be($account->user); $this->assertCount(1, DB::table('accounts')->where('id', $account->id)->whereNull('deleted_at')->get()); @@ -88,12 +106,9 @@ class AccountControllerTest extends TestCase public function testEdit() { // fake an account. - $account = FactoryMuffin::create('FireflyIII\Models\Account'); - $account->accountType->type = 'Asset account'; - $account->accountType->save(); - $this->be($account->user); - $this->assertCount(1, DB::table('accounts')->where('id', $account->id)->whereNull('deleted_at')->get()); + $this->be($this->account->user); + $this->assertCount(1, DB::table('accounts')->where('id', $this->account->id)->whereNull('deleted_at')->get()); // create a transaction journal that will act as opening balance: $openingBalance = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); @@ -110,24 +125,32 @@ class AccountControllerTest extends TestCase Amount::shouldReceive('getAllCurrencies')->once()->andReturn([$currency]); // get edit page: - $this->call('GET', '/accounts/edit/' . $account->id); + $this->call('GET', '/accounts/edit/' . $this->account->id); // assert stuff: $this->assertResponseOk(); $this->assertSessionHas('preFilled'); - $this->assertViewHas('subTitle', 'Edit ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"'); + $this->assertViewHas('subTitle', 'Edit ' . strtolower(e($this->account->accountType->type)) . ' "' . e($this->account->name) . '"'); } public function testIndex() { - $user = FactoryMuffin::create('FireflyIII\User'); - $this->be($user); + // an account: + $this->be($this->account->user); + + $collection = new Collection; + $collection->push($this->account); + + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('getAccounts')->andReturn($collection); + $repository->shouldReceive('countAccounts')->andReturn(1); + $repository->shouldReceive('getLastActivity')->andReturn(null); + + Amount::shouldReceive('format')->andReturn(''); + Amount::shouldReceive('getCurrencyCode')->once()->andReturn('A'); - // get currency code: - $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); - Amount::shouldReceive('getCurrencyCode')->andReturn($currency->code); // put stuff in session: $this->session(['start' => new Carbon, 'end' => new Carbon]); @@ -141,17 +164,136 @@ class AccountControllerTest extends TestCase public function testShow() { - $this->markTestIncomplete(); + // an account: + $this->be($this->account->user); + + Amount::shouldReceive('getCurrencyCode')->once()->andReturn('A'); + + // get edit page: + $this->call('GET', '/accounts/show/' . $this->account->id); + $this->assertResponseOk(); } public function testStore() { - $this->markTestIncomplete(); + // an account: + $this->be($this->account->user); + + $data = [ + 'name' => 'New test account ' . rand(1, 1000), + 'what' => 'asset', + 'virtualBalance' => 0, + 'accountRole' => 'defaultAsset', + 'openingBalance' => 20, + 'openingBalanceDate' => date('Y-m-d'), + 'openingBalanceCurrency' => 1, + '_token' => 'replaceme' + ]; + + // fake validation routine: + $request = $this->mock('FireflyIII\Http\Requests\AccountFormRequest'); + $request->shouldReceive('input')->andReturn(''); + + // fake store routine: + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('store')->andReturn($this->account); + + $this->call('POST', '/accounts/store', $data); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + + } + + public function testStoreAndRedirect() + { + // an account: + $this->be($this->account->user); + + $data = [ + 'name' => 'New test account ' . rand(1, 1000), + 'what' => 'asset', + 'virtualBalance' => 0, + 'accountRole' => 'defaultAsset', + 'openingBalance' => 20, + 'openingBalanceDate' => date('Y-m-d'), + 'openingBalanceCurrency' => 1, + '_token' => 'replaceme', + 'create_another' => 1, + ]; + + // fake validation routine: + $request = $this->mock('FireflyIII\Http\Requests\AccountFormRequest'); + $request->shouldReceive('input')->andReturn(''); + + // fake store routine: + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('store')->andReturn($this->account); + + $this->call('POST', '/accounts/store', $data); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + } public function testUpdate() { - $this->markTestIncomplete(); + + // an account: + $this->be($this->account->user); + + $data = [ + 'name' => 'Edited test account ' . rand(1, 1000), + 'active' => 1, + 'accountRole' => 'defaultAsset', + 'virtualBalance' => 0, + 'openingBalance' => 25, + 'openingBalanceDate' => date('Y-m-d'), + 'openingBalanceCurrency' => 1, + '_token' => 'replaceme' + ]; + + // fake validation routine: + $request = $this->mock('FireflyIII\Http\Requests\AccountFormRequest'); + $request->shouldReceive('input')->andReturn(''); + + // fake update routine: + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('update')->andReturn($this->account); + + $this->call('POST', '/accounts/update/' . $this->account->id, $data); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + } + + public function testUpdateAndRedirect() + { + + // an account: + $this->be($this->account->user); + + $data = [ + 'name' => 'Edited test account ' . rand(1, 1000), + 'active' => 1, + 'accountRole' => 'defaultAsset', + 'virtualBalance' => 0, + 'openingBalance' => 25, + 'openingBalanceDate' => date('Y-m-d'), + 'openingBalanceCurrency' => 1, + '_token' => 'replaceme', + 'return_to_edit' => 1, + ]; + + // fake validation routine: + $request = $this->mock('FireflyIII\Http\Requests\AccountFormRequest'); + $request->shouldReceive('input')->andReturn(''); + + // fake update routine: + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('update')->andReturn($this->account); + + $this->call('POST', '/accounts/update/' . $this->account->id, $data); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); } } diff --git a/tests/controllers/BillControllerTest.php b/tests/controllers/BillControllerTest.php new file mode 100644 index 0000000000..aa24ff040d --- /dev/null +++ b/tests/controllers/BillControllerTest.php @@ -0,0 +1,249 @@ +be($bill->user); + + // create an expense account: + $expense = FactoryMuffin::create('FireflyIII\Models\Account'); + // fix the name of the expense account to match one of the words + // in the bill: + $words = explode(',', $bill->match); + $word = $words[1]; + $expense->name = $word; + $expense->save(); + + // mock repository: + $repository = $this->mock('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $repository->shouldReceive('getAccounts')->andReturn([$expense]); + + // go! + $this->call('GET', '/bills/add/' . $bill->id); + $this->assertSessionHas('preFilled'); + $this->assertRedirectedToRoute('transactions.create', ['withdrawal']); + } + + public function testCreate() + { + // go! + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $this->be($bill->user); + + // CURRENCY: + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + Amount::shouldReceive('getDefaultCurrency')->once()->andReturn($currency); + Amount::shouldReceive('getAllCurrencies')->once()->andReturn([$currency]); + + $this->call('GET', '/bills/create'); + $this->assertViewHas('subTitle', 'Create new'); + $this->assertResponseOk(); + + } + + public function testDelete() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $this->be($bill->user); + $this->call('GET', '/bills/delete/' . $bill->id); + $this->assertViewHas('subTitle', 'Delete "' . e($bill->name) . '"'); + $this->assertResponseOk(); + } + + public function testDestroy() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $this->be($bill->user); + + + $this->call('POST', '/bills/destroy/' . $bill->id, ['_token' => 'replaceMe']); + $this->assertSessionHas('success', 'The bill was deleted.'); + $this->assertResponseStatus(302); + } + + public function testEdit() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $this->be($bill->user); + + // CURRENCY: + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + Amount::shouldReceive('getDefaultCurrency')->once()->andReturn($currency); + Amount::shouldReceive('getAllCurrencies')->once()->andReturn([$currency]); + + $this->call('GET', '/bills/edit/' . $bill->id); + $this->assertViewHas('subTitle', 'Edit "' . e($bill->name) . '"'); + $this->assertResponseOk(); + } + + public function testIndex() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $this->be($bill->user); + + $collection = new Collection; + $collection->push($bill); + + Amount::shouldReceive('format')->andReturn('XX'); + + $repository = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $repository->shouldReceive('getBills')->once()->andReturn($collection); + $repository->shouldReceive('nextExpectedMatch')->with($bill)->andReturn(new Carbon); + $repository->shouldReceive('lastFoundMatch')->with($bill)->andReturn(new Carbon); + + $this->call('GET', '/bills'); + $this->assertResponseOk(); + + } + + public function testRescan() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $journal = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $collection = new Collection; + $this->be($bill->user); + $collection->push($journal); + + $repository = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $repository->shouldReceive('getPossiblyRelatedJournals')->once()->andReturn($collection); + $repository->shouldReceive('scan'); + + $this->call('GET', '/bills/rescan/' . $bill->id); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', 'Rescanned everything.'); + + + } + + public function testRescanInactive() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $bill->active = 0; + $bill->save(); + $this->be($bill->user); + + $this->call('GET', '/bills/rescan/' . $bill->id); + $this->assertResponseStatus(302); + $this->assertSessionHas('warning', 'Inactive bills cannot be scanned.'); + + } + + public function testShow() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $journal = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $collection = new Collection; + + $bill->save(); + $this->be($bill->user); + $collection->push($journal); + + + $repository = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $repository->shouldReceive('getJournals')->once()->andReturn($collection); + $repository->shouldReceive('nextExpectedMatch')->once()->andReturn(new Carbon); + + Amount::shouldReceive('format')->andReturn('XX'); + Amount::shouldReceive('getCurrencyCode')->andReturn('XX'); + + $this->call('GET', '/bills/show/' . $bill->id); + } + + public function testStore() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $repository = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\BillFormRequest'); + + $this->be($bill->user); + $request->shouldReceive('getBillData')->once()->andReturn([]); + $repository->shouldReceive('store')->with([])->andReturn($bill); + + $this->call('POST', '/bills/store', ['_token' => 'replaceMe']); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', 'Bill "' . e($bill->name) . '" stored.'); + } + + public function testStoreAndRedirect() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $repository = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\BillFormRequest'); + + $this->be($bill->user); + $request->shouldReceive('getBillData')->once()->andReturn([]); + $repository->shouldReceive('store')->with([])->andReturn($bill); + + $this->call('POST', '/bills/store', ['_token' => 'replaceMe', 'create_another' => 1]); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', 'Bill "' . e($bill->name) . '" stored.'); + } + + public function testUpdate() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $repository = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\BillFormRequest'); + + $this->be($bill->user); + $request->shouldReceive('getBillData')->once()->andReturn([]); + $repository->shouldReceive('update')->andReturn($bill); + + $this->call('POST', '/bills/update/' . $bill->id, ['_token' => 'replaceMe']); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', 'Bill "' . e($bill->name) . '" updated.'); + } + + public function testUpdateAndRedirect() + { + $bill = FactoryMuffin::create('FireflyIII\Models\Bill'); + $repository = $this->mock('FireflyIII\Repositories\Bill\BillRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\BillFormRequest'); + + $this->be($bill->user); + $request->shouldReceive('getBillData')->once()->andReturn([]); + $repository->shouldReceive('update')->andReturn($bill); + + $this->call('POST', '/bills/update/' . $bill->id, ['_token' => 'replaceMe', 'return_to_edit' => 1]); + $this->assertResponseStatus(302); + + } +} \ No newline at end of file diff --git a/tests/controllers/BudgetControllerTest.php b/tests/controllers/BudgetControllerTest.php new file mode 100644 index 0000000000..0a89b99076 --- /dev/null +++ b/tests/controllers/BudgetControllerTest.php @@ -0,0 +1,311 @@ +mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $limitRepetition = FactoryMuffin::create('FireflyIII\Models\LimitRepetition'); + $budget = $limitRepetition->budgetlimit->budget; + $this->be($budget->user); + $today = new Carbon; + + $this->session(['start' => $today]); + $repository->shouldReceive('updateLimitAmount')->once()->andReturn($limitRepetition); + $this->call('POST', '/budgets/amount/' . $budget->id, ['amount' => 100, '_token' => 'replaceme']); + $this->assertResponseOk(); + + } + + public function testCreate() + { + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + $this->call('GET', '/budgets/create'); + $this->assertResponseOk(); + $this->assertViewHas('subTitle', 'Create a new budget'); + } + + public function testDelete() + { + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + $this->call('GET', '/budgets/delete/' . $budget->id); + + $this->assertResponseOk(); + $this->assertViewHas('subTitle', 'Delete budget' . e($budget->name) . '"'); + $this->assertViewHas('budget'); + $this->assertSessionHas('budgets.delete.url'); + } + + public function testDestroy() + { + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + + $this->assertCount(1, DB::table('budgets')->where('id', $budget->id)->get()); + + $this->call('POST', '/budgets/destroy/' . $budget->id, ['_token' => 'replaceme']); + + $this->assertSessionHas('success', 'The budget "' . e($budget->name) . '" was deleted.'); + $this->assertCount(0, DB::table('budgets')->wherenull('deleted_at')->where('id', $budget->id)->get()); + } + + public function testEdit() + { + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + + $this->call('GET', '/budgets/edit/' . $budget->id); + + $this->assertResponseOk(); + $this->assertViewHas('subTitle', 'Edit budget "' . e($budget->name) . '"'); + $this->assertViewHas('budget'); + $this->assertSessionHas('budgets.edit.url'); + } + + public function testIndex() + { + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + $collection = new Collection; + $collection->push($budget); + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + + $repository->shouldReceive('getActiveBudgets')->once()->andReturn($collection); + $repository->shouldReceive('getInactiveBudgets')->once()->andReturn($collection); + $repository->shouldReceive('cleanupBudgets')->once(); + $repository->shouldReceive('spentInMonth')->once(); + $repository->shouldReceive('getCurrentRepetition')->once(); + Amount::shouldReceive('getCurrencySymbol')->andReturn('x'); + Amount::shouldReceive('format')->andReturn('x'); + $this->call('GET', '/budgets'); + + $this->assertResponseOk(); + $this->assertViewHas('budgets'); + $this->assertViewHas('inactive'); + $this->assertViewHas('inactive'); + + } + + public function testNoBudget() + { + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('getWithoutBudget')->andReturn(new Collection); + + $this->call('GET', '/budgets/list/noBudget'); + $this->assertResponseOk(); + $this->assertViewHas('list'); + $this->assertViewHas('subTitle'); + } + + public function testPostUpdateIncome() + { + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + $date = Carbon::now()->startOfMonth()->format('FY'); + Preferences::shouldReceive('set')->once()->withArgs(['budgetIncomeTotal' . $date, 1001]); + + $this->call('POST', '/budgets/income', ['_token' => 'replaceme', 'amount' => 1001]); + $this->assertResponseStatus(302); + $this->assertRedirectedToRoute('budgets.index'); + } + + public function testShow() + { + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $this->be($budget->user); + + Amount::shouldReceive('getCurrencyCode')->andReturn('x'); + Amount::shouldReceive('format')->andReturn('x'); + $repository->shouldReceive('getJournals')->andReturn(new Collection); + $repository->shouldReceive('getBudgetLimits')->andReturn(new Collection); + + + $this->call('GET', '/budgets/show/' . $budget->id); + $this->assertResponseOk(); + + } + + public function testShowInvalidRepetition() + { + + $repetition = FactoryMuffin::create('FireflyIII\Models\LimitRepetition'); + $budget = $repetition->budgetLimit->budget; + $otherBudget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $otherBudget->user_id = $budget->user_id; + $otherBudget->save(); + + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $this->be($otherBudget->user); + + Amount::shouldReceive('getCurrencyCode')->andReturn('x'); + Amount::shouldReceive('format')->andReturn('x'); + $repository->shouldReceive('getJournals')->andReturn(new Collection); + $repository->shouldReceive('getBudgetLimits')->andReturn(new Collection); + + + $this->call('GET', '/budgets/show/' . $otherBudget->id . '/' . $repetition->id); + $this->assertResponseOk(); + $this->assertViewHas('message', 'Invalid selection.'); + + } + + public function testStore() + { + // a budget: + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + + $data = [ + 'name' => 'New test budget ' . rand(1, 1000), + '_token' => 'replaceme' + ]; + + // fake validation routine: + $request = $this->mock('FireflyIII\Http\Requests\BudgetFormRequest'); + $request->shouldReceive('input')->andReturn(''); + + // fake store routine: + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('store')->andReturn($budget); + + $this->call('POST', '/budgets/store', $data); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + + } + + public function testStoreAndRedirect() + { + // a budget: + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + + $data = [ + 'name' => 'New test budget ' . rand(1, 1000), + '_token' => 'replaceme', + 'create_another' => 1, + ]; + + // fake validation routine: + $request = $this->mock('FireflyIII\Http\Requests\BudgetFormRequest'); + $request->shouldReceive('input')->andReturn(''); + + // fake store routine: + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('store')->andReturn($budget); + + $this->call('POST', '/budgets/store', $data); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + + } + + public function testUpdate() + { + + // a budget: + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + + $data = [ + 'name' => 'Edited test account ' . rand(1, 1000), + 'active' => 1, + '_token' => 'replaceme' + ]; + + // fake validation routine: + $request = $this->mock('FireflyIII\Http\Requests\BudgetFormRequest'); + $request->shouldReceive('input')->andReturn(''); + + // fake update routine: + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('update')->andReturn($budget); + + $this->call('POST', '/budgets/update/' . $budget->id, $data); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + } + + public function testUpdateAndRedirect() + { + + // a budget: + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + + $data = [ + 'name' => 'Edited test account ' . rand(1, 1000), + 'active' => 1, + '_token' => 'replaceme', + 'return_to_edit' => 1, + ]; + + // fake validation routine: + $request = $this->mock('FireflyIII\Http\Requests\BudgetFormRequest'); + $request->shouldReceive('input')->andReturn(''); + + // fake update routine: + $repository = $this->mock('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $repository->shouldReceive('update')->andReturn($budget); + + $this->call('POST', '/budgets/update/' . $budget->id, $data); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + } + + public function testUpdateIncome() + { + + // a budget: + $budget = FactoryMuffin::create('FireflyIII\Models\Budget'); + $this->be($budget->user); + $date = Carbon::now()->format('FY'); + $pref = FactoryMuffin::create('FireflyIII\Models\Preference'); + Preferences::shouldReceive('get')->withArgs(['budgetIncomeTotal' . $date, 1000])->andReturn($pref); + Amount::shouldReceive('format')->andReturn('xx'); + + $this->call('GET', '/budgets/income'); + $this->assertResponseOk(); + $this->assertViewHas('amount'); + } +} \ No newline at end of file diff --git a/tests/controllers/CategoryControllerTest.php b/tests/controllers/CategoryControllerTest.php new file mode 100644 index 0000000000..33119cc388 --- /dev/null +++ b/tests/controllers/CategoryControllerTest.php @@ -0,0 +1,199 @@ +be($category->user); + + $this->call('GET', '/categories/create'); + $this->assertResponseOk(); + $this->assertViewHas('subTitle', 'Create a new category'); + } + + public function testDelete() + { + + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $this->be($category->user); + + $this->call('GET', '/categories/delete/' . $category->id); + $this->assertResponseOk(); + $this->assertViewHas('subTitle', 'Delete category' . e($category->name) . '"'); + } + + public function testDestroy() + { + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $this->be($category->user); + + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $repository->shouldReceive('destroy'); + + $this->call('POST', '/categories/destroy/' . $category->id, ['_token' => 'replaceMe']); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', 'The category "' . e($category->name) . '" was deleted.'); + } + + public function testEdit() + { + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $this->be($category->user); + + $this->call('GET', '/categories/edit/' . $category->id); + $this->assertResponseOk(); + $this->assertViewHas('subTitle', 'Edit category "' . e($category->name) . '"'); + } + + public function testIndex() + { + $collection = new Collection; + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $this->be($category->user); + $collection->push($category); + + Amount::shouldReceive('getCurrencyCode')->andReturn('xx'); + + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $repository->shouldReceive('getCategories')->andReturn($collection); + $repository->shouldReceive('getLatestActivity')->andReturn(new Carbon); + + $this->call('GET', '/categories'); + $this->assertResponseOk(); + $this->assertViewHas('categories'); + } + + public function testNoCategory() + { + $collection = new Collection; + $journal = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $this->be($journal->user); + $collection->push($journal); + + Amount::shouldReceive('format')->andReturn('xx'); + Amount::shouldReceive('getCurrencyCode')->andReturn('xx'); + + + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + $repository->shouldReceive('getWithoutCategory')->andReturn($repository); + + $this->call('GET', '/categories/list/noCategory'); + $this->assertResponseOk(); + $this->assertViewHas('subTitle'); + + + } + + public function testShow() + { + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $collection = new Collection; + $journal = FactoryMuffin::create('FireflyIII\Models\TransactionJournal'); + $this->be($category->user); + $collection->push($journal); + + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + + $repository->shouldReceive('getJournals')->andReturn($collection); + $repository->shouldReceive('countJournals')->andReturn(1); + + Amount::shouldReceive('format')->andReturn('xx'); + Amount::shouldReceive('getCurrencyCode')->andReturn('xx'); + + $this->call('GET', '/categories/show/' . $category->id); + $this->assertResponseOk(); + $this->assertViewHas('hideCategory', true); + + } + + public function testStore() + { + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + + $repository->shouldReceive('store')->andReturn($category); + $this->be($category->user); + + $this->call('POST', '/categories/store', ['_token' => 'replaceMe', 'name' => 'Bla bla #' . rand(1, 1000)]); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', 'New category "' . $category->name . '" stored!'); + } + + // + public function testStoreAndRedirect() + { + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + + $repository->shouldReceive('store')->andReturn($category); + $this->be($category->user); + + $this->call('POST', '/categories/store', ['_token' => 'replaceMe', 'create_another' => 1, 'name' => 'Bla bla #' . rand(1, 1000)]); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', 'New category "' . $category->name . '" stored!'); + } + + public function testUpdate() + { + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + + $repository->shouldReceive('update')->andReturn($category); + $this->be($category->user); + + $this->call('POST', '/categories/update/' . $category->id, ['_token' => 'replaceMe', 'name' => 'Bla bla #' . rand(1, 1000)]); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', 'Category "' . $category->name . '" updated.'); + } + + public function testUpdateAndRedirect() + { + $category = FactoryMuffin::create('FireflyIII\Models\Category'); + $repository = $this->mock('FireflyIII\Repositories\Category\CategoryRepositoryInterface'); + + $repository->shouldReceive('update')->andReturn($category); + $this->be($category->user); + + $this->call('POST', '/categories/update/' . $category->id, ['_token' => 'replaceMe', 'return_to_edit' => 1, 'name' => 'Bla bla #' . rand(1, 1000)]); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', 'Category "' . $category->name . '" updated.'); + } +} \ No newline at end of file diff --git a/tests/controllers/CurrencyControllerTest.php b/tests/controllers/CurrencyControllerTest.php new file mode 100644 index 0000000000..b06e1cb67a --- /dev/null +++ b/tests/controllers/CurrencyControllerTest.php @@ -0,0 +1,217 @@ +be($user); + + $this->call('GET', '/currency/create'); + $this->assertResponseOk(); + $this->assertViewHas('subTitle', 'Create a new currency'); + $this->assertViewHas('subTitleIcon', 'fa-plus'); + + } + + public function testDefaultCurrency() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + + $this->call('GET', '/currency/default/' . $currency->id); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', $currency->name . ' is now the default currency.'); + } + + public function testDelete() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + + $repository = $this->mock('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + $repository->shouldReceive('countJournals')->andReturn(0); + + $this->call('GET', '/currency/delete/' . $currency->id); + $this->assertResponseOk(); + $this->assertViewHas('currency'); + + } + + public function testDeleteUnable() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + + $repository = $this->mock('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + $repository->shouldReceive('countJournals')->andReturn(1); + + $this->call('GET', '/currency/delete/' . $currency->id); + $this->assertResponseStatus(302); + $this->assertSessionHas('error'); + + } + + public function testDestroy() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + + $repository = $this->mock('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + $repository->shouldReceive('countJournals')->andReturn(0); + + $this->call('POST', '/currency/destroy/' . $currency->id, ['_token' => 'replaceMe']); + $this->assertResponseStatus(302); + $this->assertSessionHas('success', 'Currency "' . e($currency->name) . '" deleted'); + + } + + public function testDestroyUnable() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + + $repository = $this->mock('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + $repository->shouldReceive('countJournals')->andReturn(1); + + $this->call('POST', '/currency/destroy/' . $currency->id, ['_token' => 'replaceMe']); + $this->assertResponseStatus(302); + $this->assertSessionHas('error'); + + } + + public function testEdit() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $this->be($user); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + + $repository = $this->mock('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + $repository->shouldReceive('countJournals')->andReturn(0); + + $this->call('GET', '/currency/edit/' . $currency->id); + $this->assertResponseOk(); + $this->assertViewHas('currency'); + } + + public function testIndex() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + $this->be($user); + + $repository = $this->mock('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + $repository->shouldReceive('get')->andReturn(new Collection); + $repository->shouldReceive('getCurrencyByPreference')->andReturn($currency); + + $this->call('GET', '/currency'); + $this->assertResponseOk(); + } + + public function testStore() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + $this->be($user); + + $repository = $this->mock('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\CurrencyFormRequest'); + $request->shouldReceive('getCurrencyData')->andReturn([]); + $repository->shouldReceive('store')->andReturn($currency); + + $this->call('POST', '/currency/store', ['_token' => 'replaceMe']); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + + + } + + public function testStoreAndReturn() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + $this->be($user); + + $repository = $this->mock('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\CurrencyFormRequest'); + $request->shouldReceive('getCurrencyData')->andReturn([]); + $repository->shouldReceive('store')->andReturn($currency); + + $this->call('POST', '/currency/store', ['_token' => 'replaceMe', 'create_another' => 1]); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + + + } + + public function testUpdate() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + $this->be($user); + + $repository = $this->mock('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\CurrencyFormRequest'); + $request->shouldReceive('getCurrencyData')->andReturn([]); + $repository->shouldReceive('update')->andReturn($currency); + + $this->call('POST', '/currency/update/' . $currency->id, ['_token' => 'replaceMe']); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + } + + public function testUpdateAndReturn() + { + $user = FactoryMuffin::create('FireflyIII\User'); + $currency = FactoryMuffin::create('FireflyIII\Models\TransactionCurrency'); + $this->be($user); + + $repository = $this->mock('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface'); + $request = $this->mock('FireflyIII\Http\Requests\CurrencyFormRequest'); + $request->shouldReceive('getCurrencyData')->andReturn([]); + $repository->shouldReceive('update')->andReturn($currency); + + $this->call('POST', '/currency/update/' . $currency->id, ['_token' => 'replaceMe', 'return_to_edit' => 1]); + $this->assertResponseStatus(302); + $this->assertSessionHas('success'); + } +} \ No newline at end of file diff --git a/tests/factories/all.php b/tests/factories/all.php index 8ddab42910..d551718cdb 100644 --- a/tests/factories/all.php +++ b/tests/factories/all.php @@ -27,74 +27,156 @@ if (!class_exists('RandomString')) { } } + FactoryMuffin::define( - 'FireflyIII\Models\Account', [ - 'user_id' => 'factory|FireflyIII\User', - 'account_type_id' => 'factory|FireflyIII\Models\AccountType', - 'name' => 'word', - 'active' => 'boolean', - 'encrypted' => 'boolean', - 'virtual_balance' => 0 - ] + 'FireflyIII\Models\Bill', + [ + 'user_id' => 'factory|FireflyIII\User', + 'name' => 'sentence', + 'match' => function () { + $words = []; + for ($i = 0; $i < 3; $i++) { + $words[] = RandomString::generateRandomString(5); + } + + return join(',', $words); + }, + 'amount_min' => 10, + 'amount_max' => 20, + 'date' => 'date', + 'active' => 1, + 'automatch' => 1, + 'repeat_freq' => 'monthly', + 'skip' => 0, + 'name_encrypted' => 1, + 'match_encrypted' => 1, + + ] ); FactoryMuffin::define( - 'FireflyIII\Models\Preference', [ - 'name' => 'word', - 'data' => 'sentence', - 'user_id' => 'factory|FireflyIII\User', - ] + 'FireflyIII\Models\Account', + [ + 'user_id' => 'factory|FireflyIII\User', + 'account_type_id' => 'factory|FireflyIII\Models\AccountType', + 'name' => 'word', + 'active' => 'boolean', + 'encrypted' => 'boolean', + 'virtual_balance' => 0 + ] ); FactoryMuffin::define( - 'FireflyIII\Models\AccountType', [ - 'type' => 'word', - 'editable' => 1, - ] + 'FireflyIII\Models\Budget', + [ + 'user_id' => 'factory|FireflyIII\User', + 'name' => 'sentence', + 'active' => 'boolean', + 'encrypted' => 1, + ] ); FactoryMuffin::define( - 'FireflyIII\Models\TransactionCurrency', [ - 'code' => function () { - return RandomString::generateRandomString(3); - }, - 'symbol' => function () { - return RandomString::generateRandomString(1); - }, - 'name' => 'word' - ] + 'FireflyIII\Models\Category', + [ + 'user_id' => 'factory|FireflyIII\User', + 'name' => 'sentence', + 'encrypted' => 1, + ] ); FactoryMuffin::define( - 'FireflyIII\User', [ - 'email' => 'email', - 'password' => bcrypt('james'), - ] + 'FireflyIII\Models\LimitRepetition', + [ + 'budget_limit_id' => 'factory|FireflyIII\Models\BudgetLimit', + 'startdate' => 'date', + 'enddate' => 'date', + 'amount' => 'integer', + ] ); FactoryMuffin::define( - 'FireflyIII\Models\Transaction', [ - 'transaction_journal_id' => 'factory|FireflyIII\Models\TransactionJournal', - 'amount' => 'integer', - 'account_id' => 'factory|FireflyIII\Models\Account' - ] + 'FireflyIII\Models\BudgetLimit', + [ + 'budget_id' => 'factory|FireflyIII\Models\Budget', + 'startdate' => 'date', + 'amount' => 'integer', + 'repeats' => 'false', + 'repeat_freq' => 'monthly', + + ] +); + + +FactoryMuffin::define( + 'FireflyIII\Models\Preference', + [ + 'name' => 'word', + 'data' => 'sentence', + 'user_id' => 'factory|FireflyIII\User', + ] ); FactoryMuffin::define( - 'FireflyIII\Models\TransactionType', [ - 'type' => 'word', - ] + 'FireflyIII\Models\AccountType', + [ + 'type' => function () { + $types = ['Expense account', 'Revenue account', 'Asset account']; + $count = DB::table('account_types')->count(); + + return $types[$count]; + }, + 'editable' => 1, + ] ); FactoryMuffin::define( - 'FireflyIII\Models\TransactionJournal', [ - 'user_id' => 'factory|FireflyIII\User', - 'transaction_type_id' => 'factory|FireflyIII\Models\TransactionType', - 'transaction_currency_id' => 'factory|FireflyIII\Models\TransactionCurrency', - 'description' => 'sentence', - 'completed' => '1', - 'date' => 'date', - 'encrypted' => '1', - 'order' => '0', - ] + 'FireflyIII\Models\TransactionCurrency', + [ + 'code' => function () { + return RandomString::generateRandomString(3); + }, + 'symbol' => function () { + return RandomString::generateRandomString(1); + }, + 'name' => 'word' + ] +); + +FactoryMuffin::define( + 'FireflyIII\User', + [ + 'email' => 'email', + 'password' => bcrypt('james'), + ] +); + +FactoryMuffin::define( + 'FireflyIII\Models\Transaction', + [ + 'transaction_journal_id' => 'factory|FireflyIII\Models\TransactionJournal', + 'amount' => 'integer', + 'account_id' => 'factory|FireflyIII\Models\Account' + ] +); + +FactoryMuffin::define( + 'FireflyIII\Models\TransactionType', + [ + 'type' => 'word', + ] +); + +FactoryMuffin::define( + 'FireflyIII\Models\TransactionJournal', + [ + 'user_id' => 'factory|FireflyIII\User', + 'transaction_type_id' => 'factory|FireflyIII\Models\TransactionType', + 'transaction_currency_id' => 'factory|FireflyIII\Models\TransactionCurrency', + 'description' => 'sentence', + 'completed' => '1', + 'date' => 'date', + 'encrypted' => '1', + 'order' => '0', + ] ); \ No newline at end of file