Big refactor to remove the deprecated transaction collector.

This commit is contained in:
James Cole
2019-05-30 12:31:19 +02:00
parent 10a6ff9bf8
commit 8b7e87ae57
117 changed files with 1314 additions and 1208 deletions

View File

@@ -204,7 +204,7 @@ class AttachmentHelper implements AttachmentHelperInterface
}
Log::debug('Done processing uploads.');
}
if (!\is_array($files) || (\is_array($files) && 0 === \count($files))) {
if (!\is_array($files) || (\is_array($files) && 0 === count($files))) {
Log::debug('Array of files is not an array. Probably nothing uploaded. Will not store attachments.');
}

View File

@@ -26,7 +26,6 @@ namespace FireflyIII\Helpers\Chart;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
@@ -117,8 +116,7 @@ class MetaPieChart implements MetaPieChartInterface
$collector->setUser($this->user);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)->setTypes([TransactionType::WITHDRAWAL]);
$journals = $collector->getExtractedJournals();
$sum = $this->sumJournals($journals);
$sum = $collector->getSum();
$sum = bcmul($sum, '-1');
$sum = bcsub($sum, $this->total);
$chartData[$key] = $sum;
@@ -131,8 +129,7 @@ class MetaPieChart implements MetaPieChartInterface
$collector->setUser($this->user);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)->setTypes([TransactionType::DEPOSIT]);
$journals = $collector->getExtractedJournals();
$sum = $this->sumJournals($journals);
$sum = $collector->getSum();
$sum = bcsub($sum, $this->total);
$chartData[$key] = $sum;
}
@@ -220,22 +217,20 @@ class MetaPieChart implements MetaPieChartInterface
*
* @codeCoverageIgnore
*
* @param Collection $set
* @param array $array
*
* @return array
*/
private function groupByTag(Collection $set): array
private function groupByTag(array $array): array
{
$grouped = [];
/** @var Transaction $transaction */
foreach ($set as $transaction) {
$journal = $transaction->transactionJournal;
$tags = $journal->tags;
/** @var array $journal */
foreach ($array as $journal) {
$tags = $journal['tags'] ?? [];
/** @var Tag $tag */
foreach ($tags as $tag) {
$tagId = $tag->id;
$grouped[$tagId] = $grouped[$tagId] ?? '0';
$grouped[$tagId] = bcadd($transaction->transaction_amount, $grouped[$tagId]);
foreach ($tags as $id => $tag) {
$grouped[$id] = $grouped[$id] ?? '0';
$grouped[$id] = bcadd($journal['amount'], $grouped[$id]);
}
}
@@ -270,22 +265,6 @@ class MetaPieChart implements MetaPieChartInterface
return $chartData;
}
/**
* @param array $journals
* @return string
*/
private function sumJournals(array $journals): string
{
$sum = '0';
/** @var array $journal */
foreach ($journals as $journal) {
$amount = (string)$journal['amount'];
$sum = bcadd($sum, $amount);
}
return $sum;
}
/**
* Accounts setter.
*
@@ -413,4 +392,6 @@ class MetaPieChart implements MetaPieChartInterface
return $this;
}
}

View File

@@ -130,23 +130,15 @@ class GroupCollector implements GroupCollectorInterface
}
/**
* Return the transaction journals without group information. Is useful in some instances.
* Same as getGroups but everything is in a paginator.
*
* @return array
* @return LengthAwarePaginator
*/
public function getExtractedJournals(): array
public function getPaginatedGroups(): LengthAwarePaginator
{
$selection = $this->getGroups();
$return = [];
/** @var array $group */
foreach ($selection as $group) {
foreach ($group['transactions'] as $journalId => $journal) {
$journal['group_title'] = $group['title'];
$return[$journalId] = $journal;
}
}
$set = $this->getGroups();
return $return;
return new LengthAwarePaginator($set, $this->total, $this->limit, $this->page);
}
/**
@@ -330,18 +322,6 @@ class GroupCollector implements GroupCollectorInterface
return $groups;
}
/**
* Same as getGroups but everything is in a paginator.
*
* @return LengthAwarePaginator
*/
public function getPaginatedGroups(): LengthAwarePaginator
{
$set = $this->getGroups();
return new LengthAwarePaginator($set, $this->total, $this->limit, $this->page);
}
/**
* Define which accounts can be part of the source and destination transactions.
*
@@ -554,7 +534,7 @@ class GroupCollector implements GroupCollectorInterface
$this->query->where('transaction_journals.date', '>=', $startStr);
$this->query->where('transaction_journals.date', '<=', $endStr);
app('log')->debug(sprintf('TransactionCollector range is now %s - %s (inclusive)', $startStr, $endStr));
app('log')->debug(sprintf('GroupCollector range is now %s - %s (inclusive)', $startStr, $endStr));
return $this;
}
@@ -642,7 +622,7 @@ class GroupCollector implements GroupCollectorInterface
*/
private function startQuery(): void
{
app('log')->debug('TransactionCollector::startQuery');
app('log')->debug('GroupCollector::startQuery');
$this->query = $this->user
->transactionGroups()
->leftJoin('transaction_journals', 'transaction_journals.transaction_group_id', 'transaction_groups.id')
@@ -778,4 +758,76 @@ class GroupCollector implements GroupCollectorInterface
return $this;
}
/**
* Limit results to a transactions without a budget..
*
* @return GroupCollectorInterface
*/
public function withoutBudget(): GroupCollectorInterface
{
$this->withBudgetInformation();
$this->query->where(
function (EloquentBuilder $q) {
$q->whereNull('budget_transaction_journal.budget_id');
}
);
return $this;
}
/**
* Limit results to a transactions without a category.
*
* @return GroupCollectorInterface
*/
public function withoutCategory(): GroupCollectorInterface
{
$this->withCategoryInformation();
$this->query->where(
function (EloquentBuilder $q) {
$q->whereNull('category_transaction_journal.category_id');
}
);
return $this;
}
/**
* Return the sum of all journals.
*
* @return string
*/
public function getSum(): string
{
$journals = $this->getExtractedJournals();
$sum = '0';
/** @var array $journal */
foreach ($journals as $journal) {
$amount = (string)$journal['amount'];
$sum = bcadd($sum, $amount);
}
return $sum;
}
/**
* Return the transaction journals without group information. Is useful in some instances.
*
* @return array
*/
public function getExtractedJournals(): array
{
$selection = $this->getGroups();
$return = [];
/** @var array $group */
foreach ($selection as $group) {
foreach ($group['transactions'] as $journalId => $journal) {
$journal['group_title'] = $group['title'];
$return[$journalId] = $journal;
}
}
return $return;
}
}

View File

@@ -46,6 +46,13 @@ interface GroupCollectorInterface
*/
public function getExtractedJournals(): array;
/**
* Return the sum of all journals.
*
* @return string
*/
public function getSum(): string;
/**
* Return the groups.
*
@@ -170,6 +177,20 @@ interface GroupCollectorInterface
*/
public function setTags(Collection $tags): GroupCollectorInterface;
/**
* Limit results to a transactions without a budget.
*
* @return GroupCollectorInterface
*/
public function withoutBudget(): GroupCollectorInterface;
/**
* Limit results to a transactions without a category.
*
* @return GroupCollectorInterface
*/
public function withoutCategory(): GroupCollectorInterface;
/**
* Limit the search to one specific transaction group.
*

View File

@@ -458,7 +458,7 @@ class TransactionCollector implements TransactionCollectorInterface
public function setBudgets(Collection $budgets): TransactionCollectorInterface
{
$budgetIds = $budgets->pluck('id')->toArray();
if (0 !== \count($budgetIds)) {
if (0 !== count($budgetIds)) {
$this->joinBudgetTables();
Log::debug('Journal collector will filter for budgets', $budgetIds);
@@ -481,7 +481,7 @@ class TransactionCollector implements TransactionCollectorInterface
public function setCategories(Collection $categories): TransactionCollectorInterface
{
$categoryIds = $categories->pluck('id')->toArray();
if (0 !== \count($categoryIds)) {
if (0 !== count($categoryIds)) {
$this->joinCategoryTables();
$this->query->where(
@@ -721,7 +721,7 @@ class TransactionCollector implements TransactionCollectorInterface
*/
public function setTypes(array $types): TransactionCollectorInterface
{
if (\count($types) > 0) {
if (count($types) > 0) {
Log::debug('Set query collector types', $types);
$this->query->whereIn('transaction_types.type', $types);
}
@@ -849,7 +849,7 @@ class TransactionCollector implements TransactionCollectorInterface
TransactionViewFilter::class => new TransactionViewFilter,
DoubleTransactionFilter::class => new DoubleTransactionFilter,
];
Log::debug(sprintf('Will run %d filters on the set.', \count($this->filters)));
Log::debug(sprintf('Will run %d filters on the set.', count($this->filters)));
foreach ($this->filters as $enabled) {
if (isset($filters[$enabled])) {
Log::debug(sprintf('Before filter %s: %d', $enabled, $set->count()));

View File

@@ -22,7 +22,7 @@ declare(strict_types=1);
namespace FireflyIII\Helpers\Report;
use FireflyIII\Helpers\Collector\TransactionCollectorInterface;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
@@ -52,54 +52,54 @@ class PopupReport implements PopupReportInterface
/**
* Collect the transactions for one account and one budget.
*
* @param Budget $budget
* @param Budget $budget
* @param Account $account
* @param array $attributes
* @param array $attributes
*
* @return Collection
* @return array
*/
public function balanceForBudget(Budget $budget, Account $account, array $attributes): Collection
public function balanceForBudget(Budget $budget, Account $account, array $attributes): array
{
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])->setBudget($budget);
return $collector->getTransactions();
return $collector->getExtractedJournals();
}
/**
* Collect the tranactions for one account and no budget.
* Collect the transactions for one account and no budget.
*
* @param Account $account
* @param array $attributes
* @param array $attributes
*
* @return Collection
* @return array
*/
public function balanceForNoBudget(Account $account, array $attributes): Collection
public function balanceForNoBudget(Account $account, array $attributes): array
{
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector
->setAccounts(new Collection([$account]))
->setTypes([TransactionType::WITHDRAWAL])
->setRange($attributes['startDate'], $attributes['endDate'])
->withoutBudget();
return $collector->getTransactions();
return $collector->getExtractedJournals();
}
/**
* Collect the tranactions for a budget.
* Collect the transactions for a budget.
*
* @param Budget $budget
* @param array $attributes
* @param array $attributes
*
* @return Collection
* @return array
*/
public function byBudget(Budget $budget, array $attributes): Collection
public function byBudget(Budget $budget, array $attributes): array
{
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($attributes['accounts'])->setRange($attributes['startDate'], $attributes['endDate']);
@@ -110,97 +110,93 @@ class PopupReport implements PopupReportInterface
$collector->setBudget($budget);
}
return $collector->getTransactions();
return $collector->getExtractedJournals();
}
/**
* Collect journals by a category.
*
* @param Category $category
* @param array $attributes
* @param array $attributes
*
* @return Collection
* @return array
*/
public function byCategory(Category $category, array $attributes): Collection
public function byCategory(Category $category, array $attributes): array
{
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts($attributes['accounts'])->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER])
->setRange($attributes['startDate'], $attributes['endDate'])->withOpposingAccount()
->setRange($attributes['startDate'], $attributes['endDate'])->withAccountInformation()
->setCategory($category);
return $collector->getTransactions();
return $collector->getExtractedJournals();
}
/**
* Group transactions by expense.
*
* @param Account $account
* @param array $attributes
* @param array $attributes
*
* @return Collection
* @return array
*/
public function byExpenses(Account $account, array $attributes): Collection
public function byExpenses(Account $account, array $attributes): array
{
/** @var JournalRepositoryInterface $repository */
$repository = app(JournalRepositoryInterface::class);
$repository->setUser($account->user);
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])
->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]);
$transactions = $collector->getTransactions();
$journals = $collector->getExtractedJournals();
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
// filter for transfers and withdrawals TO the given $account
$transactions = $transactions->filter(
function (Transaction $transaction) use ($report, $repository) {
// get the destinations:
$sources = $repository->getJournalSourceAccounts($transaction->transactionJournal)->pluck('id')->toArray();
// do these intersect with the current list?
return !empty(array_intersect($report, $sources));
$filtered = [];
// TODO not sure if filter is necessary.
/** @var array $journal */
foreach ($journals as $journal) {
if (in_array($journal['source_account_id'], $report, true)) {
$filtered[] = $journal;
}
);
return $transactions;
}
return $filtered;
}
/**
* Collect transactions by income.
*
* @param Account $account
* @param array $attributes
* @param array $attributes
*
* @return Collection
* @return array
*/
public function byIncome(Account $account, array $attributes): Collection
public function byIncome(Account $account, array $attributes): array
{
/** @var JournalRepositoryInterface $repository */
$repository = app(JournalRepositoryInterface::class);
$repository->setUser($account->user);
/** @var TransactionCollectorInterface $collector */
$collector = app(TransactionCollectorInterface::class);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($attributes['startDate'], $attributes['endDate'])
->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER]);
$transactions = $collector->getTransactions();
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER])
->withAccountInformation();
$journals = $collector->getExtractedJournals();
$report = $attributes['accounts']->pluck('id')->toArray(); // accounts used in this report
// filter the set so the destinations outside of $attributes['accounts'] are not included.
$transactions = $transactions->filter(
function (Transaction $transaction) use ($report, $repository) {
// get the destinations:
$journal = $transaction->transactionJournal;
$destinations = $repository->getJournalDestinationAccounts($journal)->pluck('id')->toArray();
// do these intersect with the current list?
return !empty(array_intersect($report, $destinations));
// TODO not sure if filter is necessary.
$filtered = [];
/** @var array $journal */
foreach ($journals as $journal) {
if (in_array($journal['destination_account_id'], $report, true)) {
$filtered[] = $journal;
}
);
return $transactions;
}
return $filtered;
}
}

