mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Better ability to store piggy banks.
This commit is contained in:
parent
f2fab5d4ee
commit
cdf1ebf3f7
@ -68,12 +68,11 @@ class PiggyBankController extends Controller
|
||||
{
|
||||
$data = $request->getData();
|
||||
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $this->parameters->get('limit'));
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$response = [];
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($piggies as $piggy) {
|
||||
$currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency;
|
||||
$currency = $piggy->transactionCurrency;
|
||||
$objectGroup = $piggy->objectGroups()->first();
|
||||
$response[] = [
|
||||
'id' => (string)$piggy->id,
|
||||
@ -99,12 +98,11 @@ class PiggyBankController extends Controller
|
||||
{
|
||||
$data = $request->getData();
|
||||
$piggies = $this->piggyRepository->searchPiggyBank($data['query'], $this->parameters->get('limit'));
|
||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||
$response = [];
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($piggies as $piggy) {
|
||||
$currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency;
|
||||
$currency = $piggy->transactionCurrency;
|
||||
$currentAmount = $this->piggyRepository->getRepetition($piggy)->current_amount ?? '0';
|
||||
$objectGroup = $piggy->objectGroups()->first();
|
||||
$response[] = [
|
||||
|
@ -36,6 +36,7 @@ use FireflyIII\Models\RuleGroup;
|
||||
use FireflyIII\Models\Tag;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
@ -63,14 +64,17 @@ class PurgeController extends Controller
|
||||
Bill::whereUserId($user->id)->onlyTrashed()->forceDelete();
|
||||
|
||||
// piggies
|
||||
$set = PiggyBank::leftJoin('accounts', 'accounts.id', 'piggy_banks.account_id')
|
||||
->where('accounts.user_id', $user->id)->onlyTrashed()->get(['piggy_banks.*'])
|
||||
;
|
||||
|
||||
/** @var PiggyBank $piggy */
|
||||
foreach ($set as $piggy) {
|
||||
$piggy->forceDelete();
|
||||
}
|
||||
$repository = app(PiggyBankRepositoryInterface::class);
|
||||
$repository->setUser($user);
|
||||
$repository->purgeAll();
|
||||
// $set = PiggyBank::leftJoin('accounts', 'accounts.id', 'piggy_banks.account_id')
|
||||
// ->where('accounts.user_id', $user->id)->onlyTrashed()->get(['piggy_banks.*'])
|
||||
// ;
|
||||
//
|
||||
// /** @var PiggyBank $piggy */
|
||||
// foreach ($set as $piggy) {
|
||||
// $piggy->forceDelete();
|
||||
// }
|
||||
|
||||
// rule group
|
||||
RuleGroup::whereUserId($user->id)->onlyTrashed()->forceDelete();
|
||||
|
@ -111,7 +111,7 @@ class ListController extends Controller
|
||||
// types to get, page size:
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
|
||||
// get list of budgets. Count it and split it.
|
||||
// get list of piggy banks. Count it and split it.
|
||||
$collection = $this->repository->getPiggyBanks($account);
|
||||
$count = $collection->count();
|
||||
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\Transformers\AccountTransformer;
|
||||
use FireflyIII\Transformers\AttachmentTransformer;
|
||||
use FireflyIII\Transformers\PiggyBankEventTransformer;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@ -118,4 +119,36 @@ class ListController extends Controller
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* This endpoint is documented at:
|
||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/piggy_banks/listAccountByPiggyBank
|
||||
*
|
||||
* List single resource.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function accounts(PiggyBank $piggyBank): JsonResponse
|
||||
{
|
||||
// types to get, page size:
|
||||
$pageSize = $this->parameters->get('limit');
|
||||
$manager = $this->getManager();
|
||||
|
||||
$collection = $piggyBank->accounts;
|
||||
$count = $collection->count();
|
||||
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
|
||||
|
||||
// make paginator:
|
||||
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
|
||||
$paginator->setPath(route('api.v1.piggy-banks.accounts', [$piggyBank->id]).$this->buildParams());
|
||||
|
||||
/** @var AccountTransformer $transformer */
|
||||
$transformer = app(AccountTransformer::class);
|
||||
$transformer->setParameters($this->parameters);
|
||||
|
||||
$resource = new FractalCollection($events, $transformer, 'accounts');
|
||||
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
|
||||
|
||||
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,13 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Api\V1\Requests\Models\PiggyBank;
|
||||
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Rules\IsValidPositiveAmount;
|
||||
use FireflyIII\Support\Request\ChecksLogin;
|
||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Validator;
|
||||
|
||||
/**
|
||||
* Class StoreRequest
|
||||
@ -42,19 +45,20 @@ class StoreRequest extends FormRequest
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
$fields = [
|
||||
$fields = [
|
||||
'order' => ['order', 'convertInteger'],
|
||||
];
|
||||
$data = $this->getAllData($fields);
|
||||
$data['name'] = $this->convertString('name');
|
||||
$data['account_id'] = $this->convertInteger('account_id');
|
||||
$data['targetamount'] = $this->convertString('target_amount');
|
||||
$data['current_amount'] = $this->convertString('current_amount');
|
||||
$data['startdate'] = $this->getCarbonDate('start_date');
|
||||
$data['targetdate'] = $this->getCarbonDate('target_date');
|
||||
$data['notes'] = $this->stringWithNewlines('notes');
|
||||
$data['object_group_id'] = $this->convertInteger('object_group_id');
|
||||
$data['object_group_title'] = $this->convertString('object_group_title');
|
||||
$data = $this->getAllData($fields);
|
||||
$data['name'] = $this->convertString('name');
|
||||
$data['accounts'] = $this->parseAccounts($this->get('accounts'));
|
||||
$data['target_amount'] = $this->convertString('target_amount');
|
||||
$data['start_date'] = $this->getCarbonDate('start_date');
|
||||
$data['target_date'] = $this->getCarbonDate('target_date');
|
||||
$data['notes'] = $this->stringWithNewlines('notes');
|
||||
$data['object_group_id'] = $this->convertInteger('object_group_id');
|
||||
$data['transaction_currency_id'] = $this->convertInteger('transaction_currency_id');
|
||||
$data['transaction_currency_code'] = $this->convertString('transaction_currency_code');
|
||||
$data['object_group_title'] = $this->convertString('object_group_title');
|
||||
|
||||
return $data;
|
||||
}
|
||||
@ -65,15 +69,67 @@ class StoreRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|min:1|max:255|uniquePiggyBankForUser',
|
||||
'current_amount' => ['nullable', new IsValidPositiveAmount()],
|
||||
'account_id' => 'required|numeric|belongsToUser:accounts,id',
|
||||
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
|
||||
'object_group_title' => ['min:1', 'max:255'],
|
||||
'target_amount' => ['required', new IsValidPositiveAmount()],
|
||||
'start_date' => 'date|nullable',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
'name' => 'required|min:1|max:255|uniquePiggyBankForUser',
|
||||
'accounts' => 'required',
|
||||
'accounts.*' => 'array|required',
|
||||
'accounts.*.account_id' => 'required|numeric|belongsToUser:accounts,id',
|
||||
'accounts.*.current_amount' => ['numeric', new IsValidPositiveAmount()],
|
||||
'object_group_id' => 'numeric|belongsToUser:object_groups,id',
|
||||
'object_group_title' => ['min:1', 'max:255'],
|
||||
'target_amount' => ['required', new IsValidPositiveAmount()],
|
||||
'start_date' => 'date|nullable',
|
||||
'transaction_currency_id' => 'exists:transaction_currencies,id',
|
||||
'transaction_currency_code' => 'exists:transaction_currencies,code',
|
||||
'target_date' => 'date|nullable|after:start_date',
|
||||
'notes' => 'max:65000',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Can only store money on liabilities and asset accouns.
|
||||
*/
|
||||
public function withValidator(Validator $validator): void
|
||||
{
|
||||
$validator->after(
|
||||
function (Validator $validator): void {
|
||||
// validate start before end only if both are there.
|
||||
$data = $validator->getData();
|
||||
if (array_key_exists('accounts', $data) && is_array($data['accounts'])) {
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$types = config('firefly.piggy_bank_account_types');
|
||||
foreach ($data['accounts'] as $index => $array) {
|
||||
$accountId = (int) ($array['account_id'] ?? 0);
|
||||
$account = $repository->find($accountId);
|
||||
if (null !== $account) {
|
||||
$type = $account->accountType->type;
|
||||
if (!in_array($type, $types, true)) {
|
||||
$validator->errors()->add(sprintf('accounts.%d', $index), trans('validation.invalid_account_type'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
if ($validator->fails()) {
|
||||
Log::channel('audit')->error(sprintf('Validation errors in %s', __CLASS__), $validator->errors()->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
private function parseAccounts(mixed $array): array
|
||||
{
|
||||
if (!is_array($array)) {
|
||||
return [];
|
||||
}
|
||||
$return = [];
|
||||
foreach ($array as $entry) {
|
||||
if (!is_array($entry)) {
|
||||
continue;
|
||||
}
|
||||
$return[] = [
|
||||
'account_id' => $this->integerFromValue((string)($entry['account_id'] ?? '0')),
|
||||
'current_amount' => $this->clearString($entry['current_amount'] ?? '0'),
|
||||
];
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
|
@ -23,8 +23,14 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Factory;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Database\QueryException;
|
||||
|
||||
/**
|
||||
* Class PiggyBankFactory
|
||||
@ -32,6 +38,72 @@ use FireflyIII\User;
|
||||
class PiggyBankFactory
|
||||
{
|
||||
private User $user;
|
||||
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;
|
||||
}
|
||||
|
||||
public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank
|
||||
{
|
||||
@ -70,4 +142,61 @@ class PiggyBankFactory
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
private function resetOrder(): void
|
||||
{
|
||||
$set = $this->user->piggyBanks()->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']);
|
||||
$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
|
||||
{
|
||||
return (int)$this->user->piggyBanks()->max('piggy_banks.order');
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
$piggyBank->accounts()->syncWithoutDetaching([$account->id, ['current_amount' => $info['current_amount'] ?? '0']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ class IndexController extends Controller
|
||||
public function index()
|
||||
{
|
||||
$this->cleanupObjectGroups();
|
||||
$this->piggyRepos->resetOrder();
|
||||
//$this->piggyRepos->resetOrder();
|
||||
$collection = $this->piggyRepos->getPiggyBanks();
|
||||
$accounts = [];
|
||||
|
||||
|
@ -55,7 +55,7 @@ class PiggyBank extends Model
|
||||
'target_amount' => 'string',
|
||||
];
|
||||
|
||||
protected $fillable = ['name', 'account_id', 'order', 'target_amount', 'start_date', 'start_date_tz', 'target_date', 'target_date_tz', 'active'];
|
||||
protected $fillable = ['name', 'account_id', 'order', 'target_amount', 'start_date', 'start_date_tz', 'target_date', 'target_date_tz', 'active','transaction_currency_id'];
|
||||
|
||||
/**
|
||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||
@ -67,9 +67,9 @@ class PiggyBank extends Model
|
||||
if (auth()->check()) {
|
||||
$piggyBankId = (int)$value;
|
||||
$piggyBank = self::where('piggy_banks.id', $piggyBankId)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
|
||||
->where('accounts.user_id', auth()->user()->id)->first(['piggy_banks.*'])
|
||||
;
|
||||
->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', auth()->user()->id)->first(['piggy_banks.*']);
|
||||
if (null !== $piggyBank) {
|
||||
return $piggyBank;
|
||||
}
|
||||
|
@ -105,4 +105,9 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
||||
|
||||
#[\Override] public function find(int $currencyId): ?TransactionCurrency
|
||||
{
|
||||
return TransactionCurrency::find($currencyId);
|
||||
}
|
||||
}
|
||||
|
@ -42,6 +42,8 @@ interface CurrencyRepositoryInterface
|
||||
*/
|
||||
public function findByCode(string $currencyCode): ?TransactionCurrency;
|
||||
|
||||
public function find(int $currencyId): ?TransactionCurrency;
|
||||
|
||||
/**
|
||||
* Returns the complete set of transactions but needs
|
||||
* no user object.
|
||||
|
@ -26,11 +26,14 @@ namespace FireflyIII\Repositories\PiggyBank;
|
||||
|
||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Factory\PiggyBankFactory;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups;
|
||||
use FireflyIII\Support\Facades\Amount;
|
||||
use Illuminate\Database\QueryException;
|
||||
|
||||
/**
|
||||
@ -178,82 +181,11 @@ trait ModifiesPiggyBanks
|
||||
*/
|
||||
public function store(array $data): PiggyBank
|
||||
{
|
||||
$order = $this->getMaxOrder() + 1;
|
||||
if (array_key_exists('order', $data)) {
|
||||
$order = $data['order'];
|
||||
}
|
||||
$data['order'] = 31337; // very high when creating.
|
||||
$piggyData = $data;
|
||||
// unset fields just in case.
|
||||
unset($piggyData['object_group_title'], $piggyData['object_group_id'], $piggyData['notes'], $piggyData['current_amount']);
|
||||
|
||||
// validate amount:
|
||||
if (array_key_exists('targetamount', $piggyData) && '' === (string)$piggyData['targetamount']) {
|
||||
$piggyData['targetamount'] = '0';
|
||||
}
|
||||
|
||||
$piggyData['startdate_tz'] = $piggyData['startdate']?->format('e');
|
||||
$piggyData['targetdate_tz'] = $piggyData['targetdate']?->format('e');
|
||||
|
||||
try {
|
||||
/** @var PiggyBank $piggyBank */
|
||||
$piggyBank = PiggyBank::create($piggyData);
|
||||
} catch (QueryException $e) {
|
||||
app('log')->error(sprintf('Could not store piggy bank: %s', $e->getMessage()), $piggyData);
|
||||
|
||||
throw new FireflyException('400005: Could not store new piggy bank.', 0, $e);
|
||||
}
|
||||
|
||||
// reset order then set order:
|
||||
$this->resetOrder();
|
||||
$this->setOrder($piggyBank, $order);
|
||||
|
||||
$this->updateNote($piggyBank, $data['notes']);
|
||||
|
||||
// repetition is auto created.
|
||||
$repetition = $this->getRepetition($piggyBank);
|
||||
if (null !== $repetition && array_key_exists('current_amount', $data) && '' !== $data['current_amount']) {
|
||||
$repetition->current_amount = $data['current_amount'];
|
||||
$repetition->save();
|
||||
}
|
||||
|
||||
$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;
|
||||
$factory = new PiggyBankFactory();
|
||||
$factory->setUser($this->user);
|
||||
return $factory->store($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct order of piggies in case of issues.
|
||||
*/
|
||||
public function resetOrder(): void
|
||||
{
|
||||
$set = $this->user->piggyBanks()->orderBy('piggy_banks.order', 'ASC')->get(['piggy_banks.*']);
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
public function setOrder(PiggyBank $piggyBank, int $newOrder): bool
|
||||
{
|
||||
@ -282,13 +214,12 @@ trait ModifiesPiggyBanks
|
||||
return true;
|
||||
}
|
||||
|
||||
private function updateNote(PiggyBank $piggyBank, string $note): bool
|
||||
public function updateNote(PiggyBank $piggyBank, string $note): void
|
||||
{
|
||||
if ('' === $note) {
|
||||
$dbNote = $piggyBank->notes()->first();
|
||||
$dbNote?->delete();
|
||||
|
||||
return true;
|
||||
return ;
|
||||
}
|
||||
$dbNote = $piggyBank->notes()->first();
|
||||
if (null === $dbNote) {
|
||||
@ -297,8 +228,6 @@ trait ModifiesPiggyBanks
|
||||
}
|
||||
$dbNote->text = trim($note);
|
||||
$dbNote->save();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function update(PiggyBank $piggyBank, array $data): PiggyBank
|
||||
|
@ -240,10 +240,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
}
|
||||
}
|
||||
|
||||
public function getMaxOrder(): int
|
||||
{
|
||||
return (int)$this->user->piggyBanks()->max('piggy_banks.order');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return note for piggy bank.
|
||||
@ -351,4 +347,9 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
|
||||
return $search->take($limit)->get();
|
||||
}
|
||||
|
||||
#[\Override] public function purgeAll(): void
|
||||
{
|
||||
throw new FireflyException('TODO Not implemented');
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,8 @@ interface PiggyBankRepositoryInterface
|
||||
|
||||
public function destroyAll(): void;
|
||||
|
||||
public function purgeAll(): void;
|
||||
|
||||
public function find(int $piggyBankId): ?PiggyBank;
|
||||
|
||||
/**
|
||||
@ -78,10 +80,7 @@ interface PiggyBankRepositoryInterface
|
||||
*/
|
||||
public function getExactAmount(PiggyBank $piggyBank, PiggyBankRepetition $repetition, TransactionJournal $journal): string;
|
||||
|
||||
/**
|
||||
* Highest order of all piggy banks.
|
||||
*/
|
||||
public function getMaxOrder(): int;
|
||||
public function updateNote(PiggyBank $piggyBank, string $note): void;
|
||||
|
||||
/**
|
||||
* Return note for piggy bank.
|
||||
@ -114,10 +113,10 @@ interface PiggyBankRepositoryInterface
|
||||
|
||||
public function removeObjectGroup(PiggyBank $piggyBank): PiggyBank;
|
||||
|
||||
/**
|
||||
* Correct order of piggies in case of issues.
|
||||
*/
|
||||
public function resetOrder(): void;
|
||||
// /**
|
||||
// * Correct order of piggies in case of issues.
|
||||
// */
|
||||
// public function resetOrder(): void;
|
||||
|
||||
/**
|
||||
* Search for piggy banks.
|
||||
@ -133,7 +132,7 @@ interface PiggyBankRepositoryInterface
|
||||
*/
|
||||
public function setOrder(PiggyBank $piggyBank, int $newOrder): bool;
|
||||
|
||||
public function setUser(null|Authenticatable|User $user): void;
|
||||
public function setUser(null | Authenticatable | User $user): void;
|
||||
|
||||
/**
|
||||
* Store new piggy bank.
|
||||
|
@ -27,6 +27,7 @@ use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Models\Webhook;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
@ -812,15 +813,15 @@ class FireflyValidator extends Validator
|
||||
public function validateUniquePiggyBankForUser($attribute, $value, $parameters): bool
|
||||
{
|
||||
$exclude = $parameters[0] ?? null;
|
||||
$query = \DB::table('piggy_banks')->whereNull('piggy_banks.deleted_at')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')->where('accounts.user_id', auth()->user()->id)
|
||||
;
|
||||
$query = 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', auth()->user()->id);
|
||||
if (null !== $exclude) {
|
||||
$query->where('piggy_banks.id', '!=', (int) $exclude);
|
||||
}
|
||||
$query->where('piggy_banks.name', $value);
|
||||
|
||||
return null === $query->first(['piggy_banks.*']);
|
||||
return 0 === $query->get(['piggy_banks.*'])->count();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -913,4 +913,7 @@ return [
|
||||
|
||||
// preselected account lists possibilities:
|
||||
'preselected_accounts' => ['all', 'assets', 'liabilities'],
|
||||
|
||||
// allowed to store a piggy bank in:
|
||||
'piggy_bank_account_types' => [AccountTypeEnum::ASSET->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::DEBT->value, AccountTypeEnum::MORTGAGE->value],
|
||||
];
|
||||
|
@ -25,6 +25,7 @@
|
||||
declare(strict_types=1);
|
||||
|
||||
return [
|
||||
'invalid_account_type' => 'A piggy bank can only be linked to asset accounts and liabilities',
|
||||
'filter_must_be_in' => 'Filter ":filter" must be one of: :values',
|
||||
'filter_not_string' => 'Filter ":filter" is expected to be a string of text',
|
||||
'bad_api_filter' => 'This API endpoint does not support ":filter" as a filter.',
|
||||
|
@ -615,6 +615,7 @@ Route::group(
|
||||
|
||||
Route::get('{piggyBank}/events', ['uses' => 'ListController@piggyBankEvents', 'as' => 'events']);
|
||||
Route::get('{piggyBank}/attachments', ['uses' => 'ListController@attachments', 'as' => 'attachments']);
|
||||
Route::get('{piggyBank}/accounts', ['uses' => 'ListController@accounts', 'as' => 'accounts']);
|
||||
}
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user