From 980120f1bd2de7bccd9a6aa6d82fd4d54c3baa0a Mon Sep 17 00:00:00 2001 From: James Cole Date: Sun, 27 Mar 2022 16:03:50 +0200 Subject: [PATCH] Update search. --- .../Collector/Extensions/AmountCollection.php | 57 +++ .../Collector/Extensions/MetaCollection.php | 144 +++--- .../Collector/Extensions/TimeCollection.php | 459 +++++++++++++++++- app/Helpers/Collector/GroupCollector.php | 63 ++- .../Collector/GroupCollectorInterface.php | 228 ++++++++- app/Support/Search/OperatorQuerySearch.php | 349 ++++++++++++- config/search.php | 1 - resources/lang/en_US/firefly.php | 33 +- resources/views/list/groups.twig | 4 +- 9 files changed, 1164 insertions(+), 174 deletions(-) diff --git a/app/Helpers/Collector/Extensions/AmountCollection.php b/app/Helpers/Collector/Extensions/AmountCollection.php index 972b7e9342..99fe7d1742 100644 --- a/app/Helpers/Collector/Extensions/AmountCollection.php +++ b/app/Helpers/Collector/Extensions/AmountCollection.php @@ -86,4 +86,61 @@ trait AmountCollection return $this; } + + /** + * Get transactions with a specific foreign amount. + * + * @param string $amount + * + * @return GroupCollectorInterface + */ + public function foreignAmountIs(string $amount): GroupCollectorInterface + { + $this->query->where( + static function (EloquentBuilder $q) use ($amount) { + $q->whereNotNull('source.foreign_amount'); + $q->where('source.foreign_amount', app('steam')->negative($amount)); + } + ); + + return $this; + } + + /** + * Get transactions where the amount is less than. + * + * @param string $amount + * + * @return GroupCollectorInterface + */ + public function foreignAmountLess(string $amount): GroupCollectorInterface + { + $this->query->where( + function (EloquentBuilder $q) use ($amount) { + $q->whereNotNull('destination.foreign_amount'); + $q->where('destination.foreign_amount', '<=', app('steam')->positive($amount)); + } + ); + + return $this; + } + + /** + * Get transactions where the amount is more than. + * + * @param string $amount + * + * @return GroupCollectorInterface + */ + public function foreignAmountMore(string $amount): GroupCollectorInterface + { + $this->query->where( + function (EloquentBuilder $q) use ($amount) { + $q->whereNotNull('destination.foreign_amount'); + $q->where('destination.foreign_amount', '>=', app('steam')->positive($amount)); + } + ); + + return $this; + } } diff --git a/app/Helpers/Collector/Extensions/MetaCollection.php b/app/Helpers/Collector/Extensions/MetaCollection.php index a8717bb424..9b42f59aab 100644 --- a/app/Helpers/Collector/Extensions/MetaCollection.php +++ b/app/Helpers/Collector/Extensions/MetaCollection.php @@ -51,6 +51,19 @@ trait MetaCollection return $this; } + /** + * Join table to get tag information. + */ + protected function joinMetaDataTables(): void + { + if (false === $this->hasJoinedMetaTables) { + $this->hasJoinedMetaTables = true; + $this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id'); + $this->fields[] = 'journal_meta.name as meta_name'; + $this->fields[] = 'journal_meta.data as meta_data'; + } + } + /** * @inheritDoc */ @@ -75,75 +88,6 @@ trait MetaCollection return $this; } - /** - * Where has no tags. - * - * @return GroupCollectorInterface - */ - public function hasAnyTag(): GroupCollectorInterface - { - $this->withTagInformation(); - $this->query->whereNotNull('tag_transaction_journal.tag_id'); - - return $this; - } - - /** - * @return GroupCollectorInterface - */ - public function withTagInformation(): GroupCollectorInterface - { - $this->fields[] = 'tags.id as tag_id'; - $this->fields[] = 'tags.tag as tag_name'; - $this->fields[] = 'tags.date as tag_date'; - $this->fields[] = 'tags.description as tag_description'; - $this->fields[] = 'tags.latitude as tag_latitude'; - $this->fields[] = 'tags.longitude as tag_longitude'; - $this->fields[] = 'tags.zoomLevel as tag_zoom_level'; - - $this->joinTagTables(); - - return $this; - } - - /** - * Join table to get tag information. - */ - protected function joinTagTables(): void - { - if (false === $this->hasJoinedTagTables) { - // join some extra tables: - $this->hasJoinedTagTables = true; - $this->query->leftJoin('tag_transaction_journal', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'); - $this->query->leftJoin('tags', 'tag_transaction_journal.tag_id', '=', 'tags.id'); - } - } - - /** - * Join table to get tag information. - */ - protected function joinMetaDataTables(): void - { - if (false === $this->hasJoinedMetaTables) { - $this->hasJoinedMetaTables = true; - $this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id'); - $this->fields[] = 'journal_meta.name as meta_name'; - $this->fields[] = 'journal_meta.data as meta_data'; - } - } - - /** - * @inheritDoc - */ - public function setExternalUrl(string $url): GroupCollectorInterface - { - $this->joinMetaDataTables(); - $this->query->where('journal_meta.name', '=', 'external_url'); - $this->query->where('journal_meta.data', '=', json_encode($url)); - - return $this; - } - /** * @param string $url * @return GroupCollectorInterface @@ -191,6 +135,50 @@ trait MetaCollection return $this; } + /** + * Where has no tags. + * + * @return GroupCollectorInterface + */ + public function hasAnyTag(): GroupCollectorInterface + { + $this->withTagInformation(); + $this->query->whereNotNull('tag_transaction_journal.tag_id'); + + return $this; + } + + /** + * @return GroupCollectorInterface + */ + public function withTagInformation(): GroupCollectorInterface + { + $this->fields[] = 'tags.id as tag_id'; + $this->fields[] = 'tags.tag as tag_name'; + $this->fields[] = 'tags.date as tag_date'; + $this->fields[] = 'tags.description as tag_description'; + $this->fields[] = 'tags.latitude as tag_latitude'; + $this->fields[] = 'tags.longitude as tag_longitude'; + $this->fields[] = 'tags.zoomLevel as tag_zoom_level'; + + $this->joinTagTables(); + + return $this; + } + + /** + * Join table to get tag information. + */ + protected function joinTagTables(): void + { + if (false === $this->hasJoinedTagTables) { + // join some extra tables: + $this->hasJoinedTagTables = true; + $this->query->leftJoin('tag_transaction_journal', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'); + $this->query->leftJoin('tags', 'tag_transaction_journal.tag_id', '=', 'tags.id'); + } + } + /** * @inheritDoc */ @@ -472,11 +460,11 @@ trait MetaCollection /** * @inheritDoc */ - public function setRecurrenceId(string $recurringId): GroupCollectorInterface + public function setExternalUrl(string $url): GroupCollectorInterface { $this->joinMetaDataTables(); - $this->query->where('journal_meta.name', '=', 'recurrence_id'); - $this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($recurringId))); + $this->query->where('journal_meta.name', '=', 'external_url'); + $this->query->where('journal_meta.data', '=', json_encode($url)); return $this; } @@ -494,6 +482,18 @@ trait MetaCollection return $this; } + /** + * @inheritDoc + */ + public function setRecurrenceId(string $recurringId): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'recurrence_id'); + $this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($recurringId))); + + return $this; + } + /** * Limit results to a specific tag. * diff --git a/app/Helpers/Collector/Extensions/TimeCollection.php b/app/Helpers/Collector/Extensions/TimeCollection.php index 22ff48ee29..01ee086e45 100644 --- a/app/Helpers/Collector/Extensions/TimeCollection.php +++ b/app/Helpers/Collector/Extensions/TimeCollection.php @@ -32,25 +32,245 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; */ trait TimeCollection { - + /** + * @param string $day + * @return GroupCollectorInterface + */ public function dayAfter(string $day): GroupCollectorInterface { $this->query->whereDay('transaction_journals.date', '>=', $day); return $this; } + /** + * @param string $day + * @return GroupCollectorInterface + */ public function dayBefore(string $day): GroupCollectorInterface { $this->query->whereDay('transaction_journals.date', '<=', $day); return $this; } + /** + * @param string $day + * @return GroupCollectorInterface + */ public function dayIs(string $day): GroupCollectorInterface { $this->query->whereDay('transaction_journals.date', '=', $day); return $this; } + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function metaDayAfter(string $day, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $day): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $transaction[$field]->day >= (int) $day; + } + } + + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function metaDayBefore(string $day, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $day): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $transaction[$field]->day <= (int) $day; + } + } + + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function metaDayIs(string $day, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $day): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return (int) $day === $transaction[$field]->day; + } + } + + return false; + }; + $this->postFilters[] = $filter; + return $this; + } + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function metaMonthAfter(string $month, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $month): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $transaction[$field]->month >= (int) $month; + } + } + + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function metaMonthBefore(string $month, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $month): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $transaction[$field]->month <= (int) $month; + } + } + + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function metaMonthIs(string $month, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $month): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return (int) $month === $transaction[$field]->month; + } + } + + return false; + }; + $this->postFilters[] = $filter; + return $this; + } + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function metaYearAfter(string $year, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $year): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $transaction[$field]->year >= (int) $year; + } + } + + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function metaYearBefore(string $year, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $year): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $transaction[$field]->year <= (int) $year; + } + } + + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function metaYearIs(string $year, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $year): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $year === (string) $transaction[$field]->year; + } + } + + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $month + * @return GroupCollectorInterface + */ public function monthAfter(string $month): GroupCollectorInterface { $this->query->whereMonth('transaction_journals.date', '>=', $month); @@ -58,6 +278,10 @@ trait TimeCollection } + /** + * @param string $month + * @return GroupCollectorInterface + */ public function monthBefore(string $month): GroupCollectorInterface { $this->query->whereMonth('transaction_journals.date', '<=', $month); @@ -65,11 +289,113 @@ trait TimeCollection } + /** + * @param string $month + * @return GroupCollectorInterface + */ public function monthIs(string $month): GroupCollectorInterface { $this->query->whereMonth('transaction_journals.date', '=', $month); return $this; + } + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function objectDayAfter(string $day, string $field): GroupCollectorInterface + { + $this->query->whereDay(sprintf('transaction_journals.%s', $field), '>=', $day); + return $this; + } + + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function objectDayBefore(string $day, string $field): GroupCollectorInterface + { + $this->query->whereDay(sprintf('transaction_journals.%s', $field), '<=', $day); + return $this; + } + + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function objectDayIs(string $day, string $field): GroupCollectorInterface + { + $this->query->whereDay(sprintf('transaction_journals.%s', $field), '=', $day); + return $this; + } + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function objectMonthAfter(string $month, string $field): GroupCollectorInterface + { + $this->query->whereMonth(sprintf('transaction_journals.%s', $field), '>=', $month); + return $this; + } + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function objectMonthBefore(string $month, string $field): GroupCollectorInterface + { + $this->query->whereMonth(sprintf('transaction_journals.%s', $field), '<=', $month); + return $this; + } + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function objectMonthIs(string $month, string $field): GroupCollectorInterface + { + $this->query->whereMonth(sprintf('transaction_journals.%s', $field), '=', $month); + return $this; + } + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function objectYearAfter(string $year, string $field): GroupCollectorInterface + { + $this->query->whereYear(sprintf('transaction_journals.%s', $field), '>=', $year); + return $this; + } + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function objectYearBefore(string $year, string $field): GroupCollectorInterface + { + $this->query->whereYear(sprintf('transaction_journals.%s', $field), '<=', $year); + return $this; + } + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function objectYearIs(string $year, string $field): GroupCollectorInterface + { + $this->query->whereYear(sprintf('transaction_journals.%s', $field), '=', $year); + return $this; } /** @@ -120,24 +446,60 @@ trait TimeCollection } /** - * Set the start and end time of the results to return. - * - * @param Carbon $start - * @param Carbon $end - * + * @param Carbon $date + * @param string $field * @return GroupCollectorInterface */ - public function setRange(Carbon $start, Carbon $end): GroupCollectorInterface + public function setMetaAfter(Carbon $date, string $field): GroupCollectorInterface { - if ($end < $start) { - [$start, $end] = [$end, $start]; - } - // always got to end of day / start of day for ranges. - $startStr = $start->format('Y-m-d 00:00:00'); - $endStr = $end->format('Y-m-d 23:59:59'); + $this->withMetaDate($field); + $date->startOfDay(); + $filter = function (int $index, array $object) use ($field, $date): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $transaction[$field]->gte($date); + } + } - $this->query->where('transaction_journals.date', '>=', $startStr); - $this->query->where('transaction_journals.date', '<=', $endStr); + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param Carbon $date + * @param string $field + * @return GroupCollectorInterface + */ + public function setMetaBefore(Carbon $date, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $date): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $transaction[$field]->lte($date); + } + } + + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @inheritDoc + */ + public function withMetaDate(string $field): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', $field); + $this->query->whereNotNull('journal_meta.data'); return $this; } @@ -160,13 +522,13 @@ trait TimeCollection $filter = function (int $index, array $object) use ($field, $start, $end): bool { foreach ($object['transactions'] as $transaction) { - if (array_key_exists('interest_date', $transaction) && $transaction['interest_date'] instanceof Carbon + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon ) { - return $transaction['interest_date']->gte($start) && $transaction['interest_date']->lte($end); + return $transaction[$field]->gte($start) && $transaction[$field]->lte($end); } } - return true; + return false; }; $this->postFilters[] = $filter; return $this; @@ -174,13 +536,63 @@ trait TimeCollection } /** - * @inheritDoc + * @param Carbon $date + * @param string $field + * @return GroupCollectorInterface */ - public function withMetaDate(string $field): GroupCollectorInterface + public function setObjectAfter(Carbon $date, string $field): GroupCollectorInterface { - $this->joinMetaDataTables(); - $this->query->where('journal_meta.name', '=', $field); - $this->query->whereNotNull('journal_meta.data'); + $afterStr = $date->format('Y-m-d 00:00:00'); + $this->query->where(sprintf('transaction_journals.%s', $field), '>=', $afterStr); + + return $this; + } + + /** + * @param Carbon $date + * @param string $field + * @return GroupCollectorInterface + */ + public function setObjectBefore(Carbon $date, string $field): GroupCollectorInterface + { + die('a'); + } + + /** + * @param Carbon $start + * @param Carbon $end + * @param string $field + * @return GroupCollectorInterface + */ + public function setObjectRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface + { + $after = $start->format('Y-m-d 00:00:00'); + $before = $end->format('Y-m-d 23:59:59'); + $this->query->where(sprintf('transaction_journals.%s', $field), '>=', $after); + $this->query->where(sprintf('transaction_journals.%s', $field), '<=', $before); + + return $this; + } + + /** + * Set the start and end time of the results to return. + * + * @param Carbon $start + * @param Carbon $end + * + * @return GroupCollectorInterface + */ + public function setRange(Carbon $start, Carbon $end): GroupCollectorInterface + { + if ($end < $start) { + [$start, $end] = [$end, $start]; + } + // always got to end of day / start of day for ranges. + $startStr = $start->format('Y-m-d 00:00:00'); + $endStr = $end->format('Y-m-d 23:59:59'); + + $this->query->where('transaction_journals.date', '>=', $startStr); + $this->query->where('transaction_journals.date', '<=', $endStr); return $this; } @@ -219,4 +631,5 @@ trait TimeCollection $this->query->whereYear('transaction_journals.date', '=', $year); return $this; } + } diff --git a/app/Helpers/Collector/GroupCollector.php b/app/Helpers/Collector/GroupCollector.php index 6004f7639e..d7e1c2f5f9 100644 --- a/app/Helpers/Collector/GroupCollector.php +++ b/app/Helpers/Collector/GroupCollector.php @@ -25,6 +25,7 @@ namespace FireflyIII\Helpers\Collector; use Carbon\Carbon; use Carbon\Exceptions\InvalidDateException; +use Closure; use Exception; use FireflyIII\Helpers\Collector\Extensions\AccountCollection; use FireflyIII\Helpers\Collector\Extensions\AmountCollection; @@ -402,7 +403,7 @@ class GroupCollector implements GroupCollectorInterface } } // unset various fields: - unset($result['tag_id'],$result['meta_data'], $result['meta_name'], $result['tag_name'], $result['tag_date'], $result['tag_description'], $result['tag_latitude'], $result['tag_longitude'], $result['tag_zoom_level']); + unset($result['tag_id'], $result['meta_data'], $result['meta_name'], $result['tag_name'], $result['tag_date'], $result['tag_description'], $result['tag_latitude'], $result['tag_longitude'], $result['tag_zoom_level']); return $result; } @@ -528,20 +529,36 @@ class GroupCollector implements GroupCollectorInterface private function postFilterCollection(Collection $collection): Collection { Log::debug('Now in postFilterCollection()'); - $newCollection = new Collection; - foreach ($collection as $i => $item) { - Log::debug(sprintf('Now working on item #%d/%d', (int) $i + 1, $collection->count())); - foreach ($this->postFilters as $func) { - if (false === $func($i, $item)) { + $currentCollection = $collection; + $total = count($this->postFilters); + /** + * @var int $i + * @var Closure $function + */ + foreach ($this->postFilters as $i => $function) { + Log::debug(sprintf('Now working on filter #%d/%d', $i + 1, $total)); + + $nextCollection = new Collection; + // loop everything in the current collection + // and save it (or not) in the new collection. + // that new collection is the next current collection + /** + * @var int $index + * @var array $item + */ + foreach ($currentCollection as $ii => $item) { + $result = $function($ii, $item); + if (false === $result) { // skip other filters, continue to next item. Log::debug('Filter returns false, jump to next item.'); - continue 2; + continue; } Log::debug('Filter returns true'); + $nextCollection->push($item); } - $newCollection->push($item); + $currentCollection = $nextCollection; } - return $newCollection; + return $currentCollection; } /** @@ -588,20 +605,6 @@ class GroupCollector implements GroupCollectorInterface return $this; } - /** - * Has attachments - * - * @return GroupCollectorInterface - */ - public function hasNoAttachments(): GroupCollectorInterface - { - Log::debug('Add filter on no attachments.'); - $this->joinAttachmentTables(); - $this->query->whereNull('attachments.attachable_id'); - - return $this; - } - /** * Join table to get attachment information. */ @@ -621,6 +624,20 @@ class GroupCollector implements GroupCollectorInterface } } + /** + * Has attachments + * + * @return GroupCollectorInterface + */ + public function hasNoAttachments(): GroupCollectorInterface + { + Log::debug('Add filter on no attachments.'); + $this->joinAttachmentTables(); + $this->query->whereNull('attachments.attachable_id'); + + return $this; + } + /** * Limit results to a specific currency, either foreign or normal one. * diff --git a/app/Helpers/Collector/GroupCollectorInterface.php b/app/Helpers/Collector/GroupCollectorInterface.php index cf42d881d4..cb4dc96aa3 100644 --- a/app/Helpers/Collector/GroupCollectorInterface.php +++ b/app/Helpers/Collector/GroupCollectorInterface.php @@ -58,7 +58,7 @@ interface GroupCollectorInterface public function amountLess(string $amount): GroupCollectorInterface; /** - * Get transactions where the amount is more than. + * Get transactions where the foreign amount is more than. * * @param string $amount * @@ -172,6 +172,33 @@ interface GroupCollectorInterface */ public function findNothing(): GroupCollectorInterface; + /** + * Get transactions with a specific foreign amount. + * + * @param string $amount + * + * @return GroupCollectorInterface + */ + public function foreignAmountIs(string $amount): GroupCollectorInterface; + + /** + * Get transactions where the amount is less than. + * + * @param string $amount + * + * @return GroupCollectorInterface + */ + public function foreignAmountLess(string $amount): GroupCollectorInterface; + + /** + * Get transactions where the foreign amount is more than. + * + * @param string $amount + * + * @return GroupCollectorInterface + */ + public function foreignAmountMore(string $amount): GroupCollectorInterface; + /** * Return the transaction journals without group information. Is useful in some instances. * @@ -230,6 +257,69 @@ interface GroupCollectorInterface */ public function internalReferenceStarts(string $externalId): GroupCollectorInterface; + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function metaDayAfter(string $day, string $field): GroupCollectorInterface; + + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function metaDayBefore(string $day, string $field): GroupCollectorInterface; + + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function metaDayIs(string $day, string $field): GroupCollectorInterface; + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function metaMonthAfter(string $month, string $field): GroupCollectorInterface; + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function metaMonthBefore(string $month, string $field): GroupCollectorInterface; + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function metaMonthIs(string $month, string $field): GroupCollectorInterface; + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function metaYearAfter(string $year, string $field): GroupCollectorInterface; + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function metaYearBefore(string $year, string $field): GroupCollectorInterface; + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function metaYearIs(string $year, string $field): GroupCollectorInterface; + /** * @param string $month * @return GroupCollectorInterface @@ -276,6 +366,69 @@ interface GroupCollectorInterface */ public function notesStartWith(string $value): GroupCollectorInterface; + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function objectDayAfter(string $day, string $field): GroupCollectorInterface; + + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function objectDayBefore(string $day, string $field): GroupCollectorInterface; + + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function objectDayIs(string $day, string $field): GroupCollectorInterface; + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function objectMonthAfter(string $month, string $field): GroupCollectorInterface; + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function objectMonthBefore(string $month, string $field): GroupCollectorInterface; + + /** + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function objectMonthIs(string $month, string $field): GroupCollectorInterface; + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function objectYearAfter(string $year, string $field): GroupCollectorInterface; + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function objectYearBefore(string $year, string $field): GroupCollectorInterface; + + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function objectYearIs(string $year, string $field): GroupCollectorInterface; + /** * Define which accounts can be part of the source and destination transactions. * @@ -403,13 +556,10 @@ interface GroupCollectorInterface public function setExternalId(string $externalId): GroupCollectorInterface; /** - * Look for specific recurring ID's. - * - * @param string $recurringId - * + * @param string $url * @return GroupCollectorInterface */ - public function setRecurrenceId(string $recurringId): GroupCollectorInterface; + public function setExternalUrl(string $url): GroupCollectorInterface; /** * Limit results to a specific foreign currency. @@ -456,6 +606,57 @@ interface GroupCollectorInterface */ public function setLimit(int $limit): GroupCollectorInterface; + /** + * Collect transactions after a specific date. + * + * @param Carbon $date + * @param string $field + * @return GroupCollectorInterface + */ + public function setMetaAfter(Carbon $date, string $field): GroupCollectorInterface; + + /** + * Collect transactions before a specific date. + * + * @param Carbon $date + * @param string $field + * @return GroupCollectorInterface + */ + public function setMetaBefore(Carbon $date, string $field): GroupCollectorInterface; + + /** + * Set the start and end time of the results to return, based on meta data. + * + * @param Carbon $start + * @param Carbon $end + * @param string $field + * + * @return GroupCollectorInterface + */ + public function setMetaDateRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface; + + /** + * @param Carbon $date + * @param string $field + * @return GroupCollectorInterface + */ + public function setObjectAfter(Carbon $date, string $field): GroupCollectorInterface; + + /** + * @param Carbon $date + * @param string $field + * @return GroupCollectorInterface + */ + public function setObjectBefore(Carbon $date, string $field): GroupCollectorInterface; + + /** + * @param Carbon $start + * @param Carbon $end + * @param string $field + * @return GroupCollectorInterface + */ + public function setObjectRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface; + /** * Set the page to get. * @@ -476,15 +677,13 @@ interface GroupCollectorInterface public function setRange(Carbon $start, Carbon $end): GroupCollectorInterface; /** - * Set the start and end time of the results to return, based on meta data. + * Look for specific recurring ID's. * - * @param Carbon $start - * @param Carbon $end - * @param string $field + * @param string $recurringId * * @return GroupCollectorInterface */ - public function setMetaDateRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface; + public function setRecurrenceId(string $recurringId): GroupCollectorInterface; /** * Search for words in descriptions. @@ -661,12 +860,6 @@ interface GroupCollectorInterface */ public function withMetaDate(string $field): GroupCollectorInterface; - /** - * @param string $url - * @return GroupCollectorInterface - */ - public function setExternalUrl(string $url): GroupCollectorInterface; - /** * Will include notes. * @@ -737,4 +930,5 @@ interface GroupCollectorInterface */ public function yearIs(string $year): GroupCollectorInterface; + } diff --git a/app/Support/Search/OperatorQuerySearch.php b/app/Support/Search/OperatorQuerySearch.php index d40190102d..df6a8e5a17 100644 --- a/app/Support/Search/OperatorQuerySearch.php +++ b/app/Support/Search/OperatorQuerySearch.php @@ -152,7 +152,7 @@ class OperatorQuerySearch implements SearchInterface */ public function parseQuery(string $query) { - Log::debug(sprintf ('Now in parseQuery(%s)', $query)); + Log::debug(sprintf('Now in parseQuery(%s)', $query)); $parser = new QueryParser(); try { $query1 = $parser->parse($query); @@ -689,6 +689,15 @@ class OperatorQuerySearch implements SearchInterface Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); $this->collector->amountIs($amount); break; + case 'foreign_amount_is': + + // strip comma's, make dots. + $value = str_replace(',', '.', (string) $value); + + $amount = app('steam')->positive($value); + Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); + $this->collector->foreignAmountIs($amount); + break; case 'amount_less': // strip comma's, make dots. $value = str_replace(',', '.', (string) $value); @@ -697,6 +706,14 @@ class OperatorQuerySearch implements SearchInterface Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); $this->collector->amountLess($amount); break; + case 'foreign_amount_less': + // strip comma's, make dots. + $value = str_replace(',', '.', (string) $value); + + $amount = app('steam')->positive($value); + Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); + $this->collector->foreignAmountLess($amount); + break; case 'amount_more': Log::debug(sprintf('Now handling operator "%s"', $operator)); // strip comma's, make dots. @@ -705,6 +722,14 @@ class OperatorQuerySearch implements SearchInterface Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); $this->collector->amountMore($amount); break; + case 'foreign_amount_more': + Log::debug(sprintf('Now handling operator "%s"', $operator)); + // strip comma's, make dots. + $value = str_replace(',', '.', (string) $value); + $amount = app('steam')->positive($value); + Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); + $this->collector->foreignAmountMore($amount); + break; // // transaction type // @@ -730,17 +755,107 @@ class OperatorQuerySearch implements SearchInterface case 'interest_date_on': $range = $this->parseDateRange($value); $this->setExactMetaDateParams('interest_date', $range); - break; - case 'created_on': + return false; + case 'interest_date_before': + $range = $this->parseDateRange($value); + $this->setMetaDateBeforeParams('interest_date', $range); + return false; + case 'interest_date_after': + $range = $this->parseDateRange($value); + $this->setMetaDateAfterParams('interest_date', $range); + return false; + + case 'book_date_on': + $range = $this->parseDateRange($value); + $this->setExactMetaDateParams('book_date', $range); + return false; + case 'book_date_before': + $range = $this->parseDateRange($value); + $this->setMetaDateBeforeParams('book_date', $range); + return false; + case 'book_date_after': + $range = $this->parseDateRange($value); + $this->setMetaDateAfterParams('book_date', $range); + return false; + + case 'process_date_on': + $range = $this->parseDateRange($value); + $this->setExactMetaDateParams('process_date', $range); + return false; + case 'process_date_before': + $range = $this->parseDateRange($value); + $this->setMetaDateBeforeParams('process_date', $range); + return false; + case 'process_date_after': + $range = $this->parseDateRange($value); + $this->setMetaDateAfterParams('process_date', $range); + return false; + case 'due_date_on': + $range = $this->parseDateRange($value); + $this->setExactMetaDateParams('due_date', $range); + return false; + case 'due_date_before': + $range = $this->parseDateRange($value); + $this->setMetaDateBeforeParams('due_date', $range); + return false; + case 'due_date_after': + $range = $this->parseDateRange($value); + $this->setMetaDateAfterParams('due_date', $range); + return false; + case 'payment_date_on': + $range = $this->parseDateRange($value); + $this->setExactMetaDateParams('payment_date', $range); + return false; + case 'payment_date_before': + $range = $this->parseDateRange($value); + $this->setMetaDateBeforeParams('payment_date', $range); + return false; + case 'payment_date_after': + $range = $this->parseDateRange($value); + $this->setMetaDateAfterParams('payment_date', $range); + return false; + case 'invoice_date_on': + $range = $this->parseDateRange($value); + $this->setExactMetaDateParams('invoice_date', $range); + return false; + case 'invoice_date_before': + $range = $this->parseDateRange($value); + $this->setMetaDateBeforeParams('invoice_date', $range); + return false; + case 'invoice_date_after': + $range = $this->parseDateRange($value); + $this->setMetaDateAfterParams('invoice_date', $range); + return false; + case 'created_at_on': Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); - $createdAt = new Carbon($value); - $this->collector->setCreatedAt($createdAt); - break; - case 'updated_on': + $range = $this->parseDateRange($value); + $this->setExactObjectDateParams('created_at', $range); + return false; + case 'created_at_before': Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); - $updatedAt = new Carbon($value); - $this->collector->setUpdatedAt($updatedAt); - break; + $range = $this->parseDateRange($value); + $this->setObjectDateBeforeParams('created_at', $range); + return false; + case 'created_at_after': + Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); + $range = $this->parseDateRange($value); + $this->setObjectDateAfterParams('created_at', $range); + return false; + case 'updated_at_on': + Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); + $range = $this->parseDateRange($value); + $this->setExactObjectDateParams('updated_at', $range); + return false; + case 'updated_at_before': + Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); + $range = $this->parseDateRange($value); + $this->setObjectDateBeforeParams('updated_at', $range); + return false; + case 'updated_at_after': + Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); + $range = $this->parseDateRange($value); + $this->setObjectDateAfterParams('updated_at', $range); + return false; // // external URL // @@ -1059,6 +1174,46 @@ class OperatorQuerySearch implements SearchInterface } } + /** + * @param string $field + * @param array $range + * @return void + * @throws FireflyException + */ + private function setExactObjectDateParams(string $field,array $range): void + { + /** + * @var string $key + * @var Carbon|string $value + */ + foreach ($range as $key => $value) { + switch ($key) { + default: + throw new FireflyException(sprintf('Cannot handle key "%s" in setExactObjectDateParams()', $key)); + case 'exact': + Log::debug(sprintf('Set %s_is_exact value "%s"',$field, $value->format('Y-m-d'))); + $this->collector->setObjectRange($value, clone $value, $field); + $this->operators->push(['type' => sprintf('%s_on', $field), 'value' => $value->format('Y-m-d'),]); + break; + case 'year': + Log::debug(sprintf('Set %s_is_exact YEAR value "%s"', $field, $value)); + $this->collector->objectYearIs($value, $field); + $this->operators->push(['type' => sprintf('%s_on_year', $field), 'value' => $value,]); + break; + case 'month': + Log::debug(sprintf('Set %s_is_exact MONTH value "%s"', $field, $value)); + $this->collector->objectMonthIs($value, $field); + $this->operators->push(['type' => sprintf('%s_on_month', $field), 'value' => $value,]); + break; + case 'day': + Log::debug(sprintf('Set %s_is_exact DAY value "%s"', $field, $value)); + $this->collector->objectDayIs($value, $field); + $this->operators->push(['type' => sprintf('%s_on_day', $field), 'value' => $value,]); + break; + } + } + } + /** * @param array $range * @@ -1097,6 +1252,84 @@ class OperatorQuerySearch implements SearchInterface } } + /** + * @param string $field + * @param array $range + * @return void + * @throws FireflyException + */ + private function setMetaDateBeforeParams(string $field, array $range): void + { + /** + * @var string $key + * @var Carbon|string $value + */ + foreach ($range as $key => $value) { + switch ($key) { + default: + throw new FireflyException(sprintf('Cannot handle key "%s" in setMetaDateBeforeParams()', $key)); + case 'exact': + $this->collector->setMetaBefore($value, $field); + $this->operators->push(['type' => sprintf('%s_before', $field), 'value' => $value->format('Y-m-d'),]); + break; + case 'year': + Log::debug(sprintf('Set %s_is_before YEAR value "%s"', $field, $value)); + $this->collector->metaYearBefore($value, $field); + $this->operators->push(['type' => sprintf('%s_before_year', $field), 'value' => $value,]); + break; + case 'month': + Log::debug(sprintf('Set %s_is_before MONTH value "%s"', $field, $value)); + $this->collector->metaMonthBefore($value, $field); + $this->operators->push(['type' => sprintf('%s_before_month', $field), 'value' => $value,]); + break; + case 'day': + Log::debug(sprintf('Set %s_is_before DAY value "%s"', $field, $value)); + $this->collector->metaDayBefore($value, $field); + $this->operators->push(['type' => sprintf('%s_before_day', $field), 'value' => $value,]); + break; + } + } + } + + /** + * @param string $field + * @param array $range + * @return void + * @throws FireflyException + */ + private function setMetaDateAfterParams(string $field, array $range): void + { + /** + * @var string $key + * @var Carbon|string $value + */ + foreach ($range as $key => $value) { + switch ($key) { + default: + throw new FireflyException(sprintf('Cannot handle key "%s" in setMetaDateAfterParams()', $key)); + case 'exact': + $this->collector->setMetaAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after', $field), 'value' => $value->format('Y-m-d'),]); + break; + case 'year': + Log::debug(sprintf('Set %s_is_after YEAR value "%s"', $field, $value)); + $this->collector->metaYearAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after_year', $field), 'value' => $value,]); + break; + case 'month': + Log::debug(sprintf('Set %s_is_after MONTH value "%s"', $field, $value)); + $this->collector->metaMonthAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after_month', $field), 'value' => $value,]); + break; + case 'day': + Log::debug(sprintf('Set %s_is_after DAY value "%s"', $field, $value)); + $this->collector->metaDayAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after_day', $field), 'value' => $value,]); + break; + } + } + } + /** * @param array $range * @@ -1135,6 +1368,82 @@ class OperatorQuerySearch implements SearchInterface } } + /** + * @param array $range + * + * @throws FireflyException + */ + private function setObjectDateAfterParams(string $field, array $range) + { + /** + * @var string $key + * @var Carbon|string $value + */ + foreach ($range as $key => $value) { + switch ($key) { + default: + throw new FireflyException(sprintf('Cannot handle key "%s" in setDateAfterParams()', $key)); + case 'exact': + $this->collector->setObjectAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after', $field), 'value' => $value->format('Y-m-d'),]); + break; + case 'year': + Log::debug(sprintf('Set date_is_after YEAR value "%s"', $value)); + $this->collector->objectYearAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after_year', $field), 'value' => $value,]); + break; + case 'month': + Log::debug(sprintf('Set date_is_after MONTH value "%s"', $value)); + $this->collector->objectMonthAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after_month', $field), 'value' => $value,]); + break; + case 'day': + Log::debug(sprintf('Set date_is_after DAY value "%s"', $value)); + $this->collector->objectDayAfter($value, $field); + $this->operators->push(['type' => sprintf('%s_after_day', $field), 'value' => $value,]); + break; + } + } + } + + /** + * @param array $range + * + * @throws FireflyException + */ + private function setObjectDateBeforeParams(string $field, array $range) + { + /** + * @var string $key + * @var Carbon|string $value + */ + foreach ($range as $key => $value) { + switch ($key) { + default: + throw new FireflyException(sprintf('Cannot handle key "%s" in setDateAfterParams()', $key)); + case 'exact': + $this->collector->setObjectBefore($value, $field); + $this->operators->push(['type' => sprintf('%s_before', $field), 'value' => $value->format('Y-m-d'),]); + break; + case 'year': + Log::debug(sprintf('Set date_is_before YEAR value "%s"', $value)); + $this->collector->objectYearBefore($value, $field); + $this->operators->push(['type' => sprintf('%s_before_year', $field), 'value' => $value,]); + break; + case 'month': + Log::debug(sprintf('Set date_is_before MONTH value "%s"', $value)); + $this->collector->objectMonthBefore($value, $field); + $this->operators->push(['type' => sprintf('%s_before_month', $field), 'value' => $value,]); + break; + case 'day': + Log::debug(sprintf('Set date_is_before DAY value "%s"', $value)); + $this->collector->objectDayBefore($value, $field); + $this->operators->push(['type' => sprintf('%s_before_day', $field), 'value' => $value,]); + break; + } + } + } + /** * @param string $field * @param array $range @@ -1151,25 +1460,25 @@ class OperatorQuerySearch implements SearchInterface foreach ($range as $key => $value) { switch ($key) { default: - throw new FireflyException(sprintf('Cannot handle key "%s" in setExactParameters()', $key)); + throw new FireflyException(sprintf('Cannot handle key "%s" in setExactMetaDateParams()', $key)); case 'exact': - Log::debug(sprintf('Set %s_date_is_exact value "%s"', $field, $value->format('Y-m-d'))); - $this->collector->setMetaDateRange($value, $value,'interest_date'); - //$this->operators->push(['type' => sprintf('%s_on', $field), 'value' => $value->format('Y-m-d'),]); + Log::debug(sprintf('Set %s_is_exact value "%s"', $field, $value->format('Y-m-d'))); + $this->collector->setMetaDateRange($value, $value, $field); + $this->operators->push(['type' => sprintf('%s_on', $field), 'value' => $value->format('Y-m-d'),]); break; case 'year': - Log::debug(sprintf('Set date_is_exact YEAR value "%s"', $value)); - //$this->collector->yearIs($value); + Log::debug(sprintf('Set %s_is_exact YEAR value "%s"', $field, $value)); + $this->collector->metaYearIs($value, $field); $this->operators->push(['type' => sprintf('%s_on_year', $field), 'value' => $value,]); break; case 'month': - Log::debug(sprintf('Set date_is_exact MONTH value "%s"', $value)); - //$this->collector->monthIs($value); + Log::debug(sprintf('Set %s_is_exact MONTH value "%s"', $field, $value)); + $this->collector->metaMonthIs($value, $field); $this->operators->push(['type' => sprintf('%s_on_month', $field), 'value' => $value,]); break; case 'day': - Log::debug(sprintf('Set date_is_exact DAY value "%s"', $value)); - //$this->collector->dayIs($value); + Log::debug(sprintf('Set %s_is_exact DAY value "%s"', $field, $value)); + $this->collector->metaDayIs($value, $field); $this->operators->push(['type' => sprintf('%s_on_day', $field), 'value' => $value,]); break; } diff --git a/config/search.php b/config/search.php index afe1bb7794..c8eb92c29a 100644 --- a/config/search.php +++ b/config/search.php @@ -127,7 +127,6 @@ return [ 'before' => ['alias' => true, 'alias_for' => 'date_before', 'needs_context' => true,], 'date_after' => ['alias' => false, 'needs_context' => true,], 'after' => ['alias' => true, 'alias_for' => 'date_after', 'needs_context' => true,], - 'interest_date_on' => ['alias' => false, 'needs_context' => true,], 'interest_date' => ['alias' => true, 'alias_for' => 'interest_date_on', 'needs_context' => true,], 'interest_date_is' => ['alias' => true, 'alias_for' => 'interest_date_on', 'needs_context' => true,], diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index a9e633e9e9..79ea98e1be 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -448,6 +448,7 @@ return [ 'search_modifier_invoice_date_after_year' => 'Transaction invoice date is after or in year ":value"', 'search_modifier_invoice_date_after_month' => 'Transaction invoice date is after or in month ":value"', 'search_modifier_invoice_date_after_day' => 'Transaction invoice date is after or on day of month ":value"', + // other dates 'search_modifier_updated_at_on_year' => 'Transaction was last updated in year ":value"', 'search_modifier_updated_at_on_month' => 'Transaction was last updated in month ":value"', 'search_modifier_updated_at_on_day' => 'Transaction was last updated on day of month ":value"', @@ -466,29 +467,29 @@ return [ 'search_modifier_created_at_after_year' => 'Transaction was created in or after year ":value"', 'search_modifier_created_at_after_month' => 'Transaction was created in or after month ":value"', 'search_modifier_created_at_after_day' => 'Transaction was created on or after day of month ":value"', - 'search_modifier_interest_date_before' => 'Transaction interest date is before ":value"', - 'search_modifier_interest_date_after' => 'Transaction interest date is after ":value"', + 'search_modifier_interest_date_before' => 'Transaction interest date is on or before ":value"', + 'search_modifier_interest_date_after' => 'Transaction interest date is on or after ":value"', 'search_modifier_book_date_on' => 'Transaction book date is on ":value"', - 'search_modifier_book_date_before' => 'Transaction book date is before ":value"', - 'search_modifier_book_date_after' => 'Transaction book date is after ":value"', + 'search_modifier_book_date_before' => 'Transaction book date is on or before ":value"', + 'search_modifier_book_date_after' => 'Transaction book date is on or after ":value"', 'search_modifier_process_date_on' => 'Transaction process date is on ":value"', - 'search_modifier_process_date_before' => 'Transaction process date is before ":value"', - 'search_modifier_process_date_after' => 'Transaction process date is after ":value"', + 'search_modifier_process_date_before' => 'Transaction process date is on or before ":value"', + 'search_modifier_process_date_after' => 'Transaction process date is on or after ":value"', 'search_modifier_due_date_on' => 'Transaction due date is on ":value"', - 'search_modifier_due_date_before' => 'Transaction due date is before ":value"', - 'search_modifier_due_date_after' => 'Transaction due date is after ":value"', + 'search_modifier_due_date_before' => 'Transaction due date is on or before ":value"', + 'search_modifier_due_date_after' => 'Transaction due date is on or after ":value"', 'search_modifier_payment_date_on' => 'Transaction payment date is on ":value"', - 'search_modifier_payment_date_before' => 'Transaction payment date is before ":value"', - 'search_modifier_payment_date_after' => 'Transaction payment date is after ":value"', + 'search_modifier_payment_date_before' => 'Transaction payment date is on or before ":value"', + 'search_modifier_payment_date_after' => 'Transaction payment date is on or after ":value"', 'search_modifier_invoice_date_on' => 'Transaction invoice date is on ":value"', - 'search_modifier_invoice_date_before' => 'Transaction invoice date is before ":value"', - 'search_modifier_invoice_date_after' => 'Transaction invoice date is after ":value"', + 'search_modifier_invoice_date_before' => 'Transaction invoice date is on or before ":value"', + 'search_modifier_invoice_date_after' => 'Transaction invoice date is on or after ":value"', 'search_modifier_created_at_on' => 'Transaction was created on ":value"', - 'search_modifier_created_at_before' => 'Transaction was created before ":value"', - 'search_modifier_created_at_after' => 'Transaction was created after ":value"', + 'search_modifier_created_at_before' => 'Transaction was created on or before ":value"', + 'search_modifier_created_at_after' => 'Transaction was created on or after ":value"', 'search_modifier_updated_at_on' => 'Transaction was updated on ":value"', - 'search_modifier_updated_at_before' => 'Transaction was updated before ":value"', - 'search_modifier_updated_at_after' => 'Transaction was updated after ":value"', + 'search_modifier_updated_at_before' => 'Transaction was updated on or before ":value"', + 'search_modifier_updated_at_after' => 'Transaction was updated on or after ":value"', 'update_rule_from_query' => 'Update rule ":rule" from search query', 'create_rule_from_query' => 'Create new rule from search query', diff --git a/resources/views/list/groups.twig b/resources/views/list/groups.twig index fb58105820..4548c33a3c 100644 --- a/resources/views/list/groups.twig +++ b/resources/views/list/groups.twig @@ -66,7 +66,7 @@ {% else %} X - {# {{ formatAmountBySymbol(sum.amount, sum.currency_symbol, sum.currency_decimal_places) }}{% if loop.index != group.sums|length %},{% endif %} #} + {{ formatAmountBySymbol(sum.amount, sum.currency_symbol, sum.currency_decimal_places) }}{% if loop.index != group.sums|length %},{% endif %} {% endif %} {% endfor %} @@ -197,7 +197,7 @@ {# THE REST #} {% else %} - {# {{ formatAmountBySymbol(transaction.amount, transaction.currency_symbol, transaction.currency_decimal_places) }} #} + {{ formatAmountBySymbol(transaction.amount, transaction.currency_symbol, transaction.currency_decimal_places) }} {% if null != transaction.foreign_amount %} ({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }}) {% endif %}