Merge branch 'release/v6.0.28'

This commit is contained in:
James Cole 2023-10-28 17:18:49 +02:00
commit 461b5ad859
533 changed files with 5164 additions and 38671 deletions

View File

@ -226,16 +226,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.35.1",
"version": "v3.37.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "ec1ccc264994b6764882669973ca435cf05bab08"
"reference": "d5ccc3807fd496ac2b448e8e5e57aa0772f0d18b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/ec1ccc264994b6764882669973ca435cf05bab08",
"reference": "ec1ccc264994b6764882669973ca435cf05bab08",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/d5ccc3807fd496ac2b448e8e5e57aa0772f0d18b",
"reference": "d5ccc3807fd496ac2b448e8e5e57aa0772f0d18b",
"shasum": ""
},
"require": {
@ -307,7 +307,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.35.1"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.37.0"
},
"funding": [
{
@ -315,7 +315,7 @@
"type": "github"
}
],
"time": "2023-10-12T13:47:26+00:00"
"time": "2023-10-28T14:49:50+00:00"
},
{
"name": "psr/container",

View File

@ -195,6 +195,16 @@ MAP_DEFAULT_LAT=51.983333
MAP_DEFAULT_LONG=5.916667
MAP_DEFAULT_ZOOM=6
#
# Some objects have room for an URL, like transactions and webhooks.
# By default, the following protocols are allowed:
# http, https, ftp, ftps, mailto
#
# To change this, set your preferred comma separated set below.
# Be sure to include http, https and other default ones if you need to.
#
VALID_URL_PROTOCOLS=
#
# Firefly III authentication settings
#

View File

@ -1,6 +1,6 @@
# This workflow prunes old workflow runs for an entire repository.
name: Prune old builds
name: "Chore - prune old builds"
on:
schedule:
@ -22,14 +22,14 @@ jobs:
repo: context.repo.repo,
status: 'cancelled',
});
const skipped = await github.rest.actions.listWorkflowRunsForRepo({
owner: context.repo.owner,
per_page: 100,
repo: context.repo.repo,
status: 'skipped',
});
for (const response of [cancelled, skipped]) {
for (const run of response.data.workflow_runs) {
console.log(`Run id ${run.id} of '${run.name}' is a cancelled/skipped run. Deleting...`);
@ -50,10 +50,10 @@ jobs:
const ms_in_day = 86400000;
const now = Date.now();
const pages = 5;
// we don't want to prune old runs from test.yml
// because we track the duration of runs over time
const workflows = [
'cleanup.yml',
'closed-issues.yml',
@ -64,9 +64,9 @@ jobs:
'sonarcloud.yml',
'stale.yml'
]
let runs_to_delete = [];
for (const workflow of workflows) {
for (let page = 0; page < pages; page += 1) {
let response = await github.rest.actions.listWorkflowRuns({
@ -76,7 +76,7 @@ jobs:
repo: context.repo.repo,
workflow_id: workflow
});
if (response.data.workflow_runs.length > 0) {
for (const run of response.data.workflow_runs) {
if (now - Date.parse(run.created_at) > ms_in_day * days_to_expiration) {
@ -86,7 +86,7 @@ jobs:
}
}
}
for (const run of runs_to_delete) {
console.log(`Run id ${run[0]} of '${run[1]}' is older than ${days_to_expiration} days. Deleting...`);
try {

View File

@ -1,4 +1,4 @@
name: "Reply to closed issue"
name: "Issues - reply to closed issue"
on:
issues:
types:

View File

@ -1,4 +1,4 @@
name: 'Dependency Review'
name: 'Code - dependency review'
on: [ pull_request ]
permissions:

View File

@ -1,4 +1,4 @@
name: 'Label Actions'
name: 'Issues - reply to specific labels'
on:
issues:

View File

@ -1,146 +0,0 @@
name: Firefly III
on:
push:
branches-ignore:
- '**'
jobs:
prepare:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Copy .env
run: test -f .env || cp .ci/.env.ci .env
- name: Prepare dependencies
run: |
set -euxo pipefail
export PATH=$PATH:$HOME/.composer/vendor/bin/
composer global require hirak/prestissimo --no-plugins --no-scripts
composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-suggest
touch ./storage/database/database.sqlite
- name: Prepare Firefly III
run: |
chmod -R 777 storage bootstrap/cache
php artisan migrate --seed
php artisan firefly-iii:upgrade-database
- name: Upload database
uses: actions/upload-artifact@v2
with:
name: database
path: storage/database/database.sqlite
- name: Upload cache
uses: actions/upload-artifact@v2
with:
name: cache
path: bootstrap/cache/
- name: Upload composer cache
uses: actions/upload-artifact@v2
with:
name: composer
path: ~/.composer
laravel-tests:
runs-on: ubuntu-latest
needs:
- prepare
steps:
- uses: actions/checkout@v3
- name: Copy .env
run: test -f .env || cp .ci/.env.ci .env
- name: Download database
uses: actions/download-artifact@v2
with:
name: database
path: storage/database/database.sqlite
- name: Download cache
uses: actions/download-artifact@v2
with:
name: cache
path: bootstrap/cache/
- name: Download vendor
uses: actions/download-artifact@v2
with:
name: composer
path: ~/.composer
- name: Install composer
run: composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-suggest
- name: PHPUnit tests
uses: php-actions/phpunit@v1
with:
config: phpunit.xml
memory: 512M
coding-standards:
runs-on: ubuntu-latest
needs:
- prepare
steps:
- uses: actions/checkout@v3
- name: Copy .env
run: test -f .env || cp .ci/.env.ci .env
- name: Download database
uses: actions/download-artifact@v2
with:
name: database
path: storage/database/database.sqlite
- name: Download cache
uses: actions/download-artifact@v2
with:
name: cache
path: bootstrap/cache/
- name: Download vendor
uses: actions/download-artifact@v2
with:
name: composer
path: ~/.composer
- name: install depenencies
run: |
composer global require nette/coding-standard
composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-suggest
- name: Execute code standard
run: /home/runner/.composer/vendor/bin/ecs check app tests --config ./.ci/firefly-iii-standard.yml
phpstan:
runs-on: ubuntu-latest
needs:
- prepare
steps:
- uses: actions/checkout@v3
- name: Copy .env
run: test -f .env || cp .ci/.env.ci .env
- name: Download database
uses: actions/download-artifact@v2
with:
name: database
path: storage/database/database.sqlite
- name: Download cache
uses: actions/download-artifact@v2
with:
name: cache
path: bootstrap/cache/
- name: Download vendor
uses: actions/download-artifact@v2
with:
name: composer
path: ~/.composer
- name: Install depenencies
run: |
composer install --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist --no-suggest
- name: Execute PHPStan
run: vendor/bin/phpstan analyse -c .ci/phpstan.neon

View File

@ -1,4 +1,4 @@
name: Lock old issues
name: 'Issues - Lock old issues'
on:
workflow_dispatch:

View File

@ -1,35 +0,0 @@
name: Qodana
on:
workflow_dispatch:
push:
branches:
- main
- develop
jobs:
qodana:
runs-on: ubuntu-latest
name: 'Qodana Scan'
steps:
- name: Setup PHP with no coverage driver
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
coverage: none
extensions: bcmath, intl
env:
update: true
- uses: actions/checkout@v3
with:
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- name: Install dependencies
run: |
composer install --no-scripts
cp .env.example .env
php artisan key:generate
php artisan clear-compiled
php artisan ide-helper:generate;
- name: 'Qodana Scan'
uses: JetBrains/qodana-action@main
env:
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}

View File

@ -1,14 +1,37 @@
name: Sonarcloud
name: 'Code - Run Sonarcloud'
on:
pull_request:
pull_request:
push:
branches:
- main
- develop
env:
DB_CONNECTION: mysql
DB_HOST: "127.0.0.1"
DB_DATABASE: firefly
DB_USER: firefly
DB_PASSWORD: secret_firefly_password
jobs:
sonarcloud:
name: SonarCloud
runs-on: ubuntu-latest
services:
mariadb:
image: mariadb:latest
ports:
- 3306:3306
env:
MYSQL_ROOT_PASSWORD: yes
MYSQL_USER: ${{ env.DB_USER }}
MYSQL_PASSWORD: ${{ env.DB_PASSWORD }}
MYSQL_DATABASE: ${{ env.DB_DATABASE }}
options: >-
--health-cmd="healthcheck.sh --connect --innodb_initialized"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- uses: actions/checkout@v3
with:
@ -24,16 +47,49 @@ jobs:
with:
php-version: '8.2'
coverage: xdebug
extensions: >-
bcmath
curl
fileinfo
iconv
intl
json
mbstring
openssl
pdo
session
simplexml
sodium
tokenizer
xml
xmlwriter
- name: Install Composer dependencies
run: composer install --prefer-dist --no-interaction --no-progress --no-scripts
- name: Verify Database connection
env:
PORT: ${{ job.services.mariadb.ports[3306] }}
run: |
while ! mysqladmin ping -h"${{env.DB_HOST}}" -P"${PORT}" --silent; do
sleep 1
done
- name: Copy environment file
run: cp .env.example .env
run: sed 's@DB_HOST=.*@DB_HOST=${{env.DB_HOST}}@g' .env.example > .env
- name: Generate app key
run: php artisan key:generate
- name: "Create the database"
run: php artisan firefly-iii:create-database
- name: "Upgrades the database to the latest version"
run: php artisan firefly-iii:upgrade-database
- name: "Integrity Database Report"
run: php artisan firefly-iii:report-integrity
- name: "Run tests with coverage"
run: composer coverage

View File

@ -1,4 +1,4 @@
name: "Close stale issues"
name: "Issues - close stale issues"
on:
schedule:
- cron: "30 1 * * *"
@ -20,13 +20,13 @@ jobs:
stale-issue-message: >
Hi there! This is an automatic reply. `Share and enjoy`
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.
stale-pr-message: >
Hi there! This is an automatic reply. `Share and enjoy`
This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
This PR has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions.
days-before-stale: 14

2
.gitignore vendored
View File

@ -1,8 +1,6 @@
/node_modules
/frontend/node_modules
/storage/*.key
/vendor
/.vagrant
npm-debug.log
yarn-error.log
.env

View File

@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;

View File

@ -31,7 +31,6 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\ApiSupport;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
@ -46,8 +45,7 @@ class AccountController extends Controller
{
use ApiSupport;
private CurrencyRepositoryInterface $currencyRepository;
private AccountRepositoryInterface $repository;
private AccountRepositoryInterface $repository;
/**
* AccountController constructor.
@ -64,9 +62,6 @@ class AccountController extends Controller
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUser($user);
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
$this->currencyRepository->setUser($user);
return $next($request);
}
);

View File

@ -28,7 +28,6 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Account\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\ApiSupport;
use Illuminate\Http\JsonResponse;
@ -43,7 +42,6 @@ class AccountController extends Controller
{
use ApiSupport;
private CurrencyRepositoryInterface $currencyRepository;
private OperationsRepositoryInterface $opsRepository;
private AccountRepositoryInterface $repository;
@ -61,9 +59,6 @@ class AccountController extends Controller
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUser($user);
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
$this->currencyRepository->setUser($user);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->opsRepository->setUser($user);

View File

@ -28,7 +28,6 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Insight\GenericRequest;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Account\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\ApiSupport;
use Illuminate\Http\JsonResponse;
@ -43,7 +42,6 @@ class AccountController extends Controller
{
use ApiSupport;
private CurrencyRepositoryInterface $currencyRepository;
private OperationsRepositoryInterface $opsRepository;
private AccountRepositoryInterface $repository;
@ -61,9 +59,6 @@ class AccountController extends Controller
$this->repository = app(AccountRepositoryInterface::class);
$this->repository->setUser($user);
$this->currencyRepository = app(CurrencyRepositoryInterface::class);
$this->currencyRepository->setUser($user);
$this->opsRepository = app(OperationsRepositoryInterface::class);
$this->opsRepository->setUser($user);

View File

@ -27,8 +27,8 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionCurrency;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Validator;

View File

@ -38,7 +38,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
@ -65,26 +64,6 @@ class ListController extends Controller
use AccountFilter;
use TransactionFilter;
private CurrencyRepositoryInterface $repository;
/**
* CurrencyRepository constructor.
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(CurrencyRepositoryInterface::class);
$this->repository->setUser(auth()->user());
return $next($request);
}
);
}
/**
* This endpoint is documented at:
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/currencies/listAccountByCurrency

View File

@ -27,10 +27,11 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionCurrency;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\CurrencyTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
use JsonException;
@ -81,13 +82,12 @@ class ShowController extends Controller
$pageSize = $this->parameters->get('limit');
$collection = $this->repository->getAll();
$count = $collection->count();
// slice them:
$currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($currencies, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.index') . $this->buildParams());
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
$manager = $this->getManager();
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);
@ -113,10 +113,15 @@ class ShowController extends Controller
*/
public function show(TransactionCurrency $currency): JsonResponse
{
/** @var User $user */
$user = auth()->user();
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup);
$this->parameters->set('defaultCurrency', $defaultCurrency);
// update fields with user info.
$currency->refreshForUser($user);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);
$transformer->setParameters($this->parameters);
@ -138,9 +143,13 @@ class ShowController extends Controller
*/
public function showDefault(): JsonResponse
{
/** @var User $user */
$user = auth()->user();
$manager = $this->getManager();
$currency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $currency);
$currency = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup);
// update fields with user info.
$currency->refreshForUser($user);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);

View File

@ -27,10 +27,11 @@ namespace FireflyIII\Api\V1\Controllers\Models\TransactionCurrency;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\StoreRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\CurrencyTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use JsonException;
use League\Fractal\Resource\Item;
@ -79,12 +80,14 @@ class StoreController extends Controller
{
$currency = $this->repository->store($request->getAll());
if (true === $request->boolean('default')) {
app('preferences')->set('currencyPreference', $currency->code);
$this->repository->makeDefault($currency);
app('preferences')->mark();
}
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
$manager = $this->getManager();
/** @var User $user */
$user = auth()->user();
$currency->refreshForUser($user);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);

View File

@ -28,10 +28,11 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\UpdateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Transformers\CurrencyTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use JsonException;
use League\Fractal\Resource\Item;
@ -82,11 +83,16 @@ class UpdateController extends Controller
if ($this->repository->currencyInUse($currency)) {
return response()->json([], 409);
}
// must not be the only one in use:
if (1 === $this->repository->get()->count()) {
return response()->json([], 409);
}
/** @var User $user */
$user = auth()->user();
$this->repository->disable($currency);
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
$currency->refreshForUser($user);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);
@ -110,14 +116,15 @@ class UpdateController extends Controller
*/
public function makeDefault(TransactionCurrency $currency): JsonResponse
{
/** @var User $user */
$user = auth()->user();
$this->repository->enable($currency);
$this->repository->makeDefault($currency);
app('preferences')->set('currencyPreference', $currency->code);
app('preferences')->mark();
$manager = $this->getManager();
$this->parameters->set('defaultCurrency', $currency);
$currency->refreshForUser($user);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);
@ -144,9 +151,10 @@ class UpdateController extends Controller
{
$this->repository->enable($currency);
$manager = $this->getManager();
/** @var User $user */
$user = auth()->user();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
$currency->refreshForUser($user);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);
@ -172,18 +180,23 @@ class UpdateController extends Controller
*/
public function update(UpdateRequest $request, TransactionCurrency $currency): JsonResponse
{
$data = $request->getAll();
$data = $request->getAll();
/** @var User $user */
$user = auth()->user();
// safety catch on currency disablement.
$set = $this->repository->get();
if (array_key_exists('enabled', $data) && false === $data['enabled'] && 1 === count($set) && $set->first()->id === $currency->id) {
return response()->json([], 409);
}
$currency = $this->repository->update($currency, $data);
if (true === $request->boolean('default')) {
app('preferences')->set('currencyPreference', $currency->code);
app('preferences')->mark();
}
app('preferences')->mark();
$manager = $this->getManager();
$defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user());
$this->parameters->set('defaultCurrency', $defaultCurrency);
$currency->refreshForUser($user);
/** @var CurrencyTransformer $transformer */
$transformer = app(CurrencyTransformer::class);

View File

@ -39,7 +39,7 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;

View File

@ -174,7 +174,7 @@ class StoreRequest extends FormRequest
public function rules(): array
{
Log::debug('Collect rules of TransactionStoreRequest');
$validProtocols = config('firefly.valid_url_protocols');
return [
// basic fields for group:
'group_title' => 'between:1,1000|nullable',
@ -233,7 +233,7 @@ class StoreRequest extends FormRequest
'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => 'min:1|max:255|nullable|url',
'transactions.*.external_url' => sprintf('min:1|max:255|nullable|url:%s', $validProtocols),
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1|max:255|nullable',

View File

@ -321,7 +321,7 @@ class UpdateRequest extends FormRequest
public function rules(): array
{
Log::debug(sprintf('Now in %s', __METHOD__));
$validProtocols = config('firefly.valid_url_protocols');
return [
// basic fields for group:
'group_title' => 'between:1,1000|nullable',
@ -375,7 +375,7 @@ class UpdateRequest extends FormRequest
'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => 'min:1|max:255|nullable|url',
'transactions.*.external_url' => sprintf('min:1|max:255|nullable|url:%s', $validProtocols),
// SEPA fields:
'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
@ -417,15 +417,22 @@ class UpdateRequest extends FormRequest
// all transaction types must be equal:
$this->validateTransactionTypesForUpdate($validator);
// user wants to update a reconciled transaction.
// source, destination, amount + foreign_amount cannot be changed
// and must be omitted from the request.
$this->preventUpdateReconciled($validator, $transactionGroup);
// validate source/destination is equal, depending on the transaction journal type.
$this->validateEqualAccountsForUpdate($validator, $transactionGroup);
// a catch when users submit splits with no source or destination info at all.
$this->preventNoAccountInfo($validator, );
// see method:
//$this->preventNoAccountInfo($validator, );
// validate that the currency fits the source and/or destination account.
// validate all account info
$this->validateAccountInformationUpdate($validator, $transactionGroup);
}
);
}

View File

@ -57,7 +57,6 @@ class UpdateRequest extends FormRequest
];
return $this->getAllData($fields);
// return $return;
}
/**

View File

@ -71,17 +71,17 @@ class CreateRequest extends FormRequest
*/
public function rules(): array
{
$triggers = implode(',', array_keys(Webhook::getTriggersForValidation()));
$responses = implode(',', array_keys(Webhook::getResponsesForValidation()));
$deliveries = implode(',', array_keys(Webhook::getDeliveriesForValidation()));
$triggers = implode(',', array_keys(Webhook::getTriggersForValidation()));
$responses = implode(',', array_keys(Webhook::getResponsesForValidation()));
$deliveries = implode(',', array_keys(Webhook::getDeliveriesForValidation()));
$validProtocols = config('firefly.valid_url_protocols');
return [
'title' => 'required|between:1,512|uniqueObjectForUser:webhooks,title',
'active' => [new IsBoolean()],
'trigger' => sprintf('required|in:%s', $triggers),
'response' => sprintf('required|in:%s', $responses),
'delivery' => sprintf('required|in:%s', $deliveries),
'url' => ['required', 'url', 'uniqueWebhook'],
'url' => ['required', sprintf('url:%s', $validProtocols), 'uniqueWebhook'],
];
}
}

