This commit is contained in:
James Cole
2026-03-21 15:05:00 +01:00
parent 0c598cb034
commit e9a37592ba
2 changed files with 68 additions and 102 deletions
+68 -92
View File
@@ -48,7 +48,6 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Override;
use Safe\Exceptions\JsonException;
use function Safe\json_decode;
/**
@@ -68,15 +67,13 @@ class GroupCollector implements GroupCollectorInterface
*/
public function __construct()
{
$this->sorting = [];
$this->postFilters = [];
$this->tags = [];
$this->user = null;
$this->userGroup = null;
$this->limit = null;
$this->page = null;
$this->startRow = null;
$this->endRow = null;
$this->sorting = [];
$this->postFilters = [];
$this->tags = [];
$this->user = null;
$this->userGroup = null;
$this->limit = null;
$this->page = null;
$this->hasAccountInfo = false;
$this->hasCatInformation = false;
@@ -274,16 +271,16 @@ class GroupCollector implements GroupCollectorInterface
foreach ($params as $param) {
$replace = sprintf('"%s"', $param);
if (is_int($param)) {
$replace = (string) $param;
$replace = (string)$param;
}
$pos = strpos($query, '?');
$pos = strpos($query, '?');
if (false !== $pos) {
$query = substr_replace($query, $replace, $pos, 1);
}
}
echo $query;
exit(PHP_EOL.'To see the query, uncomment the next lines first.');
exit(PHP_EOL . 'To see the query, uncomment the next lines first.');
// echo '<pre>';
// print_r($this->query->getBindings());
@@ -443,31 +440,29 @@ class GroupCollector implements GroupCollectorInterface
$this->query->orWhereIn('transaction_journals.transaction_group_id', $groupIds);
}
$result = $this->query->get($this->fields);
$this->total = $result->count();
// if no post-filters are present, it can be sliced and returned.
if (0 === count($this->sorting) && 0 === count($this->postFilters) && null !== $this->limit && null !== $this->page) {
$offset = ($this->page - 1) * $this->limit;
$result = $result->slice($offset, $this->limit);
}
// $this->dumpQueryInLogs();
// Log::debug(sprintf('Count of result is %d', $result->count()));
// now to parse this into an array.
$collection = $this->parseArray($result);
// now to parse the rest into an array.
$collection = $this->parseArray($result);
// filter the array using all available post filters:
$collection = $this->postFilterCollection($collection);
$collection = $this->postFilterCollection($collection);
// sort the collection, if sort instructions are present.
$collection = $this->sortCollection($collection);
// count it and continue:
$this->total = $collection->count();
$collection = $this->sortCollection($collection);
// now filter the array according to the page and the limit (if necessary)
if (null !== $this->limit && null !== $this->page) {
if (count($this->postFilters) > 0 && null !== $this->limit && null !== $this->page) {
$offset = ($this->page - 1) * $this->limit;
return $collection->slice($offset, $this->limit);
}
// OR filter the array according to the start and end row variable
if (null !== $this->startRow && null !== $this->endRow) {
return $collection->slice($this->startRow, $this->endRow);
}
return $collection;
}
@@ -477,17 +472,11 @@ class GroupCollector implements GroupCollectorInterface
public function getPaginatedGroups(): LengthAwarePaginator
{
Log::debug('Now in getPaginatedGroups()');
$set = $this->getGroups();
$limit = $this->limit ?? 1;
if (0 === $this->limit) {
$this->setLimit(50);
}
if (null !== $this->startRow && null !== $this->endRow) {
/** @var int $total */
$total = $this->endRow - $this->startRow;
return new LengthAwarePaginator($set, $this->total, $total, 1);
}
$limit = $this->limit ?? 1;
$set = $this->getGroups();
return new LengthAwarePaginator($set, $this->total, $limit, $this->page);
}
@@ -519,12 +508,6 @@ class GroupCollector implements GroupCollectorInterface
return $this;
}
public function setEndRow(int $endRow): self
{
$this->endRow = $endRow;
return $this;
}
public function setExpandGroupSearch(bool $expandGroupSearch): GroupCollectorInterface
{
@@ -636,13 +619,6 @@ class GroupCollector implements GroupCollectorInterface
return $this;
}
public function setStartRow(int $startRow): self
{
$this->startRow = $startRow;
return $this;
}
/**
* Limit the search to one specific transaction group.
*/
@@ -692,6 +668,9 @@ class GroupCollector implements GroupCollectorInterface
#[Override]
public function sortCollection(Collection $collection): Collection
{
if (0 === count($this->sorting)) {
return $collection;
}
/**
* @var string $field
* @var string $direction
@@ -731,8 +710,7 @@ class GroupCollector implements GroupCollectorInterface
// include budget ID + name (if any)
->withBudgetInformation()
// include bill ID + name (if any)
->withBillInformation()
;
->withBillInformation();
return $this;
}
@@ -740,7 +718,7 @@ class GroupCollector implements GroupCollectorInterface
private function convertToBoolean(array $array): array
{
foreach ($this->booleanFields as $field) {
$array[$field] = array_key_exists($field, $array) ? (bool) $array[$field] : null;
$array[$field] = array_key_exists($field, $array) ? (bool)$array[$field] : null;
}
return $array;
@@ -752,7 +730,7 @@ class GroupCollector implements GroupCollectorInterface
private function convertToInteger(array $array): array
{
foreach ($this->integerFields as $field) {
$array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (int) $array[$field] : null;
$array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (int)$array[$field] : null;
}
return $array;
@@ -761,7 +739,7 @@ class GroupCollector implements GroupCollectorInterface
private function convertToStrings(array $array): array
{
foreach ($this->stringFields as $field) {
$array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (string) $array[$field] : null;
$array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (string)$array[$field] : null;
}
return $array;
@@ -772,15 +750,14 @@ class GroupCollector implements GroupCollectorInterface
return $this->query
->get(['transaction_journals.transaction_group_id'])
->pluck('transaction_group_id')
->toArray()
;
->toArray();
}
private function mergeAttachments(array $existingJournal, TransactionJournal $newJournal): array
{
$newArray = $newJournal->toArray();
if (array_key_exists('attachment_id', $newArray)) {
$attachmentId = (int) $newJournal['attachment_id'];
$attachmentId = (int)$newJournal['attachment_id'];
if (0 !== $attachmentId) {
$existingJournal['attachments'][$attachmentId] = ['id' => $attachmentId];
}
@@ -793,9 +770,9 @@ class GroupCollector implements GroupCollectorInterface
{
$newArray = $newJournal->toArray();
if (array_key_exists('tag_id', $newArray)) { // assume the other fields are present as well.
$tagId = (int) $newJournal['tag_id'];
$tagId = (int)$newJournal['tag_id'];
$tagDate = null;
$tagDate = null;
try {
$tagDate = Carbon::parse($newArray['tag_date']);
@@ -804,7 +781,7 @@ class GroupCollector implements GroupCollectorInterface
}
$existingJournal['tags'][$tagId] = [
'id' => (int) $newArray['tag_id'],
'id' => (int)$newArray['tag_id'],
'name' => $newArray['tag_name'],
'date' => $tagDate,
'description' => $newArray['tag_description'],
@@ -823,13 +800,13 @@ class GroupCollector implements GroupCollectorInterface
/** @var TransactionJournal $augumentedJournal */
foreach ($collection as $augumentedJournal) {
$groupId = (int) $augumentedJournal->transaction_group_id;
$groupId = (int)$augumentedJournal->transaction_group_id;
if (!array_key_exists($groupId, $groups)) {
// make new array
$parsedGroup = $this->parseAugmentedJournal($augumentedJournal);
$groupArray = [
'id' => (int) $augumentedJournal->transaction_group_id,
$parsedGroup = $this->parseAugmentedJournal($augumentedJournal);
$groupArray = [
'id' => (int)$augumentedJournal->transaction_group_id,
'user_id' => $augumentedJournal->user_id,
'user_group_id' => $augumentedJournal->user_group_id,
// Field transaction_group_title was added by the query.
@@ -842,7 +819,7 @@ class GroupCollector implements GroupCollectorInterface
'transactions' => [],
];
// Field transaction_journal_id was added by the query.
$journalId = (int) $augumentedJournal->transaction_journal_id;
$journalId = (int)$augumentedJournal->transaction_journal_id;
$groupArray['transactions'][$journalId] = $parsedGroup;
$groups[$groupId] = $groupArray;
@@ -850,7 +827,7 @@ class GroupCollector implements GroupCollectorInterface
}
// or parse the rest.
// Field transaction_journal_id was added by the query.
$journalId = (int) $augumentedJournal->transaction_journal_id;
$journalId = (int)$augumentedJournal->transaction_journal_id;
if (array_key_exists($journalId, $groups[$groupId]['transactions'])) {
// append data to existing group + journal (for multiple tags or multiple attachments)
$groups[$groupId]['transactions'][$journalId] = $this->mergeTags($groups[$groupId]['transactions'][$journalId], $augumentedJournal);
@@ -900,27 +877,27 @@ class GroupCollector implements GroupCollectorInterface
}
// try to process meta date value (if present)
$dates = ['interest_date', 'payment_date', 'invoice_date', 'book_date', 'due_date', 'process_date'];
$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((string) json_decode((string) $result['meta_data']), 0, 10));
if (array_key_exists('meta_data', $result) && '' !== (string)$result['meta_data']) {
$result[$name] = Carbon::createFromFormat('!Y-m-d', substr((string)json_decode((string)$result['meta_data']), 0, 10));
}
}
// convert values to integers:
$result = $this->convertToInteger($result);
$result = $this->convertToInteger($result);
// convert to boolean
$result = $this->convertToBoolean($result);
$result = $this->convertToBoolean($result);
// convert back to strings because SQLite is dumb like that.
$result = $this->convertToStrings($result);
$result = $this->convertToStrings($result);
$result['reconciled'] = 1 === (int) $result['reconciled'];
$result['reconciled'] = 1 === (int)$result['reconciled'];
if (array_key_exists('tag_id', $result) && null !== $result['tag_id']) { // assume the other fields are present as well.
$tagId = (int) $augumentedJournal['tag_id'];
$tagDate = null;
$tagId = (int)$augumentedJournal['tag_id'];
$tagDate = null;
try {
$tagDate = Carbon::parse($augumentedJournal['tag_date']);
@@ -929,7 +906,7 @@ class GroupCollector implements GroupCollectorInterface
}
$result['tags'][$tagId] = [
'id' => (int) $result['tag_id'],
'id' => (int)$result['tag_id'],
'name' => $result['tag_name'],
'date' => $tagDate,
'description' => $result['tag_description'],
@@ -938,8 +915,8 @@ class GroupCollector implements GroupCollectorInterface
// also merge attachments:
if (array_key_exists('attachment_id', $result) && null !== $result['attachment_id']) {
$uploaded = 1 === (int) $result['attachment_uploaded'];
$attachmentId = (int) $augumentedJournal['attachment_id'];
$uploaded = 1 === (int)$result['attachment_uploaded'];
$attachmentId = (int)$augumentedJournal['attachment_id'];
$deleted = null !== $result['attachment_deleted_at'];
if (0 !== $attachmentId && $uploaded && !$deleted) {
$result['attachments'][$attachmentId] = [
@@ -976,13 +953,13 @@ class GroupCollector implements GroupCollectorInterface
foreach ($groups as $groudId => $group) {
/** @var array $transaction */
foreach ($group['transactions'] as $transaction) {
$currencyId = (int) $transaction['currency_id'];
$currencyId = (int)$transaction['currency_id'];
if (null === $transaction['amount']) {
throw new FireflyException(sprintf('Amount is NULL for a transaction in group #%d, please investigate.', $groudId));
}
$pcAmount = (string) ('' === $transaction['pc_amount'] ? '0' : $transaction['pc_amount']);
$pcForeignAmount = (string) ('' === $transaction['pc_foreign_amount'] ? '0' : $transaction['pc_foreign_amount']);
$foreignAmount = (string) ('' === $transaction['foreign_amount'] ? '0' : $transaction['foreign_amount']);
$pcAmount = (string)('' === $transaction['pc_amount'] ? '0' : $transaction['pc_amount']);
$pcForeignAmount = (string)('' === $transaction['pc_foreign_amount'] ? '0' : $transaction['pc_foreign_amount']);
$foreignAmount = (string)('' === $transaction['foreign_amount'] ? '0' : $transaction['foreign_amount']);
// set default:
if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) {
@@ -993,11 +970,11 @@ class GroupCollector implements GroupCollectorInterface
$groups[$groudId]['sums'][$currencyId]['amount'] = '0';
$groups[$groudId]['sums'][$currencyId]['pc_amount'] = '0';
}
$groups[$groudId]['sums'][$currencyId]['amount'] = bcadd((string) $groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']);
$groups[$groudId]['sums'][$currencyId]['pc_amount'] = bcadd((string) $groups[$groudId]['sums'][$currencyId]['pc_amount'], $pcAmount);
$groups[$groudId]['sums'][$currencyId]['amount'] = bcadd((string)$groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']);
$groups[$groudId]['sums'][$currencyId]['pc_amount'] = bcadd((string)$groups[$groudId]['sums'][$currencyId]['pc_amount'], $pcAmount);
if (null !== $transaction['foreign_amount'] && null !== $transaction['foreign_currency_id']) {
$currencyId = (int) $transaction['foreign_currency_id'];
$currencyId = (int)$transaction['foreign_currency_id'];
// set default:
if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) {
@@ -1008,7 +985,7 @@ class GroupCollector implements GroupCollectorInterface
$groups[$groudId]['sums'][$currencyId]['amount'] = '0';
$groups[$groudId]['sums'][$currencyId]['pc_amount'] = '0';
}
$groups[$groudId]['sums'][$currencyId]['amount'] = bcadd((string) $groups[$groudId]['sums'][$currencyId]['amount'], $foreignAmount);
$groups[$groudId]['sums'][$currencyId]['amount'] = bcadd((string)$groups[$groudId]['sums'][$currencyId]['amount'], $foreignAmount);
$groups[$groudId]['sums'][$currencyId]['pc_amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $pcForeignAmount);
}
}
@@ -1025,10 +1002,10 @@ class GroupCollector implements GroupCollectorInterface
return $currentCollection;
}
Log::debug(sprintf(
'GroupCollector: postFilterCollection has %d filter(s) and %d transaction(s).',
count($this->postFilters),
count($currentCollection)
));
'GroupCollector: postFilterCollection has %d filter(s) and %d transaction(s).',
count($this->postFilters),
count($currentCollection)
));
if (0 === $currentCollection->count()) {
Log::debug('Found nothing anyway, return empty collection.');
@@ -1041,7 +1018,7 @@ class GroupCollector implements GroupCollectorInterface
*/
foreach ($this->postFilters as $function) {
Log::debug('Applying filter...');
$nextCollection = new Collection();
$nextCollection = new Collection();
// loop everything in the current collection
// and save it (or not) in the new collection.
@@ -1112,8 +1089,7 @@ class GroupCollector implements GroupCollectorInterface
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->orderBy('transaction_journals.description', 'DESC')
->orderBy('source.amount', 'DESC')
;
->orderBy('source.amount', 'DESC');
}
/**
@@ -469,11 +469,6 @@ interface GroupCollectorInterface
*/
public function setEnd(Carbon $end): self;
/**
* Set the page to get.
*/
public function setEndRow(int $endRow): self;
public function setExpandGroupSearch(bool $expandGroupSearch): self;
/**
@@ -573,11 +568,6 @@ interface GroupCollectorInterface
*/
public function setStart(Carbon $start): self;
/**
* Set the page to get.
*/
public function setStartRow(int $startRow): self;
/**
* Limit results to a specific tag.
*/