mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-12 15:35:15 +00:00
🤖 Auto commit for release 'develop' on 2025-09-26
This commit is contained in:
@@ -112,7 +112,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function enrichSingle(array | Model $model): Account | array
|
||||
public function enrichSingle(array|Model $model): Account|array
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
@@ -168,9 +168,9 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$this->collection = $this->collection->map(function (Account $item) {
|
||||
$id = (int)$item->id;
|
||||
$item->full_account_type = $this->accountTypes[(int)$item->account_type_id] ?? null;
|
||||
$meta = [
|
||||
$id = (int)$item->id;
|
||||
$item->full_account_type = $this->accountTypes[(int)$item->account_type_id] ?? null;
|
||||
$meta = [
|
||||
'currency' => null,
|
||||
'location' => [
|
||||
'latitude' => null,
|
||||
@@ -217,30 +217,30 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
// add balances
|
||||
// get currencies:
|
||||
$currency = $this->primaryCurrency; // assume primary currency
|
||||
$currency = $this->primaryCurrency; // assume primary currency
|
||||
if (null !== $meta['currency']) {
|
||||
$currency = $meta['currency'];
|
||||
}
|
||||
|
||||
// get the current balance:
|
||||
$date = $this->getDate();
|
||||
$date = $this->getDate();
|
||||
// $finalBalance = Steam::finalAccountBalance($item, $date, $this->primaryCurrency, $this->convertToPrimary);
|
||||
$finalBalance = $this->balances[$id];
|
||||
$balanceDifference = $this->getBalanceDifference($id, $currency);
|
||||
$finalBalance = $this->balances[$id];
|
||||
$balanceDifference = $this->getBalanceDifference($id, $currency);
|
||||
Log::debug(sprintf('Call finalAccountBalance(%s) with date/time "%s"', var_export($this->convertToPrimary, true), $date->toIso8601String()), $finalBalance);
|
||||
|
||||
// collect current balances:
|
||||
$currentBalance = Steam::bcround($finalBalance[$currency->code] ?? '0', $currency->decimal_places);
|
||||
$openingBalance = Steam::bcround($meta['opening_balance_amount'] ?? '0', $currency->decimal_places);
|
||||
$virtualBalance = Steam::bcround($item->virtual_balance ?? '0', $currency->decimal_places);
|
||||
$debtAmount = $meta['current_debt'] ?? null;
|
||||
$currentBalance = Steam::bcround($finalBalance[$currency->code] ?? '0', $currency->decimal_places);
|
||||
$openingBalance = Steam::bcround($meta['opening_balance_amount'] ?? '0', $currency->decimal_places);
|
||||
$virtualBalance = Steam::bcround($item->virtual_balance ?? '0', $currency->decimal_places);
|
||||
$debtAmount = $meta['current_debt'] ?? null;
|
||||
|
||||
// set some pc_ default values to NULL:
|
||||
$pcCurrentBalance = null;
|
||||
$pcOpeningBalance = null;
|
||||
$pcVirtualBalance = null;
|
||||
$pcDebtAmount = null;
|
||||
$pcBalanceDifference = null;
|
||||
$pcCurrentBalance = null;
|
||||
$pcOpeningBalance = null;
|
||||
$pcVirtualBalance = null;
|
||||
$pcDebtAmount = null;
|
||||
$pcBalanceDifference = null;
|
||||
|
||||
// convert to primary currency if needed:
|
||||
if ($this->convertToPrimary && $currency->id !== $this->primaryCurrency->id) {
|
||||
@@ -279,7 +279,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
'pc_balance_difference' => $pcBalanceDifference,
|
||||
];
|
||||
// end add balances
|
||||
$item->meta = $meta;
|
||||
$item->meta = $meta;
|
||||
|
||||
return $item;
|
||||
});
|
||||
@@ -313,23 +313,25 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
private function collectLocations(): void
|
||||
{
|
||||
$locations = Location::query()->whereIn('locatable_id', $this->ids)
|
||||
->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray();
|
||||
->where('locatable_type', Account::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray()
|
||||
;
|
||||
foreach ($locations as $location) {
|
||||
$this->locations[(int)$location['locatable_id']]
|
||||
= [
|
||||
'latitude' => (float)$location['latitude'],
|
||||
'longitude' => (float)$location['longitude'],
|
||||
'zoom_level' => (int)$location['zoom_level'],
|
||||
];
|
||||
'latitude' => (float)$location['latitude'],
|
||||
'longitude' => (float)$location['longitude'],
|
||||
'zoom_level' => (int)$location['zoom_level'],
|
||||
];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d locations(s)', count($this->locations)));
|
||||
}
|
||||
|
||||
private function collectMetaData(): void
|
||||
{
|
||||
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'BIC', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
|
||||
->whereIn('account_id', $this->ids)
|
||||
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray();
|
||||
$set = AccountMeta::whereIn('name', ['is_multi_currency', 'include_net_worth', 'currency_id', 'account_role', 'account_number', 'BIC', 'liability_direction', 'interest', 'interest_period', 'current_debt'])
|
||||
->whereIn('account_id', $this->ids)
|
||||
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data'])->toArray()
|
||||
;
|
||||
|
||||
/** @var array $entry */
|
||||
foreach ($set as $entry) {
|
||||
@@ -355,9 +357,10 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Account::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
@@ -366,12 +369,13 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectObjectGroups(): void
|
||||
{
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->ids)
|
||||
->where('object_groupable_type', Account::class)
|
||||
->get(['object_groupable_id', 'object_group_id']);
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->ids)
|
||||
->where('object_groupable_type', Account::class)
|
||||
->get(['object_groupable_id', 'object_group_id'])
|
||||
;
|
||||
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$this->mappedObjects[(int)$entry->object_groupable_id] = (int)$entry->object_group_id;
|
||||
@@ -395,19 +399,20 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
->setUserGroup($this->userGroup)
|
||||
->setAccounts($this->collection)
|
||||
->withAccountInformation()
|
||||
->setTypes([TransactionTypeEnum::OPENING_BALANCE->value]);
|
||||
$journals = $collector->getExtractedJournals();
|
||||
->setTypes([TransactionTypeEnum::OPENING_BALANCE->value])
|
||||
;
|
||||
$journals = $collector->getExtractedJournals();
|
||||
foreach ($journals as $journal) {
|
||||
$this->openingBalances[(int)$journal['source_account_id']]
|
||||
= [
|
||||
'amount' => Steam::negative($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
'amount' => Steam::negative($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
$this->openingBalances[(int)$journal['destination_account_id']]
|
||||
= [
|
||||
'amount' => Steam::positive($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
'amount' => Steam::positive($journal['amount']),
|
||||
'date' => $journal['date'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,8 +436,8 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
if (0 === count($startBalance) || 0 === count($endBalance)) {
|
||||
return null;
|
||||
}
|
||||
$start = $startBalance[$currency->code] ?? '0';
|
||||
$end = $endBalance[$currency->code] ?? '0';
|
||||
$start = $startBalance[$currency->code] ?? '0';
|
||||
$end = $endBalance[$currency->code] ?? '0';
|
||||
|
||||
return bcsub($end, $start);
|
||||
}
|
||||
@@ -453,7 +458,7 @@ class AccountEnrichment implements EnrichmentInterface
|
||||
|
||||
case 'current_balance':
|
||||
case 'pc_current_balance':
|
||||
$this->collection = $this->collection->sortBy(static fn(Account $account) => $account->meta['balances'][$parameter[0]] ?? '0', SORT_NUMERIC, 'desc' === $parameter[1]);
|
||||
$this->collection = $this->collection->sortBy(static fn (Account $account) => $account->meta['balances'][$parameter[0]] ?? '0', SORT_NUMERIC, 'desc' === $parameter[1]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
@@ -79,7 +79,7 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function enrichSingle(array | Model $model): array | Model
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
|
@@ -70,7 +70,7 @@ class BudgetEnrichment implements EnrichmentInterface
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array | Model $model): array | Model
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
@@ -103,8 +103,8 @@ class BudgetEnrichment implements EnrichmentInterface
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$this->collection = $this->collection->map(function (Budget $item) {
|
||||
$id = (int)$item->id;
|
||||
$meta = [
|
||||
$id = (int)$item->id;
|
||||
$meta = [
|
||||
'object_group_id' => null,
|
||||
'object_group_order' => null,
|
||||
'object_group_title' => null,
|
||||
@@ -156,7 +156,7 @@ class BudgetEnrichment implements EnrichmentInterface
|
||||
$opsRepository->setUserGroup($this->userGroup);
|
||||
// $spent = $this->beautify();
|
||||
// $set = $this->opsRepository->sumExpenses($start, $end, null, new Collection()->push($budget))
|
||||
$expenses = $opsRepository->collectExpenses($this->start, $this->end, null, $this->collection, null);
|
||||
$expenses = $opsRepository->collectExpenses($this->start, $this->end, null, $this->collection, null);
|
||||
foreach ($this->collection as $item) {
|
||||
$id = (int)$item->id;
|
||||
$this->spent[$id] = array_values($opsRepository->sumCollectedExpensesByBudget($expenses, $item, false));
|
||||
@@ -177,9 +177,10 @@ class BudgetEnrichment implements EnrichmentInterface
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Budget::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Budget::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
@@ -188,12 +189,13 @@ class BudgetEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectObjectGroups(): void
|
||||
{
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->ids)
|
||||
->where('object_groupable_type', Budget::class)
|
||||
->get(['object_groupable_id', 'object_group_id']);
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->ids)
|
||||
->where('object_groupable_type', Budget::class)
|
||||
->get(['object_groupable_id', 'object_group_id'])
|
||||
;
|
||||
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$this->mappedObjects[(int)$entry->object_groupable_id] = (int)$entry->object_group_id;
|
||||
|
@@ -73,7 +73,7 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array | Model $model): array | Model
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
@@ -115,12 +115,12 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectBudgets(): void
|
||||
{
|
||||
$budgetIds = $this->collection->pluck('budget_id')->unique()->toArray();
|
||||
$budgets = Budget::whereIn('id', $budgetIds)->get();
|
||||
$budgetIds = $this->collection->pluck('budget_id')->unique()->toArray();
|
||||
$budgets = Budget::whereIn('id', $budgetIds)->get();
|
||||
|
||||
$repository = app(OperationsRepository::class);
|
||||
$repository->setUser($this->user);
|
||||
$expenses = $repository->collectExpenses($this->start, $this->end, null, $budgets, null);
|
||||
$expenses = $repository->collectExpenses($this->start, $this->end, null, $budgets, null);
|
||||
|
||||
/** @var BudgetLimit $budgetLimit */
|
||||
foreach ($this->collection as $budgetLimit) {
|
||||
@@ -151,8 +151,8 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectIds(): void
|
||||
{
|
||||
$this->start = $this->collection->min('start_date') ?? Carbon::now()->startOfMonth();
|
||||
$this->end = $this->collection->max('end_date') ?? Carbon::now()->endOfMonth();
|
||||
$this->start = $this->collection->min('start_date') ?? Carbon::now()->startOfMonth();
|
||||
$this->end = $this->collection->max('end_date') ?? Carbon::now()->endOfMonth();
|
||||
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($this->collection as $limit) {
|
||||
@@ -169,9 +169,10 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', BudgetLimit::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', BudgetLimit::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
@@ -180,7 +181,7 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
|
||||
private function filterToBudget(array $expenses, int $budget): array
|
||||
{
|
||||
$result = array_filter($expenses, fn(array $item) => (int)$item['budget_id'] === $budget);
|
||||
$result = array_filter($expenses, fn (array $item) => (int)$item['budget_id'] === $budget);
|
||||
Log::debug(sprintf('filterToBudget for budget #%d, from %d to %d items', $budget, count($expenses), count($result)));
|
||||
|
||||
return $result;
|
||||
@@ -188,13 +189,13 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
||||
|
||||
private function stringifyIds(): void
|
||||
{
|
||||
$this->expenses = array_map(fn($first) => array_map(function ($second) {
|
||||
$this->expenses = array_map(fn ($first) => array_map(function ($second) {
|
||||
$second['currency_id'] = (string)($second['currency_id'] ?? 0);
|
||||
|
||||
return $second;
|
||||
}, $first), $this->expenses);
|
||||
|
||||
$this->pcExpenses = array_map(fn($first) => array_map(function ($second) {
|
||||
$this->pcExpenses = array_map(fn ($first) => array_map(function ($second) {
|
||||
$second['currency_id'] = (string)($second['currency_id'] ?? 0);
|
||||
|
||||
return $second;
|
||||
|
@@ -62,7 +62,7 @@ class CategoryEnrichment implements EnrichmentInterface
|
||||
return $collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array | Model $model): array | Model
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
@@ -123,9 +123,10 @@ class CategoryEnrichment implements EnrichmentInterface
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Category::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Category::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
@@ -139,9 +140,9 @@ class CategoryEnrichment implements EnrichmentInterface
|
||||
$opsRepository = app(OperationsRepositoryInterface::class);
|
||||
$opsRepository->setUser($this->user);
|
||||
$opsRepository->setUserGroup($this->userGroup);
|
||||
$expenses = $opsRepository->collectExpenses($this->start, $this->end, null, $this->collection);
|
||||
$income = $opsRepository->collectIncome($this->start, $this->end, null, $this->collection);
|
||||
$transfers = $opsRepository->collectTransfers($this->start, $this->end, null, $this->collection);
|
||||
$expenses = $opsRepository->collectExpenses($this->start, $this->end, null, $this->collection);
|
||||
$income = $opsRepository->collectIncome($this->start, $this->end, null, $this->collection);
|
||||
$transfers = $opsRepository->collectTransfers($this->start, $this->end, null, $this->collection);
|
||||
foreach ($this->collection as $item) {
|
||||
$id = (int)$item->id;
|
||||
$this->spent[$id] = array_values($opsRepository->sumCollectedTransactionsByCategory($expenses, $item, 'negative', false));
|
||||
|
@@ -33,7 +33,7 @@ interface EnrichmentInterface
|
||||
{
|
||||
public function enrich(Collection $collection): Collection;
|
||||
|
||||
public function enrichSingle(array | Model $model): array | Model;
|
||||
public function enrichSingle(array|Model $model): array|Model;
|
||||
|
||||
public function setUser(User $user): void;
|
||||
|
||||
|
@@ -43,13 +43,13 @@ use Illuminate\Support\Facades\Log;
|
||||
|
||||
class PiggyBankEnrichment implements EnrichmentInterface
|
||||
{
|
||||
private array $accountIds = []; // @phpstan-ignore-line
|
||||
private array $accounts = []; // @phpstan-ignore-line
|
||||
private array $amounts = [];
|
||||
private array $accountIds = []; // @phpstan-ignore-line
|
||||
private array $accounts = []; // @phpstan-ignore-line
|
||||
private array $amounts = [];
|
||||
private Collection $collection;
|
||||
private array $currencies = [];
|
||||
private array $currencyIds = [];
|
||||
private array $ids = [];
|
||||
private array $currencies = [];
|
||||
private array $currencyIds = [];
|
||||
private array $ids = [];
|
||||
// private array $accountCurrencies = [];
|
||||
private array $mappedObjects = [];
|
||||
private array $notes = [];
|
||||
@@ -77,7 +77,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array | Model $model): array | Model
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
@@ -100,14 +100,14 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$this->collection = $this->collection->map(function (PiggyBank $item) {
|
||||
$id = (int)$item->id;
|
||||
$currencyId = (int)$item->transaction_currency_id;
|
||||
$currency = $this->currencies[$currencyId] ?? $this->primaryCurrency;
|
||||
$targetAmount = null;
|
||||
$id = (int)$item->id;
|
||||
$currencyId = (int)$item->transaction_currency_id;
|
||||
$currency = $this->currencies[$currencyId] ?? $this->primaryCurrency;
|
||||
$targetAmount = null;
|
||||
if (0 !== bccomp($item->target_amount, '0')) {
|
||||
$targetAmount = $item->target_amount;
|
||||
}
|
||||
$meta = [
|
||||
$meta = [
|
||||
'notes' => $this->notes[$id] ?? null,
|
||||
'currency' => $this->currencies[$currencyId] ?? null,
|
||||
// 'auto_budget' => $this->autoBudgets[$id] ?? null,
|
||||
@@ -136,17 +136,17 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
}
|
||||
// add current amount(s).
|
||||
foreach ($this->amounts[$id] as $accountId => $row) {
|
||||
$meta['accounts'][] = [
|
||||
$meta['accounts'][] = [
|
||||
'account_id' => (string)$accountId,
|
||||
'name' => $this->accounts[$accountId]['name'] ?? '',
|
||||
'current_amount' => Steam::bcround($row['current_amount'], $currency->decimal_places),
|
||||
'pc_current_amount' => Steam::bcround($row['pc_current_amount'], $this->primaryCurrency->decimal_places),
|
||||
];
|
||||
$meta['current_amount'] = bcadd($meta['current_amount'], $row['current_amount']);
|
||||
$meta['current_amount'] = bcadd($meta['current_amount'], $row['current_amount']);
|
||||
// only add pc_current_amount when the pc_current_amount is set
|
||||
$meta['pc_current_amount'] = null === $row['pc_current_amount'] ? null : bcadd($meta['pc_current_amount'], $row['pc_current_amount']);
|
||||
}
|
||||
$meta['current_amount'] = Steam::bcround($meta['current_amount'], $currency->decimal_places);
|
||||
$meta['current_amount'] = Steam::bcround($meta['current_amount'], $currency->decimal_places);
|
||||
// only round this number when pc_current_amount is set.
|
||||
$meta['pc_current_amount'] = null === $meta['pc_current_amount'] ? null : Steam::bcround($meta['pc_current_amount'], $this->primaryCurrency->decimal_places);
|
||||
|
||||
@@ -160,7 +160,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
$meta['save_per_month'] = Steam::bcround($this->getSuggestedMonthlyAmount($item->start_date, $item->target_date, $meta['target_amount'], $meta['current_amount']), $currency->decimal_places);
|
||||
$meta['pc_save_per_month'] = Steam::bcround($this->getSuggestedMonthlyAmount($item->start_date, $item->target_date, $meta['pc_target_amount'], $meta['pc_current_amount']), $currency->decimal_places);
|
||||
|
||||
$item->meta = $meta;
|
||||
$item->meta = $meta;
|
||||
|
||||
return $item;
|
||||
});
|
||||
@@ -176,7 +176,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
$this->ids[] = $id;
|
||||
$this->currencyIds[$id] = (int)$piggy->transaction_currency_id;
|
||||
}
|
||||
$this->ids = array_unique($this->ids);
|
||||
$this->ids = array_unique($this->ids);
|
||||
|
||||
// collect currencies.
|
||||
$currencies = TransactionCurrency::whereIn('id', $this->currencyIds)->get();
|
||||
@@ -185,10 +185,10 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
}
|
||||
|
||||
// collect accounts
|
||||
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->ids)->get(['piggy_bank_id', 'account_id', 'current_amount', 'native_current_amount']);
|
||||
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->ids)->get(['piggy_bank_id', 'account_id', 'current_amount', 'native_current_amount']);
|
||||
foreach ($set as $item) {
|
||||
$id = (int)$item->piggy_bank_id;
|
||||
$accountId = (int)$item->account_id;
|
||||
$id = (int)$item->piggy_bank_id;
|
||||
$accountId = (int)$item->account_id;
|
||||
$this->amounts[$id] ??= [];
|
||||
if (!array_key_exists($id, $this->accountIds)) {
|
||||
$this->accountIds[$id] = (int)$item->account_id;
|
||||
@@ -206,7 +206,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
}
|
||||
|
||||
// get account currency preference for ALL.
|
||||
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
|
||||
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
|
||||
|
||||
/** @var AccountMeta $item */
|
||||
foreach ($set as $item) {
|
||||
@@ -219,7 +219,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
}
|
||||
|
||||
// get account info.
|
||||
$set = Account::whereIn('id', array_values($this->accountIds))->get();
|
||||
$set = Account::whereIn('id', array_values($this->accountIds))->get();
|
||||
|
||||
/** @var Account $item */
|
||||
foreach ($set as $item) {
|
||||
@@ -234,9 +234,10 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', PiggyBank::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', PiggyBank::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
@@ -245,12 +246,13 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectObjectGroups(): void
|
||||
{
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->ids)
|
||||
->where('object_groupable_type', PiggyBank::class)
|
||||
->get(['object_groupable_id', 'object_group_id']);
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->ids)
|
||||
->where('object_groupable_type', PiggyBank::class)
|
||||
->get(['object_groupable_id', 'object_group_id'])
|
||||
;
|
||||
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$this->mappedObjects[(int)$entry->object_groupable_id] = (int)$entry->object_group_id;
|
||||
|
@@ -66,7 +66,7 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array | Model $model): array | Model
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
@@ -89,10 +89,10 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$this->collection = $this->collection->map(function (PiggyBankEvent $item) {
|
||||
$id = (int)$item->id;
|
||||
$piggyId = (int)$item->piggy_bank_id;
|
||||
$journalId = (int)$item->transaction_journal_id;
|
||||
$currency = null;
|
||||
$id = (int)$item->id;
|
||||
$piggyId = (int)$item->piggy_bank_id;
|
||||
$journalId = (int)$item->transaction_journal_id;
|
||||
$currency = null;
|
||||
if (array_key_exists($piggyId, $this->accountIds)) {
|
||||
$accountId = $this->accountIds[$piggyId];
|
||||
if (array_key_exists($accountId, $this->accountCurrencies)) {
|
||||
@@ -120,7 +120,7 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||
}
|
||||
$this->ids = array_unique($this->ids);
|
||||
// collect groups with journal info.
|
||||
$set = TransactionJournal::whereIn('id', $this->journalIds)->get(['id', 'transaction_group_id']);
|
||||
$set = TransactionJournal::whereIn('id', $this->journalIds)->get(['id', 'transaction_group_id']);
|
||||
|
||||
/** @var TransactionJournal $item */
|
||||
foreach ($set as $item) {
|
||||
@@ -128,7 +128,7 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||
}
|
||||
|
||||
// collect account info.
|
||||
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->piggyBankIds)->get(['piggy_bank_id', 'account_id']);
|
||||
$set = DB::table('account_piggy_bank')->whereIn('piggy_bank_id', $this->piggyBankIds)->get(['piggy_bank_id', 'account_id']);
|
||||
foreach ($set as $item) {
|
||||
$id = (int)$item->piggy_bank_id;
|
||||
if (!array_key_exists($id, $this->accountIds)) {
|
||||
@@ -137,12 +137,12 @@ class PiggyBankEventEnrichment implements EnrichmentInterface
|
||||
}
|
||||
|
||||
// get account currency preference for ALL.
|
||||
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
|
||||
$set = AccountMeta::whereIn('account_id', array_values($this->accountIds))->where('name', 'currency_id')->get();
|
||||
|
||||
/** @var AccountMeta $item */
|
||||
foreach ($set as $item) {
|
||||
$accountId = (int)$item->account_id;
|
||||
$currencyId = (int)$item->data;
|
||||
$accountId = (int)$item->account_id;
|
||||
$currencyId = (int)$item->data;
|
||||
if (!array_key_exists($currencyId, $this->currencies)) {
|
||||
$this->currencies[$currencyId] = Amount::getTransactionCurrencyById($currencyId);
|
||||
}
|
||||
|
@@ -51,11 +51,12 @@ use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
use function Safe\json_decode;
|
||||
|
||||
class RecurringEnrichment implements EnrichmentInterface
|
||||
{
|
||||
private array $accounts = [];
|
||||
private array $accounts = [];
|
||||
private Collection $collection;
|
||||
// private array $transactionTypeIds = [];
|
||||
// private array $transactionTypes = [];
|
||||
@@ -97,7 +98,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array | Model $model): array | Model
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
@@ -131,7 +132,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
return (string)trans('firefly.recurring_monthly', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip - 1], $this->language);
|
||||
}
|
||||
if ('ndom' === $repetition->repetition_type) {
|
||||
$parts = explode(',', $repetition->repetition_moment);
|
||||
$parts = explode(',', $repetition->repetition_moment);
|
||||
// first part is number of week, second is weekday.
|
||||
$dayOfWeek = trans(sprintf('config.dow_%s', $parts[1]), [], $this->language);
|
||||
if ($repetition->repetition_skip > 0) {
|
||||
@@ -148,7 +149,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
}
|
||||
// $diffInYears = (int)$today->diffInYears($repDate, true);
|
||||
// $repDate->addYears($diffInYears); // technically not necessary.
|
||||
$string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js'));
|
||||
$string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js'));
|
||||
|
||||
return (string)trans('firefly.recurring_yearly', ['date' => $string], $this->language);
|
||||
}
|
||||
@@ -171,8 +172,8 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$this->collection = $this->collection->map(function (Recurrence $item) {
|
||||
$id = (int)$item->id;
|
||||
$meta = [
|
||||
$id = (int)$item->id;
|
||||
$meta = [
|
||||
'notes' => $this->notes[$id] ?? null,
|
||||
'repetitions' => array_values($this->repetitions[$id] ?? []),
|
||||
'transactions' => $this->processTransactions(array_values($this->transactions[$id] ?? [])),
|
||||
@@ -285,7 +286,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
{
|
||||
/** @var Recurrence $recurrence */
|
||||
foreach ($this->collection as $recurrence) {
|
||||
$id = (int)$recurrence->id;
|
||||
$id = (int)$recurrence->id;
|
||||
// $typeId = (int)$recurrence->transaction_type_id;
|
||||
$this->ids[] = $id;
|
||||
// $this->transactionTypeIds[$id] = $typeId;
|
||||
@@ -303,9 +304,10 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->ids)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Recurrence::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Recurrence::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
@@ -335,20 +337,20 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
Log::debug('Start of enrichment: collectRepetitions()');
|
||||
$repository = app(RecurringRepositoryInterface::class);
|
||||
$repository->setUserGroup($this->userGroup);
|
||||
$set = RecurrenceRepetition::whereIn('recurrence_id', $this->ids)->get();
|
||||
$set = RecurrenceRepetition::whereIn('recurrence_id', $this->ids)->get();
|
||||
|
||||
/** @var RecurrenceRepetition $repetition */
|
||||
foreach ($set as $repetition) {
|
||||
$recurrence = $this->collection->filter(fn(Recurrence $item) => (int)$item->id === (int)$repetition->recurrence_id)->first();
|
||||
$fromDate = clone($recurrence->latest_date ?? $recurrence->first_date);
|
||||
$id = (int)$repetition->recurrence_id;
|
||||
$repId = (int)$repetition->id;
|
||||
$recurrence = $this->collection->filter(fn (Recurrence $item) => (int)$item->id === (int)$repetition->recurrence_id)->first();
|
||||
$fromDate = clone ($recurrence->latest_date ?? $recurrence->first_date);
|
||||
$id = (int)$repetition->recurrence_id;
|
||||
$repId = (int)$repetition->id;
|
||||
$this->repetitions[$id] ??= [];
|
||||
|
||||
// get the (future) occurrences for this specific type of repetition:
|
||||
$amount = 'daily' === $repetition->repetition_type ? 9 : 5;
|
||||
$set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount);
|
||||
$occurrences = [];
|
||||
$amount = 'daily' === $repetition->repetition_type ? 9 : 5;
|
||||
$set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount);
|
||||
$occurrences = [];
|
||||
|
||||
/** @var Carbon $carbon */
|
||||
foreach ($set as $carbon) {
|
||||
@@ -371,8 +373,8 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectTransactionMetaData(): void
|
||||
{
|
||||
$ids = array_keys($this->transactions);
|
||||
$meta = RecurrenceTransactionMeta::whereNull('deleted_at')->whereIn('rt_id', $ids)->get();
|
||||
$ids = array_keys($this->transactions);
|
||||
$meta = RecurrenceTransactionMeta::whereNull('deleted_at')->whereIn('rt_id', $ids)->get();
|
||||
// other meta-data to be collected:
|
||||
$billIds = [];
|
||||
$piggyBankIds = [];
|
||||
@@ -384,8 +386,8 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
$transactionId = (int)$entry->rt_id;
|
||||
|
||||
// this should refer to another array, were rtIds can be used to find the recurrence.
|
||||
$recurrenceId = $this->recurrenceIds[$transactionId] ?? 0;
|
||||
$name = (string)($entry->name ?? '');
|
||||
$recurrenceId = $this->recurrenceIds[$transactionId] ?? 0;
|
||||
$name = (string)($entry->name ?? '');
|
||||
if (0 === $recurrenceId) {
|
||||
Log::error(sprintf('Could not find recurrence ID for recurrence transaction ID %d', $transactionId));
|
||||
|
||||
@@ -485,14 +487,14 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
|
||||
/** @var RecurrenceTransaction $transaction */
|
||||
foreach ($set as $transaction) {
|
||||
$id = (int)$transaction->recurrence_id;
|
||||
$transactionId = (int)$transaction->id;
|
||||
$this->recurrenceIds[$transactionId] = $id;
|
||||
$this->transactions[$id] ??= [];
|
||||
$amount = $transaction->amount;
|
||||
$foreignAmount = $transaction->foreign_amount;
|
||||
$id = (int)$transaction->recurrence_id;
|
||||
$transactionId = (int)$transaction->id;
|
||||
$this->recurrenceIds[$transactionId] = $id;
|
||||
$this->transactions[$id] ??= [];
|
||||
$amount = $transaction->amount;
|
||||
$foreignAmount = $transaction->foreign_amount;
|
||||
|
||||
$this->transactions[$id][$transactionId] = [
|
||||
$this->transactions[$id][$transactionId] = [
|
||||
'id' => (string)$transactionId,
|
||||
// 'recurrence_id' => $id,
|
||||
'transaction_currency_id' => (int)$transaction->transaction_currency_id,
|
||||
@@ -529,8 +531,8 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
private function getLanguage(): void
|
||||
{
|
||||
/** @var Preference $preference */
|
||||
$preference = Preferences::getForUser($this->user, 'language', config('firefly.default_language', 'en_US'));
|
||||
$language = $preference->data;
|
||||
$preference = Preferences::getForUser($this->user, 'language', config('firefly.default_language', 'en_US'));
|
||||
$language = $preference->data;
|
||||
if (is_array($language)) {
|
||||
$language = 'en_US';
|
||||
}
|
||||
@@ -543,9 +545,9 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
$return = [];
|
||||
$converter = new ExchangeRateConverter();
|
||||
foreach ($transactions as $transaction) {
|
||||
$currencyId = $transaction['transaction_currency_id'];
|
||||
$pcAmount = null;
|
||||
$pcForeignAmount = null;
|
||||
$currencyId = $transaction['transaction_currency_id'];
|
||||
$pcAmount = null;
|
||||
$pcForeignAmount = null;
|
||||
// set the same amount in the primary currency, if both are the same anyway.
|
||||
if (true === $this->convertToPrimary && $currencyId === (int)$this->primaryCurrency->id) {
|
||||
$pcAmount = $transaction['amount'];
|
||||
@@ -561,26 +563,26 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
}
|
||||
}
|
||||
|
||||
$transaction['pc_amount'] = $pcAmount;
|
||||
$transaction['pc_foreign_amount'] = $pcForeignAmount;
|
||||
$transaction['pc_amount'] = $pcAmount;
|
||||
$transaction['pc_foreign_amount'] = $pcForeignAmount;
|
||||
|
||||
$sourceId = $transaction['source_id'];
|
||||
$transaction['source_name'] = $this->accounts[$sourceId]->name;
|
||||
$transaction['source_iban'] = $this->accounts[$sourceId]->iban;
|
||||
$transaction['source_type'] = $this->accounts[$sourceId]->accountType->type;
|
||||
$transaction['source_id'] = (string)$transaction['source_id'];
|
||||
$sourceId = $transaction['source_id'];
|
||||
$transaction['source_name'] = $this->accounts[$sourceId]->name;
|
||||
$transaction['source_iban'] = $this->accounts[$sourceId]->iban;
|
||||
$transaction['source_type'] = $this->accounts[$sourceId]->accountType->type;
|
||||
$transaction['source_id'] = (string)$transaction['source_id'];
|
||||
|
||||
$destId = $transaction['destination_id'];
|
||||
$transaction['destination_name'] = $this->accounts[$destId]->name;
|
||||
$transaction['destination_iban'] = $this->accounts[$destId]->iban;
|
||||
$transaction['destination_type'] = $this->accounts[$destId]->accountType->type;
|
||||
$transaction['destination_id'] = (string)$transaction['destination_id'];
|
||||
$destId = $transaction['destination_id'];
|
||||
$transaction['destination_name'] = $this->accounts[$destId]->name;
|
||||
$transaction['destination_iban'] = $this->accounts[$destId]->iban;
|
||||
$transaction['destination_type'] = $this->accounts[$destId]->accountType->type;
|
||||
$transaction['destination_id'] = (string)$transaction['destination_id'];
|
||||
|
||||
$transaction['currency_id'] = (string)$currencyId;
|
||||
$transaction['currency_name'] = $this->currencies[$currencyId]->name;
|
||||
$transaction['currency_code'] = $this->currencies[$currencyId]->code;
|
||||
$transaction['currency_symbol'] = $this->currencies[$currencyId]->symbol;
|
||||
$transaction['currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places;
|
||||
$transaction['currency_id'] = (string)$currencyId;
|
||||
$transaction['currency_name'] = $this->currencies[$currencyId]->name;
|
||||
$transaction['currency_code'] = $this->currencies[$currencyId]->code;
|
||||
$transaction['currency_symbol'] = $this->currencies[$currencyId]->symbol;
|
||||
$transaction['currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places;
|
||||
|
||||
$transaction['primary_currency_id'] = (string)$this->primaryCurrency->id;
|
||||
$transaction['primary_currency_name'] = $this->primaryCurrency->name;
|
||||
@@ -602,7 +604,7 @@ class RecurringEnrichment implements EnrichmentInterface
|
||||
$transaction['foreign_currency_decimal_places'] = $this->currencies[$currencyId]->decimal_places;
|
||||
}
|
||||
unset($transaction['transaction_currency_id']);
|
||||
$return[] = $transaction;
|
||||
$return[] = $transaction;
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
@@ -86,11 +86,11 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
$paidDates = $this->paidDates;
|
||||
$payDates = $this->payDates;
|
||||
$this->collection = $this->collection->map(function (Bill $item) use ($notes, $objectGroups, $paidDates, $payDates) {
|
||||
$id = (int)$item->id;
|
||||
$currency = $item->transactionCurrency;
|
||||
$nem = $this->getNextExpectedMatch($payDates[$id] ?? []);
|
||||
$id = (int)$item->id;
|
||||
$currency = $item->transactionCurrency;
|
||||
$nem = $this->getNextExpectedMatch($payDates[$id] ?? []);
|
||||
|
||||
$meta = [
|
||||
$meta = [
|
||||
'notes' => null,
|
||||
'object_group_id' => null,
|
||||
'object_group_title' => null,
|
||||
@@ -101,7 +101,7 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
'nem' => $nem,
|
||||
'nem_diff' => $this->getNextExpectedMatchDiff($nem, $payDates[$id] ?? []),
|
||||
];
|
||||
$amounts = [
|
||||
$amounts = [
|
||||
'amount_min' => Steam::bcround($item->amount_min, $currency->decimal_places),
|
||||
'amount_max' => Steam::bcround($item->amount_max, $currency->decimal_places),
|
||||
'average' => Steam::bcround(bcdiv(bcadd($item->amount_min, $item->amount_max), '2'), $currency->decimal_places),
|
||||
@@ -142,7 +142,7 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
return $collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array | Model $model): array | Model
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
@@ -177,13 +177,13 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
*/
|
||||
protected function lastPaidDate(Bill $subscription, Collection $dates, Carbon $default): Carbon
|
||||
{
|
||||
$filtered = $dates->filter(fn(TransactionJournal $journal) => (int)$journal->bill_id === (int)$subscription->id);
|
||||
$filtered = $dates->filter(fn (TransactionJournal $journal) => (int)$journal->bill_id === (int)$subscription->id);
|
||||
Log::debug(sprintf('Filtered down from %d to %d entries for bill #%d.', $dates->count(), $filtered->count(), $subscription->id));
|
||||
if (0 === $filtered->count()) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$latest = $filtered->first()->date;
|
||||
$latest = $filtered->first()->date;
|
||||
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($filtered as $journal) {
|
||||
@@ -198,9 +198,10 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->subscriptionIds)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Bill::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', Bill::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
@@ -209,12 +210,13 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
|
||||
private function collectObjectGroups(): void
|
||||
{
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->subscriptionIds)
|
||||
->where('object_groupable_type', Bill::class)
|
||||
->get(['object_groupable_id', 'object_group_id']);
|
||||
$set = DB::table('object_groupables')
|
||||
->whereIn('object_groupable_id', $this->subscriptionIds)
|
||||
->where('object_groupable_type', Bill::class)
|
||||
->get(['object_groupable_id', 'object_group_id'])
|
||||
;
|
||||
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
$ids = array_unique($set->pluck('object_group_id')->toArray());
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$this->mappedObjects[(int)$entry->object_groupable_id] = (int)$entry->object_group_id;
|
||||
@@ -242,13 +244,13 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
// 2023-07-18 this particular date is used to search for the last paid date.
|
||||
// 2023-07-18 the cloned $searchDate is used to grab the correct transactions.
|
||||
/** @var Carbon $start */
|
||||
$start = clone $this->start;
|
||||
$searchStart = clone $start;
|
||||
$start = clone $this->start;
|
||||
$searchStart = clone $start;
|
||||
$start->subDay();
|
||||
|
||||
/** @var Carbon $end */
|
||||
$end = clone $this->end;
|
||||
$searchEnd = clone $end;
|
||||
$end = clone $this->end;
|
||||
$searchEnd = clone $end;
|
||||
|
||||
// move the search dates to the start of the day.
|
||||
$searchStart->startOfDay();
|
||||
@@ -257,13 +259,13 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
Log::debug(sprintf('Search parameters are: start: %s, end: %s', $searchStart->format('Y-m-d H:i:s'), $searchEnd->format('Y-m-d H:i:s')));
|
||||
|
||||
// Get from database when bills were paid.
|
||||
$set = $this->user->transactionJournals()
|
||||
->whereIn('bill_id', $this->subscriptionIds)
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('transaction_currencies AS currency', 'currency.id', '=', 'transactions.transaction_currency_id')
|
||||
->leftJoin('transaction_currencies AS foreign_currency', 'foreign_currency.id', '=', 'transactions.foreign_currency_id')
|
||||
->where('transactions.amount', '>', 0)
|
||||
->before($searchEnd)->after($searchStart)->get(
|
||||
$set = $this->user->transactionJournals()
|
||||
->whereIn('bill_id', $this->subscriptionIds)
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('transaction_currencies AS currency', 'currency.id', '=', 'transactions.transaction_currency_id')
|
||||
->leftJoin('transaction_currencies AS foreign_currency', 'foreign_currency.id', '=', 'transactions.foreign_currency_id')
|
||||
->where('transactions.amount', '>', 0)
|
||||
->before($searchEnd)->after($searchStart)->get(
|
||||
[
|
||||
'transaction_journals.id',
|
||||
'transaction_journals.date',
|
||||
@@ -280,24 +282,25 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
'transactions.amount',
|
||||
'transactions.foreign_amount',
|
||||
]
|
||||
);
|
||||
)
|
||||
;
|
||||
Log::debug(sprintf('Count %d entries in set', $set->count()));
|
||||
|
||||
// for each bill, do a loop.
|
||||
$converter = new ExchangeRateConverter();
|
||||
$converter = new ExchangeRateConverter();
|
||||
|
||||
/** @var Bill $subscription */
|
||||
foreach ($this->collection as $subscription) {
|
||||
// Grab from array the most recent payment. If none exist, fall back to the start date and pretend *that* was the last paid date.
|
||||
Log::debug(sprintf('Grab last paid date from function, return %s if it comes up with nothing.', $start->format('Y-m-d')));
|
||||
$lastPaidDate = $this->lastPaidDate($subscription, $set, $start);
|
||||
$lastPaidDate = $this->lastPaidDate($subscription, $set, $start);
|
||||
Log::debug(sprintf('Result of lastPaidDate is %s', $lastPaidDate->format('Y-m-d')));
|
||||
|
||||
// At this point the "next match" is exactly after the last time the bill was paid.
|
||||
$result = [];
|
||||
$filtered = $set->filter(fn(TransactionJournal $journal) => (int)$journal->bill_id === (int)$subscription->id);
|
||||
$result = [];
|
||||
$filtered = $set->filter(fn (TransactionJournal $journal) => (int)$journal->bill_id === (int)$subscription->id);
|
||||
foreach ($filtered as $entry) {
|
||||
$array = [
|
||||
$array = [
|
||||
'transaction_group_id' => (string)$entry->transaction_group_id,
|
||||
'transaction_journal_id' => (string)$entry->id,
|
||||
'date' => $entry->date->toAtomString(),
|
||||
@@ -360,12 +363,12 @@ class SubscriptionEnrichment implements EnrichmentInterface
|
||||
|
||||
/** @var Bill $subscription */
|
||||
foreach ($this->collection as $subscription) {
|
||||
$id = (int)$subscription->id;
|
||||
$lastPaidDate = $this->getLastPaidDate($this->paidDates[$id] ?? []);
|
||||
$payDates = $this->calculator->getPayDates($this->start, $this->end, $subscription->date, $subscription->repeat_freq, $subscription->skip, $lastPaidDate);
|
||||
$payDatesFormatted = [];
|
||||
$id = (int)$subscription->id;
|
||||
$lastPaidDate = $this->getLastPaidDate($this->paidDates[$id] ?? []);
|
||||
$payDates = $this->calculator->getPayDates($this->start, $this->end, $subscription->date, $subscription->repeat_freq, $subscription->skip, $lastPaidDate);
|
||||
$payDatesFormatted = [];
|
||||
foreach ($payDates as $string) {
|
||||
$date = Carbon::createFromFormat('!Y-m-d', $string, config('app.timezone'));
|
||||
$date = Carbon::createFromFormat('!Y-m-d', $string, config('app.timezone'));
|
||||
if (!$date instanceof Carbon) {
|
||||
$date = today(config('app.timezone'));
|
||||
}
|
||||
|
@@ -83,7 +83,7 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
}
|
||||
|
||||
#[Override]
|
||||
public function enrichSingle(array | Model $model): array | TransactionGroup
|
||||
public function enrichSingle(array|Model $model): array|TransactionGroup
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
if (is_array($model)) {
|
||||
@@ -109,28 +109,28 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
|
||||
private function appendCollectedData(): void
|
||||
{
|
||||
$notes = $this->notes;
|
||||
$tags = $this->tags;
|
||||
$metaData = $this->metaData;
|
||||
$locations = $this->locations;
|
||||
$attachmentCount = $this->attachmentCount;
|
||||
$primaryCurrency = $this->primaryCurrency;
|
||||
$notes = $this->notes;
|
||||
$tags = $this->tags;
|
||||
$metaData = $this->metaData;
|
||||
$locations = $this->locations;
|
||||
$attachmentCount = $this->attachmentCount;
|
||||
$primaryCurrency = $this->primaryCurrency;
|
||||
|
||||
$this->collection = $this->collection->map(function (array $item) use ($primaryCurrency, $notes, $tags, $metaData, $locations, $attachmentCount) {
|
||||
foreach ($item['transactions'] as $index => $transaction) {
|
||||
$journalId = (int)$transaction['transaction_journal_id'];
|
||||
$journalId = (int)$transaction['transaction_journal_id'];
|
||||
|
||||
// attach notes if they exist:
|
||||
$item['transactions'][$index]['notes'] = array_key_exists($journalId, $notes) ? $notes[$journalId] : null;
|
||||
$item['transactions'][$index]['notes'] = array_key_exists($journalId, $notes) ? $notes[$journalId] : null;
|
||||
|
||||
// attach tags if they exist:
|
||||
$item['transactions'][$index]['tags'] = array_key_exists($journalId, $tags) ? $tags[$journalId] : [];
|
||||
$item['transactions'][$index]['tags'] = array_key_exists($journalId, $tags) ? $tags[$journalId] : [];
|
||||
|
||||
// attachment count
|
||||
$item['transactions'][$index]['attachment_count'] = array_key_exists($journalId, $attachmentCount) ? $attachmentCount[$journalId] : 0;
|
||||
|
||||
// default location data
|
||||
$item['transactions'][$index]['location'] = [
|
||||
$item['transactions'][$index]['location'] = [
|
||||
'latitude' => null,
|
||||
'longitude' => null,
|
||||
'zoom_level' => null,
|
||||
@@ -146,8 +146,8 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
];
|
||||
|
||||
// append meta data
|
||||
$item['transactions'][$index]['meta'] = [];
|
||||
$item['transactions'][$index]['meta_date'] = [];
|
||||
$item['transactions'][$index]['meta'] = [];
|
||||
$item['transactions'][$index]['meta_date'] = [];
|
||||
if (array_key_exists($journalId, $metaData)) {
|
||||
// loop al meta data:
|
||||
foreach ($metaData[$journalId] as $name => $value) {
|
||||
@@ -175,11 +175,12 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
// select count(id) as nr_of_attachments, attachable_id from attachments
|
||||
// group by attachable_id
|
||||
$attachments = Attachment::query()
|
||||
->whereIn('attachable_id', $this->journalIds)
|
||||
->where('attachable_type', TransactionJournal::class)
|
||||
->groupBy('attachable_id')
|
||||
->get(['attachable_id', DB::raw('COUNT(id) as nr_of_attachments')])
|
||||
->toArray();
|
||||
->whereIn('attachable_id', $this->journalIds)
|
||||
->where('attachable_type', TransactionJournal::class)
|
||||
->groupBy('attachable_id')
|
||||
->get(['attachable_id', DB::raw('COUNT(id) as nr_of_attachments')])
|
||||
->toArray()
|
||||
;
|
||||
foreach ($attachments as $row) {
|
||||
$this->attachmentCount[(int)$row['attachable_id']] = (int)$row['nr_of_attachments'];
|
||||
}
|
||||
@@ -199,14 +200,15 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
private function collectLocations(): void
|
||||
{
|
||||
$locations = Location::query()->whereIn('locatable_id', $this->journalIds)
|
||||
->where('locatable_type', TransactionJournal::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray();
|
||||
->where('locatable_type', TransactionJournal::class)->get(['locations.locatable_id', 'locations.latitude', 'locations.longitude', 'locations.zoom_level'])->toArray()
|
||||
;
|
||||
foreach ($locations as $location) {
|
||||
$this->locations[(int)$location['locatable_id']]
|
||||
= [
|
||||
'latitude' => (float)$location['latitude'],
|
||||
'longitude' => (float)$location['longitude'],
|
||||
'zoom_level' => (int)$location['zoom_level'],
|
||||
];
|
||||
'latitude' => (float)$location['latitude'],
|
||||
'longitude' => (float)$location['longitude'],
|
||||
'zoom_level' => (int)$location['zoom_level'],
|
||||
];
|
||||
}
|
||||
Log::debug(sprintf('Enrich with %d locations(s)', count($this->locations)));
|
||||
}
|
||||
@@ -215,8 +217,8 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
{
|
||||
$set = TransactionJournalMeta::whereIn('transaction_journal_id', $this->journalIds)->get(['transaction_journal_id', 'name', 'data'])->toArray();
|
||||
foreach ($set as $entry) {
|
||||
$name = $entry['name'];
|
||||
$data = (string)$entry['data'];
|
||||
$name = $entry['name'];
|
||||
$data = (string)$entry['data'];
|
||||
if ('' === $data) {
|
||||
continue;
|
||||
}
|
||||
@@ -234,9 +236,10 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
private function collectNotes(): void
|
||||
{
|
||||
$notes = Note::query()->whereIn('noteable_id', $this->journalIds)
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', TransactionJournal::class)->get(['notes.noteable_id', 'notes.text'])->toArray();
|
||||
->whereNotNull('notes.text')
|
||||
->where('notes.text', '!=', '')
|
||||
->where('noteable_type', TransactionJournal::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
|
||||
;
|
||||
foreach ($notes as $note) {
|
||||
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
|
||||
}
|
||||
@@ -246,11 +249,12 @@ class TransactionGroupEnrichment implements EnrichmentInterface
|
||||
private function collectTags(): void
|
||||
{
|
||||
$set = Tag::leftJoin('tag_transaction_journal', 'tags.id', '=', 'tag_transaction_journal.tag_id')
|
||||
->whereIn('tag_transaction_journal.transaction_journal_id', $this->journalIds)
|
||||
->get(['tag_transaction_journal.transaction_journal_id', 'tags.tag'])->toArray();
|
||||
->whereIn('tag_transaction_journal.transaction_journal_id', $this->journalIds)
|
||||
->get(['tag_transaction_journal.transaction_journal_id', 'tags.tag'])->toArray()
|
||||
;
|
||||
foreach ($set as $item) {
|
||||
$journalId = $item['transaction_journal_id'];
|
||||
$this->tags[$journalId] ??= [];
|
||||
$this->tags[$journalId] ??= [];
|
||||
$this->tags[$journalId][] = $item['tag'];
|
||||
}
|
||||
}
|
||||
|
@@ -66,7 +66,7 @@ class WebhookEnrichment implements EnrichmentInterface
|
||||
return $this->collection;
|
||||
}
|
||||
|
||||
public function enrichSingle(array | Model $model): array | Model
|
||||
public function enrichSingle(array|Model $model): array|Model
|
||||
{
|
||||
Log::debug(__METHOD__);
|
||||
$collection = new Collection()->push($model);
|
||||
|
Reference in New Issue
Block a user