View File

@ -81,10 +81,10 @@ class UpdateRequest extends FormRequest
*/
public function rules(): array
{
$triggers = implode(',', array_keys(Webhook::getTriggersForValidation()));
$responses = implode(',', array_keys(Webhook::getResponsesForValidation()));
$deliveries = implode(',', array_keys(Webhook::getDeliveriesForValidation()));
$triggers = implode(',', array_keys(Webhook::getTriggersForValidation()));
$responses = implode(',', array_keys(Webhook::getResponsesForValidation()));
$deliveries = implode(',', array_keys(Webhook::getDeliveriesForValidation()));
$validProtocols = config('firefly.valid_url_protocols');
/** @var Webhook $webhook */
$webhook = $this->route()->parameter('webhook');
@ -94,7 +94,7 @@ class UpdateRequest extends FormRequest
'trigger' => sprintf('in:%s', $triggers),
'response' => sprintf('in:%s', $responses),
'delivery' => sprintf('in:%s', $deliveries),
'url' => ['url', sprintf('uniqueExistingWebhook:%d', $webhook->id)],
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)],
];
}
}

View File

@ -32,7 +32,6 @@ use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter;
use http\Env\Response;
use Illuminate\Http\JsonResponse;
/**

View File

@ -32,13 +32,12 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Collection;

View File

@ -33,7 +33,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;

View File

@ -31,6 +31,8 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
/**
* Show = show a single account.
* Index = show all accounts
* Class ShowController
*/
class ShowController extends Controller

View File

@ -0,0 +1,87 @@
<?php
/*
* ShowController.php
* Copyright (c) 2023 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\Api\V2\Controllers\Model\Bill;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\UserGroups\Bill\BillRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\BillTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* Class ShowController
*/
class IndexController extends Controller
{
use ValidatesUserGroupTrait;
private BillRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(BillRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) {
$this->repository->setUserGroup($userGroup);
}
return $next($request);
}
);
}
/**
* @param Request $request
*
* TODO see autocomplete/accountcontroller for list.
*
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$this->repository->correctOrder();
$bills = $this->repository->getBills();
$pageSize = $this->parameters->get('limit');
$count = $bills->count();
$bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
$transformer = new BillTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList('subscriptions', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@ -30,7 +30,6 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Bill;
use FireflyIII\Repositories\UserGroups\Bill\BillRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\AccountTransformer;
use FireflyIII\Transformers\V2\BillTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
@ -63,29 +62,6 @@ class ShowController extends Controller
);
}
/**
* @param Request $request
*
* TODO see autocomplete/accountcontroller for list.
*
* @return JsonResponse
*/
public function index(Request $request): JsonResponse
{
$this->repository->correctOrder();
$bills = $this->repository->getBills();
$pageSize = $this->parameters->get('limit');
$count = $bills->count();
$bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
$transformer = new BillTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList('subscriptions', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE);
}
/**
* TODO this endpoint is not documented
*/

View File

@ -26,7 +26,6 @@ namespace FireflyIII\Api\V2\Controllers\Model\Bill;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\UserGroups\Bill\BillRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use Illuminate\Http\JsonResponse;

View File

