2018-02-19 19:44:46 +01:00
|
|
|
<?php
|
2022-12-29 19:41:57 +01:00
|
|
|
|
2018-02-19 19:44:46 +01:00
|
|
|
/**
|
|
|
|
* PiggyBankFactory.php
|
2020-02-16 14:00:57 +01:00
|
|
|
* Copyright (c) 2019 james@firefly-iii.org
|
2018-02-19 19:44:46 +01:00
|
|
|
*
|
2019-10-02 06:37:26 +02:00
|
|
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
2018-02-19 19:44:46 +01:00
|
|
|
*
|
2019-10-02 06:37:26 +02:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU Affero General Public License as
|
|
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
|
|
* License, or (at your option) any later version.
|
2018-02-19 19:44:46 +01:00
|
|
|
*
|
2019-10-02 06:37:26 +02:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
2018-02-19 19:44:46 +01:00
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2019-10-02 06:37:26 +02:00
|
|
|
* GNU Affero General Public License for more details.
|
2018-02-19 19:44:46 +01:00
|
|
|
*
|
2019-10-02 06:37:26 +02:00
|
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2018-02-19 19:44:46 +01:00
|
|
|
*/
|
2018-05-11 10:08:34 +02:00
|
|
|
declare(strict_types=1);
|
2018-02-19 19:44:46 +01:00
|
|
|
|
|
|
|
namespace FireflyIII\Factory;
|
2021-03-28 11:46:23 +02:00
|
|
|
|
2024-12-01 18:16:48 +01:00
|
|
|
use FireflyIII\Exceptions\FireflyException;
|
2018-02-19 19:44:46 +01:00
|
|
|
use FireflyIII\Models\PiggyBank;
|
2024-12-01 18:16:48 +01:00
|
|
|
use FireflyIII\Models\TransactionCurrency;
|
|
|
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
|
|
|
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
|
|
|
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
2018-02-19 19:44:46 +01:00
|
|
|
use FireflyIII\User;
|
2024-12-01 18:16:48 +01:00
|
|
|
use Illuminate\Database\QueryException;
|
2018-02-19 19:44:46 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Class PiggyBankFactory
|
|
|
|
*/
|
|
|
|
class PiggyBankFactory
|
|
|
|
{
|
2024-12-06 08:10:31 +01:00
|
|
|
public User $user {
|
|
|
|
set(User $value) {
|
|
|
|
$this->user = $value;
|
|
|
|
}
|
|
|
|
}
|
2024-12-01 18:16:48 +01:00
|
|
|
private CurrencyRepositoryInterface $currencyRepository;
|
|
|
|
private AccountRepositoryInterface $accountRepository;
|
|
|
|
private PiggyBankRepositoryInterface $piggyBankRepository;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Store a piggy bank or come back with an exception.
|
|
|
|
*
|
|
|
|
* @param array $data
|
|
|
|
*
|
|
|
|
* @return PiggyBank
|
|
|
|
*/
|
|
|
|
public function store(array $data): PiggyBank {
|
|
|
|
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
|
|
|
|
$this->accountRepository = app(AccountRepositoryInterface::class);
|
|
|
|
$this->piggyBankRepository = app(PiggyBankRepositoryInterface::class);
|
|
|
|
$this->currencyRepository->setUser($this->user);
|
|
|
|
$this->accountRepository->setUser($this->user);
|
|
|
|
$this->piggyBankRepository->setUser($this->user);
|
|
|
|
$piggyBankData =$data;
|
|
|
|
|
|
|
|
// unset some fields
|
|
|
|
unset($piggyBankData['object_group_title'],$piggyBankData['transaction_currency_code'],$piggyBankData['transaction_currency_id'],$piggyBankData['accounts'], $piggyBankData['object_group_id'], $piggyBankData['notes']);
|
|
|
|
|
|
|
|
// validate amount:
|
|
|
|
if (array_key_exists('target_amount', $piggyBankData) && '' === (string)$piggyBankData['target_amount']) {
|
|
|
|
$piggyBankData['target_amount'] = '0';
|
|
|
|
}
|
|
|
|
|
|
|
|
$piggyBankData['start_date_tz'] = $piggyBankData['start_date']?->format('e');
|
|
|
|
$piggyBankData['target_date_tz'] = $piggyBankData['target_date']?->format('e');
|
|
|
|
$piggyBankData['account_id'] = null;
|
|
|
|
$piggyBankData['transaction_currency_id'] = $this->getCurrency($data)->id;
|
|
|
|
$piggyBankData['order'] = 131337;
|
|
|
|
|
|
|
|
try {
|
|
|
|
/** @var PiggyBank $piggyBank */
|
|
|
|
$piggyBank = PiggyBank::create($piggyBankData);
|
|
|
|
} catch (QueryException $e) {
|
|
|
|
app('log')->error(sprintf('Could not store piggy bank: %s', $e->getMessage()), $piggyBankData);
|
|
|
|
|
|
|
|
throw new FireflyException('400005: Could not store new piggy bank.', 0, $e);
|
|
|
|
}
|
|
|
|
$piggyBank = $this->setOrder($piggyBank, $data);
|
|
|
|
$this->linkToAccountIds($piggyBank, $data['accounts']);
|
|
|
|
$this->piggyBankRepository->updateNote($piggyBank, $data['notes']);
|
|
|
|
|
|
|
|
$objectGroupTitle = $data['object_group_title'] ?? '';
|
|
|
|
if ('' !== $objectGroupTitle) {
|
|
|
|
$objectGroup = $this->findOrCreateObjectGroup($objectGroupTitle);
|
|
|
|
if (null !== $objectGroup) {
|
|
|
|
$piggyBank->objectGroups()->sync([$objectGroup->id]);
|
|
|
|
$piggyBank->save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// try also with ID
|
|
|
|
$objectGroupId = (int)($data['object_group_id'] ?? 0);
|
|
|
|
if (0 !== $objectGroupId) {
|
|
|
|
$objectGroup = $this->findObjectGroupById($objectGroupId);
|
|
|
|
if (null !== $objectGroup) {
|
|
|
|
$piggyBank->objectGroups()->sync([$objectGroup->id]);
|
|
|
|
$piggyBank->save();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $piggyBank;
|
|
|
|
}
|
2018-09-06 12:29:32 +02:00
|
|
|
|
2018-02-19 19:44:46 +01:00
|
|
|
public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank
|
|
|
|
{
|
2022-12-29 19:41:57 +01:00
|
|
|
$piggyBankId = (int)$piggyBankId;
|
|
|
|
$piggyBankName = (string)$piggyBankName;
|
2018-07-06 19:06:08 +02:00
|
|
|
if ('' === $piggyBankName && 0 === $piggyBankId) {
|
2018-02-19 19:44:46 +01:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
// first find by ID:
|
|
|
|
if ($piggyBankId > 0) {
|
2023-12-20 19:35:52 +01:00
|
|
|
/** @var null|PiggyBank $piggyBank */
|
2018-03-01 20:54:50 +01:00
|
|
|
$piggyBank = $this->user->piggyBanks()->find($piggyBankId);
|
2018-04-02 14:42:07 +02:00
|
|
|
if (null !== $piggyBank) {
|
2018-02-19 19:44:46 +01:00
|
|
|
return $piggyBank;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// then find by name:
|
2019-02-13 17:38:41 +01:00
|
|
|
if ('' !== $piggyBankName) {
|
2023-12-20 19:35:52 +01:00
|
|
|
/** @var null|PiggyBank $piggyBank */
|
2018-03-01 20:54:50 +01:00
|
|
|
$piggyBank = $this->findByName($piggyBankName);
|
2018-04-02 14:42:07 +02:00
|
|
|
if (null !== $piggyBank) {
|
2018-02-19 19:44:46 +01:00
|
|
|
return $piggyBank;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2018-03-01 20:54:50 +01:00
|
|
|
public function findByName(string $name): ?PiggyBank
|
|
|
|
{
|
2019-08-10 13:42:33 +02:00
|
|
|
return $this->user->piggyBanks()->where('piggy_banks.name', $name)->first();
|
2018-03-01 20:54:50 +01:00
|
|
|
}
|
|
|
|
|
2024-12-01 18:16:48 +01:00
|
|
|
private function getCurrency(array $data): TransactionCurrency {
|
|
|
|
// currency:
|
|
|
|
$defaultCurrency = app('amount')->getDefaultCurrency();
|
|
|
|
$currency = null;
|
|
|
|
if (array_key_exists('transaction_currency_code', $data)) {
|
|
|
|
$currency = $this->currencyRepository->findByCode((string)($data['transaction_currency_code'] ?? ''));
|
|
|
|
}
|
|
|
|
if (array_key_exists('transaction_currency_id', $data)) {
|
|
|
|
$currency = $this->currencyRepository->find((int)($data['transaction_currency_id'] ?? 0));
|
|
|
|
}
|
|
|
|
$currency ??= $defaultCurrency;
|
|
|
|
return $currency;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function setOrder(PiggyBank $piggyBank, array $data): PiggyBank {
|
|
|
|
$this->resetOrder();
|
|
|
|
$order = $this->getMaxOrder() + 1;
|
|
|
|
if (array_key_exists('order', $data)) {
|
|
|
|
$order = $data['order'];
|
|
|
|
}
|
|
|
|
$piggyBank->order = $order;
|
|
|
|
$piggyBank->save();
|
|
|
|
return $piggyBank;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-12-04 06:38:47 +01:00
|
|
|
public function resetOrder(): void
|
2024-12-01 18:16:48 +01:00
|
|
|
{
|
2024-12-04 06:38:47 +01:00
|
|
|
// TODO duplicate code
|
|
|
|
$set = PiggyBank
|
|
|
|
::leftJoin('account_piggy_bank', 'account_piggy_bank.piggy_bank_id', '=', 'piggy_banks.id')
|
|
|
|
->leftJoin('accounts', 'accounts.id', '=', 'account_piggy_bank.account_id')
|
|
|
|
->where('accounts.user_id', $this->user->id)
|
|
|
|
->with(
|
|
|
|
[
|
|
|
|
'account',
|
|
|
|
'objectGroups',
|
|
|
|
]
|
|
|
|
)
|
|
|
|
->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']);
|
2024-12-01 18:16:48 +01:00
|
|
|
$current = 1;
|
|
|
|
foreach ($set as $piggyBank) {
|
|
|
|
if ($piggyBank->order !== $current) {
|
|
|
|
app('log')->debug(sprintf('Piggy bank #%d ("%s") was at place %d but should be on %d', $piggyBank->id, $piggyBank->name, $piggyBank->order, $current));
|
|
|
|
$piggyBank->order = $current;
|
|
|
|
$piggyBank->save();
|
|
|
|
}
|
|
|
|
++$current;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private function getMaxOrder(): int
|
|
|
|
{
|
2024-12-06 08:10:31 +01:00
|
|
|
return (int) $this->piggyBankRepository->getPiggyBanks()->max('order');
|
|
|
|
|
2024-12-01 18:16:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private function linkToAccountIds(PiggyBank $piggyBank, array $accounts): void {
|
|
|
|
/** @var array $info */
|
|
|
|
foreach($accounts as $info) {
|
|
|
|
$account = $this->accountRepository->find((int)($info['account_id'] ?? 0));
|
|
|
|
if(null === $account) {
|
|
|
|
continue;
|
|
|
|
}
|
2024-12-06 08:10:31 +01:00
|
|
|
$piggyBank->accounts()->syncWithoutDetaching([$account->id => ['current_amount' => $info['current_amount'] ?? '0']]);
|
2024-12-01 18:16:48 +01:00
|
|
|
}
|
|
|
|
}
|
2018-03-05 19:35:58 +01:00
|
|
|
}
|