View File

@@ -39,9 +39,9 @@ interface PopupReportInterface
* @param Account $account
* @param array $attributes
*
* @return Collection
* @return array
*/
public function balanceForBudget(Budget $budget, Account $account, array $attributes): Collection;
public function balanceForBudget(Budget $budget, Account $account, array $attributes): array;
/**
* Get balances for transactions without a budget.
@@ -49,9 +49,9 @@ interface PopupReportInterface
* @param Account $account
* @param array $attributes
*
* @return Collection
* @return array
*/
public function balanceForNoBudget(Account $account, array $attributes): Collection;
public function balanceForNoBudget(Account $account, array $attributes): array;
/**
* Group by budget.
@@ -59,9 +59,9 @@ interface PopupReportInterface
* @param Budget $budget
* @param array $attributes
*
* @return Collection
* @return array
*/
public function byBudget(Budget $budget, array $attributes): Collection;
public function byBudget(Budget $budget, array $attributes): array;
/**
* Group by category.
@@ -69,9 +69,9 @@ interface PopupReportInterface
* @param Category $category
* @param array $attributes
*
* @return Collection
* @return array
*/
public function byCategory(Category $category, array $attributes): Collection;
public function byCategory(Category $category, array $attributes): array;
/**
* Do something with expense. Sorry, I am not very inspirational here.
@@ -79,9 +79,9 @@ interface PopupReportInterface
* @param Account $account
* @param array $attributes
*
* @return Collection
* @return array
*/
public function byExpenses(Account $account, array $attributes): Collection;
public function byExpenses(Account $account, array $attributes): array;
/**
* Do something with income. Sorry, I am not very inspirational here.
@@ -89,7 +89,7 @@ interface PopupReportInterface
* @param Account $account
* @param array $attributes
*
* @return Collection
* @return array
*/
public function byIncome(Account $account, array $attributes): Collection;
public function byIncome(Account $account, array $attributes): array;
}

View File

@@ -57,9 +57,9 @@ trait UpdateTrait
// get releases from array.
$releases = $request->getReleases();
Log::debug(sprintf('Found %d releases', \count($releases)));
Log::debug(sprintf('Found %d releases', count($releases)));
if (\count($releases) > 0) {
if (count($releases) > 0) {
// first entry should be the latest entry:
/** @var Release $first */
$first = reset($releases);