@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Budget;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Transformers\V2\BudgetTransformer;
use Illuminate\Http\JsonResponse;
@ -61,7 +62,7 @@ class ListController extends Controller
public function index(Request $request): JsonResponse
{
echo 'this needs move to Administration';
exit;
throw new FireflyException('Needs migration to IndexController');
$collection = $this->repository->getActiveBudgets();
$total = $collection->count();
$collection->slice($this->pageXSize * $this->parameters->get('page'), $this->pXageSize);

View File

@ -65,6 +65,7 @@ class ShowController extends Controller
*/
public function budgeted(DateRequest $request, Budget $budget): JsonResponse
{
throw new FireflyException('Needs refactoring, uses deprecated method.');
$data = $request->getAll();
$result = $this->repository->budgetedInPeriodForBudget($budget, $data['start'], $data['end']);
$converted = $this->cerSum(array_values($result));
@ -79,6 +80,7 @@ class ShowController extends Controller
*/
public function spent(DateRequest $request, Budget $budget): JsonResponse
{
throw new FireflyException('Needs refactoring, uses deprecated method.');
$data = $request->getAll();
$result = $this->repository->spentInPeriodForBudget($budget, $data['start'], $data['end']);
$converted = $this->cerSum(array_values($result));

View File

@ -65,6 +65,7 @@ class SumController extends Controller
*/
public function budgeted(DateRequest $request): JsonResponse
{
throw new FireflyException('Needs refactoring, uses deprecated method.');
$data = $request->getAll();
$result = $this->repository->budgetedInPeriod($data['start'], $data['end']);
$converted = $this->cerSum(array_values($result));
@ -82,6 +83,7 @@ class SumController extends Controller
*/
public function spent(DateRequest $request): JsonResponse
{
throw new FireflyException('Needs refactoring, uses deprecated method.');
$data = $request->getAll();
$result = $this->repository->spentInPeriod($data['start'], $data['end']);
$converted = $this->cerSum(array_values($result));

View File

@ -26,6 +26,7 @@ namespace FireflyIII\Api\V2\Controllers\Model\BudgetLimit;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Generic\DateRequest;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Transformers\V2\BudgetLimitTransformer;
@ -57,6 +58,7 @@ class ListController extends Controller
*/
public function index(DateRequest $request, Budget $budget): JsonResponse
{
throw new FireflyException('Needs refactoring, move to IndexController.');
$pageSize = $this->parameters->get('limit');
$dates = $request->getAll();
$collection = $this->repository->getBudgetLimits($budget, $dates['start'], $dates['end']);
@ -67,7 +69,7 @@ class ListController extends Controller
$transformer = new BudgetLimitTransformer();
return response()
->api($this->jsonApiList('budget_limits', $paginator, $transformer))
->api($this->jsonApiList('budget-limits', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@ -0,0 +1,74 @@
<?php
/*
* IndexController.php
* Copyright (c) 2023 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\Api\V2\Controllers\Model\Currency;
use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Transformers\V2\CurrencyTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator;
/**
* Class IndexController
*/
class IndexController extends Controller
{
private CurrencyRepositoryInterface $repository;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(CurrencyRepositoryInterface::class);
return $next($request);
}
);
}
/**
* TODO This endpoint is not yet documented.
*
* Display a listing of the resource.
*
* @return JsonResponse
*/
public function index(): JsonResponse
{
$bills = $this->repository->getAll();
$pageSize = $this->parameters->get('limit');
$count = $bills->count();
$bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
$paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page'));
$transformer = new CurrencyTransformer();
$transformer->setParameters($this->parameters); // give params to transformer
return response()
->json($this->jsonApiList('currencies', $paginator, $transformer))
->header('Content-Type', self::CONTENT_TYPE);
}
}

View File

@ -37,7 +37,7 @@ use Illuminate\Pagination\LengthAwarePaginator;
/**
* Class ShowController
*/
class ShowController extends Controller
class IndexController extends Controller
{
use ValidatesUserGroupTrait;

View File

@ -30,7 +30,6 @@ use FireflyIII\Api\V2\Request\Model\Transaction\StoreRequest;
use FireflyIII\Events\StoredTransactionGroup;
use FireflyIII\Exceptions\DuplicateTransactionException;
use FireflyIII\Exceptions\FireflyException;
use Illuminate\Validation\ValidationException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Rules\IsDuplicateTransaction;
@ -38,6 +37,7 @@ use FireflyIII\Transformers\V2\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
/**
* Class StoreController

View File

@ -41,7 +41,7 @@ use FireflyIII\Repositories\UserGroups\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\User;

View File

@ -28,9 +28,7 @@ use FireflyIII\Models\AccountType;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use FireflyIII\User;
use FireflyIII\Validation\Administration\ValidatesAdministrationAccess;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Validator;
/**
* Class AutocompleteRequest

View File

@ -57,6 +57,7 @@ class StoreRequest extends FormRequest
use GroupValidation;
use CurrencyValidation;
use AppendsLocationData;
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
/**

View File

@ -37,6 +37,7 @@ class StoreRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL];
/**

View File

@ -37,6 +37,7 @@ class UpdateMembershipRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL];
/**

View File

@ -38,6 +38,7 @@ class UpdateRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
protected array $acceptedRoles = [UserRoleEnum::OWNER, UserRoleEnum::FULL];
/**

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use Artisan;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
use Schema;

View File

@ -162,6 +162,6 @@ class CorrectOpeningBalanceCurrencies extends Command
$repos = app(AccountRepositoryInterface::class);
$repos->setUser($account->user);
return $repos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUser($account->user);
return $repos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrencyByUserGroup($account->userGroup);
}
}

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Integrity;
use Artisan;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
use Schema;

View File

@ -83,6 +83,7 @@ class CreateDatabase extends Command
$pdo = new PDO($dsn, env('DB_USERNAME'), env('DB_PASSWORD'), $options);
} catch (PDOException $e) {
$this->friendlyError(sprintf('Error when connecting to DB: %s', $e->getMessage()));
return 1;
}
// only continue when no error.

View File

@ -34,7 +34,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
@ -129,20 +128,7 @@ class AccountCurrencies extends Command
$accounts = $this->accountRepos->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
// get user's currency preference:
$defaultCurrencyCode = app('preferences')->getForUser($user, 'currencyPreference', $systemCurrencyCode)->data;
if (!is_string($defaultCurrencyCode)) {
$defaultCurrencyCode = $systemCurrencyCode;
}
/** @var TransactionCurrency|null $defaultCurrency */
$defaultCurrency = TransactionCurrency::where('code', $defaultCurrencyCode)->first();
if (null === $defaultCurrency) {
Log::error(sprintf('Users currency pref "%s" does not exist!', $defaultCurrencyCode));
$this->friendlyError(sprintf('User has a preference for "%s", but this currency does not exist.', $defaultCurrencyCode));
return;
}
$defaultCurrency = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup);
/** @var Account $account */
foreach ($accounts as $account) {

View File

@ -77,7 +77,7 @@ class BudgetLimitCurrency extends Command
if (null !== $budget) {
$user = $budget->user;
if (null !== $user) {
$currency = app('amount')->getDefaultCurrencyByUser($user);
$currency = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup);
$budgetLimit->transaction_currency_id = $currency->id;
$budgetLimit->save();
$this->friendlyInfo(

View File

@ -31,7 +31,6 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalCLIRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Console\Command;
@ -52,7 +51,6 @@ class OtherCurrenciesCorrections extends Command
private AccountRepositoryInterface $accountRepos;
private JournalCLIRepositoryInterface $cliRepos;
private int $count;
private CurrencyRepositoryInterface $currencyRepos;
private JournalRepositoryInterface $journalRepos;
/**
@ -93,7 +91,6 @@ class OtherCurrenciesCorrections extends Command
$this->count = 0;
$this->accountCurrencies = [];
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
$this->journalRepos = app(JournalRepositoryInterface::class);
$this->cliRepos = app(JournalCLIRepositoryInterface::class);
}
@ -138,7 +135,6 @@ class OtherCurrenciesCorrections extends Command
{
$this->accountRepos->setUser($journal->user);
$this->journalRepos->setUser($journal->user);
$this->currencyRepos->setUser($journal->user);
$this->cliRepos->setUser($journal->user);
$leadTransaction = $this->getLeadTransaction($journal);

View File

@ -0,0 +1,175 @@
<?php
/*
* UpgradeCurrencyPreferences.php
* Copyright (c) 2023 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\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\Preference;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\UserGroup;
use FireflyIII\User;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
/**
* Class UpgradeCurrencyPreferences
* TODO DONT FORGET TO ADD THIS TO THE DOCKER BUILD
*/
class UpgradeCurrencyPreferences extends Command
{
use ShowsFriendlyMessages;
public const CONFIG_NAME = '610_upgrade_currency_prefs';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Upgrade user currency preferences';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:upgrade-currency-preferences {--F|force : Force the execution of this command.}';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
if ($this->isExecuted() && true !== $this->option('force')) {
$this->friendlyInfo('This command has already been executed.');
return 0;
}
$this->runUpgrade();
$this->friendlyPositive('Currency preferences migrated.');
//$this->markAsExecuted();
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;
}
private function runUpgrade(): void
{
$groups = UserGroup::get();
/** @var UserGroup $group */
foreach ($groups as $group) {
$this->upgradeGroupPreferences($group);
}
$users = User::get();
/** @var User $user */
foreach ($users as $user) {
$this->upgradeUserPreferences($user);
}
}
/**
* @param UserGroup $group
*
* @return void
*/
private function upgradeGroupPreferences(UserGroup $group)
{
$currencies = TransactionCurrency::get();
$enabled = new Collection();
/** @var TransactionCurrency $currency */
foreach ($currencies as $currency) {
if ($currency->enabled) {
$enabled->push($currency);
}
}
$group->currencies()->sync($enabled->pluck('id')->toArray());
}
/**
* @param User $user
*
* @return void
*/
private function upgradeUserPreferences(User $user): void
{
$currencies = TransactionCurrency::get();
$enabled = new Collection();
/** @var TransactionCurrency $currency */
foreach ($currencies as $currency) {
if ($currency->enabled) {
$enabled->push($currency);
}
}
$user->currencies()->sync($enabled->pluck('id')->toArray());
// set the default currency for the user and for the group:
$preference = $this->getPreference($user);
$defaultCurrency = TransactionCurrency::where('code', $preference)->first();
if (null === $currency) {
// get EUR
$defaultCurrency = TransactionCurrency::where('code', 'EUR')->first();
}
$user->currencies()->updateExistingPivot($defaultCurrency->id, ['user_default' => true]);
$user->userGroup->currencies()->updateExistingPivot($defaultCurrency->id, ['group_default' => true]);
}
/**
* @param User $user
*
* @return string
*/
private function getPreference(User $user): string
{
$preference = Preference::where('user_id', $user->id)->where('name', 'currencyPreference')->first(['id', 'user_id', 'name', 'data', 'updated_at', 'created_at']);
if (null !== $preference) {
return (string)$preference->data;
}
return 'EUR';
}
/**
*
*/
private function markAsExecuted(): void
{
app('fireflyconfig')->set(self::CONFIG_NAME, true);
}
}

View File

@ -25,7 +25,6 @@ namespace FireflyIII\Console\Commands\Upgrade;
set_time_limit(0);
use Artisan;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use Illuminate\Console\Command;
@ -72,6 +71,7 @@ class UpgradeDatabase extends Command
// also just in case, some integrity commands:
'firefly-iii:create-group-memberships',
'firefly-iii:upgrade-group-information',
'firefly-iii:upgrade-currency-preferences',
];
$args = [];
if ($this->option('force')) {

View File

@ -10,6 +10,7 @@ use Illuminate\Console\Command;
*/
class UpgradeSkeleton extends Command
{
use ShowsFriendlyMessages;
public const CONFIG_NAME = '480_some_name';
/**
* The console command description.

View File

@ -26,7 +26,6 @@ namespace FireflyIII\Factory;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use Illuminate\Support\Facades\Log;
/**
* Class AccountMetaFactory

View File

@ -55,7 +55,7 @@ class BillFactory
Log::debug(sprintf('Now in %s', __METHOD__), $data);
$factory = app(TransactionCurrencyFactory::class);
$currency = $factory->find((int)($data['currency_id'] ?? null), (string)($data['currency_code'] ?? null)) ??
app('amount')->getDefaultCurrencyByUser($this->user);
app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
try {
$skip = array_key_exists('skip', $data) ? $data['skip'] : 0;

View File

@ -45,7 +45,6 @@ class TransactionCurrencyFactory
$data['symbol'] = e($data['symbol']);
$data['name'] = e($data['name']);
$data['decimal_places'] = (int)$data['decimal_places'];
$data['enabled'] = (bool)$data['enabled'];
// if the code already exists (deleted)
// force delete it and then create the transaction:
$count = TransactionCurrency::withTrashed()->whereCode($data['code'])->count();
@ -63,7 +62,7 @@ class TransactionCurrencyFactory
'code' => $data['code'],
'symbol' => $data['symbol'],
'decimal_places' => $data['decimal_places'],
'enabled' => $data['enabled'],
'enabled' => false,
]
);
} catch (QueryException $e) {

View File

@ -39,9 +39,9 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\JournalDestroyService;
use FireflyIII\Services\Internal\Support\JournalServiceTrait;
use FireflyIII\Support\NullArrayObject;
@ -479,7 +479,7 @@ class TransactionJournalFactory
$preference = $this->accountRepository->getAccountCurrency($account);
if (null === $preference && null === $currency) {
// return user's default:
return app('amount')->getDefaultCurrencyByUser($this->user);
return app('amount')->getDefaultCurrencyByUserGroup($this->user->userGroup);
}
$result = ($preference ?? $currency) ?? app('amount')->getSystemCurrency();
Log::debug(sprintf('Currency is now #%d (%s) because of account #%d (%s)', $result->id, $result->code, $account->id, $account->name));

View File

@ -34,29 +34,29 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
trait CollectorProperties
{
public const TEST = 'Test';
private bool $expandGroupSearch;
private array $fields;
private bool $hasAccountInfo;
private bool $hasBillInformation;
private bool $hasBudgetInformation;
private bool $hasCatInformation;
private bool $hasJoinedAttTables;
private bool $hasJoinedMetaTables;
private bool $hasJoinedTagTables;
private bool $hasNotesInformation;
private array $integerFields;
private ?int $limit;
private ?int $page;
private array $postFilters;
private bool $expandGroupSearch;
private array $fields;
private bool $hasAccountInfo;
private bool $hasBillInformation;
private bool $hasBudgetInformation;
private bool $hasCatInformation;
private bool $hasJoinedAttTables;
private bool $hasJoinedMetaTables;
private bool $hasJoinedTagTables;
private bool $hasNotesInformation;
private array $integerFields;
private ?int $limit;
private ?int $page;
private array $postFilters;
private HasMany $query;
private array $stringFields;
private array $stringFields;
/*
* This array is used to collect ALL tags the user may search for (using 'setTags').
* This way the user can call 'setTags' multiple times and get a joined result.
*
*/
private array $tags;
private int $total;
private ?User $user;
private array $tags;
private int $total;
private ?User $user;
private ?UserGroup $userGroup;
}

View File

@ -29,8 +29,8 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface as AdminAccountRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use FireflyIII\User;

View File

@ -29,8 +29,8 @@ use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use Illuminate\Support\Collection;
/**

View File

@ -32,7 +32,7 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Controllers\DateCalculation;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;

View File

@ -34,7 +34,7 @@ use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Controllers\DateCalculation;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;

View File

@ -33,7 +33,7 @@ use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use FireflyIII\Support\Http\Controllers\AugumentData;
use FireflyIII\Support\Http\Controllers\ChartGeneration;

View File

@ -1,435 +0,0 @@
<?php
/**
* CurrencyController.php
* Copyright (c) 2019 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\Http\Controllers;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Requests\CurrencyFormRequest;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
/**
* Class CurrencyController.
*/
class CurrencyController extends Controller
{
protected CurrencyRepositoryInterface $repository;
protected UserRepositoryInterface $userRepository;
/**
* CurrencyController constructor.
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.currencies'));
app('view')->share('mainTitleIcon', 'fa-usd');
$this->repository = app(CurrencyRepositoryInterface::class);
$this->userRepository = app(UserRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Create a currency.
*
* @param Request $request
*
* @return Factory|RedirectResponse|Redirector|View
*/
public function create(Request $request)
{
/** @var User $user */
$user = auth()->user();
if (!$this->userRepository->hasRole($user, 'owner')) {
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
return redirect(route('currencies.index'));
}
$subTitleIcon = 'fa-plus';
$subTitle = (string)trans('firefly.create_currency');
// put previous url in session if not redirect from store (not "create another").
if (true !== session('currencies.create.fromStore')) {
$this->rememberPreviousUrl('currencies.create.url');
}
$request->session()->forget('currencies.create.fromStore');
Log::channel('audit')->info('Create new currency.');
return view('currencies.create', compact('subTitleIcon', 'subTitle'));
}
/**
* Make currency the default currency.
*
* @param Request $request
*
* @return RedirectResponse|Redirector
* @throws FireflyException
*/
public function defaultCurrency(Request $request)
{
$currencyId = (int)$request->get('id');
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));
$this->repository->enable($currency);
$request->session()->flash('success', (string)trans('firefly.new_default_currency', ['name' => $currency->name]));
return redirect(route('currencies.index'));
}
}
return redirect(route('currencies.index'));
}
/**
* Deletes a currency.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return Factory|RedirectResponse|Redirector|View
*/
public function delete(Request $request, TransactionCurrency $currency)
{
/** @var User $user */
$user = auth()->user();
if (!$this->userRepository->hasRole($user, '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));
return redirect(route('currencies.index'));
}
if ($this->repository->currencyInUse($currency)) {
$location = $this->repository->currencyInUseAt($currency);
$message = (string)trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]);
$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));
return redirect(route('currencies.index'));
}
// put previous url in session
$this->rememberPreviousUrl('currencies.delete.url');
$subTitle = (string)trans('form.delete_currency', ['name' => $currency->name]);
Log::channel('audit')->info(sprintf('Visit page to delete currency %s.', $currency->code));
return view('currencies.delete', compact('currency', 'subTitle'));
}
/**
* Destroys a currency.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return RedirectResponse|Redirector
*/
public function destroy(Request $request, TransactionCurrency $currency)
{
/** @var User $user */
$user = auth()->user();
if (!$this->userRepository->hasRole($user, '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));
return redirect(route('currencies.index'));
}
if ($this->repository->currencyInUse($currency)) {
$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));
return redirect(route('currencies.index'));
}
if ($this->repository->isFallbackCurrency($currency)) {
$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));
return redirect(route('currencies.index'));
}
Log::channel('audit')->info(sprintf('Deleted currency %s.', $currency->code));
$this->repository->destroy($currency);
$request->session()->flash('success', (string)trans('firefly.deleted_currency', ['name' => $currency->name]));
return redirect($this->getPreviousUrl('currencies.delete.url'));
}
/**
* @param Request $request
*
* @return JsonResponse
* @throws FireflyException
*/
public function disableCurrency(Request $request): JsonResponse
{
$currencyId = (int)$request->get('id');
$currency = $this->repository->find($currencyId);
// valid currency?
if (null === $currency) {
return response()->json([]);
}
app('preferences')->mark();
// user must be "owner"
/** @var User $user */
$user = auth()->user();
if (!$this->userRepository->hasRole($user, '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));
return response()->json([]);
}
// currency cannot be in use.
if ($this->repository->currencyInUse($currency)) {
$location = $this->repository->currencyInUseAt($currency);
$message = (string)trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]);
$request->session()->flash('error', $message);
Log::channel('audit')->info(sprintf('Tried to disable currency %s but is in use.', $currency->code));
return response()->json([]);
}
// currency disabled!
$this->repository->disable($currency);
Log::channel('audit')->info(sprintf('Disabled currency %s.', $currency->code));
$this->repository->ensureMinimalEnabledCurrencies();
// extra warning
if ('EUR' === $currency->code) {
session()->flash('warning', (string)trans('firefly.disable_EUR_side_effects'));
}
session()->flash('success', (string)trans('firefly.currency_is_now_disabled', ['name' => $currency->name]));
return response()->json([]);
}
/**
* Edit a currency.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return Factory|RedirectResponse|Redirector|View
*/
public function edit(Request $request, TransactionCurrency $currency)
{
/** @var User $user */
$user = auth()->user();
if (!$this->userRepository->hasRole($user, '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));
return redirect(route('currencies.index'));
}
$subTitleIcon = 'fa-pencil';
$subTitle = (string)trans('breadcrumbs.edit_currency', ['name' => $currency->name]);
$currency->symbol = htmlentities($currency->symbol);
// code to handle active-checkboxes
$hasOldInput = null !== $request->old('_token');
$preFilled = [
'enabled' => $hasOldInput ? (bool)$request->old('enabled') : $currency->enabled,
];
$request->session()->flash('preFilled', $preFilled);
Log::channel('audit')->info('Edit currency.', $currency->toArray());
// put previous url in session if not redirect from store (not "return_to_edit").
if (true !== session('currencies.edit.fromUpdate')) {
$this->rememberPreviousUrl('currencies.edit.url');
}
$request->session()->forget('currencies.edit.fromUpdate');
return view('currencies.edit', compact('currency', 'subTitle', 'subTitleIcon'));
}
/**
* @param Request $request
*
* @return JsonResponse
*/
public function enableCurrency(Request $request): JsonResponse
{
$currencyId = (int)$request->get('id');
if ($currencyId > 0) {
// valid currency?
$currency = $this->repository->find($currencyId);
if (null !== $currency) {
app('preferences')->mark();
$this->repository->enable($currency);
session()->flash('success', (string)trans('firefly.currency_is_now_enabled', ['name' => $currency->name]));
Log::channel('audit')->info(sprintf('Enabled currency %s.', $currency->code));
}
}
return response()->json([]);
}
/**
* Show overview of currencies.
*
* @param Request $request
*
* @return Factory|View
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function index(Request $request)
{
/** @var User $user */
$user = auth()->user();
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
$collection = $this->repository->getAll();
$total = $collection->count();
$collection = $collection->slice(($page - 1) * $pageSize, $pageSize);
$currencies = new LengthAwarePaginator($collection, $total, $pageSize, $page);
$currencies->setPath(route('currencies.index'));
$defaultCurrency = $this->repository->getCurrencyByPreference(app('preferences')->get('currencyPreference', config('firefly.default_currency', 'EUR')));
$isOwner = true;
if (!$this->userRepository->hasRole($user, 'owner')) {
$request->session()->flash('info', (string)trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')]));
$isOwner = false;
}
return view('currencies.index', compact('currencies', 'defaultCurrency', 'isOwner'));
}
/**
* Store new currency.
*
* @param CurrencyFormRequest $request
*
* @return $this|RedirectResponse|Redirector
*/
public function store(CurrencyFormRequest $request)
{
/** @var User $user */
$user = auth()->user();
$data = $request->getCurrencyData();
if (!$this->userRepository->hasRole($user, 'owner')) {
Log::error('User ' . auth()->user()->id . ' is not admin, but tried to store a currency.');
Log::channel('audit')->info('Tried to create (POST) currency without admin rights.', $data);
return redirect($this->getPreviousUrl('currencies.create.url'));
}
$data['enabled'] = true;
try {
$currency = $this->repository->store($data);
} catch (FireflyException $e) {
Log::error($e->getMessage());
Log::channel('audit')->info('Could not store (POST) currency without admin rights.', $data);
$request->session()->flash('error', (string)trans('firefly.could_not_store_currency'));
$currency = null;
}
$redirect = redirect($this->getPreviousUrl('currencies.create.url'));
if (null !== $currency) {
$request->session()->flash('success', (string)trans('firefly.created_currency', ['name' => $currency->name]));
Log::channel('audit')->info('Created (POST) currency.', $data);
if (1 === (int)$request->get('create_another')) {
$request->session()->put('currencies.create.fromStore', true);
$redirect = redirect(route('currencies.create'))->withInput();
}
}
return $redirect;
}
/**
* Updates a currency.
*
* @param CurrencyFormRequest $request
* @param TransactionCurrency $currency
*
* @return RedirectResponse|Redirector
*/
public function update(CurrencyFormRequest $request, TransactionCurrency $currency)
{
/** @var User $user */
$user = auth()->user();
$data = $request->getCurrencyData();
if (false === $data['enabled'] && $this->repository->currencyInUse($currency)) {
$data['enabled'] = true;
}
if (!$this->userRepository->hasRole($user, '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);
return redirect(route('currencies.index'));
}
$currency = $this->repository->update($currency, $data);
Log::channel('audit')->info('Updated (POST) currency.', $data);
$request->session()->flash('success', (string)trans('firefly.updated_currency', ['name' => $currency->name]));
app('preferences')->mark();
if (1 === (int)$request->get('return_to_edit')) {
$request->session()->put('currencies.edit.fromUpdate', true);
return redirect(route('currencies.edit', [$currency->id]));
}
return redirect($this->getPreviousUrl('currencies.edit.url'));
}
}

View File

@ -118,9 +118,6 @@ class HomeController extends Controller
*/
public function index(AccountRepositoryInterface $repository): mixed
{
if ('v3' === config('firefly.layout')) {
return view('pwa');
}
$types = config('firefly.accountTypesByIdentifier.asset');
$count = $repository->count($types);
Log::channel('audit')->info('User visits homepage.');

View File

@ -29,7 +29,7 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Controllers\GetConfigurationData;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
@ -56,13 +56,11 @@ class JavascriptController extends Controller
*/
public function accounts(AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepository): Response
{
$accounts = $repository->getAccountsByType(
$accounts = $repository->getAccountsByType(
[AccountType::DEFAULT, AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD]
);
$preference = app('preferences')->get('currencyPreference', config('firefly.default_currency', 'EUR'));
$default = $currencyRepository->findByCodeNull((string)$preference->data);
$data = ['accounts' => []];
$default = app('amount')->getDefaultCurrency();
$data = ['accounts' => []];
/** @var Account $account */
foreach ($accounts as $account) {

View File

@ -35,7 +35,7 @@ use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Repositories\Budget\OperationsRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;

View File

@ -27,7 +27,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Requests\NewUserFormRequest;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Controllers\CreateStuff;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
@ -41,8 +41,7 @@ class NewUserController extends Controller
{
use CreateStuff;
/** @var AccountRepositoryInterface The account repository */
private $repository;
private AccountRepositoryInterface $repository;
/**
* NewUserController constructor.
@ -114,7 +113,7 @@ class NewUserController extends Controller
$this->createCashWalletAccount($currency, $language); // create cash wallet account
// store currency preference:
app('preferences')->set('currencyPreference', $currency->code);
$currencyRepository->makeDefault($currency);
// store frontpage preferences:
$accounts = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();

View File

@ -89,10 +89,10 @@ class CreateController extends Controller
session()->flash('success', trans('firefly.stored_journal', ['description' => $title]));
session()->flash('success_url', $link);
if('edit' === $request->get('redirect')) {
if ('edit' === $request->get('redirect')) {
return response()->json(['redirect' => route('transactions.edit', [$newGroup->id])]);
}
return response()->json(['redirect' => route('transactions.show', [$newGroup->id])]);
}
}

View File

@ -25,8 +25,11 @@ namespace FireflyIII\Http\Controllers\Transaction;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Routing\Redirector;
use Illuminate\View\View;
@ -36,8 +39,10 @@ use Illuminate\View\View;
*/
class EditController extends Controller
{
private JournalRepositoryInterface $repository;
/**
* EditController constructor.
* IndexController constructor.
*
*/
@ -45,12 +50,14 @@ class EditController extends Controller
{
parent::__construct();
// some useful repositories:
// translations:
$this->middleware(
static function ($request, $next) {
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.transactions'));
app('view')->share('mainTitleIcon', 'fa-exchange');
$this->repository = app(JournalRepositoryInterface::class);
return $next($request);
}
);
@ -98,4 +105,15 @@ class EditController extends Controller
)
);
}
/**
* @param TransactionJournal $journal
*
* @return JsonResponse
*/
public function unreconcile(TransactionJournal $journal): JsonResponse
{
$this->repository->unreconcileById($journal->id);
return response()->json([], 204);
}
}

View File

@ -0,0 +1,143 @@
<?php
/*
* CreateController.php
* Copyright (c) 2023 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\Http\Controllers\TransactionCurrency;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\CurrencyFormRequest;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
/**
* Class CreateController
*/
class CreateController extends Controller
{
protected CurrencyRepositoryInterface $repository;
protected UserRepositoryInterface $userRepository;
/**
* CurrencyController constructor.
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.currencies'));
app('view')->share('mainTitleIcon', 'fa-usd');
$this->repository = app(CurrencyRepositoryInterface::class);
$this->userRepository = app(UserRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Create a currency.
*
* @param Request $request
*
* @return Factory|RedirectResponse|Redirector|View
*/
public function create(Request $request)
{
/** @var User $user */
$user = auth()->user();
if (!$this->userRepository->hasRole($user, 'owner')) {
$request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))]));
return redirect(route('currencies.index'));
}
$subTitleIcon = 'fa-plus';
$subTitle = (string)trans('firefly.create_currency');
// put previous url in session if not redirect from store (not "create another").
if (true !== session('currencies.create.fromStore')) {
$this->rememberPreviousUrl('currencies.create.url');
}
$request->session()->forget('currencies.create.fromStore');
Log::channel('audit')->info('Create new currency.');
return view('currencies.create', compact('subTitleIcon', 'subTitle'));
}
/**
* Store new currency.
*
* @param CurrencyFormRequest $request
*
* @return $this|RedirectResponse|Redirector
*/
public function store(CurrencyFormRequest $request)
{
/** @var User $user */
$user = auth()->user();
$data = $request->getCurrencyData();
if (!$this->userRepository->hasRole($user, 'owner')) {
Log::error('User ' . auth()->user()->id . ' is not admin, but tried to store a currency.');
Log::channel('audit')->info('Tried to create (POST) currency without admin rights.', $data);
return redirect($this->getPreviousUrl('currencies.create.url'))->withInput();
}
$data['enabled'] = true;
try {
$currency = $this->repository->store($data);
} catch (FireflyException $e) {
Log::error($e->getMessage());
Log::channel('audit')->info('Could not store (POST) currency without admin rights.', $data);
$request->session()->flash('error', (string)trans('firefly.could_not_store_currency'));
$currency = null;
}
$redirect = redirect($this->getPreviousUrl('currencies.create.url'));
if (null !== $currency) {
$request->session()->flash('success', (string)trans('firefly.created_currency', ['name' => $currency->name]));
Log::channel('audit')->info('Created (POST) currency.', $data);
if (1 === (int)$request->get('create_another')) {
$request->session()->put('currencies.create.fromStore', true);
$redirect = redirect(route('currencies.create'))->withInput();
}
}
return $redirect;
}
}

