mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/5.6.0'
This commit is contained in:
commit
1d02d86f9e
2
.gitignore
vendored
2
.gitignore
vendored
@ -15,4 +15,4 @@ yarn-error.log
|
|||||||
public/google*.html
|
public/google*.html
|
||||||
report.html
|
report.html
|
||||||
composer.phar
|
composer.phar
|
||||||
app.js.map
|
app.js.map
|
155
app/Console/Commands/Upgrade/CreateGroupMemberships.php
Normal file
155
app/Console/Commands/Upgrade/CreateGroupMemberships.php
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CreateGroupMemberships.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Console\Commands\Upgrade;
|
||||||
|
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Models\GroupMembership;
|
||||||
|
use FireflyIII\Models\UserGroup;
|
||||||
|
use FireflyIII\Models\UserRole;
|
||||||
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class CreateGroupMemberships
|
||||||
|
*/
|
||||||
|
class CreateGroupMemberships extends Command
|
||||||
|
{
|
||||||
|
public const CONFIG_NAME = '560_create_group_memberships';
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'SOME DESCRIPTION';
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'firefly-iii:create-group-memberships {--F|force : Force the execution of this command.}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
$start = microtime(true);
|
||||||
|
if ($this->isExecuted() && true !== $this->option('force')) {
|
||||||
|
$this->warn('This command has already been executed.');
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$this->createGroupMemberships();
|
||||||
|
$this->markAsExecuted();
|
||||||
|
|
||||||
|
$end = round(microtime(true) - $start, 2);
|
||||||
|
$this->info(sprintf('in %s seconds.', $end));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function isExecuted(): bool
|
||||||
|
{
|
||||||
|
$configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false);
|
||||||
|
if (null !== $configVar) {
|
||||||
|
return (bool)$configVar->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function createGroupMemberships(): void
|
||||||
|
{
|
||||||
|
$users = User::get();
|
||||||
|
/** @var User $user */
|
||||||
|
foreach ($users as $user) {
|
||||||
|
Log::debug(sprintf('Manage group memberships for user #%d', $user->id));
|
||||||
|
if (!$this->hasGroupMembership($user)) {
|
||||||
|
Log::debug(sprintf('User #%d has no main group.', $user->id));
|
||||||
|
$this->createGroupMembership($user);
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Done with user #%d', $user->id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function hasGroupMembership(User $user): bool
|
||||||
|
{
|
||||||
|
return $user->groupMemberships()->count() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $user
|
||||||
|
*
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function createGroupMembership(User $user): void
|
||||||
|
{
|
||||||
|
$userGroup = UserGroup::create(['title' => $user->email]);
|
||||||
|
$userRole = UserRole::where('title', UserRole::OWNER)->first();
|
||||||
|
|
||||||
|
if (null === $userRole) {
|
||||||
|
throw new FireflyException('Firefly III could not find a user role. Please make sure all validations have run.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$membership = GroupMembership::create(
|
||||||
|
[
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_role_id' => $userRole->id,
|
||||||
|
'user_group_id' => $userGroup->id,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
if (null === $membership) {
|
||||||
|
throw new FireflyException('Firefly III could not create user group management object. Please make sure all validations have run.');
|
||||||
|
}
|
||||||
|
$user->user_group_id = $userGroup->id;
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
Log::debug(sprintf('User #%d now has main group.', $user->id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function markAsExecuted(): void
|
||||||
|
{
|
||||||
|
app('fireflyconfig')->set(self::CONFIG_NAME, true);
|
||||||
|
}
|
||||||
|
}
|
@ -75,6 +75,7 @@ class UpgradeDatabase extends Command
|
|||||||
'firefly-iii:migrate-tag-locations',
|
'firefly-iii:migrate-tag-locations',
|
||||||
'firefly-iii:migrate-recurrence-type',
|
'firefly-iii:migrate-recurrence-type',
|
||||||
'firefly-iii:upgrade-liabilities',
|
'firefly-iii:upgrade-liabilities',
|
||||||
|
'firefly-iii:create-group-memberships',
|
||||||
|
|
||||||
// there are 16 verify commands.
|
// there are 16 verify commands.
|
||||||
'firefly-iii:fix-piggies',
|
'firefly-iii:fix-piggies',
|
||||||
|
@ -63,7 +63,7 @@ class APIEventHandler
|
|||||||
// see if user has alternative email address:
|
// see if user has alternative email address:
|
||||||
$pref = app('preferences')->getForUser($user, 'remote_guard_alt_email');
|
$pref = app('preferences')->getForUser($user, 'remote_guard_alt_email');
|
||||||
if (null !== $pref) {
|
if (null !== $pref) {
|
||||||
$email = $pref->data;
|
$email = (string)(is_array($pref->data) ? $email : $pref->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log::debug(sprintf('Now in APIEventHandler::accessTokenCreated. Email is %s, IP is %s', $email, $ipAddress));
|
Log::debug(sprintf('Now in APIEventHandler::accessTokenCreated. Email is %s, IP is %s', $email, $ipAddress));
|
||||||
|
@ -35,6 +35,9 @@ use FireflyIII\Mail\NewIPAddressWarningMail;
|
|||||||
use FireflyIII\Mail\RegisteredUser as RegisteredUserMail;
|
use FireflyIII\Mail\RegisteredUser as RegisteredUserMail;
|
||||||
use FireflyIII\Mail\RequestedNewPassword as RequestedNewPasswordMail;
|
use FireflyIII\Mail\RequestedNewPassword as RequestedNewPasswordMail;
|
||||||
use FireflyIII\Mail\UndoEmailChangeMail;
|
use FireflyIII\Mail\UndoEmailChangeMail;
|
||||||
|
use FireflyIII\Models\GroupMembership;
|
||||||
|
use FireflyIII\Models\UserGroup;
|
||||||
|
use FireflyIII\Models\UserRole;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Auth\Events\Login;
|
use Illuminate\Auth\Events\Login;
|
||||||
@ -248,6 +251,34 @@ class UserEventHandler
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param RegisteredUser $event
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function createGroupMembership(RegisteredUser $event): bool
|
||||||
|
{
|
||||||
|
$user = $event->user;
|
||||||
|
// create a new group.
|
||||||
|
$group = UserGroup::create(['title' => $user->email]);
|
||||||
|
$role = UserRole::where('title', UserRole::OWNER)->first();
|
||||||
|
if (null === $role) {
|
||||||
|
throw new FireflyException('The user role is unexpectedly empty. Did you run all migrations?');
|
||||||
|
}
|
||||||
|
GroupMembership::create(
|
||||||
|
[
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_group_id' => $group->id,
|
||||||
|
'user_role_id' => $role->id,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$user->user_group_id = $group->id;
|
||||||
|
$user->save();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method will send the user a registration mail, welcoming him or her to Firefly III.
|
* This method will send the user a registration mail, welcoming him or her to Firefly III.
|
||||||
* This message is only sent when the configuration of Firefly III says so.
|
* This message is only sent when the configuration of Firefly III says so.
|
||||||
|
@ -767,4 +767,14 @@ class GroupCollector implements GroupCollectorInterface
|
|||||||
|
|
||||||
return $groups;
|
return $groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function findNothing(): GroupCollectorInterface
|
||||||
|
{
|
||||||
|
$this->query->where('transaction_groups.id', -1);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,13 @@ interface GroupCollectorInterface
|
|||||||
*/
|
*/
|
||||||
public function amountLess(string $amount): GroupCollectorInterface;
|
public function amountLess(string $amount): GroupCollectorInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ensure the search will find nothing at all, zero results.
|
||||||
|
*
|
||||||
|
* @return GroupCollectorInterface
|
||||||
|
*/
|
||||||
|
public function findNothing(): GroupCollectorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get transactions where the amount is more than.
|
* Get transactions where the amount is more than.
|
||||||
*
|
*
|
||||||
|
@ -137,10 +137,16 @@ class AvailableBudgetController extends Controller
|
|||||||
*
|
*
|
||||||
* @return RedirectResponse|Redirector
|
* @return RedirectResponse|Redirector
|
||||||
*/
|
*/
|
||||||
public function delete(AvailableBudget $availableBudget)
|
public function delete(Request $request)
|
||||||
{
|
{
|
||||||
$this->abRepository->destroyAvailableBudget($availableBudget);
|
$id = (int)$request->get('id');
|
||||||
session()->flash('success', trans('firefly.deleted_ab'));
|
if (0 !== $id) {
|
||||||
|
$availableBudget = $this->abRepository->findById($id);
|
||||||
|
if (null !== $availableBudget) {
|
||||||
|
$this->abRepository->destroyAvailableBudget($availableBudget);
|
||||||
|
session()->flash('success', trans('firefly.deleted_ab'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return redirect(route('budgets.index'));
|
return redirect(route('budgets.index'));
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Http\Controllers;
|
namespace FireflyIII\Http\Controllers;
|
||||||
|
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Http\Requests\CurrencyFormRequest;
|
use FireflyIII\Http\Requests\CurrencyFormRequest;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
@ -41,7 +42,7 @@ use Log;
|
|||||||
class CurrencyController extends Controller
|
class CurrencyController extends Controller
|
||||||
{
|
{
|
||||||
protected CurrencyRepositoryInterface $repository;
|
protected CurrencyRepositoryInterface $repository;
|
||||||
protected UserRepositoryInterface $userRepository;
|
protected UserRepositoryInterface $userRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CurrencyController constructor.
|
* CurrencyController constructor.
|
||||||
@ -54,7 +55,7 @@ class CurrencyController extends Controller
|
|||||||
|
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
app('view')->share('title', (string) trans('firefly.currencies'));
|
app('view')->share('title', (string)trans('firefly.currencies'));
|
||||||
app('view')->share('mainTitleIcon', 'fa-usd');
|
app('view')->share('mainTitleIcon', 'fa-usd');
|
||||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||||
$this->userRepository = app(UserRepositoryInterface::class);
|
$this->userRepository = app(UserRepositoryInterface::class);
|
||||||
@ -63,6 +64,7 @@ class CurrencyController extends Controller
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a currency.
|
* Create a currency.
|
||||||
*
|
*
|
||||||
@ -75,13 +77,13 @@ class CurrencyController extends Controller
|
|||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||||
$request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$subTitleIcon = 'fa-plus';
|
$subTitleIcon = 'fa-plus';
|
||||||
$subTitle = (string) trans('firefly.create_currency');
|
$subTitle = (string)trans('firefly.create_currency');
|
||||||
|
|
||||||
// put previous url in session if not redirect from store (not "create another").
|
// put previous url in session if not redirect from store (not "create another").
|
||||||
if (true !== session('currencies.create.fromStore')) {
|
if (true !== session('currencies.create.fromStore')) {
|
||||||
@ -102,15 +104,23 @@ class CurrencyController extends Controller
|
|||||||
*
|
*
|
||||||
* @return RedirectResponse|Redirector
|
* @return RedirectResponse|Redirector
|
||||||
*/
|
*/
|
||||||
public function defaultCurrency(Request $request, TransactionCurrency $currency)
|
public function defaultCurrency(Request $request)
|
||||||
{
|
{
|
||||||
app('preferences')->set('currencyPreference', $currency->code);
|
$currencyId = (int)$request->get('id');
|
||||||
app('preferences')->mark();
|
if ($currencyId > 0) {
|
||||||
|
// valid currency?
|
||||||
|
$currency = $this->repository->find($currencyId);
|
||||||
|
if (null !== $currency) {
|
||||||
|
app('preferences')->set('currencyPreference', $currency->code);
|
||||||
|
app('preferences')->mark();
|
||||||
|
Log::channel('audit')->info(sprintf('Make %s the default currency.', $currency->code));
|
||||||
|
|
||||||
Log::channel('audit')->info(sprintf('Make %s the default currency.', $currency->code));
|
$this->repository->enable($currency);
|
||||||
|
$request->session()->flash('success', (string)trans('firefly.new_default_currency', ['name' => $currency->name]));
|
||||||
|
|
||||||
$this->repository->enable($currency);
|
return redirect(route('currencies.index'));
|
||||||
$request->session()->flash('success', (string) trans('firefly.new_default_currency', ['name' => $currency->name]));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
}
|
}
|
||||||
@ -129,7 +139,7 @@ class CurrencyController extends Controller
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||||
|
|
||||||
$request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
||||||
Log::channel('audit')->info(sprintf('Tried to visit page to delete currency %s but is not site owner.', $currency->code));
|
Log::channel('audit')->info(sprintf('Tried to visit page to delete currency %s but is not site owner.', $currency->code));
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
@ -138,7 +148,7 @@ class CurrencyController extends Controller
|
|||||||
|
|
||||||
if ($this->repository->currencyInUse($currency)) {
|
if ($this->repository->currencyInUse($currency)) {
|
||||||
$location = $this->repository->currencyInUseAt($currency);
|
$location = $this->repository->currencyInUseAt($currency);
|
||||||
$message = (string) trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]);
|
$message = (string)trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]);
|
||||||
$request->session()->flash('error', $message);
|
$request->session()->flash('error', $message);
|
||||||
Log::channel('audit')->info(sprintf('Tried to visit page to delete currency %s but currency is in use.', $currency->code));
|
Log::channel('audit')->info(sprintf('Tried to visit page to delete currency %s but currency is in use.', $currency->code));
|
||||||
|
|
||||||
@ -147,7 +157,7 @@ class CurrencyController extends Controller
|
|||||||
|
|
||||||
// put previous url in session
|
// put previous url in session
|
||||||
$this->rememberPreviousUri('currencies.delete.uri');
|
$this->rememberPreviousUri('currencies.delete.uri');
|
||||||
$subTitle = (string) trans('form.delete_currency', ['name' => $currency->name]);
|
$subTitle = (string)trans('form.delete_currency', ['name' => $currency->name]);
|
||||||
Log::channel('audit')->info(sprintf('Visit page to delete currency %s.', $currency->code));
|
Log::channel('audit')->info(sprintf('Visit page to delete currency %s.', $currency->code));
|
||||||
|
|
||||||
return prefixView('currencies.delete', compact('currency', 'subTitle'));
|
return prefixView('currencies.delete', compact('currency', 'subTitle'));
|
||||||
@ -167,7 +177,7 @@ class CurrencyController extends Controller
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||||
|
|
||||||
$request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
||||||
Log::channel('audit')->info(sprintf('Tried to delete currency %s but is not site owner.', $currency->code));
|
Log::channel('audit')->info(sprintf('Tried to delete currency %s but is not site owner.', $currency->code));
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
@ -175,14 +185,14 @@ class CurrencyController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($this->repository->currencyInUse($currency)) {
|
if ($this->repository->currencyInUse($currency)) {
|
||||||
$request->session()->flash('error', (string) trans('firefly.cannot_delete_currency', ['name' => e($currency->name)]));
|
$request->session()->flash('error', (string)trans('firefly.cannot_delete_currency', ['name' => e($currency->name)]));
|
||||||
Log::channel('audit')->info(sprintf('Tried to delete currency %s but is in use.', $currency->code));
|
Log::channel('audit')->info(sprintf('Tried to delete currency %s but is in use.', $currency->code));
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->repository->isFallbackCurrency($currency)) {
|
if ($this->repository->isFallbackCurrency($currency)) {
|
||||||
$request->session()->flash('error', (string) trans('firefly.cannot_delete_fallback_currency', ['name' => e($currency->name)]));
|
$request->session()->flash('error', (string)trans('firefly.cannot_delete_fallback_currency', ['name' => e($currency->name)]));
|
||||||
Log::channel('audit')->info(sprintf('Tried to delete currency %s but is FALLBACK.', $currency->code));
|
Log::channel('audit')->info(sprintf('Tried to delete currency %s but is FALLBACK.', $currency->code));
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
@ -191,7 +201,7 @@ class CurrencyController extends Controller
|
|||||||
Log::channel('audit')->info(sprintf('Deleted currency %s.', $currency->code));
|
Log::channel('audit')->info(sprintf('Deleted currency %s.', $currency->code));
|
||||||
$this->repository->destroy($currency);
|
$this->repository->destroy($currency);
|
||||||
|
|
||||||
$request->session()->flash('success', (string) trans('firefly.deleted_currency', ['name' => $currency->name]));
|
$request->session()->flash('success', (string)trans('firefly.deleted_currency', ['name' => $currency->name]));
|
||||||
|
|
||||||
return redirect($this->getPreviousUri('currencies.delete.uri'));
|
return redirect($this->getPreviousUri('currencies.delete.uri'));
|
||||||
}
|
}
|
||||||
@ -200,8 +210,8 @@ class CurrencyController extends Controller
|
|||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param TransactionCurrency $currency
|
* @param TransactionCurrency $currency
|
||||||
*
|
*
|
||||||
* @throws FireflyException
|
|
||||||
* @return RedirectResponse|Redirector
|
* @return RedirectResponse|Redirector
|
||||||
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function disableCurrency(Request $request, TransactionCurrency $currency)
|
public function disableCurrency(Request $request, TransactionCurrency $currency)
|
||||||
{
|
{
|
||||||
@ -211,7 +221,7 @@ class CurrencyController extends Controller
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||||
|
|
||||||
$request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
||||||
Log::channel('audit')->info(sprintf('Tried to disable currency %s but is not site owner.', $currency->code));
|
Log::channel('audit')->info(sprintf('Tried to disable currency %s but is not site owner.', $currency->code));
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
@ -221,7 +231,7 @@ class CurrencyController extends Controller
|
|||||||
if ($this->repository->currencyInUse($currency)) {
|
if ($this->repository->currencyInUse($currency)) {
|
||||||
|
|
||||||
$location = $this->repository->currencyInUseAt($currency);
|
$location = $this->repository->currencyInUseAt($currency);
|
||||||
$message = (string) trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]);
|
$message = (string)trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]);
|
||||||
|
|
||||||
$request->session()->flash('error', $message);
|
$request->session()->flash('error', $message);
|
||||||
Log::channel('audit')->info(sprintf('Tried to disable currency %s but is in use.', $currency->code));
|
Log::channel('audit')->info(sprintf('Tried to disable currency %s but is in use.', $currency->code));
|
||||||
@ -245,10 +255,10 @@ class CurrencyController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ('EUR' === $currency->code) {
|
if ('EUR' === $currency->code) {
|
||||||
session()->flash('warning', (string) trans('firefly.disable_EUR_side_effects'));
|
session()->flash('warning', (string)trans('firefly.disable_EUR_side_effects'));
|
||||||
}
|
}
|
||||||
|
|
||||||
session()->flash('success', (string) trans('firefly.currency_is_now_disabled', ['name' => $currency->name]));
|
session()->flash('success', (string)trans('firefly.currency_is_now_disabled', ['name' => $currency->name]));
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
}
|
}
|
||||||
@ -267,7 +277,7 @@ class CurrencyController extends Controller
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||||
|
|
||||||
$request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
||||||
Log::channel('audit')->info(sprintf('Tried to edit currency %s but is not owner.', $currency->code));
|
Log::channel('audit')->info(sprintf('Tried to edit currency %s but is not owner.', $currency->code));
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
@ -275,13 +285,13 @@ class CurrencyController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$subTitleIcon = 'fa-pencil';
|
$subTitleIcon = 'fa-pencil';
|
||||||
$subTitle = (string) trans('breadcrumbs.edit_currency', ['name' => $currency->name]);
|
$subTitle = (string)trans('breadcrumbs.edit_currency', ['name' => $currency->name]);
|
||||||
$currency->symbol = htmlentities($currency->symbol);
|
$currency->symbol = htmlentities($currency->symbol);
|
||||||
|
|
||||||
// code to handle active-checkboxes
|
// code to handle active-checkboxes
|
||||||
$hasOldInput = null !== $request->old('_token');
|
$hasOldInput = null !== $request->old('_token');
|
||||||
$preFilled = [
|
$preFilled = [
|
||||||
'enabled' => $hasOldInput ? (bool) $request->old('enabled') : $currency->enabled,
|
'enabled' => $hasOldInput ? (bool)$request->old('enabled') : $currency->enabled,
|
||||||
];
|
];
|
||||||
|
|
||||||
$request->session()->flash('preFilled', $preFilled);
|
$request->session()->flash('preFilled', $preFilled);
|
||||||
@ -306,7 +316,7 @@ class CurrencyController extends Controller
|
|||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
|
|
||||||
$this->repository->enable($currency);
|
$this->repository->enable($currency);
|
||||||
session()->flash('success', (string) trans('firefly.currency_is_now_enabled', ['name' => $currency->name]));
|
session()->flash('success', (string)trans('firefly.currency_is_now_enabled', ['name' => $currency->name]));
|
||||||
Log::channel('audit')->info(sprintf('Enabled currency %s.', $currency->code));
|
Log::channel('audit')->info(sprintf('Enabled currency %s.', $currency->code));
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
@ -323,8 +333,8 @@ class CurrencyController extends Controller
|
|||||||
{
|
{
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page');
|
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
|
||||||
$pageSize = (int) app('preferences')->get('listPageSize', 50)->data;
|
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
|
||||||
$collection = $this->repository->getAll();
|
$collection = $this->repository->getAll();
|
||||||
$total = $collection->count();
|
$total = $collection->count();
|
||||||
$collection = $collection->slice(($page - 1) * $pageSize, $pageSize);
|
$collection = $collection->slice(($page - 1) * $pageSize, $pageSize);
|
||||||
@ -334,12 +344,13 @@ class CurrencyController extends Controller
|
|||||||
$defaultCurrency = $this->repository->getCurrencyByPreference(app('preferences')->get('currencyPreference', config('firefly.default_currency', 'EUR')));
|
$defaultCurrency = $this->repository->getCurrencyByPreference(app('preferences')->get('currencyPreference', config('firefly.default_currency', 'EUR')));
|
||||||
$isOwner = true;
|
$isOwner = true;
|
||||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||||
$request->session()->flash('info', (string) trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')]));
|
$request->session()->flash('info', (string)trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')]));
|
||||||
$isOwner = false;
|
$isOwner = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return prefixView('currencies.index', compact('currencies', 'defaultCurrency', 'isOwner'));
|
return prefixView('currencies.index', compact('currencies', 'defaultCurrency', 'isOwner'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store new currency.
|
* Store new currency.
|
||||||
*
|
*
|
||||||
@ -367,15 +378,15 @@ class CurrencyController extends Controller
|
|||||||
} catch (FireflyException $e) {
|
} catch (FireflyException $e) {
|
||||||
Log::error($e->getMessage());
|
Log::error($e->getMessage());
|
||||||
Log::channel('audit')->info('Could not store (POST) currency without admin rights.', $data);
|
Log::channel('audit')->info('Could not store (POST) currency without admin rights.', $data);
|
||||||
$request->session()->flash('error', (string) trans('firefly.could_not_store_currency'));
|
$request->session()->flash('error', (string)trans('firefly.could_not_store_currency'));
|
||||||
$currency = null;
|
$currency = null;
|
||||||
}
|
}
|
||||||
$redirect = redirect($this->getPreviousUri('currencies.create.uri'));
|
$redirect = redirect($this->getPreviousUri('currencies.create.uri'));
|
||||||
|
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
$request->session()->flash('success', (string) trans('firefly.created_currency', ['name' => $currency->name]));
|
$request->session()->flash('success', (string)trans('firefly.created_currency', ['name' => $currency->name]));
|
||||||
Log::channel('audit')->info('Created (POST) currency.', $data);
|
Log::channel('audit')->info('Created (POST) currency.', $data);
|
||||||
if (1 === (int) $request->get('create_another')) {
|
if (1 === (int)$request->get('create_another')) {
|
||||||
|
|
||||||
$request->session()->put('currencies.create.fromStore', true);
|
$request->session()->put('currencies.create.fromStore', true);
|
||||||
|
|
||||||
@ -386,6 +397,7 @@ class CurrencyController extends Controller
|
|||||||
|
|
||||||
return $redirect;
|
return $redirect;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates a currency.
|
* Updates a currency.
|
||||||
*
|
*
|
||||||
@ -405,7 +417,7 @@ class CurrencyController extends Controller
|
|||||||
}
|
}
|
||||||
if (!$this->userRepository->hasRole($user, 'owner')) {
|
if (!$this->userRepository->hasRole($user, 'owner')) {
|
||||||
|
|
||||||
$request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
|
||||||
Log::channel('audit')->info('Tried to update (POST) currency without admin rights.', $data);
|
Log::channel('audit')->info('Tried to update (POST) currency without admin rights.', $data);
|
||||||
|
|
||||||
return redirect(route('currencies.index'));
|
return redirect(route('currencies.index'));
|
||||||
@ -413,10 +425,10 @@ class CurrencyController extends Controller
|
|||||||
}
|
}
|
||||||
$currency = $this->repository->update($currency, $data);
|
$currency = $this->repository->update($currency, $data);
|
||||||
Log::channel('audit')->info('Updated (POST) currency.', $data);
|
Log::channel('audit')->info('Updated (POST) currency.', $data);
|
||||||
$request->session()->flash('success', (string) trans('firefly.updated_currency', ['name' => $currency->name]));
|
$request->session()->flash('success', (string)trans('firefly.updated_currency', ['name' => $currency->name]));
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
|
|
||||||
if (1 === (int) $request->get('return_to_edit')) {
|
if (1 === (int)$request->get('return_to_edit')) {
|
||||||
|
|
||||||
$request->session()->put('currencies.edit.fromUpdate', true);
|
$request->session()->put('currencies.edit.fromUpdate', true);
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ use FireflyIII\Events\RequestedVersionCheckStatus;
|
|||||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Http\Middleware\Installer;
|
use FireflyIII\Http\Middleware\Installer;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
|
use FireflyIII\Models\GroupMembership;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
|
@ -86,6 +86,7 @@ class InstallController extends Controller
|
|||||||
'firefly-iii:migrate-tag-locations' => [],
|
'firefly-iii:migrate-tag-locations' => [],
|
||||||
'firefly-iii:migrate-recurrence-type' => [],
|
'firefly-iii:migrate-recurrence-type' => [],
|
||||||
'firefly-iii:upgrade-liabilities' => [],
|
'firefly-iii:upgrade-liabilities' => [],
|
||||||
|
'firefly-iii:create-group-memberships' => [],
|
||||||
|
|
||||||
// verify commands
|
// verify commands
|
||||||
'firefly-iii:fix-piggies' => [],
|
'firefly-iii:fix-piggies' => [],
|
||||||
@ -111,7 +112,7 @@ class InstallController extends Controller
|
|||||||
|
|
||||||
// final command to set latest version in DB
|
// final command to set latest version in DB
|
||||||
'firefly-iii:set-latest-version' => ['--james-is-cool' => true],
|
'firefly-iii:set-latest-version' => ['--james-is-cool' => true],
|
||||||
'firefly-iii:verify-security-alerts' => [],
|
'firefly-iii:verify-security-alerts' => [],
|
||||||
];
|
];
|
||||||
|
|
||||||
$this->lastError = '';
|
$this->lastError = '';
|
||||||
|
@ -39,8 +39,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
/**
|
/**
|
||||||
* Class Account
|
* Class Account
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
@ -89,16 +89,16 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
* @method static Builder|Account withTrashed()
|
* @method static Builder|Account withTrashed()
|
||||||
* @method static Builder|Account withoutTrashed()
|
* @method static Builder|Account withoutTrashed()
|
||||||
* @mixin Eloquent
|
* @mixin Eloquent
|
||||||
* @property Carbon $lastActivityDate
|
* @property Carbon $lastActivityDate
|
||||||
* @property string $startBalance
|
* @property string $startBalance
|
||||||
* @property string $endBalance
|
* @property string $endBalance
|
||||||
* @property string $difference
|
* @property string $difference
|
||||||
* @property string $interest
|
* @property string $interest
|
||||||
* @property string $interestPeriod
|
* @property string $interestPeriod
|
||||||
* @property string $accountTypeString
|
* @property string $accountTypeString
|
||||||
* @property string $location
|
* @property string $location
|
||||||
* @property string $liability_direction
|
* @property string $liability_direction
|
||||||
* @property string $current_debt
|
* @property string $current_debt
|
||||||
*/
|
*/
|
||||||
class Account extends Model
|
class Account extends Model
|
||||||
{
|
{
|
||||||
@ -149,11 +149,12 @@ class Account extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all of the tags for the post.
|
* @return BelongsTo
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function objectGroups()
|
public function accountType(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->morphToMany(ObjectGroup::class, 'object_groupable');
|
return $this->belongsTo(AccountType::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,24 +166,6 @@ class Account extends Model
|
|||||||
return $this->morphMany(Attachment::class, 'attachable');
|
return $this->morphMany(Attachment::class, 'attachable');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return HasMany
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
|
||||||
public function accountMeta(): HasMany
|
|
||||||
{
|
|
||||||
return $this->hasMany(AccountMeta::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return BelongsTo
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
|
||||||
public function accountType(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(AccountType::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the account number.
|
* Get the account number.
|
||||||
*
|
*
|
||||||
@ -198,6 +181,15 @@ class Account extends Model
|
|||||||
return $metaValue ? $metaValue->data : '';
|
return $metaValue ? $metaValue->data : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return HasMany
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public function accountMeta(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(AccountMeta::class);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
@ -231,6 +223,14 @@ class Account extends Model
|
|||||||
return $this->morphMany(Note::class, 'noteable');
|
return $this->morphMany(Note::class, 'noteable');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of the tags for the post.
|
||||||
|
*/
|
||||||
|
public function objectGroups()
|
||||||
|
{
|
||||||
|
return $this->morphToMany(ObjectGroup::class, 'object_groupable');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return HasMany
|
* @return HasMany
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
|
@ -27,6 +27,7 @@ use Illuminate\Database\Eloquent\Builder;
|
|||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
use JsonException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class AccountMeta
|
* Class AccountMeta
|
||||||
@ -79,7 +80,7 @@ class AccountMeta extends Model
|
|||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*
|
*
|
||||||
* @return mixed
|
* @return mixed
|
||||||
* @throws \JsonException
|
* @throws JsonException
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
public function getDataAttribute($value)
|
public function getDataAttribute($value)
|
||||||
|
@ -28,6 +28,7 @@ use Illuminate\Database\Eloquent\Collection;
|
|||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\AccountType
|
* FireflyIII\Models\AccountType
|
||||||
*
|
*
|
||||||
@ -74,7 +75,7 @@ class AccountType extends Model
|
|||||||
public const MORTGAGE = 'Mortgage';
|
public const MORTGAGE = 'Mortgage';
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public const CREDITCARD = 'Credit card';
|
public const CREDITCARD = 'Credit card';
|
||||||
/** @var string */
|
/** @var string */
|
||||||
public const LIABILITY_CREDIT = 'Liability credit account';
|
public const LIABILITY_CREDIT = 'Liability credit account';
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
|
@ -37,12 +37,12 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
/**
|
/**
|
||||||
* FireflyIII\Models\Attachment
|
* FireflyIII\Models\Attachment
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property int $attachable_id
|
* @property int $attachable_id
|
||||||
* @property string $attachable_type
|
* @property string $attachable_type
|
||||||
* @property bool $file_exists
|
* @property bool $file_exists
|
||||||
* @property string $md5
|
* @property string $md5
|
||||||
|
@ -22,27 +22,27 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Query\Builder;
|
use Illuminate\Database\Query\Builder;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\AvailableBudget
|
* FireflyIII\Models\AvailableBudget
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property int $transaction_currency_id
|
* @property int $transaction_currency_id
|
||||||
* @property string $amount
|
* @property string $amount
|
||||||
* @property \Illuminate\Support\Carbon $start_date
|
* @property Carbon $start_date
|
||||||
* @property \Illuminate\Support\Carbon $end_date
|
* @property Carbon $end_date
|
||||||
* @property-read TransactionCurrency $transactionCurrency
|
* @property-read TransactionCurrency $transactionCurrency
|
||||||
* @property-read User $user
|
* @property-read User $user
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|AvailableBudget newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|AvailableBudget newModelQuery()
|
||||||
@ -65,6 +65,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
class AvailableBudget extends Model
|
class AvailableBudget extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
@ -87,13 +88,13 @@ class AvailableBudget extends Model
|
|||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*
|
*
|
||||||
* @throws NotFoundHttpException
|
|
||||||
* @return AvailableBudget
|
* @return AvailableBudget
|
||||||
|
* @throws NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public static function routeBinder(string $value): AvailableBudget
|
public static function routeBinder(string $value): AvailableBudget
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$availableBudgetId = (int) $value;
|
$availableBudgetId = (int)$value;
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
/** @var AvailableBudget $availableBudget */
|
/** @var AvailableBudget $availableBudget */
|
||||||
|
@ -39,9 +39,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
* FireflyIII\Models\Budget
|
* FireflyIII\Models\Budget
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property bool $active
|
* @property bool $active
|
||||||
@ -74,7 +74,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
* @method static Builder|Budget withTrashed()
|
* @method static Builder|Budget withTrashed()
|
||||||
* @method static Builder|Budget withoutTrashed()
|
* @method static Builder|Budget withoutTrashed()
|
||||||
* @mixin Eloquent
|
* @mixin Eloquent
|
||||||
* @property string $email
|
* @property string $email
|
||||||
*/
|
*/
|
||||||
class Budget extends Model
|
class Budget extends Model
|
||||||
{
|
{
|
||||||
|
@ -22,23 +22,23 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\BudgetLimit
|
* FireflyIII\Models\BudgetLimit
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property int $budget_id
|
* @property int $budget_id
|
||||||
* @property int|null $transaction_currency_id
|
* @property int|null $transaction_currency_id
|
||||||
* @property \Illuminate\Support\Carbon $start_date
|
* @property Carbon $start_date
|
||||||
* @property \Illuminate\Support\Carbon|null $end_date
|
* @property Carbon|null $end_date
|
||||||
* @property string $amount
|
* @property string $amount
|
||||||
* @property string $spent
|
* @property string $spent
|
||||||
* @property string|null $period
|
* @property string|null $period
|
||||||
|
@ -96,13 +96,13 @@ class Category extends Model
|
|||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*
|
*
|
||||||
* @throws NotFoundHttpException
|
|
||||||
* @return Category
|
* @return Category
|
||||||
|
* @throws NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public static function routeBinder(string $value): Category
|
public static function routeBinder(string $value): Category
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$categoryId = (int) $value;
|
$categoryId = (int)$value;
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
/** @var Category $category */
|
/** @var Category $category */
|
||||||
@ -114,14 +114,6 @@ class Category extends Model
|
|||||||
throw new NotFoundHttpException;
|
throw new NotFoundHttpException;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
* @return BelongsToMany
|
|
||||||
*/
|
|
||||||
public function transactionJournals(): BelongsToMany
|
|
||||||
{
|
|
||||||
return $this->belongsToMany(TransactionJournal::class, 'category_transaction_journal', 'category_id');
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @return MorphMany
|
* @return MorphMany
|
||||||
@ -140,6 +132,15 @@ class Category extends Model
|
|||||||
return $this->morphMany(Note::class, 'noteable');
|
return $this->morphMany(Note::class, 'noteable');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* @return BelongsToMany
|
||||||
|
*/
|
||||||
|
public function transactionJournals(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(TransactionJournal::class, 'category_transaction_journal', 'category_id');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @return BelongsToMany
|
* @return BelongsToMany
|
||||||
|
@ -31,12 +31,12 @@ use Illuminate\Support\Carbon;
|
|||||||
/**
|
/**
|
||||||
* FireflyIII\Models\Configuration
|
* FireflyIII\Models\Configuration
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property mixed $data
|
* @property mixed $data
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Configuration newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|Configuration newModelQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Configuration newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|Configuration newQuery()
|
||||||
* @method static Builder|Configuration onlyTrashed()
|
* @method static Builder|Configuration onlyTrashed()
|
||||||
@ -70,7 +70,8 @@ class Configuration extends Model
|
|||||||
protected $table = 'configuration';
|
protected $table = 'configuration';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See reference nr. 17
|
* See reference nr. 17
|
||||||
|
*
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
*
|
*
|
||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
|
@ -22,24 +22,24 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\CurrencyExchangeRate
|
* FireflyIII\Models\CurrencyExchangeRate
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property string|null $deleted_at
|
* @property string|null $deleted_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property int $from_currency_id
|
* @property int $from_currency_id
|
||||||
* @property int $to_currency_id
|
* @property int $to_currency_id
|
||||||
* @property \Illuminate\Support\Carbon $date
|
* @property Carbon $date
|
||||||
* @property string $rate
|
* @property string $rate
|
||||||
* @property string|null $user_rate
|
* @property string|null $user_rate
|
||||||
* @property-read TransactionCurrency $fromCurrency
|
* @property-read TransactionCurrency $fromCurrency
|
||||||
|
61
app/Models/GroupMembership.php
Normal file
61
app/Models/GroupMembership.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GroupMembership.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class GroupMembership
|
||||||
|
*/
|
||||||
|
class GroupMembership extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ['user_id', 'user_group_id', 'user_role_id'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo
|
||||||
|
*/
|
||||||
|
public function user(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo
|
||||||
|
*/
|
||||||
|
public function userGroup(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(UserGroup::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return BelongsTo
|
||||||
|
*/
|
||||||
|
public function userRole(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(UserRole::class);
|
||||||
|
}
|
||||||
|
}
|
@ -22,21 +22,22 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Query\Builder;
|
use Illuminate\Database\Query\Builder;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\LinkType
|
* FireflyIII\Models\LinkType
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property string $outward
|
* @property string $outward
|
||||||
* @property string $inward
|
* @property string $inward
|
||||||
@ -63,6 +64,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
class LinkType extends Model
|
class LinkType extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
@ -84,14 +86,14 @@ class LinkType extends Model
|
|||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*
|
*
|
||||||
* @throws NotFoundHttpException
|
|
||||||
* @return LinkType
|
* @return LinkType
|
||||||
*
|
*
|
||||||
|
* @throws NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public static function routeBinder(string $value): LinkType
|
public static function routeBinder(string $value): LinkType
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$linkTypeId = (int) $value;
|
$linkTypeId = (int)$value;
|
||||||
$linkType = self::find($linkTypeId);
|
$linkType = self::find($linkTypeId);
|
||||||
if (null !== $linkType) {
|
if (null !== $linkType) {
|
||||||
return $linkType;
|
return $linkType;
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
@ -30,6 +31,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\Location
|
* FireflyIII\Models\Location
|
||||||
*
|
*
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
@ -32,6 +33,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
use Illuminate\Database\Eloquent\Relations\MorphToMany;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\ObjectGroup
|
* FireflyIII\Models\ObjectGroup
|
||||||
*
|
*
|
||||||
@ -63,8 +65,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
*/
|
*/
|
||||||
class ObjectGroup extends Model
|
class ObjectGroup extends Model
|
||||||
{
|
{
|
||||||
protected $fillable = ['title', 'order', 'user_id'];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
@ -77,13 +77,36 @@ class ObjectGroup extends Model
|
|||||||
'user_id' => 'integer',
|
'user_id' => 'integer',
|
||||||
'deleted_at' => 'datetime',
|
'deleted_at' => 'datetime',
|
||||||
];
|
];
|
||||||
|
protected $fillable = ['title', 'order', 'user_id'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||||
|
*
|
||||||
|
* @param string $value
|
||||||
|
*
|
||||||
|
* @return ObjectGroup
|
||||||
|
* @throws NotFoundHttpException
|
||||||
|
*/
|
||||||
|
public static function routeBinder(string $value): ObjectGroup
|
||||||
|
{
|
||||||
|
if (auth()->check()) {
|
||||||
|
$objectGroupId = (int)$value;
|
||||||
|
/** @var ObjectGroup $objectGroup */
|
||||||
|
$objectGroup = self::where('object_groups.id', $objectGroupId)
|
||||||
|
->where('object_groups.user_id', auth()->user()->id)->first();
|
||||||
|
if (null !== $objectGroup) {
|
||||||
|
return $objectGroup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new NotFoundHttpException;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return MorphToMany
|
* @return MorphToMany
|
||||||
*/
|
*/
|
||||||
public function piggyBanks()
|
public function accounts()
|
||||||
{
|
{
|
||||||
return $this->morphedByMany(PiggyBank::class, 'object_groupable');
|
return $this->morphedByMany(Account::class, 'object_groupable');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -97,31 +120,9 @@ class ObjectGroup extends Model
|
|||||||
/**
|
/**
|
||||||
* @return MorphToMany
|
* @return MorphToMany
|
||||||
*/
|
*/
|
||||||
public function accounts()
|
public function piggyBanks()
|
||||||
{
|
{
|
||||||
return $this->morphedByMany(Account::class, 'object_groupable');
|
return $this->morphedByMany(PiggyBank::class, 'object_groupable');
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
|
||||||
*
|
|
||||||
* @param string $value
|
|
||||||
*
|
|
||||||
* @throws NotFoundHttpException
|
|
||||||
* @return ObjectGroup
|
|
||||||
*/
|
|
||||||
public static function routeBinder(string $value): ObjectGroup
|
|
||||||
{
|
|
||||||
if (auth()->check()) {
|
|
||||||
$objectGroupId = (int) $value;
|
|
||||||
/** @var ObjectGroup $objectGroup */
|
|
||||||
$objectGroup = self::where('object_groups.id', $objectGroupId)
|
|
||||||
->where('object_groups.user_id', auth()->user()->id)->first();
|
|
||||||
if (null !== $objectGroup) {
|
|
||||||
return $objectGroup;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new NotFoundHttpException;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
@ -31,19 +30,21 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Query\Builder;
|
use Illuminate\Database\Query\Builder;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\PiggyBank
|
* FireflyIII\Models\PiggyBank
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property int $account_id
|
* @property int $account_id
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property string $targetamount
|
* @property string $targetamount
|
||||||
* @property \Illuminate\Support\Carbon|null $startdate
|
* @property Carbon|null $startdate
|
||||||
* @property \Illuminate\Support\Carbon|null $targetdate
|
* @property Carbon|null $targetdate
|
||||||
* @property int $order
|
* @property int $order
|
||||||
* @property bool $active
|
* @property bool $active
|
||||||
* @property bool $encrypted
|
* @property bool $encrypted
|
||||||
@ -108,13 +109,13 @@ class PiggyBank extends Model
|
|||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*
|
*
|
||||||
* @throws NotFoundHttpException
|
|
||||||
* @return PiggyBank
|
* @return PiggyBank
|
||||||
|
* @throws NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public static function routeBinder(string $value): PiggyBank
|
public static function routeBinder(string $value): PiggyBank
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$piggyBankId = (int) $value;
|
$piggyBankId = (int)$value;
|
||||||
$piggyBank = self::where('piggy_banks.id', $piggyBankId)
|
$piggyBank = self::where('piggy_banks.id', $piggyBankId)
|
||||||
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
|
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
|
||||||
->where('accounts.user_id', auth()->user()->id)->first(['piggy_banks.*']);
|
->where('accounts.user_id', auth()->user()->id)->first(['piggy_banks.*']);
|
||||||
@ -125,23 +126,6 @@ class PiggyBank extends Model
|
|||||||
throw new NotFoundHttpException;
|
throw new NotFoundHttpException;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all of the tags for the post.
|
|
||||||
*/
|
|
||||||
public function objectGroups()
|
|
||||||
{
|
|
||||||
return $this->morphToMany(ObjectGroup::class, 'object_groupable');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
* @return MorphMany
|
|
||||||
*/
|
|
||||||
public function attachments(): MorphMany
|
|
||||||
{
|
|
||||||
return $this->morphMany(Attachment::class, 'attachable');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @return BelongsTo
|
* @return BelongsTo
|
||||||
@ -151,6 +135,15 @@ class PiggyBank extends Model
|
|||||||
return $this->belongsTo(Account::class);
|
return $this->belongsTo(Account::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* @return MorphMany
|
||||||
|
*/
|
||||||
|
public function attachments(): MorphMany
|
||||||
|
{
|
||||||
|
return $this->morphMany(Attachment::class, 'attachable');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* Get all of the piggy bank's notes.
|
* Get all of the piggy bank's notes.
|
||||||
@ -160,6 +153,14 @@ class PiggyBank extends Model
|
|||||||
return $this->morphMany(Note::class, 'noteable');
|
return $this->morphMany(Note::class, 'noteable');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all of the tags for the post.
|
||||||
|
*/
|
||||||
|
public function objectGroups()
|
||||||
|
{
|
||||||
|
return $this->morphToMany(ObjectGroup::class, 'object_groupable');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @return HasMany
|
* @return HasMany
|
||||||
@ -185,6 +186,6 @@ class PiggyBank extends Model
|
|||||||
*/
|
*/
|
||||||
public function setTargetamountAttribute($value): void
|
public function setTargetamountAttribute($value): void
|
||||||
{
|
{
|
||||||
$this->attributes['targetamount'] = (string) $value;
|
$this->attributes['targetamount'] = (string)$value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,20 +22,21 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\PiggyBankEvent
|
* FireflyIII\Models\PiggyBankEvent
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property int $piggy_bank_id
|
* @property int $piggy_bank_id
|
||||||
* @property int|null $transaction_journal_id
|
* @property int|null $transaction_journal_id
|
||||||
* @property \Illuminate\Support\Carbon $date
|
* @property Carbon $date
|
||||||
* @property string $amount
|
* @property string $amount
|
||||||
* @property PiggyBank $piggyBank
|
* @property PiggyBank $piggyBank
|
||||||
* @property-read TransactionJournal|null $transactionJournal
|
* @property-read TransactionJournal|null $transactionJournal
|
||||||
@ -85,7 +86,7 @@ class PiggyBankEvent extends Model
|
|||||||
*/
|
*/
|
||||||
public function setAmountAttribute($value): void
|
public function setAmountAttribute($value): void
|
||||||
{
|
{
|
||||||
$this->attributes['amount'] = (string) $value;
|
$this->attributes['amount'] = (string)$value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -31,14 +31,14 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
/**
|
/**
|
||||||
* FireflyIII\Models\PiggyBankRepetition
|
* FireflyIII\Models\PiggyBankRepetition
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
* @property int $piggy_bank_id
|
* @property int $piggy_bank_id
|
||||||
* @property \Illuminate\Support\Carbon|null $startdate
|
* @property \Illuminate\Support\Carbon|null $startdate
|
||||||
* @property \Illuminate\Support\Carbon|null $targetdate
|
* @property \Illuminate\Support\Carbon|null $targetdate
|
||||||
* @property string $currentamount
|
* @property string $currentamount
|
||||||
* @property-read PiggyBank $piggyBank
|
* @property-read PiggyBank $piggyBank
|
||||||
* @method static EloquentBuilder|PiggyBankRepetition newModelQuery()
|
* @method static EloquentBuilder|PiggyBankRepetition newModelQuery()
|
||||||
* @method static EloquentBuilder|PiggyBankRepetition newQuery()
|
* @method static EloquentBuilder|PiggyBankRepetition newQuery()
|
||||||
* @method static EloquentBuilder|PiggyBankRepetition onDates(Carbon $start, Carbon $target)
|
* @method static EloquentBuilder|PiggyBankRepetition onDates(Carbon $start, Carbon $target)
|
||||||
@ -124,6 +124,6 @@ class PiggyBankRepetition extends Model
|
|||||||
*/
|
*/
|
||||||
public function setCurrentamountAttribute($value): void
|
public function setCurrentamountAttribute($value): void
|
||||||
{
|
{
|
||||||
$this->attributes['currentamount'] = (string) $value;
|
$this->attributes['currentamount'] = (string)$value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,13 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
/**
|
/**
|
||||||
* FireflyIII\Models\Preference
|
* FireflyIII\Models\Preference
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property string $name
|
* @property string $name
|
||||||
* @property int|string|array|null $data
|
* @property int|string|array|null $data
|
||||||
* @property-read User $user
|
* @property-read User $user
|
||||||
* @method static Builder|Preference newModelQuery()
|
* @method static Builder|Preference newModelQuery()
|
||||||
* @method static Builder|Preference newQuery()
|
* @method static Builder|Preference newQuery()
|
||||||
* @method static Builder|Preference query()
|
* @method static Builder|Preference query()
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
@ -37,10 +38,10 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
/**
|
/**
|
||||||
* FireflyIII\Models\Recurrence
|
* FireflyIII\Models\Recurrence
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property int $transaction_type_id
|
* @property int $transaction_type_id
|
||||||
* @property string $title
|
* @property string $title
|
||||||
@ -89,6 +90,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
class Recurrence extends Model
|
class Recurrence extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
@ -120,13 +122,13 @@ class Recurrence extends Model
|
|||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*
|
*
|
||||||
* @throws NotFoundHttpException
|
|
||||||
* @return Recurrence
|
* @return Recurrence
|
||||||
|
* @throws NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public static function routeBinder(string $value): Recurrence
|
public static function routeBinder(string $value): Recurrence
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$recurrenceId = (int) $value;
|
$recurrenceId = (int)$value;
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
/** @var Recurrence $recurrence */
|
/** @var Recurrence $recurrence */
|
||||||
@ -138,6 +140,15 @@ class Recurrence extends Model
|
|||||||
throw new NotFoundHttpException;
|
throw new NotFoundHttpException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* @return MorphMany
|
||||||
|
*/
|
||||||
|
public function attachments(): MorphMany
|
||||||
|
{
|
||||||
|
return $this->morphMany(Attachment::class, 'attachable');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* Get all of the notes.
|
* Get all of the notes.
|
||||||
@ -183,15 +194,6 @@ class Recurrence extends Model
|
|||||||
return $this->belongsTo(TransactionCurrency::class);
|
return $this->belongsTo(TransactionCurrency::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
* @return MorphMany
|
|
||||||
*/
|
|
||||||
public function attachments(): MorphMany
|
|
||||||
{
|
|
||||||
return $this->morphMany(Attachment::class, 'attachable');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @return BelongsTo
|
* @return BelongsTo
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
@ -58,6 +59,7 @@ use Illuminate\Support\Carbon;
|
|||||||
class RecurrenceMeta extends Model
|
class RecurrenceMeta extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
|
@ -22,20 +22,21 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Query\Builder;
|
use Illuminate\Database\Query\Builder;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\RecurrenceRepetition
|
* FireflyIII\Models\RecurrenceRepetition
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property int $recurrence_id
|
* @property int $recurrence_id
|
||||||
* @property string $repetition_type
|
* @property string $repetition_type
|
||||||
* @property string $repetition_moment
|
* @property string $repetition_moment
|
||||||
@ -70,6 +71,7 @@ class RecurrenceRepetition extends Model
|
|||||||
/** @var int */
|
/** @var int */
|
||||||
public const WEEKEND_TO_MONDAY = 4;
|
public const WEEKEND_TO_MONDAY = 4;
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
|
@ -22,20 +22,21 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Query\Builder;
|
use Illuminate\Database\Query\Builder;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Collection;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\RecurrenceTransaction
|
* FireflyIII\Models\RecurrenceTransaction
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property int $recurrence_id
|
* @property int $recurrence_id
|
||||||
@ -49,7 +50,7 @@ use Illuminate\Support\Collection;
|
|||||||
* @property-read Account $destinationAccount
|
* @property-read Account $destinationAccount
|
||||||
* @property-read TransactionCurrency|null $foreignCurrency
|
* @property-read TransactionCurrency|null $foreignCurrency
|
||||||
* @property-read Recurrence $recurrence
|
* @property-read Recurrence $recurrence
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|RecurrenceTransactionMeta[] $recurrenceTransactionMeta
|
* @property-read Collection|RecurrenceTransactionMeta[] $recurrenceTransactionMeta
|
||||||
* @property-read int|null $recurrence_transaction_meta_count
|
* @property-read int|null $recurrence_transaction_meta_count
|
||||||
* @property-read Account $sourceAccount
|
* @property-read Account $sourceAccount
|
||||||
* @property-read TransactionCurrency $transactionCurrency
|
* @property-read TransactionCurrency $transactionCurrency
|
||||||
@ -79,6 +80,7 @@ use Illuminate\Support\Collection;
|
|||||||
class RecurrenceTransaction extends Model
|
class RecurrenceTransaction extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
@ -153,6 +155,7 @@ class RecurrenceTransaction extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(TransactionCurrency::class);
|
return $this->belongsTo(TransactionCurrency::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @return BelongsTo
|
* @return BelongsTo
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
@ -58,6 +59,7 @@ use Illuminate\Support\Carbon;
|
|||||||
class RecurrenceTransactionMeta extends Model
|
class RecurrenceTransactionMeta extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
|
@ -36,25 +36,25 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
/**
|
/**
|
||||||
* FireflyIII\Models\Rule
|
* FireflyIII\Models\Rule
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property int $rule_group_id
|
* @property int $rule_group_id
|
||||||
* @property string $title
|
* @property string $title
|
||||||
* @property string|null $description
|
* @property string|null $description
|
||||||
* @property int $order
|
* @property int $order
|
||||||
* @property bool $active
|
* @property bool $active
|
||||||
* @property bool $stop_processing
|
* @property bool $stop_processing
|
||||||
* @property bool $strict
|
* @property bool $strict
|
||||||
* @property-read string $action_value
|
* @property-read string $action_value
|
||||||
* @property-read Collection|RuleAction[] $ruleActions
|
* @property-read Collection|RuleAction[] $ruleActions
|
||||||
* @property-read int|null $rule_actions_count
|
* @property-read int|null $rule_actions_count
|
||||||
* @property-read RuleGroup $ruleGroup
|
* @property-read RuleGroup $ruleGroup
|
||||||
* @property Collection|RuleTrigger[] $ruleTriggers
|
* @property Collection|RuleTrigger[] $ruleTriggers
|
||||||
* @property-read int|null $rule_triggers_count
|
* @property-read int|null $rule_triggers_count
|
||||||
* @property-read User $user
|
* @property-read User $user
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Rule newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|Rule newModelQuery()
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|Rule newQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|Rule newQuery()
|
||||||
* @method static Builder|Rule onlyTrashed()
|
* @method static Builder|Rule onlyTrashed()
|
||||||
|
@ -22,18 +22,18 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\RuleAction
|
* FireflyIII\Models\RuleAction
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property int $rule_id
|
* @property int $rule_id
|
||||||
* @property string $action_type
|
* @property string $action_type
|
||||||
* @property string $action_value
|
* @property string $action_value
|
||||||
|
@ -22,30 +22,31 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Query\Builder;
|
use Illuminate\Database\Query\Builder;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Carbon;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\RuleGroup
|
* FireflyIII\Models\RuleGroup
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property string $title
|
* @property string $title
|
||||||
* @property string|null $description
|
* @property string|null $description
|
||||||
* @property int $order
|
* @property int $order
|
||||||
* @property bool $active
|
* @property bool $active
|
||||||
* @property bool $stop_processing
|
* @property bool $stop_processing
|
||||||
* @property \Illuminate\Database\Eloquent\Collection|Rule[] $rules
|
* @property Collection|Rule[] $rules
|
||||||
* @property-read int|null $rules_count
|
* @property-read int|null $rules_count
|
||||||
* @property-read User $user
|
* @property-read User $user
|
||||||
* @method static \Illuminate\Database\Eloquent\Builder|RuleGroup newModelQuery()
|
* @method static \Illuminate\Database\Eloquent\Builder|RuleGroup newModelQuery()
|
||||||
@ -69,6 +70,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
class RuleGroup extends Model
|
class RuleGroup extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
@ -92,13 +94,13 @@ class RuleGroup extends Model
|
|||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*
|
*
|
||||||
* @throws NotFoundHttpException
|
|
||||||
* @return RuleGroup
|
* @return RuleGroup
|
||||||
|
* @throws NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public static function routeBinder(string $value): RuleGroup
|
public static function routeBinder(string $value): RuleGroup
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$ruleGroupId = (int) $value;
|
$ruleGroupId = (int)$value;
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
/** @var RuleGroup $ruleGroup */
|
/** @var RuleGroup $ruleGroup */
|
||||||
|
@ -22,18 +22,18 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\RuleTrigger
|
* FireflyIII\Models\RuleTrigger
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property int $rule_id
|
* @property int $rule_id
|
||||||
* @property string $trigger_type
|
* @property string $trigger_type
|
||||||
* @property string $trigger_value
|
* @property string $trigger_value
|
||||||
|
@ -35,33 +35,33 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||||||
/**
|
/**
|
||||||
* FireflyIII\Models\Transaction
|
* FireflyIII\Models\Transaction
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property \Illuminate\Support\Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
* @property \Illuminate\Support\Carbon|null $deleted_at
|
||||||
* @property bool $reconciled
|
* @property bool $reconciled
|
||||||
* @property int $account_id
|
* @property int $account_id
|
||||||
* @property int $transaction_journal_id
|
* @property int $transaction_journal_id
|
||||||
* @property string|null $description
|
* @property string|null $description
|
||||||
* @property int|null $transaction_currency_id
|
* @property int|null $transaction_currency_id
|
||||||
* @property string $modified
|
* @property string $modified
|
||||||
* @property string $modified_foreign
|
* @property string $modified_foreign
|
||||||
* @property string $date
|
* @property string $date
|
||||||
* @property string $max_date
|
* @property string $max_date
|
||||||
* @property string $amount
|
* @property string $amount
|
||||||
* @property string|null $foreign_amount
|
* @property string|null $foreign_amount
|
||||||
* @property int|null $foreign_currency_id
|
* @property int|null $foreign_currency_id
|
||||||
* @property int $identifier
|
* @property int $identifier
|
||||||
* @property-read \FireflyIII\Models\Account $account
|
* @property-read Account $account
|
||||||
* @property-read Collection|\FireflyIII\Models\Budget[] $budgets
|
* @property-read Collection|Budget[] $budgets
|
||||||
* @property-read int|null $budgets_count
|
* @property-read int|null $budgets_count
|
||||||
* @property-read Collection|\FireflyIII\Models\Category[] $categories
|
* @property-read Collection|Category[] $categories
|
||||||
* @property-read int|null $categories_count
|
* @property-read int|null $categories_count
|
||||||
* @property-read \FireflyIII\Models\TransactionCurrency|null $foreignCurrency
|
* @property-read TransactionCurrency|null $foreignCurrency
|
||||||
* @property-read \FireflyIII\Models\TransactionCurrency|null $transactionCurrency
|
* @property-read TransactionCurrency|null $transactionCurrency
|
||||||
* @property-read \FireflyIII\Models\TransactionJournal $transactionJournal
|
* @property-read TransactionJournal $transactionJournal
|
||||||
* @method static Builder|Transaction after(\Carbon\Carbon $date)
|
* @method static Builder|Transaction after(Carbon $date)
|
||||||
* @method static Builder|Transaction before(\Carbon\Carbon $date)
|
* @method static Builder|Transaction before(Carbon $date)
|
||||||
* @method static Builder|Transaction newModelQuery()
|
* @method static Builder|Transaction newModelQuery()
|
||||||
* @method static Builder|Transaction newQuery()
|
* @method static Builder|Transaction newQuery()
|
||||||
* @method static \Illuminate\Database\Query\Builder|Transaction onlyTrashed()
|
* @method static \Illuminate\Database\Query\Builder|Transaction onlyTrashed()
|
||||||
@ -83,11 +83,12 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||||||
* @method static \Illuminate\Database\Query\Builder|Transaction withTrashed()
|
* @method static \Illuminate\Database\Query\Builder|Transaction withTrashed()
|
||||||
* @method static \Illuminate\Database\Query\Builder|Transaction withoutTrashed()
|
* @method static \Illuminate\Database\Query\Builder|Transaction withoutTrashed()
|
||||||
* @mixin Eloquent
|
* @mixin Eloquent
|
||||||
* @property int $the_count
|
* @property int $the_count
|
||||||
*/
|
*/
|
||||||
class Transaction extends Model
|
class Transaction extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes, HasFactory;
|
use SoftDeletes, HasFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
@ -110,30 +111,6 @@ class Transaction extends Model
|
|||||||
/** @var array Hidden from view */
|
/** @var array Hidden from view */
|
||||||
protected $hidden = ['encrypted'];
|
protected $hidden = ['encrypted'];
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a table is joined.
|
|
||||||
*
|
|
||||||
* @param Builder $query
|
|
||||||
* @param string $table
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*/
|
|
||||||
public static function isJoined(Builder $query, string $table): bool
|
|
||||||
{
|
|
||||||
$joins = $query->getQuery()->joins;
|
|
||||||
if (null === $joins) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
foreach ($joins as $join) {
|
|
||||||
if ($join->table === $table) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the account this object belongs to.
|
* Get the account this object belongs to.
|
||||||
*
|
*
|
||||||
@ -194,6 +171,30 @@ class Transaction extends Model
|
|||||||
$query->where('transaction_journals.date', '>=', $date->format('Y-m-d 00:00:00'));
|
$query->where('transaction_journals.date', '>=', $date->format('Y-m-d 00:00:00'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a table is joined.
|
||||||
|
*
|
||||||
|
* @param Builder $query
|
||||||
|
* @param string $table
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
public static function isJoined(Builder $query, string $table): bool
|
||||||
|
{
|
||||||
|
$joins = $query->getQuery()->joins;
|
||||||
|
if (null === $joins) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach ($joins as $join) {
|
||||||
|
if ($join->table === $table) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for transactions BEFORE the specified date.
|
* Check for transactions BEFORE the specified date.
|
||||||
*
|
*
|
||||||
@ -235,7 +236,7 @@ class Transaction extends Model
|
|||||||
*/
|
*/
|
||||||
public function setAmountAttribute($value): void
|
public function setAmountAttribute($value): void
|
||||||
{
|
{
|
||||||
$this->attributes['amount'] = (string) $value;
|
$this->attributes['amount'] = (string)$value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,21 +22,22 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Database\Query\Builder;
|
use Illuminate\Database\Query\Builder;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\TransactionCurrency
|
* FireflyIII\Models\TransactionCurrency
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property \Illuminate\Support\Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property bool $enabled
|
* @property bool $enabled
|
||||||
* @property string $code
|
* @property string $code
|
||||||
* @property string $name
|
* @property string $name
|
||||||
@ -90,13 +91,13 @@ class TransactionCurrency extends Model
|
|||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*
|
*
|
||||||
* @throws NotFoundHttpException
|
|
||||||
* @return TransactionCurrency
|
* @return TransactionCurrency
|
||||||
|
* @throws NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public static function routeBinder(string $value): TransactionCurrency
|
public static function routeBinder(string $value): TransactionCurrency
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$currencyId = (int) $value;
|
$currencyId = (int)$value;
|
||||||
$currency = self::find($currencyId);
|
$currency = self::find($currencyId);
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
return $currency;
|
return $currency;
|
||||||
|
@ -32,6 +32,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
|||||||
use Illuminate\Database\Query\Builder;
|
use Illuminate\Database\Query\Builder;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\TransactionGroup
|
* FireflyIII\Models\TransactionGroup
|
||||||
*
|
*
|
||||||
@ -85,13 +86,13 @@ class TransactionGroup extends Model
|
|||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*
|
*
|
||||||
* @throws NotFoundHttpException
|
|
||||||
* @return TransactionGroup
|
* @return TransactionGroup
|
||||||
|
* @throws NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public static function routeBinder(string $value): TransactionGroup
|
public static function routeBinder(string $value): TransactionGroup
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$groupId = (int) $value;
|
$groupId = (int)$value;
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
/** @var TransactionGroup $group */
|
/** @var TransactionGroup $group */
|
||||||
|
@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException;
|
|||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||||
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
@ -40,52 +41,52 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
/**
|
/**
|
||||||
* FireflyIII\Models\TransactionJournal
|
* FireflyIII\Models\TransactionJournal
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Carbon\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Carbon\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property \Carbon\Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
* @property int $user_id
|
* @property int $user_id
|
||||||
* @property int $transaction_type_id
|
* @property int $transaction_type_id
|
||||||
* @property int|null $transaction_group_id
|
* @property int|null $transaction_group_id
|
||||||
* @property int|null $bill_id
|
* @property int|null $bill_id
|
||||||
* @property int|null $transaction_currency_id
|
* @property int|null $transaction_currency_id
|
||||||
* @property string $description
|
* @property string $description
|
||||||
* @property \Carbon\Carbon $date
|
* @property Carbon $date
|
||||||
* @property \Carbon\Carbon|null $interest_date
|
* @property Carbon|null $interest_date
|
||||||
* @property \Carbon\Carbon|null $book_date
|
* @property Carbon|null $book_date
|
||||||
* @property \Carbon\Carbon|null $process_date
|
* @property Carbon|null $process_date
|
||||||
* @property int $order
|
* @property int $order
|
||||||
* @property int $tag_count
|
* @property int $tag_count
|
||||||
* @property string $transaction_type_type
|
* @property string $transaction_type_type
|
||||||
* @property bool $encrypted
|
* @property bool $encrypted
|
||||||
* @property bool $completed
|
* @property bool $completed
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Attachment[] $attachments
|
* @property-read Collection|Attachment[] $attachments
|
||||||
* @property-read int|null $attachments_count
|
* @property-read int|null $attachments_count
|
||||||
* @property-read \FireflyIII\Models\Bill|null $bill
|
* @property-read Bill|null $bill
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Budget[] $budgets
|
* @property-read Collection|Budget[] $budgets
|
||||||
* @property-read int|null $budgets_count
|
* @property-read int|null $budgets_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Category[] $categories
|
* @property-read Collection|Category[] $categories
|
||||||
* @property-read int|null $categories_count
|
* @property-read int|null $categories_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournalLink[] $destJournalLinks
|
* @property-read Collection|TransactionJournalLink[] $destJournalLinks
|
||||||
* @property-read int|null $dest_journal_links_count
|
* @property-read int|null $dest_journal_links_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Note[] $notes
|
* @property-read Collection|Note[] $notes
|
||||||
* @property-read int|null $notes_count
|
* @property-read int|null $notes_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\PiggyBankEvent[] $piggyBankEvents
|
* @property-read Collection|PiggyBankEvent[] $piggyBankEvents
|
||||||
* @property-read int|null $piggy_bank_events_count
|
* @property-read int|null $piggy_bank_events_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournalLink[] $sourceJournalLinks
|
* @property-read Collection|TransactionJournalLink[] $sourceJournalLinks
|
||||||
* @property-read int|null $source_journal_links_count
|
* @property-read int|null $source_journal_links_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Tag[] $tags
|
* @property-read Collection|Tag[] $tags
|
||||||
* @property-read int|null $tags_count
|
* @property-read int|null $tags_count
|
||||||
* @property-read \FireflyIII\Models\TransactionCurrency|null $transactionCurrency
|
* @property-read TransactionCurrency|null $transactionCurrency
|
||||||
* @property-read \FireflyIII\Models\TransactionGroup|null $transactionGroup
|
* @property-read TransactionGroup|null $transactionGroup
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournalMeta[] $transactionJournalMeta
|
* @property-read Collection|TransactionJournalMeta[] $transactionJournalMeta
|
||||||
* @property-read int|null $transaction_journal_meta_count
|
* @property-read int|null $transaction_journal_meta_count
|
||||||
* @property-read \FireflyIII\Models\TransactionType $transactionType
|
* @property-read TransactionType $transactionType
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions
|
* @property-read Collection|Transaction[] $transactions
|
||||||
* @property-read int|null $transactions_count
|
* @property-read int|null $transactions_count
|
||||||
* @property-read User $user
|
* @property-read User $user
|
||||||
* @method static EloquentBuilder|TransactionJournal after(\Carbon\Carbon $date)
|
* @method static EloquentBuilder|TransactionJournal after(Carbon $date)
|
||||||
* @method static EloquentBuilder|TransactionJournal before(\Carbon\Carbon $date)
|
* @method static EloquentBuilder|TransactionJournal before(Carbon $date)
|
||||||
* @method static EloquentBuilder|TransactionJournal newModelQuery()
|
* @method static EloquentBuilder|TransactionJournal newModelQuery()
|
||||||
* @method static EloquentBuilder|TransactionJournal newQuery()
|
* @method static EloquentBuilder|TransactionJournal newQuery()
|
||||||
* @method static \Illuminate\Database\Query\Builder|TransactionJournal onlyTrashed()
|
* @method static \Illuminate\Database\Query\Builder|TransactionJournal onlyTrashed()
|
||||||
@ -112,9 +113,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
* @method static \Illuminate\Database\Query\Builder|TransactionJournal withTrashed()
|
* @method static \Illuminate\Database\Query\Builder|TransactionJournal withTrashed()
|
||||||
* @method static \Illuminate\Database\Query\Builder|TransactionJournal withoutTrashed()
|
* @method static \Illuminate\Database\Query\Builder|TransactionJournal withoutTrashed()
|
||||||
* @mixin Eloquent
|
* @mixin Eloquent
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Location[] $locations
|
* @property-read Collection|Location[] $locations
|
||||||
* @property-read int|null $locations_count
|
* @property-read int|null $locations_count
|
||||||
* @property int $the_count
|
* @property int $the_count
|
||||||
*/
|
*/
|
||||||
class TransactionJournal extends Model
|
class TransactionJournal extends Model
|
||||||
{
|
{
|
||||||
@ -147,31 +148,6 @@ class TransactionJournal extends Model
|
|||||||
/** @var array Hidden from view */
|
/** @var array Hidden from view */
|
||||||
protected $hidden = ['encrypted'];
|
protected $hidden = ['encrypted'];
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if tables are joined.
|
|
||||||
*
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
*
|
|
||||||
* @param Builder $query
|
|
||||||
* @param string $table
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function isJoined(Builder $query, string $table): bool
|
|
||||||
{
|
|
||||||
$joins = $query->getQuery()->joins;
|
|
||||||
if (null === $joins) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
foreach ($joins as $join) {
|
|
||||||
if ($join->table === $table) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||||
*
|
*
|
||||||
@ -215,15 +191,6 @@ class TransactionJournal extends Model
|
|||||||
return $this->belongsTo(Bill::class);
|
return $this->belongsTo(Bill::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
* @return MorphMany
|
|
||||||
*/
|
|
||||||
public function locations(): MorphMany
|
|
||||||
{
|
|
||||||
return $this->morphMany(Location::class, 'locatable');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @return BelongsToMany
|
* @return BelongsToMany
|
||||||
@ -264,6 +231,15 @@ class TransactionJournal extends Model
|
|||||||
return $this->transactionType->isTransfer();
|
return $this->transactionType->isTransfer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* @return MorphMany
|
||||||
|
*/
|
||||||
|
public function locations(): MorphMany
|
||||||
|
{
|
||||||
|
return $this->morphMany(Location::class, 'locatable');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* Get all of the notes.
|
* Get all of the notes.
|
||||||
@ -324,6 +300,31 @@ class TransactionJournal extends Model
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if tables are joined.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
|
* @param Builder $query
|
||||||
|
* @param string $table
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function isJoined(Builder $query, string $table): bool
|
||||||
|
{
|
||||||
|
$joins = $query->getQuery()->joins;
|
||||||
|
if (null === $joins) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
foreach ($joins as $join) {
|
||||||
|
if ($join->table === $table) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* @return HasMany
|
* @return HasMany
|
||||||
|
@ -22,21 +22,21 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FireflyIII\Models\TransactionJournalLink
|
* FireflyIII\Models\TransactionJournalLink
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property \Illuminate\Support\Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property int $link_type_id
|
* @property int $link_type_id
|
||||||
* @property int $source_id
|
* @property int $source_id
|
||||||
* @property int $destination_id
|
* @property int $destination_id
|
||||||
@ -80,14 +80,14 @@ class TransactionJournalLink extends Model
|
|||||||
*
|
*
|
||||||
* @param string $value
|
* @param string $value
|
||||||
*
|
*
|
||||||
* @throws NotFoundHttpException
|
|
||||||
* @return TransactionJournalLink
|
* @return TransactionJournalLink
|
||||||
*
|
*
|
||||||
|
* @throws NotFoundHttpException
|
||||||
*/
|
*/
|
||||||
public static function routeBinder(string $value): TransactionJournalLink
|
public static function routeBinder(string $value): TransactionJournalLink
|
||||||
{
|
{
|
||||||
if (auth()->check()) {
|
if (auth()->check()) {
|
||||||
$linkId = (int) $value;
|
$linkId = (int)$value;
|
||||||
$link = self::where('journal_links.id', $linkId)
|
$link = self::where('journal_links.id', $linkId)
|
||||||
->leftJoin('transaction_journals as t_a', 't_a.id', '=', 'source_id')
|
->leftJoin('transaction_journals as t_a', 't_a.id', '=', 'source_id')
|
||||||
->leftJoin('transaction_journals as t_b', 't_b.id', '=', 'destination_id')
|
->leftJoin('transaction_journals as t_b', 't_b.id', '=', 'destination_id')
|
||||||
|
@ -60,6 +60,7 @@ use Illuminate\Support\Carbon;
|
|||||||
class TransactionJournalMeta extends Model
|
class TransactionJournalMeta extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that should be casted to native types.
|
* The attributes that should be casted to native types.
|
||||||
*
|
*
|
||||||
|
46
app/Models/UserGroup.php
Normal file
46
app/Models/UserGroup.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UserGroup.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UserGroup
|
||||||
|
*/
|
||||||
|
class UserGroup extends Model
|
||||||
|
{
|
||||||
|
protected $fillable = ['title'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
|
* @return HasMany
|
||||||
|
*/
|
||||||
|
public function groupMemberships(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(GroupMembership::class);
|
||||||
|
}
|
||||||
|
}
|
54
app/Models/UserRole.php
Normal file
54
app/Models/UserRole.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UserRole.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UserRole
|
||||||
|
*/
|
||||||
|
class UserRole extends Model
|
||||||
|
{
|
||||||
|
public const READ_ONLY = 'ro';
|
||||||
|
public const CHANGE_TRANSACTIONS = 'change_tx';
|
||||||
|
public const CHANGE_RULES = 'change_rules';
|
||||||
|
public const CHANGE_PIGGY_BANKS = 'change_piggies';
|
||||||
|
public const CHANGE_REPETITIONS = 'change_reps';
|
||||||
|
public const VIEW_REPORTS = 'view_reports';
|
||||||
|
public const FULL = 'full';
|
||||||
|
public const OWNER = 'owner';
|
||||||
|
protected $fillable = ['title'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
|
* @return HasMany
|
||||||
|
*/
|
||||||
|
public function groupMemberships(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(GroupMembership::class);
|
||||||
|
}
|
||||||
|
}
|
@ -22,6 +22,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Models;
|
namespace FireflyIII\Models;
|
||||||
|
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
@ -36,7 +37,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
/**
|
/**
|
||||||
* FireflyIII\Models\Webhook
|
* FireflyIII\Models\Webhook
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property Carbon|null $deleted_at
|
* @property Carbon|null $deleted_at
|
||||||
@ -66,8 +67,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
* @method static \Illuminate\Database\Query\Builder|Webhook withTrashed()
|
* @method static \Illuminate\Database\Query\Builder|Webhook withTrashed()
|
||||||
* @method static \Illuminate\Database\Query\Builder|Webhook withoutTrashed()
|
* @method static \Illuminate\Database\Query\Builder|Webhook withoutTrashed()
|
||||||
* @mixin Eloquent
|
* @mixin Eloquent
|
||||||
* @property string $title
|
* @property string $title
|
||||||
* @property string $secret
|
* @property string $secret
|
||||||
* @method static Builder|Webhook whereSecret($value)
|
* @method static Builder|Webhook whereSecret($value)
|
||||||
* @method static Builder|Webhook whereTitle($value)
|
* @method static Builder|Webhook whereTitle($value)
|
||||||
*/
|
*/
|
||||||
@ -88,9 +89,6 @@ class Webhook extends Model
|
|||||||
|
|
||||||
// delivery
|
// delivery
|
||||||
public const DELIVERY_JSON = 300;
|
public const DELIVERY_JSON = 300;
|
||||||
|
|
||||||
protected $fillable = ['active', 'trigger', 'response', 'delivery', 'user_id', 'url', 'title', 'secret'];
|
|
||||||
|
|
||||||
protected $casts
|
protected $casts
|
||||||
= [
|
= [
|
||||||
'active' => 'boolean',
|
'active' => 'boolean',
|
||||||
@ -98,6 +96,7 @@ class Webhook extends Model
|
|||||||
'response' => 'integer',
|
'response' => 'integer',
|
||||||
'delivery' => 'integer',
|
'delivery' => 'integer',
|
||||||
];
|
];
|
||||||
|
protected $fillable = ['active', 'trigger', 'response', 'delivery', 'user_id', 'url', 'title', 'secret'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||||
|
@ -64,15 +64,6 @@ class WebhookAttempt extends Model
|
|||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
|
|
||||||
/**
|
|
||||||
* @codeCoverageIgnore
|
|
||||||
* @return BelongsTo
|
|
||||||
*/
|
|
||||||
public function webhookMessage(): BelongsTo
|
|
||||||
{
|
|
||||||
return $this->belongsTo(WebhookMessage::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
* Route binder. Converts the key in the URL to the specified object (or throw 404).
|
||||||
*
|
*
|
||||||
@ -95,4 +86,13 @@ class WebhookAttempt extends Model
|
|||||||
}
|
}
|
||||||
throw new NotFoundHttpException;
|
throw new NotFoundHttpException;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* @return BelongsTo
|
||||||
|
*/
|
||||||
|
public function webhookMessage(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(WebhookMessage::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
/**
|
/**
|
||||||
* FireflyIII\Models\WebhookMessage
|
* FireflyIII\Models\WebhookMessage
|
||||||
*
|
*
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property Carbon|null $created_at
|
* @property Carbon|null $created_at
|
||||||
* @property Carbon|null $updated_at
|
* @property Carbon|null $updated_at
|
||||||
* @property string|null $deleted_at
|
* @property string|null $deleted_at
|
||||||
|
@ -68,6 +68,7 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
RegisteredUser::class => [
|
RegisteredUser::class => [
|
||||||
'FireflyIII\Handlers\Events\UserEventHandler@sendRegistrationMail',
|
'FireflyIII\Handlers\Events\UserEventHandler@sendRegistrationMail',
|
||||||
'FireflyIII\Handlers\Events\UserEventHandler@attachUserRole',
|
'FireflyIII\Handlers\Events\UserEventHandler@attachUserRole',
|
||||||
|
'FireflyIII\Handlers\Events\UserEventHandler@createGroupMembership',
|
||||||
],
|
],
|
||||||
// is a User related event.
|
// is a User related event.
|
||||||
Login::class => [
|
Login::class => [
|
||||||
|
@ -79,6 +79,14 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function findById(int $id): ?AvailableBudget
|
||||||
|
{
|
||||||
|
return $this->user->availableBudgets->find($id);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a list of all available budgets (in all currencies) (for the selected period).
|
* Return a list of all available budgets (in all currencies) (for the selected period).
|
||||||
*
|
*
|
||||||
|
@ -56,6 +56,13 @@ interface AvailableBudgetRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function find(TransactionCurrency $currency, Carbon $start, Carbon $end): ?AvailableBudget;
|
public function find(TransactionCurrency $currency, Carbon $start, Carbon $end): ?AvailableBudget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $id
|
||||||
|
*
|
||||||
|
* @return AvailableBudget|null
|
||||||
|
*/
|
||||||
|
public function findById(int $id): ?AvailableBudget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a list of all available budgets (in all currencies) (for the selected period).
|
* Return a list of all available budgets (in all currencies) (for the selected period).
|
||||||
*
|
*
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Repositories\Budget;
|
namespace FireflyIII\Repositories\Budget;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Exception;
|
use Exception;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
@ -88,6 +89,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface
|
|||||||
)
|
)
|
||||||
->where('budget_limits.transaction_currency_id', $currency->id)
|
->where('budget_limits.transaction_currency_id', $currency->id)
|
||||||
->whereNull('budgets.deleted_at')
|
->whereNull('budgets.deleted_at')
|
||||||
|
->where('budgets.active', true)
|
||||||
->where('budgets.user_id', $this->user->id);
|
->where('budgets.user_id', $this->user->id);
|
||||||
if (null !== $budgets && $budgets->count() > 0) {
|
if (null !== $budgets && $budgets->count() > 0) {
|
||||||
$query->whereIn('budget_limits.budget_id', $budgets->pluck('id')->toArray());
|
$query->whereIn('budget_limits.budget_id', $budgets->pluck('id')->toArray());
|
||||||
@ -318,7 +320,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface
|
|||||||
// find the budget:
|
// find the budget:
|
||||||
$budget = $this->user->budgets()->find((int)$data['budget_id']);
|
$budget = $this->user->budgets()->find((int)$data['budget_id']);
|
||||||
if (null === $budget) {
|
if (null === $budget) {
|
||||||
throw new FireflyException('200004: Budget does not exist.');
|
throw new FireflyException('200004: Budget does not exist.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// find limit with same date range and currency.
|
// find limit with same date range and currency.
|
||||||
@ -328,7 +330,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface
|
|||||||
->where('budget_limits.transaction_currency_id', $currency->id)
|
->where('budget_limits.transaction_currency_id', $currency->id)
|
||||||
->first(['budget_limits.*']);
|
->first(['budget_limits.*']);
|
||||||
if (null !== $limit) {
|
if (null !== $limit) {
|
||||||
throw new FireflyException('200027: Budget limit already exists.');
|
throw new FireflyException('200027: Budget limit already exists.');
|
||||||
}
|
}
|
||||||
Log::debug('No existing budget limit, create a new one');
|
Log::debug('No existing budget limit, create a new one');
|
||||||
|
|
||||||
@ -424,6 +426,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface
|
|||||||
} catch (Exception $e) { // @phpstan-ignore-line
|
} catch (Exception $e) { // @phpstan-ignore-line
|
||||||
// @ignoreException
|
// @ignoreException
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// update if exists:
|
// update if exists:
|
||||||
|
@ -117,6 +117,18 @@ class BudgetRepository implements BudgetRepositoryInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a budget or return NULL
|
||||||
|
*
|
||||||
|
* @param int|null $budgetId |null
|
||||||
|
*
|
||||||
|
* @return Budget|null
|
||||||
|
*/
|
||||||
|
public function find(int $budgetId = null): ?Budget
|
||||||
|
{
|
||||||
|
return $this->user->budgets()->find($budgetId);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int|null $budgetId
|
* @param int|null $budgetId
|
||||||
* @param string|null $budgetName
|
* @param string|null $budgetName
|
||||||
@ -157,18 +169,6 @@ class BudgetRepository implements BudgetRepositoryInterface
|
|||||||
return $this->user->budgets()->where('name', 'LIKE', $query)->first();
|
return $this->user->budgets()->where('name', 'LIKE', $query)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a budget or return NULL
|
|
||||||
*
|
|
||||||
* @param int|null $budgetId |null
|
|
||||||
*
|
|
||||||
* @return Budget|null
|
|
||||||
*/
|
|
||||||
public function find(int $budgetId = null): ?Budget
|
|
||||||
{
|
|
||||||
return $this->user->budgets()->find($budgetId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the oldest journal or transaction date known to this budget.
|
* This method returns the oldest journal or transaction date known to this budget.
|
||||||
* Will cache result.
|
* Will cache result.
|
||||||
|
@ -56,6 +56,14 @@ interface BudgetRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function destroyAutoBudget(Budget $budget): void;
|
public function destroyAutoBudget(Budget $budget): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param int|null $budgetId
|
||||||
|
*
|
||||||
|
* @return Budget|null
|
||||||
|
*/
|
||||||
|
public function find(int $budgetId = null): ?Budget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int|null $budgetId
|
* @param int|null $budgetId
|
||||||
* @param string|null $budgetName
|
* @param string|null $budgetName
|
||||||
@ -73,14 +81,6 @@ interface BudgetRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function findByName(?string $name): ?Budget;
|
public function findByName(?string $name): ?Budget;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param int|null $budgetId
|
|
||||||
*
|
|
||||||
* @return Budget|null
|
|
||||||
*/
|
|
||||||
public function find(int $budgetId = null): ?Budget;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns the oldest journal or transaction date known to this budget.
|
* This method returns the oldest journal or transaction date known to this budget.
|
||||||
* Will cache result.
|
* Will cache result.
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Repositories\Budget;
|
namespace FireflyIII\Repositories\Budget;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
@ -146,8 +147,8 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface
|
|||||||
|
|
||||||
/** @noinspection MoreThanThreeArgumentsInspection */
|
/** @noinspection MoreThanThreeArgumentsInspection */
|
||||||
/**
|
/**
|
||||||
* See reference nr. 15
|
* See reference nr. 15
|
||||||
* See reference nr. 16
|
* See reference nr. 16
|
||||||
*
|
*
|
||||||
* @param Carbon $start
|
* @param Carbon $start
|
||||||
* @param Carbon $end
|
* @param Carbon $end
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Repositories\Budget;
|
namespace FireflyIII\Repositories\Budget;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
|
@ -180,7 +180,7 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
|
|
||||||
// add journal to array:
|
// add journal to array:
|
||||||
// only a subset of the fields.
|
// only a subset of the fields.
|
||||||
$journalId = (int)$journal['transaction_journal_id'];
|
$journalId = (int)$journal['transaction_journal_id'];
|
||||||
$array[$currencyId]['budgets'][$budgetId]['transaction_journals'][$journalId] = [
|
$array[$currencyId]['budgets'][$budgetId]['transaction_journals'][$journalId] = [
|
||||||
'amount' => app('steam')->negative($journal['amount']),
|
'amount' => app('steam')->negative($journal['amount']),
|
||||||
'destination_account_id' => $journal['destination_account_id'],
|
'destination_account_id' => $journal['destination_account_id'],
|
||||||
@ -227,7 +227,7 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
if ($accounts->count() > 0) {
|
if ($accounts->count() > 0) {
|
||||||
$collector->setAccounts($accounts);
|
$collector->setAccounts($accounts);
|
||||||
}
|
}
|
||||||
// See reference nr. 13
|
// See reference nr. 13
|
||||||
$set = $collector->getGroups();
|
$set = $collector->getGroups();
|
||||||
$return = [];
|
$return = [];
|
||||||
$total = [];
|
$total = [];
|
||||||
@ -343,23 +343,13 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
$array[$foreignId]['sum'] = bcadd($array[$foreignId]['sum'], app('steam')->negative($journal['foreign_amount']));
|
$array[$foreignId]['sum'] = bcadd($array[$foreignId]['sum'], app('steam')->negative($journal['foreign_amount']));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $array;
|
return $array;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Collection
|
|
||||||
*/
|
|
||||||
private function getBudgets(): Collection
|
|
||||||
{
|
|
||||||
/** @var BudgetRepositoryInterface $repos */
|
|
||||||
$repos = app(BudgetRepositoryInterface::class);
|
|
||||||
|
|
||||||
return $repos->getActiveBudgets();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For now, simply refer to whichever repository holds this function.
|
* For now, simply refer to whichever repository holds this function.
|
||||||
* See reference nr. 14
|
* See reference nr. 14
|
||||||
*
|
*
|
||||||
* @param Budget $budget
|
* @param Budget $budget
|
||||||
* @param Carbon|null $start
|
* @param Carbon|null $start
|
||||||
@ -374,4 +364,15 @@ class OperationsRepository implements OperationsRepositoryInterface
|
|||||||
|
|
||||||
return $blRepository->getBudgetLimits($budget, $start, $end);
|
return $blRepository->getBudgetLimits($budget, $start, $end);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection
|
||||||
|
*/
|
||||||
|
private function getBudgets(): Collection
|
||||||
|
{
|
||||||
|
/** @var BudgetRepositoryInterface $repos */
|
||||||
|
$repos = app(BudgetRepositoryInterface::class);
|
||||||
|
|
||||||
|
return $repos->getActiveBudgets();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ interface OperationsRepositoryInterface
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function budgetedPerDay(Budget $budget): string;
|
public function budgetedPerDay(Budget $budget): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Collection $budgets
|
* @param Collection $budgets
|
||||||
* @param Collection $accounts
|
* @param Collection $accounts
|
||||||
|
@ -88,14 +88,15 @@ trait ModifiesPiggyBanks
|
|||||||
*/
|
*/
|
||||||
public function canAddAmount(PiggyBank $piggyBank, string $amount): bool
|
public function canAddAmount(PiggyBank $piggyBank, string $amount): bool
|
||||||
{
|
{
|
||||||
$leftOnAccount = $this->leftOnAccount($piggyBank, today(config('app.timezone')));
|
$today = today(config('app.timezone'));
|
||||||
|
$leftOnAccount = $this->leftOnAccount($piggyBank, $today);
|
||||||
$savedSoFar = (string)$this->getRepetition($piggyBank)->currentamount;
|
$savedSoFar = (string)$this->getRepetition($piggyBank)->currentamount;
|
||||||
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
$leftToSave = bcsub($piggyBank->targetamount, $savedSoFar);
|
||||||
$maxAmount = 1 === bccomp($leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount;
|
$maxAmount = 1 === bccomp($leftOnAccount, $leftToSave) ? $leftToSave : $leftOnAccount;
|
||||||
$compare = bccomp($amount, $maxAmount);
|
$compare = bccomp($amount, $maxAmount);
|
||||||
$result = $compare <= 0;
|
$result = $compare <= 0;
|
||||||
|
|
||||||
Log::debug(sprintf('Left on account: %s', $leftOnAccount));
|
Log::debug(sprintf('Left on account: %s on %s', $leftOnAccount, $today->format('Y-m-d')));
|
||||||
Log::debug(sprintf('Saved so far: %s', $savedSoFar));
|
Log::debug(sprintf('Saved so far: %s', $savedSoFar));
|
||||||
Log::debug(sprintf('Left to save: %s', $leftToSave));
|
Log::debug(sprintf('Left to save: %s', $leftToSave));
|
||||||
Log::debug(sprintf('Maximum amount: %s', $maxAmount));
|
Log::debug(sprintf('Maximum amount: %s', $maxAmount));
|
||||||
|
@ -345,6 +345,10 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
if (null !== $account) {
|
if (null !== $account) {
|
||||||
$this->collector->setSourceAccounts(new Collection([$account]));
|
$this->collector->setSourceAccounts(new Collection([$account]));
|
||||||
}
|
}
|
||||||
|
if (null === $account) {
|
||||||
|
// since the source does not exist, cannot return results:
|
||||||
|
$this->collector->findNothing();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'journal_id':
|
case 'journal_id':
|
||||||
$parts = explode(',', $value);
|
$parts = explode(',', $value);
|
||||||
@ -383,6 +387,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
if (null !== $account) {
|
if (null !== $account) {
|
||||||
$this->collector->setDestinationAccounts(new Collection([$account]));
|
$this->collector->setDestinationAccounts(new Collection([$account]));
|
||||||
}
|
}
|
||||||
|
if (null === $account) {
|
||||||
|
$this->collector->findNothing();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'account_id':
|
case 'account_id':
|
||||||
$parts = explode(',', $value);
|
$parts = explode(',', $value);
|
||||||
@ -396,6 +403,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
if ($collection->count() > 0) {
|
if ($collection->count() > 0) {
|
||||||
$this->collector->setAccounts($collection);
|
$this->collector->setAccounts($collection);
|
||||||
}
|
}
|
||||||
|
if (0 === $collection->count()) {
|
||||||
|
$this->collector->findNothing();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
//
|
//
|
||||||
// cash account
|
// cash account
|
||||||
@ -436,12 +446,18 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
$this->collector->setCurrency($currency);
|
$this->collector->setCurrency($currency);
|
||||||
}
|
}
|
||||||
|
if (null === $currency) {
|
||||||
|
$this->collector->findNothing();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'foreign_currency_is':
|
case 'foreign_currency_is':
|
||||||
$currency = $this->findCurrency($value);
|
$currency = $this->findCurrency($value);
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
$this->collector->setForeignCurrency($currency);
|
$this->collector->setForeignCurrency($currency);
|
||||||
}
|
}
|
||||||
|
if (null === $currency) {
|
||||||
|
$this->collector->findNothing();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
//
|
//
|
||||||
// attachments
|
// attachments
|
||||||
@ -463,6 +479,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setCategories($result);
|
$this->collector->setCategories($result);
|
||||||
}
|
}
|
||||||
|
if (0 === $result->count()) {
|
||||||
|
$this->collector->findNothing();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
//
|
//
|
||||||
// budgets
|
// budgets
|
||||||
@ -478,6 +497,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setBudgets($result);
|
$this->collector->setBudgets($result);
|
||||||
}
|
}
|
||||||
|
if (0 === $result->count()) {
|
||||||
|
$this->collector->findNothing();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
//
|
//
|
||||||
// bill
|
// bill
|
||||||
@ -493,6 +515,9 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setBills($result);
|
$this->collector->setBills($result);
|
||||||
}
|
}
|
||||||
|
if (0 === $result->count()) {
|
||||||
|
$this->collector->findNothing();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
//
|
//
|
||||||
// tags
|
// tags
|
||||||
@ -508,6 +533,11 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
if ($result->count() > 0) {
|
if ($result->count() > 0) {
|
||||||
$this->collector->setTags($result);
|
$this->collector->setTags($result);
|
||||||
}
|
}
|
||||||
|
// no tags found means search must result in nothing.
|
||||||
|
if (0 === $result->count()) {
|
||||||
|
Log::info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
|
||||||
|
$this->collector->findNothing();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
//
|
//
|
||||||
// notes
|
// notes
|
||||||
@ -698,10 +728,8 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
// get accounts:
|
// get accounts:
|
||||||
$accounts = $this->accountRepository->searchAccount($value, $searchTypes, 25);
|
$accounts = $this->accountRepository->searchAccount($value, $searchTypes, 25);
|
||||||
if (0 === $accounts->count()) {
|
if (0 === $accounts->count()) {
|
||||||
Log::debug('Found zero accounts, search for invalid account.');
|
Log::debug('Found zero accounts, search for non existing account, NO results will be returned.');
|
||||||
$account = new Account;
|
$this->collector->findNothing();
|
||||||
$account->id = 0;
|
|
||||||
$this->collector->$collectorMethod(new Collection([$account]));
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -713,10 +741,8 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (0 === $filtered->count()) {
|
if (0 === $filtered->count()) {
|
||||||
Log::debug('Left with zero accounts, search for invalid account.');
|
Log::debug('Left with zero accounts, so cannot find anything, NO results will be returned.');
|
||||||
$account = new Account;
|
$this->collector->findNothing();
|
||||||
$account->id = 0;
|
|
||||||
$this->collector->$collectorMethod(new Collection([$account]));
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -764,9 +790,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
$accounts = $this->accountRepository->searchAccountNr($value, $searchTypes, 25);
|
$accounts = $this->accountRepository->searchAccountNr($value, $searchTypes, 25);
|
||||||
if (0 === $accounts->count()) {
|
if (0 === $accounts->count()) {
|
||||||
Log::debug('Found zero accounts, search for invalid account.');
|
Log::debug('Found zero accounts, search for invalid account.');
|
||||||
$account = new Account;
|
$this->collector->findNothing();
|
||||||
$account->id = 0;
|
|
||||||
$this->collector->$collectorMethod(new Collection([$account]));
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -791,9 +815,7 @@ class OperatorQuerySearch implements SearchInterface
|
|||||||
|
|
||||||
if (0 === $filtered->count()) {
|
if (0 === $filtered->count()) {
|
||||||
Log::debug('Left with zero, search for invalid account');
|
Log::debug('Left with zero, search for invalid account');
|
||||||
$account = new Account;
|
$this->collector->findNothing();
|
||||||
$account->id = 0;
|
|
||||||
$this->collector->$collectorMethod(new Collection([$account]));
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -57,12 +57,18 @@ class UpdatePiggybank implements ActionInterface
|
|||||||
public function actOnArray(array $journal): bool
|
public function actOnArray(array $journal): bool
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('Triggered rule action UpdatePiggybank on journal #%d', $journal['transaction_journal_id']));
|
Log::debug(sprintf('Triggered rule action UpdatePiggybank on journal #%d', $journal['transaction_journal_id']));
|
||||||
|
|
||||||
|
// refresh the transaction type.
|
||||||
|
$user = User::find($journal['user_id']);
|
||||||
|
$journalObj = $user->transactionJournals()->find($journal['transaction_journal_id']);
|
||||||
|
$type = TransactionType::find((int)$journalObj->transaction_type_id);
|
||||||
|
$journal['transaction_type_type'] = $type->type;
|
||||||
|
|
||||||
if (TransactionType::TRANSFER !== $journal['transaction_type_type']) {
|
if (TransactionType::TRANSFER !== $journal['transaction_type_type']) {
|
||||||
Log::info(sprintf('Journal #%d is a "%s" so skip this action.', $journal['transaction_journal_id'], $journal['transaction_type_type']));
|
Log::info(sprintf('Journal #%d is a "%s" so skip this action.', $journal['transaction_journal_id'], $journal['transaction_type_type']));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$user = User::find($journal['user_id']);
|
|
||||||
|
|
||||||
$piggyBank = $this->findPiggybank($user);
|
$piggyBank = $this->findPiggybank($user);
|
||||||
if (null === $piggyBank) {
|
if (null === $piggyBank) {
|
||||||
@ -92,7 +98,7 @@ class UpdatePiggybank implements ActionInterface
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Log::info('Piggy bank is not linked to source or destination, so no action will be taken.');
|
Log::info(sprintf('Piggy bank is not linked to source ("#%d") or destination ("#%d"), so no action will be taken.', $source->account_id, $destination->account_id));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
38
app/User.php
38
app/User.php
@ -34,6 +34,7 @@ use FireflyIII\Models\Bill;
|
|||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Models\CurrencyExchangeRate;
|
use FireflyIII\Models\CurrencyExchangeRate;
|
||||||
|
use FireflyIII\Models\GroupMembership;
|
||||||
use FireflyIII\Models\ObjectGroup;
|
use FireflyIII\Models\ObjectGroup;
|
||||||
use FireflyIII\Models\PiggyBank;
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Models\Preference;
|
use FireflyIII\Models\Preference;
|
||||||
@ -45,8 +46,10 @@ use FireflyIII\Models\Tag;
|
|||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionGroup;
|
use FireflyIII\Models\TransactionGroup;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
|
use FireflyIII\Models\UserGroup;
|
||||||
use FireflyIII\Models\Webhook;
|
use FireflyIII\Models\Webhook;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||||
@ -136,14 +139,14 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|||||||
* @method static Builder|User whereObjectguid($value)
|
* @method static Builder|User whereObjectguid($value)
|
||||||
* @property string|null $provider
|
* @property string|null $provider
|
||||||
* @method static Builder|User whereProvider($value)
|
* @method static Builder|User whereProvider($value)
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|ObjectGroup[] $objectGroups
|
* @property-read \Illuminate\Database\Eloquent\Collection|ObjectGroup[] $objectGroups
|
||||||
* @property-read int|null $object_groups_count
|
* @property-read int|null $object_groups_count
|
||||||
* @property-read \Illuminate\Database\Eloquent\Collection|Webhook[] $webhooks
|
* @property-read \Illuminate\Database\Eloquent\Collection|Webhook[] $webhooks
|
||||||
* @property-read int|null $webhooks_count
|
* @property-read int|null $webhooks_count
|
||||||
* @property string|null $two_factor_secret
|
* @property string|null $two_factor_secret
|
||||||
* @property string|null $two_factor_recovery_codes
|
* @property string|null $two_factor_recovery_codes
|
||||||
* @property string|null $guid
|
* @property string|null $guid
|
||||||
* @property string|null $domain
|
* @property string|null $domain
|
||||||
* @method static Builder|User whereDomain($value)
|
* @method static Builder|User whereDomain($value)
|
||||||
* @method static Builder|User whereGuid($value)
|
* @method static Builder|User whereGuid($value)
|
||||||
* @method static Builder|User whereTwoFactorRecoveryCodes($value)
|
* @method static Builder|User whereTwoFactorRecoveryCodes($value)
|
||||||
@ -212,6 +215,16 @@ class User extends Authenticatable
|
|||||||
return $this->hasMany(Account::class);
|
return $this->hasMany(Account::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
|
* @return HasMany
|
||||||
|
*/
|
||||||
|
public function groupMemberships(): HasMany
|
||||||
|
{
|
||||||
|
return $this->hasMany(GroupMembership::class)->with(['userGroup','userRole']);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* Link to attachments
|
* Link to attachments
|
||||||
@ -300,6 +313,14 @@ class User extends Authenticatable
|
|||||||
return $this->hasMany(Category::class);
|
return $this->hasMany(Category::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* @return BelongsTo
|
||||||
|
*/
|
||||||
|
public function userGroup(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(UserGroup::class,);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* @codeCoverageIgnore
|
* @codeCoverageIgnore
|
||||||
* Link to currency exchange rates
|
* Link to currency exchange rates
|
||||||
@ -449,6 +470,7 @@ class User extends Authenticatable
|
|||||||
}
|
}
|
||||||
|
|
||||||
// start LDAP related code
|
// start LDAP related code
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the database column name of the domain.
|
* Get the database column name of the domain.
|
||||||
*
|
*
|
||||||
|
@ -28,7 +28,6 @@ use FireflyIII\Exceptions\FireflyException;
|
|||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\AccountMeta;
|
use FireflyIII\Models\AccountMeta;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\PiggyBank;
|
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Models\Webhook;
|
use FireflyIII\Models\Webhook;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
@ -43,6 +42,7 @@ use Google2FA;
|
|||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Validation\Validator;
|
use Illuminate\Validation\Validator;
|
||||||
use Log;
|
use Log;
|
||||||
|
use ValueError;
|
||||||
use function is_string;
|
use function is_string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,6 +114,7 @@ class FireflyValidator extends Validator
|
|||||||
* @param mixed $value
|
* @param mixed $value
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function validateIban($attribute, $value): bool
|
public function validateIban($attribute, $value): bool
|
||||||
{
|
{
|
||||||
@ -168,11 +169,15 @@ class FireflyValidator extends Validator
|
|||||||
"\u{202F}", // narrow no-break space
|
"\u{202F}", // narrow no-break space
|
||||||
"\u{3000}", // ideographic space
|
"\u{3000}", // ideographic space
|
||||||
"\u{FEFF}", // zero width no -break space
|
"\u{FEFF}", // zero width no -break space
|
||||||
|
'-',
|
||||||
|
'?'
|
||||||
];
|
];
|
||||||
$replace = '';
|
$replace = '';
|
||||||
$value = str_replace($search, $replace, $value);
|
$value = str_replace($search, $replace, $value);
|
||||||
$value = strtoupper($value);
|
$value = strtoupper($value);
|
||||||
|
|
||||||
|
// replace characters outside of ASCI range.
|
||||||
|
$value = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $value);
|
||||||
$search = [' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
|
$search = [' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
|
||||||
$replace = ['', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31',
|
$replace = ['', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31',
|
||||||
'32', '33', '34', '35',];
|
'32', '33', '34', '35',];
|
||||||
@ -185,7 +190,14 @@ class FireflyValidator extends Validator
|
|||||||
if (0 === strlen($iban)) {
|
if (0 === strlen($iban)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$checksum = bcmod($iban, '97');
|
try {
|
||||||
|
$checksum = bcmod($iban, '97');
|
||||||
|
} catch (ValueError $e) {
|
||||||
|
$message = sprintf('Could not validate IBAN check value "%s" (IBAN "%s")', $iban, $value);
|
||||||
|
Log::error($message);
|
||||||
|
Log::error($e->getTraceAsString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return 1 === (int)$checksum;
|
return 1 === (int)$checksum;
|
||||||
}
|
}
|
||||||
@ -471,12 +483,13 @@ class FireflyValidator extends Validator
|
|||||||
$ignore = (int)($parameters[0] ?? 0.0);
|
$ignore = (int)($parameters[0] ?? 0.0);
|
||||||
$accountTypeIds = $accountTypes->pluck('id')->toArray();
|
$accountTypeIds = $accountTypes->pluck('id')->toArray();
|
||||||
/** @var Collection $set */
|
/** @var Collection $set */
|
||||||
$set = auth()->user()->accounts()->whereIn('account_type_id', $accountTypeIds)->where('id', '!=', $ignore)->get();
|
$set = auth()->user()->accounts()->whereIn('account_type_id', $accountTypeIds)->where('id', '!=', $ignore)->get();
|
||||||
$result = $set->first(
|
$result = $set->first(
|
||||||
function (Account $account) use ($value) {
|
function (Account $account) use ($value) {
|
||||||
return $account->name === $value;
|
return $account->name === $value;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return null === $result;
|
return null === $result;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -500,6 +513,7 @@ class FireflyValidator extends Validator
|
|||||||
return $account->name === $value;
|
return $account->name === $value;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
return null === $result;
|
return null === $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -717,7 +731,8 @@ class FireflyValidator extends Validator
|
|||||||
if (null !== $exclude) {
|
if (null !== $exclude) {
|
||||||
$query->where('piggy_banks.id', '!=', (int)$exclude);
|
$query->where('piggy_banks.id', '!=', (int)$exclude);
|
||||||
}
|
}
|
||||||
$query->where('piggy_banks.name',$value);
|
$query->where('piggy_banks.name', $value);
|
||||||
|
|
||||||
return null === $query->first(['piggy_banks.*']);
|
return null === $query->first(['piggy_banks.*']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
37
changelog.md
37
changelog.md
@ -2,38 +2,55 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
## 5.6.0 - 2021-xx-xx
|
## 5.6.0 - 2021-09-17
|
||||||
|
|
||||||
⚠️ This release features new LDAP libraries. Your mileage may vary. Make sure you back up everything. Firefly III may accidentally create a new account for you instead of reusing the old one. There is no option for LDAP filters yet.
|
⚠️ This release features new LDAP libraries. Your mileage may vary. Make sure you back up everything. Firefly III may accidentally create a new account for you instead of reusing the old one. There is no option for LDAP filters yet.
|
||||||
|
|
||||||
|
Please refer to the [documentation](https://docs.firefly-iii.org/firefly-iii/) and support channels if you run into problems:
|
||||||
|
|
||||||
|
- [Gitter.im](https://gitter.im/firefly-iii/firefly-iii)
|
||||||
|
- [Twitter](https://twitter.com/Firefly_III/)
|
||||||
|
- [GitHub Issues](https://github.com/firefly-iii/firefly-iii/issues)
|
||||||
|
- [GitHub Discussions](https://github.com/firefly-iii/firefly-iii/discussions)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- A few new pages for the new v2 layout. Thanks @alex6480!
|
- A few new pages for the new v2 layout. Thanks @alex6480!
|
||||||
- Added a new currency yay!
|
- Added a new currency, thanks @kasperkls02!
|
||||||
- You can now manage loans and debts a little better.
|
- You can now manage loans and debts a little better, see also the documentation for help.
|
||||||
|
- Some screenshots are now in the GitHub repository for better management, thanks @Flightkick!
|
||||||
|
- @LBreda has added a service worker and updated icons, thanks!
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
- @hoshsadiq has added all PHP requirements to the composer file, thanks!
|
||||||
- A better cache routine for layout v2 pages.
|
- A better cache routine for layout v2 pages.
|
||||||
- All LDAP libraries have been upgrade.
|
- All LDAP libraries have been upgraded.
|
||||||
|
- New issue templates and help text for easier GitHub support.
|
||||||
### Deprecated
|
- First preparations for multi-administration and group membership options.
|
||||||
- Initial release.
|
- The search will return nothing if you submit invalid values, instead of everything.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- All telemetry options have been removed.
|
- All telemetry options have been removed.
|
||||||
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- [Issue 4894](https://github.com/firefly-iii/firefly-iii/issues/4894) Bad number comparison
|
- [Issue 4894](https://github.com/firefly-iii/firefly-iii/issues/4894) Bad number comparison
|
||||||
|
- [Issue 4987](https://github.com/firefly-iii/firefly-iii/issues/4987) Budgeted amount includes inactive budgets
|
||||||
|
- [Issue 4988](https://github.com/firefly-iii/firefly-iii/issues/4988) Can't select liability account from imported transactions
|
||||||
|
- #5042 HTTP 500 when creating Personal Access Token or OAuth Client
|
||||||
- Various Sonarqube issues, thanks @hazma-fadil!
|
- Various Sonarqube issues, thanks @hazma-fadil!
|
||||||
- Correct menu display, thanks @vonsogt!
|
- Correct menu display, thanks @vonsogt!
|
||||||
|
- The IBAN validator will filter special characters.
|
||||||
|
- In some cases, piggy banks would report being full or empty while this was not actually the case.
|
||||||
|
- Various other bugs and minor issues.
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
- Feature to be able to rebuild Docker images and show security warnings in new builds.
|
- Feature to be able to rebuild Docker images and show security warnings in new builds.
|
||||||
|
- [CVE-2021-3663](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3663) A missing rate limiter makes brute-forcing the login easy.
|
||||||
|
- It also fixes [CVE-2021-3728](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3728), [CVE-2021-3729](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3729) and [CVE-2021-3730](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-3730), all variations of the same security vulnerability: some actions in Firefly III were vulnerable to CSRF.
|
||||||
|
|
||||||
### API
|
### API
|
||||||
- You can disable webhooks with an extra field in API submissions.
|
- You can disable webhooks with an extra field in API submissions.
|
||||||
- There is a static cron token (see `.env.example`) which is useful for Docker.
|
- There is a static cron token (see `.env.example`) which is useful for Docker.
|
||||||
|
- A better endpoint to move transactions around, see [api-docs.firefly-iii.org](https://api-docs.firefly-iii.org).
|
||||||
|
|
||||||
## 5.5.13 - 2021-07-25
|
## 5.5.13 - 2021-07-25
|
||||||
|
|
||||||
|
@ -74,14 +74,18 @@
|
|||||||
"ext-curl": "*",
|
"ext-curl": "*",
|
||||||
"ext-fileinfo": "*",
|
"ext-fileinfo": "*",
|
||||||
"ext-gd": "*",
|
"ext-gd": "*",
|
||||||
|
"ext-iconv": "*",
|
||||||
"ext-intl": "*",
|
"ext-intl": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
|
"ext-mbstring": "*",
|
||||||
"ext-openssl": "*",
|
"ext-openssl": "*",
|
||||||
"ext-pdo": "*",
|
"ext-pdo": "*",
|
||||||
"ext-session": "*",
|
"ext-session": "*",
|
||||||
"ext-simplexml": "*",
|
"ext-simplexml": "*",
|
||||||
|
"ext-sodium": "*",
|
||||||
"ext-tokenizer": "*",
|
"ext-tokenizer": "*",
|
||||||
"ext-xml": "*",
|
"ext-xml": "*",
|
||||||
|
"ext-xmlwriter": "*",
|
||||||
"bacon/bacon-qr-code": "2.*",
|
"bacon/bacon-qr-code": "2.*",
|
||||||
"diglactic/laravel-breadcrumbs": "^7.0",
|
"diglactic/laravel-breadcrumbs": "^7.0",
|
||||||
"doctrine/dbal": "3.*",
|
"doctrine/dbal": "3.*",
|
||||||
@ -173,6 +177,7 @@
|
|||||||
"@php artisan firefly-iii:migrate-tag-locations",
|
"@php artisan firefly-iii:migrate-tag-locations",
|
||||||
"@php artisan firefly-iii:migrate-recurrence-type",
|
"@php artisan firefly-iii:migrate-recurrence-type",
|
||||||
"@php artisan firefly-iii:upgrade-liabilities",
|
"@php artisan firefly-iii:upgrade-liabilities",
|
||||||
|
"@php artisan firefly-iii:create-group-memberships",
|
||||||
|
|
||||||
"@php artisan firefly-iii:fix-piggies",
|
"@php artisan firefly-iii:fix-piggies",
|
||||||
"@php artisan firefly-iii:create-link-types",
|
"@php artisan firefly-iii:create-link-types",
|
||||||
|
602
composer.lock
generated
602
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,25 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* breadcrumbs.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -1,4 +1,25 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bulk.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
use FireflyIII\Enums\ClauseType;
|
use FireflyIII\Enums\ClauseType;
|
||||||
|
@ -101,9 +101,9 @@ return [
|
|||||||
'webhooks' => true,
|
'webhooks' => true,
|
||||||
'handle_debts' => true,
|
'handle_debts' => true,
|
||||||
],
|
],
|
||||||
'version' => '5.6.0-alpha.2',
|
'version' => '5.6.0',
|
||||||
'api_version' => '1.5.3',
|
'api_version' => '1.5.3',
|
||||||
'db_version' => 17,
|
'db_version' => 18,
|
||||||
|
|
||||||
// generic settings
|
// generic settings
|
||||||
'maxUploadSize' => 1073741824, // 1 GB
|
'maxUploadSize' => 1073741824, // 1 GB
|
||||||
|
@ -1,4 +1,25 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ldap.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
40
config/user_roles.php
Normal file
40
config/user_roles.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* user_roles.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Models\UserRole;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
'roles' => [
|
||||||
|
UserRole::READ_ONLY => [],
|
||||||
|
UserRole::CHANGE_TRANSACTIONS => [],
|
||||||
|
UserRole::CHANGE_RULES => [],
|
||||||
|
UserRole::CHANGE_PIGGY_BANKS => [],
|
||||||
|
UserRole::CHANGE_REPETITIONS => [],
|
||||||
|
UserRole::VIEW_REPORTS => [],
|
||||||
|
UserRole::FULL => [],
|
||||||
|
UserRole::OWNER => [],
|
||||||
|
],
|
||||||
|
];
|
148
database/migrations/2021_08_28_073733_user_groups.php
Normal file
148
database/migrations/2021_08_28_073733_user_groups.php
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2021_08_28_073733_user_groups.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UserGroups
|
||||||
|
*/
|
||||||
|
class UserGroups extends Migration
|
||||||
|
{
|
||||||
|
private array $tables
|
||||||
|
= ['accounts', 'attachments', 'available_budgets', 'bills', 'budgets', 'categories', 'recurrences', 'rule_groups', 'rules', 'tags',
|
||||||
|
'transaction_groups', 'transaction_journals', 'webhooks'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
// remove columns from tables
|
||||||
|
/** @var string $tableName */
|
||||||
|
foreach ($this->tables as $tableName) {
|
||||||
|
Schema::table(
|
||||||
|
$tableName, function (Blueprint $table) use ($tableName) {
|
||||||
|
|
||||||
|
$table->dropForeign(sprintf('%s_to_ugi', $tableName));
|
||||||
|
if (Schema::hasColumn($tableName, 'user_group_id')) {
|
||||||
|
$table->dropColumn('user_group_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Schema::table(
|
||||||
|
'users', function (Blueprint $table) {
|
||||||
|
|
||||||
|
$table->dropForeign('type_user_group_id');
|
||||||
|
if (Schema::hasColumn('users', 'user_group_id')) {
|
||||||
|
$table->dropColumn('user_group_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Schema::dropIfExists('group_memberships');
|
||||||
|
Schema::dropIfExists('user_roles');
|
||||||
|
Schema::dropIfExists('user_groups');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* user is a member of a user_group through a user_group_role
|
||||||
|
* may have multiple roles in a group
|
||||||
|
*/
|
||||||
|
Schema::create(
|
||||||
|
'user_groups', static function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
|
||||||
|
$table->string('title', 255);
|
||||||
|
$table->unique('title');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Schema::create(
|
||||||
|
'user_roles', static function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
|
||||||
|
$table->string('title', 255);
|
||||||
|
$table->unique('title');
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
Schema::create(
|
||||||
|
'group_memberships',
|
||||||
|
static function (Blueprint $table) {
|
||||||
|
$table->bigIncrements('id');
|
||||||
|
$table->timestamps();
|
||||||
|
$table->softDeletes();
|
||||||
|
$table->integer('user_id', false, true);
|
||||||
|
$table->bigInteger('user_group_id', false, true);
|
||||||
|
$table->bigInteger('user_role_id', false, true);
|
||||||
|
|
||||||
|
$table->foreign('user_id')->references('id')->on('users')->onUpdate('cascade')->onDelete('cascade');
|
||||||
|
$table->foreign('user_group_id')->references('id')->on('user_groups')->onUpdate('cascade')->onDelete('cascade');
|
||||||
|
$table->foreign('user_role_id')->references('id')->on('user_roles')->onUpdate('cascade')->onDelete('cascade');
|
||||||
|
$table->unique(['user_id', 'user_group_id', 'user_role_id']);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
Schema::table(
|
||||||
|
'users', function (Blueprint $table) {
|
||||||
|
if (!Schema::hasColumn('users', 'user_group_id')) {
|
||||||
|
$table->bigInteger('user_group_id', false, true)->nullable();
|
||||||
|
$table->foreign('user_group_id', 'type_user_group_id')->references('id')->on('user_groups')->onDelete('set null')->onUpdate('cascade');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// ADD columns from tables
|
||||||
|
/** @var string $tableName */
|
||||||
|
foreach ($this->tables as $tableName) {
|
||||||
|
Schema::table(
|
||||||
|
$tableName, function (Blueprint $table) use ($tableName) {
|
||||||
|
|
||||||
|
if (!Schema::hasColumn($tableName, 'user_group_id')) {
|
||||||
|
$table->bigInteger('user_group_id', false, true)->nullable()->after('user_id');
|
||||||
|
$table->foreign('user_group_id', sprintf('%s_to_ugi', $tableName))->references('id')->on('user_groups')->onDelete('set null')->onUpdate('cascade');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -40,5 +40,6 @@ class DatabaseSeeder extends Seeder
|
|||||||
$this->call(PermissionSeeder::class);
|
$this->call(PermissionSeeder::class);
|
||||||
$this->call(LinkTypeSeeder::class);
|
$this->call(LinkTypeSeeder::class);
|
||||||
$this->call(ConfigSeeder::class);
|
$this->call(ConfigSeeder::class);
|
||||||
|
$this->call(UserRoleSeeder::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
63
database/seeders/UserRoleSeeder.php
Normal file
63
database/seeders/UserRoleSeeder.php
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UserRoleSeeder.php
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Database\Seeders;
|
||||||
|
|
||||||
|
use FireflyIII\Models\UserRole;
|
||||||
|
use Illuminate\Database\Seeder;
|
||||||
|
use PDOEXception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UserRoleSeeder
|
||||||
|
*/
|
||||||
|
class UserRoleSeeder extends Seeder
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the database seeds.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$roles = [
|
||||||
|
UserRole::READ_ONLY,
|
||||||
|
UserRole::CHANGE_TRANSACTIONS,
|
||||||
|
UserRole::CHANGE_RULES,
|
||||||
|
UserRole::CHANGE_PIGGY_BANKS,
|
||||||
|
UserRole::CHANGE_REPETITIONS,
|
||||||
|
UserRole::VIEW_REPORTS,
|
||||||
|
UserRole::FULL,
|
||||||
|
UserRole::OWNER,
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @var string $role */
|
||||||
|
foreach ($roles as $role) {
|
||||||
|
try {
|
||||||
|
UserRole::create(['title' => $role]);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
// @ignoreException
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,13 +17,13 @@
|
|||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
"postcss": "^8.1.14",
|
"postcss": "^8.1.14",
|
||||||
"resolve-url-loader": "^4.0.0",
|
"resolve-url-loader": "^4.0.0",
|
||||||
"sass": "^1.37.0",
|
"sass": "^1.39.2",
|
||||||
"sass-loader": "^12.0.0",
|
"sass-loader": "^12.0.0",
|
||||||
"vue-i18n": "^8.24.2",
|
"vue-i18n": "^8.24.2",
|
||||||
"vue-loader": "^15",
|
"vue-loader": "^15",
|
||||||
"vue-template-compiler": "^2.6.12",
|
"vue-template-compiler": "^2.6.12",
|
||||||
"vuex": "^3.6.2",
|
"vuex": "^3.6.2",
|
||||||
"webpack": "^5.40.0"
|
"webpack": "^5.52.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||||
|
@ -279,8 +279,8 @@ export default {
|
|||||||
// console.log('end of finaliseSubmission');
|
// console.log('end of finaliseSubmission');
|
||||||
},
|
},
|
||||||
handleSubmissionError: function (errors) {
|
handleSubmissionError: function (errors) {
|
||||||
console.log('Bad');
|
console.error('Bad');
|
||||||
console.log(errors);
|
console.error(errors);
|
||||||
this.inError = true;
|
this.inError = true;
|
||||||
this.submitting = false;
|
this.submitting = false;
|
||||||
this.errors = lodashClonedeep(this.defaultErrors);
|
this.errors = lodashClonedeep(this.defaultErrors);
|
||||||
@ -320,12 +320,12 @@ export default {
|
|||||||
this.parseAccount(response.data);
|
this.parseAccount(response.data);
|
||||||
}
|
}
|
||||||
).catch(error => {
|
).catch(error => {
|
||||||
console.log('I failed :(');
|
console.error('I failed :(');
|
||||||
console.log(error);
|
console.error(error);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
storeField: function (payload) {
|
storeField: function (payload) {
|
||||||
console.log(payload);
|
//console.log(payload);
|
||||||
if ('location' === payload.field) {
|
if ('location' === payload.field) {
|
||||||
if (true === payload.value.hasMarker) {
|
if (true === payload.value.hasMarker) {
|
||||||
this.account.location = payload.value;
|
this.account.location = payload.value;
|
||||||
|
@ -20,13 +20,145 @@
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
I am a show
|
<div class="row">
|
||||||
|
<div class="col-lg-12 col-md-6 col-sm-12 col-xs-12">
|
||||||
|
<!-- Custom Tabs -->
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header d-flex p-0">
|
||||||
|
<h3 class="card-title p-3">Tabs</h3>
|
||||||
|
<ul class="nav nav-pills ml-auto p-2">
|
||||||
|
<li class="nav-item"><a class="nav-link active" href="#main_chart" data-toggle="tab">Chart</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="#budgets" data-toggle="tab">Budgets</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="#categories" data-toggle="tab">Categories</a></li>
|
||||||
|
</ul>
|
||||||
|
</div><!-- /.card-header -->
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="tab-content">
|
||||||
|
<div class="tab-pane active" id="main_chart">
|
||||||
|
1: main chart
|
||||||
|
</div>
|
||||||
|
<!-- /.tab-pane -->
|
||||||
|
<div class="tab-pane" id="budgets">
|
||||||
|
2: tree map from/to budget
|
||||||
|
</div>
|
||||||
|
<!-- /.tab-pane -->
|
||||||
|
<div class="tab-pane" id="categories">
|
||||||
|
2: tree map from/to cat
|
||||||
|
</div>
|
||||||
|
<!-- /.tab-pane -->
|
||||||
|
</div>
|
||||||
|
<!-- /.tab-content -->
|
||||||
|
</div><!-- /.card-body -->
|
||||||
|
</div>
|
||||||
|
<!-- ./card -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<TransactionListLarge
|
||||||
|
:entries="rawTransactions"
|
||||||
|
:page="currentPage"
|
||||||
|
:total="total"
|
||||||
|
:per-page="perPage"
|
||||||
|
:sort-desc="sortDesc"
|
||||||
|
v-on:jump-page="jumpToPage($event)"
|
||||||
|
/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12 col-md-6 col-sm-12 col-xs-12">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">
|
||||||
|
Blocks
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
Blocks
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import TransactionListLarge from "../transactions/TransactionListLarge";
|
||||||
|
import format from "date-fns/format";
|
||||||
|
import {mapGetters} from "vuex";
|
||||||
|
import {configureAxios} from "../../shared/forageStore";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Show"
|
name: "Show",
|
||||||
|
computed: {
|
||||||
|
...mapGetters('root', ['listPageSize', 'cacheKey']),
|
||||||
|
...mapGetters('dashboard/index', ['start', 'end',]),
|
||||||
|
'showReady': function () {
|
||||||
|
return null !== this.start && null !== this.end && null !== this.listPageSize && this.ready;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
accountId: 0,
|
||||||
|
rawTransactions: [],
|
||||||
|
ready: false,
|
||||||
|
loading: false,
|
||||||
|
total: 0,
|
||||||
|
sortDesc: false,
|
||||||
|
currentPage: 1,
|
||||||
|
perPage: 51,
|
||||||
|
locale: 'en-US',
|
||||||
|
api: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.ready = true;
|
||||||
|
let parts = window.location.pathname.split('/');
|
||||||
|
this.accountId = parseInt(parts[parts.length - 1]);
|
||||||
|
this.perPage = this.listPageSize ?? 51;
|
||||||
|
|
||||||
|
let params = new URLSearchParams(window.location.search);
|
||||||
|
this.currentPage = params.get('page') ? parseInt(params.get('page')) : 1;
|
||||||
|
this.getTransactions();
|
||||||
|
},
|
||||||
|
components: {TransactionListLarge},
|
||||||
|
methods: {
|
||||||
|
getTransactions: function () {
|
||||||
|
if (this.showReady && !this.loading) {
|
||||||
|
this.loading = true;
|
||||||
|
configureAxios().then(async (api) => {
|
||||||
|
// console.log('Now getTransactions() x Start');
|
||||||
|
let startStr = format(this.start, 'y-MM-dd');
|
||||||
|
let endStr = format(this.end, 'y-MM-dd');
|
||||||
|
this.rawTransactions = [];
|
||||||
|
|
||||||
|
let url = './api/v1/accounts/' + this.accountId + '/transactions?page=1&limit=' + this.perPage + '&start=' + startStr + '&end=' + endStr;
|
||||||
|
|
||||||
|
|
||||||
|
api.get(url)
|
||||||
|
.then(response => {
|
||||||
|
// console.log('Now getTransactions() DONE!');
|
||||||
|
this.total = parseInt(response.data.meta.pagination.total);
|
||||||
|
this.rawTransactions = response.data.data;
|
||||||
|
this.loading = false;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
jumpToPage: function (event) {
|
||||||
|
// console.log('noticed a change!');
|
||||||
|
this.currentPage = event.page;
|
||||||
|
this.downloadTransactionList(event.page);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
start: function () {
|
||||||
|
this.getTransactions();
|
||||||
|
},
|
||||||
|
end: function () {
|
||||||
|
this.getTransactions();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
108
frontend/src/components/dashboard/DashboardListLarge.vue
Normal file
108
frontend/src/components/dashboard/DashboardListLarge.vue
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<!--
|
||||||
|
- DashboardListLarge.vue
|
||||||
|
- Copyright (c) 2020 james@firefly-iii.org
|
||||||
|
-
|
||||||
|
- This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
-
|
||||||
|
- 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.
|
||||||
|
-
|
||||||
|
- This program is distributed in the hope that it will be useful,
|
||||||
|
- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
- GNU Affero General Public License for more details.
|
||||||
|
-
|
||||||
|
- 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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<table class="table table-striped table-sm">
|
||||||
|
<caption style="display:none;">{{ $t('firefly.transaction_table_description') }}</caption>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="text-left" scope="col">{{ $t('firefly.description') }}</th>
|
||||||
|
<th scope="col">{{ $t('firefly.opposing_account') }}</th>
|
||||||
|
<th class="text-right" scope="col">{{ $t('firefly.amount') }}</th>
|
||||||
|
<th scope="col">{{ $t('firefly.category') }}</th>
|
||||||
|
<th scope="col">{{ $t('firefly.budget') }}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr v-for="transaction in this.transactions">
|
||||||
|
<td>
|
||||||
|
<a :href="'transactions/show/' + transaction.id " :title="transaction.date">
|
||||||
|
<span v-if="transaction.attributes.transactions.length > 1">{{ transaction.attributes.group_title }}</span>
|
||||||
|
<span v-if="1===transaction.attributes.transactions.length">{{ transaction.attributes.transactions[0].description }}</span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-for="tr in transaction.attributes.transactions">
|
||||||
|
<a v-if="'withdrawal' === tr.type" :href="'accounts/show/' + tr.destination_id">{{ tr.destination_name }}</a>
|
||||||
|
<a v-if="'deposit' === tr.type" :href="'accounts/show/' + tr.source_id">{{ tr.source_name }}</a>
|
||||||
|
<a v-if="'transfer' === tr.type && parseInt(tr.source_id) === account_id" :href="'accounts/show/' + tr.destination_id">{{ tr.destination_name }}</a>
|
||||||
|
<a v-if="'transfer' === tr.type && parseInt(tr.destination_id) === account_id" :href="'accounts/show/' + tr.source_id">{{ tr.source_name }}</a>
|
||||||
|
<br/>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td style="text-align:right;">
|
||||||
|
<span v-for="tr in transaction.attributes.transactions">
|
||||||
|
<span v-if="'withdrawal' === tr.type" class="text-danger">
|
||||||
|
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount * -1) }}<br>
|
||||||
|
</span>
|
||||||
|
<span v-if="'deposit' === tr.type" class="text-success">
|
||||||
|
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount) }}<br>
|
||||||
|
</span>
|
||||||
|
<span v-if="'transfer' === tr.type && parseInt(tr.source_id) === account_id" class="text-info">
|
||||||
|
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount * -1) }}<br>
|
||||||
|
</span>
|
||||||
|
<span v-if="'transfer' === tr.type && parseInt(tr.destination_id) === account_id" class="text-info">
|
||||||
|
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount) }}<br>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-for="tr in transaction.attributes.transactions">
|
||||||
|
<a v-if="0!==tr.category_id" :href="'categories/show/' + tr.category_id">{{ tr.category_name }}</a><br/>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span v-for="tr in transaction.attributes.transactions">
|
||||||
|
<a v-if="0!==tr.budget_id" :href="'budgets/show/' + tr.budget_id">{{ tr.budget_name }}</a><br/>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "DashboardListLarge",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
locale: 'en-US'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.locale = localStorage.locale ?? 'en-US';
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
transactions: {
|
||||||
|
type: Array,
|
||||||
|
default: function () {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
account_id: {
|
||||||
|
type: Number,
|
||||||
|
default: function () {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
- TransactionListMedium.vue
|
- DashboardListMedium.vue
|
||||||
- Copyright (c) 2020 james@firefly-iii.org
|
- Copyright (c) 2020 james@firefly-iii.org
|
||||||
-
|
-
|
||||||
- This file is part of Firefly III (https://github.com/firefly-iii).
|
- This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
@ -68,7 +68,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "TransactionListMedium",
|
name: "DashboardListMedium",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
locale: 'en-US'
|
locale: 'en-US'
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
- TransactionListSmall.vue
|
- DashboardListSmall.vue
|
||||||
- Copyright (c) 2020 james@firefly-iii.org
|
- Copyright (c) 2020 james@firefly-iii.org
|
||||||
-
|
-
|
||||||
- This file is part of Firefly III (https://github.com/firefly-iii).
|
- This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
@ -59,7 +59,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "TransactionListSmall",
|
name: "DashboardListSmall",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
locale: 'en-US'
|
locale: 'en-US'
|
@ -107,8 +107,8 @@ export default {
|
|||||||
this.drawChart();
|
this.drawChart();
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log('Has error!');
|
console.error('Has error!');
|
||||||
console.log(error);
|
console.error(error);
|
||||||
this.error = true;
|
this.error = true;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -62,9 +62,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body table-responsive p-0">
|
<div class="card-body table-responsive p-0">
|
||||||
<div>
|
<div>
|
||||||
<transaction-list-large v-if="1===accounts.length" :account_id="account.id" :transactions="account.transactions"/>
|
<dashboard-list-large v-if="1===accounts.length" :account_id="account.id" :transactions="account.transactions"/>
|
||||||
<transaction-list-medium v-if="2===accounts.length" :account_id="account.id" :transactions="account.transactions"/>
|
<dashboard-list-medium v-if="2===accounts.length" :account_id="account.id" :transactions="account.transactions"/>
|
||||||
<transaction-list-small v-if="accounts.length > 2" :account_id="account.id" :transactions="account.transactions"/>
|
<dashboard-list-small v-if="accounts.length > 2" :account_id="account.id" :transactions="account.transactions"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -830,6 +830,10 @@ export default {
|
|||||||
//console.log('getExpectedSourceTypes.');
|
//console.log('getExpectedSourceTypes.');
|
||||||
this.sourceAllowedTypes = response.data.data.value.source[this.transactionType];
|
this.sourceAllowedTypes = response.data.data.value.source[this.transactionType];
|
||||||
this.destinationAllowedTypes = response.data.data.value.destination[this.transactionType];
|
this.destinationAllowedTypes = response.data.data.value.destination[this.transactionType];
|
||||||
|
|
||||||
|
// console.log('sourceAllowedTypes');
|
||||||
|
// console.log(this.sourceAllowedTypes);
|
||||||
|
|
||||||
// console.log('Source allowed types for ' + this.transactionType + ' is: ');
|
// console.log('Source allowed types for ' + this.transactionType + ' is: ');
|
||||||
// console.log(this.sourceAllowedTypes);
|
// console.log(this.sourceAllowedTypes);
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
<SplitPills
|
<SplitPills
|
||||||
:transactions="transactions"
|
:transactions="transactions"
|
||||||
:count="transactions.length"
|
:count="transactions.length"
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="tab-content">
|
<div class="tab-content">
|
||||||
@ -132,6 +131,7 @@ export default {
|
|||||||
this.groupId = parseInt(parts[parts.length - 1]);
|
this.groupId = parseInt(parts[parts.length - 1]);
|
||||||
this.transactions = [];
|
this.transactions = [];
|
||||||
this.getTransactionGroup();
|
this.getTransactionGroup();
|
||||||
|
//this.getExpectedSourceTypes();
|
||||||
this.getAllowedOpposingTypes();
|
this.getAllowedOpposingTypes();
|
||||||
this.getCustomFields();
|
this.getCustomFields();
|
||||||
},
|
},
|
||||||
@ -238,6 +238,9 @@ export default {
|
|||||||
watch: {
|
watch: {
|
||||||
submittedAttachments: function () {
|
submittedAttachments: function () {
|
||||||
this.finaliseSubmission();
|
this.finaliseSubmission();
|
||||||
|
},
|
||||||
|
transactionType: function() {
|
||||||
|
this.getExpectedSourceTypes();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -299,8 +302,12 @@ export default {
|
|||||||
this.transactionType = array.type.charAt(0).toUpperCase() + array.type.slice(1);
|
this.transactionType = array.type.charAt(0).toUpperCase() + array.type.slice(1);
|
||||||
|
|
||||||
// See reference nr. 5
|
// See reference nr. 5
|
||||||
|
|
||||||
this.sourceAllowedTypes = [array.source_type];
|
this.sourceAllowedTypes = [array.source_type];
|
||||||
this.destinationAllowedTypes = [array.destination_type];
|
this.destinationAllowedTypes = [array.destination_type];
|
||||||
|
// console.log('sourceAllowedTypes (parseTransaction)');
|
||||||
|
// console.log(this.sourceAllowedTypes);
|
||||||
|
|
||||||
this.date = array.date.substring(0, 16);
|
this.date = array.date.substring(0, 16);
|
||||||
this.originalDate = array.date.substring(0, 16);
|
this.originalDate = array.date.substring(0, 16);
|
||||||
}
|
}
|
||||||
@ -427,6 +434,18 @@ export default {
|
|||||||
this.originalTransactions[index].links.push(object);
|
this.originalTransactions[index].links.push(object);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
getExpectedSourceTypes: function () {
|
||||||
|
axios.get('./api/v1/configuration/firefly.expected_source_types')
|
||||||
|
.then(response => {
|
||||||
|
this.sourceAllowedTypes = response.data.data.value.source[this.transactionType];
|
||||||
|
this.destinationAllowedTypes = response.data.data.value.destination[this.transactionType];
|
||||||
|
// console.log('sourceAllowedTypes (getExpectedSourceTypes)');
|
||||||
|
// console.log(JSON.stringify(response.data.data.value.source[this.transactionType]));
|
||||||
|
// console.log(JSON.stringify(response.data.data.value.source));
|
||||||
|
// console.log(this.transactionType);
|
||||||
|
//console.log(this.transactionType);
|
||||||
|
});
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* Get API value.
|
* Get API value.
|
||||||
*/
|
*/
|
||||||
|
@ -36,123 +36,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<!-- page is ignored for the time being -->
|
||||||
<div class="col-lg-8 col-md-6 col-sm-12 col-xs-12">
|
<TransactionListLarge
|
||||||
<b-pagination
|
:entries="rawTransactions"
|
||||||
v-model="currentPage"
|
:page="currentPage"
|
||||||
:total-rows="total"
|
:total="total"
|
||||||
:per-page="perPage"
|
:per-page="perPage"
|
||||||
aria-controls="my-table"
|
:sort-desc="sortDesc"
|
||||||
></b-pagination>
|
v-on:jump-page="jumpToPage($event)"
|
||||||
</div>
|
/>
|
||||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
|
||||||
<button @click="newCacheKey" class="btn btn-sm float-right btn-info"><span class="fas fa-sync"></span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col">
|
|
||||||
<div class="card">
|
|
||||||
<div class="card-body p-0">
|
|
||||||
<b-table id="my-table" small striped hover responsive="md" primary-key="key" :no-local-sorting="false"
|
|
||||||
:items="transactionRows"
|
|
||||||
:fields="fields"
|
|
||||||
:per-page="perPage"
|
|
||||||
sort-icon-left
|
|
||||||
ref="table"
|
|
||||||
:current-page="currentPage"
|
|
||||||
:busy.sync="loading"
|
|
||||||
:sort-desc.sync="sortDesc"
|
|
||||||
:sort-compare="tableSortCompare"
|
|
||||||
>
|
|
||||||
<template #table-busy>
|
|
||||||
<span class="fa fa-spinner"></span>
|
|
||||||
</template>
|
|
||||||
<template #cell(type)="data">
|
|
||||||
<span v-if="! data.item.split || data.item.split_parent === null">
|
|
||||||
<span class="fas fa-long-arrow-alt-right" v-if="'deposit' === data.item.type"></span>
|
|
||||||
<span class="fas fa-long-arrow-alt-left" v-else-if="'withdrawal' === data.item.type"></span>
|
|
||||||
<span class="fas fa-long-arrows-alt-h" v-else-if="'transfer' === data.item.type"></span>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #cell(description)="data">
|
|
||||||
<span class="fas fa-angle-right" v-if="data.item.split && data.item.split_parent !== null"></span>
|
|
||||||
<a :class="false === data.item.active ? 'text-muted' : ''" :href="'./transactions/show/' + data.item.id" :title="data.value">{{
|
|
||||||
data.value
|
|
||||||
}}</a>
|
|
||||||
</template>
|
|
||||||
<template #cell(amount)="data">
|
|
||||||
<span class="text-success" v-if="'deposit' === data.item.type">
|
|
||||||
{{ Intl.NumberFormat(locale, {style: 'currency', currency: data.item.currency_code}).format(data.item.amount) }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="text-danger" v-else-if="'withdrawal' === data.item.type">
|
|
||||||
{{ Intl.NumberFormat(locale, {style: 'currency', currency: data.item.currency_code}).format(-data.item.amount) }}
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span class="text-muted" v-else-if="'transfer' === data.item.type">
|
|
||||||
{{ Intl.NumberFormat(locale, {style: 'currency', currency: data.item.currency_code}).format(data.item.amount) }}
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template #cell(date)="data">
|
|
||||||
{{ data.item.date_formatted }}
|
|
||||||
</template>
|
|
||||||
<template #cell(source_account)="data">
|
|
||||||
<a :class="false === data.item.active ? 'text-muted' : ''" :href="'./accounts/show/' + data.item.source_id"
|
|
||||||
:title="data.item.source_name">{{ data.item.source_name }}</a>
|
|
||||||
</template>
|
|
||||||
<template #cell(destination_account)="data">
|
|
||||||
<a :class="false === data.item.active ? 'text-muted' : ''" :href="'./accounts/show/' + data.item.destination_id"
|
|
||||||
:title="data.item.destination_name">{{ data.item.destination_name }}</a>
|
|
||||||
</template>
|
|
||||||
<template #cell(menu)="data">
|
|
||||||
<div class="btn-group btn-group-sm" v-if="! data.item.split || data.item.split_parent === null">
|
|
||||||
<div class="dropdown">
|
|
||||||
<button class="btn btn-light btn-sm dropdown-toggle" type="button" :id="'dropdownMenuButton' + data.item.id" data-toggle="dropdown"
|
|
||||||
aria-haspopup="true" aria-expanded="false">
|
|
||||||
{{ $t('firefly.actions') }}
|
|
||||||
</button>
|
|
||||||
<div class="dropdown-menu" :aria-labelledby="'dropdownMenuButton' + data.item.id">
|
|
||||||
<a class="dropdown-item" :href="'./transactions/edit/' + data.item.id"><span class="fa fas fa-pencil-alt"></span> {{ $t('firefly.edit') }}</a>
|
|
||||||
<a class="dropdown-item" :href="'./transactions/delete/' + data.item.id"><span class="fa far fa-trash"></span> {{ $t('firefly.delete') }}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="btn btn-light btn-sm" v-if="data.item.split && data.item.split_parent === null && data.item.collapsed === true"
|
|
||||||
v-on:click="toggleCollapse(data.item)">
|
|
||||||
<span class="fa fa-caret-down"></span>
|
|
||||||
{{ $t('firefly.transaction_expand_split') }}
|
|
||||||
</div>
|
|
||||||
<div class="btn btn-light btn-sm" v-else-if="data.item.split && data.item.split_parent === null && data.item.collapsed === false"
|
|
||||||
v-on:click="toggleCollapse(data.item)">
|
|
||||||
<span class="fa fa-caret-up"></span>
|
|
||||||
{{ $t('firefly.transaction_collapse_split') }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #cell(category)="data">
|
|
||||||
{{ data.item.category_name }}
|
|
||||||
</template>
|
|
||||||
</b-table>
|
|
||||||
</div>
|
|
||||||
<div class="card-footer">
|
|
||||||
<a :href="'./transactions/create/' + type" class="btn btn-success"
|
|
||||||
:title="$t('firefly.create_new_transaction')">{{ $t('firefly.create_new_transaction') }}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-8 col-md-6 col-sm-12 col-xs-12">
|
|
||||||
<b-pagination
|
|
||||||
v-model="currentPage"
|
|
||||||
:total-rows="total"
|
|
||||||
:per-page="perPage"
|
|
||||||
aria-controls="my-table"
|
|
||||||
></b-pagination>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
|
||||||
<button @click="newCacheKey" class="btn btn-sm float-right btn-info"><span class="fas fa-sync"></span></button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-2 col-lg-4 col-sm-6 col-xs-12" v-for="range in ranges">
|
<div class="col-xl-2 col-lg-4 col-sm-6 col-xs-12" v-for="range in ranges">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
@ -176,18 +68,18 @@ import sub from "date-fns/sub";
|
|||||||
import startOfMonth from "date-fns/startOfMonth";
|
import startOfMonth from "date-fns/startOfMonth";
|
||||||
import endOfMonth from "date-fns/endOfMonth";
|
import endOfMonth from "date-fns/endOfMonth";
|
||||||
import {configureAxios} from "../../shared/forageStore";
|
import {configureAxios} from "../../shared/forageStore";
|
||||||
|
import TransactionListLarge from "./TransactionListLarge";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Index",
|
name: "Index",
|
||||||
|
components: {TransactionListLarge},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
transactions: [],
|
rawTransactions: [],
|
||||||
transactionRows: [],
|
|
||||||
type: 'all',
|
type: 'all',
|
||||||
downloaded: false,
|
downloaded: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
ready: false,
|
ready: false,
|
||||||
fields: [],
|
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
perPage: 5,
|
perPage: 5,
|
||||||
total: 1,
|
total: 1,
|
||||||
@ -236,6 +128,7 @@ export default {
|
|||||||
let parts = pathName.split('/');
|
let parts = pathName.split('/');
|
||||||
this.type = parts[parts.length - 1];
|
this.type = parts[parts.length - 1];
|
||||||
this.perPage = this.listPageSize ?? 51;
|
this.perPage = this.listPageSize ?? 51;
|
||||||
|
|
||||||
if (5 === parts.length) {
|
if (5 === parts.length) {
|
||||||
this.urlStart = new Date(parts[3]);
|
this.urlStart = new Date(parts[3]);
|
||||||
this.urlEnd = new Date(parts[4]);
|
this.urlEnd = new Date(parts[4]);
|
||||||
@ -244,57 +137,27 @@ export default {
|
|||||||
|
|
||||||
let params = new URLSearchParams(window.location.search);
|
let params = new URLSearchParams(window.location.search);
|
||||||
this.currentPage = params.get('page') ? parseInt(params.get('page')) : 1;
|
this.currentPage = params.get('page') ? parseInt(params.get('page')) : 1;
|
||||||
this.updateFieldList();
|
|
||||||
this.ready = true;
|
this.ready = true;
|
||||||
|
|
||||||
// make object thing:
|
|
||||||
// let token = document.head.querySelector('meta[name="csrf-token"]');
|
|
||||||
// this.api = setup(
|
|
||||||
// {
|
|
||||||
// // `axios` options
|
|
||||||
// //baseURL: './',
|
|
||||||
// headers: {'X-CSRF-TOKEN': token.content, 'X-James': 'yes'},
|
|
||||||
//
|
|
||||||
// // `axios-cache-adapter` options
|
|
||||||
// cache: {
|
|
||||||
// maxAge: 15 * 60 * 1000,
|
|
||||||
// readHeaders: false,
|
|
||||||
// exclude: {
|
|
||||||
// query: false,
|
|
||||||
// },
|
|
||||||
// debug: true
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
...mapMutations('root', ['refreshCacheKey',]),
|
...mapMutations('root', ['refreshCacheKey',]),
|
||||||
updateFieldList: function () {
|
|
||||||
this.fields = [
|
|
||||||
{key: 'type', label: ' ', sortable: false},
|
|
||||||
{key: 'description', label: this.$t('list.description'), sortable: true},
|
|
||||||
{key: 'amount', label: this.$t('list.amount'), sortable: true},
|
|
||||||
{key: 'date', label: this.$t('list.date'), sortable: true},
|
|
||||||
{key: 'source_account', label: this.$t('list.source_account'), sortable: true},
|
|
||||||
{key: 'destination_account', label: this.$t('list.destination_account'), sortable: true},
|
|
||||||
{key: 'category_name', label: this.$t('list.category'), sortable: true},
|
|
||||||
{key: 'menu', label: ' ', sortable: false},
|
|
||||||
];
|
|
||||||
},
|
|
||||||
newCacheKey: function () {
|
newCacheKey: function () {
|
||||||
this.refreshCacheKey();
|
this.refreshCacheKey();
|
||||||
this.downloaded = false;
|
this.downloaded = false;
|
||||||
this.accounts = [];
|
this.accounts = [];
|
||||||
this.getTransactionList();
|
this.getTransactionList();
|
||||||
},
|
},
|
||||||
|
jumpToPage: function(event) {
|
||||||
|
// console.log('noticed a change!');
|
||||||
|
this.currentPage = event.page;
|
||||||
|
this.downloadTransactionList(event.page);
|
||||||
|
},
|
||||||
getTransactionList: function () {
|
getTransactionList: function () {
|
||||||
// console.log('getTransactionList()');
|
|
||||||
if (this.indexReady && !this.loading && !this.downloaded) {
|
if (this.indexReady && !this.loading && !this.downloaded) {
|
||||||
// console.log('Index ready, not loading and not already downloaded. Reset.');
|
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
this.perPage = this.listPageSize ?? 51;
|
this.perPage = this.listPageSize ?? 51;
|
||||||
this.transactions = [];
|
this.rawTransactions = [];
|
||||||
this.transactionRows = [];
|
this.downloadTransactionList(this.currentPage);
|
||||||
this.downloadTransactionList(1);
|
|
||||||
this.calculateDateRanges();
|
this.calculateDateRanges();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -303,165 +166,39 @@ export default {
|
|||||||
let currentDate = this.start;
|
let currentDate = this.start;
|
||||||
|
|
||||||
while (currentDate > yearAgo) {
|
while (currentDate > yearAgo) {
|
||||||
// start + end of month:
|
|
||||||
let st = startOfMonth(currentDate);
|
let st = startOfMonth(currentDate);
|
||||||
let en = endOfMonth(currentDate);
|
let en = endOfMonth(currentDate);
|
||||||
|
|
||||||
this.ranges.push({start: st, end: en});
|
this.ranges.push({start: st, end: en});
|
||||||
|
|
||||||
currentDate = sub(currentDate, {months: 1});
|
currentDate = sub(currentDate, {months: 1});
|
||||||
//console.log(currentDate);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
formatDate: function (date, frm) {
|
formatDate: function (date, frm) {
|
||||||
return format(date, frm);
|
return format(date, frm);
|
||||||
},
|
},
|
||||||
downloadTransactionList: function (page) {
|
downloadTransactionList: function (page) {
|
||||||
// console.log('downloadTransactionList(' + page + ')');
|
|
||||||
configureAxios().then(async (api) => {
|
configureAxios().then(async (api) => {
|
||||||
let startStr = format(this.start, 'y-MM-dd');
|
let startStr = format(this.start, 'y-MM-dd');
|
||||||
let endStr = format(this.end, 'y-MM-dd');
|
let endStr = format(this.end, 'y-MM-dd');
|
||||||
// console.log(this.urlEnd);
|
|
||||||
// console.log(this.urlStart);
|
if (null !== this.urlEnd && null !== this.urlStart) {
|
||||||
if(null !== this.urlEnd && null !== this.urlStart) {
|
|
||||||
startStr = format(this.urlStart, 'y-MM-dd');
|
startStr = format(this.urlStart, 'y-MM-dd');
|
||||||
endStr = format(this.urlEnd, 'y-MM-dd');
|
endStr = format(this.urlEnd, 'y-MM-dd');
|
||||||
}
|
}
|
||||||
|
|
||||||
api.get('./api/v1/transactions?type=' + this.type + '&page=' + page + "&start=" + startStr + "&end=" + endStr + '&cache=' + this.cacheKey)
|
let url = './api/v1/transactions?type=' + this.type + '&page=' + page + "&start=" + startStr + "&end=" + endStr + '&cache=' + this.cacheKey;
|
||||||
|
api.get(url)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
|
|
||||||
//let currentPage = parseInt(response.data.meta.pagination.current_page);
|
|
||||||
//let totalPages = parseInt(response.data.meta.pagination.total_pages);
|
|
||||||
this.total = parseInt(response.data.meta.pagination.total);
|
this.total = parseInt(response.data.meta.pagination.total);
|
||||||
//console.log('total is ' + this.total);
|
this.rawTransactions = response.data.data;
|
||||||
this.transactions.push(...response.data.data);
|
this.loading = false;
|
||||||
// if (currentPage < totalPage) {
|
|
||||||
// let nextPage = currentPage + 1;
|
|
||||||
// this.downloadTransactionList(nextPage);
|
|
||||||
// }
|
|
||||||
// if (currentPage >= totalPage) {
|
|
||||||
// console.log('Looks like all downloaded.');
|
|
||||||
this.downloaded = true;
|
|
||||||
this.createTransactionRows();
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
createTransactionRows: function () {
|
|
||||||
this.transactionRows = [];
|
|
||||||
for (let i in this.transactions) {
|
|
||||||
let transaction = this.transactions[i];
|
|
||||||
let transactionRow = this.getTransactionRow(transaction, 0);
|
|
||||||
this.transactionRows.push(transactionRow);
|
|
||||||
|
|
||||||
if (transaction.attributes.transactions.length > 1) {
|
|
||||||
transactionRow.description = transaction.attributes.group_title;
|
|
||||||
transactionRow.split = true;
|
|
||||||
transactionRow.collapsed = transaction.collapsed === true || transaction.collapsed === undefined;
|
|
||||||
transactionRow.amount = transaction.attributes.transactions
|
|
||||||
.map(transaction => Number(transaction.amount))
|
|
||||||
.reduce((sum, n) => sum + n);
|
|
||||||
transactionRow.source_name = '';
|
|
||||||
transactionRow.source_id = '';
|
|
||||||
transactionRow.destination_name = '';
|
|
||||||
transactionRow.destination_id = '';
|
|
||||||
|
|
||||||
if (!transactionRow.collapsed) {
|
|
||||||
for (let i = 0; i < transaction.attributes.transactions.length; i++) {
|
|
||||||
let splitTransactionRow = this.getTransactionRow(transaction, i);
|
|
||||||
splitTransactionRow.key = splitTransactionRow.id + "." + i
|
|
||||||
splitTransactionRow.split = true;
|
|
||||||
splitTransactionRow.split_index = i + 1;
|
|
||||||
splitTransactionRow.split_parent = transactionRow;
|
|
||||||
this.transactionRows.push(splitTransactionRow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.loading = false;
|
|
||||||
},
|
|
||||||
getTransactionRow(transaction, index) {
|
|
||||||
let transactionRow = {};
|
|
||||||
let currentTransaction = transaction.attributes.transactions[index];
|
|
||||||
|
|
||||||
transactionRow.key = transaction.id;
|
|
||||||
transactionRow.id = transaction.id;
|
|
||||||
transactionRow.type = currentTransaction.type;
|
|
||||||
transactionRow.description = currentTransaction.description;
|
|
||||||
transactionRow.amount = currentTransaction.amount;
|
|
||||||
transactionRow.currency_code = currentTransaction.currency_code;
|
|
||||||
transactionRow.date = new Date(currentTransaction.date);
|
|
||||||
transactionRow.date_formatted = format(transactionRow.date, this.$t('config.month_and_day_fns'));
|
|
||||||
transactionRow.source_name = currentTransaction.source_name;
|
|
||||||
transactionRow.source_id = currentTransaction.source_id;
|
|
||||||
transactionRow.destination_name = currentTransaction.destination_name;
|
|
||||||
transactionRow.destination_id = currentTransaction.destination_id;
|
|
||||||
transactionRow.category_id = currentTransaction.category_id;
|
|
||||||
transactionRow.category_name = currentTransaction.category_name;
|
|
||||||
transactionRow.split = false;
|
|
||||||
transactionRow.split_index = 0;
|
|
||||||
transactionRow.split_parent = null;
|
|
||||||
|
|
||||||
return transactionRow;
|
|
||||||
},
|
|
||||||
toggleCollapse: function (row) {
|
|
||||||
let transaction = this.transactions.filter(transaction => transaction.id === row.id)[0];
|
|
||||||
if (transaction.collapsed === undefined) {
|
|
||||||
transaction.collapsed = false;
|
|
||||||
} else {
|
|
||||||
transaction.collapsed = !transaction.collapsed;
|
|
||||||
}
|
|
||||||
this.createTransactionRows();
|
|
||||||
},
|
|
||||||
tableSortCompare: function (aRow, bRow, key, sortDesc, formatter, compareOptions, compareLocale) {
|
|
||||||
let a = aRow[key]
|
|
||||||
let b = bRow[key]
|
|
||||||
|
|
||||||
if (aRow.id === bRow.id) {
|
|
||||||
// Order split transactions normally when compared to each other, except always put the header first
|
|
||||||
if (aRow.split_parent === null) {
|
|
||||||
return sortDesc ? 1 : -1;
|
|
||||||
} else if (bRow.split_parent === null) {
|
|
||||||
return sortDesc ? -1 : 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Sort split transactions based on their parent when compared to other transactions
|
|
||||||
if (aRow.split && aRow.split_parent !== null) {
|
|
||||||
a = aRow.split_parent[key]
|
|
||||||
}
|
|
||||||
if (bRow.split && bRow.split_parent !== null) {
|
|
||||||
b = bRow.split_parent[key]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
(typeof a === 'number' && typeof b === 'number') ||
|
|
||||||
(a instanceof Date && b instanceof Date)
|
|
||||||
) {
|
|
||||||
// If both compared fields are native numbers or both are native dates
|
|
||||||
return a < b ? -1 : a > b ? 1 : 0
|
|
||||||
} else {
|
|
||||||
// Otherwise stringify the field data and use String.prototype.localeCompare
|
|
||||||
return toString(a).localeCompare(toString(b), compareLocale, compareOptions)
|
|
||||||
}
|
|
||||||
|
|
||||||
function toString(value) {
|
|
||||||
if (value === null || typeof value === 'undefined') {
|
|
||||||
return ''
|
|
||||||
} else if (value instanceof Object) {
|
|
||||||
return Object.keys(value)
|
|
||||||
.sort()
|
|
||||||
.map(key => toString(value[key]))
|
|
||||||
.join(' ')
|
|
||||||
} else {
|
|
||||||
return String(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -19,84 +19,390 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<table class="table table-striped table-sm">
|
<div>
|
||||||
<caption style="display:none;">{{ $t('firefly.transaction_table_description') }}</caption>
|
<div class="row">
|
||||||
<thead>
|
<div class="col-lg-8 col-md-6 col-sm-12 col-xs-12">
|
||||||
<tr>
|
<BPagination v-if="!loading"
|
||||||
<th class="text-left" scope="col">{{ $t('firefly.description') }}</th>
|
v-model="currentPage"
|
||||||
<th scope="col">{{ $t('firefly.opposing_account') }}</th>
|
:total-rows="total"
|
||||||
<th class="text-right" scope="col">{{ $t('firefly.amount') }}</th>
|
:per-page="perPage"
|
||||||
<th scope="col">{{ $t('firefly.category') }}</th>
|
aria-controls="my-table"
|
||||||
<th scope="col">{{ $t('firefly.budget') }}</th>
|
></BPagination>
|
||||||
</tr>
|
</div>
|
||||||
</thead>
|
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
||||||
<tbody>
|
<button @click="newCacheKey" class="btn btn-sm float-right btn-info"><span class="fas fa-sync"></span></button>
|
||||||
<tr v-for="transaction in this.transactions">
|
</div>
|
||||||
<td>
|
</div>
|
||||||
<a :href="'transactions/show/' + transaction.id " :title="transaction.date">
|
<div class="row">
|
||||||
<span v-if="transaction.attributes.transactions.length > 1">{{ transaction.attributes.group_title }}</span>
|
<div class="col">
|
||||||
<span v-if="1===transaction.attributes.transactions.length">{{ transaction.attributes.transactions[0].description }}</span>
|
<div class="card">
|
||||||
</a>
|
<div class="card-body p-0">
|
||||||
</td>
|
<BTable id="my-table" small striped hover responsive="md" primary-key="key" :no-local-sorting="false"
|
||||||
<td>
|
:items="transactions"
|
||||||
<span v-for="tr in transaction.attributes.transactions">
|
:fields="fields"
|
||||||
<a v-if="'withdrawal' === tr.type" :href="'accounts/show/' + tr.destination_id">{{ tr.destination_name }}</a>
|
:per-page="perPage"
|
||||||
<a v-if="'deposit' === tr.type" :href="'accounts/show/' + tr.source_id">{{ tr.source_name }}</a>
|
sort-icon-left
|
||||||
<a v-if="'transfer' === tr.type && parseInt(tr.source_id) === account_id" :href="'accounts/show/' + tr.destination_id">{{ tr.destination_name }}</a>
|
ref="table"
|
||||||
<a v-if="'transfer' === tr.type && parseInt(tr.destination_id) === account_id" :href="'accounts/show/' + tr.source_id">{{ tr.source_name }}</a>
|
:current-page="currentPage"
|
||||||
<br/>
|
:busy.sync="loading"
|
||||||
|
:sort-desc.sync="sortDesc"
|
||||||
|
:sort-compare="tableSortCompare"
|
||||||
|
>
|
||||||
|
<template #table-busy>
|
||||||
|
<span class="fa fa-spinner fa-spin"></span>
|
||||||
|
</template>
|
||||||
|
<template #cell(type)="data">
|
||||||
|
<span v-if="!data.item.dummy">
|
||||||
|
<span class="fas fa-long-arrow-alt-right" v-if="'deposit' === data.item.type"></span>
|
||||||
|
<span class="fas fa-long-arrow-alt-left" v-else-if="'withdrawal' === data.item.type"></span>
|
||||||
|
<span class="fas fa-long-arrows-alt-h" v-else-if="'transfer' === data.item.type"></span>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</template>
|
||||||
<td style="text-align:right;">
|
<template #cell(description)="data">
|
||||||
<span v-for="tr in transaction.attributes.transactions">
|
<span class="fa fa-spinner fa-spin" v-if="data.item.dummy"></span>
|
||||||
<span v-if="'withdrawal' === tr.type" class="text-danger">
|
<span v-if="!data.item.split">
|
||||||
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount * -1) }}<br>
|
<a :href="'./transactions/show/' + data.item.id" :title="data.value">
|
||||||
</span>
|
{{ data.item.description }}
|
||||||
<span v-if="'deposit' === tr.type" class="text-success">
|
</a>
|
||||||
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount) }}<br>
|
</span>
|
||||||
</span>
|
<span v-if="data.item.split">
|
||||||
<span v-if="'transfer' === tr.type && parseInt(tr.source_id) === account_id" class="text-info">
|
<!-- title first -->
|
||||||
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount * -1) }}<br>
|
<span class="fas fa-angle-right" @click="toggleCollapse(data.item.id)" style="cursor: pointer;"></span>
|
||||||
</span>
|
<a :href="'./transactions/show/' + data.item.id" :title="data.value">
|
||||||
<span v-if="'transfer' === tr.type && parseInt(tr.destination_id) === account_id" class="text-info">
|
{{ data.item.description }}
|
||||||
{{ Intl.NumberFormat(locale, {style: 'currency', currency: tr.currency_code}).format(tr.amount) }}<br>
|
</a><br />
|
||||||
|
<span v-if="!data.item.collapsed">
|
||||||
|
<span v-for="(split, index) in data.item.splits" v-bind:key="index">
|
||||||
|
{{ split.description }}<br />
|
||||||
</span>
|
</span>
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</template>
|
||||||
<td>
|
<template #cell(amount)="data">
|
||||||
<span v-for="tr in transaction.attributes.transactions">
|
<!-- row amount first (3x) -->
|
||||||
<a v-if="0!==tr.category_id" :href="'categories/show/' + tr.category_id">{{ tr.category_name }}</a><br/>
|
<span :class="'text-success ' + (!data.item.collapsed ? 'font-weight-bold' : '')" v-if="'deposit' === data.item.type">
|
||||||
|
{{ Intl.NumberFormat(locale, {style: 'currency', currency: data.item.currency_code}).format(data.item.amount) }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
<span :class="'text-danger ' + (!data.item.collapsed ? 'font-weight-bold' : '')" v-if="'withdrawal' === data.item.type">
|
||||||
<td>
|
{{ Intl.NumberFormat(locale, {style: 'currency', currency: data.item.currency_code}).format(-data.item.amount) }}
|
||||||
<span v-for="tr in transaction.attributes.transactions">
|
|
||||||
<a v-if="0!==tr.budget_id" :href="'budgets/show/' + tr.budget_id">{{ tr.budget_name }}</a><br/>
|
|
||||||
</span>
|
</span>
|
||||||
</td>
|
<span :class="'text-muted ' + (!data.item.collapsed ? 'font-weight-bold' : '')" v-if="'transfer' === data.item.type">
|
||||||
</tr>
|
{{ Intl.NumberFormat(locale, {style: 'currency', currency: data.item.currency_code}).format(data.item.amount) }}
|
||||||
</tbody>
|
</span>
|
||||||
</table>
|
<br />
|
||||||
|
<!-- splits -->
|
||||||
|
<span v-if="!data.item.collapsed">
|
||||||
|
<span v-for="(split, index) in data.item.splits" v-bind:key="index">
|
||||||
|
{{ Intl.NumberFormat(locale, {style: 'currency', currency: split.currency_code}).format(split.amount) }}<br />
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #cell(date)="data">
|
||||||
|
{{ data.item.date_formatted }}
|
||||||
|
</template>
|
||||||
|
<template #cell(source_account)="data">
|
||||||
|
<!-- extra break for splits -->
|
||||||
|
<span v-if="true===data.item.split && !data.item.collapsed">
|
||||||
|
<br />
|
||||||
|
</span>
|
||||||
|
<em v-if="true===data.item.split && data.item.collapsed">
|
||||||
|
...
|
||||||
|
</em>
|
||||||
|
|
||||||
|
<!-- loop all accounts, hidden if split -->
|
||||||
|
<span v-for="(split, index) in data.item.splits" v-bind:key="index" v-if="false===data.item.split || (true===data.item.split && !data.item.collapsed)">
|
||||||
|
<a :href="'./accounts/show/' + split.source_id" :title="split.source_name">{{ split.source_name }}</a><br />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #cell(destination_account)="data">
|
||||||
|
<!-- extra break for splits -->
|
||||||
|
<span v-if="true===data.item.split && !data.item.collapsed">
|
||||||
|
<br />
|
||||||
|
</span>
|
||||||
|
<em v-if="true===data.item.split && data.item.collapsed">
|
||||||
|
...
|
||||||
|
</em>
|
||||||
|
|
||||||
|
<!-- loop all accounts, hidden if split -->
|
||||||
|
<span v-for="(split, index) in data.item.splits" v-bind:key="index" v-if="false===data.item.split || (true===data.item.split && !data.item.collapsed)">
|
||||||
|
<a :href="'./accounts/show/' + split.destination_id" :title="split.destination_name">{{ split.destination_name }}</a><br />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
<template #cell(menu)="data">
|
||||||
|
<div class="btn-group btn-group-sm">
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="btn btn-light btn-sm dropdown-toggle" type="button" :id="'dropdownMenuButton' + data.item.id" data-toggle="dropdown"
|
||||||
|
aria-haspopup="true" aria-expanded="false">
|
||||||
|
{{ $t('firefly.actions') }}
|
||||||
|
</button>
|
||||||
|
<div class="dropdown-menu" :aria-labelledby="'dropdownMenuButton' + data.item.id">
|
||||||
|
<a class="dropdown-item" :href="'./transactions/edit/' + data.item.id"><span class="fa fas fa-pencil-alt"></span> {{
|
||||||
|
$t('firefly.edit')
|
||||||
|
}}</a>
|
||||||
|
<a class="dropdown-item" :href="'./transactions/delete/' + data.item.id"><span class="fa far fa-trash"></span> {{
|
||||||
|
$t('firefly.delete')
|
||||||
|
}}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #cell(category_name)="data">
|
||||||
|
<!-- extra break for splits -->
|
||||||
|
<span v-if="true===data.item.split && !data.item.collapsed">
|
||||||
|
<br />
|
||||||
|
</span>
|
||||||
|
<em v-if="true===data.item.split && data.item.collapsed">
|
||||||
|
...
|
||||||
|
</em>
|
||||||
|
|
||||||
|
<!-- loop all categories, hidden if split -->
|
||||||
|
<span v-for="(split, index) in data.item.splits" v-bind:key="index" v-if="false===data.item.split || (true===data.item.split && !data.item.collapsed)">
|
||||||
|
<a :href="'./categories/show/' + split.category_id" :title="split.category_name">{{ split.category_name }}</a><br />
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</BTable>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="card-footer"> (button)
|
||||||
|
<!--
|
||||||
|
<a :href="'./transactions/create/' + type" class="btn btn-success"
|
||||||
|
:title="$t('firefly.create_new_transaction')">{{ $t('firefly.create_new_transaction') }}</a>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-8 col-md-6 col-sm-12 col-xs-12">
|
||||||
|
<BPagination
|
||||||
|
v-model="currentPage"
|
||||||
|
:total-rows="total"
|
||||||
|
:per-page="perPage"
|
||||||
|
aria-controls="my-table"
|
||||||
|
></BPagination>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
|
||||||
|
<button @click="newCacheKey" class="btn btn-sm float-right btn-info"><span class="fas fa-sync"></span></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import {mapGetters, mapMutations} from "vuex";
|
||||||
|
import {BPagination, BTable} from 'bootstrap-vue';
|
||||||
|
import format from "date-fns/format";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TransactionListLarge",
|
name: "TransactionListLarge",
|
||||||
|
components: {BPagination, BTable},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
locale: 'en-US'
|
locale: 'en-US',
|
||||||
|
fields: [],
|
||||||
|
currentPage: 1,
|
||||||
|
transactions: [],
|
||||||
|
loading: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
...mapGetters('root', ['listPageSize', 'cacheKey']),
|
||||||
|
},
|
||||||
created() {
|
created() {
|
||||||
this.locale = localStorage.locale ?? 'en-US';
|
this.locale = localStorage.locale ?? 'en-US';
|
||||||
|
this.updateFieldList();
|
||||||
|
//this.currentPage = this.page;
|
||||||
|
this.parseTransactions();
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
currentPage: function (value) {
|
||||||
|
// console.log('Watch currentPage go to ' + value);
|
||||||
|
this.$emit('jump-page', {page: value});
|
||||||
|
},
|
||||||
|
entries: function (value) {
|
||||||
|
this.parseTransactions();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations('root', ['refreshCacheKey',]),
|
||||||
|
parseTransactions: function () {
|
||||||
|
// console.log('Start of parseTransactions. Count of entries is ' + this.entries.length + ' and page is ' + this.page);
|
||||||
|
// console.log('Reported total is ' + this.total);
|
||||||
|
if (0 === this.entries.length) {
|
||||||
|
// console.log('Will not render now');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// console.log('Now have ' + this.transactions.length + ' transactions');
|
||||||
|
for (let i = 0; i < this.total; i++) {
|
||||||
|
this.transactions.push({dummy: true});
|
||||||
|
// console.log('Push dummy to index ' + i);
|
||||||
|
// console.log('Now have ' + this.transactions.length + ' transactions');
|
||||||
|
}
|
||||||
|
// console.log('Generated ' + this.total + ' dummies');
|
||||||
|
// console.log('Now have ' + this.transactions.length + ' transactions');
|
||||||
|
let index = (this.page - 1) * this.perPage;
|
||||||
|
// console.log('Start index is ' + index);
|
||||||
|
for (let i in this.entries) {
|
||||||
|
let transaction = this.entries[i];
|
||||||
|
|
||||||
|
// build split
|
||||||
|
this.transactions[index] = this.parseTransaction(transaction);
|
||||||
|
// console.log('Push transaction to index ' + index);
|
||||||
|
// console.log('Now have ' + this.transactions.length + ' transactions');
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
// console.log('Added ' + this.entries.length + ' entries');
|
||||||
|
// console.log('Now have ' + this.transactions.length + ' transactions');
|
||||||
|
// console.log(this.transactions);
|
||||||
|
|
||||||
|
|
||||||
|
this.loading = false;
|
||||||
|
},
|
||||||
|
newCacheKey: function () {
|
||||||
|
alert('TODO');
|
||||||
|
this.refreshCacheKey();
|
||||||
|
},
|
||||||
|
updateFieldList: function () {
|
||||||
|
this.fields = [
|
||||||
|
{key: 'type', label: ' ', sortable: false},
|
||||||
|
{key: 'description', label: this.$t('list.description'), sortable: true},
|
||||||
|
{key: 'amount', label: this.$t('list.amount'), sortable: true},
|
||||||
|
{key: 'date', label: this.$t('list.date'), sortable: true},
|
||||||
|
{key: 'source_account', label: this.$t('list.source_account'), sortable: true},
|
||||||
|
{key: 'destination_account', label: this.$t('list.destination_account'), sortable: true},
|
||||||
|
{key: 'category_name', label: this.$t('list.category'), sortable: true},
|
||||||
|
{key: 'menu', label: ' ', sortable: false},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Parse a single transaction.
|
||||||
|
* @param transaction
|
||||||
|
*/
|
||||||
|
parseTransaction: function (transaction) {
|
||||||
|
let row = {};
|
||||||
|
|
||||||
|
// default values:
|
||||||
|
row.splits = [];
|
||||||
|
row.key = transaction.id;
|
||||||
|
row.id = transaction.id
|
||||||
|
row.dummy = false;
|
||||||
|
|
||||||
|
// pick this up from the first transaction
|
||||||
|
let first = transaction.attributes.transactions[0];
|
||||||
|
row.type = first.type;
|
||||||
|
row.date = new Date(first.date);
|
||||||
|
row.date_formatted = format(row.date, this.$t('config.month_and_day_fns'));
|
||||||
|
row.description = first.description;
|
||||||
|
row.collapsed = true;
|
||||||
|
row.split = false;
|
||||||
|
row.amount = 0;
|
||||||
|
row.currency_code = first.currency_code;
|
||||||
|
if (transaction.attributes.transactions.length > 1) {
|
||||||
|
row.split = true;
|
||||||
|
row.description = transaction.attributes.group_title;
|
||||||
|
}
|
||||||
|
|
||||||
|
// collapsed?
|
||||||
|
if (typeof transaction.collapsed !== 'undefined') {
|
||||||
|
row.collapsed = transaction.collapsed;
|
||||||
|
}
|
||||||
|
//console.log('is collapsed? ' + row.collapsed);
|
||||||
|
|
||||||
|
// then loop each split
|
||||||
|
for (let i in transaction.attributes.transactions) {
|
||||||
|
if (transaction.attributes.transactions.hasOwnProperty(i)) {
|
||||||
|
let info = transaction.attributes.transactions[i];
|
||||||
|
let split = {};
|
||||||
|
row.amount = row.amount + parseFloat(info.amount);
|
||||||
|
split.description = info.description;
|
||||||
|
split.amount = info.amount;
|
||||||
|
split.currency_code = info.currency_code;
|
||||||
|
split.source_name = info.source_name;
|
||||||
|
split.source_id = info.source_id;
|
||||||
|
split.destination_name = info.destination_name;
|
||||||
|
split.destination_id = info.destination_id;
|
||||||
|
split.category_id = info.category_id;
|
||||||
|
split.category_name = info.category_name;
|
||||||
|
split.split_index = i;
|
||||||
|
row.splits.push(split);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
},
|
||||||
|
toggleCollapse: function (id) {
|
||||||
|
let transaction = this.transactions.filter(transaction => transaction.id === id)[0];
|
||||||
|
transaction.collapsed = !transaction.collapsed;
|
||||||
|
},
|
||||||
|
tableSortCompare: function (aRow, bRow, key, sortDesc, formatter, compareOptions, compareLocale) {
|
||||||
|
let a = aRow[key]
|
||||||
|
let b = bRow[key]
|
||||||
|
|
||||||
|
if (aRow.id === bRow.id) {
|
||||||
|
// Order split transactions normally when compared to each other, except always put the header first
|
||||||
|
if (aRow.split_parent === null) {
|
||||||
|
return sortDesc ? 1 : -1;
|
||||||
|
} else if (bRow.split_parent === null) {
|
||||||
|
return sortDesc ? -1 : 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Sort split transactions based on their parent when compared to other transactions
|
||||||
|
if (aRow.split && aRow.split_parent !== null) {
|
||||||
|
a = aRow.split_parent[key]
|
||||||
|
}
|
||||||
|
if (bRow.split && bRow.split_parent !== null) {
|
||||||
|
b = bRow.split_parent[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
(typeof a === 'number' && typeof b === 'number') ||
|
||||||
|
(a instanceof Date && b instanceof Date)
|
||||||
|
) {
|
||||||
|
// If both compared fields are native numbers or both are native dates
|
||||||
|
return a < b ? -1 : a > b ? 1 : 0
|
||||||
|
} else {
|
||||||
|
// Otherwise stringify the field data and use String.prototype.localeCompare
|
||||||
|
return toString(a).localeCompare(toString(b), compareLocale, compareOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
function toString(value) {
|
||||||
|
if (value === null || typeof value === 'undefined') {
|
||||||
|
return ''
|
||||||
|
} else if (value instanceof Object) {
|
||||||
|
return Object.keys(value)
|
||||||
|
.sort()
|
||||||
|
.map(key => toString(value[key]))
|
||||||
|
.join(' ')
|
||||||
|
} else {
|
||||||
|
return String(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
transactions: {
|
page: {
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
perPage: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
sortDesc: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
total: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: function () {
|
default: function () {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
account_id: {
|
accountId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
default: function () {
|
default: function () {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -169,13 +169,13 @@
|
|||||||
"repeat_freq_quarterly": "\u03c4\u03c1\u03b9\u03bc\u03b7\u03bd\u03b9\u03b1\u03af\u03c9\u03c2",
|
"repeat_freq_quarterly": "\u03c4\u03c1\u03b9\u03bc\u03b7\u03bd\u03b9\u03b1\u03af\u03c9\u03c2",
|
||||||
"repeat_freq_monthly": "\u03bc\u03b7\u03bd\u03b9\u03b1\u03af\u03c9\u03c2",
|
"repeat_freq_monthly": "\u03bc\u03b7\u03bd\u03b9\u03b1\u03af\u03c9\u03c2",
|
||||||
"repeat_freq_weekly": "\u03b5\u03b2\u03b4\u03bf\u03bc\u03b1\u03b4\u03b9\u03b1\u03af\u03c9\u03c2",
|
"repeat_freq_weekly": "\u03b5\u03b2\u03b4\u03bf\u03bc\u03b1\u03b4\u03b9\u03b1\u03af\u03c9\u03c2",
|
||||||
"credit_card_type_monthlyFull": "Full payment every month",
|
"credit_card_type_monthlyFull": "\u0395\u03be\u03cc\u03c6\u03bb\u03b7\u03c3\u03b7 \u03ba\u03ac\u03b8\u03b5 \u03bc\u03ae\u03bd\u03b1",
|
||||||
"update_liabilities_account": "\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03c5\u03c0\u03bf\u03c7\u03c1\u03ad\u03c9\u03c3\u03b7\u03c2",
|
"update_liabilities_account": "\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03c5\u03c0\u03bf\u03c7\u03c1\u03ad\u03c9\u03c3\u03b7\u03c2",
|
||||||
"update_expense_account": "\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03bf\u03cd \u03b4\u03b1\u03c0\u03b1\u03bd\u03ce\u03bd",
|
"update_expense_account": "\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03bf\u03cd \u03b4\u03b1\u03c0\u03b1\u03bd\u03ce\u03bd",
|
||||||
"update_revenue_account": "\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03bf\u03cd \u03b5\u03c3\u03cc\u03b4\u03c9\u03bd",
|
"update_revenue_account": "\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03bf\u03cd \u03b5\u03c3\u03cc\u03b4\u03c9\u03bd",
|
||||||
"update_undefined_account": "Update account",
|
"update_undefined_account": "\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03bf\u03cd",
|
||||||
"update_asset_account": "\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03bf\u03cd \u03ba\u03b5\u03c6\u03b1\u03bb\u03b1\u03af\u03bf\u03c5",
|
"update_asset_account": "\u0395\u03bd\u03b7\u03bc\u03ad\u03c1\u03c9\u03c3\u03b7 \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03bf\u03cd \u03ba\u03b5\u03c6\u03b1\u03bb\u03b1\u03af\u03bf\u03c5",
|
||||||
"updated_account_js": "Updated account \"<a href=\"accounts\/show\/{ID}\">{title}<\/a>\"."
|
"updated_account_js": "\u0395\u03bd\u03b7\u03bc\u03b5\u03c1\u03ce\u03b8\u03b7\u03ba\u03b5 \u03bf \u03bb\u03bf\u03b3\u03b1\u03c1\u03b9\u03b1\u03c3\u03bc\u03cc\u03c2 \"<a href=\"accounts\/show\/{ID}\">{title}<\/a>\"."
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"piggy_bank": "\u039a\u03bf\u03c5\u03bc\u03c0\u03b1\u03c1\u03ac\u03c2",
|
"piggy_bank": "\u039a\u03bf\u03c5\u03bc\u03c0\u03b1\u03c1\u03ac\u03c2",
|
||||||
|
@ -169,13 +169,13 @@
|
|||||||
"repeat_freq_quarterly": "trimestriel",
|
"repeat_freq_quarterly": "trimestriel",
|
||||||
"repeat_freq_monthly": "mensuel",
|
"repeat_freq_monthly": "mensuel",
|
||||||
"repeat_freq_weekly": "hebdomadaire",
|
"repeat_freq_weekly": "hebdomadaire",
|
||||||
"credit_card_type_monthlyFull": "Full payment every month",
|
"credit_card_type_monthlyFull": "Paiement complet tous les mois",
|
||||||
"update_liabilities_account": "Mettre \u00e0 jour le passif",
|
"update_liabilities_account": "Mettre \u00e0 jour le passif",
|
||||||
"update_expense_account": "Mettre \u00e0 jour le compte de d\u00e9penses",
|
"update_expense_account": "Mettre \u00e0 jour le compte de d\u00e9penses",
|
||||||
"update_revenue_account": "Mettre \u00e0 jour le compte de recettes",
|
"update_revenue_account": "Mettre \u00e0 jour le compte de recettes",
|
||||||
"update_undefined_account": "Update account",
|
"update_undefined_account": "Mettre \u00e0 jour le compte",
|
||||||
"update_asset_account": "Mettre \u00e0 jour le compte d\u2019actif",
|
"update_asset_account": "Mettre \u00e0 jour le compte d\u2019actif",
|
||||||
"updated_account_js": "Updated account \"<a href=\"accounts\/show\/{ID}\">{title}<\/a>\"."
|
"updated_account_js": "Compte \"<a href=\"accounts\/show\/{ID}\">{title}<\/a>\" mis \u00e0 jour."
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"piggy_bank": "Tirelire",
|
"piggy_bank": "Tirelire",
|
||||||
|
@ -173,9 +173,9 @@
|
|||||||
"update_liabilities_account": "\u30c1\u30e3\u30f3\u30cd\u30eb\u3092\u66f4\u65b0",
|
"update_liabilities_account": "\u30c1\u30e3\u30f3\u30cd\u30eb\u3092\u66f4\u65b0",
|
||||||
"update_expense_account": "\u652f\u51fa\u5148\u30a2\u30ab\u30a6\u30f3\u30c8\uff08\u652f\u51fa\u5143\u30a2\u30ab\u30a6\u30f3\u30c8\n\uff09",
|
"update_expense_account": "\u652f\u51fa\u5148\u30a2\u30ab\u30a6\u30f3\u30c8\uff08\u652f\u51fa\u5143\u30a2\u30ab\u30a6\u30f3\u30c8\n\uff09",
|
||||||
"update_revenue_account": "\u652f\u51fa\u30a2\u30ab\u30a6\u30f3\u30c8\uff08\u53ce\u5165\u30a2\u30ab\u30a6\u30f3\u30c8\uff09",
|
"update_revenue_account": "\u652f\u51fa\u30a2\u30ab\u30a6\u30f3\u30c8\uff08\u53ce\u5165\u30a2\u30ab\u30a6\u30f3\u30c8\uff09",
|
||||||
"update_undefined_account": "Update account",
|
"update_undefined_account": "\u53e3\u5ea7\u60c5\u5831\u306e\u66f4\u65b0",
|
||||||
"update_asset_account": "\u652f\u51fa\u30a2\u30ab\u30a6\u30f3\u30c8\uff08\u8cc7\u7523\u52d8\u5b9a\uff09",
|
"update_asset_account": "\u652f\u51fa\u30a2\u30ab\u30a6\u30f3\u30c8\uff08\u8cc7\u7523\u52d8\u5b9a\uff09",
|
||||||
"updated_account_js": "Updated account \"<a href=\"accounts\/show\/{ID}\">{title}<\/a>\"."
|
"updated_account_js": "\u53e3\u5ea7\u300c<a href=\"accounts\/show\/{ID}\">{title}<\/a>\u300d\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002"
|
||||||
},
|
},
|
||||||
"list": {
|
"list": {
|
||||||
"piggy_bank": "\u8caf\u91d1\u7bb1",
|
"piggy_bank": "\u8caf\u91d1\u7bb1",
|
||||||
|
@ -149,7 +149,7 @@
|
|||||||
"bill_repeats_weekly_other": "Repeats every other week",
|
"bill_repeats_weekly_other": "Repeats every other week",
|
||||||
"bill_repeats_monthly_other": "Repeats every other month",
|
"bill_repeats_monthly_other": "Repeats every other month",
|
||||||
"bill_repeats_quarterly_other": "Repeats every other quarter",
|
"bill_repeats_quarterly_other": "Repeats every other quarter",
|
||||||
"bill_repeats_half-year_other": "Repeats yearly",
|
"bill_repeats_half-year_other": "\u041f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f \u0435\u0436\u0435\u0433\u043e\u0434\u043d\u043e",
|
||||||
"bill_repeats_yearly_other": "Repeats every other year",
|
"bill_repeats_yearly_other": "Repeats every other year",
|
||||||
"bill_repeats_weekly_skip": "Repeats every {skip} weeks",
|
"bill_repeats_weekly_skip": "Repeats every {skip} weeks",
|
||||||
"bill_repeats_monthly_skip": "Repeats every {skip} months",
|
"bill_repeats_monthly_skip": "Repeats every {skip} months",
|
||||||
|
20
frontend/src/pages/accounts/edit.js
vendored
20
frontend/src/pages/accounts/edit.js
vendored
@ -1,3 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* edit.js
|
||||||
|
* Copyright (c) 2021 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
require('../../bootstrap');
|
require('../../bootstrap');
|
||||||
|
|
||||||
import Edit from "../../components/accounts/Edit";
|
import Edit from "../../components/accounts/Edit";
|
||||||
|
27
frontend/src/pages/accounts/show.js
vendored
27
frontend/src/pages/accounts/show.js
vendored
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
require('../../bootstrap');
|
require('../../bootstrap');
|
||||||
|
|
||||||
|
import store from '../../components/store';
|
||||||
import Show from "../../components/accounts/Show";
|
import Show from "../../components/accounts/Show";
|
||||||
|
|
||||||
// i18n
|
// i18n
|
||||||
@ -29,12 +30,22 @@ let i18n = require('../../i18n');
|
|||||||
// get page name?
|
// get page name?
|
||||||
|
|
||||||
|
|
||||||
let props = {
|
let props = {};
|
||||||
|
|
||||||
};
|
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
i18n,
|
i18n,
|
||||||
render(createElement) {
|
store,
|
||||||
return createElement(Show, {props: props});
|
render(createElement) {
|
||||||
}
|
return createElement(Show, {props: props});
|
||||||
}).$mount('#accounts_show');
|
},
|
||||||
|
beforeCreate() {
|
||||||
|
// See reference nr. 10
|
||||||
|
this.$store.commit('initialiseStore');
|
||||||
|
this.$store.dispatch('updateCurrencyPreference');
|
||||||
|
|
||||||
|
// init the new root store (dont care about results)
|
||||||
|
this.$store.dispatch('root/initialiseStore');
|
||||||
|
|
||||||
|
// also init the dashboard store.
|
||||||
|
this.$store.dispatch('dashboard/index/initialiseStore');
|
||||||
|
},
|
||||||
|
}).$mount('#accounts_show');
|
||||||
|
12
frontend/src/pages/dashboard.js
vendored
12
frontend/src/pages/dashboard.js
vendored
@ -28,9 +28,9 @@ import MainBudgetList from '../components/dashboard/MainBudgetList';
|
|||||||
import MainCreditList from '../components/dashboard/MainCreditList';
|
import MainCreditList from '../components/dashboard/MainCreditList';
|
||||||
import MainDebitList from '../components/dashboard/MainDebitList';
|
import MainDebitList from '../components/dashboard/MainDebitList';
|
||||||
import MainPiggyList from '../components/dashboard/MainPiggyList';
|
import MainPiggyList from '../components/dashboard/MainPiggyList';
|
||||||
import TransactionListLarge from '../components/transactions/TransactionListLarge';
|
import DashboardListLarge from '../components/dashboard/DashboardListLarge';
|
||||||
import TransactionListMedium from '../components/transactions/TransactionListMedium';
|
import DashboardListMedium from '../components/dashboard/DashboardListMedium';
|
||||||
import TransactionListSmall from '../components/transactions/TransactionListSmall';
|
import DashboardListSmall from '../components/dashboard/DashboardListSmall';
|
||||||
import Calendar from '../components/dashboard/Calendar';
|
import Calendar from '../components/dashboard/Calendar';
|
||||||
import MainCategoryList from '../components/dashboard/MainCategoryList';
|
import MainCategoryList from '../components/dashboard/MainCategoryList';
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
@ -48,9 +48,9 @@ import store from '../components/store';
|
|||||||
require('../bootstrap');
|
require('../bootstrap');
|
||||||
require('chart.js');
|
require('chart.js');
|
||||||
|
|
||||||
Vue.component('transaction-list-large', TransactionListLarge);
|
Vue.component('dashboard-list-large', DashboardListLarge);
|
||||||
Vue.component('transaction-list-medium', TransactionListMedium);
|
Vue.component('dashboard-list-medium', DashboardListMedium);
|
||||||
Vue.component('transaction-list-small', TransactionListSmall);
|
Vue.component('dashboard-list-small', DashboardListSmall);
|
||||||
|
|
||||||
// components as an example
|
// components as an example
|
||||||
|
|
||||||
|
4
frontend/src/pages/transactions/index.js
vendored
4
frontend/src/pages/transactions/index.js
vendored
@ -23,16 +23,12 @@ require('../../bootstrap');
|
|||||||
import Vue from "vue";
|
import Vue from "vue";
|
||||||
import store from "../../components/store";
|
import store from "../../components/store";
|
||||||
import Index from "../../components/transactions/Index";
|
import Index from "../../components/transactions/Index";
|
||||||
import {BPagination, BTable} from 'bootstrap-vue';
|
|
||||||
import Calendar from "../../components/dashboard/Calendar";
|
import Calendar from "../../components/dashboard/Calendar";
|
||||||
|
|
||||||
// i18n
|
// i18n
|
||||||
let i18n = require('../../i18n');
|
let i18n = require('../../i18n');
|
||||||
let props = {};
|
let props = {};
|
||||||
|
|
||||||
Vue.component('b-table', BTable);
|
|
||||||
Vue.component('b-pagination', BPagination);
|
|
||||||
|
|
||||||
const app = new Vue({
|
const app = new Vue({
|
||||||
i18n,
|
i18n,
|
||||||
store,
|
store,
|
||||||
|
58
frontend/src/serviceworker.js
vendored
Normal file
58
frontend/src/serviceworker.js
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* serviceworker.js
|
||||||
|
* Copyright (c) 2021 Lorenzo Breda (https://github.com/lbreda)
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let staticCachePrefix = "firefly-III-"
|
||||||
|
let staticCacheName = staticCachePrefix + new Date().getTime();
|
||||||
|
let cachedFiles = [
|
||||||
|
'/offline',
|
||||||
|
'/v2/plugins/local-fonts/gf-source.css',
|
||||||
|
'/v2/css/app.css',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Create cache on install
|
||||||
|
self.addEventListener("install", event => {
|
||||||
|
this.skipWaiting();
|
||||||
|
event.waitUntil(
|
||||||
|
caches.open(staticCacheName).then(cache => cache.addAll(cachedFiles))
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear cache on activate
|
||||||
|
self.addEventListener('activate', event => {
|
||||||
|
event.waitUntil(
|
||||||
|
caches.keys().then(cacheNames => {
|
||||||
|
return Promise.all(
|
||||||
|
cacheNames
|
||||||
|
.filter(cacheName => (cacheName.startsWith(staticCachePrefix)))
|
||||||
|
.filter(cacheName => (cacheName !== staticCacheName))
|
||||||
|
.map(cacheName => caches.delete(cacheName))
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Serve from Cache or return the offline page
|
||||||
|
self.addEventListener("fetch", event => {
|
||||||
|
event.respondWith(
|
||||||
|
caches.match(event.request)
|
||||||
|
.then(response => (response || fetch(event.request)))
|
||||||
|
.catch(() => caches.match('offline'))
|
||||||
|
)
|
||||||
|
});
|
1282
frontend/yarn.lock
1282
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@johmun/vue-tags-input": "^2",
|
"@johmun/vue-tags-input": "^2",
|
||||||
"@vue/compiler-sfc": "^3.1.5",
|
"@vue/compiler-sfc": "^3.2.11",
|
||||||
"axios": "^0.21",
|
"axios": "^0.21",
|
||||||
"bootstrap-sass": "^3",
|
"bootstrap-sass": "^3",
|
||||||
"cross-env": "^7.0",
|
"cross-env": "^7.0",
|
||||||
@ -21,7 +21,7 @@
|
|||||||
"uiv": "^1.3",
|
"uiv": "^1.3",
|
||||||
"vue": "^2.6",
|
"vue": "^2.6",
|
||||||
"vue-i18n": "^8.25",
|
"vue-i18n": "^8.25",
|
||||||
"vue-loader": "^16.3.1",
|
"vue-loader": "^15",
|
||||||
"vue-template-compiler": "^2.6"
|
"vue-template-compiler": "^2.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# Please report security issues related to Firefly III
|
# For this (sub)domain, report Firefly III security issues ONLY
|
||||||
# to me ASAP via the email address below.
|
# Other reports will be IGNORED
|
||||||
|
|
||||||
Contact: mailto:thegrumpydictator@gmail.com
|
Contact: mailto:james@firefly-iii.org
|
||||||
Encryption: https://keybase.io/jc5/pgp_keys.asc?fingerprint=90f546f13b81b67a1baa5dddc16961e655e74b5e
|
Encryption: https://keybase.io/jc5/pgp_keys.asc?fingerprint=5d22ce912243bea5185ab2289d53bf7bdccbf49e
|
||||||
Acknowledgements: https://github.com/firefly-iii/firefly-iii
|
Acknowledgements: https://github.com/firefly-iii/firefly-iii
|
||||||
Signature: https://firefly-iii.org/.well-known/security.txt.sig
|
Signature: https://firefly-iii.org/.well-known/security.txt.sig
|
||||||
|
@ -3,15 +3,83 @@
|
|||||||
"short_name": "Firefly III",
|
"short_name": "Firefly III",
|
||||||
"start_url": "/",
|
"start_url": "/",
|
||||||
"icons": [
|
"icons": [
|
||||||
|
{
|
||||||
|
"src": "/maskable72.png",
|
||||||
|
"sizes": "72x72",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/maskable76.png",
|
||||||
|
"sizes": "76x76",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/maskable96.png",
|
||||||
|
"sizes": "96x96",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/maskable120.png",
|
||||||
|
"sizes": "120x120",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/maskable128.png",
|
||||||
|
"sizes": "128x128",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/maskable144.png",
|
||||||
|
"sizes": "144x144",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/maskable152.png",
|
||||||
|
"sizes": "152x152",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/maskable180.png",
|
||||||
|
"sizes": "180x180",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "/android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png",
|
||||||
|
"scope": "any"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/maskable192.png",
|
||||||
|
"sizes": "192x192",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/maskable384.png",
|
||||||
|
"sizes": "384x384",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-512x512.png",
|
"src": "/android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png",
|
||||||
|
"scope": "any"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/maskable512.png",
|
||||||
|
"sizes": "512x512",
|
||||||
|
"type": "image/png",
|
||||||
|
"scope": "maskable"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme_color": "#1e6581",
|
"theme_color": "#1e6581",
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user