Make it possible to search by interest date.

This commit is contained in:
James Cole 2022-03-27 08:48:30 +02:00
parent ff7f4e5bba
commit 679e72e5e2
No known key found for this signature in database
GPG Key ID: B49A324B7EAD6D80
8 changed files with 240 additions and 72 deletions

View File

@ -44,10 +44,7 @@ trait MetaCollection
*/ */
public function externalIdContains(string $externalId): GroupCollectorInterface public function externalIdContains(string $externalId): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'external_id'); $this->query->where('journal_meta.name', '=', 'external_id');
$this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s%%', $externalId)); $this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s%%', $externalId));
@ -59,10 +56,7 @@ trait MetaCollection
*/ */
public function externalIdEnds(string $externalId): GroupCollectorInterface public function externalIdEnds(string $externalId): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'external_id'); $this->query->where('journal_meta.name', '=', 'external_id');
$this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s"', $externalId)); $this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s"', $externalId));
@ -74,10 +68,7 @@ trait MetaCollection
*/ */
public function externalIdStarts(string $externalId): GroupCollectorInterface public function externalIdStarts(string $externalId): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'external_id'); $this->query->where('journal_meta.name', '=', 'external_id');
$this->query->where('journal_meta.data', 'LIKE', sprintf('"%s%%', $externalId)); $this->query->where('journal_meta.data', 'LIKE', sprintf('"%s%%', $externalId));
@ -129,15 +120,24 @@ trait MetaCollection
} }
/** /**
* @inheritDoc * Join table to get tag information.
*/ */
public function setExternalUrl(string $url): GroupCollectorInterface protected function joinMetaDataTables(): void
{ {
if (false === $this->hasJoinedMetaTables) { if (false === $this->hasJoinedMetaTables) {
$this->hasJoinedMetaTables = true; $this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id'); $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.name', '=', 'external_url');
$this->query->where('journal_meta.data', '=', json_encode($url)); $this->query->where('journal_meta.data', '=', json_encode($url));
@ -150,10 +150,7 @@ trait MetaCollection
*/ */
public function externalUrlContains(string $url): GroupCollectorInterface public function externalUrlContains(string $url): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$url = json_encode($url); $url = json_encode($url);
$url = str_replace('\\', '\\\\', trim($url, '"')); $url = str_replace('\\', '\\\\', trim($url, '"'));
$this->query->where('journal_meta.name', '=', 'external_url'); $this->query->where('journal_meta.name', '=', 'external_url');
@ -168,10 +165,7 @@ trait MetaCollection
*/ */
public function externalUrlEnds(string $url): GroupCollectorInterface public function externalUrlEnds(string $url): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$url = json_encode($url); $url = json_encode($url);
$url = str_replace('\\', '\\\\', ltrim($url, '"')); $url = str_replace('\\', '\\\\', ltrim($url, '"'));
$this->query->where('journal_meta.name', '=', 'external_url'); $this->query->where('journal_meta.name', '=', 'external_url');
@ -186,10 +180,7 @@ trait MetaCollection
*/ */
public function externalUrlStarts(string $url): GroupCollectorInterface public function externalUrlStarts(string $url): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$url = json_encode($url); $url = json_encode($url);
$url = str_replace('\\', '\\\\', rtrim($url, '"')); $url = str_replace('\\', '\\\\', rtrim($url, '"'));
//var_dump($url); //var_dump($url);
@ -205,10 +196,7 @@ trait MetaCollection
*/ */
public function internalReferenceContains(string $externalId): GroupCollectorInterface public function internalReferenceContains(string $externalId): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'internal_reference'); $this->query->where('journal_meta.name', '=', 'internal_reference');
$this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s%%', $externalId)); $this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s%%', $externalId));
@ -220,10 +208,7 @@ trait MetaCollection
*/ */
public function internalReferenceEnds(string $externalId): GroupCollectorInterface public function internalReferenceEnds(string $externalId): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'internal_reference'); $this->query->where('journal_meta.name', '=', 'internal_reference');
$this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s"', $externalId)); $this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s"', $externalId));
@ -235,10 +220,7 @@ trait MetaCollection
*/ */
public function internalReferenceStarts(string $externalId): GroupCollectorInterface public function internalReferenceStarts(string $externalId): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'internal_reference'); $this->query->where('journal_meta.name', '=', 'internal_reference');
$this->query->where('journal_meta.data', 'LIKE', sprintf('"%s%%', $externalId)); $this->query->where('journal_meta.data', 'LIKE', sprintf('"%s%%', $externalId));
@ -480,25 +462,31 @@ trait MetaCollection
*/ */
public function setExternalId(string $externalId): GroupCollectorInterface public function setExternalId(string $externalId): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'external_id'); $this->query->where('journal_meta.name', '=', 'external_id');
$this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($externalId))); $this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($externalId)));
return $this; 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;
}
/** /**
* @inheritDoc * @inheritDoc
*/ */
public function setInternalReference(string $internalReference): GroupCollectorInterface public function setInternalReference(string $internalReference): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'internal_reference'); $this->query->where('journal_meta.name', '=', 'internal_reference');
$this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s%%', $internalReference)); $this->query->where('journal_meta.data', 'LIKE', sprintf('%%%s%%', $internalReference));
@ -620,10 +608,7 @@ trait MetaCollection
*/ */
public function withExternalUrl(): GroupCollectorInterface public function withExternalUrl(): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true;
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where('journal_meta.name', '=', 'external_url'); $this->query->where('journal_meta.name', '=', 'external_url');
$this->query->whereNotNull('journal_meta.data'); $this->query->whereNotNull('journal_meta.data');
@ -673,16 +658,16 @@ trait MetaCollection
*/ */
public function withoutExternalUrl(): GroupCollectorInterface public function withoutExternalUrl(): GroupCollectorInterface
{ {
if (false === $this->hasJoinedMetaTables) { $this->joinMetaDataTables();
$this->hasJoinedMetaTables = true; // TODO not sure if this will work properly.
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
}
$this->query->where(function (Builder $q1) { $this->query->where(function (Builder $q1) {
$q1->where(function (Builder $q2) { $q1->where(function (Builder $q2) {
$q2->where('journal_meta.name', '=', 'external_url'); $q2->where('journal_meta.name', '=', 'external_url');
$q2->whereNull('journal_meta.data'); $q2->whereNull('journal_meta.data');
})->orWhere(function (Builder $q3) { })->orWhere(function (Builder $q3) {
$q3->where('journal_meta.name', '!=', 'external_url'); $q3->where('journal_meta.name', '!=', 'external_url');
})->orWhere(function (Builder $q4) {
$q4->whereNull('journal_meta.name');
}); });
}); });

View File

@ -142,6 +142,49 @@ trait TimeCollection
return $this; return $this;
} }
/**
* @param Carbon $start
* @param Carbon $end
* @param string $field
* @return GroupCollectorInterface
*/
public function setMetaDateRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface
{
if ($end < $start) {
[$start, $end] = [$end, $start];
}
$end = clone $end; // this is so weird, but it works if $end and $start secretly point to the same object.
$end->endOfDay();
$start->startOfDay();
$this->withMetaDate($field);
$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
) {
return $transaction['interest_date']->gte($start) && $transaction['interest_date']->lte($end);
}
}
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;
}
/** /**
* Collect transactions updated on a specific date. * Collect transactions updated on a specific date.
* *

View File

@ -339,9 +339,15 @@ class GroupCollector implements GroupCollectorInterface
*/ */
private function parseAugmentedJournal(TransactionJournal $augumentedJournal): array private function parseAugmentedJournal(TransactionJournal $augumentedJournal): array
{ {
$result = $augumentedJournal->toArray(); $result = $augumentedJournal->toArray();
$result['tags'] = []; $result['tags'] = [];
$result['attachments'] = []; $result['attachments'] = [];
$result['interest_date'] = null;
$result['payment_date'] = null;
$result['invoice_date'] = null;
$result['book_date'] = null;
$result['due_date'] = null;
$result['process_date'] = null;
try { try {
$result['date'] = new Carbon($result['date'], 'UTC'); $result['date'] = new Carbon($result['date'], 'UTC');
$result['created_at'] = new Carbon($result['created_at'], 'UTC'); $result['created_at'] = new Carbon($result['created_at'], 'UTC');
@ -355,6 +361,15 @@ class GroupCollector implements GroupCollectorInterface
Log::error($e->getMessage()); Log::error($e->getMessage());
} }
// try to process meta date value (if present)
$dates = ['interest_date', 'payment_date', 'invoice_date', 'book_date', 'due_date', 'process_date'];
if (array_key_exists('meta_name', $result) && in_array($result['meta_name'], $dates, true)) {
$name = $result['meta_name'];
if (array_key_exists('meta_data', $result) && '' !== (string) $result['meta_data']) {
$result[$name] = Carbon::createFromFormat('!Y-m-d', substr(json_decode($result['meta_data']), 0, 10));
}
}
// convert values to integers: // convert values to integers:
$result = $this->convertToInteger($result); $result = $this->convertToInteger($result);
@ -387,7 +402,7 @@ class GroupCollector implements GroupCollectorInterface
} }
} }
// unset various fields: // unset various fields:
unset($result['tag_id'], $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; return $result;
} }
@ -515,7 +530,7 @@ class GroupCollector implements GroupCollectorInterface
Log::debug('Now in postFilterCollection()'); Log::debug('Now in postFilterCollection()');
$newCollection = new Collection; $newCollection = new Collection;
foreach ($collection as $i => $item) { foreach ($collection as $i => $item) {
Log::debug(sprintf('Now working on item #%d/%d', $i + 1, $collection->count())); Log::debug(sprintf('Now working on item #%d/%d', (int) $i + 1, $collection->count()));
foreach ($this->postFilters as $func) { foreach ($this->postFilters as $func) {
if (false === $func($i, $item)) { if (false === $func($i, $item)) {
// skip other filters, continue to next item. // skip other filters, continue to next item.
@ -573,6 +588,20 @@ class GroupCollector implements GroupCollectorInterface
return $this; 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. * Join table to get attachment information.
*/ */

View File

@ -205,6 +205,13 @@ interface GroupCollectorInterface
*/ */
public function hasAttachments(): GroupCollectorInterface; public function hasAttachments(): GroupCollectorInterface;
/**
* Has no attachments
*
* @return GroupCollectorInterface
*/
public function hasNoAttachments(): GroupCollectorInterface;
/** /**
* @param string $externalId * @param string $externalId
* @return GroupCollectorInterface * @return GroupCollectorInterface
@ -395,6 +402,15 @@ interface GroupCollectorInterface
*/ */
public function setExternalId(string $externalId): GroupCollectorInterface; public function setExternalId(string $externalId): GroupCollectorInterface;
/**
* Look for specific recurring ID's.
*
* @param string $recurringId
*
* @return GroupCollectorInterface
*/
public function setRecurrenceId(string $recurringId): GroupCollectorInterface;
/** /**
* Limit results to a specific foreign currency. * Limit results to a specific foreign currency.
* *
@ -459,6 +475,17 @@ interface GroupCollectorInterface
*/ */
public function setRange(Carbon $start, Carbon $end): GroupCollectorInterface; public function setRange(Carbon $start, Carbon $end): 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;
/** /**
* Search for words in descriptions. * Search for words in descriptions.
* *
@ -626,6 +653,14 @@ interface GroupCollectorInterface
*/ */
public function withExternalUrl(): GroupCollectorInterface; public function withExternalUrl(): GroupCollectorInterface;
/**
* Transaction must have meta date field X.
*
* @param string $field
* @return GroupCollectorInterface
*/
public function withMetaDate(string $field): GroupCollectorInterface;
/** /**
* @param string $url * @param string $url
* @return GroupCollectorInterface * @return GroupCollectorInterface

View File

@ -152,7 +152,7 @@ class OperatorQuerySearch implements SearchInterface
*/ */
public function parseQuery(string $query) public function parseQuery(string $query)
{ {
Log::debug(sprintf('Now in parseQuery(%s)', $query)); Log::debug(sprintf ('Now in parseQuery(%s)', $query));
$parser = new QueryParser(); $parser = new QueryParser();
try { try {
$query1 = $parser->parse($query); $query1 = $parser->parse($query);
@ -496,6 +496,10 @@ class OperatorQuerySearch implements SearchInterface
Log::debug('Set collector to filter on attachments.'); Log::debug('Set collector to filter on attachments.');
$this->collector->hasAttachments(); $this->collector->hasAttachments();
break; break;
case 'has_no_attachments':
Log::debug('Set collector to filter on NO attachments.');
$this->collector->hasNoAttachments();
break;
// //
// categories // categories
case 'has_no_category': case 'has_no_category':
@ -711,7 +715,7 @@ class OperatorQuerySearch implements SearchInterface
// //
// dates // dates
// //
case 'date_is': case 'date_on':
$range = $this->parseDateRange($value); $range = $this->parseDateRange($value);
$this->setExactDateParams($range); $this->setExactDateParams($range);
return false; return false;
@ -723,6 +727,10 @@ class OperatorQuerySearch implements SearchInterface
$range = $this->parseDateRange($value); $range = $this->parseDateRange($value);
$this->setDateAfterParams($range); $this->setDateAfterParams($range);
return false; return false;
case 'interest_date_on':
$range = $this->parseDateRange($value);
$this->setExactMetaDateParams('interest_date', $range);
break;
case 'created_on': case 'created_on':
Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value));
$createdAt = new Carbon($value); $createdAt = new Carbon($value);
@ -760,6 +768,9 @@ class OperatorQuerySearch implements SearchInterface
case 'external_id_is': case 'external_id_is':
$this->collector->setExternalId($value); $this->collector->setExternalId($value);
break; break;
case 'recurrence_id':
$this->collector->setRecurrenceId($value);
break;
case 'external_id_contains': case 'external_id_contains':
$this->collector->externalIdContains($value); $this->collector->externalIdContains($value);
break; break;
@ -1027,22 +1038,22 @@ class OperatorQuerySearch implements SearchInterface
case 'exact': case 'exact':
Log::debug(sprintf('Set date_is_exact value "%s"', $value->format('Y-m-d'))); Log::debug(sprintf('Set date_is_exact value "%s"', $value->format('Y-m-d')));
$this->collector->setRange($value, $value); $this->collector->setRange($value, $value);
$this->operators->push(['type' => 'date_is', 'value' => $value->format('Y-m-d'),]); $this->operators->push(['type' => 'date_on', 'value' => $value->format('Y-m-d'),]);
break; break;
case 'year': case 'year':
Log::debug(sprintf('Set date_is_exact YEAR value "%s"', $value)); Log::debug(sprintf('Set date_is_exact YEAR value "%s"', $value));
$this->collector->yearIs($value); $this->collector->yearIs($value);
$this->operators->push(['type' => 'date_is_year', 'value' => $value,]); $this->operators->push(['type' => 'date_on_year', 'value' => $value,]);
break; break;
case 'month': case 'month':
Log::debug(sprintf('Set date_is_exact MONTH value "%s"', $value)); Log::debug(sprintf('Set date_is_exact MONTH value "%s"', $value));
$this->collector->monthIs($value); $this->collector->monthIs($value);
$this->operators->push(['type' => 'date_is_month', 'value' => $value,]); $this->operators->push(['type' => 'date_on_month', 'value' => $value,]);
break; break;
case 'day': case 'day':
Log::debug(sprintf('Set date_is_exact DAY value "%s"', $value)); Log::debug(sprintf('Set date_is_exact DAY value "%s"', $value));
$this->collector->dayIs($value); $this->collector->dayIs($value);
$this->operators->push(['type' => 'date_is_day', 'value' => $value,]); $this->operators->push(['type' => 'date_on_day', 'value' => $value,]);
break; break;
} }
} }
@ -1123,4 +1134,45 @@ class OperatorQuerySearch implements SearchInterface
} }
} }
} }
/**
* @param string $field
* @param array $range
* @return void
* @throws FireflyException
*/
private function setExactMetaDateParams(string $field, array $range): void
{
Log::debug('Now in setExactMetaDateParams()');
/**
* @var string $key
* @var Carbon|string $value
*/
foreach ($range as $key => $value) {
switch ($key) {
default:
throw new FireflyException(sprintf('Cannot handle key "%s" in setExactParameters()', $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'),]);
break;
case 'year':
Log::debug(sprintf('Set date_is_exact YEAR value "%s"', $value));
//$this->collector->yearIs($value);
$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);
$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);
$this->operators->push(['type' => sprintf('%s_on_day', $field), 'value' => $value,]);
break;
}
}
}
} }

