. */ declare(strict_types=1); namespace FireflyIII\Services\Internal\Update; use FireflyIII\Events\Model\Bill\UpdatedExistingBill; use FireflyIII\Factory\TransactionCurrencyFactory; use FireflyIII\Models\Bill; use FireflyIII\Models\ObjectGroup; use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups; use FireflyIII\Services\Internal\Support\BillServiceTrait; use FireflyIII\Support\Facades\Amount; use FireflyIII\User; /** * Class BillUpdateService */ class BillUpdateService { use BillServiceTrait; use CreatesObjectGroups; protected User $user; public function update(Bill $bill, array $data): Bill { $this->user = $bill->user; $oldData = $bill->toArray(); if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { $factory = app(TransactionCurrencyFactory::class); $currency = $factory->find( (int) ($data['currency_id'] ?? null), $data['currency_code'] ?? null ) ?? Amount::getPrimaryCurrencyByUserGroup($bill->user->userGroup); // enable the currency if it isn't. $currency->enabled = true; $currency->save(); $bill->transaction_currency_id = $currency->id; $bill->save(); } // update bill properties: $bill = $this->updateBillProperties($bill, $data); $bill->save(); $bill->refresh(); // update note: if (array_key_exists('notes', $data)) { $this->updateNote($bill, (string) $data['notes']); } // update order. if (array_key_exists('order', $data)) { // update the order of the piggy bank: $oldOrder = $bill->order; $newOrder = (int) ($data['order'] ?? $oldOrder); if ($oldOrder !== $newOrder) { $this->updateOrder($bill, $oldOrder, $newOrder); } } // update using name: if (array_key_exists('object_group_title', $data)) { $objectGroupTitle = $data['object_group_title'] ?? ''; if ('' !== $objectGroupTitle) { $objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle); if ($objectGroup instanceof ObjectGroup) { $bill->objectGroups()->sync([$objectGroup->id]); $bill->save(); } return $bill; } // remove if name is empty. Should be overruled by ID. $bill->objectGroups()->sync([]); $bill->save(); } if (array_key_exists('object_group_id', $data)) { // try also with ID: $objectGroupId = (int) ($data['object_group_id'] ?? 0); if (0 !== $objectGroupId) { $objectGroup = $this->findObjectGroupById($objectGroupId); if ($objectGroup instanceof ObjectGroup) { $bill->objectGroups()->sync([$objectGroup->id]); $bill->save(); } return $bill; } $bill->objectGroups()->sync([]); $bill->save(); } event(new UpdatedExistingBill($bill, $oldData)); return $bill; } /** * @SuppressWarnings("PHPMD.NPathComplexity") */ private function updateBillProperties(Bill $bill, array $data): Bill { if (array_key_exists('name', $data) && '' !== (string) $data['name']) { $bill->name = $data['name']; } if (array_key_exists('amount_min', $data) && '' !== (string) $data['amount_min']) { $bill->amount_min = $data['amount_min']; } if (array_key_exists('amount_max', $data) && '' !== (string) $data['amount_max']) { $bill->amount_max = $data['amount_max']; } if (array_key_exists('date', $data) && '' !== (string) $data['date']) { $bill->date = $data['date']; $bill->date_tz = $data['date']->format('e'); } if (array_key_exists('repeat_freq', $data) && '' !== (string) $data['repeat_freq']) { $bill->repeat_freq = $data['repeat_freq']; } if (array_key_exists('skip', $data)) { $bill->skip = $data['skip']; } if (array_key_exists('active', $data)) { $bill->active = $data['active']; } if (array_key_exists('end_date', $data)) { $bill->end_date = $data['end_date']; $bill->end_date_tz = $data['end_date']?->format('e'); } if (array_key_exists('extension_date', $data)) { $bill->extension_date = $data['extension_date']; $bill->extension_date_tz = $data['extension_date']?->format('e'); } $bill->match = 'EMPTY'; $bill->automatch = true; $bill->save(); return $bill; } private function updateOrder(Bill $bill, int $oldOrder, int $newOrder): void { if ($newOrder > $oldOrder) { $this->user ->bills() ->where('order', '<=', $newOrder) ->where('order', '>', $oldOrder) ->where('bills.id', '!=', $bill->id) ->decrement('bills.order') ; $bill->order = $newOrder; $bill->save(); } if ($newOrder < $oldOrder) { $this->user ->bills() ->where('order', '>=', $newOrder) ->where('order', '<', $oldOrder) ->where('bills.id', '!=', $bill->id) ->increment('bills.order') ; $bill->order = $newOrder; $bill->save(); } } }