View File

@ -0,0 +1,147 @@
<?php
/*
* DeleteController.php
* Copyright (c) 2023 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\Http\Controllers\TransactionCurrency;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
/**
* Class DeleteController
*/
class DeleteController extends Controller
{
protected CurrencyRepositoryInterface $repository;
protected UserRepositoryInterface $userRepository;
/**
* CurrencyController constructor.
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.currencies'));
app('view')->share('mainTitleIcon', 'fa-usd');
$this->repository = app(CurrencyRepositoryInterface::class);
$this->userRepository = app(UserRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Deletes a currency.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return Factory|RedirectResponse|Redirector|View
*/
public function delete(Request $request, TransactionCurrency $currency)
{
/** @var User $user */
$user = auth()->user();
if (!$this->userRepository->hasRole($user, '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));
return redirect(route('currencies.index'));
}
if ($this->repository->currencyInUse($currency)) {
$location = $this->repository->currencyInUseAt($currency);
$message = (string)trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]);
$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));
return redirect(route('currencies.index'));
}
// put previous url in session
$this->rememberPreviousUrl('currencies.delete.url');
$subTitle = (string)trans('form.delete_currency', ['name' => $currency->name]);
Log::channel('audit')->info(sprintf('Visit page to delete currency %s.', $currency->code));
return view('currencies.delete', compact('currency', 'subTitle'));
}
/**
* Destroys a currency.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return RedirectResponse|Redirector
*/
public function destroy(Request $request, TransactionCurrency $currency)
{
/** @var User $user */
$user = auth()->user();
if (!$this->userRepository->hasRole($user, '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));
return redirect(route('currencies.index'));
}
if ($this->repository->currencyInUse($currency)) {
$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));
return redirect(route('currencies.index'));
}
if ($this->repository->isFallbackCurrency($currency)) {
$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));
return redirect(route('currencies.index'));
}
Log::channel('audit')->info(sprintf('Deleted currency %s.', $currency->code));
$this->repository->destroy($currency);
$request->session()->flash('success', (string)trans('firefly.deleted_currency', ['name' => $currency->name]));
return redirect($this->getPreviousUrl('currencies.delete.url'));
}
}

