Update search.

This commit is contained in:
James Cole 2022-03-27 16:03:50 +02:00
parent 679e72e5e2
commit 980120f1bd
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
9 changed files with 1164 additions and 174 deletions

View File

@ -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;
}
}

View File

@ -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.
*

View File

@ -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;
}
}

View File

@ -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.
*

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,],

View File

@ -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',

View File

@ -66,7 +66,7 @@
</span>
{% 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 %}
</td>
@ -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 %}