diff --git a/app/Http/Controllers/Chart/BudgetReportController.php b/app/Http/Controllers/Chart/BudgetReportController.php
index 2d0ee59b49..439c8414dd 100644
--- a/app/Http/Controllers/Chart/BudgetReportController.php
+++ b/app/Http/Controllers/Chart/BudgetReportController.php
@@ -153,7 +153,7 @@ class BudgetReportController extends Controller
$cache->addProperty($start);
$cache->addProperty($end);
if ($cache->has()) {
- //return response()->json($cache->get()); // @codeCoverageIgnore
+ return response()->json($cache->get()); // @codeCoverageIgnore
}
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
$function = app('navigation')->preferredEndOfPeriod($start, $end);
diff --git a/app/Http/Controllers/Json/AutoCompleteController.php b/app/Http/Controllers/Json/AutoCompleteController.php
index e5f87f3b68..10fbc664e4 100644
--- a/app/Http/Controllers/Json/AutoCompleteController.php
+++ b/app/Http/Controllers/Json/AutoCompleteController.php
@@ -30,8 +30,10 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
+use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
+use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Log;
@@ -54,7 +56,7 @@ class AutoCompleteController extends Controller
public function accounts(Request $request): JsonResponse
{
$accountTypes = explode(',', $request->get('types') ?? '');
- $search = $request->get('query');
+ $search = $request->get('search');
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
@@ -92,15 +94,45 @@ class AutoCompleteController extends Controller
}
/**
+ * Searches in the titles of all transaction journals.
+ * The result is limited to the top 15 unique results.
+ *
+ * @param Request $request
* @return JsonResponse
- * @codeCoverageIgnore
*/
- public function budgets(): JsonResponse
+ public function allJournals(Request $request): JsonResponse
{
+ $search = (string)$request->get('search');
+ /** @var JournalRepositoryInterface $repository */
+ $repository = app(JournalRepositoryInterface::class);
+ $result = $repository->searchJournalDescriptions($search);
+
+ // limit and unique
+ $filtered = $result->unique('description');
+ $limited = $filtered->slice(0, 15);
+ $array = $limited->toArray();
+ foreach ($array as $index => $item) {
+ // give another key for consistency
+ $array[$index]['name'] = $item['description'];
+ }
+
+
+ return response()->json($array);
+
+ }
+
+ /**
+ * @param Request $request
+ * @return JsonResponse
+ */
+ public function budgets(Request $request): JsonResponse
+ {
+ $search = (string)$request->get('search');
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class);
+ $result = $repository->searchBudget($search);
- return response()->json($repository->getActiveBudgets()->toArray());
+ return response()->json($result->toArray());
}
/**
@@ -111,7 +143,7 @@ class AutoCompleteController extends Controller
*/
public function categories(Request $request): JsonResponse
{
- $query = (string)$request->get('query');
+ $query = (string)$request->get('search');
/** @var CategoryRepositoryInterface $repository */
$repository = app(CategoryRepositoryInterface::class);
$result = $repository->searchCategory($query);
@@ -119,6 +151,44 @@ class AutoCompleteController extends Controller
return response()->json($result->toArray());
}
+ /**
+ * @param Request $request
+ * @return JsonResponse
+ */
+ public function currencyNames(Request $request): JsonResponse
+ {
+ $query = (string)$request->get('search');
+ /** @var CurrencyRepositoryInterface $repository */
+ $repository = app(CurrencyRepositoryInterface::class);
+ $result = $repository->searchCurrency($query)->toArray();
+ foreach ($result as $index => $item) {
+ $result[$index]['name'] = sprintf('%s (%s)', $item['name'], $item['code']);
+ }
+
+ return response()->json($result);
+ }
+
+ /**
+ * @param Request $request
+ *
+ * @return JsonResponse
+ * @codeCoverageIgnore
+ */
+ public function transactionTypes(Request $request): JsonResponse
+ {
+ $query = (string)$request->get('search');
+ /** @var TransactionTypeRepositoryInterface $repository */
+ $repository = app(TransactionTypeRepositoryInterface::class);
+ $array = $repository->searchTypes($query)->toArray();
+
+ foreach ($array as $index => $item) {
+ // different key for consistency.
+ $array[$index]['name'] = $item['type'];
+ }
+
+ return response()->json($array);
+ }
+
/**
* @return JsonResponse
* @codeCoverageIgnore
@@ -164,13 +234,18 @@ class AutoCompleteController extends Controller
*/
public function tags(Request $request): JsonResponse
{
- $query = (string)$request->get('query');
+ $search = (string)$request->get('search');
/** @var TagRepositoryInterface $repository */
$repository = app(TagRepositoryInterface::class);
- $result = $repository->searchTags($query);
+ $result = $repository->searchTags($search);
+ $array = $result->toArray();
+ foreach ($array as $index => $item) {
+ // rename field for consistency.
+ $array[$index]['name'] = $item['tag'];
+ }
- return response()->json($result->toArray());
+ return response()->json($array);
}
}
diff --git a/app/Http/Controllers/Recurring/CreateController.php b/app/Http/Controllers/Recurring/CreateController.php
index 4a946fadc3..4606a6d6ac 100644
--- a/app/Http/Controllers/Recurring/CreateController.php
+++ b/app/Http/Controllers/Recurring/CreateController.php
@@ -46,6 +46,7 @@ class CreateController extends Controller
/**
* CreateController constructor.
+ * @codeCoverageIgnore
*/
public function __construct()
{
diff --git a/app/Http/Controllers/Recurring/DeleteController.php b/app/Http/Controllers/Recurring/DeleteController.php
index 8b7b548541..5ad24fce6c 100644
--- a/app/Http/Controllers/Recurring/DeleteController.php
+++ b/app/Http/Controllers/Recurring/DeleteController.php
@@ -39,6 +39,7 @@ class DeleteController extends Controller
/**
* DeleteController constructor.
+ * @codeCoverageIgnore
*/
public function __construct()
{
@@ -79,8 +80,8 @@ class DeleteController extends Controller
* Destroy the recurring transaction.
*
* @param RecurringRepositoryInterface $repository
- * @param Request $request
- * @param Recurrence $recurrence
+ * @param Request $request
+ * @param Recurrence $recurrence
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
diff --git a/app/Http/Controllers/Recurring/EditController.php b/app/Http/Controllers/Recurring/EditController.php
index 02ce761a85..e99b900814 100644
--- a/app/Http/Controllers/Recurring/EditController.php
+++ b/app/Http/Controllers/Recurring/EditController.php
@@ -47,6 +47,7 @@ class EditController extends Controller
/**
* EditController constructor.
+ * @codeCoverageIgnore
*/
public function __construct()
{
@@ -70,7 +71,7 @@ class EditController extends Controller
/**
* Edit a recurring transaction.
*
- * @param Request $request
+ * @param Request $request
* @param Recurrence $recurrence
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
@@ -92,7 +93,7 @@ class EditController extends Controller
$repetition = $recurrence->recurrenceRepetitions()->first();
$currentRepType = $repetition->repetition_type;
if ('' !== $repetition->repetition_moment) {
- $currentRepType .= ',' . $repetition->repetition_moment;
+ $currentRepType .= ',' . $repetition->repetition_moment; // @codeCoverageIgnore
}
// put previous url in session if not redirect from store (not "return_to_edit").
@@ -123,9 +124,12 @@ class EditController extends Controller
$hasOldInput = null !== $request->old('_token');
$preFilled = [
- 'transaction_type' => strtolower($recurrence->transactionType->type),
- 'active' => $hasOldInput ? (bool)$request->old('active') : $recurrence->active,
- 'apply_rules' => $hasOldInput ? (bool)$request->old('apply_rules') : $recurrence->apply_rules,
+ 'transaction_type' => strtolower($recurrence->transactionType->type),
+ 'active' => $hasOldInput ? (bool)$request->old('active') : $recurrence->active,
+ 'apply_rules' => $hasOldInput ? (bool)$request->old('apply_rules') : $recurrence->apply_rules,
+ 'deposit_source_id' => $array['transactions'][0]['source_id'],
+ 'withdrawal_destination_id' => $array['transactions'][0]['destination_id'],
+
];
return view(
@@ -138,7 +142,7 @@ class EditController extends Controller
* Update the recurring transaction.
*
* @param RecurrenceFormRequest $request
- * @param Recurrence $recurrence
+ * @param Recurrence $recurrence
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
* @throws \FireflyIII\Exceptions\FireflyException
diff --git a/app/Http/Controllers/Recurring/IndexController.php b/app/Http/Controllers/Recurring/IndexController.php
index a4f66c5fa1..b5c7af9859 100644
--- a/app/Http/Controllers/Recurring/IndexController.php
+++ b/app/Http/Controllers/Recurring/IndexController.php
@@ -48,6 +48,7 @@ class IndexController extends Controller
/**
* IndexController constructor.
+ * @codeCoverageIgnore
*/
public function __construct()
{
@@ -121,8 +122,8 @@ class IndexController extends Controller
$transformer = app(RecurrenceTransformer::class);
$transformer->setParameters(new ParameterBag);
- $array = $transformer->transform($recurrence);
- $transactions = $this->recurring->getTransactions($recurrence);
+ $array = $transformer->transform($recurrence);
+ $groups = $this->recurring->getTransactions($recurrence);
// transform dates back to Carbon objects:
foreach ($array['recurrence_repetitions'] as $index => $repetition) {
@@ -133,7 +134,7 @@ class IndexController extends Controller
$subTitle = (string)trans('firefly.overview_for_recurrence', ['title' => $recurrence->title]);
- return view('recurring.show', compact('recurrence', 'subTitle', 'array', 'transactions'));
+ return view('recurring.show', compact('recurrence', 'subTitle', 'array', 'groups'));
}
}
diff --git a/app/Http/Controllers/Report/ExpenseController.php b/app/Http/Controllers/Report/ExpenseController.php
index 4a09328033..ef8e3d4d2a 100644
--- a/app/Http/Controllers/Report/ExpenseController.php
+++ b/app/Http/Controllers/Report/ExpenseController.php
@@ -47,6 +47,7 @@ class ExpenseController extends Controller
/**
* Constructor for ExpenseController
+ * @codeCoverageIgnore
*/
public function __construct()
{
@@ -252,11 +253,11 @@ class ExpenseController extends Controller
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
- $cache->addProperty('expense-budget');
+ $cache->addProperty('top-expense');
$cache->addProperty($accounts->pluck('id')->toArray());
$cache->addProperty($expense->pluck('id')->toArray());
if ($cache->has()) {
- return $cache->get(); // @codeCoverageIgnore
+ //return $cache->get(); // @codeCoverageIgnore
}
$combined = $this->combineAccounts($expense);
$all = new Collection;
@@ -268,11 +269,11 @@ class ExpenseController extends Controller
$collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($accounts);
- $collector->setAccounts($all);
- $set = $collector->getExtractedJournals();
+ $collector->setAccounts($all)->withAccountInformation();
+ $sorted = $collector->getExtractedJournals();
- usort($set, function ($a, $b) {
- return $a['amount'] <=> $b['amount'];
+ usort($sorted, function ($a, $b) {
+ return $a['amount'] <=> $b['amount']; // @codeCoverageIgnore
});
try {
@@ -304,11 +305,11 @@ class ExpenseController extends Controller
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
- $cache->addProperty('expense-budget');
+ $cache->addProperty('top-income');
$cache->addProperty($accounts->pluck('id')->toArray());
$cache->addProperty($expense->pluck('id')->toArray());
if ($cache->has()) {
- return $cache->get(); // @codeCoverageIgnore
+ //return $cache->get(); // @codeCoverageIgnore
}
$combined = $this->combineAccounts($expense);
$all = new Collection;
@@ -321,11 +322,15 @@ class ExpenseController extends Controller
$collector = app(GroupCollectorInterface::class);
$total = $accounts->merge($all);
- $collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAccounts($total);
- $journals = $collector->getExtractedJournals();
+ $collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAccounts($total)->withAccountInformation();
+ $sorted = $collector->getExtractedJournals();
- usort($journals, function ($a, $b) {
- return $a['amount'] <=> $b['amount'];
+ foreach (array_keys($sorted) as $key) {
+ $sorted[$key]['amount'] = bcmul($sorted[$key]['amount'], '-1');
+ }
+
+ usort($sorted, function ($a, $b) {
+ return $a['amount'] <=> $b['amount']; // @codeCoverageIgnore
});
try {
diff --git a/app/Http/Controllers/Report/OperationsController.php b/app/Http/Controllers/Report/OperationsController.php
index 8b8eca74c1..c5bffbba86 100644
--- a/app/Http/Controllers/Report/OperationsController.php
+++ b/app/Http/Controllers/Report/OperationsController.php
@@ -41,6 +41,7 @@ class OperationsController extends Controller
/**
* OperationsController constructor.
+ * @codeCoverageIgnore
*/
public function __construct()
{
diff --git a/app/Http/Controllers/Rule/CreateController.php b/app/Http/Controllers/Rule/CreateController.php
index 155ed5205f..b8030dfda4 100644
--- a/app/Http/Controllers/Rule/CreateController.php
+++ b/app/Http/Controllers/Rule/CreateController.php
@@ -45,6 +45,7 @@ class CreateController extends Controller
/**
* RuleController constructor.
+ * @codeCoverageIgnore
*/
public function __construct()
{
diff --git a/app/Http/Controllers/Rule/DeleteController.php b/app/Http/Controllers/Rule/DeleteController.php
index a568f2dd91..61f605ef2f 100644
--- a/app/Http/Controllers/Rule/DeleteController.php
+++ b/app/Http/Controllers/Rule/DeleteController.php
@@ -39,6 +39,7 @@ class DeleteController extends Controller
/**
* RuleController constructor.
+ * @codeCoverageIgnore
*/
public function __construct()
{
diff --git a/app/Http/Controllers/Rule/EditController.php b/app/Http/Controllers/Rule/EditController.php
index b474878cf6..d136c175ee 100644
--- a/app/Http/Controllers/Rule/EditController.php
+++ b/app/Http/Controllers/Rule/EditController.php
@@ -45,6 +45,7 @@ class EditController extends Controller
/**
* RuleController constructor.
+ * @codeCoverageIgnore
*/
public function __construct()
{
diff --git a/app/Http/Controllers/Rule/IndexController.php b/app/Http/Controllers/Rule/IndexController.php
index 53831990c1..4593b67de6 100644
--- a/app/Http/Controllers/Rule/IndexController.php
+++ b/app/Http/Controllers/Rule/IndexController.php
@@ -45,6 +45,7 @@ class IndexController extends Controller
/**
* RuleController constructor.
+ * @codeCoverageIgnore
*/
public function __construct()
{
diff --git a/app/Http/Controllers/Rule/SelectController.php b/app/Http/Controllers/Rule/SelectController.php
index c8edd0cabd..02a26ca0e8 100644
--- a/app/Http/Controllers/Rule/SelectController.php
+++ b/app/Http/Controllers/Rule/SelectController.php
@@ -76,7 +76,7 @@ class SelectController extends Controller
* Execute the given rule on a set of existing transactions.
*
* @param SelectTransactionsRequest $request
- * @param Rule $rule
+ * @param Rule $rule
*
* @return RedirectResponse
*/
@@ -181,11 +181,12 @@ class SelectController extends Controller
// Return json response
$view = 'ERROR, see logs.';
try {
- $view = view('list.journals-tiny', ['transactions' => $matchingTransactions])->render();
+ $view = view('list.journals-array-tiny', ['journals' => $matchingTransactions])->render();
// @codeCoverageIgnoreStart
} catch (Throwable $exception) {
Log::error(sprintf('Could not render view in testTriggers(): %s', $exception->getMessage()));
Log::error($exception->getTraceAsString());
+ $view = sprintf('Could not render list.journals-tiny: %s', $exception->getMessage());
}
// @codeCoverageIgnoreEnd
@@ -236,17 +237,17 @@ class SelectController extends Controller
// Warn the user if only a subset of transactions is returned
$warning = '';
- if ($matchingTransactions->count() === $limit) {
+ if (count($matchingTransactions) === $limit) {
$warning = (string)trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]); // @codeCoverageIgnore
}
- if (0 === $matchingTransactions->count()) {
+ if (0 === count($matchingTransactions)) {
$warning = (string)trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]); // @codeCoverageIgnore
}
// Return json response
$view = 'ERROR, see logs.';
try {
- $view = view('list.journals-tiny', ['transactions' => $matchingTransactions])->render();
+ $view = view('list.journals-array-tiny', ['journals' => $matchingTransactions])->render();
// @codeCoverageIgnoreStart
} catch (Throwable $exception) {
Log::error(sprintf('Could not render view in testTriggersByRule(): %s', $exception->getMessage()));
diff --git a/app/Http/Controllers/Transaction/IndexController.php b/app/Http/Controllers/Transaction/IndexController.php
index 479186ca23..fc03aaf7af 100644
--- a/app/Http/Controllers/Transaction/IndexController.php
+++ b/app/Http/Controllers/Transaction/IndexController.php
@@ -36,7 +36,31 @@ use Illuminate\Http\Request;
*/
class IndexController extends Controller
{
- use PeriodOverview;
+ use PeriodOverview;
+
+ /** @var JournalRepositoryInterface */
+ private $repository;
+
+ /**
+ * IndexController constructor.
+ * @codeCoverageIgnore
+ */
+ public function __construct()
+ {
+ parent::__construct();
+
+ // translations:
+ $this->middleware(
+ function ($request, $next) {
+ app('view')->share('mainTitleIcon', 'fa-credit-card');
+ app('view')->share('title', (string)trans('firefly.accounts'));
+
+ $this->repository = app(JournalRepositoryInterface::class);
+
+ return $next($request);
+ }
+ );
+ }
/**
* Index for a range of transactions.
@@ -54,6 +78,7 @@ class IndexController extends Controller
$types = config('firefly.transactionTypesByType.' . $objectType);
$page = (int)$request->get('page');
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
+ $pageSize =3;
if (null === $start) {
$start = session('start');
$end = session('end');
@@ -62,16 +87,16 @@ class IndexController extends Controller
$end = session('end');
}
- if ($end < $start) {
- [$start, $end] = [$end, $start];
- }
-
- $path = route('transactions.index', [$objectType, $start->format('Y-m-d'), $end->format('Y-m-d')]);
-
+ [$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
+ $path = route('transactions.index', [$objectType, $start->format('Y-m-d'), $end->format('Y-m-d')]);
$startStr = $start->formatLocalized($this->monthAndDayFormat);
$endStr = $end->formatLocalized($this->monthAndDayFormat);
$subTitle = (string)trans(sprintf('firefly.title_%s_between', $objectType), ['start' => $startStr, 'end' => $endStr]);
- $periods = $this->getTransactionPeriodOverview($objectType, $end);
+
+ $firstJournal = $this->repository->firstNull();
+ $startPeriod = null === $firstJournal ? new Carbon : $firstJournal->date;
+ $endPeriod = clone $end;
+ $periods = $this->getTransactionPeriodOverview($objectType, $startPeriod, $endPeriod);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
diff --git a/app/Http/Middleware/StartFireflySession.php b/app/Http/Middleware/StartFireflySession.php
index 4b6ece87cc..513f49b74c 100644
--- a/app/Http/Middleware/StartFireflySession.php
+++ b/app/Http/Middleware/StartFireflySession.php
@@ -53,10 +53,10 @@ class StartFireflySession extends StartSession
&& 'GET' === $request->method()
&& !$request->ajax()) {
$session->setPreviousUrl($uri);
- Log::debug(sprintf('Will set previous URL to %s', $uri));
+ //Log::debug(sprintf('Will set previous URL to %s', $uri));
return;
}
- Log::debug(sprintf('Will NOT set previous URL to %s', $uri));
+ //Log::debug(sprintf('Will NOT set previous URL to %s', $uri));
}
}
diff --git a/app/Http/Requests/RecurrenceFormRequest.php b/app/Http/Requests/RecurrenceFormRequest.php
index 24cd086e7e..5863128db3 100644
--- a/app/Http/Requests/RecurrenceFormRequest.php
+++ b/app/Http/Requests/RecurrenceFormRequest.php
@@ -29,6 +29,9 @@ use FireflyIII\Models\Recurrence;
use FireflyIII\Models\TransactionType;
use FireflyIII\Rules\ValidRecurrenceRepetitionType;
use FireflyIII\Rules\ValidRecurrenceRepetitionValue;
+use FireflyIII\Validation\AccountValidator;
+use Illuminate\Validation\Validator;
+use Log;
/**
* Class RecurrenceFormRequest
@@ -136,6 +139,86 @@ class RecurrenceFormRequest extends Request
return $return;
}
+
+ /**
+ * Configure the validator instance with special rules for after the basic validation rules.
+ *
+ * @param Validator $validator
+ *
+ * @return void
+ */
+ public function withValidator(Validator $validator): void
+ {
+ $validator->after(
+ function (Validator $validator) {
+ // validate all account info
+ $this->validateAccountInformation($validator);
+ }
+ );
+ }
+
+ /**
+ * Validates the given account information. Switches on given transaction type.
+ *
+ * @param Validator $validator
+ * @throws FireflyException
+ */
+ public function validateAccountInformation(Validator $validator): void
+ {
+ Log::debug('Now in validateAccountInformation()');
+ /** @var AccountValidator $accountValidator */
+ $accountValidator = app(AccountValidator::class);
+ $data = $validator->getData();
+ $transactionType = $data['transaction_type'] ?? 'invalid';
+
+ $accountValidator->setTransactionType($transactionType);
+
+ // default values:
+ $sourceId = null;
+ $destinationId = null;
+
+ switch ($this->string('transaction_type')) {
+ default:
+ throw new FireflyException(sprintf('Cannot handle transaction type "%s"', $this->string('transaction_type'))); // @codeCoverageIgnore
+ case 'withdrawal':
+ $sourceId = (int)$data['source_id'];
+ $destinationId = (int)$data['withdrawal_destination_id'];
+ break;
+ case 'deposit':
+ $sourceId = (int)$data['deposit_source_id'];
+ $destinationId = (int)$data['destination_id'];
+ break;
+ case 'transfer':
+ $sourceId = (int)$data['source_id'];
+ $destinationId = (int)$data['destination_id'];
+ break;
+ }
+
+
+ // validate source account.
+ $validSource = $accountValidator->validateSource($sourceId, null);
+
+ // do something with result:
+ if (false === $validSource) {
+ $message = (string)trans('validation.generic_invalid_source');
+ $validator->errors()->add('source_id', $message);
+ $validator->errors()->add('deposit_source_id', $message);
+
+ return;
+ }
+
+ // validate destination account
+ $validDestination = $accountValidator->validateDestination($destinationId, null);
+ // do something with result:
+ if (false === $validDestination) {
+ $message = (string)trans('validation.generic_invalid_destination');
+ $validator->errors()->add('destination_id', $message);
+ $validator->errors()->add('withdrawal_destination_id', $message);
+
+ return;
+ }
+ }
+
/**
* The rules for this request.
*
diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php
index a6352a596e..03e51e17b5 100644
--- a/app/Repositories/Budget/BudgetRepository.php
+++ b/app/Repositories/Budget/BudgetRepository.php
@@ -647,9 +647,13 @@ class BudgetRepository implements BudgetRepositoryInterface
*/
public function searchBudget(string $query): Collection
{
- $query = sprintf('%%%s%%', $query);
- return $this->user->budgets()->where('name', 'LIKE', $query)->get();
+ $search = $this->user->budgets();
+ if ('' !== $query) {
+ $search->where('name', 'LIKE', sprintf('%%%s%%', $query));
+ }
+
+ return $search->get();
}
/**
diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php
index 89c91acfb0..771482a788 100644
--- a/app/Repositories/Category/CategoryRepository.php
+++ b/app/Repositories/Category/CategoryRepository.php
@@ -111,22 +111,6 @@ class CategoryRepository implements CategoryRepositoryInterface
return $collector->getExtractedJournals();
}
- /**
- * @param array $journals
- * @return string
- */
- private function sumJournals(array $journals): string
- {
- $sum = '0';
- /** @var array $journal */
- foreach ($journals as $journal) {
- $amount = (string)$journal['amount'];
- $sum = bcadd($sum, $amount);
- }
-
- return $sum;
- }
-
/**
* A very cryptic method name that means:
*
@@ -156,7 +140,7 @@ class CategoryRepository implements CategoryRepositoryInterface
$currencyId = (int)$journal['currency_id'];
if (!isset($return[$currencyId])) {
$return[$currencyId] = [
- 'earned' => '0',
+ 'earned' => '0',
'currency_id' => $currencyId,
'currency_symbol' => $journal['currency_symbol'],
'currency_code' => $journal['currency_code'],
@@ -264,8 +248,6 @@ class CategoryRepository implements CategoryRepositoryInterface
return $result;
}
- /** @noinspection MoreThanThreeArgumentsInspection */
-
/**
* Find a category or return NULL
*
@@ -278,6 +260,8 @@ class CategoryRepository implements CategoryRepositoryInterface
return $this->user->categories()->find($categoryId);
}
+ /** @noinspection MoreThanThreeArgumentsInspection */
+
/**
* Find a category.
*
@@ -297,8 +281,6 @@ class CategoryRepository implements CategoryRepositoryInterface
return null;
}
- /** @noinspection MoreThanThreeArgumentsInspection */
-
/**
* @param array $data
*
@@ -313,6 +295,8 @@ class CategoryRepository implements CategoryRepositoryInterface
return $factory->findOrCreate(null, $data['name']);
}
+ /** @noinspection MoreThanThreeArgumentsInspection */
+
/**
* @param Category $category
*
@@ -341,47 +325,6 @@ class CategoryRepository implements CategoryRepositoryInterface
return $firstJournalDate;
}
- /**
- * @param Category $category
- *
- * @return Carbon|null
- */
- private function getFirstJournalDate(Category $category): ?Carbon
- {
- $query = $category->transactionJournals()->orderBy('date', 'ASC');
- $result = $query->first(['transaction_journals.*']);
-
- if (null !== $result) {
- return $result->date;
- }
-
- return null;
- }
-
- /** @noinspection MoreThanThreeArgumentsInspection */
-
- /**
- * @param Category $category
- *
- * @return Carbon|null
- */
- private function getFirstTransactionDate(Category $category): ?Carbon
- {
- // check transactions:
- $query = $category->transactions()
- ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
- ->orderBy('transaction_journals.date', 'ASC');
-
- $lastTransaction = $query->first(['transaction_journals.*']);
- if (null !== $lastTransaction) {
- return new Carbon($lastTransaction->date);
- }
-
- return null;
- }
-
- /** @noinspection MoreThanThreeArgumentsInspection */
-
/**
* Get all categories with ID's.
*
@@ -394,8 +337,6 @@ class CategoryRepository implements CategoryRepositoryInterface
return $this->user->categories()->whereIn('id', $categoryIds)->get();
}
- /** @noinspection MoreThanThreeArgumentsInspection */
-
/**
* @param Category $category
* @param Collection $accounts
@@ -426,55 +367,7 @@ class CategoryRepository implements CategoryRepositoryInterface
return $lastJournalDate;
}
- /**
- * @param Category $category
- * @param Collection $accounts
- *
- * @return Carbon|null
- */
- private function getLastJournalDate(Category $category, Collection $accounts): ?Carbon
- {
- $query = $category->transactionJournals()->orderBy('date', 'DESC');
-
- if ($accounts->count() > 0) {
- $query->leftJoin('transactions as t', 't.transaction_journal_id', '=', 'transaction_journals.id');
- $query->whereIn('t.account_id', $accounts->pluck('id')->toArray());
- }
-
- $result = $query->first(['transaction_journals.*']);
-
- if (null !== $result) {
- return $result->date;
- }
-
- return null;
- }
-
- /**
- * @param Category $category
- * @param Collection $accounts
- *
- * @return Carbon|null
- * @throws \Exception
- */
- private function getLastTransactionDate(Category $category, Collection $accounts): ?Carbon
- {
- // check transactions:
- $query = $category->transactions()
- ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
- ->orderBy('transaction_journals.date', 'DESC');
- if ($accounts->count() > 0) {
- // filter journals:
- $query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
- }
-
- $lastTransaction = $query->first(['transaction_journals.*']);
- if (null !== $lastTransaction) {
- return new Carbon($lastTransaction->date);
- }
-
- return null;
- }
+ /** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $categories
@@ -518,6 +411,8 @@ class CategoryRepository implements CategoryRepositoryInterface
return $data;
}
+ /** @noinspection MoreThanThreeArgumentsInspection */
+
/**
* @param Collection $accounts
* @param Carbon $start
@@ -555,6 +450,8 @@ class CategoryRepository implements CategoryRepositoryInterface
return $result;
}
+ /** @noinspection MoreThanThreeArgumentsInspection */
+
/**
* @param Collection $categories
* @param Collection $accounts
@@ -644,9 +541,12 @@ class CategoryRepository implements CategoryRepositoryInterface
*/
public function searchCategory(string $query): Collection
{
- $query = sprintf('%%%s%%', $query);
+ $search = $this->user->categories();
+ if ('' !== $query) {
+ $search->where('name', 'LIKE', sprintf('%%%s%%', $query));
+ }
- return $this->user->categories()->where('name', 'LIKE', $query)->get();
+ return $search->get();
}
/**
@@ -831,4 +731,107 @@ class CategoryRepository implements CategoryRepositoryInterface
return $service->update($category, $data);
}
+
+ /**
+ * @param array $journals
+ * @return string
+ */
+ private function sumJournals(array $journals): string
+ {
+ $sum = '0';
+ /** @var array $journal */
+ foreach ($journals as $journal) {
+ $amount = (string)$journal['amount'];
+ $sum = bcadd($sum, $amount);
+ }
+
+ return $sum;
+ }
+
+ /**
+ * @param Category $category
+ *
+ * @return Carbon|null
+ */
+ private function getFirstJournalDate(Category $category): ?Carbon
+ {
+ $query = $category->transactionJournals()->orderBy('date', 'ASC');
+ $result = $query->first(['transaction_journals.*']);
+
+ if (null !== $result) {
+ return $result->date;
+ }
+
+ return null;
+ }
+
+ /**
+ * @param Category $category
+ *
+ * @return Carbon|null
+ */
+ private function getFirstTransactionDate(Category $category): ?Carbon
+ {
+ // check transactions:
+ $query = $category->transactions()
+ ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
+ ->orderBy('transaction_journals.date', 'ASC');
+
+ $lastTransaction = $query->first(['transaction_journals.*']);
+ if (null !== $lastTransaction) {
+ return new Carbon($lastTransaction->date);
+ }
+
+ return null;
+ }
+
+ /**
+ * @param Category $category
+ * @param Collection $accounts
+ *
+ * @return Carbon|null
+ */
+ private function getLastJournalDate(Category $category, Collection $accounts): ?Carbon
+ {
+ $query = $category->transactionJournals()->orderBy('date', 'DESC');
+
+ if ($accounts->count() > 0) {
+ $query->leftJoin('transactions as t', 't.transaction_journal_id', '=', 'transaction_journals.id');
+ $query->whereIn('t.account_id', $accounts->pluck('id')->toArray());
+ }
+
+ $result = $query->first(['transaction_journals.*']);
+
+ if (null !== $result) {
+ return $result->date;
+ }
+
+ return null;
+ }
+
+ /**
+ * @param Category $category
+ * @param Collection $accounts
+ *
+ * @return Carbon|null
+ * @throws \Exception
+ */
+ private function getLastTransactionDate(Category $category, Collection $accounts): ?Carbon
+ {
+ // check transactions:
+ $query = $category->transactions()
+ ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
+ ->orderBy('transaction_journals.date', 'DESC');
+ if ($accounts->count() > 0) {
+ // filter journals:
+ $query->whereIn('transactions.account_id', $accounts->pluck('id')->toArray());
+ }
+
+ $lastTransaction = $query->first(['transaction_journals.*']);
+ if (null !== $lastTransaction) {
+ return new Carbon($lastTransaction->date);
+ }
+
+ return null;
+ }
}
diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php
index f17d874fd2..4256266dd6 100644
--- a/app/Repositories/Currency/CurrencyRepository.php
+++ b/app/Repositories/Currency/CurrencyRepository.php
@@ -258,7 +258,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
/**
* Find by object, ID or code. Returns user default or system default.
*
- * @param int|null $currencyId
+ * @param int|null $currencyId
* @param string|null $currencyCode
*
* @return TransactionCurrency|null
@@ -288,7 +288,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
/**
* Find by object, ID or code. Returns NULL if nothing found.
*
- * @param int|null $currencyId
+ * @param int|null $currencyId
* @param string|null $currencyCode
*
* @return TransactionCurrency|null
@@ -369,7 +369,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
*
* @param TransactionCurrency $fromCurrency
* @param TransactionCurrency $toCurrency
- * @param Carbon $date
+ * @param Carbon $date
*
* @return CurrencyExchangeRate|null
*/
@@ -438,7 +438,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
/**
* @param TransactionCurrency $currency
- * @param array $data
+ * @param array $data
*
* @return TransactionCurrency
*/
@@ -449,4 +449,18 @@ class CurrencyRepository implements CurrencyRepositoryInterface
return $service->update($currency, $data);
}
+
+ /**
+ * @param string $search
+ * @return Collection
+ */
+ public function searchCurrency(string $search): Collection
+ {
+ $query = TransactionCurrency::where('enabled', 1);
+ if ('' !== $search) {
+ $query->where('name', 'LIKE', sprintf('%%%s%%', $search));
+ }
+
+ return $query->get();
+ }
}
diff --git a/app/Repositories/Currency/CurrencyRepositoryInterface.php b/app/Repositories/Currency/CurrencyRepositoryInterface.php
index 5122588827..9dc3105287 100644
--- a/app/Repositories/Currency/CurrencyRepositoryInterface.php
+++ b/app/Repositories/Currency/CurrencyRepositoryInterface.php
@@ -34,6 +34,12 @@ use Illuminate\Support\Collection;
*/
interface CurrencyRepositoryInterface
{
+ /**
+ * @param string $search
+ * @return Collection
+ */
+ public function searchCurrency(string $search): Collection;
+
/**
* @param TransactionCurrency $currency
*
diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php
index 5340c32f0e..6b1d3a30be 100644
--- a/app/Repositories/Journal/JournalRepository.php
+++ b/app/Repositories/Journal/JournalRepository.php
@@ -54,6 +54,8 @@ use stdClass;
*/
class JournalRepository implements JournalRepositoryInterface
{
+
+
/** @var User */
private $user;
@@ -67,7 +69,25 @@ class JournalRepository implements JournalRepositoryInterface
}
}
+ /**
+ * Search in journal descriptions.
+ *
+ * @param string $search
+ * @return Collection
+ */
+ public function searchJournalDescriptions(string $search): Collection
+ {
+ $query = $this->user->transactionJournals()
+ ->orderBy('date', 'DESC');
+ if ('' !== $query) {
+ $query->where('description', 'LIKE', sprintf('%%%s%%', $search));
+ }
+
+ return $query->get();
+ }
+
/** @noinspection MoreThanThreeArgumentsInspection */
+
/**
* @param TransactionJournal $journal
* @param TransactionType $type
diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php
index 5a3b6a5cf0..0fe12b0ce1 100644
--- a/app/Repositories/Journal/JournalRepositoryInterface.php
+++ b/app/Repositories/Journal/JournalRepositoryInterface.php
@@ -41,6 +41,14 @@ use Illuminate\Support\MessageBag;
interface JournalRepositoryInterface
{
+ /**
+ * Search in journal descriptions.
+ *
+ * @param string $search
+ * @return Collection
+ */
+ public function searchJournalDescriptions(string $search): Collection;
+
/**
* Get all transaction journals with a specific type, regardless of user.
*
diff --git a/app/Repositories/Recurring/RecurringRepository.php b/app/Repositories/Recurring/RecurringRepository.php
index e6074daad6..4248272e2e 100644
--- a/app/Repositories/Recurring/RecurringRepository.php
+++ b/app/Repositories/Recurring/RecurringRepository.php
@@ -303,13 +303,11 @@ class RecurringRepository implements RecurringRepositoryInterface
}
/**
- * TODO check usage and verify it still works.
- *
* @param Recurrence $recurrence
*
* @return Collection
*/
- public function getTransactions(Recurrence $recurrence): array
+ public function getTransactions(Recurrence $recurrence): Collection
{
$journalMeta = TransactionJournalMeta
::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id')
@@ -319,9 +317,17 @@ class RecurringRepository implements RecurringRepositoryInterface
->where('data', json_encode((string)$recurrence->id))
->get()->pluck('transaction_journal_id')->toArray();
$search = [];
+
+
+
foreach ($journalMeta as $journalId) {
$search[] = (int)$journalId;
}
+ if (0 === count($search)) {
+
+ return [];
+ }
+
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
@@ -330,7 +336,7 @@ class RecurringRepository implements RecurringRepositoryInterface
// filter on specific journals.
$collector->setJournalIds($search);
- return $collector->getExtractedJournals();
+ return $collector->getGroups();
}
/**
diff --git a/app/Repositories/Recurring/RecurringRepositoryInterface.php b/app/Repositories/Recurring/RecurringRepositoryInterface.php
index 15e89f53d3..ee609f685b 100644
--- a/app/Repositories/Recurring/RecurringRepositoryInterface.php
+++ b/app/Repositories/Recurring/RecurringRepositoryInterface.php
@@ -141,9 +141,9 @@ interface RecurringRepositoryInterface
/**
* @param Recurrence $recurrence
*
- * @return array
+ * @return Collection
*/
- public function getTransactions(Recurrence $recurrence): array;
+ public function getTransactions(Recurrence $recurrence): Collection;
/**
* Calculate the next X iterations starting on the date given in $date.
diff --git a/app/Repositories/TransactionType/TransactionTypeRepository.php b/app/Repositories/TransactionType/TransactionTypeRepository.php
index bb7cab684a..0e139c6787 100644
--- a/app/Repositories/TransactionType/TransactionTypeRepository.php
+++ b/app/Repositories/TransactionType/TransactionTypeRepository.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\TransactionType;
use FireflyIII\Models\TransactionType;
+use Illuminate\Support\Collection;
use Log;
/**
@@ -46,7 +47,7 @@ class TransactionTypeRepository implements TransactionTypeRepositoryInterface
/**
* @param TransactionType|null $type
- * @param string|null $typeString
+ * @param string|null $typeString
*
* @return TransactionType
*/
@@ -67,4 +68,17 @@ class TransactionTypeRepository implements TransactionTypeRepositoryInterface
return $search;
}
+
+ /**
+ * @param string $query
+ * @return Collection
+ */
+ public function searchTypes(string $query): Collection
+ {
+ if ('' === $query) {
+ return TransactionType::get();
+ }
+
+ return TransactionType::where('type', 'LIKE', sprintf('%%%s%%', $query))->get();
+ }
}
\ No newline at end of file
diff --git a/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php b/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php
index d6e4f2679f..0300889cf5 100644
--- a/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php
+++ b/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php
@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\TransactionType;
use FireflyIII\Models\TransactionType;
+use Illuminate\Support\Collection;
/**
* Interface TransactionTypeRepositoryInterface
@@ -44,4 +45,10 @@ interface TransactionTypeRepositoryInterface
* @return TransactionType|null
*/
public function findByType(string $type): ?TransactionType;
+
+ /**
+ * @param string $query
+ * @return Collection
+ */
+ public function searchTypes(string $query): Collection;
}
\ No newline at end of file
diff --git a/app/Support/Binder/AccountList.php b/app/Support/Binder/AccountList.php
index 500d6e1aed..2ef02c9de8 100644
--- a/app/Support/Binder/AccountList.php
+++ b/app/Support/Binder/AccountList.php
@@ -36,7 +36,7 @@ class AccountList implements BinderInterface
/**
* @param string $value
- * @param Route $route
+ * @param Route $route
*
* @return Collection
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
@@ -44,25 +44,29 @@ class AccountList implements BinderInterface
*/
public static function routeBinder(string $value, Route $route): Collection
{
+ Log::debug(sprintf('Now in AccountList::routeBinder("%s")', $value));
if (auth()->check()) {
+ Log::debug('User is logged in.');
$collection = new Collection;
if ('allAssetAccounts' === $value) {
- /** @var \Illuminate\Support\Collection $collection */
+ /** @var Collection $collection */
$collection = auth()->user()->accounts()
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.type', AccountType::ASSET)
->orderBy('accounts.name', 'ASC')
->get(['accounts.*']);
+ Log::debug(sprintf('Collection length is %d', $collection->count()));
}
if ('allAssetAccounts' !== $value) {
$incoming = array_map('\intval', explode(',', $value));
$list = array_merge(array_unique($incoming), [0]);
- /** @var \Illuminate\Support\Collection $collection */
+ /** @var Collection $collection */
$collection = auth()->user()->accounts()
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->whereIn('accounts.id', $list)
->orderBy('accounts.name', 'ASC')
->get(['accounts.*']);
+ Log::debug(sprintf('Collection length is %d', $collection->count()));
}
if ($collection->count() > 0) {
diff --git a/app/Support/Binder/BudgetList.php b/app/Support/Binder/BudgetList.php
index 731cf20b24..629b282879 100644
--- a/app/Support/Binder/BudgetList.php
+++ b/app/Support/Binder/BudgetList.php
@@ -25,6 +25,7 @@ namespace FireflyIII\Support\Binder;
use FireflyIII\Models\Budget;
use Illuminate\Routing\Route;
use Illuminate\Support\Collection;
+use Log;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
@@ -34,7 +35,7 @@ class BudgetList implements BinderInterface
{
/**
* @param string $value
- * @param Route $route
+ * @param Route $route
*
* @return Collection
* @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
@@ -42,27 +43,36 @@ class BudgetList implements BinderInterface
*/
public static function routeBinder(string $value, Route $route): Collection
{
+ Log::debug(sprintf('Now in BudgetList::routeBinder("%s")', $value));
if (auth()->check()) {
$list = array_unique(array_map('\intval', explode(',', $value)));
+ Log::debug('List is now', $list);
if (0 === count($list)) {
+ Log::warning('List count is zero, return 404.');
throw new NotFoundHttpException; // @codeCoverageIgnore
}
- /** @var \Illuminate\Support\Collection $collection */
+ /** @var Collection $collection */
$collection = auth()->user()->budgets()
->where('active', 1)
->whereIn('id', $list)
->get();
+ Log::debug(sprintf('Found %d active budgets', $collection->count()), $list);
// add empty budget if applicable.
if (in_array(0, $list, true)) {
+ Log::debug('Add empty budget because $list contains 0.');
$collection->push(new Budget);
}
if ($collection->count() > 0) {
+ Log::debug(sprintf('List length is > 0 (%d), so return it.', $collection->count()));
+
return $collection;
}
+ Log::debug('List length is zero, fall back to 404.');
}
+ Log::debug('Final fallback to 404.');
throw new NotFoundHttpException;
}
}
diff --git a/app/Support/ExpandedForm.php b/app/Support/ExpandedForm.php
index 6bd00d27a2..e04eeedd8d 100644
--- a/app/Support/ExpandedForm.php
+++ b/app/Support/ExpandedForm.php
@@ -102,10 +102,7 @@ class ExpandedForm
{
// make repositories
/** @var AccountRepositoryInterface $repository */
- $repository = app(AccountRepositoryInterface::class);
- /** @var CurrencyRepositoryInterface $currencyRepos */
- $currencyRepos = app(CurrencyRepositoryInterface::class);
-
+ $repository = app(AccountRepositoryInterface::class);
$accountList = $repository->getActiveAccountsByType(
[AccountType::ASSET, AccountType::DEFAULT, AccountType::MORTGAGE, AccountType::DEBT, AccountType::CREDITCARD, AccountType::LOAN,]
);
@@ -113,12 +110,15 @@ class ExpandedForm
$defaultCurrency = app('amount')->getDefaultCurrency();
$grouped = [];
// group accounts:
+
/** @var Account $account */
foreach ($accountList as $account) {
- $balance = app('steam')->balance($account, new Carbon);
- $currencyId = (int)$repository->getMetaValue($account, 'currency_id');
- $currency = $currencyRepos->findNull($currencyId);
- $role = $repository->getMetaValue($account, 'account_role');
+ $balance = app('steam')->balance($account, new Carbon);
+
+ $currency = $repository->getAccountCurrency($account) ?? $defaultCurrency;
+
+ $role = $repository->getMetaValue($account, 'account_role');
+
if ('' === $role && !in_array($account->accountType->type, $liabilityTypes, true)) {
$role = 'no_account_type'; // @codeCoverageIgnore
}
@@ -126,15 +126,11 @@ class ExpandedForm
if (in_array($account->accountType->type, $liabilityTypes, true)) {
$role = 'l_' . $account->accountType->type; // @codeCoverageIgnore
}
-
- if (null === $currency) {
- $currency = $defaultCurrency;
- }
-
$key = (string)trans('firefly.opt_group_' . $role);
$grouped[$key][$account->id] = $account->name . ' (' . app('amount')->formatAnything($currency, $balance, false) . ')';
}
+
return $this->select($name, $grouped, $value, $options);
}
@@ -152,8 +148,6 @@ class ExpandedForm
// make repositories
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
- /** @var CurrencyRepositoryInterface $currencyRepos */
- $currencyRepos = app(CurrencyRepositoryInterface::class);
$accountList = $repository->getActiveAccountsByType(
[
@@ -176,10 +170,9 @@ class ExpandedForm
// group accounts:
/** @var Account $account */
foreach ($accountList as $account) {
- $balance = app('steam')->balance($account, new Carbon);
- $currencyId = (int)$repository->getMetaValue($account, 'currency_id');
- $currency = $currencyRepos->findNull($currencyId);
- $role = (string)$repository->getMetaValue($account, 'account_role');
+ $balance = app('steam')->balance($account, new Carbon);
+ $currency = $repository->getAccountCurrency($account) ?? $defaultCurrency;
+ $role = (string)$repository->getMetaValue($account, 'account_role');
if ('' === $role && !in_array($account->accountType->type, $liabilityTypes, true)) {
$role = 'no_account_type'; // @codeCoverageIgnore
}
@@ -217,8 +210,6 @@ class ExpandedForm
// make repositories
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
- /** @var CurrencyRepositoryInterface $currencyRepos */
- $currencyRepos = app(CurrencyRepositoryInterface::class);
$accountList = $repository->getActiveAccountsByType(
[
@@ -241,10 +232,9 @@ class ExpandedForm
// group accounts:
/** @var Account $account */
foreach ($accountList as $account) {
- $balance = app('steam')->balance($account, new Carbon);
- $currencyId = (int)$repository->getMetaValue($account, 'currency_id');
- $currency = $currencyRepos->findNull($currencyId);
- $role = (string)$repository->getMetaValue($account, 'account_role');
+ $balance = app('steam')->balance($account, new Carbon);
+ $currency = $repository->getAccountCurrency($account) ?? $defaultCurrency;
+ $role = (string)$repository->getMetaValue($account, 'account_role');
if ('' === $role && !in_array($account->accountType->type, $liabilityTypes, true)) {
$role = 'no_account_type'; // @codeCoverageIgnore
}
@@ -257,10 +247,6 @@ class ExpandedForm
$role = 'l_' . $account->accountType->type; // @codeCoverageIgnore
}
- if (null === $currency) {
- $currency = $defaultCurrency;
- }
-
$key = (string)trans('firefly.opt_group_' . $role);
$grouped[$key][$account->id] = $account->name . ' (' . app('amount')->formatAnything($currency, $balance, false) . ')';
}
diff --git a/app/Support/Http/Controllers/PeriodOverview.php b/app/Support/Http/Controllers/PeriodOverview.php
index d6a1f36286..fb842b02cf 100644
--- a/app/Support/Http/Controllers/PeriodOverview.php
+++ b/app/Support/Http/Controllers/PeriodOverview.php
@@ -30,7 +30,6 @@ use FireflyIII\Models\Category;
use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
-use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
@@ -81,10 +80,7 @@ trait PeriodOverview
protected function getAccountPeriodOverview(Account $account, Carbon $start, Carbon $end): array
{
$range = app('preferences')->get('viewRange', '1M')->data;
-
- if ($end < $start) {
- [$start, $end] = [$end, $start]; // @codeCoverageIgnore
- }
+ [$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
// properties for cache
$cache = new CacheProperties;
@@ -159,10 +155,7 @@ trait PeriodOverview
protected function getCategoryPeriodOverview(Category $category, Carbon $start, Carbon $end): array
{
$range = app('preferences')->get('viewRange', '1M')->data;
-
- if ($end < $start) {
- [$start, $end] = [$end, $start]; // @codeCoverageIgnore
- }
+ [$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
// properties for entries with their amounts.
$cache = new CacheProperties();
@@ -173,7 +166,7 @@ trait PeriodOverview
$cache->addProperty($category->id);
if ($cache->has()) {
- //return $cache->get(); // @codeCoverageIgnore
+ return $cache->get(); // @codeCoverageIgnore
}
/** @var array $dates */
$dates = app('navigation')->blockPeriods($start, $end, $range);
@@ -240,9 +233,7 @@ trait PeriodOverview
{
$range = app('preferences')->get('viewRange', '1M')->data;
- if ($end < $start) {
- [$start, $end] = [$end, $start]; // @codeCoverageIgnore
- }
+ [$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
$cache = new CacheProperties;
$cache->addProperty($start);
@@ -250,7 +241,7 @@ trait PeriodOverview
$cache->addProperty('no-budget-period-entries');
if ($cache->has()) {
- //return $cache->get(); // @codeCoverageIgnore
+ return $cache->get(); // @codeCoverageIgnore
}
/** @var array $dates */
@@ -284,6 +275,8 @@ trait PeriodOverview
}
/**
+ * TODO fix date.
+ *
* Show period overview for no category view.
*
* @param Carbon $theDate
@@ -309,7 +302,7 @@ trait PeriodOverview
$cache->addProperty('no-category-period-entries');
if ($cache->has()) {
- //return $cache->get(); // @codeCoverageIgnore
+ return $cache->get(); // @codeCoverageIgnore
}
$dates = app('navigation')->blockPeriods($start, $end, $range);
@@ -379,11 +372,7 @@ trait PeriodOverview
/** @var Carbon $end */
$start = clone $date;
$end = $repository->firstUseDate($tag) ?? new Carbon;
-
-
- if ($end < $start) {
- [$start, $end] = [$end, $start]; // @codeCoverageIgnore
- }
+ [$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
// properties for entries with their amounts.
$cache = new CacheProperties;
@@ -431,63 +420,60 @@ trait PeriodOverview
* @param string $transactionType
* @param Carbon $endDate
*
- * @return Collection
+ * @return array
*/
- protected function getTransactionPeriodOverview(string $transactionType, Carbon $endDate): Collection
+ protected function getTransactionPeriodOverview(string $transactionType, Carbon $start, Carbon $end): array
{
- die('not yet complete');
- /** @var JournalRepositoryInterface $repository */
- $repository = app(JournalRepositoryInterface::class);
- $range = app('preferences')->get('viewRange', '1M')->data;
- $endJournal = $repository->firstNull();
- $end = null === $endJournal ? new Carbon : $endJournal->date;
- $start = clone $endDate;
- $types = config('firefly.transactionTypesByType.' . $transactionType);
+ $range = app('preferences')->get('viewRange', '1M')->data;
+ $types = config(sprintf('firefly.transactionTypesByType.%s', $transactionType));
+ [$start, $end] = $end < $start ? [$end, $start] : [$start, $end];
- if ($end < $start) {
- [$start, $end] = [$end, $start]; // @codeCoverageIgnore
+ // properties for cache
+ $cache = new CacheProperties;
+ $cache->addProperty($start);
+ $cache->addProperty($end);
+ $cache->addProperty('transactions-period-entries');
+ $cache->addProperty($transactionType);
+ if ($cache->has()) {
+ // return $cache->get(); // @codeCoverageIgnore
}
-
/** @var array $dates */
$dates = app('navigation')->blockPeriods($start, $end, $range);
- $entries = new Collection;
+ $entries = [];
+
+ // collect all journals in this period (regardless of type)
+ $collector = app(GroupCollectorInterface::class);
+ $collector->setTypes($types)->setRange($start, $end);
+ $genericSet = $collector->getExtractedJournals();
foreach ($dates as $currentDate) {
- /** @var GroupCollectorInterface $collector */
- $collector = app(GroupCollectorInterface::class);
- $collector->setTypes($types)->setRange($currentDate['start'], $currentDate['end']);
- $journals = $collector->getExtractedJournals();
- $amounts = $this->getJournalsSum($journals);
-
$spent = [];
$earned = [];
$transferred = [];
+ $title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
// set to correct array
if ('expenses' === $transactionType || 'withdrawal' === $transactionType) {
- $spent = $amounts;
+ $spent = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
}
if ('revenue' === $transactionType || 'deposit' === $transactionType) {
- $earned = $amounts;
+ $earned = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
}
if ('transfer' === $transactionType || 'transfers' === $transactionType) {
- $transferred = $amounts;
+ $transferred = $this->filterJournalsByDate($genericSet, $currentDate['start'], $currentDate['end']);
}
- $title = app('navigation')->periodShow($currentDate['end'], $currentDate['period']);
- $entries->push(
+ $entries[] =
[
- 'transactions' => $amounts['count'],
- 'title' => $title,
- 'spent' => $spent,
- 'earned' => $earned,
- 'transferred' => $transferred,
- 'route' => route(
- 'transactions.index', [$transactionType, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]
- ),
- ]
- );
+ 'title' => $title,
+ 'route' =>
+ route('transactions.index', [$transactionType, $currentDate['start']->format('Y-m-d'), $currentDate['end']->format('Y-m-d')]),
+ 'total_transactions' => count($spent) + count($earned) + count($transferred),
+ 'spent' => $this->groupByCurrency($spent),
+ 'earned' => $this->groupByCurrency($earned),
+ 'transferred' => $this->groupByCurrency($transferred),
+ ];
}
return $entries;
diff --git a/app/Support/Http/Controllers/RequestInformation.php b/app/Support/Http/Controllers/RequestInformation.php
index 062d79f1fc..af803a9047 100644
--- a/app/Support/Http/Controllers/RequestInformation.php
+++ b/app/Support/Http/Controllers/RequestInformation.php
@@ -178,7 +178,7 @@ trait RequestInformation
// both must be array and either must be > 0
if (count($intro) > 0 || count($specialIntro) > 0) {
$shownDemo = app('preferences')->get($key, false)->data;
- Log::debug(sprintf('Check if user has already seen intro with key "%s". Result is %s', $key, var_export($shownDemo, true)));
+ //Log::debug(sprintf('Check if user has already seen intro with key "%s". Result is %s', $key, var_export($shownDemo, true)));
}
if (!is_bool($shownDemo)) {
$shownDemo = true;
diff --git a/app/Support/Http/Controllers/UserNavigation.php b/app/Support/Http/Controllers/UserNavigation.php
index dc135e6133..2152c8d4d7 100644
--- a/app/Support/Http/Controllers/UserNavigation.php
+++ b/app/Support/Http/Controllers/UserNavigation.php
@@ -50,7 +50,7 @@ trait UserNavigation
*/
protected function getPreviousUri(string $identifier): string
{
- Log::debug(sprintf('Trying to retrieve URL stored under "%s"', $identifier));
+ // Log::debug(sprintf('Trying to retrieve URL stored under "%s"', $identifier));
// "forbidden" words for specific identifiers:
// if these are in the previous URI, don't refer back there.
$array = [
@@ -67,24 +67,24 @@ trait UserNavigation
'transactions.mass-delete.uri' => '/transactions/show/',
];
$forbidden = $array[$identifier] ?? '/show/';
- Log::debug(sprintf('The forbidden word for %s is "%s"', $identifier, $forbidden));
+ //Log::debug(sprintf('The forbidden word for %s is "%s"', $identifier, $forbidden));
$uri = (string)session($identifier);
- Log::debug(sprintf('The URI is %s', $uri));
+ //Log::debug(sprintf('The URI is %s', $uri));
if (
!(false === strpos($identifier, 'delete'))
&& !(false === strpos($uri, $forbidden))) {
$uri = $this->redirectUri;
- Log::debug(sprintf('URI is now %s (identifier contains "delete")', $uri));
+ //Log::debug(sprintf('URI is now %s (identifier contains "delete")', $uri));
}
if (!(false === strpos($uri, 'jscript'))) {
$uri = $this->redirectUri; // @codeCoverageIgnore
- Log::debug(sprintf('URI is now %s (uri contains jscript)', $uri));
+ //Log::debug(sprintf('URI is now %s (uri contains jscript)', $uri));
}
// more debug notes:
- Log::debug(sprintf('strpos($identifier, "delete"): %s', var_export(strpos($identifier, 'delete'), true)));
- Log::debug(sprintf('strpos($uri, $forbidden): %s', var_export(strpos($uri, $forbidden), true)));
+ //Log::debug(sprintf('strpos($identifier, "delete"): %s', var_export(strpos($identifier, 'delete'), true)));
+ //Log::debug(sprintf('strpos($uri, $forbidden): %s', var_export(strpos($uri, $forbidden), true)));
return $uri;
}
@@ -154,10 +154,10 @@ trait UserNavigation
if (null === $errors || (null !== $errors && 0 === $errors->count())) {
$url = app('url')->previous();
session()->put($identifier, $url);
- Log::debug(sprintf('Will put previous URI in cache under key %s: %s', $identifier, $url));
+ //Log::debug(sprintf('Will put previous URI in cache under key %s: %s', $identifier, $url));
return;
}
- Log::debug(sprintf('The users session contains errors somehow so we will not remember the URI!: %s', var_export($errors, true)));
+ //Log::debug(sprintf('The users session contains errors somehow so we will not remember the URI!: %s', var_export($errors, true)));
}
}
diff --git a/app/TransactionRules/TransactionMatcher.php b/app/TransactionRules/TransactionMatcher.php
index ac01df0d57..f54cd3dc23 100644
--- a/app/TransactionRules/TransactionMatcher.php
+++ b/app/TransactionRules/TransactionMatcher.php
@@ -265,10 +265,10 @@ class TransactionMatcher
// - all transactions have been fetched from the database
// - the maximum number of transactions to return has been found
// - the maximum number of transactions to search in have been searched
- $pageSize = min($this->searchLimit, min($this->triggeredLimit, 50));
- $processed = 0;
- $page = 1;
- $result = [];
+ $pageSize = min($this->searchLimit, min($this->triggeredLimit, 50));
+ $processed = 0;
+ $page = 1;
+ $totalResult = [];
Log::debug(sprintf('Search limit is %d, triggered limit is %d, so page size is %d', $this->searchLimit, $this->triggeredLimit, $pageSize));
@@ -322,8 +322,8 @@ class TransactionMatcher
Log::debug(sprintf('Found %d journals that match.', count($filtered)));
// merge:
- $result = $result + $filtered;
- Log::debug(sprintf('Total count is now %d', count($result)));
+ $totalResult = $totalResult + $filtered;
+ Log::debug(sprintf('Total count is now %d', count($totalResult)));
// Update counters
++$page;
@@ -333,7 +333,7 @@ class TransactionMatcher
// Check for conditions to finish the loop
$reachedEndOfList = count($journals) < 1;
- $foundEnough = count($result) >= $this->triggeredLimit;
+ $foundEnough = count($totalResult) >= $this->triggeredLimit;
$searchedEnough = ($processed >= $this->searchLimit);
Log::debug(sprintf('reachedEndOfList: %s', var_export($reachedEndOfList, true)));
@@ -342,6 +342,6 @@ class TransactionMatcher
} while (!$reachedEndOfList && !$foundEnough && !$searchedEnough);
Log::debug('End of do-loop');
- return $result;
+ return $totalResult;
}
}
diff --git a/app/TransactionRules/Triggers/CurrencyIs.php b/app/TransactionRules/Triggers/CurrencyIs.php
index d936a47a5e..03fdc9b5b6 100644
--- a/app/TransactionRules/Triggers/CurrencyIs.php
+++ b/app/TransactionRules/Triggers/CurrencyIs.php
@@ -70,8 +70,15 @@ final class CurrencyIs extends AbstractTrigger implements TriggerInterface
{
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);
- $currency = $repository->findByNameNull($this->triggerValue);
- $hit = true;
+
+ // if currency name contains " ("
+ if (0 === strpos($this->triggerValue, ' (')) {
+ $parts = explode(' (', $this->triggerValue);
+ $this->triggerValue = $parts[0];
+ }
+
+ $currency = $repository->findByNameNull($this->triggerValue);
+ $hit = true;
if (null !== $currency) {
/** @var Transaction $transaction */
foreach ($journal->transactions as $transaction) {
diff --git a/app/Validation/TransactionValidation.php b/app/Validation/TransactionValidation.php
index 7e523879e6..62dd43259a 100644
--- a/app/Validation/TransactionValidation.php
+++ b/app/Validation/TransactionValidation.php
@@ -41,7 +41,7 @@ trait TransactionValidation
*/
public function validateAccountInformation(Validator $validator): void
{
- Log::debug('Now in validateAccountInformation()');
+ //Log::debug('Now in validateAccountInformation()');
$data = $validator->getData();
$transactionType = $data['type'] ?? 'invalid';
diff --git a/public/v1/css/firefly.css b/public/v1/css/firefly.css
index 03eb004b8a..92ef770452 100644
--- a/public/v1/css/firefly.css
+++ b/public/v1/css/firefly.css
@@ -19,6 +19,10 @@
*/
+.no-margin-pagination {padding-bottom:0;padding-top:0;}
+.no-margin-pagination ul.pagination {margin:0 !important;}
+
+
input.ti-new-tag-input {
font-size: 14px !important;
line-height: 1.42857143;
diff --git a/public/v1/js/ff/recurring/create.js b/public/v1/js/ff/recurring/create.js
index 8eb77f162c..da87215c5a 100644
--- a/public/v1/js/ff/recurring/create.js
+++ b/public/v1/js/ff/recurring/create.js
@@ -189,13 +189,13 @@ function updateFormFields() {
// show source account ID:
$('#source_id_holder').show();
+ // show destination name:
+ // $('#destination_name_holder').show(); // old one
+ $('#withdrawal_destination_id_holder').show();
+
// hide destination ID:
$('#destination_id_holder').hide();
- // show destination name:
- //$('#destination_name_holder').show(); // old one
- $('#withdrawal_destination_id_holder').show();
-
// show budget
$('#budget_id_holder').show();
@@ -212,7 +212,6 @@ function updateFormFields() {
// $('#destination_name_holder').hide(); // old one
$('#withdrawal_destination_id_holder').hide();
-
$('#destination_id_holder').show();
$('#budget_id_holder').hide();
$('#piggy_bank_id_holder').hide();
diff --git a/public/v1/js/ff/recurring/edit.js b/public/v1/js/ff/recurring/edit.js
index 8127059ed4..bc5ea5d8e7 100644
--- a/public/v1/js/ff/recurring/edit.js
+++ b/public/v1/js/ff/recurring/edit.js
@@ -184,13 +184,15 @@ function updateFormFields() {
if (transactionType === 'withdrawal') {
// hide source account name:
- $('#source_name_holder').hide();
+ // $('#source_name_holder').hide(); // no longer used
+ $('#deposit_source_id_holder').hide();
// show source account ID:
$('#source_id_holder').show();
// show destination name:
- $('#destination_name_holder').show();
+ // $('#destination_name_holder').show(); // no longer used.
+ $('#withdrawal_destination_id_holder').show();
// hide destination ID:
$('#destination_id_holder').hide();
@@ -203,18 +205,28 @@ function updateFormFields() {
}
if (transactionType === 'deposit') {
- $('#source_name_holder').show();
+ // $('#source_name_holder').show(); // no longer used
+ $('#deposit_source_id_holder').show();
+
$('#source_id_holder').hide();
- $('#destination_name_holder').hide();
+
+ // $('#destination_name_holder').hide(); // no longer used
+ $('#withdrawal_destination_id_holder').hide();
+
$('#destination_id_holder').show();
$('#budget_id_holder').hide();
$('#piggy_bank_id_holder').hide();
}
if (transactionType === 'transfer') {
- $('#source_name_holder').hide();
+ // $('#source_name_holder').hide(); // no longer used
+ $('#deposit_source_id_holder').hide();
+
$('#source_id_holder').show();
- $('#destination_name_holder').hide();
+
+ // $('#destination_name_holder').hide(); // no longer used
+ $('#withdrawal_destination_id_holder').show();
+
$('#destination_id_holder').show();
$('#budget_id_holder').hide();
$('#piggy_bank_id_holder').show();
diff --git a/public/v1/js/ff/rules/create-edit.js b/public/v1/js/ff/rules/create-edit.js
index 3a62d58b16..a7939c9248 100644
--- a/public/v1/js/ff/rules/create-edit.js
+++ b/public/v1/js/ff/rules/create-edit.js
@@ -307,7 +307,7 @@ function updateTriggerInput(selectList) {
case 'to_account_is':
case 'to_account_contains':
console.log('Select list value is ' + selectList.val() + ', so input needs auto complete.');
- createAutoComplete(inputResult, 'json/all-accounts');
+ createAutoComplete(inputResult, 'json/accounts');
break;
case 'tag_is':
console.log('Select list value is ' + selectList.val() + ', so input needs auto complete.');
@@ -377,8 +377,8 @@ function createAutoComplete(input, URI) {
prefetch: {
url: URI + '?uid=' + uid,
filter: function (list) {
- return $.map(list, function (name) {
- return {name: name};
+ return $.map(list, function (item) {
+ return {name: item.name};
});
}
},
@@ -386,8 +386,8 @@ function createAutoComplete(input, URI) {
url: URI + '?search=%QUERY&uid=' + uid,
wildcard: '%QUERY',
filter: function (list) {
- return $.map(list, function (name) {
- return {name: name};
+ return $.map(list, function (item) {
+ return {name: item.name};
});
}
}
diff --git a/resources/lang/en_US/validation.php b/resources/lang/en_US/validation.php
index c28e44520c..a88bd5a43b 100644
--- a/resources/lang/en_US/validation.php
+++ b/resources/lang/en_US/validation.php
@@ -189,4 +189,7 @@ return [
'ob_source_need_data' => 'Need to get a valid source account ID and/or valid source account name to continue.',
'ob_dest_need_data' => 'Need to get a valid destination account ID and/or valid destination account name to continue.',
'ob_dest_bad_data' => 'Could not find a valid destination account when searching for ID ":id" or name ":name".',
+
+ 'generic_invalid_source' => 'You can\'t use this account as the source account.',
+ 'generic_invalid_destination' => 'You can\'t use this account as the destination account.',
];
diff --git a/resources/views/v1/list/groups.twig b/resources/views/v1/list/groups.twig
index f62c16fa32..1a44199aa5 100644
--- a/resources/views/v1/list/groups.twig
+++ b/resources/views/v1/list/groups.twig
@@ -5,9 +5,12 @@ TODO: hide and show columns
-
- {{ groups.render|raw }}
- |
+
+
+
+
+
+ |
@@ -16,7 +19,7 @@ TODO: hide and show columns
- {{ group.title }}
+ {{ group.title }}
|
@@ -25,7 +28,7 @@ TODO: hide and show columns
{% endfor %}
|
|
-
+ |
@@ -41,52 +44,54 @@ TODO: hide and show columns
{% for index, transaction in group.transactions %}
{% set style="" %}
{% if group.transactions|length == loop.index and group.count > 1 %}
- {% set style="style='border-bottom:1px #aaa solid;'" %}
+ {% set style="border-bottom:1px #aaa solid;" %}
{% endif %}
-
- {% if journal.transaction_type_type == 'Withdrawal' %}
+ |
+ {% if transaction.transaction_type_type == 'Withdrawal' %}
{% endif %}
- {% if journal.transaction_type_type == 'Deposit' %}
+ {% if transaction.transaction_type_type == 'Deposit' %}
{% endif %}
- {% if journal.transaction_type_type == 'Transfer' %}
+ {% if transaction.transaction_type_type == 'Transfer' %}
{% endif %}
- {% if journal.transaction_type_type == 'Reconciliation' %}
+ {% if transaction.transaction_type_type == 'Reconciliation' %}
{% endif %}
- {% if journal.transaction_type_type == 'Opening balance' %}
+ {% if transaction.transaction_type_type == 'Opening balance' %}
{% endif %}
|
-
+ |
{% if transaction.reconciled %}
{% endif %}
{{ transaction.description }}
|
-
+ |
{{ formatAmountBySymbol(transaction.amount, transaction.currency_symbol, transaction.currency_symbol_decimal_places) }}
{% if null != transaction.foreign_amount %}
({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_symbol_decimal_places) }})
{% endif %}
|
- {{ transaction.date.formatLocalized(monthAndDayFormat) }} |
-
+ |
+ {{ transaction.date.formatLocalized(monthAndDayFormat) }}
+ |
+
{{ transaction.source_account_name }}
|
-
+ |
{{ transaction.destination_account_name }}
|
-
+ |
{% if group.count == 1 %}
{% endif %}
|
+
+
+
+
+ |
{% endfor %}
{% endfor %}
|
+
+
+
+
+
+
+
+
+
+
+ |
+
+
-
-
diff --git a/resources/views/v1/list/journals-array-tiny.twig b/resources/views/v1/list/journals-array-tiny.twig
new file mode 100644
index 0000000000..f3fa763136
--- /dev/null
+++ b/resources/views/v1/list/journals-array-tiny.twig
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git a/resources/views/v1/recurring/edit.twig b/resources/views/v1/recurring/edit.twig
index 7d91a0d45e..50d4a4e2a3 100644
--- a/resources/views/v1/recurring/edit.twig
+++ b/resources/views/v1/recurring/edit.twig
@@ -91,13 +91,19 @@
{{ ExpandedForm.longAccountList('source_id', array.transactions[0].source_id, {label: trans('form.asset_source_account')}) }}
{# source account name for deposits: #}
- {{ ExpandedForm.text('source_name', array.transactions[0].source_name, {label: trans('form.revenue_account')}) }}
+ {#{{ ExpandedForm.text('source_name', array.transactions[0].source_name, {label: trans('form.revenue_account')}) }}#}
+
+ {# NEW for deposits, a drop down with revenue accounts, loan debt cash and mortgage #}
+ {{ ExpandedForm.activeDepositDestinations('deposit_source_id', preFilled.deposit_source_id, {label: trans('form.deposit_source_id')}) }}
{# destination if deposit or transfer: #}
{{ ExpandedForm.longAccountList('destination_id', array.transactions[0].destination_id, {label: trans('form.asset_destination_account')} ) }}
{# destination account name for withdrawals #}
- {{ ExpandedForm.text('destination_name', array.transactions[0].destination_name, {label: trans('form.expense_account')}) }}
+ {# {{ ExpandedForm.text('destination_name', array.transactions[0].destination_name, {label: trans('form.expense_account')}) }}#}
+
+ {# NEW for withdrawals, also a drop down with expense accounts, loans, debts, mortgages or (cash). #}
+ {{ ExpandedForm.activeWithdrawalDestinations('withdrawal_destination_id', preFilled.withdrawal_destination_id, {label: trans('form.withdrawal_destination_id')}) }}
diff --git a/resources/views/v1/recurring/show.twig b/resources/views/v1/recurring/show.twig
index 046b33d3a9..ad603c6769 100644
--- a/resources/views/v1/recurring/show.twig
+++ b/resources/views/v1/recurring/show.twig
@@ -198,7 +198,7 @@
- {% include 'list.transactions' with {showBudgets:true, showCategories:true} %}
+ {% include 'list.groups' %}
diff --git a/resources/views/v1/reports/partials/exp-categories.twig b/resources/views/v1/reports/partials/exp-categories.twig
index 1ff99b927d..bfa38f242b 100644
--- a/resources/views/v1/reports/partials/exp-categories.twig
+++ b/resources/views/v1/reports/partials/exp-categories.twig
@@ -31,7 +31,7 @@
{{ '0'|formatAmount }}
{% else %}
{% for income in entry.earned.per_currency %}
- {{ formatAmountBySymbol(income.sum, income.currency.symbol, income.currency.dp) }}
+ {{ formatAmountBySymbol(income.sum * -1, income.currency.symbol, income.currency.dp) }}
{% endfor %}
{% endif %}
diff --git a/resources/views/v1/reports/partials/exp-not-grouped.twig b/resources/views/v1/reports/partials/exp-not-grouped.twig
index ab4250937c..ec26868ce6 100644
--- a/resources/views/v1/reports/partials/exp-not-grouped.twig
+++ b/resources/views/v1/reports/partials/exp-not-grouped.twig
@@ -23,7 +23,7 @@
{{ '0'|formatAmount }}
{% endif %}
{% for income in amounts.earned.per_currency %}
- {{ formatAmountBySymbol(income.sum, income.currency.symbol, income.currency.dp) }}
+ {{ formatAmountBySymbol(income.sum * -1, income.currency.symbol, income.currency.dp) }}
{% endfor %}
diff --git a/resources/views/v1/reports/partials/top-transactions.twig b/resources/views/v1/reports/partials/top-transactions.twig
index f384049535..c52c4fa895 100644
--- a/resources/views/v1/reports/partials/top-transactions.twig
+++ b/resources/views/v1/reports/partials/top-transactions.twig
@@ -10,15 +10,21 @@
{% for transaction in sorted %}
-
- {{ transaction.opposing_account_name }}
+ |
+ {{ transaction.destination_account_name }}
|
{{ transaction.description }} |
{{ transaction.date.formatLocalized(monthAndDayFormat) }}
|
- {{ transaction|transactionAmount }} |
+
+
+ {{ formatAmountBySymbol(transaction.amount, transaction.currency_symbol, transaction.currency_symbol_decimal_places) }}
+ {% if null != transaction.foreign_amount %}
+ ({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_symbol_decimal_places) }})
+ {% endif %}
+ |
{% endfor %}
diff --git a/resources/views/v1/transactions/index.twig b/resources/views/v1/transactions/index.twig
index 921f16da60..9ce51a3103 100644
--- a/resources/views/v1/transactions/index.twig
+++ b/resources/views/v1/transactions/index.twig
@@ -7,7 +7,7 @@
{% block content %}
{# upper show-all instruction #}
- {% if periods.count > 0 %}
+ {% if periods|length > 0 %}
{{ 'showEverything'|_ }}
@@ -17,7 +17,7 @@
{# list with journals #}
-
+
{# boxes with info #}
- {% if periods.count > 0 %}
+ {% if periods|length > 0 %}
{% include 'list.periods' %}
@@ -56,7 +56,7 @@
{# lower show-all instruction #}
- {% if periods.count > 0 %}
+ {% if periods|length > 0 %}
{{ 'showEverything'|_ }}
diff --git a/routes/web.php b/routes/web.php
index 050373120a..72008dfe25 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -537,6 +537,8 @@ Route::group(
Route::get('currencies', ['uses' => 'Json\AutoCompleteController@currencies', 'as' => 'autocomplete.currencies']);
Route::get('piggy-banks', ['uses' => 'Json\AutoCompleteController@piggyBanks', 'as' => 'autocomplete.piggy-banks']);
Route::get('tags', ['uses' => 'Json\AutoCompleteController@tags', 'as' => 'autocomplete.tags']);
+ Route::get('transaction-journals/all', ['uses' => 'Json\AutoCompleteController@allJournals', 'as' => 'autocomplete.all-journals']);
+ Route::get('currency-names', ['uses' => 'Json\AutoCompleteController@currencyNames', 'as' => 'autocomplete.currency-names']);
diff --git a/tests/Feature/Controllers/Chart/BudgetReportControllerTest.php b/tests/Feature/Controllers/Chart/BudgetReportControllerTest.php
index 1f5db9a55e..cd3ccc8ed1 100644
--- a/tests/Feature/Controllers/Chart/BudgetReportControllerTest.php
+++ b/tests/Feature/Controllers/Chart/BudgetReportControllerTest.php
@@ -133,6 +133,8 @@ class BudgetReportControllerTest extends TestCase
$limit3->budget_id = $budget->id;
$limit3->start_date = new Carbon('2012-01-01');
$limit3->end_date = new Carbon('2012-01-31');
+ $limit3->amount = '100';
+ $limit3->save();
$fiscalHelper->shouldReceive('endOfFiscalYear')->atLeast()->once()->andReturn($date);
diff --git a/tests/Feature/Controllers/Recurring/CreateControllerTest.php b/tests/Feature/Controllers/Recurring/CreateControllerTest.php
index 73658580cf..f1d58d61ee 100644
--- a/tests/Feature/Controllers/Recurring/CreateControllerTest.php
+++ b/tests/Feature/Controllers/Recurring/CreateControllerTest.php
@@ -24,8 +24,9 @@ declare(strict_types=1);
namespace Tests\Feature\Controllers\Recurring;
+use Amount;
use Carbon\Carbon;
-use FireflyIII\Models\TransactionCurrency;
+use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
@@ -33,14 +34,18 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
+use FireflyIII\Validation\AccountValidator;
use Illuminate\Support\Collection;
use Log;
use Mockery;
+use Preferences;
+use Steam;
use Tests\TestCase;
/**
*
* Class CreateControllerTest
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
class CreateControllerTest extends TestCase
{
@@ -58,76 +63,100 @@ class CreateControllerTest extends TestCase
*/
public function testCreate(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
+ // mock repositories, even if not used.
+ $this->mock(RecurringRepositoryInterface::class);
+ $this->mock(CurrencyRepositoryInterface::class);
+ $this->mock(PiggyBankRepositoryInterface::class);
+
+ $accountRepos = $this->mock(AccountRepositoryInterface::class);
+ $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
+ $userRepos = $this->mock(UserRepositoryInterface::class);
+
+ $euro = $this->getEuro();
+ $asset = $this->getRandomAsset();
+ $cash = $this->getRandomAsset();
+ $this->mockDefaultSession();
- return;
- $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
- $userRepos = $this->mock(UserRepositoryInterface::class);
- $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
- $accountRepos = $this->mock(AccountRepositoryInterface::class);
- $piggyRepos = $this->mock(PiggyBankRepositoryInterface::class);
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
-
$budgetRepos->shouldReceive('getActiveBudgets')->andReturn(new Collection)->once();
- \Amount::shouldReceive('getDefaultCurrency')->andReturn(TransactionCurrency::find(1));
+
+
+ // for view:
+ $accountRepos->shouldReceive('getActiveAccountsByType')->atLeast()->once()->andReturn(new Collection([$asset]));
+ Steam::shouldReceive('balance')->andReturn('100')->atLeast()->once();
+ $accountRepos->shouldReceive('getAccountCurrency')->atLeast()->once()->andReturn($euro);
+ $accountRepos->shouldReceive('getMetaValue')->atLeast()->once()->andReturnNull();
+ $accountRepos->shouldReceive('getCashAccount')->atLeast()->once()->andReturn($cash);
+ //Amount::shouldReceive('getDefaultCurrency')->andReturn($euro)->atLeast()->once();
+ Amount::shouldReceive('formatAnything')->atLeast()->once()->andReturn('100');
$this->be($this->user());
$response = $this->get(route('recurring.create'));
$response->assertStatus(200);
$response->assertSee('
');
+ $response->assertSee('source_id_holder');
+ $response->assertSee('deposit_source_id');
+ $response->assertSee('withdrawal_destination_id');
+
}
/**
+ * Stores a withdrawal. From Asset account to Expense account
+ *
* @covers \FireflyIII\Http\Controllers\Recurring\CreateController
* @covers \FireflyIII\Http\Requests\RecurrenceFormRequest
*/
- public function testStore(): void
+ public function testStoreWithdrawalExpense(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
+ // mock repositories, even if not used.
+ $this->mock(BudgetRepositoryInterface::class);
- return;
$recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
- $categoryRepos = $this->mock(CategoryRepositoryInterface::class);
- $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
- $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $userRepos = $this->mock(UserRepositoryInterface::class);
- $accountRepos = $this->mock(AccountRepositoryInterface::class);
- $piggyRepos = $this->mock(PiggyBankRepositoryInterface::class);
+ $validator = $this->mock(AccountValidator::class);
+ $source = $this->getRandomAsset();
+ $destination = $this->getRandomExpense();
+ $tomorrow = Carbon::now()->addDays(2);
+ $recurrence = $this->user()->recurrences()->first();
- $tomorrow = Carbon::now()->addDays(2);
- $recurrence = $this->user()->recurrences()->first();
- $data = [
- 'title' => 'hello' . $this->randomInt(),
- 'first_date' => $tomorrow->format('Y-m-d'),
- 'repetition_type' => 'daily',
- 'skip' => 0,
- 'recurring_description' => 'Some descr' . $this->randomInt(),
- 'active' => '1',
- 'apply_rules' => '1',
- 'foreign_amount' => '1',
- 'foreign_currency_id' => '2',
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
+ // validator:
+ $validator->shouldReceive('setTransactionType')->withArgs(['withdrawal'])->atLeast()->once();
+ $validator->shouldReceive('validateSource')->atLeast()->once()->andReturn(true);
+ $validator->shouldReceive('validateDestination')->atLeast()->once()->andReturn(true);
+
+
+ $data = [
+ 'title' => sprintf('hello %d', $this->randomInt()),
+ 'first_date' => $tomorrow->format('Y-m-d'),
+ 'repetition_type' => 'daily',
+ 'skip' => 0,
+ 'recurring_description' => sprintf('Some descr %d', $this->randomInt()),
+ 'active' => '1',
+ 'apply_rules' => '1',
+ 'foreign_amount' => '1',
+ 'foreign_currency_id' => '2',
// mandatory for transaction:
- 'transaction_description' => 'Some descr',
- 'transaction_type' => 'withdrawal',
- 'transaction_currency_id' => '1',
- 'amount' => '30',
+ 'transaction_description' => 'Some descr',
+ 'transaction_type' => 'withdrawal',
+ 'transaction_currency_id' => '1',
+ 'amount' => '30',
// mandatory account info:
- 'source_id' => '1',
- 'destination_name' => 'Some Expense',
+ 'source_id' => $source->id,
+ 'withdrawal_destination_id' => $destination->id,
// optional fields:
- 'budget_id' => '1',
- 'category' => 'CategoryA',
- 'tags' => 'A,B,C',
- 'create_another' => '1',
- 'repetition_end' => 'times',
- 'repetitions' => 3,
+ 'budget_id' => '1',
+ 'category' => 'CategoryA',
+ 'tags' => 'A,B,C',
+ 'create_another' => '1',
+ 'repetition_end' => 'times',
+ 'repetitions' => 3,
];
$recurringRepos->shouldReceive('store')->andReturn($recurrence)->once();
@@ -139,23 +168,89 @@ class CreateControllerTest extends TestCase
}
/**
+ * Stores a withdrawal. But throw error.
+ *
* @covers \FireflyIII\Http\Controllers\Recurring\CreateController
* @covers \FireflyIII\Http\Requests\RecurrenceFormRequest
*/
- public function testStoreDeposit(): void
+ public function testStoreError(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
+ // mock repositories, even if not used.
+ $this->mock(BudgetRepositoryInterface::class);
- return;
$recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
- $categoryRepos = $this->mock(CategoryRepositoryInterface::class);
- $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
- $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $userRepos = $this->mock(UserRepositoryInterface::class);
- $accountRepos = $this->mock(AccountRepositoryInterface::class);
- $piggyRepos = $this->mock(PiggyBankRepositoryInterface::class);
+ $validator = $this->mock(AccountValidator::class);
+ $source = $this->getRandomAsset();
+ $destination = $this->getRandomExpense();
+ $tomorrow = Carbon::now()->addDays(2);
+ $this->mockDefaultSession();
+
+ // validator:
+ $validator->shouldReceive('setTransactionType')->withArgs(['withdrawal'])->atLeast()->once();
+ $validator->shouldReceive('validateSource')->atLeast()->once()->andReturn(true);
+ $validator->shouldReceive('validateDestination')->atLeast()->once()->andReturn(true);
+
+ $data = [
+ 'title' => sprintf('hello %d', $this->randomInt()),
+ 'first_date' => $tomorrow->format('Y-m-d'),
+ 'repetition_type' => 'daily',
+ 'skip' => 0,
+ 'recurring_description' => sprintf('Some descr %d', $this->randomInt()),
+ 'active' => '1',
+ 'apply_rules' => '1',
+ 'foreign_amount' => '1',
+ 'foreign_currency_id' => '2',
+
+ // mandatory for transaction:
+ 'transaction_description' => 'Some descr',
+ 'transaction_type' => 'withdrawal',
+ 'transaction_currency_id' => '1',
+ 'amount' => '30',
+
+ // mandatory account info:
+ 'source_id' => $source->id,
+ 'withdrawal_destination_id' => $destination->id,
+
+ // optional fields:
+ 'budget_id' => '1',
+ 'category' => 'CategoryA',
+ 'tags' => 'A,B,C',
+ 'create_another' => '1',
+ 'repetition_end' => 'times',
+ 'repetitions' => 3,
+ ];
+
+ $recurringRepos->shouldReceive('store')->andThrow(new FireflyException('Some exception'));
+
+ $this->be($this->user());
+ $response = $this->post(route('recurring.store'), $data);
+ $response->assertStatus(302);
+ $response->assertSessionHas('error', 'Some exception');
+ }
+
+ /**
+ * Store a deposit from Revenue to Asset.
+ *
+ * @covers \FireflyIII\Http\Controllers\Recurring\CreateController
+ * @covers \FireflyIII\Http\Requests\RecurrenceFormRequest
+ */
+ public function testStoreDepositRevenue(): void
+ {
+ $this->mock(BudgetRepositoryInterface::class);
+
+ $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
+ $validator = $this->mock(AccountValidator::class);
+ $source = $this->getRandomRevenue();
+ $destination = $this->getRandomAsset();
+
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
+ // validator:
+ $validator->shouldReceive('setTransactionType')->withArgs(['deposit'])->atLeast()->once();
+ $validator->shouldReceive('validateSource')->atLeast()->once()->andReturn(true);
+ $validator->shouldReceive('validateDestination')->atLeast()->once()->andReturn(true);
$tomorrow = Carbon::now()->addDays(2);
$recurrence = $this->user()->recurrences()->first();
@@ -177,10 +272,8 @@ class CreateControllerTest extends TestCase
'amount' => '30',
// mandatory account info:
- 'source_id' => '2',
- 'source_name' => 'Some source',
- 'destination_id' => '1',
- 'destination_name' => 'Some Expense',
+ 'deposit_source_id' => $source->id,
+ 'destination_id' => $destination->id,
// optional fields:
'budget_id' => '1',
@@ -200,53 +293,58 @@ class CreateControllerTest extends TestCase
}
/**
+ * Store a withdrawal but it's monthly, not daily.
+ *
* @covers \FireflyIII\Http\Controllers\Recurring\CreateController
* @covers \FireflyIII\Http\Requests\RecurrenceFormRequest
*/
public function testStoreMonthly(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
+ $this->mock(BudgetRepositoryInterface::class);
- return;
$recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
- $categoryRepos = $this->mock(CategoryRepositoryInterface::class);
- $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
- $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $userRepos = $this->mock(UserRepositoryInterface::class);
- $accountRepos = $this->mock(AccountRepositoryInterface::class);
- $piggyRepos = $this->mock(PiggyBankRepositoryInterface::class);
+ $validator = $this->mock(AccountValidator::class);
+ $source = $this->getRandomAsset();
+ $destination = $this->getRandomExpense();
+ $tomorrow = Carbon::now()->addDays(2);
+ $recurrence = $this->user()->recurrences()->first();
- $tomorrow = Carbon::now()->addDays(2);
- $recurrence = $this->user()->recurrences()->first();
- $data = [
- 'title' => 'hello' . $this->randomInt(),
- 'first_date' => $tomorrow->format('Y-m-d'),
- 'repetition_type' => 'monthly,5',
- 'skip' => 0,
- 'recurring_description' => 'Some descr' . $this->randomInt(),
- 'active' => '1',
- 'apply_rules' => '1',
- 'foreign_amount' => '1',
- 'foreign_currency_id' => '2',
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
+ // validator:
+ $validator->shouldReceive('setTransactionType')->withArgs(['withdrawal'])->atLeast()->once();
+ $validator->shouldReceive('validateSource')->atLeast()->once()->andReturn(true);
+ $validator->shouldReceive('validateDestination')->atLeast()->once()->andReturn(true);
+
+ $data = [
+ 'title' => sprintf('hello %d', $this->randomInt()),
+ 'first_date' => $tomorrow->format('Y-m-d'),
+ 'repetition_type' => 'monthly,5',
+ 'skip' => 0,
+ 'recurring_description' => sprintf('Some descr %d', $this->randomInt()),
+ 'active' => '1',
+ 'apply_rules' => '1',
+ 'foreign_amount' => '1',
+ 'foreign_currency_id' => '2',
// mandatory for transaction:
- 'transaction_description' => 'Some descr',
- 'transaction_type' => 'withdrawal',
- 'transaction_currency_id' => '1',
- 'amount' => '30',
+ 'transaction_description' => 'Some descr',
+ 'transaction_type' => 'withdrawal',
+ 'transaction_currency_id' => '1',
+ 'amount' => '30',
// mandatory account info:
- 'source_id' => '1',
- 'destination_name' => 'Some Expense',
+ 'source_id' => $source->id,
+ 'withdrawal_destination_id' => $destination->id,
// optional fields:
- 'budget_id' => '1',
- 'category' => 'CategoryA',
- 'tags' => 'A,B,C',
- 'create_another' => '1',
- 'repetition_end' => 'times',
- 'repetitions' => 3,
+ 'budget_id' => '1',
+ 'category' => 'CategoryA',
+ 'tags' => 'A,B,C',
+ 'create_another' => '1',
+ 'repetition_end' => 'times',
+ 'repetitions' => 3,
];
$recurringRepos->shouldReceive('store')->andReturn($recurrence)->once();
@@ -258,53 +356,58 @@ class CreateControllerTest extends TestCase
}
/**
+ * Store a withdrawal but use ndom.
+ *
* @covers \FireflyIII\Http\Controllers\Recurring\CreateController
* @covers \FireflyIII\Http\Requests\RecurrenceFormRequest
*/
public function testStoreNdom(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
+ $this->mock(BudgetRepositoryInterface::class);
- return;
$recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
- $categoryRepos = $this->mock(CategoryRepositoryInterface::class);
- $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
- $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $userRepos = $this->mock(UserRepositoryInterface::class);
- $accountRepos = $this->mock(AccountRepositoryInterface::class);
- $piggyRepos = $this->mock(PiggyBankRepositoryInterface::class);
+ $validator = $this->mock(AccountValidator::class);
+ $source = $this->getRandomAsset();
+ $destination = $this->getRandomExpense();
+ $tomorrow = Carbon::now()->addDays(2);
+ $recurrence = $this->user()->recurrences()->first();
- $tomorrow = Carbon::now()->addDays(2);
- $recurrence = $this->user()->recurrences()->first();
- $data = [
- 'title' => 'hello' . $this->randomInt(),
- 'first_date' => $tomorrow->format('Y-m-d'),
- 'repetition_type' => 'ndom,3,5',
- 'skip' => 0,
- 'recurring_description' => 'Some descr' . $this->randomInt(),
- 'active' => '1',
- 'apply_rules' => '1',
- 'foreign_amount' => '1',
- 'foreign_currency_id' => '2',
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
+ // validator:
+ $validator->shouldReceive('setTransactionType')->withArgs(['withdrawal'])->atLeast()->once();
+ $validator->shouldReceive('validateSource')->atLeast()->once()->andReturn(true);
+ $validator->shouldReceive('validateDestination')->atLeast()->once()->andReturn(true);
+
+ $data = [
+ 'title' => sprintf('hello %d', $this->randomInt()),
+ 'first_date' => $tomorrow->format('Y-m-d'),
+ 'repetition_type' => 'ndom,3,5',
+ 'skip' => 0,
+ 'recurring_description' => sprintf('Some descr %d', $this->randomInt()),
+ 'active' => '1',
+ 'apply_rules' => '1',
+ 'foreign_amount' => '1',
+ 'foreign_currency_id' => '2',
// mandatory for transaction:
- 'transaction_description' => 'Some descr',
- 'transaction_type' => 'withdrawal',
- 'transaction_currency_id' => '1',
- 'amount' => '30',
+ 'transaction_description' => 'Some descr',
+ 'transaction_type' => 'withdrawal',
+ 'transaction_currency_id' => '1',
+ 'amount' => '30',
// mandatory account info:
- 'source_id' => '1',
- 'destination_name' => 'Some Expense',
+ 'source_id' => $source->id,
+ 'withdrawal_destination_id' => $destination->id,
// optional fields:
- 'budget_id' => '1',
- 'category' => 'CategoryA',
- 'tags' => 'A,B,C',
- 'create_another' => '1',
- 'repetition_end' => 'times',
- 'repetitions' => 3,
+ 'budget_id' => '1',
+ 'category' => 'CategoryA',
+ 'tags' => 'A,B,C',
+ 'create_another' => '1',
+ 'repetition_end' => 'times',
+ 'repetitions' => 3,
];
$recurringRepos->shouldReceive('store')->andReturn($recurrence)->once();
@@ -321,17 +424,20 @@ class CreateControllerTest extends TestCase
*/
public function testStoreTransfer(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
+ $this->mock(BudgetRepositoryInterface::class);
- return;
$recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
- $categoryRepos = $this->mock(CategoryRepositoryInterface::class);
- $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
- $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $userRepos = $this->mock(UserRepositoryInterface::class);
- $accountRepos = $this->mock(AccountRepositoryInterface::class);
- $piggyRepos = $this->mock(PiggyBankRepositoryInterface::class);
+ $validator = $this->mock(AccountValidator::class);
+ $source = $this->getRandomAsset();
+ $destination = $this->getRandomAsset($source->id);
+
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
+ // validator:
+ $validator->shouldReceive('setTransactionType')->withArgs(['transfer'])->atLeast()->once();
+ $validator->shouldReceive('validateSource')->atLeast()->once()->andReturn(true);
+ $validator->shouldReceive('validateDestination')->atLeast()->once()->andReturn(true);
$tomorrow = Carbon::now()->addDays(2);
@@ -354,10 +460,8 @@ class CreateControllerTest extends TestCase
'amount' => '30',
// mandatory account info:
- 'source_id' => '2',
- 'source_name' => 'Some source',
- 'destination_id' => '1',
- 'destination_name' => 'Some Expense',
+ 'source_id' => $source->id,
+ 'destination_id' => $destination->id,
// optional fields:
'budget_id' => '1',
@@ -382,49 +486,51 @@ class CreateControllerTest extends TestCase
*/
public function testStoreUntilDate(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
+ $this->mock(BudgetRepositoryInterface::class);
- return;
$recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
- $categoryRepos = $this->mock(CategoryRepositoryInterface::class);
- $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
- $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $userRepos = $this->mock(UserRepositoryInterface::class);
- $accountRepos = $this->mock(AccountRepositoryInterface::class);
- $piggyRepos = $this->mock(PiggyBankRepositoryInterface::class);
+ $validator = $this->mock(AccountValidator::class);
+ $source = $this->getRandomAsset();
+ $destination = $this->getRandomExpense();
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
+ // validator:
+ $validator->shouldReceive('setTransactionType')->withArgs(['withdrawal'])->atLeast()->once();
+ $validator->shouldReceive('validateSource')->atLeast()->once()->andReturn(true);
+ $validator->shouldReceive('validateDestination')->atLeast()->once()->andReturn(true);
$tomorrow = Carbon::now()->addDays(2);
$recurrence = $this->user()->recurrences()->first();
$data = [
- 'title' => 'hello' . $this->randomInt(),
- 'first_date' => $tomorrow->format('Y-m-d'),
- 'repetition_type' => 'daily',
- 'skip' => 0,
- 'recurring_description' => 'Some descr' . $this->randomInt(),
- 'active' => '1',
- 'apply_rules' => '1',
- 'foreign_amount' => '1',
- 'foreign_currency_id' => '2',
+ 'title' => sprintf('hello %d', $this->randomInt()),
+ 'first_date' => $tomorrow->format('Y-m-d'),
+ 'repetition_type' => 'daily',
+ 'skip' => 0,
+ 'recurring_description' => sprintf('Some descr %d', $this->randomInt()),
+ 'active' => '1',
+ 'apply_rules' => '1',
+ 'foreign_amount' => '1',
+ 'foreign_currency_id' => '2',
// mandatory for transaction:
- 'transaction_description' => 'Some descr',
- 'transaction_type' => 'withdrawal',
- 'transaction_currency_id' => '1',
- 'amount' => '30',
+ 'transaction_description' => 'Some descr',
+ 'transaction_type' => 'withdrawal',
+ 'transaction_currency_id' => '1',
+ 'amount' => '30',
// mandatory account info:
- 'source_id' => '1',
- 'destination_name' => 'Some Expense',
+ 'source_id' => $source->id,
+ 'withdrawal_destination_id' => $destination->id,
// optional fields:
- 'budget_id' => '1',
- 'category' => 'CategoryA',
- 'tags' => 'A,B,C',
- 'create_another' => '1',
- 'repetition_end' => 'until_date',
- 'repeat_until' => $tomorrow->format('Y-m-d'),
+ 'budget_id' => '1',
+ 'category' => 'CategoryA',
+ 'tags' => 'A,B,C',
+ 'create_another' => '1',
+ 'repetition_end' => 'until_date',
+ 'repeat_until' => $tomorrow->format('Y-m-d'),
];
$recurringRepos->shouldReceive('store')->andReturn($recurrence)->once();
@@ -441,48 +547,51 @@ class CreateControllerTest extends TestCase
*/
public function testStoreYearly(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
+ $this->mock(BudgetRepositoryInterface::class);
- return;
$recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
- $categoryRepos = $this->mock(CategoryRepositoryInterface::class);
- $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
- $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $userRepos = $this->mock(UserRepositoryInterface::class);
- $accountRepos = $this->mock(AccountRepositoryInterface::class);
- $piggyRepos = $this->mock(PiggyBankRepositoryInterface::class);
+ $validator = $this->mock(AccountValidator::class);
+ $source = $this->getRandomAsset();
+ $destination = $this->getRandomExpense();
+ $tomorrow = Carbon::now()->addDays(2);
+ $recurrence = $this->user()->recurrences()->first();
- $tomorrow = Carbon::now()->addDays(2);
- $recurrence = $this->user()->recurrences()->first();
- $data = [
- 'title' => 'hello' . $this->randomInt(),
- 'first_date' => $tomorrow->format('Y-m-d'),
- 'repetition_type' => 'yearly,2018-01-01',
- 'skip' => 0,
- 'recurring_description' => 'Some descr' . $this->randomInt(),
- 'active' => '1',
- 'apply_rules' => '1',
- 'foreign_amount' => '1',
- 'foreign_currency_id' => '2',
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
+ // validator:
+ $validator->shouldReceive('setTransactionType')->withArgs(['withdrawal'])->atLeast()->once();
+ $validator->shouldReceive('validateSource')->atLeast()->once()->andReturn(true);
+ $validator->shouldReceive('validateDestination')->atLeast()->once()->andReturn(true);
+
+ $data = [
+ 'title' => sprintf('hello %d', $this->randomInt()),
+ 'first_date' => $tomorrow->format('Y-m-d'),
+ 'repetition_type' => 'yearly,2018-01-01',
+ 'skip' => 0,
+ 'recurring_description' => sprintf('Some descr %d', $this->randomInt()),
+ 'active' => '1',
+ 'apply_rules' => '1',
+ 'foreign_amount' => '1',
+ 'foreign_currency_id' => '2',
// mandatory for transaction:
- 'transaction_description' => 'Some descr',
- 'transaction_type' => 'withdrawal',
- 'transaction_currency_id' => '1',
- 'amount' => '30',
+ 'transaction_description' => 'Some descr',
+ 'transaction_type' => 'withdrawal',
+ 'transaction_currency_id' => '1',
+ 'amount' => '30',
// mandatory account info:
- 'source_id' => '1',
- 'destination_name' => 'Some Expense',
+ 'source_id' => $source->id,
+ 'withdrawal_destination_id' => $destination->id,
// optional fields:
- 'budget_id' => '1',
- 'category' => 'CategoryA',
- 'tags' => 'A,B,C',
- 'create_another' => '1',
- 'repetition_end' => 'times',
- 'repetitions' => 3,
+ 'budget_id' => '1',
+ 'category' => 'CategoryA',
+ 'tags' => 'A,B,C',
+ 'create_another' => '1',
+ 'repetition_end' => 'times',
+ 'repetitions' => 3,
];
$recurringRepos->shouldReceive('store')->andReturn($recurrence)->once();
diff --git a/tests/Feature/Controllers/Recurring/DeleteControllerTest.php b/tests/Feature/Controllers/Recurring/DeleteControllerTest.php
index 05484ffbea..8391ed0dbd 100644
--- a/tests/Feature/Controllers/Recurring/DeleteControllerTest.php
+++ b/tests/Feature/Controllers/Recurring/DeleteControllerTest.php
@@ -28,6 +28,7 @@ use FireflyIII\Repositories\User\UserRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
use Mockery;
+use Preferences;
use Tests\TestCase;
/**
@@ -53,7 +54,9 @@ class DeleteControllerTest extends TestCase
$recurringRepos = $this->mock(RecurringRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
- $recurringRepos->shouldReceive('getTransactions')->andReturn(new Collection())->once();
+ $this->mockDefaultSession();
+
+ $recurringRepos->shouldReceive('getTransactions')->andReturn(new Collection)->once();
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
$this->be($this->user());
@@ -70,6 +73,9 @@ class DeleteControllerTest extends TestCase
$recurringRepos = $this->mock(RecurringRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
$recurringRepos->shouldReceive('destroy')->once();
diff --git a/tests/Feature/Controllers/Recurring/EditControllerTest.php b/tests/Feature/Controllers/Recurring/EditControllerTest.php
index e2cab419e7..0df8300abf 100644
--- a/tests/Feature/Controllers/Recurring/EditControllerTest.php
+++ b/tests/Feature/Controllers/Recurring/EditControllerTest.php
@@ -23,19 +23,21 @@ declare(strict_types=1);
namespace Tests\Feature\Controllers\Recurring;
+use Amount;
use Carbon\Carbon;
-use FireflyIII\Factory\CategoryFactory;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
-use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Transformers\RecurrenceTransformer;
+use FireflyIII\Validation\AccountValidator;
use Illuminate\Support\Collection;
use Log;
use Mockery;
+use Preferences;
+use Steam;
use Tests\TestCase;
/**
@@ -58,23 +60,44 @@ class EditControllerTest extends TestCase
*/
public function testEdit(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
+ $this->mock(CurrencyRepositoryInterface::class);
+ $this->mock(PiggyBankRepositoryInterface::class);
- return;
- $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
- $userRepos = $this->mock(UserRepositoryInterface::class);
- $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
- $accountRepos = $this->mock(AccountRepositoryInterface::class);
- $categoryFactory = $this->mock(CategoryFactory::class);
- $piggyRepos = $this->mock(PiggyBankRepositoryInterface::class);
- $transformer = $this->mock(RecurrenceTransformer::class);
+ $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
+ $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
+ $userRepos = $this->mock(UserRepositoryInterface::class);
+ $accountRepos = $this->mock(AccountRepositoryInterface::class);
+ $transformer = $this->mock(RecurrenceTransformer::class);
+ $asset = $this->getRandomAsset();
+ $euro = $this->getEuro();
+ $cash = $this->getRandomAsset();
+ $this->mockDefaultSession();
+ $transformed = [
+ 'transactions' => [
+ [
+ 'source_id' => 1,
+ 'destination_id' => 1,
+ ],
+ ],
+ ];
+
+ // for view:
+ $accountRepos->shouldReceive('getActiveAccountsByType')->atLeast()->once()->andReturn(new Collection([$asset]));
+ Steam::shouldReceive('balance')->andReturn('100')->atLeast()->once();
+ $accountRepos->shouldReceive('getAccountCurrency')->atLeast()->once()->andReturn($euro);
+ $accountRepos->shouldReceive('getMetaValue')->atLeast()->once()->andReturnNull();
+ $accountRepos->shouldReceive('getCashAccount')->atLeast()->once()->andReturn($cash);
+ //Amount::shouldReceive('getDefaultCurrency')->andReturn($euro)->atLeast()->once();
+ Amount::shouldReceive('formatAnything')->atLeast()->once()->andReturn('100');
+
+ // transform recurrence.
$transformer->shouldReceive('setParameters')->atLeast()->once();
- $transformer->shouldReceive('transform')->atLeast()->once();
+ $transformer->shouldReceive('transform')->atLeast()->once()->andReturn($transformed);
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
+ // get stuff from recurrence.
$recurringRepos->shouldReceive('setUser');
$recurringRepos->shouldReceive('getNoteText')->andReturn('Note!');
$recurringRepos->shouldReceive('repetitionDescription')->andReturn('dunno');
@@ -90,6 +113,8 @@ class EditControllerTest extends TestCase
$response = $this->get(route('recurring.edit', [1]));
$response->assertStatus(200);
$response->assertSee('');
+ $response->assertSee('deposit_source_id');
+ $response->assertSee('withdrawal_destination_id');
}
/**
@@ -98,51 +123,52 @@ class EditControllerTest extends TestCase
*/
public function testUpdate(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
+ $this->mock(BudgetRepositoryInterface::class);
+ $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
+ $validator = $this->mock(AccountValidator::class);
+ $expense = $this->getRandomExpense();
- return;
- $recurringRepos = $this->mock(RecurringRepositoryInterface::class);
- $budgetRepos = $this->mock(BudgetRepositoryInterface::class);
- $categoryRepos = $this->mock(CategoryRepositoryInterface::class);
- $userRepos = $this->mock(UserRepositoryInterface::class);
- $currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
- $accountRepos = $this->mock(AccountRepositoryInterface::class);
- $categoryFactory = $this->mock(CategoryFactory::class);
- $piggyRepos = $this->mock(PiggyBankRepositoryInterface::class);
- $transformer = $this->mock(RecurrenceTransformer::class);
+ $this->mockDefaultSession();
$recurringRepos->shouldReceive('update')->once();
+ // validator:
+ $validator->shouldReceive('setTransactionType')->withArgs(['withdrawal'])->atLeast()->once();
+ $validator->shouldReceive('validateSource')->atLeast()->once()->andReturn(true);
+ $validator->shouldReceive('validateDestination')->atLeast()->once()->andReturn(true);
+ Preferences::shouldReceive('mark')->once();
+
$tomorrow = Carbon::now()->addDays(2);
$recurrence = $this->user()->recurrences()->first();
$data = [
- 'id' => $recurrence->id,
- 'title' => 'hello',
- 'first_date' => $tomorrow->format('Y-m-d'),
- 'repetition_type' => 'daily',
- 'skip' => 0,
- 'recurring_description' => 'Some descr',
- 'active' => '1',
- 'apply_rules' => '1',
- 'return_to_edit' => '1',
+ 'id' => $recurrence->id,
+ 'title' => 'hello',
+ 'first_date' => $tomorrow->format('Y-m-d'),
+ 'repetition_type' => 'daily',
+ 'skip' => 0,
+ 'recurring_description' => 'Some descr',
+ 'active' => '1',
+ 'apply_rules' => '1',
+ 'return_to_edit' => '1',
// mandatory for transaction:
- 'transaction_description' => 'Some descr',
- 'transaction_type' => 'withdrawal',
- 'transaction_currency_id' => '1',
- 'amount' => '30',
+ 'transaction_description' => 'Some descr',
+ 'transaction_type' => 'withdrawal',
+ 'transaction_currency_id' => '1',
+ 'amount' => '30',
// mandatory account info:
- 'source_id' => '1',
- 'source_name' => '',
- 'destination_id' => '',
- 'destination_name' => 'Some Expense',
+ 'source_id' => '1',
+ 'source_name' => '',
+ 'withdrawal_destination_id' => $expense->id,
+ 'destination_id' => '',
+ 'destination_name' => 'Some Expense',
// optional fields:
- 'budget_id' => '1',
- 'category' => 'CategoryA',
- 'tags' => 'A,B,C',
- 'create_another' => '1',
- 'repetition_end' => 'times',
- 'repetitions' => 3,
+ 'budget_id' => '1',
+ 'category' => 'CategoryA',
+ 'tags' => 'A,B,C',
+ 'create_another' => '1',
+ 'repetition_end' => 'times',
+ 'repetitions' => 3,
];
diff --git a/tests/Feature/Controllers/Recurring/IndexControllerTest.php b/tests/Feature/Controllers/Recurring/IndexControllerTest.php
index 8c0f7f96b9..ee9912fc67 100644
--- a/tests/Feature/Controllers/Recurring/IndexControllerTest.php
+++ b/tests/Feature/Controllers/Recurring/IndexControllerTest.php
@@ -25,6 +25,7 @@ namespace Tests\Feature\Controllers\Recurring;
use FireflyIII\Factory\CategoryFactory;
use FireflyIII\Models\Configuration;
+use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
@@ -32,6 +33,7 @@ use FireflyIII\Transformers\RecurrenceTransformer;
use Illuminate\Support\Collection;
use Log;
use Mockery;
+use Preferences;
use Tests\TestCase;
/**
@@ -61,6 +63,13 @@ class IndexControllerTest extends TestCase
$categoryFactory = $this->mock(CategoryFactory::class);
$transformer = $this->mock(RecurrenceTransformer::class);
+ // mock calls
+ $pref = new Preference;
+ $pref->data = 50;
+ Preferences::shouldReceive('get')->withArgs(['listPageSize', 50])->atLeast()->once()->andReturn($pref);
+
+ $this->mockDefaultSession();
+
$transformer->shouldReceive('setParameters')->atLeast()->once();
$transformer->shouldReceive('transform')->atLeast()->once()->andReturn(
[
@@ -83,7 +92,6 @@ class IndexControllerTest extends TestCase
// mock cron job config:
\FireflyConfig::shouldReceive('get')->withArgs(['last_rt_job', 0])->once()->andReturn($config);
- \FireflyConfig::shouldReceive('get')->withArgs(['is_demo_site', false])->once()->andReturn($falseConfig);
$repository->shouldReceive('get')->andReturn($collection)->once();
@@ -94,6 +102,9 @@ class IndexControllerTest extends TestCase
$response->assertSee('');
}
+ /**
+ * @covers \FireflyIII\Http\Controllers\Recurring\IndexController
+ */
public function testShow(): void
{
$repository = $this->mock(RecurringRepositoryInterface::class);
@@ -102,6 +113,8 @@ class IndexControllerTest extends TestCase
$categoryFactory = $this->mock(CategoryFactory::class);
$transformer = $this->mock(RecurrenceTransformer::class);
+ $this->mockDefaultSession();
+
$transformer->shouldReceive('setParameters')->atLeast()->once();
$transformer->shouldReceive('transform')->atLeast()->once()->andReturn(
[
@@ -109,7 +122,13 @@ class IndexControllerTest extends TestCase
'first_date' => '2018-01-01',
'repeat_until' => null,
'latest_date' => null,
- 'recurrence_repetitions' => [],
+ 'recurrence_repetitions' => [
+ [
+ 'occurrences' => [
+ '2019-01-01'
+ ]
+ ]
+ ],
]
);
diff --git a/tests/Feature/Controllers/Report/ExpenseControllerTest.php b/tests/Feature/Controllers/Report/ExpenseControllerTest.php
index 54c49dee5c..9270e11cf8 100644
--- a/tests/Feature/Controllers/Report/ExpenseControllerTest.php
+++ b/tests/Feature/Controllers/Report/ExpenseControllerTest.php
@@ -22,14 +22,14 @@ declare(strict_types=1);
namespace Tests\Feature\Controllers\Report;
+use Amount;
use Carbon\Carbon;
-
+use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Helpers\Fiscal\FiscalHelperInterface;
use FireflyIII\Models\AccountType;
-use FireflyIII\Models\Transaction;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
-use Illuminate\Support\Collection;
use Log;
+use Preferences;
use Tests\TestCase;
/**
@@ -56,46 +56,30 @@ class ExpenseControllerTest extends TestCase
*/
public function testBudget(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
-
- return;
- $expense = $this->user()->accounts()->where('account_type_id', 4)->first();
- $revenue = $this->user()->accounts()->where('account_type_id', 5)->first();
$repository = $this->mock(AccountRepositoryInterface::class);
$fiscalHelper = $this->mock(FiscalHelperInterface::class);
+ $collector = $this->mock(GroupCollectorInterface::class);
+ $expense = $this->getRandomExpense();
+ $revenue = $this->getRandomRevenue();
$date = new Carbon;
+ $transactions = [$this->getRandomWithdrawalAsArray()];
+
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('lastActivity')->atLeast()->once();
+
+
$fiscalHelper->shouldReceive('endOfFiscalYear')->atLeast()->once()->andReturn($date);
$fiscalHelper->shouldReceive('startOfFiscalYear')->atLeast()->once()->andReturn($date);
$repository->shouldReceive('findByName')->once()->withArgs([$expense->name, [AccountType::REVENUE]])->andReturn($revenue);
+ Amount::shouldReceive('formatAnything')->atLeast()->once()->andReturn('-100');
- // fake collection:
- $transA = new Transaction;
- $transA->transaction_currency_id = 1;
- $transA->transaction_budget_name = 'Budget';
- $transA->transaction_budget_id = 1;
- $transA->transaction_currency_symbol = 'A';
- $transA->transaction_currency_dp = 2;
- $transA->transaction_amount = '100';
- $transB = new Transaction;
- $transB->transaction_currency_id = 2;
- $transB->transaction_budget_name = null;
- $transB->transaction_budget_id = 0;
- $transB->transaction_journal_budget_name = 'Budget2';
- $transB->transaction_journal_budget_id = 2;
- $transB->transaction_currency_symbol = 'A';
- $transB->transaction_currency_dp = 2;
- $transB->transaction_amount = '100';
- $collection = new Collection([$transA, $transB]);
- // mock collector for spentByBudget (complex)
- $collector = $this->mock(TransactionCollectorInterface::class);
// dont care about any calls, just return a default set of fake transactions:
- $collector->shouldReceive('setRange')->andReturnSelf();
- $collector->shouldReceive('setTypes')->andReturnSelf();
- $collector->shouldReceive('setAccounts')->andReturnSelf();
- $collector->shouldReceive('setOpposingAccounts')->andReturnSelf();
- $collector->shouldReceive('withBudgetInformation')->andReturnSelf();
- $collector->shouldReceive('getTransactions')->andReturn($collection);
+ $collector->shouldReceive('setRange')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('setTypes')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('setAccounts')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('withBudgetInformation')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('getExtractedJournals')->andReturn($transactions)->atLeast()->once();
$this->be($this->user());
@@ -108,57 +92,37 @@ class ExpenseControllerTest extends TestCase
*/
public function testCategory(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
-
- return;
- $expense = $this->user()->accounts()->where('account_type_id', 4)->first();
- $revenue = $this->user()->accounts()->where('account_type_id', 5)->first();
$repository = $this->mock(AccountRepositoryInterface::class);
$fiscalHelper = $this->mock(FiscalHelperInterface::class);
+ $collector = $this->mock(GroupCollectorInterface::class);
+ $expense = $this->getRandomExpense();
+ $revenue = $this->getRandomRevenue();
$date = new Carbon;
+ $one = $this->getRandomWithdrawalAsArray();
+ $two = $this->getRandomWithdrawalAsArray();
+
+ // two categories
+ $oneCat = $this->getRandomCategory();
+ $twoCat = $this->user()->categories()->where('id', '!=', $oneCat->id)->inRandomOrder()->first();
+
+ $one['category_id'] = $oneCat->id;
+ $one['category_name'] = $oneCat->name;
+ $two['category_id'] = $twoCat->id;
+ $two['category_name'] = $twoCat->name;
+
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('lastActivity')->atLeast()->once();
+
$fiscalHelper->shouldReceive('endOfFiscalYear')->atLeast()->once()->andReturn($date);
$fiscalHelper->shouldReceive('startOfFiscalYear')->atLeast()->once()->andReturn($date);
$repository->shouldReceive('findByName')->once()->withArgs([$expense->name, [AccountType::REVENUE]])->andReturn($revenue);
+ Amount::shouldReceive('formatAnything')->atLeast()->once()->andReturn('-100');
- // fake collection:
- $transA = new Transaction;
- $transA->transaction_currency_id = 1;
- $transA->transaction_category_name = 'Category';
- $transA->transaction_category_id = 1;
- $transA->transaction_currency_symbol = 'A';
- $transA->transaction_currency_dp = 2;
- $transA->transaction_amount = '100';
- $transB = new Transaction;
- $transB->transaction_currency_id = 2;
- $transB->transaction_category_name = null;
- $transB->transaction_category_id = 0;
- $transB->transaction_journal_category_name = 'Category2';
- $transB->transaction_journal_category_id = 2;
- $transB->transaction_currency_symbol = 'A';
- $transB->transaction_currency_dp = 2;
- $transB->transaction_amount = '100';
- $collection = new Collection([$transA, $transB]);
- $transC = new Transaction;
- $transC->transaction_currency_id = 3;
- $transC->transaction_category_name = null;
- $transC->transaction_category_id = 0;
- $transC->transaction_journal_category_name = 'Category3';
- $transC->transaction_journal_category_id = 3;
- $transC->transaction_currency_symbol = 'A';
- $transC->transaction_currency_dp = 2;
- $transC->transaction_amount = '100';
- $secondCollection = new Collection([$transC]);
-
- // mock collector for spentByCategory and earnedByCategory (complex)
- $collector = $this->mock(TransactionCollectorInterface::class);
- // dont care about any calls, just return a default set of fake transactions:
- $collector->shouldReceive('setRange')->andReturnSelf();
- $collector->shouldReceive('setTypes')->andReturnSelf();
- $collector->shouldReceive('setAccounts')->andReturnSelf();
- $collector->shouldReceive('setOpposingAccounts')->andReturnSelf();
- $collector->shouldReceive('withCategoryInformation')->andReturnSelf();
- $collector->shouldReceive('getTransactions')->andReturn($collection, $secondCollection);
- //$collector->shouldReceive('')->andReturnSelf();
+ $collector->shouldReceive('setRange')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('setTypes')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('setAccounts')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('withCategoryInformation')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('getExtractedJournals')->andReturn([$one], [$two])->atLeast()->once();
$this->be($this->user());
$response = $this->get(route('report-data.expense.category', ['1', $expense->id, '20170101', '20170131']));
@@ -170,45 +134,27 @@ class ExpenseControllerTest extends TestCase
*/
public function testSpent(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
-
- return;
- $expense = $this->user()->accounts()->where('account_type_id', 4)->first();
- $revenue = $this->user()->accounts()->where('account_type_id', 5)->first();
$repository = $this->mock(AccountRepositoryInterface::class);
$fiscalHelper = $this->mock(FiscalHelperInterface::class);
+ $collector = $this->mock(GroupCollectorInterface::class);
+
+ $expense = $this->getRandomExpense();
+ $revenue = $this->getRandomRevenue();
$date = new Carbon;
+ $transactions = [$this->getRandomWithdrawalAsArray()];
+
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('lastActivity')->atLeast()->once();
+
$fiscalHelper->shouldReceive('endOfFiscalYear')->atLeast()->once()->andReturn($date);
$fiscalHelper->shouldReceive('startOfFiscalYear')->atLeast()->once()->andReturn($date);
$repository->shouldReceive('findByName')->once()->withArgs([$expense->name, [AccountType::REVENUE]])->andReturn($revenue);
- // fake collection:
- $transA = new Transaction;
- $transA->transaction_currency_id = 1;
- $transA->transaction_category_name = 'Category';
- $transA->transaction_category_id = 1;
- $transA->transaction_currency_symbol = 'A';
- $transA->transaction_currency_dp = 2;
- $transA->transaction_amount = '100';
- $transB = new Transaction;
- $transB->transaction_currency_id = 2;
- $transB->transaction_category_name = null;
- $transB->transaction_category_id = 0;
- $transB->transaction_journal_budget_name = 'Category2';
- $transB->transaction_journal_budget_id = 2;
- $transB->transaction_currency_symbol = 'A';
- $transB->transaction_currency_dp = 2;
- $transB->transaction_amount = '100';
- $collection = new Collection([$transA, $transB]);
-
- // mock collector for spentInPeriod and earnedInPeriod (complex)
- $collector = $this->mock(TransactionCollectorInterface::class);
- // dont care about any calls, just return a default set of fake transactions:
- $collector->shouldReceive('setRange')->andReturnSelf();
- $collector->shouldReceive('setTypes')->andReturnSelf();
- $collector->shouldReceive('setAccounts')->andReturnSelf();
- $collector->shouldReceive('setOpposingAccounts')->andReturnSelf();
- $collector->shouldReceive('getTransactions')->andReturn($collection);
+ $collector->shouldReceive('setRange')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('setTypes')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('setAccounts')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('getExtractedJournals')->andReturn($transactions)->atLeast()->once();
+ Amount::shouldReceive('formatAnything')->atLeast()->once()->andReturn('-100');
$this->be($this->user());
$response = $this->get(route('report-data.expense.spent', ['1', $expense->id, '20170101', '20170131']));
@@ -220,47 +166,29 @@ class ExpenseControllerTest extends TestCase
*/
public function testTopExpense(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
-
- return;
- $expense = $this->user()->accounts()->where('account_type_id', 4)->first();
- $revenue = $this->user()->accounts()->where('account_type_id', 5)->first();
+ Log::debug(sprintf('Now in test %s', __METHOD__));
$repository = $this->mock(AccountRepositoryInterface::class);
$fiscalHelper = $this->mock(FiscalHelperInterface::class);
+ $collector = $this->mock(GroupCollectorInterface::class);
+
+ $expense = $this->getRandomExpense();
+ $revenue = $this->getRandomRevenue();
$date = new Carbon;
+ $transactions = [$this->getRandomWithdrawalAsArray()];
+
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('lastActivity')->atLeast()->once();
+
$fiscalHelper->shouldReceive('endOfFiscalYear')->atLeast()->once()->andReturn($date);
$fiscalHelper->shouldReceive('startOfFiscalYear')->atLeast()->once()->andReturn($date);
$repository->shouldReceive('findByName')->once()->withArgs([$expense->name, [AccountType::REVENUE]])->andReturn($revenue);
- // fake collection:
- $transA = new Transaction;
- $transA->transaction_currency_id = 1;
- $transA->transaction_category_name = 'Category';
- $transA->transaction_category_id = 1;
- $transA->transaction_currency_symbol = 'A';
- $transA->transaction_currency_dp = 2;
- $transA->transaction_amount = '100';
- $transA->opposing_account_id = $expense->id;
- $transB = new Transaction;
- $transB->transaction_currency_id = 2;
- $transB->transaction_category_name = null;
- $transB->transaction_category_id = 0;
- $transB->transaction_journal_budget_name = 'Category2';
- $transB->transaction_journal_budget_id = 2;
- $transB->transaction_currency_symbol = 'A';
- $transB->transaction_currency_dp = 2;
- $transB->transaction_amount = '100';
- $transB->opposing_account_id = $expense->id;
- $collection = new Collection([$transA, $transB]);
+ $collector->shouldReceive('setRange')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('setTypes')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('withAccountInformation')->andReturnSelf()->atLeast()->once();
- // mock collector for topExpense (complex)
- $collector = $this->mock(TransactionCollectorInterface::class);
- // dont care about any calls, just return a default set of fake transactions:
- $collector->shouldReceive('setRange')->andReturnSelf();
- $collector->shouldReceive('setTypes')->andReturnSelf();
- $collector->shouldReceive('setAccounts')->andReturnSelf();
- $collector->shouldReceive('setOpposingAccounts')->andReturnSelf();
- $collector->shouldReceive('getTransactions')->andReturn($collection);
+ $collector->shouldReceive('setAccounts')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('getExtractedJournals')->andReturn($transactions)->atLeast()->once();
$this->be($this->user());
$response = $this->get(route('report-data.expense.expenses', ['1', $expense->id, '20170101', '20170131']));
@@ -272,46 +200,28 @@ class ExpenseControllerTest extends TestCase
*/
public function testTopIncome(): void
{
- $this->markTestIncomplete('Needs to be rewritten for v4.8.0');
-
- return;
- $expense = $this->user()->accounts()->where('account_type_id', 4)->first();
- $revenue = $this->user()->accounts()->where('account_type_id', 5)->first();
+ Log::debug(sprintf('Now in test %s', __METHOD__));
$repository = $this->mock(AccountRepositoryInterface::class);
$fiscalHelper = $this->mock(FiscalHelperInterface::class);
+ $collector = $this->mock(GroupCollectorInterface::class);
+
+ $expense = $this->getRandomExpense();
+ $revenue = $this->getRandomRevenue();
$date = new Carbon;
+ $transactions = [$this->getRandomWithdrawalAsArray()];
+
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('lastActivity')->atLeast()->once();
+
$fiscalHelper->shouldReceive('endOfFiscalYear')->atLeast()->once()->andReturn($date);
$fiscalHelper->shouldReceive('startOfFiscalYear')->atLeast()->once()->andReturn($date);
$repository->shouldReceive('findByName')->once()->withArgs([$expense->name, [AccountType::REVENUE]])->andReturn($revenue);
- // fake collection:
- $transA = new Transaction;
- $transA->transaction_currency_id = 1;
- $transA->transaction_category_name = 'Category';
- $transA->transaction_category_id = 1;
- $transA->transaction_currency_symbol = 'A';
- $transA->transaction_currency_dp = 2;
- $transA->transaction_amount = '100';
- $transA->opposing_account_id = $expense->id;
- $transB = new Transaction;
- $transB->transaction_currency_id = 2;
- $transB->transaction_category_name = null;
- $transB->transaction_category_id = 0;
- $transB->transaction_journal_budget_name = 'Category2';
- $transB->transaction_journal_budget_id = 2;
- $transB->transaction_currency_symbol = 'A';
- $transB->transaction_currency_dp = 2;
- $transB->transaction_amount = '100';
- $transB->opposing_account_id = $expense->id;
- $collection = new Collection([$transA, $transB]);
-
- $collector = $this->mock(TransactionCollectorInterface::class);
- $collector->shouldReceive('setRange')->andReturnSelf();
- $collector->shouldReceive('setTypes')->andReturnSelf();
- $collector->shouldReceive('setAccounts')->andReturnSelf();
- $collector->shouldReceive('setOpposingAccounts')->andReturnSelf();
- $collector->shouldReceive('getTransactions')->andReturn($collection);
- //$collector->shouldReceive('')->andReturnSelf();
+ $collector->shouldReceive('setRange')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('setTypes')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('setAccounts')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('withAccountInformation')->andReturnSelf()->atLeast()->once();
+ $collector->shouldReceive('getExtractedJournals')->andReturn($transactions)->atLeast()->once();
$this->be($this->user());
diff --git a/tests/Feature/Controllers/Rule/CreateControllerTest.php b/tests/Feature/Controllers/Rule/CreateControllerTest.php
index 9d7a6820ce..3a92054183 100644
--- a/tests/Feature/Controllers/Rule/CreateControllerTest.php
+++ b/tests/Feature/Controllers/Rule/CreateControllerTest.php
@@ -33,6 +33,7 @@ use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use Log;
use Mockery;
+use Preferences;
use Tests\TestCase;
/**
@@ -56,12 +57,13 @@ class CreateControllerTest extends TestCase
public function testCreate(): void
{
// mock stuff
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$billRepos = $this->mock(BillRepositoryInterface::class);
$ruleRepos = $this->mock(RuleRepositoryInterface::class);
$ruleGroupRepos = $this->mock(RuleGroupRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
+
+ $this->mockDefaultSession();
+ $this->mockIntroPreference('shown_demo_rules_create');
$ruleGroupRepos->shouldReceive('count')->atLeast()->once()->andReturn(1);
$ruleRepos->shouldReceive('count')->atLeast()->once()->andReturn(1);
@@ -80,17 +82,17 @@ class CreateControllerTest extends TestCase
public function testCreateFromBill(): void
{
// mock stuff
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$billRepos = $this->mock(BillRepositoryInterface::class);
$ruleRepos = $this->mock(RuleRepositoryInterface::class);
$ruleGroupRepos = $this->mock(RuleGroupRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
+
$ruleGroupRepos->shouldReceive('count')->atLeast()->once()->andReturn(1);
$ruleRepos->shouldReceive('count')->atLeast()->once()->andReturn(1);
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
$this->be($this->user());
$response = $this->get(route('rules.create-from-bill', [1, 1]));
@@ -114,17 +116,17 @@ class CreateControllerTest extends TestCase
$this->session(['_old_input' => $old]);
// mock stuff
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$ruleRepos = $this->mock(RuleRepositoryInterface::class);
$ruleGroupRepos = $this->mock(RuleGroupRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
+ $this->mockIntroPreference('shown_demo_rules_create');
+
$ruleGroupRepos->shouldReceive('count')->atLeast()->once()->andReturn(1);
$ruleRepos->shouldReceive('count')->atLeast()->once()->andReturn(1);
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
-
$this->be($this->user());
$response = $this->get(route('rules.create', [1]));
$response->assertStatus(200);
@@ -139,12 +141,13 @@ class CreateControllerTest extends TestCase
{
// mock stuff
$repository = $this->mock(RuleRepositoryInterface::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$ruleGroupRepos = $this->mock(RuleGroupRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
$repository->shouldReceive('store')->andReturn(new Rule);
$this->session(['rules.create.uri' => 'http://localhost']);
diff --git a/tests/Feature/Controllers/Rule/DeleteControllerTest.php b/tests/Feature/Controllers/Rule/DeleteControllerTest.php
index e8ef6e0aa9..5f2cde8962 100644
--- a/tests/Feature/Controllers/Rule/DeleteControllerTest.php
+++ b/tests/Feature/Controllers/Rule/DeleteControllerTest.php
@@ -30,6 +30,7 @@ use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use Log;
use Mockery;
+use Preferences;
use Tests\TestCase;
/**
@@ -54,13 +55,14 @@ class DeleteControllerTest extends TestCase
public function testDelete(): void
{
// mock stuff
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$ruleRepos = $this->mock(RuleRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
+
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
+
$this->be($this->user());
$response = $this->get(route('rules.delete', [1]));
@@ -75,10 +77,11 @@ class DeleteControllerTest extends TestCase
{
// mock stuff
$repository = $this->mock(RuleRepositoryInterface::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
$repository->shouldReceive('destroy');
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
$this->session(['rules.delete.uri' => 'http://localhost']);
$this->be($this->user());
$response = $this->post(route('rules.destroy', [1]));
diff --git a/tests/Feature/Controllers/Rule/EditControllerTest.php b/tests/Feature/Controllers/Rule/EditControllerTest.php
index bf8edd854b..dc9e96cf6f 100644
--- a/tests/Feature/Controllers/Rule/EditControllerTest.php
+++ b/tests/Feature/Controllers/Rule/EditControllerTest.php
@@ -33,6 +33,7 @@ use FireflyIII\Repositories\User\UserRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
use Mockery;
+use Preferences;
use Tests\TestCase;
/**
@@ -57,12 +58,11 @@ class EditControllerTest extends TestCase
// mock stuff
$groupRepos = $this->mock(RuleGroupRepositoryInterface::class);
$repository = $this->mock(RuleRepositoryInterface::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
$repository->shouldReceive('getPrimaryTrigger')->andReturn(new Rule);
$groupRepos->shouldReceive('get')->andReturn(new Collection);
@@ -90,11 +90,11 @@ class EditControllerTest extends TestCase
// mock stuff
$groupRepos = $this->mock(RuleGroupRepositoryInterface::class);
$repository = $this->mock(RuleRepositoryInterface::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
+ $this->mockDefaultSession();
+
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
$repository->shouldReceive('getPrimaryTrigger')->andReturn(new Rule);
$groupRepos->shouldReceive('get')->andReturn(new Collection);
@@ -112,11 +112,12 @@ class EditControllerTest extends TestCase
{
// mock stuff
$repository = $this->mock(RuleRepositoryInterface::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
- $rule = Rule::find(1);
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
+
+ $this->mockDefaultSession();
+ Preferences::shouldReceive('mark')->atLeast()->once();
+
$repository->shouldReceive('update');
$data = [
diff --git a/tests/Feature/Controllers/Rule/IndexControllerTest.php b/tests/Feature/Controllers/Rule/IndexControllerTest.php
index 00f3c36e22..0d8850cc97 100644
--- a/tests/Feature/Controllers/Rule/IndexControllerTest.php
+++ b/tests/Feature/Controllers/Rule/IndexControllerTest.php
@@ -59,11 +59,11 @@ class IndexControllerTest extends TestCase
{
// mock stuff
$repository = $this->mock(RuleRepositoryInterface::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$ruleGroupRepos = $this->mock(RuleGroupRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
+
$repository->shouldReceive('moveDown');
+ $this->mockDefaultSession();
$this->be($this->user());
@@ -81,11 +81,12 @@ class IndexControllerTest extends TestCase
// mock stuff
$repository = $this->mock(RuleRepositoryInterface::class);
$ruleGroupRepos = $this->mock(RuleGroupRepositoryInterface::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
+ $this->mockIntroPreference('shown_demo_rules_index');
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
+
$ruleGroupRepos->shouldReceive('count')->andReturn(0);
$ruleGroupRepos->shouldReceive('store');
$repository->shouldReceive('getFirstRuleGroup')->andReturn(new RuleGroup);
@@ -106,11 +107,10 @@ class IndexControllerTest extends TestCase
{
// mock stuff
$repository = $this->mock(RuleRepositoryInterface::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$ruleGroupRepos = $this->mock(RuleGroupRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
$data = ['actions' => [1, 2, 3]];
$repository->shouldReceive('reorderRuleActions')->once();
@@ -127,11 +127,10 @@ class IndexControllerTest extends TestCase
{
// mock stuff
$repository = $this->mock(RuleRepositoryInterface::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$ruleGroupRepos = $this->mock(RuleGroupRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
$data = ['triggers' => [1, 2, 3]];
$repository->shouldReceive('reorderRuleTriggers')->once();
@@ -148,12 +147,11 @@ class IndexControllerTest extends TestCase
{
// mock stuff
$repository = $this->mock(RuleRepositoryInterface::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$ruleGroupRepos = $this->mock(RuleGroupRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
$repository->shouldReceive('moveUp');
$this->be($this->user());
diff --git a/tests/Feature/Controllers/Rule/SelectControllerTest.php b/tests/Feature/Controllers/Rule/SelectControllerTest.php
index 90d617b587..fbe53a9900 100644
--- a/tests/Feature/Controllers/Rule/SelectControllerTest.php
+++ b/tests/Feature/Controllers/Rule/SelectControllerTest.php
@@ -63,6 +63,7 @@ class SelectControllerTest extends TestCase
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$repository = $this->mock(RuleRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
$this->session(['first' => new Carbon('2010-01-01')]);
$accountRepos->shouldReceive('getAccountsById')->andReturn(new Collection([$account]));
@@ -81,7 +82,7 @@ class SelectControllerTest extends TestCase
Queue::assertPushed(
ExecuteRuleOnExistingTransactions::class, function (Job $job) {
- return $job->getRule()->id === 1;
+ return 1=== $job->getRule()->id;
}
);
}
@@ -93,6 +94,7 @@ class SelectControllerTest extends TestCase
{
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
+ $this->mockDefaultSession();
$userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->atLeast()->once()->andReturn(true);
$accountRepos->shouldReceive('getAccountsByType')->andReturn(new Collection);
@@ -119,11 +121,9 @@ class SelectControllerTest extends TestCase
// mock stuff
$matcher = $this->mock(TransactionMatcher::class);
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
$accountRepos = $this->mock(AccountRepositoryInterface::class);
-
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
+ $this->mockDefaultSession();
$matcher->shouldReceive('setStrict')->once()->withArgs([false])->andReturnSelf();
$matcher->shouldReceive('setTriggeredLimit')->withArgs([10])->andReturnSelf()->once();
@@ -144,11 +144,12 @@ class SelectControllerTest extends TestCase
{
$matcher = $this->mock(TransactionMatcher::class);
$accountRepos = $this->mock(AccountRepositoryInterface::class);
+ $this->mockDefaultSession();
$matcher->shouldReceive('setTriggeredLimit')->withArgs([10])->andReturnSelf()->once();
$matcher->shouldReceive('setSearchLimit')->withArgs([200])->andReturnSelf()->once();
$matcher->shouldReceive('setRule')->andReturnSelf()->once();
- $matcher->shouldReceive('findTransactionsByRule')->andReturn(new Collection);
+ $matcher->shouldReceive('findTransactionsByRule')->andReturn([]);
$this->be($this->user());
$response = $this->get(route('rules.test-triggers-rule', [1]));
@@ -163,11 +164,9 @@ class SelectControllerTest extends TestCase
*/
public function testTestTriggersError(): void
{
- $journalRepos = $this->mock(JournalRepositoryInterface::class);
$userRepos = $this->mock(UserRepositoryInterface::class);
$accountRepos = $this->mock(AccountRepositoryInterface::class);
-
- $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal);
+ $this->mockDefaultSession();
$this->be($this->user());
$uri = route('rules.test-triggers');
diff --git a/tests/TestCase.php b/tests/TestCase.php
index 787fd9f7d0..fd1147920e 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -30,7 +30,6 @@ use DB;
use Exception;
use FireflyConfig;
use FireflyIII\Exceptions\FireflyException;
-
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget;
@@ -167,7 +166,9 @@ abstract class TestCase extends BaseTestCase
'currency_decimal_places' => $euro->decimal_places,
'amount' => '-30',
'budget_id' => $budget->id,
+ 'budget_name' => $budget->name,
'category_id' => $category->id,
+ 'category_name' => $category->name,
];
}
diff --git a/tests/Unit/Console/Commands/Upgrade/TransferCurrenciesCorrectionsTest.php b/tests/Unit/Console/Commands/Upgrade/TransferCurrenciesCorrectionsTest.php
index 65b36997e0..5f834e4e5e 100644
--- a/tests/Unit/Console/Commands/Upgrade/TransferCurrenciesCorrectionsTest.php
+++ b/tests/Unit/Console/Commands/Upgrade/TransferCurrenciesCorrectionsTest.php
@@ -491,25 +491,35 @@ class TransferCurrenciesCorrectionsTest extends TestCase
}
/**
- * Basic test. Source transaction has bad currency.
+ * Basic test. Source transaction has bad currency, and this must be fixed.
+ *
+ * TODO something in this test is too random, and it fails. Not sure why.
*
* @covers \FireflyIII\Console\Commands\Upgrade\TransferCurrenciesCorrections
*/
public function testHandleTransferBadDestCurrency(): void
{
-
+ Log::warning(sprintf('Now in test %s.', __METHOD__));
$accountRepos = $this->mock(AccountRepositoryInterface::class);
$currencyRepos = $this->mock(CurrencyRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class);
$transfer = $this->getRandomTransfer();
$euro = $this->getEuro();
-
+ $dollar = $this->getDollar();
// get destination transaction and remove currency:
+ $transfer->transaction_currency_id = $euro->id;
+ $transfer->save();
+
+ Log::debug(sprintf('Gave transfer #%d currency EUR', $transfer->id));
+
+
/** @var Transaction $destination */
$destination = $transfer->transactions()->where('amount', '>', 0)->first();
- $destination->transaction_currency_id = 2;
+ $destination->transaction_currency_id = $dollar->id;
$destination->save();
+ Log::debug(sprintf('Gave transaction #%d currency USD', $destination->id));
+
// mock calls:
$journalRepos->shouldReceive('getAllJournals')
->withArgs([[TransactionType::TRANSFER]])
@@ -518,12 +528,10 @@ class TransferCurrenciesCorrectionsTest extends TestCase
// account repos
$accountRepos->shouldReceive('getMetaValue')
->atLeast()->once()
- ->withArgs([Mockery::any(), 'currency_id'])->andReturn('1');
+ ->withArgs([Mockery::any(), 'currency_id'])->andReturn((string)$euro->id);
// currency repos
- $currencyRepos->shouldReceive('findNull')
- ->atLeast()->once()
- ->withArgs([1])->andReturn($euro);
+ $currencyRepos->shouldReceive('findNull')->atLeast()->once()->withArgs([$euro->id])->andReturn($euro);
// configuration
$false = new Configuration;
@@ -536,7 +544,7 @@ class TransferCurrenciesCorrectionsTest extends TestCase
->assertExitCode(0);
// assume problem is fixed:
- $this->assertCount(1, Transaction::where('id', $destination->id)->where('transaction_currency_id', 1)->get());
+ $this->assertCount(1, Transaction::where('id', $destination->id)->where('transaction_currency_id', $euro->id)->get());
}
}
\ No newline at end of file
diff --git a/tests/Unit/Factory/RecurrenceFactoryTest.php b/tests/Unit/Factory/RecurrenceFactoryTest.php
index ab5e465855..e1c92bcb00 100644
--- a/tests/Unit/Factory/RecurrenceFactoryTest.php
+++ b/tests/Unit/Factory/RecurrenceFactoryTest.php
@@ -26,6 +26,7 @@ namespace Tests\Unit\Factory;
use Amount;
use Carbon\Carbon;
+use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\AccountFactory;
use FireflyIII\Factory\BudgetFactory;
use FireflyIII\Factory\CategoryFactory;
@@ -831,8 +832,13 @@ class RecurrenceFactoryTest extends TestCase
/** @var RecurrenceFactory $factory */
$factory = app(RecurrenceFactory::class);
$factory->setUser($this->user());
-
- $result = $factory->create($data);
+ $result = null;
+ try {
+ $result = $factory->create($data);
+ } catch (FireflyException $e) {
+ $this->assertEquals('Cannot make a recurring transaction of type "bad type"', $e->getMessage());
+ $this->assertTrue(true);
+ }
$this->assertNull($result);
}