View File

@ -0,0 +1,151 @@
<?php
/*
* EditController.php
* Copyright (c) 2023 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\Http\Controllers\TransactionCurrency;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\CurrencyFormRequest;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;
class EditController extends Controller
{
protected CurrencyRepositoryInterface $repository;
protected UserRepositoryInterface $userRepository;
/**
* CurrencyController constructor.
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.currencies'));
app('view')->share('mainTitleIcon', 'fa-usd');
$this->repository = app(CurrencyRepositoryInterface::class);
$this->userRepository = app(UserRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Edit a currency.
*
* @param Request $request
* @param TransactionCurrency $currency
*
* @return Factory|RedirectResponse|Redirector|View
*/
public function edit(Request $request, TransactionCurrency $currency)
{
/** @var User $user */
$user = auth()->user();
if (!$this->userRepository->hasRole($user, '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));
return redirect(route('currencies.index'));
}
$subTitleIcon = 'fa-pencil';
$subTitle = (string)trans('breadcrumbs.edit_currency', ['name' => $currency->name]);
$currency->symbol = htmlentities($currency->symbol);
// is currently enabled (for this user?)
$userCurrencies = $this->repository->get()->pluck('id')->toArray();
$enabled = in_array($currency->id, $userCurrencies, true);
// code to handle active-checkboxes
$hasOldInput = null !== $request->old('_token');
$preFilled = [
'enabled' => $hasOldInput ? (bool)$request->old('enabled') : $enabled,
];
$request->session()->flash('preFilled', $preFilled);
Log::channel('audit')->info('Edit currency.', $currency->toArray());
// put previous url in session if not redirect from store (not "return_to_edit").
if (true !== session('currencies.edit.fromUpdate')) {
$this->rememberPreviousUrl('currencies.edit.url');
}
$request->session()->forget('currencies.edit.fromUpdate');
return view('currencies.edit', compact('currency', 'subTitle', 'subTitleIcon'));
}
/**
* Updates a currency.
*
* @param CurrencyFormRequest $request
* @param TransactionCurrency $currency
*
* @return RedirectResponse|Redirector
*/
public function update(CurrencyFormRequest $request, TransactionCurrency $currency)
{
/** @var User $user */
$user = auth()->user();
$data = $request->getCurrencyData();
if (false === $data['enabled'] && $this->repository->currencyInUse($currency)) {
$data['enabled'] = true;
}
if (!$this->userRepository->hasRole($user, '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);
return redirect(route('currencies.index'));
}
$currency = $this->repository->update($currency, $data);
Log::channel('audit')->info('Updated (POST) currency.', $data);
$request->session()->flash('success', (string)trans('firefly.updated_currency', ['name' => $currency->name]));
app('preferences')->mark();
if (1 === (int)$request->get('return_to_edit')) {
$request->session()->put('currencies.edit.fromUpdate', true);
return redirect(route('currencies.edit', [$currency->id]));
}
return redirect($this->getPreviousUrl('currencies.edit.url'));
}
}

View File

@ -0,0 +1,105 @@
<?php
/*
* IndexController.php
* Copyright (c) 2023 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\Http\Controllers\TransactionCurrency;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\View\View;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class IndexController extends Controller
{
protected CurrencyRepositoryInterface $repository;
protected UserRepositoryInterface $userRepository;
/**
* CurrencyController constructor.
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.currencies'));
app('view')->share('mainTitleIcon', 'fa-usd');
$this->repository = app(CurrencyRepositoryInterface::class);
$this->userRepository = app(UserRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Show overview of currencies.
*
* @param Request $request
*
* @return Factory|View
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function index(Request $request)
{
/** @var User $user */
$user = auth()->user();
$page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page');
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
$collection = $this->repository->getAll();
$total = $collection->count();
$collection = $collection->slice(($page - 1) * $pageSize, $pageSize);
// order so default is on top:
$collection = $collection->sortBy(
function (TransactionCurrency $currency) {
$default = true === $currency->userDefault ? 0 : 1;
$enabled = true === $currency->userEnabled ? 0 : 1;
return sprintf('%s-%s-%s', $default, $enabled, $currency->code);
}
);
$currencies = new LengthAwarePaginator($collection, $total, $pageSize, $page);
$currencies->setPath(route('currencies.index'));
$isOwner = true;
if (!$this->userRepository->hasRole($user, 'owner')) {
$request->session()->flash('info', (string)trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')]));
$isOwner = false;
}
return view('currencies.index', compact('currencies', 'isOwner'));
}
}

View File

@ -26,6 +26,7 @@ namespace FireflyIII\Http\Middleware;
use Closure;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\Webhook;
@ -68,6 +69,10 @@ class InterestingMessage
Preferences::mark();
$this->handleWebhookMessage($request);
}
if ($this->currencyMessage($request)) {
Preferences::mark();
$this->handleCurrencyMessage($request);
}
return $next($request);
}
@ -221,10 +226,10 @@ class InterestingMessage
private function webhookMessage(Request $request): bool
{
// get parameters from request.
$billId = $request->get('webhook_id');
$message = $request->get('message');
$webhookId = $request->get('webhook_id');
$message = $request->get('message');
return null !== $billId && null !== $message;
return null !== $webhookId && null !== $message;
}
/**
@ -252,4 +257,51 @@ class InterestingMessage
session()->flash('success', (string)trans('firefly.stored_new_webhook', ['title' => $webhook->title]));
}
}
/**
* @param Request $request
*
* @return bool
*/
private function currencyMessage(Request $request): bool
{
// get parameters from request.
$code = $request->get('code');
$message = $request->get('message');
return null !== $code && null !== $message;
}
private function handleCurrencyMessage(Request $request): void
{
// params:
// get parameters from request.
$code = $request->get('code');
$message = $request->get('message');
/** @var TransactionCurrency $webhook */
$currency = TransactionCurrency::whereCode($code)->first();
if (null === $currency) {
return;
}
if ('enabled' === $message) {
session()->flash('success', (string)trans('firefly.currency_is_now_enabled', ['name' => $currency->name]));
}
if ('enable_failed' === $message) {
session()->flash('error', (string)trans('firefly.could_not_enable_currency', ['name' => $currency->name]));
}
if ('disabled' === $message) {
session()->flash('success', (string)trans('firefly.currency_is_now_disabled', ['name' => $currency->name]));
}
if ('disable_failed' === $message) {
session()->flash('error', (string)trans('firefly.could_not_disable_currency', ['name' => $currency->name]));
}
if ('default' === $message) {
session()->flash('success', (string)trans('firefly.new_default_currency', ['name' => $currency->name]));
}
if ('default_failed' === $message) {
session()->flash('error', (string)trans('firefly.default_currency_failed', ['name' => $currency->name]));
}
}
}

