diff --git a/app/Http/Controllers/PiggyBank/IndexController.php b/app/Http/Controllers/PiggyBank/IndexController.php index 6542c922de..64cab7c4ed 100644 --- a/app/Http/Controllers/PiggyBank/IndexController.php +++ b/app/Http/Controllers/PiggyBank/IndexController.php @@ -179,14 +179,6 @@ class IndexController extends Controller $return[$accountId]['target'] = '0'; $return[$accountId]['to_save'] = '0'; } - - // calculate new interesting fields: - // $return[$accountId]['left'] -= $array['current_amount']; - // $return[$accountId]['saved'] += $array['current_amount']; - // $return[$accountId]['target'] += $array['target_amount']; - // $return[$accountId]['to_save'] += ($array['target_amount'] - $array['current_amount']); - // $return['account_name'] = $account['name']; - } } diff --git a/app/Support/JsonApi/Enrichments/AccountEnrichment.php b/app/Support/JsonApi/Enrichments/AccountEnrichment.php index bbfcb90fd9..52ec2d19eb 100644 --- a/app/Support/JsonApi/Enrichments/AccountEnrichment.php +++ b/app/Support/JsonApi/Enrichments/AccountEnrichment.php @@ -33,6 +33,7 @@ use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountType; use FireflyIII\Models\Location; use FireflyIII\Models\Note; +use FireflyIII\Models\ObjectGroup; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\UserGroup; use FireflyIII\Support\Facades\Amount; @@ -41,6 +42,7 @@ use FireflyIII\Support\Http\Api\ExchangeRateConverter; use FireflyIII\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; use Override; @@ -67,6 +69,8 @@ class AccountEnrichment implements EnrichmentInterface private ?Carbon $date = null; private bool $convertToPrimary = false; private array $balances = []; + private array $objectGroups = []; + private array $mappedObjects = []; /** * TODO The account enricher must do conversion from and to the primary currency. @@ -113,6 +117,7 @@ class AccountEnrichment implements EnrichmentInterface $this->collectLastActivities(); $this->collectLocations(); $this->collectOpeningBalances(); + $this->collectObjectGroups(); $this->collectBalances(); $this->appendCollectedData(); @@ -142,10 +147,9 @@ class AccountEnrichment implements EnrichmentInterface 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) { @@ -171,10 +175,9 @@ 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']; } @@ -184,15 +187,14 @@ 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))); } @@ -207,20 +209,19 @@ 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'], + ]; } } @@ -247,6 +248,9 @@ class AccountEnrichment implements EnrichmentInterface 'longitude' => null, 'zoom_level' => null, ], + 'object_group_id' => null, + 'object_group_order' => null, + 'object_group_title' => null, 'opening_balance_date' => null, 'opening_balance_amount' => null, 'account_number' => null, @@ -254,6 +258,14 @@ class AccountEnrichment implements EnrichmentInterface 'last_activity' => $this->lastActivities[$id] ?? null, ]; + // add object group if available + if (array_key_exists($id, $this->mappedObjects)) { + $key = $this->mappedObjects[$id]; + $meta['object_group_id'] = $this->objectGroups[$key]['id']; + $meta['object_group_title'] = $this->objectGroups[$key]['title']; + $meta['object_group_order'] = $this->objectGroups[$key]['order']; + } + // if location, add location: if (array_key_exists($id, $this->locations)) { $meta['location'] = $this->locations[$id]; @@ -276,28 +288,28 @@ 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]; + $finalBalance = $this->balances[$id]; 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($account->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($account->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; + $pcCurrentBalance = null; + $pcOpeningBalance = null; + $pcVirtualBalance = null; + $pcDebtAmount = null; // convert to primary currency if needed: if ($this->convertToPrimary && $currency->id !== $this->primaryCurrency->id) { @@ -320,7 +332,7 @@ class AccountEnrichment implements EnrichmentInterface $openingBalance = null; $pcOpeningBalance = null; } - $meta['balances'] = [ + $meta['balances'] = [ 'current_balance' => $currentBalance, 'pc_current_balance' => $pcCurrentBalance, 'opening_balance' => $openingBalance, @@ -331,7 +343,7 @@ class AccountEnrichment implements EnrichmentInterface 'pc_debt_amount' => $pcDebtAmount, ]; // end add balances - $item->meta = $meta; + $item->meta = $meta; return $item; }); @@ -347,6 +359,27 @@ class AccountEnrichment implements EnrichmentInterface $this->balances = Steam::accountsBalancesOptimized($this->collection, $this->getDate(), $this->primaryCurrency, $this->convertToPrimary); } + 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']); + + $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; + } + + $groups = ObjectGroup::whereIn('id', $ids)->get(['id', 'title', 'order'])->toArray(); + foreach ($groups as $group) { + $group['id'] = (int)$group['id']; + $group['order'] = (int)$group['order']; + $this->objectGroups[(int)$group['id']] = $group; + } + } + public function setDate(?Carbon $date): void { $this->date = $date; diff --git a/app/Support/JsonApi/Enrichments/BudgetEnrichment.php b/app/Support/JsonApi/Enrichments/BudgetEnrichment.php index d25c12fd4e..d5fbf15348 100644 --- a/app/Support/JsonApi/Enrichments/BudgetEnrichment.php +++ b/app/Support/JsonApi/Enrichments/BudgetEnrichment.php @@ -8,6 +8,7 @@ use Carbon\Carbon; use FireflyIII\Models\AutoBudget; use FireflyIII\Models\Budget; use FireflyIII\Models\Note; +use FireflyIII\Models\ObjectGroup; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\UserGroup; use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; @@ -15,6 +16,7 @@ use FireflyIII\Support\Facades\Amount; use FireflyIII\User; use Illuminate\Database\Eloquent\Model; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Log; class BudgetEnrichment implements EnrichmentInterface @@ -32,6 +34,8 @@ class BudgetEnrichment implements EnrichmentInterface private ?Carbon $end = null; private array $spent = []; private array $pcSpent = []; + private array $objectGroups = []; + private array $mappedObjects = []; public function __construct() { @@ -46,6 +50,8 @@ class BudgetEnrichment implements EnrichmentInterface $this->collectNotes(); $this->collectAutoBudgets(); $this->collectExpenses(); + $this->collectObjectGroups(); + $this->appendCollectedData(); return $this->collection; @@ -83,10 +89,9 @@ 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']; } @@ -96,14 +101,27 @@ class BudgetEnrichment implements EnrichmentInterface private function appendCollectedData(): void { $this->collection = $this->collection->map(function (Budget $item) { - $id = (int)$item->id; - $meta = [ - 'notes' => $this->notes[$id] ?? null, - 'currency' => $this->currencies[$id] ?? null, - 'auto_budget' => $this->autoBudgets[$id] ?? null, - 'spent' => $this->spent[$id] ?? null, - 'pc_spent' => $this->pcSpent[$id] ?? null, + $id = (int)$item->id; + $meta = [ + 'object_group_id' => null, + 'object_group_order' => null, + 'object_group_title' => null, + 'notes' => $this->notes[$id] ?? null, + 'currency' => $this->currencies[$id] ?? null, + 'auto_budget' => $this->autoBudgets[$id] ?? null, + 'spent' => $this->spent[$id] ?? null, + 'pc_spent' => $this->pcSpent[$id] ?? null, ]; + + // add object group if available + if (array_key_exists($id, $this->mappedObjects)) { + $key = $this->mappedObjects[$id]; + $meta['object_group_id'] = $this->objectGroups[$key]['id']; + $meta['object_group_title'] = $this->objectGroups[$key]['title']; + $meta['object_group_order'] = $this->objectGroups[$key]['order']; + } + + $item->meta = $meta; return $item; @@ -136,7 +154,7 @@ class BudgetEnrichment implements EnrichmentInterface $opsRepository->setUserGroup($this->userGroup); // $spent = $this->beautify(); // $set = $this->opsRepository->sumExpenses($start, $end, null, new Collection([$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)); @@ -154,4 +172,25 @@ class BudgetEnrichment implements EnrichmentInterface { $this->start = $start; } + + 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']); + + $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; + } + + $groups = ObjectGroup::whereIn('id', $ids)->get(['id', 'title', 'order'])->toArray(); + foreach ($groups as $group) { + $group['id'] = (int)$group['id']; + $group['order'] = (int)$group['order']; + $this->objectGroups[(int)$group['id']] = $group; + } + } } diff --git a/app/Transformers/AccountTransformer.php b/app/Transformers/AccountTransformer.php index 6b4b64d309..1f8ff4dadc 100644 --- a/app/Transformers/AccountTransformer.php +++ b/app/Transformers/AccountTransformer.php @@ -108,7 +108,9 @@ class AccountTransformer extends AbstractTransformer 'type' => strtolower($accountType), 'account_role' => $accountRole, - // TODO object group + 'object_group_id' => $account->meta['object_group_id'], + 'object_group_order' => $account->meta['object_group_order'], + 'object_group_title' => $account->meta['object_group_title'], // currency information, structured for 6.3.0. 'object_has_currency_setting' => $hasCurrencySettings, diff --git a/app/Transformers/AttachmentTransformer.php b/app/Transformers/AttachmentTransformer.php index 66f924314d..5611a00d96 100644 --- a/app/Transformers/AttachmentTransformer.php +++ b/app/Transformers/AttachmentTransformer.php @@ -55,7 +55,6 @@ class AttachmentTransformer extends AbstractTransformer 'updated_at' => $attachment->updated_at->toAtomString(), 'attachable_id' => (string) $attachment->attachable_id, 'attachable_type' => str_replace('FireflyIII\Models\\', '', $attachment->attachable_type), - 'md5' => $attachment->md5, 'hash' => $attachment->md5, 'filename' => $attachment->filename, 'download_url' => route('api.v1.attachments.download', [$attachment->id]), diff --git a/app/Transformers/BillTransformer.php b/app/Transformers/BillTransformer.php index 7beb2201a3..96d4732307 100644 --- a/app/Transformers/BillTransformer.php +++ b/app/Transformers/BillTransformer.php @@ -93,7 +93,6 @@ class BillTransformer extends AbstractTransformer 'object_group_order' => $bill->meta['object_group_order'], 'object_group_title' => $bill->meta['object_group_title'], - 'paid_dates' => $bill->meta['paid_dates'], 'pay_dates' => $bill->meta['pay_dates'], 'next_expected_match' => $bill->meta['nem']?->toAtomString(), diff --git a/app/Transformers/BudgetLimitTransformer.php b/app/Transformers/BudgetLimitTransformer.php index f518cf17d8..e43d34f647 100644 --- a/app/Transformers/BudgetLimitTransformer.php +++ b/app/Transformers/BudgetLimitTransformer.php @@ -76,6 +76,8 @@ class BudgetLimitTransformer extends AbstractTransformer if ($this->convertToPrimary && $currency->id !== $this->primaryCurrency->id) { $pcAmount = Steam::bcround($budgetLimit->native_amount, $this->primaryCurrency->decimal_places); } + // TODO fix currency collection. + // TODO fix documentation.a return [ 'id' => (string)$budgetLimit->id, diff --git a/app/Transformers/BudgetTransformer.php b/app/Transformers/BudgetTransformer.php index cb1d73ea99..4d14da1b8c 100644 --- a/app/Transformers/BudgetTransformer.php +++ b/app/Transformers/BudgetTransformer.php @@ -86,8 +86,9 @@ class BudgetTransformer extends AbstractTransformer 'notes' => $budget->meta['notes'], 'auto_budget_type' => $abType, 'auto_budget_period' => $abPeriod, - - // TODO object group + 'object_group_id' => $budget->meta['object_group_id'], + 'object_group_order' => $budget->meta['object_group_order'], + 'object_group_title' => $budget->meta['object_group_title'], // new currency settings. 'object_has_currency_setting' => null !== $budget->meta['currency'],