View File

@ -85,13 +85,11 @@ return [
'external_id' => ['alias' => true, 'alias_for' => 'external_id_contains', 'needs_context' => true,], 'external_id' => ['alias' => true, 'alias_for' => 'external_id_contains', 'needs_context' => true,],
'external_id_ends' => ['alias' => false, 'needs_context' => true,], 'external_id_ends' => ['alias' => false, 'needs_context' => true,],
'external_id_starts' => ['alias' => false, 'needs_context' => true,], 'external_id_starts' => ['alias' => false, 'needs_context' => true,],
'internal_reference_is' => ['alias' => false, 'needs_context' => true,], 'internal_reference_is' => ['alias' => false, 'needs_context' => true,],
'internal_reference_contains' => ['alias' => false, 'needs_context' => true,], 'internal_reference_contains' => ['alias' => false, 'needs_context' => true,],
'internal_reference' => ['alias' => true, 'alias_for' => 'internal_reference_contains', 'needs_context' => true,], 'internal_reference' => ['alias' => true, 'alias_for' => 'internal_reference_contains', 'needs_context' => true,],
'internal_reference_ends' => ['alias' => false, 'needs_context' => true,], 'internal_reference_ends' => ['alias' => false, 'needs_context' => true,],
'internal_reference_starts' => ['alias' => false, 'needs_context' => true,], 'internal_reference_starts' => ['alias' => false, 'needs_context' => true,],
'external_url_is' => ['alias' => false, 'needs_context' => true,], 'external_url_is' => ['alias' => false, 'needs_context' => true,],
'external_url_contains' => ['alias' => false, 'needs_context' => true,], 'external_url_contains' => ['alias' => false, 'needs_context' => true,],
'external_url' => ['alias' => true, 'alias_for' => 'external_url_contains', 'needs_context' => true,], 'external_url' => ['alias' => true, 'alias_for' => 'external_url_contains', 'needs_context' => true,],
@ -99,12 +97,13 @@ return [
'external_url_starts' => ['alias' => false, 'needs_context' => true,], 'external_url_starts' => ['alias' => false, 'needs_context' => true,],
'has_attachments' => ['alias' => false, 'needs_context' => false,], 'has_attachments' => ['alias' => false, 'needs_context' => false,],
'has_any_category' => ['alias' => false, 'needs_context' => false,], 'has_any_category' => ['alias' => false, 'needs_context' => false,],
// TODO here we are
'has_any_budget' => ['alias' => false, 'needs_context' => false,], 'has_any_budget' => ['alias' => false, 'needs_context' => false,],
'has_any_bill' => ['alias' => false, 'needs_context' => false,], 'has_any_bill' => ['alias' => false, 'needs_context' => false,],
'has_any_tag' => ['alias' => false, 'needs_context' => false,], 'has_any_tag' => ['alias' => false, 'needs_context' => false,],
'any_notes' => ['alias' => false, 'needs_context' => false,], 'any_notes' => ['alias' => false, 'needs_context' => false,],
'has_any_notes' => ['alias' => true, 'alias_for' => 'any_notes', 'needs_context' => false,],
'any_external_url' => ['alias' => false, 'needs_context' => false,], 'any_external_url' => ['alias' => false, 'needs_context' => false,],
'has_any_external_url' => ['alias' => true, 'alias_for' => 'any_external_url', 'needs_context' => false,],
'has_no_attachments' => ['alias' => false, 'needs_context' => false,], 'has_no_attachments' => ['alias' => false, 'needs_context' => false,],
'has_no_category' => ['alias' => false, 'needs_context' => false,], 'has_no_category' => ['alias' => false, 'needs_context' => false,],
'has_no_budget' => ['alias' => false, 'needs_context' => false,], 'has_no_budget' => ['alias' => false, 'needs_context' => false,],
@ -128,6 +127,7 @@ return [
'before' => ['alias' => true, 'alias_for' => 'date_before', 'needs_context' => true,], 'before' => ['alias' => true, 'alias_for' => 'date_before', 'needs_context' => true,],
'date_after' => ['alias' => false, 'needs_context' => true,], 'date_after' => ['alias' => false, 'needs_context' => true,],
'after' => ['alias' => true, 'alias_for' => 'date_after', 'needs_context' => true,], 'after' => ['alias' => true, 'alias_for' => 'date_after', 'needs_context' => true,],
'interest_date_on' => ['alias' => false, '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' => ['alias' => true, 'alias_for' => 'interest_date_on', 'needs_context' => true,],
'interest_date_is' => ['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

@ -285,7 +285,7 @@ return [
// old // old
'search_modifier_date_is' => 'Transaction date is ":value"', 'search_modifier_date_on' => 'Transaction date is ":value"',
'search_modifier_id' => 'Transaction ID is ":value"', 'search_modifier_id' => 'Transaction ID is ":value"',
'search_modifier_date_before' => 'Transaction date is before or on ":value"', 'search_modifier_date_before' => 'Transaction date is before or on ":value"',
'search_modifier_date_after' => 'Transaction date is after or on ":value"', 'search_modifier_date_after' => 'Transaction date is after or on ":value"',
@ -393,6 +393,7 @@ return [
'search_modifier_foreign_amount_more' => 'The foreign amount is more than ":value"', 'search_modifier_foreign_amount_more' => 'The foreign amount is more than ":value"',
// date fields // date fields
'search_modifier_interest_date_on' => 'Transaction interest date is ":value"',
'search_modifier_interest_date_on_year' => 'Transaction interest date is in year ":value"', 'search_modifier_interest_date_on_year' => 'Transaction interest date is in year ":value"',
'search_modifier_interest_date_on_month' => 'Transaction interest date is in month ":value"', 'search_modifier_interest_date_on_month' => 'Transaction interest date is in month ":value"',
'search_modifier_interest_date_on_day' => 'Transaction interest date is on day of month ":value"', 'search_modifier_interest_date_on_day' => 'Transaction interest date is on day of month ":value"',
@ -465,7 +466,29 @@ return [
'search_modifier_created_at_after_year' => 'Transaction was created in or after year ":value"', '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_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_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_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_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_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_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_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_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_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"',
'update_rule_from_query' => 'Update rule ":rule" from search query', 'update_rule_from_query' => 'Update rule ":rule" from search query',
'create_rule_from_query' => 'Create new rule from search query', 'create_rule_from_query' => 'Create new rule from search query',

View File

@ -65,7 +65,8 @@
{{ formatAmountBySymbol(sum.amount*-1, sum.currency_symbol, sum.currency_decimal_places, false) }}{% if loop.index != group.sums|length %},{% endif %}X {{ formatAmountBySymbol(sum.amount*-1, sum.currency_symbol, sum.currency_decimal_places, false) }}{% if loop.index != group.sums|length %},{% endif %}X
</span> </span>
{% else %} {% else %}
{{ formatAmountBySymbol(sum.amount, sum.currency_symbol, sum.currency_decimal_places) }}{% if loop.index != group.sums|length %},{% endif %} X
{# {{ formatAmountBySymbol(sum.amount, sum.currency_symbol, sum.currency_decimal_places) }}{% if loop.index != group.sums|length %},{% endif %} #}
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</td> </td>
@ -196,7 +197,7 @@
{# THE REST #} {# THE REST #}
{% else %} {% 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 %} {% if null != transaction.foreign_amount %}
({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }}) ({{ formatAmountBySymbol(transaction.foreign_amount, transaction.foreign_currency_symbol, transaction.foreign_currency_decimal_places) }})
{% endif %} {% endif %}