View File

@ -40,6 +40,7 @@ class AccountFormRequest extends FormRequest
use ConvertsDataTypes;
use AppendsLocationData;
use ChecksLogin;
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
/**

View File

@ -45,7 +45,7 @@ class MassEditJournalRequest extends FormRequest
// fixed
return [
'description.*' => 'required|min:1|max:255',
'description.*' => 'required|min:1|max:1024',
'source_id.*' => 'numeric|belongsToUser:accounts,id',
'destination_id.*' => 'numeric|belongsToUser:accounts,id',
'journals.*' => 'numeric|belongsToUser:transaction_journals,id',

View File

@ -84,7 +84,7 @@ class DownloadExchangeRates implements ShouldQueue
public function handle(): void
{
Log::debug('Now in handle()');
$currencies = $this->repository->get();
$currencies = $this->repository->getCompleteSet();
/** @var TransactionCurrency $currency */
foreach ($currencies as $currency) {

View File

@ -42,36 +42,36 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class Account
*
* @property int $id
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property int $user_id
* @property int $account_type_id
* @property string $name
* @property string|null $virtual_balance
* @property string|null $iban
* @property bool $active
* @property bool $encrypted
* @property int $order
* @property-read Collection|AccountMeta[] $accountMeta
* @property-read int|null $account_meta_count
* @property AccountType $accountType
* @property-read Collection|Attachment[] $attachments
* @property-read int|null $attachments_count
* @property-read string $account_number
* @property-read string $edit_name
* @property-read Collection|Location[] $locations
* @property-read int|null $locations_count
* @property-read Collection|Note[] $notes
* @property-read int|null $notes_count
* @property-read Collection|ObjectGroup[] $objectGroups
* @property-read int|null $object_groups_count
* @property-read Collection|PiggyBank[] $piggyBanks
* @property-read int|null $piggy_banks_count
* @property-read Collection|Transaction[] $transactions
* @property-read int|null $transactions_count
* @property-read User $user
* @property int $id
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property int $user_id
* @property int $account_type_id
* @property string $name
* @property string|null $virtual_balance
* @property string|null $iban
* @property bool $active
* @property bool $encrypted
* @property int $order
* @property-read Collection|AccountMeta[] $accountMeta
* @property-read int|null $account_meta_count
* @property AccountType $accountType
* @property-read Collection|Attachment[] $attachments
* @property-read int|null $attachments_count
* @property-read string $account_number
* @property-read string $edit_name
* @property-read Collection|Location[] $locations
* @property-read int|null $locations_count
* @property-read Collection|Note[] $notes
* @property-read int|null $notes_count
* @property-read Collection|ObjectGroup[] $objectGroups
* @property-read int|null $object_groups_count
* @property-read Collection|PiggyBank[] $piggyBanks
* @property-read int|null $piggy_banks_count
* @property-read Collection|Transaction[] $transactions
* @property-read int|null $transactions_count
* @property-read User $user
* @method static EloquentBuilder|Account accountTypeIn($types)
* @method static EloquentBuilder|Account newModelQuery()
* @method static EloquentBuilder|Account newQuery()
@ -91,18 +91,19 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static EloquentBuilder|Account whereVirtualBalance($value)
* @method static Builder|Account withTrashed()
* @method static Builder|Account withoutTrashed()
* @property Carbon $lastActivityDate
* @property string $startBalance
* @property string $endBalance
* @property string $difference
* @property string $interest
* @property string $interestPeriod
* @property string $accountTypeString
* @property Location $location
* @property string $liability_direction
* @property string $current_debt
* @property int|null $user_group_id
* @property Carbon $lastActivityDate
* @property string $startBalance
* @property string $endBalance
* @property string $difference
* @property string $interest
* @property string $interestPeriod
* @property string $accountTypeString
* @property Location $location
* @property string $liability_direction
* @property string $current_debt
* @property int|null $user_group_id
* @method static EloquentBuilder|Account whereUserGroupId($value)
* @property-read UserGroup|null $userGroup
* @mixin Eloquent
*/
class Account extends Model
@ -283,6 +284,14 @@ class Account extends Model
return $this->hasMany(Transaction::class);
}
/**
* @return BelongsTo
*/
public function userGroup(): BelongsTo
{
return $this->belongsTo(UserGroup::class);
}
/**
* Get the virtual balance
*

View File

@ -61,7 +61,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|ObjectGroup whereTitle($value)
* @method static Builder|ObjectGroup whereUpdatedAt($value)
* @method static Builder|ObjectGroup whereUserId($value)
* @property int|null $user_group_id
* @property int|null $user_group_id
* @method static Builder|ObjectGroup whereUserGroupId($value)
* @mixin Eloquent
*/

View File

@ -125,6 +125,14 @@ class Rule extends Model
throw new NotFoundHttpException();
}
/**
* @return BelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* @return HasMany
*/
@ -159,14 +167,6 @@ class Rule extends Model
$this->attributes['description'] = e($value);
}
/**
* @return BelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
/**
* @return BelongsTo
*/

View File

@ -24,8 +24,10 @@ declare(strict_types=1);
namespace FireflyIII\Models;
use Eloquent;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\Builder;
@ -35,21 +37,23 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* FireflyIII\Models\TransactionCurrency
*
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Carbon|null $deleted_at
* @property bool $enabled
* @property string $code
* @property string $name
* @property string $symbol
* @property int $decimal_places
* @property-read Collection|BudgetLimit[] $budgetLimits
* @property-read int|null $budget_limits_count
* @property-read Collection|TransactionJournal[] $transactionJournals
* @property-read int|null $transaction_journals_count
* @property-read Collection|Transaction[] $transactions
* @property-read int|null $transactions_count
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Carbon|null $deleted_at
* @property bool $enabled
* @property bool $userDefault
* @property bool $userEnabled
* @property string $code
* @property string $name
* @property string $symbol
* @property int $decimal_places
* @property-read Collection|BudgetLimit[] $budgetLimits
* @property-read int|null $budget_limits_count
* @property-read Collection|TransactionJournal[] $transactionJournals
* @property-read int|null $transaction_journals_count
* @property-read Collection|Transaction[] $transactions
* @property-read int|null $transactions_count
* @method static \Illuminate\Database\Eloquent\Builder|TransactionCurrency newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|TransactionCurrency newQuery()
* @method static Builder|TransactionCurrency onlyTrashed()
@ -65,6 +69,10 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static \Illuminate\Database\Eloquent\Builder|TransactionCurrency whereUpdatedAt($value)
* @method static Builder|TransactionCurrency withTrashed()
* @method static Builder|TransactionCurrency withoutTrashed()
* @property-read Collection<int, UserGroup> $userGroups
* @property-read int|null $user_groups_count
* @property-read Collection<int, User> $users
* @property-read int|null $users_count
* @mixin Eloquent
*/
class TransactionCurrency extends Model
@ -101,6 +109,7 @@ class TransactionCurrency extends Model
$currencyId = (int)$value;
$currency = self::find($currencyId);
if (null !== $currency) {
$currency->refreshForUser(auth()->user());
return $currency;
}
}
@ -115,6 +124,19 @@ class TransactionCurrency extends Model
return $this->hasMany(BudgetLimit::class);
}
/**
* @param User $user
*
* @return void
*/
public function refreshForUser(User $user)
{
$current = $user->userGroup->currencies()->where('transaction_currencies.id', $this->id)->first();
$default = app('amount')->getDefaultCurrencyByUserGroup($user->userGroup);
$this->userDefault = (int)$default->id === (int)$this->id;
$this->userEnabled = null !== $current;
}
/**
* @return HasMany
*/
@ -130,4 +152,24 @@ class TransactionCurrency extends Model
{
return $this->hasMany(Transaction::class);
}
/**
* Link to user groups
*
* @return BelongsToMany
*/
public function userGroups(): BelongsToMany
{
return $this->belongsToMany(UserGroup::class)->withTimestamps()->withPivot('group_default');
}
/**
* Link to users
*
* @return BelongsToMany
*/
public function users(): BelongsToMany
{
return $this->belongsToMany(User::class)->withTimestamps()->withPivot('user_default');
}
}

View File

@ -41,50 +41,50 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* FireflyIII\Models\TransactionJournal
*
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Carbon|null $deleted_at
* @property int $user_id
* @property int $transaction_type_id
* @property int|null $transaction_group_id
* @property int|null $bill_id
* @property int|null $transaction_currency_id
* @property string $description
* @property Carbon $date
* @property Carbon|null $interest_date
* @property Carbon|null $book_date
* @property Carbon|null $process_date
* @property int $order
* @property int $tag_count
* @property string $transaction_type_type
* @property bool $encrypted
* @property bool $completed
* @property-read Collection|Attachment[] $attachments
* @property-read int|null $attachments_count
* @property-read Bill|null $bill
* @property-read Collection|Budget[] $budgets
* @property-read int|null $budgets_count
* @property-read Collection|Category[] $categories
* @property-read int|null $categories_count
* @property-read Collection|TransactionJournalLink[] $destJournalLinks
* @property-read int|null $dest_journal_links_count
* @property-read Collection|Note[] $notes
* @property-read int|null $notes_count
* @property-read Collection|PiggyBankEvent[] $piggyBankEvents
* @property-read int|null $piggy_bank_events_count
* @property-read Collection|TransactionJournalLink[] $sourceJournalLinks
* @property-read int|null $source_journal_links_count
* @property-read Collection|Tag[] $tags
* @property-read int|null $tags_count
* @property-read TransactionCurrency|null $transactionCurrency
* @property-read TransactionGroup|null $transactionGroup
* @property-read Collection|TransactionJournalMeta[] $transactionJournalMeta
* @property-read int|null $transaction_journal_meta_count
* @property-read TransactionType $transactionType
* @property-read Collection|Transaction[] $transactions
* @property-read int|null $transactions_count
* @property-read User $user
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property Carbon|null $deleted_at
* @property int $user_id
* @property int $transaction_type_id
* @property int|null $transaction_group_id
* @property int|null $bill_id
* @property int|null $transaction_currency_id
* @property string $description
* @property Carbon $date
* @property Carbon|null $interest_date
* @property Carbon|null $book_date
* @property Carbon|null $process_date
* @property int $order
* @property int $tag_count
* @property string $transaction_type_type
* @property bool $encrypted
* @property bool $completed
* @property-read Collection|Attachment[] $attachments
* @property-read int|null $attachments_count
* @property-read Bill|null $bill
* @property-read Collection|Budget[] $budgets
* @property-read int|null $budgets_count
* @property-read Collection|Category[] $categories
* @property-read int|null $categories_count
* @property-read Collection|TransactionJournalLink[] $destJournalLinks
* @property-read int|null $dest_journal_links_count
* @property-read Collection|Note[] $notes
* @property-read int|null $notes_count
* @property-read Collection|PiggyBankEvent[] $piggyBankEvents
* @property-read int|null $piggy_bank_events_count
* @property-read Collection|TransactionJournalLink[] $sourceJournalLinks
* @property-read int|null $source_journal_links_count
* @property-read Collection|Tag[] $tags
* @property-read int|null $tags_count
* @property-read TransactionCurrency|null $transactionCurrency
* @property-read TransactionGroup|null $transactionGroup
* @property-read Collection|TransactionJournalMeta[] $transactionJournalMeta
* @property-read int|null $transaction_journal_meta_count
* @property-read TransactionType $transactionType
* @property-read Collection|Transaction[] $transactions
* @property-read int|null $transactions_count
* @property-read User $user
* @method static EloquentBuilder|TransactionJournal after(Carbon $date)
* @method static EloquentBuilder|TransactionJournal before(Carbon $date)
* @method static EloquentBuilder|TransactionJournal newModelQuery()
@ -112,13 +112,13 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static EloquentBuilder|TransactionJournal whereUserId($value)
* @method static \Illuminate\Database\Query\Builder|TransactionJournal withTrashed()
* @method static \Illuminate\Database\Query\Builder|TransactionJournal withoutTrashed()
* @property-read Collection|Location[] $locations
* @property-read int|null $locations_count
* @property int $the_count
* @property int|null $user_group_id
* @property-read Collection|Location[] $locations
* @property-read int|null $locations_count
* @property int $the_count
* @property int|null $user_group_id
* @method static EloquentBuilder|TransactionJournal whereUserGroupId($value)
* @property-read Collection<int, \FireflyIII\Models\AuditLogEntry> $auditLogEntries
* @property-read int|null $audit_log_entries_count
* @property-read Collection<int, AuditLogEntry> $auditLogEntries
* @property-read int|null $audit_log_entries_count
* @mixin Eloquent
*/
class TransactionJournal extends Model

