mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-12 15:35:15 +00:00
Expand query search.
This commit is contained in:
@@ -216,9 +216,9 @@ trait AccountCollection
|
||||
$this->query->leftJoin('account_types as dest_account_type', 'dest_account_type.id', '=', 'dest_account.account_type_id');
|
||||
|
||||
// and add fields:
|
||||
$this->fields[] = 'dest_account.name as destination_account_name';
|
||||
$this->fields[] = 'dest_account.iban as destination_account_iban';
|
||||
$this->fields[] = 'dest_account_type.type as destination_account_type';
|
||||
$this->fields[] = 'dest_account.name as destination_account_name';
|
||||
$this->fields[] = 'dest_account.iban as destination_account_iban';
|
||||
$this->fields[] = 'dest_account_type.type as destination_account_type';
|
||||
$this->hasAccountInfo = true;
|
||||
}
|
||||
|
||||
|
@@ -32,20 +32,20 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
*/
|
||||
trait CollectorProperties
|
||||
{
|
||||
private array $fields;
|
||||
private bool $hasAccountInfo;
|
||||
private bool $hasBillInformation;
|
||||
private bool $hasBudgetInformation;
|
||||
private bool $hasCatInformation;
|
||||
private bool $hasJoinedAttTables;
|
||||
private bool $hasJoinedMetaTables;
|
||||
private bool $hasJoinedTagTables;
|
||||
private bool $hasNotesInformation;
|
||||
private array $integerFields;
|
||||
private ?int $limit;
|
||||
private ?int $page;
|
||||
private array $fields;
|
||||
private bool $hasAccountInfo;
|
||||
private bool $hasBillInformation;
|
||||
private bool $hasBudgetInformation;
|
||||
private bool $hasCatInformation;
|
||||
private bool $hasJoinedAttTables;
|
||||
private bool $hasJoinedMetaTables;
|
||||
private bool $hasJoinedTagTables;
|
||||
private bool $hasNotesInformation;
|
||||
private array $integerFields;
|
||||
private ?int $limit;
|
||||
private ?int $page;
|
||||
private array $postFilters;
|
||||
private HasMany $query;
|
||||
private int $total;
|
||||
private ?User $user;
|
||||
private array $postFilters;
|
||||
private int $total;
|
||||
private ?User $user;
|
||||
}
|
||||
|
@@ -39,6 +39,50 @@ use Log;
|
||||
*/
|
||||
trait MetaCollection
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function externalIdContains(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$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.data', 'LIKE', sprintf('%%%s%%', $externalId));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function externalIdEnds(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$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.data', 'LIKE', sprintf('%%%s"', $externalId));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function externalIdStarts(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$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.data', 'LIKE', sprintf('"%s%%', $externalId));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Where has no tags.
|
||||
@@ -53,6 +97,82 @@ trait MetaCollection
|
||||
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
|
||||
*/
|
||||
public function internalReferenceContains(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$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.data', 'LIKE', sprintf('%%%s%%', $externalId));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function internalReferenceEnds(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$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.data', 'LIKE', sprintf('%%%s"', $externalId));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function internalReferenceStarts(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$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.data', 'LIKE', sprintf('"%s%%', $externalId));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
@@ -66,6 +186,29 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withNotes(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasNotesInformation) {
|
||||
// join bill table
|
||||
$this->query->leftJoin(
|
||||
'notes',
|
||||
static function (JoinClause $join) {
|
||||
$join->on('notes.noteable_id', '=', 'transaction_journals.id');
|
||||
$join->where('notes.noteable_type', '=', 'FireflyIII\Models\TransactionJournal');
|
||||
$join->whereNull('notes.deleted_at');
|
||||
}
|
||||
);
|
||||
// add fields
|
||||
$this->fields[] = 'notes.text as notes';
|
||||
$this->hasNotesInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
@@ -120,6 +263,25 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include bill name + ID, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withBillInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasBillInformation) {
|
||||
// join bill table
|
||||
$this->query->leftJoin('bills', 'bills.id', '=', 'transaction_journals.bill_id');
|
||||
// add fields
|
||||
$this->fields[] = 'bills.id as bill_id';
|
||||
$this->fields[] = 'bills.name as bill_name';
|
||||
$this->hasBillInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the search to a specific set of bills.
|
||||
*
|
||||
@@ -150,6 +312,27 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include budget ID + name, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withBudgetInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasBudgetInformation) {
|
||||
// join link table
|
||||
$this->query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
// join cat table
|
||||
$this->query->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id');
|
||||
// add fields
|
||||
$this->fields[] = 'budgets.id as budget_id';
|
||||
$this->fields[] = 'budgets.name as budget_name';
|
||||
$this->hasBudgetInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the search to a specific set of budgets.
|
||||
*
|
||||
@@ -184,6 +367,27 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include category ID + name, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withCategoryInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasCatInformation) {
|
||||
// join link table
|
||||
$this->query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
// join cat table
|
||||
$this->query->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id');
|
||||
// add fields
|
||||
$this->fields[] = 'categories.id as category_id';
|
||||
$this->fields[] = 'categories.name as category_name';
|
||||
$this->hasCatInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the search to a specific category.
|
||||
*
|
||||
@@ -214,87 +418,6 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function externalIdContains(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$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.data', 'LIKE', sprintf('%%%s%%', $externalId));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function externalIdEnds(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$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.data', 'LIKE', sprintf('%%%s"', $externalId));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function externalIdStarts(string $externalId): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$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.data', 'LIKE', sprintf('"%s%%', $externalId));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withoutExternalUrl(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$this->hasJoinedMetaTables = true;
|
||||
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
|
||||
}
|
||||
$this->query->where(function (Builder $q1) {
|
||||
$q1->where(function (Builder $q2) {
|
||||
$q2->where('journal_meta.name', '=', 'external_url');
|
||||
$q2->whereNull('journal_meta.data');
|
||||
})->orWhere(function (Builder $q3) {
|
||||
$q3->where('journal_meta.name', '!=', 'external_url');
|
||||
});
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withExternalUrl(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$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->whereNotNull('journal_meta.data');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -353,11 +476,11 @@ trait MetaCollection
|
||||
$this->withTagInformation();
|
||||
|
||||
// this method adds a "postFilter" to the collector.
|
||||
$list = $tags->pluck('tag')->toArray();
|
||||
$filter = function (int $index, array $object) use ($list): bool {
|
||||
foreach($object['transactions'] as $transaction) {
|
||||
foreach($transaction['tags'] as $tag) {
|
||||
if(in_array($tag['name'], $list)) {
|
||||
$list = $tags->pluck('tag')->toArray();
|
||||
$filter = function (int $index, array $object) use ($list): bool {
|
||||
foreach ($object['transactions'] as $transaction) {
|
||||
foreach ($transaction['tags'] as $tag) {
|
||||
if (in_array($tag['name'], $list)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -394,25 +517,6 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include bill name + ID, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withBillInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasBillInformation) {
|
||||
// join bill table
|
||||
$this->query->leftJoin('bills', 'bills.id', '=', 'transaction_journals.bill_id');
|
||||
// add fields
|
||||
$this->fields[] = 'bills.id as bill_id';
|
||||
$this->fields[] = 'bills.name as bill_name';
|
||||
$this->hasBillInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to a transactions without a budget..
|
||||
*
|
||||
@@ -426,27 +530,6 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include budget ID + name, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withBudgetInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasBudgetInformation) {
|
||||
// join link table
|
||||
$this->query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
// join cat table
|
||||
$this->query->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id');
|
||||
// add fields
|
||||
$this->fields[] = 'budgets.id as budget_id';
|
||||
$this->fields[] = 'budgets.name as budget_name';
|
||||
$this->hasBudgetInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to a transactions without a category.
|
||||
*
|
||||
@@ -460,64 +543,17 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will include category ID + name, if any.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withCategoryInformation(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasCatInformation) {
|
||||
// join link table
|
||||
$this->query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id');
|
||||
// join cat table
|
||||
$this->query->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id');
|
||||
// add fields
|
||||
$this->fields[] = 'categories.id as category_id';
|
||||
$this->fields[] = 'categories.name as category_name';
|
||||
$this->hasCatInformation = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withNotes(): GroupCollectorInterface
|
||||
public function withExternalUrl(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasNotesInformation) {
|
||||
// join bill table
|
||||
$this->query->leftJoin(
|
||||
'notes',
|
||||
static function (JoinClause $join) {
|
||||
$join->on('notes.noteable_id', '=', 'transaction_journals.id');
|
||||
$join->where('notes.noteable_type', '=', 'FireflyIII\Models\TransactionJournal');
|
||||
$join->whereNull('notes.deleted_at');
|
||||
}
|
||||
);
|
||||
// add fields
|
||||
$this->fields[] = 'notes.text as notes';
|
||||
$this->hasNotesInformation = true;
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$this->hasJoinedMetaTables = true;
|
||||
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_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();
|
||||
$this->query->where('journal_meta.name', '=', 'external_url');
|
||||
$this->query->whereNotNull('journal_meta.data');
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -560,6 +596,27 @@ trait MetaCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withoutExternalUrl(): GroupCollectorInterface
|
||||
{
|
||||
if (false === $this->hasJoinedMetaTables) {
|
||||
$this->hasJoinedMetaTables = true;
|
||||
$this->query->leftJoin('journal_meta', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id');
|
||||
}
|
||||
$this->query->where(function (Builder $q1) {
|
||||
$q1->where(function (Builder $q2) {
|
||||
$q2->where('journal_meta.name', '=', 'external_url');
|
||||
$q2->whereNull('journal_meta.data');
|
||||
})->orWhere(function (Builder $q3) {
|
||||
$q3->where('journal_meta.name', '!=', 'external_url');
|
||||
});
|
||||
});
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
@@ -586,17 +643,4 @@ trait MetaCollection
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -33,6 +33,45 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||
trait TimeCollection
|
||||
{
|
||||
|
||||
public function dayAfter(string $day): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereDay('transaction_journals.date', '>=', $day);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dayBefore(string $day): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereDay('transaction_journals.date', '<=', $day);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function dayIs(string $day): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereDay('transaction_journals.date', '=', $day);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function monthAfter(string $month): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereMonth('transaction_journals.date', '>=', $month);
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function monthBefore(string $month): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereMonth('transaction_journals.date', '<=', $month);
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function monthIs(string $month): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereMonth('transaction_journals.date', '=', $month);
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect transactions after a specific date.
|
||||
*
|
||||
@@ -120,22 +159,9 @@ trait TimeCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function yearIs(string $year): GroupCollectorInterface
|
||||
public function yearAfter(string $year): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereYear('transaction_journals.date', '=', $year);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function monthIs(string $month): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereMonth('transaction_journals.date', '=', $month);
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function dayIs(string $day): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereDay('transaction_journals.date', '=', $day);
|
||||
$this->query->whereYear('transaction_journals.date', '>=', $year);
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -145,35 +171,9 @@ trait TimeCollection
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function monthBefore(string $month): GroupCollectorInterface
|
||||
public function yearIs(string $year): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereMonth('transaction_journals.date', '<=', $month);
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function dayBefore(string $day): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereDay('transaction_journals.date', '<=', $day);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function yearAfter(string $year): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereYear('transaction_journals.date', '>=', $year);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function monthAfter(string $month): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereMonth('transaction_journals.date', '>=', $month);
|
||||
return $this;
|
||||
|
||||
}
|
||||
|
||||
public function dayAfter(string $day): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereDay('transaction_journals.date', '>=', $day);
|
||||
$this->query->whereYear('transaction_journals.date', '=', $year);
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@@ -203,6 +203,26 @@ class GroupCollector implements GroupCollectorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function dumpQuery(): void
|
||||
{
|
||||
echo $this->query->select($this->fields)->toSql();
|
||||
echo '<pre>';
|
||||
print_r($this->query->getBindings());
|
||||
echo '</pre>';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function dumpQueryInLogs(): void
|
||||
{
|
||||
Log::debug($this->query->select($this->fields)->toSql());
|
||||
Log::debug('Bindings', $this->query->getBindings());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -263,388 +283,6 @@ class GroupCollector implements GroupCollectorInterface
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as getGroups but everything is in a paginator.
|
||||
*
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function getPaginatedGroups(): LengthAwarePaginator
|
||||
{
|
||||
$set = $this->getGroups();
|
||||
if (0 === $this->limit) {
|
||||
$this->setLimit(50);
|
||||
}
|
||||
|
||||
return new LengthAwarePaginator($set, $this->total, $this->limit, $this->page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has attachments
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function hasAttachments(): GroupCollectorInterface
|
||||
{
|
||||
Log::debug('Add filter on attachment ID.');
|
||||
$this->joinAttachmentTables();
|
||||
$this->query->whereNotNull('attachments.attachable_id');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to a specific currency, either foreign or normal one.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setCurrency(TransactionCurrency $currency): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where(
|
||||
static function (EloquentBuilder $q) use ($currency) {
|
||||
$q->where('source.transaction_currency_id', $currency->id);
|
||||
$q->orWhere('source.foreign_currency_id', $currency->id);
|
||||
}
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setForeignCurrency(TransactionCurrency $currency): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('source.foreign_currency_id', $currency->id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the result to a set of specific transaction groups.
|
||||
*
|
||||
* @param array $groupIds
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setIds(array $groupIds): GroupCollectorInterface
|
||||
{
|
||||
|
||||
$this->query->whereIn('transaction_groups.id', $groupIds);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the result to a set of specific journals.
|
||||
*
|
||||
* @param array $journalIds
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setJournalIds(array $journalIds): GroupCollectorInterface
|
||||
{
|
||||
if (!empty($journalIds)) {
|
||||
// make all integers.
|
||||
$integerIDs = array_map('intval', $journalIds);
|
||||
|
||||
|
||||
$this->query->whereIn('transaction_journals.id', $integerIDs);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the number of returned entries.
|
||||
*
|
||||
* @param int $limit
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setLimit(int $limit): GroupCollectorInterface
|
||||
{
|
||||
$this->limit = $limit;
|
||||
app('log')->debug(sprintf('GroupCollector: The limit is now %d', $limit));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the page to get.
|
||||
*
|
||||
* @param int $page
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setPage(int $page): GroupCollectorInterface
|
||||
{
|
||||
$page = 0 === $page ? 1 : $page;
|
||||
$this->page = $page;
|
||||
app('log')->debug(sprintf('GroupCollector: page is now %d', $page));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for words in descriptions.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setSearchWords(array $array): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where(
|
||||
static function (EloquentBuilder $q) use ($array) {
|
||||
$q->where(
|
||||
static function (EloquentBuilder $q1) use ($array) {
|
||||
foreach ($array as $word) {
|
||||
$keyword = sprintf('%%%s%%', $word);
|
||||
$q1->where('transaction_journals.description', 'LIKE', $keyword);
|
||||
}
|
||||
}
|
||||
);
|
||||
$q->orWhere(
|
||||
static function (EloquentBuilder $q2) use ($array) {
|
||||
foreach ($array as $word) {
|
||||
$keyword = sprintf('%%%s%%', $word);
|
||||
$q2->where('transaction_groups.title', 'LIKE', $keyword);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the search to one specific transaction group.
|
||||
*
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setTransactionGroup(TransactionGroup $transactionGroup): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('transaction_groups.id', $transactionGroup->id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the included transaction types.
|
||||
*
|
||||
* @param array $types
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setTypes(array $types): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereIn('transaction_types.type', $types);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user object and start the query.
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setUser(User $user): GroupCollectorInterface
|
||||
{
|
||||
if (null === $this->user) {
|
||||
$this->user = $user;
|
||||
$this->startQuery();
|
||||
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically include all stuff required to make API calls work.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withAPIInformation(): GroupCollectorInterface
|
||||
{
|
||||
// include source + destination account name and type.
|
||||
$this->withAccountInformation()
|
||||
// include category ID + name (if any)
|
||||
->withCategoryInformation()
|
||||
// include budget ID + name (if any)
|
||||
->withBudgetInformation()
|
||||
// include bill ID + name (if any)
|
||||
->withBillInformation();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withAttachmentInformation(): GroupCollectorInterface
|
||||
{
|
||||
$this->fields[] = 'attachments.id as attachment_id';
|
||||
$this->fields[] = 'attachments.uploaded as attachment_uploaded';
|
||||
$this->joinAttachmentTables();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join table to get attachment information.
|
||||
*/
|
||||
private function joinAttachmentTables(): void
|
||||
{
|
||||
if (false === $this->hasJoinedAttTables) {
|
||||
// join some extra tables:
|
||||
$this->hasJoinedAttTables = true;
|
||||
$this->query->leftJoin('attachments', 'attachments.attachable_id', '=', 'transaction_journals.id')
|
||||
->where(
|
||||
static function (EloquentBuilder $q1) {
|
||||
$q1->where('attachments.attachable_type', TransactionJournal::class);
|
||||
//$q1->where('attachments.uploaded', true);
|
||||
$q1->orWhereNull('attachments.attachable_type');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the query.
|
||||
*/
|
||||
private function startQuery(): void
|
||||
{
|
||||
//app('log')->debug('GroupCollector::startQuery');
|
||||
$this->query = $this->user
|
||||
//->transactionGroups()
|
||||
//->leftJoin('transaction_journals', 'transaction_journals.transaction_group_id', 'transaction_groups.id')
|
||||
->transactionJournals()
|
||||
->leftJoin('transaction_groups', 'transaction_journals.transaction_group_id', 'transaction_groups.id')
|
||||
|
||||
// join source transaction.
|
||||
->leftJoin(
|
||||
'transactions as source',
|
||||
function (JoinClause $join) {
|
||||
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('source.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
// join destination transaction
|
||||
->leftJoin(
|
||||
'transactions as destination',
|
||||
function (JoinClause $join) {
|
||||
$join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('destination.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
// left join transaction type.
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('transaction_currencies as currency', 'currency.id', '=', 'source.transaction_currency_id')
|
||||
->leftJoin('transaction_currencies as foreign_currency', 'foreign_currency.id', '=', 'source.foreign_currency_id')
|
||||
->whereNull('transaction_groups.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('source.deleted_at')
|
||||
->whereNull('destination.deleted_at')
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->orderBy('transaction_journals.description', 'DESC')
|
||||
->orderBy('source.amount', 'DESC');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function dumpQuery(): void
|
||||
{
|
||||
echo $this->query->select($this->fields)->toSql();
|
||||
echo '<pre>';
|
||||
print_r($this->query->getBindings());
|
||||
echo '</pre>';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function dumpQueryInLogs(): void
|
||||
{
|
||||
Log::debug($this->query->select($this->fields)->toSql());
|
||||
Log::debug('Bindings', $this->query->getBindings());
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a selected set of fields to arrays.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function convertToInteger(array $array): array
|
||||
{
|
||||
foreach ($this->integerFields as $field) {
|
||||
$array[$field] = array_key_exists($field, $array) ? (int) $array[$field] : null;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $existingJournal
|
||||
* @param TransactionJournal $newJournal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mergeAttachments(array $existingJournal, TransactionJournal $newJournal): array
|
||||
{
|
||||
$newArray = $newJournal->toArray();
|
||||
if (array_key_exists('attachment_id', $newArray)) {
|
||||
$attachmentId = (int) $newJournal['attachment_id'];
|
||||
|
||||
$existingJournal['attachments'][$attachmentId] = [
|
||||
'id' => $attachmentId,
|
||||
];
|
||||
}
|
||||
|
||||
return $existingJournal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $existingJournal
|
||||
* @param TransactionJournal $newJournal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mergeTags(array $existingJournal, TransactionJournal $newJournal): array
|
||||
{
|
||||
$newArray = $newJournal->toArray();
|
||||
if (array_key_exists('tag_id', $newArray)) { // assume the other fields are present as well.
|
||||
$tagId = (int) $newJournal['tag_id'];
|
||||
|
||||
$tagDate = null;
|
||||
try {
|
||||
$tagDate = Carbon::parse($newArray['tag_date']);
|
||||
} catch (InvalidDateException $e) {
|
||||
Log::debug(sprintf('Could not parse date: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
$existingJournal['tags'][$tagId] = [
|
||||
'id' => (int) $newArray['tag_id'],
|
||||
'name' => $newArray['tag_name'],
|
||||
'date' => $tagDate,
|
||||
'description' => $newArray['tag_description'],
|
||||
];
|
||||
}
|
||||
|
||||
return $existingJournal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $collection
|
||||
*
|
||||
@@ -754,6 +392,72 @@ class GroupCollector implements GroupCollectorInterface
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a selected set of fields to arrays.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function convertToInteger(array $array): array
|
||||
{
|
||||
foreach ($this->integerFields as $field) {
|
||||
$array[$field] = array_key_exists($field, $array) ? (int) $array[$field] : null;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $existingJournal
|
||||
* @param TransactionJournal $newJournal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mergeTags(array $existingJournal, TransactionJournal $newJournal): array
|
||||
{
|
||||
$newArray = $newJournal->toArray();
|
||||
if (array_key_exists('tag_id', $newArray)) { // assume the other fields are present as well.
|
||||
$tagId = (int) $newJournal['tag_id'];
|
||||
|
||||
$tagDate = null;
|
||||
try {
|
||||
$tagDate = Carbon::parse($newArray['tag_date']);
|
||||
} catch (InvalidDateException $e) {
|
||||
Log::debug(sprintf('Could not parse date: %s', $e->getMessage()));
|
||||
}
|
||||
|
||||
$existingJournal['tags'][$tagId] = [
|
||||
'id' => (int) $newArray['tag_id'],
|
||||
'name' => $newArray['tag_name'],
|
||||
'date' => $tagDate,
|
||||
'description' => $newArray['tag_description'],
|
||||
];
|
||||
}
|
||||
|
||||
return $existingJournal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $existingJournal
|
||||
* @param TransactionJournal $newJournal
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function mergeAttachments(array $existingJournal, TransactionJournal $newJournal): array
|
||||
{
|
||||
$newArray = $newJournal->toArray();
|
||||
if (array_key_exists('attachment_id', $newArray)) {
|
||||
$attachmentId = (int) $newJournal['attachment_id'];
|
||||
|
||||
$existingJournal['attachments'][$attachmentId] = [
|
||||
'id' => $attachmentId,
|
||||
];
|
||||
}
|
||||
|
||||
return $existingJournal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $groups
|
||||
*
|
||||
@@ -824,4 +528,300 @@ class GroupCollector implements GroupCollectorInterface
|
||||
}
|
||||
return $newCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as getGroups but everything is in a paginator.
|
||||
*
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function getPaginatedGroups(): LengthAwarePaginator
|
||||
{
|
||||
$set = $this->getGroups();
|
||||
if (0 === $this->limit) {
|
||||
$this->setLimit(50);
|
||||
}
|
||||
|
||||
return new LengthAwarePaginator($set, $this->total, $this->limit, $this->page);
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the number of returned entries.
|
||||
*
|
||||
* @param int $limit
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setLimit(int $limit): GroupCollectorInterface
|
||||
{
|
||||
$this->limit = $limit;
|
||||
app('log')->debug(sprintf('GroupCollector: The limit is now %d', $limit));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Has attachments
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function hasAttachments(): GroupCollectorInterface
|
||||
{
|
||||
Log::debug('Add filter on attachment ID.');
|
||||
$this->joinAttachmentTables();
|
||||
$this->query->whereNotNull('attachments.attachable_id');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join table to get attachment information.
|
||||
*/
|
||||
private function joinAttachmentTables(): void
|
||||
{
|
||||
if (false === $this->hasJoinedAttTables) {
|
||||
// join some extra tables:
|
||||
$this->hasJoinedAttTables = true;
|
||||
$this->query->leftJoin('attachments', 'attachments.attachable_id', '=', 'transaction_journals.id')
|
||||
->where(
|
||||
static function (EloquentBuilder $q1) {
|
||||
$q1->where('attachments.attachable_type', TransactionJournal::class);
|
||||
//$q1->where('attachments.uploaded', true);
|
||||
$q1->orWhereNull('attachments.attachable_type');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit results to a specific currency, either foreign or normal one.
|
||||
*
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setCurrency(TransactionCurrency $currency): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where(
|
||||
static function (EloquentBuilder $q) use ($currency) {
|
||||
$q->where('source.transaction_currency_id', $currency->id);
|
||||
$q->orWhere('source.foreign_currency_id', $currency->id);
|
||||
}
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function setForeignCurrency(TransactionCurrency $currency): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('source.foreign_currency_id', $currency->id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the result to a set of specific transaction groups.
|
||||
*
|
||||
* @param array $groupIds
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setIds(array $groupIds): GroupCollectorInterface
|
||||
{
|
||||
|
||||
$this->query->whereIn('transaction_groups.id', $groupIds);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the result to a set of specific journals.
|
||||
*
|
||||
* @param array $journalIds
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setJournalIds(array $journalIds): GroupCollectorInterface
|
||||
{
|
||||
if (!empty($journalIds)) {
|
||||
// make all integers.
|
||||
$integerIDs = array_map('intval', $journalIds);
|
||||
|
||||
|
||||
$this->query->whereIn('transaction_journals.id', $integerIDs);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the page to get.
|
||||
*
|
||||
* @param int $page
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setPage(int $page): GroupCollectorInterface
|
||||
{
|
||||
$page = 0 === $page ? 1 : $page;
|
||||
$this->page = $page;
|
||||
app('log')->debug(sprintf('GroupCollector: page is now %d', $page));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for words in descriptions.
|
||||
*
|
||||
* @param array $array
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setSearchWords(array $array): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where(
|
||||
static function (EloquentBuilder $q) use ($array) {
|
||||
$q->where(
|
||||
static function (EloquentBuilder $q1) use ($array) {
|
||||
foreach ($array as $word) {
|
||||
$keyword = sprintf('%%%s%%', $word);
|
||||
$q1->where('transaction_journals.description', 'LIKE', $keyword);
|
||||
}
|
||||
}
|
||||
);
|
||||
$q->orWhere(
|
||||
static function (EloquentBuilder $q2) use ($array) {
|
||||
foreach ($array as $word) {
|
||||
$keyword = sprintf('%%%s%%', $word);
|
||||
$q2->where('transaction_groups.title', 'LIKE', $keyword);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the search to one specific transaction group.
|
||||
*
|
||||
* @param TransactionGroup $transactionGroup
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setTransactionGroup(TransactionGroup $transactionGroup): GroupCollectorInterface
|
||||
{
|
||||
$this->query->where('transaction_groups.id', $transactionGroup->id);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the included transaction types.
|
||||
*
|
||||
* @param array $types
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setTypes(array $types): GroupCollectorInterface
|
||||
{
|
||||
$this->query->whereIn('transaction_types.type', $types);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user object and start the query.
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setUser(User $user): GroupCollectorInterface
|
||||
{
|
||||
if (null === $this->user) {
|
||||
$this->user = $user;
|
||||
$this->startQuery();
|
||||
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the query.
|
||||
*/
|
||||
private function startQuery(): void
|
||||
{
|
||||
//app('log')->debug('GroupCollector::startQuery');
|
||||
$this->query = $this->user
|
||||
//->transactionGroups()
|
||||
//->leftJoin('transaction_journals', 'transaction_journals.transaction_group_id', 'transaction_groups.id')
|
||||
->transactionJournals()
|
||||
->leftJoin('transaction_groups', 'transaction_journals.transaction_group_id', 'transaction_groups.id')
|
||||
|
||||
// join source transaction.
|
||||
->leftJoin(
|
||||
'transactions as source',
|
||||
function (JoinClause $join) {
|
||||
$join->on('source.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('source.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
// join destination transaction
|
||||
->leftJoin(
|
||||
'transactions as destination',
|
||||
function (JoinClause $join) {
|
||||
$join->on('destination.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('destination.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
// left join transaction type.
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin('transaction_currencies as currency', 'currency.id', '=', 'source.transaction_currency_id')
|
||||
->leftJoin('transaction_currencies as foreign_currency', 'foreign_currency.id', '=', 'source.foreign_currency_id')
|
||||
->whereNull('transaction_groups.deleted_at')
|
||||
->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('source.deleted_at')
|
||||
->whereNull('destination.deleted_at')
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->orderBy('transaction_journals.description', 'DESC')
|
||||
->orderBy('source.amount', 'DESC');
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatically include all stuff required to make API calls work.
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withAPIInformation(): GroupCollectorInterface
|
||||
{
|
||||
// include source + destination account name and type.
|
||||
$this->withAccountInformation()
|
||||
// include category ID + name (if any)
|
||||
->withCategoryInformation()
|
||||
// include budget ID + name (if any)
|
||||
->withBudgetInformation()
|
||||
// include bill ID + name (if any)
|
||||
->withBillInformation();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function withAttachmentInformation(): GroupCollectorInterface
|
||||
{
|
||||
$this->fields[] = 'attachments.id as attachment_id';
|
||||
$this->fields[] = 'attachments.uploaded as attachment_uploaded';
|
||||
$this->joinAttachmentTables();
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@@ -66,6 +66,24 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function amountMore(string $amount): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $day
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function dayAfter(string $day): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $day
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function dayBefore(string $day): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $day
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function dayIs(string $day): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* End of the description must match:
|
||||
*
|
||||
@@ -111,6 +129,24 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function excludeSourceAccounts(Collection $accounts): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $externalId
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function externalIdContains(string $externalId): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $externalId
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function externalIdEnds(string $externalId): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $externalId
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function externalIdStarts(string $externalId): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Ensure the search will find nothing at all, zero results.
|
||||
*
|
||||
@@ -151,6 +187,42 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function hasAttachments(): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $externalId
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function internalReferenceContains(string $externalId): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $externalId
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function internalReferenceEnds(string $externalId): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $externalId
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function internalReferenceStarts(string $externalId): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $month
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function monthAfter(string $month): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $month
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function monthBefore(string $month): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $month
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function monthIs(string $month): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
*
|
||||
@@ -305,38 +377,6 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function setExternalId(string $externalId): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $externalId
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function externalIdContains(string $externalId): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $externalId
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function externalIdStarts(string $externalId): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $externalId
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function externalIdEnds(string $externalId): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Transactions without an external URL
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withoutExternalUrl(): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Transactions with an external URL
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withExternalUrl(): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Limit results to a specific foreign currency.
|
||||
*
|
||||
@@ -437,15 +477,6 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function setTags(Collection $tags): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Only when does not have these tags
|
||||
*
|
||||
* @param Collection $tags
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setWithoutSpecificTags(Collection $tags): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Limit the search to one specific transaction group.
|
||||
*
|
||||
@@ -482,6 +513,15 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function setUser(User $user): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Only when does not have these tags
|
||||
*
|
||||
* @param Collection $tags
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function setWithoutSpecificTags(Collection $tags): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Either account can be set, but NOT both. This effectively excludes internal transfers.
|
||||
*
|
||||
@@ -561,6 +601,13 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function withCategoryInformation(): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Transactions with an external URL
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withExternalUrl(): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Will include notes.
|
||||
*
|
||||
@@ -596,6 +643,13 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function withoutCategory(): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* Transactions without an external URL
|
||||
*
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function withoutExternalUrl(): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
@@ -606,15 +660,22 @@ interface GroupCollectorInterface
|
||||
*/
|
||||
public function withoutTags(): GroupCollectorInterface;
|
||||
|
||||
|
||||
public function yearIs(string $year): GroupCollectorInterface;
|
||||
public function monthIs(string $month): GroupCollectorInterface;
|
||||
public function dayIs(string $day): GroupCollectorInterface;
|
||||
public function yearBefore(string $year): GroupCollectorInterface;
|
||||
public function monthBefore(string $month): GroupCollectorInterface;
|
||||
public function dayBefore(string $day): GroupCollectorInterface;
|
||||
/**
|
||||
* @param string $year
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function yearAfter(string $year): GroupCollectorInterface;
|
||||
public function monthAfter(string $month): GroupCollectorInterface;
|
||||
public function dayAfter(string $day): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $year
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function yearBefore(string $year): GroupCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param string $year
|
||||
* @return GroupCollectorInterface
|
||||
*/
|
||||
public function yearIs(string $year): GroupCollectorInterface;
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user