From 5722622251d8faed21741089b3b786a2fdbbf937 Mon Sep 17 00:00:00 2001 From: James Cole Date: Mon, 30 Oct 2017 17:28:43 +0100 Subject: [PATCH] Modify search for #963 --- app/Helpers/Collector/JournalCollector.php | 104 +++++++++++++++++- .../Collector/JournalCollectorInterface.php | 35 ++++++ app/Http/Controllers/SearchController.php | 3 +- app/Support/Search/Modifier.php | 37 +------ app/Support/Search/Search.php | 49 +++++++++ 5 files changed, 188 insertions(+), 40 deletions(-) diff --git a/app/Helpers/Collector/JournalCollector.php b/app/Helpers/Collector/JournalCollector.php index ce23a994cd..a228f15ec0 100644 --- a/app/Helpers/Collector/JournalCollector.php +++ b/app/Helpers/Collector/JournalCollector.php @@ -133,7 +133,7 @@ class JournalCollector implements JournalCollectorInterface public function addFilter(string $filter): JournalCollectorInterface { $interfaces = class_implements($filter); - if (in_array(FilterInterface::class, $interfaces) && !in_array($filter, $this->filters) ) { + if (in_array(FilterInterface::class, $interfaces) && !in_array($filter, $this->filters)) { Log::debug(sprintf('Enabled filter %s', $filter)); $this->filters[] = $filter; } @@ -141,6 +141,78 @@ class JournalCollector implements JournalCollectorInterface return $this; } + /** + * @param string $amount + * + * @return JournalCollectorInterface + */ + public function amountIs(string $amount): JournalCollectorInterface + { + $this->query->where( + function (EloquentBuilder $q) use ($amount) { + $q->where('transactions.amount', $amount); + $q->orWhere('transactions.amount', bcmul($amount, '-1')); + } + ); + + return $this; + } + + /** + * @param string $amount + * + * @return JournalCollectorInterface + */ + public function amountLess(string $amount): JournalCollectorInterface + { + $this->query->where( + function (EloquentBuilder $q1) use ($amount) { + $q1->where( + function (EloquentBuilder $q2) use ($amount) { + // amount < 0 and .amount > -$amount + $amount = bcmul($amount,'-1'); + $q2->where('transactions.amount', '<', 0)->where('transactions.amount', '>', $amount); + } + ) + ->orWhere( + function (EloquentBuilder $q3) use ($amount) { + // amount > 0 and .amount < $amount + $q3->where('transactions.amount', '>', 0)->where('transactions.amount', '<', $amount); + } + ); + } + ); + + return $this; + } + + /** + * @param string $amount + * + * @return JournalCollectorInterface + */ + public function amountMore(string $amount): JournalCollectorInterface + { + $this->query->where( + function (EloquentBuilder $q1) use ($amount) { + $q1->where( + function (EloquentBuilder $q2) use ($amount) { + // amount < 0 and .amount < -$amount + $amount = bcmul($amount,'-1'); + $q2->where('transactions.amount', '<', 0)->where('transactions.amount', '<', $amount); + } + ) + ->orWhere( + function (EloquentBuilder $q3) use ($amount) { + // amount > 0 and .amount > $amount + $q3->where('transactions.amount', '>', 0)->where('transactions.amount', '>', $amount); + } + ); + } + ); + return $this; + } + /** * @return int * @throws FireflyException @@ -251,6 +323,20 @@ class JournalCollector implements JournalCollectorInterface return $this; } + /** + * @param Carbon $after + * + * @return JournalCollectorInterface + */ + public function setAfter(Carbon $after): JournalCollectorInterface + { + $afterStr = $after->format('Y-m-d'); + $this->query->where('transaction_journals.date', '>=', $afterStr); + Log::debug(sprintf('JournalCollector range is now after %s (inclusive)', $afterStr)); + + return $this; + } + /** * @return JournalCollectorInterface */ @@ -273,6 +359,20 @@ class JournalCollector implements JournalCollectorInterface return $this; } + /** + * @param Carbon $before + * + * @return JournalCollectorInterface + */ + public function setBefore(Carbon $before): JournalCollectorInterface + { + $beforeStr = $before->format('Y-m-d'); + $this->query->where('transaction_journals.date', '<=', $beforeStr); + Log::debug(sprintf('JournalCollector range is now before %s (inclusive)', $beforeStr)); + + return $this; + } + /** * @param Collection $bills * @@ -523,7 +623,7 @@ class JournalCollector implements JournalCollectorInterface ->orderBy('transaction_journals.order', 'ASC') ->orderBy('transaction_journals.id', 'DESC') ->orderBy('transaction_journals.description', 'DESC') - ->orderBy('transactions.amount','DESC'); + ->orderBy('transactions.amount', 'DESC'); $this->query = $query; diff --git a/app/Helpers/Collector/JournalCollectorInterface.php b/app/Helpers/Collector/JournalCollectorInterface.php index 9844dc1231..f6fafd77f4 100644 --- a/app/Helpers/Collector/JournalCollectorInterface.php +++ b/app/Helpers/Collector/JournalCollectorInterface.php @@ -45,6 +45,27 @@ interface JournalCollectorInterface */ public function addFilter(string $filter): JournalCollectorInterface; + /** + * @param string $amount + * + * @return JournalCollectorInterface + */ + public function amountMore(string $amount): JournalCollectorInterface; + + /** + * @param string $amount + * + * @return JournalCollectorInterface + */ + public function amountLess(string $amount): JournalCollectorInterface; + + /** + * @param string $amount + * + * @return JournalCollectorInterface + */ + public function amountIs(string $amount): JournalCollectorInterface; + /** * @return int */ @@ -74,11 +95,25 @@ interface JournalCollectorInterface */ public function setAccounts(Collection $accounts): JournalCollectorInterface; + /** + * @param Carbon $after + * + * @return JournalCollectorInterface + */ + public function setAfter(Carbon $after): JournalCollectorInterface; + /** * @return JournalCollectorInterface */ public function setAllAssetAccounts(): JournalCollectorInterface; + /** + * @param Carbon $before + * + * @return JournalCollectorInterface + */ + public function setBefore(Carbon $before): JournalCollectorInterface; + /** * @param Collection $bills * diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index ac51869007..c2fdf179db 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -82,7 +82,7 @@ class SearchController extends Controller $cache->addProperty($fullQuery); if ($cache->has()) { - $transactions = $cache->get(); + //$transactions = $cache->get(); } if (!$cache->has()) { @@ -93,7 +93,6 @@ class SearchController extends Controller $cache->store($transactions); } - $html = view('search.search', compact('transactions'))->render(); return Response::json(['count' => $transactions->count(), 'html' => $html]); diff --git a/app/Support/Search/Modifier.php b/app/Support/Search/Modifier.php index 89ee78d544..a7386efce0 100644 --- a/app/Support/Search/Modifier.php +++ b/app/Support/Search/Modifier.php @@ -61,24 +61,8 @@ class Modifier */ public static function apply(array $modifier, Transaction $transaction): bool { + $res = true; switch ($modifier['type']) { - default: - throw new FireflyException(sprintf('Search modifier "%s" is not (yet) supported. Sorry!', $modifier['type'])); - case 'amount': - case 'amount_is': - $res = self::amountCompare($transaction, $modifier['value'], 0); - Log::debug(sprintf('Amount is %s? %s', $modifier['value'], var_export($res, true))); - break; - case 'amount_min': - case 'amount_less': - $res = self::amountCompare($transaction, $modifier['value'], 1); - Log::debug(sprintf('Amount less than %s? %s', $modifier['value'], var_export($res, true))); - break; - case 'amount_max': - case 'amount_more': - $res = self::amountCompare($transaction, $modifier['value'], -1); - Log::debug(sprintf('Amount more than %s? %s', $modifier['value'], var_export($res, true))); - break; case 'source': $res = self::stringCompare($transaction->account_name, $modifier['value']); Log::debug(sprintf('Source is %s? %s', $modifier['value'], var_export($res, true))); @@ -99,25 +83,6 @@ class Modifier $res = self::stringCompare(strval($transaction->bill_name), $modifier['value']); Log::debug(sprintf('Bill is %s? %s', $modifier['value'], var_export($res, true))); break; - case 'type': - $res = self::stringCompare($transaction->transaction_type_type, $modifier['value']); - Log::debug(sprintf('Transaction type is %s? %s', $modifier['value'], var_export($res, true))); - break; - case 'date': - case 'on': - $res = self::sameDate($transaction->date, $modifier['value']); - Log::debug(sprintf('Date same as %s? %s', $modifier['value'], var_export($res, true))); - break; - case 'date_before': - case 'before': - $res = self::dateBefore($transaction->date, $modifier['value']); - Log::debug(sprintf('Date before %s? %s', $modifier['value'], var_export($res, true))); - break; - case 'date_after': - case 'after': - $res = self::dateAfter($transaction->date, $modifier['value']); - Log::debug(sprintf('Date before %s? %s', $modifier['value'], var_export($res, true))); - break; } return $res; diff --git a/app/Support/Search/Search.php b/app/Support/Search/Search.php index 0f76ad9a74..d057e08636 100644 --- a/app/Support/Search/Search.php +++ b/app/Support/Search/Search.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Search; +use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Helpers\Filter\InternalTransferFilter; @@ -121,6 +122,10 @@ class Search implements SearchInterface if ($this->hasModifiers()) { $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); } + + // some modifiers can be applied to the collector directly. + $collector = $this->applyModifiers($collector); + $collector->removeFilter(InternalTransferFilter::class); $set = $collector->getPaginatedJournals()->getCollection(); @@ -186,6 +191,50 @@ class Search implements SearchInterface $this->user = $user; } + private function applyModifiers(JournalCollectorInterface $collector): JournalCollectorInterface + { + foreach ($this->modifiers as $modifier) { + switch ($modifier['type']) { + case 'amount_is': + case 'amount': + $amount = app('steam')->positive(strval($modifier['value'])); + $collector->amountIs($amount); + break; + case 'amount_min': + case 'amount_less': + $amount = app('steam')->positive(strval($modifier['value'])); + $collector->amountLess($amount); + break; + case 'amount_max': + case 'amount_more': + $amount = app('steam')->positive(strval($modifier['value'])); + $collector->amountMore($amount); + break; + case 'type': + $collector->setTypes([ucfirst($modifier['value'])]); + break; + case 'date': + case 'on': + $start = new Carbon($modifier['value']); + $collector->setRange($start, $start); + break; + case 'date_before': + case 'before': + $before = new Carbon($modifier['value']); + $collector->setBefore($before); + break; + case 'date_after': + case 'after': + $after = new Carbon($modifier['value']); + $collector->setBefore($after); + break; + } + } + + + return $collector; + } + /** * @param string $string */