View File

@ -30,6 +30,7 @@ use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Support\Carbon;
@ -38,13 +39,13 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class UserGroup
*
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property string|null $deleted_at
* @property string $title
* @property-read Collection|GroupMembership[] $groupMemberships
* @property-read int|null $group_memberships_count
* @property int $id
* @property Carbon|null $created_at
* @property Carbon|null $updated_at
* @property string|null $deleted_at
* @property string $title
* @property-read Collection|GroupMembership[] $groupMemberships
* @property-read int|null $group_memberships_count
* @method static Builder|UserGroup newModelQuery()
* @method static Builder|UserGroup newQuery()
* @method static Builder|UserGroup query()
@ -53,38 +54,40 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|UserGroup whereId($value)
* @method static Builder|UserGroup whereTitle($value)
* @method static Builder|UserGroup whereUpdatedAt($value)
* @property-read Collection<int, Account> $accounts
* @property-read int|null $accounts_count
* @property-read Collection<int, AvailableBudget> $availableBudgets
* @property-read int|null $available_budgets_count
* @property-read Collection<int, Bill> $bills
* @property-read int|null $bills_count
* @property-read Collection<int, Budget> $budgets
* @property-read int|null $budgets_count
* @property-read Collection<int, PiggyBank> $piggyBanks
* @property-read int|null $piggy_banks_count
* @property-read Collection<int, TransactionJournal> $transactionJournals
* @property-read int|null $transaction_journals_count
* @property-read Collection<int, \FireflyIII\Models\Attachment> $attachments
* @property-read int|null $attachments_count
* @property-read Collection<int, \FireflyIII\Models\Category> $categories
* @property-read int|null $categories_count
* @property-read Collection<int, \FireflyIII\Models\CurrencyExchangeRate> $currencyExchangeRates
* @property-read int|null $currency_exchange_rates_count
* @property-read Collection<int, \FireflyIII\Models\ObjectGroup> $objectGroups
* @property-read int|null $object_groups_count
* @property-read Collection<int, \FireflyIII\Models\Recurrence> $recurrences
* @property-read int|null $recurrences_count
* @property-read Collection<int, \FireflyIII\Models\RuleGroup> $ruleGroups
* @property-read int|null $rule_groups_count
* @property-read Collection<int, \FireflyIII\Models\Rule> $rules
* @property-read int|null $rules_count
* @property-read Collection<int, \FireflyIII\Models\Tag> $tags
* @property-read int|null $tags_count
* @property-read Collection<int, \FireflyIII\Models\TransactionGroup> $transactionGroups
* @property-read int|null $transaction_groups_count
* @property-read Collection<int, \FireflyIII\Models\Webhook> $webhooks
* @property-read int|null $webhooks_count
* @property-read Collection<int, Account> $accounts
* @property-read int|null $accounts_count
* @property-read Collection<int, AvailableBudget> $availableBudgets
* @property-read int|null $available_budgets_count
* @property-read Collection<int, Bill> $bills
* @property-read int|null $bills_count
* @property-read Collection<int, Budget> $budgets
* @property-read int|null $budgets_count
* @property-read Collection<int, PiggyBank> $piggyBanks
* @property-read int|null $piggy_banks_count
* @property-read Collection<int, TransactionJournal> $transactionJournals
* @property-read int|null $transaction_journals_count
* @property-read Collection<int, Attachment> $attachments
* @property-read int|null $attachments_count
* @property-read Collection<int, Category> $categories
* @property-read int|null $categories_count
* @property-read Collection<int, CurrencyExchangeRate> $currencyExchangeRates
* @property-read int|null $currency_exchange_rates_count
* @property-read Collection<int, ObjectGroup> $objectGroups
* @property-read int|null $object_groups_count
* @property-read Collection<int, Recurrence> $recurrences
* @property-read int|null $recurrences_count
* @property-read Collection<int, RuleGroup> $ruleGroups
* @property-read int|null $rule_groups_count
* @property-read Collection<int, Rule> $rules
* @property-read int|null $rules_count
* @property-read Collection<int, Tag> $tags
* @property-read int|null $tags_count
* @property-read Collection<int, TransactionGroup> $transactionGroups
* @property-read int|null $transaction_groups_count
* @property-read Collection<int, Webhook> $webhooks
* @property-read int|null $webhooks_count
* @property-read Collection<int, TransactionCurrency> $currencies
* @property-read int|null $currencies_count
* @mixin Eloquent
*/
class UserGroup extends Model
@ -179,6 +182,16 @@ class UserGroup extends Model
return $this->hasMany(Category::class);
}
/**
* Link to currencies
*
* @return BelongsToMany
*/
public function currencies(): BelongsToMany
{
return $this->belongsToMany(TransactionCurrency::class)->withTimestamps()->withPivot('group_default');
}
/**
* Link to exchange rates.
*

View File

@ -25,7 +25,6 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\Admin;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;

View File

@ -26,7 +26,6 @@ namespace FireflyIII\Notifications\Admin;
use FireflyIII\Models\InvitedUser;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;

View File

@ -25,7 +25,6 @@ declare(strict_types=1);
namespace FireflyIII\Notifications\Admin;
use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;

View File

@ -29,9 +29,9 @@ use FireflyIII\Support\Notifications\UrlValidator;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Log;
use Illuminate\Notifications\Messages\SlackMessage;
/**
* Class UserLogin

View File

@ -28,7 +28,6 @@ use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
use Laravel\Passport\Passport;
use Laravel\Sanctum\Sanctum;
use URL;
/**
* Class AppServiceProvider

View File

@ -25,6 +25,8 @@ namespace FireflyIII\Providers;
use FireflyIII\Repositories\Currency\CurrencyRepository;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepository as GroupCurrencyRepository;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface as GroupCurrencyRepositoryInterface;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;
@ -55,6 +57,19 @@ class CurrencyServiceProvider extends ServiceProvider
$repository->setUser(auth()->user());
}
return $repository;
}
);
$this->app->bind(
GroupCurrencyRepositoryInterface::class,
function (Application $app) {
/** @var GroupCurrencyRepository $repository */
$repository = app(GroupCurrencyRepository::class);
// phpstan does not get the reference to auth
if ($app->auth->check()) { // @phpstan-ignore-line
$repository->setUser(auth()->user());
}
return $repository;
}
);

View File

@ -31,10 +31,10 @@ use FireflyIII\Repositories\Journal\JournalCLIRepository;
use FireflyIII\Repositories\Journal\JournalCLIRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepository;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Journal\JournalRepository as GroupJournalRepository;
use FireflyIII\Repositories\UserGroups\Journal\JournalRepositoryInterface as GroupJournalRepositoryInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepository;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Journal\JournalRepository as GroupJournalRepository;
use FireflyIII\Repositories\UserGroups\Journal\JournalRepositoryInterface as GroupJournalRepositoryInterface;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;

View File

@ -25,10 +25,8 @@ namespace FireflyIII\Providers;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepository;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\UserGroups\PiggyBank\PiggyBankRepository as AdminPiggyBankRepository;
use FireflyIII\Repositories\UserGroups\PiggyBank\PiggyBankRepositoryInterface as AdminPiggyBankRepositoryInterface;
use Illuminate\Foundation\Application;
use Illuminate\Support\ServiceProvider;

View File

@ -28,7 +28,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Collection;

View File

@ -38,7 +38,7 @@ use FireflyIII\Models\RuleAction;
use FireflyIII\Models\RuleTrigger;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Repositories\UserGroups\Currency\CurrencyRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\BudgetDestroyService;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Authenticatable;
@ -429,6 +429,7 @@ class BudgetRepository implements BudgetRepositoryInterface
// set or update the currency.
if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) {
/** @var CurrencyRepositoryInterface $repos */
$repos = app(CurrencyRepositoryInterface::class);
$currencyId = (int)($data['currency_id'] ?? 0);
$currencyCode = (string)($data['currency_code'] ?? '');
@ -837,6 +838,7 @@ class BudgetRepository implements BudgetRepositoryInterface
$type = AutoBudget::AUTO_BUDGET_ADJUSTED;
}
/** @var CurrencyRepositoryInterface $repos */
$repos = app(CurrencyRepositoryInterface::class);
$currency = null;
if (array_key_exists('currency_id', $data)) {

View File

@ -24,25 +24,12 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Currency;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\TransactionCurrencyFactory;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\Bill;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\Preference;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\Services\Internal\Destroy\CurrencyDestroyService;
use FireflyIII\Services\Internal\Update\CurrencyUpdateService;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use JsonException;
/**
* Class CurrencyRepository.
@ -51,327 +38,6 @@ class CurrencyRepository implements CurrencyRepositoryInterface
{
private User $user;
/**
* @param TransactionCurrency $currency
*
* @return bool
* @throws FireflyException
*/
public function currencyInUse(TransactionCurrency $currency): bool
{
$result = $this->currencyInUseAt($currency);
return null !== $result;
}
/**
* @param TransactionCurrency $currency
*
* @return string|null
* @throws FireflyException
*/
public function currencyInUseAt(TransactionCurrency $currency): ?string
{
Log::debug(sprintf('Now in currencyInUse() for #%d ("%s")', $currency->id, $currency->code));
$countJournals = $this->countJournals($currency);
if ($countJournals > 0) {
Log::info(sprintf('Count journals is %d, return true.', $countJournals));
return 'journals';
}
// is the only currency left
if (1 === $this->getAll()->count()) {
Log::info('Is the last currency in the system, return true. ');
return 'last_left';
}
// is being used in accounts:
$meta = AccountMeta::where('name', 'currency_id')->where('data', json_encode((string)$currency->id))->count();
if ($meta > 0) {
Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta));
return 'account_meta';
}
// is being used in bills:
$bills = Bill::where('transaction_currency_id', $currency->id)->count();
if ($bills > 0) {
Log::info(sprintf('Used in %d bills as currency, return true. ', $bills));
return 'bills';
}
// is being used in recurring transactions
$recurringAmount = RecurrenceTransaction::where('transaction_currency_id', $currency->id)->count();
$recurringForeign = RecurrenceTransaction::where('foreign_currency_id', $currency->id)->count();
if ($recurringAmount > 0 || $recurringForeign > 0) {
Log::info(sprintf('Used in %d recurring transactions as (foreign) currency id, return true. ', $recurringAmount + $recurringForeign));
return 'recurring';
}
// is being used in accounts (as integer)
$meta = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id')
->whereNull('accounts.deleted_at')
->where('account_meta.name', 'currency_id')->where('account_meta.data', json_encode((int)$currency->id))->count();
if ($meta > 0) {
Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta));
return 'account_meta';
}
// is being used in available budgets
$availableBudgets = AvailableBudget::where('transaction_currency_id', $currency->id)->count();
if ($availableBudgets > 0) {
Log::info(sprintf('Used in %d available budgets as currency, return true. ', $availableBudgets));
return 'available_budgets';
}
// is being used in budget limits
$budgetLimit = BudgetLimit::where('transaction_currency_id', $currency->id)->count();
if ($budgetLimit > 0) {
Log::info(sprintf('Used in %d budget limits as currency, return true. ', $budgetLimit));
return 'budget_limits';
}
// is the default currency for the user or the system
$defaultCode = app('preferences')->getForUser($this->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data;
if ($currency->code === $defaultCode) {
Log::info('Is the default currency of the user, return true.');
return 'current_default';
}
Log::debug('Currency is not used, return false.');
return null;
}
/**
* @param TransactionCurrency $currency
*
* @return int
*/
public function countJournals(TransactionCurrency $currency): int
{
$count = $currency->transactions()->whereNull('deleted_at')->count() + $currency->transactionJournals()->whereNull('deleted_at')->count();
// also count foreign:
return $count + Transaction::where('foreign_currency_id', $currency->id)->count();
}
/**
* @return Collection
*/
public function getAll(): Collection
{
return TransactionCurrency::orderBy('code', 'ASC')->get();
}
/**
* @return Collection
*/
public function get(): Collection
{
return TransactionCurrency::where('enabled', true)->orderBy('code', 'ASC')->get();
}
/**
* @param TransactionCurrency $currency
*
* @return bool
*/
public function destroy(TransactionCurrency $currency): bool
{
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
if ($repository->hasRole($this->user, 'owner')) {
/** @var CurrencyDestroyService $service */
$service = app(CurrencyDestroyService::class);
$service->destroy($currency);
}
return true;
}
/**
* Disables a currency
*
* @param TransactionCurrency $currency
*/
public function disable(TransactionCurrency $currency): void
{
$currency->enabled = false;
$currency->save();
}
/**
* @inheritDoc
*/
public function ensureMinimalEnabledCurrencies(): void
{
// if no currencies are enabled, enable the first one in the DB (usually the EUR)
if (0 === $this->get()->count()) {
/** @var TransactionCurrency $first */
$first = $this->getAll()->first();
if (null === $first) {
throw new FireflyException('No currencies found. You broke Firefly III');
}
Log::channel('audit')->info(sprintf('Auto-enabled currency %s.', $first->code));
$this->enable($first);
app('preferences')->set('currencyPreference', $first->code);
app('preferences')->mark();
}
}
/**
* @param TransactionCurrency $currency
* Enables a currency
*/
public function enable(TransactionCurrency $currency): void
{
$currency->enabled = true;
$currency->save();
}
/**
* Find by currency code, return NULL if unfound.
* Used in Import Currency!
*
* @param string $currencyCode
*
* @return TransactionCurrency|null
* @deprecated
*/
public function findByCodeNull(string $currencyCode): ?TransactionCurrency
{
return TransactionCurrency::where('code', $currencyCode)->first();
}
/**
* Find by currency name.
*
* @param string $currencyName
*
* @return TransactionCurrency|null
*/
public function findByName(string $currencyName): ?TransactionCurrency
{
return TransactionCurrency::whereName($currencyName)->first();
}
/**
* Find by currency name or return null.
* Used in Import Currency!
*
* @param string $currencyName
*
* @return TransactionCurrency|null
* @deprecated
*/
public function findByNameNull(string $currencyName): ?TransactionCurrency
{
return TransactionCurrency::whereName($currencyName)->first();
}
/**
* Find by currency symbol.
*
* @param string $currencySymbol
*
* @return TransactionCurrency|null
*/
public function findBySymbol(string $currencySymbol): ?TransactionCurrency
{
return TransactionCurrency::whereSymbol($currencySymbol)->first();
}
/**
* Find by currency symbol or return NULL
* Used in Import Currency!
*
* @param string $currencySymbol
*
* @return TransactionCurrency|null
* @deprecated
*/
public function findBySymbolNull(string $currencySymbol): ?TransactionCurrency
{
return TransactionCurrency::whereSymbol($currencySymbol)->first();
}
/**
* Find by object, ID or code. Returns user default or system default.
*
* @param int|null $currencyId
* @param string|null $currencyCode
*
* @return TransactionCurrency
* @throws FireflyException
* @throws JsonException
*/
public function findCurrency(?int $currencyId, ?string $currencyCode): TransactionCurrency
{
$result = $this->findCurrencyNull($currencyId, $currencyCode);
if (null === $result) {
Log::debug('Grabbing default currency for this user...');
$result = app('amount')->getDefaultCurrencyByUser($this->user);
}
if (null === $result) {
Log::debug('Grabbing EUR as fallback.');
$result = $this->findByCode('EUR');
}
Log::debug(sprintf('Final result: %s', $result->code));
if (false === $result->enabled) {
Log::debug(sprintf('Also enabled currency %s', $result->code));
$this->enable($result);
}
return $result;
}
/**
* Find by object, ID or code. Returns NULL if nothing found.
*
* @param int|null $currencyId
* @param string|null $currencyCode
*
* @return TransactionCurrency|null
*/
public function findCurrencyNull(?int $currencyId, ?string $currencyCode): ?TransactionCurrency
{
Log::debug('Now in findCurrencyNull()');
$result = $this->find((int)$currencyId);
if (null === $result) {
Log::debug(sprintf('Searching for currency with code %s...', $currencyCode));
$result = $this->findByCode((string)$currencyCode);
}
if (null !== $result && false === $result->enabled) {
Log::debug(sprintf('Also enabled currency %s', $result->code));
$this->enable($result);
}
return $result;
}
/**
* Find by ID, return NULL if not found.
*
* @param int $currencyId
*
* @return TransactionCurrency|null
*/
public function find(int $currencyId): ?TransactionCurrency
{
return TransactionCurrency::find($currencyId);
}
/**
* Find by currency code, return NULL if unfound.
@ -385,30 +51,18 @@ class CurrencyRepository implements CurrencyRepositoryInterface
return TransactionCurrency::where('code', $currencyCode)->first();
}
/**
* @param array $ids
* Returns the complete set of transactions but needs
* no user object.
*
* @return Collection
*/
public function getByIds(array $ids): Collection
public function getCompleteSet(): Collection
{
return TransactionCurrency::orderBy('code', 'ASC')->whereIn('id', $ids)->get();
return TransactionCurrency::orderBy('code', 'ASC')->get();
}
/**
* @param Preference $preference
*
* @return TransactionCurrency
*/
public function getCurrencyByPreference(Preference $preference): TransactionCurrency
{
$preferred = TransactionCurrency::where('code', $preference->data)->first();
if (null === $preferred) {
$preferred = TransactionCurrency::first();
}
return $preferred;
}
/**
* Get currency exchange rate.
@ -442,30 +96,6 @@ class CurrencyRepository implements CurrencyRepositoryInterface
return null;
}
/**
* @inheritDoc
*/
public function isFallbackCurrency(TransactionCurrency $currency): bool
{
return $currency->code === config('firefly.default_currency', 'EUR');
}
/**
* @param string $search
* @param int $limit
*
* @return Collection
*/
public function searchCurrency(string $search, int $limit): Collection
{
$query = TransactionCurrency::where('enabled', true);
if ('' !== $search) {
$query->where('name', 'LIKE', sprintf('%%%s%%', $search));
}
return $query->take($limit)->get();
}
/**
* TODO must be a factory
*
@ -499,36 +129,4 @@ class CurrencyRepository implements CurrencyRepositoryInterface
}
}
/**
* @param array $data
*
* @return TransactionCurrency
* @throws FireflyException
*/
public function store(array $data): TransactionCurrency
{
/** @var TransactionCurrencyFactory $factory */
$factory = app(TransactionCurrencyFactory::class);
$result = $factory->create($data);
if (null === $result) {
throw new FireflyException('400004: Could not store new currency.');
}
return $result;
}
/**
* @param TransactionCurrency $currency
* @param array $data
*
* @return TransactionCurrency
*/
public function update(TransactionCurrency $currency, array $data): TransactionCurrency
{
/** @var CurrencyUpdateService $service */
$service = app(CurrencyUpdateService::class);
return $service->update($currency, $data);
}
}

View File

@ -24,9 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Currency;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\Preference;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Authenticatable;
@ -37,67 +35,11 @@ use Illuminate\Support\Collection;
*/
interface CurrencyRepositoryInterface
{
/**
* @param TransactionCurrency $currency
*
* @return int
*/
public function countJournals(TransactionCurrency $currency): int;
/**
* @param TransactionCurrency $currency
*
* @return bool
*/
public function currencyInUse(TransactionCurrency $currency): bool;
/**
* Currency is in use where exactly.
*
* @param TransactionCurrency $currency
*
* @return string|null
*/
public function currencyInUseAt(TransactionCurrency $currency): ?string;
/**
* @param TransactionCurrency $currency
*
* @return bool
*/
public function destroy(TransactionCurrency $currency): bool;
/**
* Disables a currency
*
* @param TransactionCurrency $currency
*/
public function disable(TransactionCurrency $currency): void;
/**
* Enables a currency
*
* @param TransactionCurrency $currency
*/
public function enable(TransactionCurrency $currency): void;
/**
* @return void
*/
public function ensureMinimalEnabledCurrencies(): void;
/**
* Find by ID, return NULL if not found.
*
* @param int $currencyId
*
* @return TransactionCurrency|null
*/
public function find(int $currencyId): ?TransactionCurrency;
/**
* Find by currency code, return NULL if unfound.
*
* Used in the download exchange rates cron job. Does not require user object.
*
* @param string $currencyCode
*
* @return TransactionCurrency|null
@ -105,97 +47,20 @@ interface CurrencyRepositoryInterface
public function findByCode(string $currencyCode): ?TransactionCurrency;
/**
* Find by currency code, return NULL if unfound.
* Returns the complete set of transactions but needs
* no user object.
*
* @param string $currencyCode
*
* @return TransactionCurrency|null
*/
public function findByCodeNull(string $currencyCode): ?TransactionCurrency;
/**
* Find by currency name.
*
* @param string $currencyName
*
* @return TransactionCurrency|null
*/
public function findByName(string $currencyName): ?TransactionCurrency;
/**
* Find by currency name.
*
* @param string $currencyName
*
* @return TransactionCurrency|null
*/
public function findByNameNull(string $currencyName): ?TransactionCurrency;
/**
* Find by currency symbol.
*
* @param string $currencySymbol
*
* @return TransactionCurrency|null
*/
public function findBySymbol(string $currencySymbol): ?TransactionCurrency;
/**
* Find by currency symbol.
*
* @param string $currencySymbol
*
* @return TransactionCurrency|null
*/
public function findBySymbolNull(string $currencySymbol): ?TransactionCurrency;
/**
* Find by object, ID or code. Returns user default or system default.
*
* @param int|null $currencyId
* @param string|null $currencyCode
*
* @return TransactionCurrency
*/
public function findCurrency(?int $currencyId, ?string $currencyCode): TransactionCurrency;
/**
* Find by object, ID or code. Returns NULL if nothing found.
*
* @param int|null $currencyId
* @param string|null $currencyCode
*
* @return TransactionCurrency|null
*/
public function findCurrencyNull(?int $currencyId, ?string $currencyCode): ?TransactionCurrency;
/**
* @return Collection
*/
public function get(): Collection;
/**
* @return Collection
*/
public function getAll(): Collection;
/**
* @param array $ids
* Used by the download exchange rate cron job.
*
* @return Collection
*/
public function getByIds(array $ids): Collection;
/**
* @param Preference $preference
*
* @return TransactionCurrency
*/
public function getCurrencyByPreference(Preference $preference): TransactionCurrency;
public function getCompleteSet(): Collection;
/**
* Get currency exchange rate.
*
* Used in the download exchange rate cron job. Needs the user object!
*
* @param TransactionCurrency $fromCurrency
* @param TransactionCurrency $toCurrency
* @param Carbon $date
@ -205,22 +70,9 @@ interface CurrencyRepositoryInterface
public function getExchangeRate(TransactionCurrency $fromCurrency, TransactionCurrency $toCurrency, Carbon $date): ?CurrencyExchangeRate;
/**
* @param TransactionCurrency $currency
* Set currency exchange rate.
*
* @return bool
*/
public function isFallbackCurrency(TransactionCurrency $currency): bool;
/**
* @param string $search
* @param int $limit
*
* @return Collection
*/
public function searchCurrency(string $search, int $limit): Collection;
/**
* TODO must be a factory
* Used in download exchange rate cron job. Needs the user object!
*
* @param TransactionCurrency $fromCurrency
* @param TransactionCurrency $toCurrency
@ -236,19 +88,4 @@ interface CurrencyRepositoryInterface
*/
public function setUser(User | Authenticatable | null $user): void;
/**
* @param array $data
*
* @return TransactionCurrency
* @throws FireflyException
*/
public function store(array $data): TransactionCurrency;
/**
* @param TransactionCurrency $currency
* @param array $data
*
* @return TransactionCurrency
*/
public function update(TransactionCurrency $currency, array $data): TransactionCurrency;
}

Some files were not shown because too many files have changed in this diff Show More