mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-12-19 17:51:19 +00:00
Compare commits
82 Commits
v6.3.0-bet
...
v6.3.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39b61c71e8 | ||
|
|
fa2c964790 | ||
|
|
134aeb3a46 | ||
|
|
6f6e1a4ff4 | ||
|
|
b743bf3d9e | ||
|
|
84ee6f16c9 | ||
|
|
9fe39e42b3 | ||
|
|
4013c7e316 | ||
|
|
0b76747531 | ||
|
|
3129756b37 | ||
|
|
b0df383004 | ||
|
|
9c5b1df86c | ||
|
|
5854e24775 | ||
|
|
3f873422f2 | ||
|
|
f898990773 | ||
|
|
a5759ab1c6 | ||
|
|
9bd6417e02 | ||
|
|
cd12a10214 | ||
|
|
ee8cb62e04 | ||
|
|
87ee95a852 | ||
|
|
10f8436885 | ||
|
|
6955846a1c | ||
|
|
11d2f8d471 | ||
|
|
99347ffff1 | ||
|
|
3ddc11a905 | ||
|
|
0a48c0c20f | ||
|
|
8bc764d6ef | ||
|
|
4b4f568558 | ||
|
|
d42117281a | ||
|
|
d68ed5a713 | ||
|
|
2f6f36c3f0 | ||
|
|
984aa02e35 | ||
|
|
cdadc7d533 | ||
|
|
4d59955cc5 | ||
|
|
fc547ba59a | ||
|
|
1b2ded3167 | ||
|
|
dcf20a472a | ||
|
|
7bd528defe | ||
|
|
9e6d123165 | ||
|
|
c592f51c83 | ||
|
|
fbb6f30366 | ||
|
|
4546c721fb | ||
|
|
3a659c9a81 | ||
|
|
e28a988eb3 | ||
|
|
a29742fe1f | ||
|
|
dd06838eec | ||
|
|
5eb828bff8 | ||
|
|
c7f3701053 | ||
|
|
ab6799442c | ||
|
|
1fe9bf7d76 | ||
|
|
bd14797da6 | ||
|
|
93b4e6a8d0 | ||
|
|
5566671971 | ||
|
|
defcc7a00c | ||
|
|
5183de634b | ||
|
|
7771b0311c | ||
|
|
52abe3bbc2 | ||
|
|
34db9f41c2 | ||
|
|
72c31fbe6a | ||
|
|
1d8dd41564 | ||
|
|
3409240a19 | ||
|
|
eccc58e75a | ||
|
|
24098f35bb | ||
|
|
e7d9dc57d8 | ||
|
|
f04ed5b8f0 | ||
|
|
8bd44f429b | ||
|
|
fb7866b165 | ||
|
|
98db6db1eb | ||
|
|
0a235ec523 | ||
|
|
cb4f7ad0a8 | ||
|
|
91ce1d3b88 | ||
|
|
8f9ab150ee | ||
|
|
8d52f83b4f | ||
|
|
fb19739b54 | ||
|
|
acd4f28ae3 | ||
|
|
e4d443db50 | ||
|
|
fe9d36cd27 | ||
|
|
a916cc7e78 | ||
|
|
77d15f884b | ||
|
|
ab773c9052 | ||
|
|
87d292ca27 | ||
|
|
946e272d1c |
@@ -1,6 +1,6 @@
|
|||||||
parameters:
|
parameters:
|
||||||
scanFiles:
|
scanFiles:
|
||||||
- ../_ide_helper
|
- ../_ide_helper.php
|
||||||
paths:
|
paths:
|
||||||
- ../app
|
- ../app
|
||||||
- ../database
|
- ../database
|
||||||
|
|||||||
3
.github/release-notes/alpha.md
vendored
3
.github/release-notes/alpha.md
vendored
@@ -1,6 +1,7 @@
|
|||||||
Welcome to release %version of Firefly III. This **alpha** release contains the latest fixes, translations and features. It is probably buggy and may not work as expected. You can download the release below, and adventurous Docker users can find this release under the `alpha` tag.
|
Welcome to release %version of Firefly III. This **alpha** release contains the latest fixes, translations and features. It is probably buggy and may not work as expected. You can download the release below, and adventurous Docker users can find this release under the `alpha` tag.
|
||||||
|
|
||||||
:warning: Please be careful with this alpha release, as it may not work as expected.
|
> [!WARNING]
|
||||||
|
> Please be careful with this alpha release, as it may not work as expected.
|
||||||
|
|
||||||
Alpha releases are created to test new features and fixes before they are included in a stable release. They are not recommended for production use. This release was created on %date and may contain unexpected bugs. Data loss is rare but possible.
|
Alpha releases are created to test new features and fixes before they are included in a stable release. They are not recommended for production use. This release was created on %date and may contain unexpected bugs. Data loss is rare but possible.
|
||||||
|
|
||||||
|
|||||||
3
.github/release-notes/beta.md
vendored
3
.github/release-notes/beta.md
vendored
@@ -1,6 +1,7 @@
|
|||||||
Welcome to release %version of Firefly III. This **beta** release contains the latest fixes, translations and features. It may be buggy, nor work as expected. You can download the release below, and adventurous Docker users can find this release under the `beta` tag.
|
Welcome to release %version of Firefly III. This **beta** release contains the latest fixes, translations and features. It may be buggy, nor work as expected. You can download the release below, and adventurous Docker users can find this release under the `beta` tag.
|
||||||
|
|
||||||
:warning: Please be careful with this beta release, as it may not work as expected.
|
> [!WARNING]
|
||||||
|
> Please be careful with this beta release, as it may not work as expected.
|
||||||
|
|
||||||
Alpha releases are created to test new features and fixes before they are included in a stable release. They are not recommended for production use. This release was created on %date and may contain unexpected bugs. Data loss is rare but possible.
|
Alpha releases are created to test new features and fixes before they are included in a stable release. They are not recommended for production use. This release was created on %date and may contain unexpected bugs. Data loss is rare but possible.
|
||||||
|
|
||||||
|
|||||||
3
.github/release-notes/branch.md
vendored
3
.github/release-notes/branch.md
vendored
@@ -1,6 +1,7 @@
|
|||||||
Welcome to release %version of Firefly III. This branch-related release contains the latest fixes, translations and features. It is probably buggy and may not work as expected. You can download the release below, and adventurous Docker users can find this release under the `branch-*` tag.
|
Welcome to release %version of Firefly III. This branch-related release contains the latest fixes, translations and features. It is probably buggy and may not work as expected. You can download the release below, and adventurous Docker users can find this release under the `branch-*` tag.
|
||||||
|
|
||||||
:warning: Please be careful with this branch release, as it may not work as expected.
|
> [!WARNING]
|
||||||
|
> Please be careful with this branch release, as it may not work as expected.
|
||||||
|
|
||||||
Branch releases are created to test large new features that are developed alongside the normal release flow. They are not recommended for production use. This release was created on %date and may contain unexpected bugs. Data loss is rare but possible.
|
Branch releases are created to test large new features that are developed alongside the normal release flow. They are not recommended for production use. This release was created on %date and may contain unexpected bugs. Data loss is rare but possible.
|
||||||
|
|
||||||
|
|||||||
3
.github/release-notes/develop.md
vendored
3
.github/release-notes/develop.md
vendored
@@ -1,6 +1,7 @@
|
|||||||
Welcome to the latest development release of Firefly III. This test release contains the absolute latest fixes, translations and features. It is probably buggy and may not work as expected. You can download the release below, and adventurous Docker users can find this release under the `develop` tag.
|
Welcome to the latest development release of Firefly III. This test release contains the absolute latest fixes, translations and features. It is probably buggy and may not work as expected. You can download the release below, and adventurous Docker users can find this release under the `develop` tag.
|
||||||
|
|
||||||
:warning: Please be careful with this pre-release, as it may not work as expected.
|
> [!WARNING]
|
||||||
|
> Please be careful with this pre-release, as it may not work as expected.
|
||||||
|
|
||||||
This release was created on %date and may contain unexpected bugs. Data loss is rare but possible.
|
This release was created on %date and may contain unexpected bugs. Data loss is rare but possible.
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/depsreview.yml
vendored
2
.github/workflows/depsreview.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout repository'
|
- name: 'Checkout repository'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v5
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: 'Dependency review'
|
- name: 'Dependency review'
|
||||||
|
|||||||
2
.github/workflows/lock.yml
vendored
2
.github/workflows/lock.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
discussions: write
|
discussions: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/lock-threads@v5
|
- uses: JC5/lock-threads@v6.0.2
|
||||||
with:
|
with:
|
||||||
issue-inactive-days: 21
|
issue-inactive-days: 21
|
||||||
pr-inactive-days: 21
|
pr-inactive-days: 21
|
||||||
|
|||||||
16
.github/workflows/release.yml
vendored
16
.github/workflows/release.yml
vendored
@@ -50,7 +50,7 @@ jobs:
|
|||||||
git pull
|
git pull
|
||||||
echo "Current branch is $(git branch --show-current)"
|
echo "Current branch is $(git branch --show-current)"
|
||||||
env:
|
env:
|
||||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
|
||||||
- name: Configure Git
|
- name: Configure Git
|
||||||
run: |
|
run: |
|
||||||
# do some configuration
|
# do some configuration
|
||||||
@@ -118,7 +118,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
FIREFLY_III_ROOT: /github/workspace
|
FIREFLY_III_ROOT: /github/workspace
|
||||||
GH_TOKEN: ""
|
GH_TOKEN: ""
|
||||||
FF_III_VERSION: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
FF_III_VERSION: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
|
||||||
- name: Generate JSON v1
|
- name: Generate JSON v1
|
||||||
id: json-v1
|
id: json-v1
|
||||||
uses: JC5/firefly-iii-dev@main
|
uses: JC5/firefly-iii-dev@main
|
||||||
@@ -221,7 +221,7 @@ jobs:
|
|||||||
echo "tarName=$tarName" >> "$GITHUB_ENV"
|
echo "tarName=$tarName" >> "$GITHUB_ENV"
|
||||||
echo "BRANCH_NAME=$BRANCH_NAME" >> "$GITHUB_ENV"
|
echo "BRANCH_NAME=$BRANCH_NAME" >> "$GITHUB_ENV"
|
||||||
env:
|
env:
|
||||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
|
||||||
- name: Commit all changes
|
- name: Commit all changes
|
||||||
run: |
|
run: |
|
||||||
# add all content, except output.txt (this contains the changelog and/or the download instructions)
|
# add all content, except output.txt (this contains the changelog and/or the download instructions)
|
||||||
@@ -232,12 +232,12 @@ jobs:
|
|||||||
git commit -m "🤖 Auto commit for release '$version' on $(date +'%Y-%m-%d')" || true
|
git commit -m "🤖 Auto commit for release '$version' on $(date +'%Y-%m-%d')" || true
|
||||||
git push
|
git push
|
||||||
env:
|
env:
|
||||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
|
||||||
- name: Generate release description
|
- name: Generate release description
|
||||||
id: release-description
|
id: release-description
|
||||||
uses: JC5/firefly-iii-dev@main
|
uses: JC5/firefly-iii-dev@main
|
||||||
with:
|
with:
|
||||||
action: "ff3:generate-release-notes firefly-iii ${{ github.event.inputs.version }}"
|
action: "ff3:generate-release-notes firefly-iii ${{ inputs.version || 'develop' }}"
|
||||||
output: 'output'
|
output: 'output'
|
||||||
env:
|
env:
|
||||||
FIREFLY_III_ROOT: /github/workspace
|
FIREFLY_III_ROOT: /github/workspace
|
||||||
@@ -291,7 +291,7 @@ jobs:
|
|||||||
echo "DONE!"
|
echo "DONE!"
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
|
||||||
- name: Create archives
|
- name: Create archives
|
||||||
run: |
|
run: |
|
||||||
echo "Create zip file $zipName"
|
echo "Create zip file $zipName"
|
||||||
@@ -375,7 +375,7 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
|
||||||
- name: Upload artifacts
|
- name: Upload artifacts
|
||||||
run: |
|
run: |
|
||||||
# add zip file to release.
|
# add zip file to release.
|
||||||
@@ -411,4 +411,4 @@ jobs:
|
|||||||
rm -f $tarName.sha256
|
rm -f $tarName.sha256
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
version: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
|
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
use FireflyIII\Enums\AccountTypeEnum;
|
use FireflyIII\Enums\AccountTypeEnum;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
@@ -34,7 +35,6 @@ use FireflyIII\Support\Debug\Timer;
|
|||||||
use FireflyIII\Support\Facades\Amount;
|
use FireflyIII\Support\Facades\Amount;
|
||||||
use FireflyIII\Support\Facades\Steam;
|
use FireflyIII\Support\Facades\Steam;
|
||||||
use FireflyIII\Support\Http\Api\AccountFilter;
|
use FireflyIII\Support\Http\Api\AccountFilter;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
@@ -47,6 +47,7 @@ class AccountController extends Controller
|
|||||||
|
|
||||||
// this array only exists to test if the constructor will use it properly.
|
// this array only exists to test if the constructor will use it properly.
|
||||||
protected array $accepts = ['application/json', 'application/vnd.api+json'];
|
protected array $accepts = ['application/json', 'application/vnd.api+json'];
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
|
||||||
/** @var array<int, string> */
|
/** @var array<int, string> */
|
||||||
private array $balanceTypes;
|
private array $balanceTypes;
|
||||||
@@ -60,10 +61,10 @@ class AccountController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
/** @var User $user */
|
$this->validateUserGroup($request);
|
||||||
$user = auth()->user();
|
|
||||||
$this->repository = app(AccountRepositoryInterface::class);
|
$this->repository = app(AccountRepositoryInterface::class);
|
||||||
$this->repository->setUser($user);
|
$this->repository->setUser($this->user);
|
||||||
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\Bill;
|
use FireflyIII\Models\Bill;
|
||||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +37,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class BillController extends Controller
|
class BillController extends Controller
|
||||||
{
|
{
|
||||||
private BillRepositoryInterface $repository;
|
private BillRepositoryInterface $repository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_SUBSCRIPTIONS];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BillController constructor.
|
* BillController constructor.
|
||||||
@@ -46,10 +47,10 @@ class BillController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
/** @var User $user */
|
$this->validateUserGroup($request);
|
||||||
$user = auth()->user();
|
|
||||||
$this->repository = app(BillRepositoryInterface::class);
|
$this->repository = app(BillRepositoryInterface::class);
|
||||||
$this->repository->setUser($user);
|
$this->repository->setUser($this->user);
|
||||||
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +37,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class BudgetController extends Controller
|
class BudgetController extends Controller
|
||||||
{
|
{
|
||||||
private BudgetRepositoryInterface $repository;
|
private BudgetRepositoryInterface $repository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_BUDGETS];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BudgetController constructor.
|
* BudgetController constructor.
|
||||||
@@ -46,10 +47,10 @@ class BudgetController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
/** @var User $user */
|
$this->validateUserGroup($request);
|
||||||
$user = auth()->user();
|
|
||||||
$this->repository = app(BudgetRepositoryInterface::class);
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
$this->repository->setUser($user);
|
$this->repository->setUser($this->user);
|
||||||
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\Category;
|
use FireflyIII\Models\Category;
|
||||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +37,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class CategoryController extends Controller
|
class CategoryController extends Controller
|
||||||
{
|
{
|
||||||
private CategoryRepositoryInterface $repository;
|
private CategoryRepositoryInterface $repository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CategoryController constructor.
|
* CategoryController constructor.
|
||||||
@@ -46,10 +47,10 @@ class CategoryController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
/** @var User $user */
|
$this->validateUserGroup($request);
|
||||||
$user = auth()->user();
|
|
||||||
$this->repository = app(CategoryRepositoryInterface::class);
|
$this->repository = app(CategoryRepositoryInterface::class);
|
||||||
$this->repository->setUser($user);
|
$this->repository->setUser($this->user);
|
||||||
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
use Deprecated;
|
use Deprecated;
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,6 +38,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class CurrencyController extends Controller
|
class CurrencyController extends Controller
|
||||||
{
|
{
|
||||||
private CurrencyRepositoryInterface $repository;
|
private CurrencyRepositoryInterface $repository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CurrencyController constructor.
|
* CurrencyController constructor.
|
||||||
@@ -47,10 +48,10 @@ class CurrencyController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
/** @var User $user */
|
$this->validateUserGroup($request);
|
||||||
$user = auth()->user();
|
|
||||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||||
$this->repository->setUser($user);
|
$this->repository->setUser($this->user);
|
||||||
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\ObjectGroup;
|
use FireflyIII\Models\ObjectGroup;
|
||||||
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
|
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +37,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class ObjectGroupController extends Controller
|
class ObjectGroupController extends Controller
|
||||||
{
|
{
|
||||||
private ObjectGroupRepositoryInterface $repository;
|
private ObjectGroupRepositoryInterface $repository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CurrencyController constructor.
|
* CurrencyController constructor.
|
||||||
@@ -46,10 +47,10 @@ class ObjectGroupController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
/** @var User $user */
|
$this->validateUserGroup($request);
|
||||||
$user = auth()->user();
|
|
||||||
$this->repository = app(ObjectGroupRepositoryInterface::class);
|
$this->repository = app(ObjectGroupRepositoryInterface::class);
|
||||||
$this->repository->setUser($user);
|
$this->repository->setUser($this->user);
|
||||||
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\PiggyBank;
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,6 +39,7 @@ class PiggyBankController extends Controller
|
|||||||
{
|
{
|
||||||
private AccountRepositoryInterface $accountRepository;
|
private AccountRepositoryInterface $accountRepository;
|
||||||
private PiggyBankRepositoryInterface $piggyRepository;
|
private PiggyBankRepositoryInterface $piggyRepository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_PIGGY_BANKS];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PiggyBankController constructor.
|
* PiggyBankController constructor.
|
||||||
@@ -48,22 +49,19 @@ class PiggyBankController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
/** @var User $user */
|
$this->validateUserGroup($request);
|
||||||
$user = auth()->user();
|
|
||||||
$this->piggyRepository = app(PiggyBankRepositoryInterface::class);
|
$this->piggyRepository = app(PiggyBankRepositoryInterface::class);
|
||||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||||
$this->piggyRepository->setUser($user);
|
$this->piggyRepository->setUser($this->user);
|
||||||
$this->accountRepository->setUser($user);
|
$this->piggyRepository->setUserGroup($this->userGroup);
|
||||||
|
$this->accountRepository->setUser($this->user);
|
||||||
|
$this->accountRepository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getPiggiesAC
|
|
||||||
*/
|
|
||||||
public function piggyBanks(AutocompleteRequest $request): JsonResponse
|
public function piggyBanks(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
@@ -90,10 +88,6 @@ class PiggyBankController extends Controller
|
|||||||
return response()->api($response);
|
return response()->api($response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getPiggiesBalanceAC
|
|
||||||
*/
|
|
||||||
public function piggyBanksWithBalance(AutocompleteRequest $request): JsonResponse
|
public function piggyBanksWithBalance(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\Recurrence;
|
use FireflyIII\Models\Recurrence;
|
||||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
@@ -36,6 +37,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class RecurrenceController extends Controller
|
class RecurrenceController extends Controller
|
||||||
{
|
{
|
||||||
private RecurringRepositoryInterface $repository;
|
private RecurringRepositoryInterface $repository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_RECURRING];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RecurrenceController constructor.
|
* RecurrenceController constructor.
|
||||||
@@ -45,19 +47,16 @@ class RecurrenceController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
$this->repository = app(RecurringRepositoryInterface::class);
|
$this->repository = app(RecurringRepositoryInterface::class);
|
||||||
|
$this->repository->setUser($this->user);
|
||||||
$this->repository->setUser(auth()->user());
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getRecurringAC
|
|
||||||
*/
|
|
||||||
public function recurring(AutocompleteRequest $request): JsonResponse
|
public function recurring(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\Rule;
|
use FireflyIII\Models\Rule;
|
||||||
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
@@ -36,6 +37,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class RuleController extends Controller
|
class RuleController extends Controller
|
||||||
{
|
{
|
||||||
private RuleRepositoryInterface $repository;
|
private RuleRepositoryInterface $repository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_RULES];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RuleController constructor.
|
* RuleController constructor.
|
||||||
@@ -45,18 +47,16 @@ class RuleController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
$this->repository = app(RuleRepositoryInterface::class);
|
$this->repository = app(RuleRepositoryInterface::class);
|
||||||
$this->repository->setUser(auth()->user());
|
$this->repository->setUser($this->user);
|
||||||
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getRulesAC
|
|
||||||
*/
|
|
||||||
public function rules(AutocompleteRequest $request): JsonResponse
|
public function rules(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Models\RuleGroup;
|
||||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
@@ -36,6 +37,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class RuleGroupController extends Controller
|
class RuleGroupController extends Controller
|
||||||
{
|
{
|
||||||
private RuleGroupRepositoryInterface $repository;
|
private RuleGroupRepositoryInterface $repository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_RULES];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RuleGroupController constructor.
|
* RuleGroupController constructor.
|
||||||
@@ -45,18 +47,16 @@ class RuleGroupController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
$this->repository = app(RuleGroupRepositoryInterface::class);
|
$this->repository = app(RuleGroupRepositoryInterface::class);
|
||||||
$this->repository->setUser(auth()->user());
|
$this->repository->setUser($this->user);
|
||||||
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getRuleGroupsAC
|
|
||||||
*/
|
|
||||||
public function ruleGroups(AutocompleteRequest $request): JsonResponse
|
public function ruleGroups(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +37,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class TagController extends Controller
|
class TagController extends Controller
|
||||||
{
|
{
|
||||||
private TagRepositoryInterface $repository;
|
private TagRepositoryInterface $repository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TagController constructor.
|
* TagController constructor.
|
||||||
@@ -46,20 +47,16 @@ class TagController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
/** @var User $user */
|
$this->validateUserGroup($request);
|
||||||
$user = auth()->user();
|
|
||||||
$this->repository = app(TagRepositoryInterface::class);
|
$this->repository = app(TagRepositoryInterface::class);
|
||||||
$this->repository->setUser($user);
|
$this->repository->setUser($this->user);
|
||||||
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getTagAC
|
|
||||||
*/
|
|
||||||
public function tags(AutocompleteRequest $request): JsonResponse
|
public function tags(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ use FireflyIII\Enums\UserRoleEnum;
|
|||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||||
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
@@ -52,24 +51,19 @@ class TransactionController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
/** @var User $user */
|
$this->validateUserGroup($request);
|
||||||
$user = auth()->user();
|
|
||||||
$userGroup = $this->validateUserGroup($request);
|
|
||||||
$this->repository = app(JournalRepositoryInterface::class);
|
$this->repository = app(JournalRepositoryInterface::class);
|
||||||
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
|
$this->groupRepository = app(TransactionGroupRepositoryInterface::class);
|
||||||
$this->repository->setUser($user);
|
$this->repository->setUser($this->user);
|
||||||
$this->groupRepository->setUser($user);
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
$this->groupRepository->setUserGroup($userGroup);
|
$this->groupRepository->setUser($this->user);
|
||||||
|
$this->groupRepository->setUserGroup($this->userGroup);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getTransactionsAC
|
|
||||||
*/
|
|
||||||
public function transactions(AutocompleteRequest $request): JsonResponse
|
public function transactions(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
@@ -92,10 +86,6 @@ class TransactionController extends Controller
|
|||||||
return response()->api($array);
|
return response()->api($array);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getTransactionsIDAC
|
|
||||||
*/
|
|
||||||
public function transactionsWithID(AutocompleteRequest $request): JsonResponse
|
public function transactionsWithID(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Autocomplete;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
use FireflyIII\Api\V1\Requests\Autocomplete\AutocompleteRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface;
|
use FireflyIII\Repositories\TransactionType\TransactionTypeRepositoryInterface;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
@@ -36,6 +37,7 @@ use Illuminate\Http\JsonResponse;
|
|||||||
class TransactionTypeController extends Controller
|
class TransactionTypeController extends Controller
|
||||||
{
|
{
|
||||||
private TransactionTypeRepositoryInterface $repository;
|
private TransactionTypeRepositoryInterface $repository;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TransactionTypeController constructor.
|
* TransactionTypeController constructor.
|
||||||
@@ -45,6 +47,7 @@ class TransactionTypeController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
$this->repository = app(TransactionTypeRepositoryInterface::class);
|
$this->repository = app(TransactionTypeRepositoryInterface::class);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
@@ -52,10 +55,6 @@ class TransactionTypeController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at
|
|
||||||
* * https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/autocomplete/getTransactionTypesAC
|
|
||||||
*/
|
|
||||||
public function transactionTypes(AutocompleteRequest $request): JsonResponse
|
public function transactionTypes(AutocompleteRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$data = $request->getData();
|
$data = $request->getData();
|
||||||
|
|||||||
@@ -26,17 +26,14 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Chart\ChartRequest;
|
use FireflyIII\Api\V1\Requests\Chart\ChartRequest;
|
||||||
use FireflyIII\Enums\AccountTypeEnum;
|
|
||||||
use FireflyIII\Enums\UserRoleEnum;
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\Preference;
|
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Support\Chart\ChartData;
|
|
||||||
use FireflyIII\Support\Facades\Preferences;
|
|
||||||
use FireflyIII\Support\Facades\Steam;
|
use FireflyIII\Support\Facades\Steam;
|
||||||
use FireflyIII\Support\Http\Api\ApiSupport;
|
use FireflyIII\Support\Http\Api\ApiSupport;
|
||||||
|
use FireflyIII\Support\Http\Api\CleansChartData;
|
||||||
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
|
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
@@ -47,11 +44,12 @@ use Illuminate\Support\Facades\Log;
|
|||||||
class AccountController extends Controller
|
class AccountController extends Controller
|
||||||
{
|
{
|
||||||
use ApiSupport;
|
use ApiSupport;
|
||||||
|
use CleansChartData;
|
||||||
use CollectsAccountsFromFilter;
|
use CollectsAccountsFromFilter;
|
||||||
|
|
||||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
|
||||||
private ChartData $chartData;
|
private array $chartData = [];
|
||||||
private AccountRepositoryInterface $repository;
|
private AccountRepositoryInterface $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,11 +60,10 @@ class AccountController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
$this->chartData = new ChartData();
|
|
||||||
$this->repository = app(AccountRepositoryInterface::class);
|
$this->repository = app(AccountRepositoryInterface::class);
|
||||||
|
$this->validateUserGroup($request);
|
||||||
$userGroup = $this->validateUserGroup($request);
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
$this->repository->setUserGroup($userGroup);
|
$this->repository->setUser($this->user);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
@@ -84,7 +81,7 @@ class AccountController extends Controller
|
|||||||
// move date to end of day
|
// move date to end of day
|
||||||
$queryParameters['start']->startOfDay();
|
$queryParameters['start']->startOfDay();
|
||||||
$queryParameters['end']->endOfDay();
|
$queryParameters['end']->endOfDay();
|
||||||
Log::debug(sprintf('dashboard(), convert to primary: %s', var_export($this->convertToPrimary, true)));
|
// Log::debug(sprintf('dashboard(), convert to primary: %s', var_export($this->convertToPrimary, true)));
|
||||||
|
|
||||||
// loop each account, and collect info:
|
// loop each account, and collect info:
|
||||||
/** @var Account $account */
|
/** @var Account $account */
|
||||||
@@ -93,7 +90,7 @@ class AccountController extends Controller
|
|||||||
$this->renderAccountData($queryParameters, $account);
|
$this->renderAccountData($queryParameters, $account);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response()->json($this->chartData->render());
|
return response()->json($this->clean($this->chartData));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,7 +107,7 @@ class AccountController extends Controller
|
|||||||
$previous = array_values($range)[0]['balance'];
|
$previous = array_values($range)[0]['balance'];
|
||||||
$pcPrevious = null;
|
$pcPrevious = null;
|
||||||
if (!$currency instanceof TransactionCurrency) {
|
if (!$currency instanceof TransactionCurrency) {
|
||||||
$currency = $this->default;
|
$currency = $this->primaryCurrency;
|
||||||
}
|
}
|
||||||
$currentSet = [
|
$currentSet = [
|
||||||
'label' => $account->name,
|
'label' => $account->name,
|
||||||
@@ -133,6 +130,7 @@ class AccountController extends Controller
|
|||||||
'yAxisID' => 0,
|
'yAxisID' => 0,
|
||||||
'period' => '1D',
|
'period' => '1D',
|
||||||
'entries' => [],
|
'entries' => [],
|
||||||
|
'pc_entries' => [],
|
||||||
];
|
];
|
||||||
if ($this->convertToPrimary) {
|
if ($this->convertToPrimary) {
|
||||||
$currentSet['pc_entries'] = [];
|
$currentSet['pc_entries'] = [];
|
||||||
@@ -162,21 +160,6 @@ class AccountController extends Controller
|
|||||||
|
|
||||||
$currentStart->addDay();
|
$currentStart->addDay();
|
||||||
}
|
}
|
||||||
$this->chartData->add($currentSet);
|
$this->chartData[] = $currentSet;
|
||||||
}
|
|
||||||
|
|
||||||
private function getFrontPageAccountIds(): array
|
|
||||||
{
|
|
||||||
$defaultSet = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
|
|
||||||
|
|
||||||
/** @var Preference $frontpage */
|
|
||||||
$frontpage = Preferences::get('frontpageAccounts', $defaultSet);
|
|
||||||
|
|
||||||
if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
|
|
||||||
$frontpage->data = $defaultSet;
|
|
||||||
$frontpage->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $frontpage->data ?? $defaultSet;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class BalanceController extends Controller
|
|||||||
use CollectsAccountsFromFilter;
|
use CollectsAccountsFromFilter;
|
||||||
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
|
||||||
private array $chartData;
|
private array $chartData = [];
|
||||||
private GroupCollectorInterface $collector;
|
private GroupCollectorInterface $collector;
|
||||||
private AccountRepositoryInterface $repository;
|
private AccountRepositoryInterface $repository;
|
||||||
|
|
||||||
@@ -38,13 +38,13 @@ class BalanceController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
$this->repository = app(AccountRepositoryInterface::class);
|
$this->repository = app(AccountRepositoryInterface::class);
|
||||||
$this->collector = app(GroupCollectorInterface::class);
|
$this->collector = app(GroupCollectorInterface::class);
|
||||||
$userGroup = $this->validateUserGroup($request);
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
$this->repository->setUserGroup($userGroup);
|
$this->collector->setUserGroup($this->userGroup);
|
||||||
$this->collector->setUserGroup($userGroup);
|
$this->repository->setUser($this->user);
|
||||||
$this->chartData = [];
|
$this->collector->setUser($this->user);
|
||||||
// $this->default = app('amount')->getPrimaryCurrency();
|
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Data\DateRequest;
|
use FireflyIII\Api\V1\Requests\Data\SameDateRequest;
|
||||||
use FireflyIII\Enums\UserRoleEnum;
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
@@ -63,13 +63,16 @@ class BudgetController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
$this->repository = app(BudgetRepositoryInterface::class);
|
$this->repository = app(BudgetRepositoryInterface::class);
|
||||||
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
|
$this->blRepository = app(BudgetLimitRepositoryInterface::class);
|
||||||
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
$this->opsRepository = app(OperationsRepositoryInterface::class);
|
||||||
$userGroup = $this->validateUserGroup($request);
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
$this->repository->setUserGroup($userGroup);
|
$this->opsRepository->setUserGroup($this->userGroup);
|
||||||
$this->opsRepository->setUserGroup($userGroup);
|
$this->blRepository->setUserGroup($this->userGroup);
|
||||||
$this->blRepository->setUserGroup($userGroup);
|
$this->repository->setUser($this->user);
|
||||||
|
$this->opsRepository->setUser($this->user);
|
||||||
|
$this->blRepository->setUser($this->user);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
@@ -81,7 +84,7 @@ class BudgetController extends Controller
|
|||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function overview(DateRequest $request): JsonResponse
|
public function overview(SameDateRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$params = $request->getAll();
|
$params = $request->getAll();
|
||||||
|
|
||||||
@@ -157,12 +160,6 @@ class BudgetController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// if no limits
|
|
||||||
// if (0 === $limits->count()) {
|
|
||||||
// return as a single item in an array
|
|
||||||
// $rows = $this->noBudgetLimits($budget, $start, $end);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// is always an array
|
// is always an array
|
||||||
$return = [];
|
$return = [];
|
||||||
foreach ($rows as $row) {
|
foreach ($rows as $row) {
|
||||||
@@ -193,9 +190,9 @@ class BudgetController extends Controller
|
|||||||
],
|
],
|
||||||
'pc_entries' => [
|
'pc_entries' => [
|
||||||
'budgeted' => $row['pc_budgeted'],
|
'budgeted' => $row['pc_budgeted'],
|
||||||
'spent' => '0',
|
'spent' => $row['pc_spent'],
|
||||||
'left' => '0',
|
'left' => $row['pc_left'],
|
||||||
'overspent' => '0',
|
'overspent' => $row['pc_overspent'],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
$return[] = $current;
|
$return[] = $current;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
|
|||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Data\DateRequest;
|
use FireflyIII\Api\V1\Requests\Data\SameDateRequest;
|
||||||
use FireflyIII\Enums\AccountTypeEnum;
|
use FireflyIII\Enums\AccountTypeEnum;
|
||||||
use FireflyIII\Enums\TransactionTypeEnum;
|
use FireflyIII\Enums\TransactionTypeEnum;
|
||||||
use FireflyIII\Enums\UserRoleEnum;
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
@@ -59,11 +59,13 @@ class CategoryController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
$this->accountRepos = app(AccountRepositoryInterface::class);
|
$this->accountRepos = app(AccountRepositoryInterface::class);
|
||||||
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
|
$this->currencyRepos = app(CurrencyRepositoryInterface::class);
|
||||||
$userGroup = $this->validateUserGroup($request);
|
$this->accountRepos->setUserGroup($this->userGroup);
|
||||||
$this->accountRepos->setUserGroup($userGroup);
|
$this->currencyRepos->setUserGroup($this->userGroup);
|
||||||
$this->currencyRepos->setUserGroup($userGroup);
|
$this->accountRepos->setUser($this->user);
|
||||||
|
$this->currencyRepos->setUser($this->user);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
@@ -78,7 +80,7 @@ class CategoryController extends Controller
|
|||||||
*
|
*
|
||||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||||
*/
|
*/
|
||||||
public function overview(DateRequest $request): JsonResponse
|
public function overview(SameDateRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
/** @var Carbon $start */
|
/** @var Carbon $start */
|
||||||
$start = $this->parameters->get('start');
|
$start = $this->parameters->get('start');
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ abstract class Controller extends BaseController
|
|||||||
private function getParameters(): ParameterBag
|
private function getParameters(): ParameterBag
|
||||||
{
|
{
|
||||||
$bag = new ParameterBag();
|
$bag = new ParameterBag();
|
||||||
$page = (int) request()->get('page');
|
$page = (int)request()->get('page');
|
||||||
if ($page < 1) {
|
if ($page < 1) {
|
||||||
$page = 1;
|
$page = 1;
|
||||||
}
|
}
|
||||||
@@ -131,13 +131,13 @@ abstract class Controller extends BaseController
|
|||||||
$obj = null;
|
$obj = null;
|
||||||
if (null !== $date) {
|
if (null !== $date) {
|
||||||
try {
|
try {
|
||||||
$obj = Carbon::parse((string) $date);
|
$obj = Carbon::parse((string)$date);
|
||||||
} catch (InvalidFormatException $e) {
|
} catch (InvalidFormatException $e) {
|
||||||
// don't care
|
// don't care
|
||||||
Log::warning(
|
Log::warning(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Ignored invalid date "%s" in API controller parameter check: %s',
|
'Ignored invalid date "%s" in API controller parameter check: %s',
|
||||||
substr((string) $date, 0, 20),
|
substr((string)$date, 0, 20),
|
||||||
$e->getMessage()
|
$e->getMessage()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -158,7 +158,7 @@ abstract class Controller extends BaseController
|
|||||||
$value = null;
|
$value = null;
|
||||||
}
|
}
|
||||||
if (null !== $value) {
|
if (null !== $value) {
|
||||||
$value = (int) $value;
|
$value = (int)$value;
|
||||||
if ($value < 1) {
|
if ($value < 1) {
|
||||||
$value = 1;
|
$value = 1;
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ abstract class Controller extends BaseController
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
/** @var Preference $pageSize */
|
/** @var Preference $pageSize */
|
||||||
$pageSize = (int) app('preferences')->getForUser($user, 'listPageSize', 50)->data;
|
$pageSize = (int)app('preferences')->getForUser($user, 'listPageSize', 50)->data;
|
||||||
$bag->set($integer, $pageSize);
|
$bag->set($integer, $pageSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ abstract class Controller extends BaseController
|
|||||||
$sortParameters = [];
|
$sortParameters = [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$param = (string) request()->query->get('sort');
|
$param = (string)request()->query->get('sort');
|
||||||
} catch (BadRequestException $e) {
|
} catch (BadRequestException $e) {
|
||||||
Log::error('Request field "sort" contains a non-scalar value. Value set to NULL.');
|
Log::error('Request field "sort" contains a non-scalar value. Value set to NULL.');
|
||||||
Log::error($e->getMessage());
|
Log::error($e->getMessage());
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Data\Bulk;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Data\Bulk\TransactionRequest;
|
use FireflyIII\Api\V1\Requests\Data\Bulk\TransactionRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
|
use FireflyIII\Services\Internal\Destroy\AccountDestroyService;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
@@ -44,23 +45,23 @@ class TransactionController extends Controller
|
|||||||
{
|
{
|
||||||
private AccountRepositoryInterface $repository;
|
private AccountRepositoryInterface $repository;
|
||||||
|
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::MANAGE_TRANSACTIONS];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
$this->repository = app(AccountRepositoryInterface::class);
|
$this->repository = app(AccountRepositoryInterface::class);
|
||||||
$this->repository->setUser(auth()->user());
|
$this->repository->setUserGroup($this->userGroup);
|
||||||
|
$this->repository->setUser($this->user);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/bulkUpdateTransactions
|
|
||||||
*/
|
|
||||||
public function update(TransactionRequest $request): JsonResponse
|
public function update(TransactionRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$query = $request->getAll();
|
$query = $request->getAll();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
|
|||||||
use FireflyIII\Api\V1\Requests\Data\DestroyRequest;
|
use FireflyIII\Api\V1\Requests\Data\DestroyRequest;
|
||||||
use FireflyIII\Enums\AccountTypeEnum;
|
use FireflyIII\Enums\AccountTypeEnum;
|
||||||
use FireflyIII\Enums\TransactionTypeEnum;
|
use FireflyIII\Enums\TransactionTypeEnum;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
@@ -55,12 +56,20 @@ class DestroyController extends Controller
|
|||||||
{
|
{
|
||||||
private bool $unused;
|
private bool $unused;
|
||||||
|
|
||||||
/**
|
protected array $acceptedRoles = [UserRoleEnum::FULL];
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/destroyData
|
public function __construct()
|
||||||
*
|
{
|
||||||
* @throws FireflyException
|
parent::__construct();
|
||||||
*/
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function destroy(DestroyRequest $request): JsonResponse
|
public function destroy(DestroyRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$objects = $request->getObjects();
|
$objects = $request->getObjects();
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Data\Export;
|
|||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\Data\Export\ExportRequest;
|
use FireflyIII\Api\V1\Requests\Data\Export\ExportRequest;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Support\Export\ExportDataGenerator;
|
use FireflyIII\Support\Export\ExportDataGenerator;
|
||||||
use Illuminate\Http\Response as LaravelResponse;
|
use Illuminate\Http\Response as LaravelResponse;
|
||||||
@@ -39,6 +40,7 @@ use function Safe\date;
|
|||||||
class ExportController extends Controller
|
class ExportController extends Controller
|
||||||
{
|
{
|
||||||
private ExportDataGenerator $exporter;
|
private ExportDataGenerator $exporter;
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ExportController constructor.
|
* ExportController constructor.
|
||||||
@@ -48,8 +50,10 @@ class ExportController extends Controller
|
|||||||
parent::__construct();
|
parent::__construct();
|
||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
$this->exporter = app(ExportDataGenerator::class);
|
$this->exporter = app(ExportDataGenerator::class);
|
||||||
$this->exporter->setUser(auth()->user());
|
$this->exporter->setUserGroup($this->userGroup);
|
||||||
|
$this->exporter->setUser($this->user);
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
@@ -57,9 +61,6 @@ class ExportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportAccounts
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*
|
*
|
||||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||||
@@ -99,9 +100,6 @@ class ExportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportBills
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*
|
*
|
||||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||||
@@ -114,9 +112,6 @@ class ExportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportBudgets
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*
|
*
|
||||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||||
@@ -129,9 +124,6 @@ class ExportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportCategories
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*
|
*
|
||||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||||
@@ -144,9 +136,6 @@ class ExportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportPiggies
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*
|
*
|
||||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||||
@@ -159,9 +148,6 @@ class ExportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportRecurring
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*
|
*
|
||||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||||
@@ -174,9 +160,6 @@ class ExportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportRules
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*
|
*
|
||||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||||
@@ -189,9 +172,6 @@ class ExportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportTags
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*
|
*
|
||||||
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
|
||||||
@@ -204,9 +184,6 @@ class ExportController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/exportTransactions
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function transactions(ExportRequest $request): LaravelResponse
|
public function transactions(ExportRequest $request): LaravelResponse
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V1\Controllers\Data;
|
namespace FireflyIII\Api\V1\Controllers\Data;
|
||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
|
use FireflyIII\Enums\UserRoleEnum;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\Bill;
|
use FireflyIII\Models\Bill;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
@@ -44,10 +45,22 @@ use Illuminate\Http\JsonResponse;
|
|||||||
*/
|
*/
|
||||||
class PurgeController extends Controller
|
class PurgeController extends Controller
|
||||||
{
|
{
|
||||||
|
protected array $acceptedRoles = [UserRoleEnum::FULL];
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
$this->middleware(
|
||||||
|
function ($request, $next) {
|
||||||
|
$this->validateUserGroup($request);
|
||||||
|
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO cleanup and use repositories.
|
* TODO cleanup and use repositories.
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/data/purgeData
|
|
||||||
*/
|
*/
|
||||||
public function purge(): JsonResponse
|
public function purge(): JsonResponse
|
||||||
{
|
{
|
||||||
@@ -66,14 +79,6 @@ class PurgeController extends Controller
|
|||||||
$repository = app(PiggyBankRepositoryInterface::class);
|
$repository = app(PiggyBankRepositoryInterface::class);
|
||||||
$repository->setUser($user);
|
$repository->setUser($user);
|
||||||
$repository->purgeAll();
|
$repository->purgeAll();
|
||||||
// $set = PiggyBank::leftJoin('accounts', 'accounts.id', 'piggy_banks.account_id')
|
|
||||||
// ->where('accounts.user_id', $user->id)->onlyTrashed()->get(['piggy_banks.*'])
|
|
||||||
// ;
|
|
||||||
//
|
|
||||||
// /** @var PiggyBank $piggy */
|
|
||||||
// foreach ($set as $piggy) {
|
|
||||||
// $piggy->forceDelete();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// rule group
|
// rule group
|
||||||
RuleGroup::whereUserId($user->id)->onlyTrashed()->forceDelete();
|
RuleGroup::whereUserId($user->id)->onlyTrashed()->forceDelete();
|
||||||
|
|||||||
@@ -64,10 +64,6 @@ class AccountController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseAsset
|
|
||||||
*/
|
|
||||||
public function asset(GenericRequest $request): JsonResponse
|
public function asset(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
@@ -91,10 +87,6 @@ class AccountController extends Controller
|
|||||||
return response()->json($result);
|
return response()->json($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseExpense
|
|
||||||
*/
|
|
||||||
public function expense(GenericRequest $request): JsonResponse
|
public function expense(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
|
|||||||
@@ -58,9 +58,6 @@ class BillController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseBill
|
|
||||||
*
|
|
||||||
* Expenses per bill, possibly filtered by bill and account.
|
* Expenses per bill, possibly filtered by bill and account.
|
||||||
*/
|
*/
|
||||||
public function bill(GenericRequest $request): JsonResponse
|
public function bill(GenericRequest $request): JsonResponse
|
||||||
@@ -122,9 +119,6 @@ class BillController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseNoBill
|
|
||||||
*
|
|
||||||
* Expenses for no bill filtered by account.
|
* Expenses for no bill filtered by account.
|
||||||
*/
|
*/
|
||||||
public function noBill(GenericRequest $request): JsonResponse
|
public function noBill(GenericRequest $request): JsonResponse
|
||||||
|
|||||||
@@ -63,10 +63,6 @@ class BudgetController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseBudget
|
|
||||||
*/
|
|
||||||
public function budget(GenericRequest $request): JsonResponse
|
public function budget(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
@@ -98,10 +94,6 @@ class BudgetController extends Controller
|
|||||||
return response()->json($result);
|
return response()->json($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseNoBudget
|
|
||||||
*/
|
|
||||||
public function noBudget(GenericRequest $request): JsonResponse
|
public function noBudget(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
|
|||||||
@@ -63,10 +63,6 @@ class CategoryController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightTransferCategory
|
|
||||||
*/
|
|
||||||
public function category(GenericRequest $request): JsonResponse
|
public function category(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
@@ -98,10 +94,6 @@ class CategoryController extends Controller
|
|||||||
return response()->json($result);
|
return response()->json($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightTransferNoCategory
|
|
||||||
*/
|
|
||||||
public function noCategory(GenericRequest $request): JsonResponse
|
public function noCategory(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
|
|||||||
@@ -37,10 +37,6 @@ use Illuminate\Support\Facades\Log;
|
|||||||
*/
|
*/
|
||||||
class PeriodController extends Controller
|
class PeriodController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseTotal
|
|
||||||
*/
|
|
||||||
public function total(GenericRequest $request): JsonResponse
|
public function total(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$accounts = $request->getAssetAccounts();
|
$accounts = $request->getAssetAccounts();
|
||||||
|
|||||||
@@ -57,9 +57,6 @@ class TagController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseNoTag
|
|
||||||
*
|
|
||||||
* Expenses for no tag filtered by account.
|
* Expenses for no tag filtered by account.
|
||||||
*/
|
*/
|
||||||
public function noTag(GenericRequest $request): JsonResponse
|
public function noTag(GenericRequest $request): JsonResponse
|
||||||
@@ -115,9 +112,6 @@ class TagController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightExpenseTag
|
|
||||||
*
|
|
||||||
* Expenses per tag, possibly filtered by tag and account.
|
* Expenses per tag, possibly filtered by tag and account.
|
||||||
*/
|
*/
|
||||||
public function tag(GenericRequest $request): JsonResponse
|
public function tag(GenericRequest $request): JsonResponse
|
||||||
|
|||||||
@@ -64,10 +64,6 @@ class AccountController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightIncomeAsset
|
|
||||||
*/
|
|
||||||
public function asset(GenericRequest $request): JsonResponse
|
public function asset(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
@@ -92,10 +88,6 @@ class AccountController extends Controller
|
|||||||
return response()->json($result);
|
return response()->json($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightIncomeRevenue
|
|
||||||
*/
|
|
||||||
public function revenue(GenericRequest $request): JsonResponse
|
public function revenue(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
|
|||||||
@@ -63,10 +63,6 @@ class CategoryController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightIncomeCategory
|
|
||||||
*/
|
|
||||||
public function category(GenericRequest $request): JsonResponse
|
public function category(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
@@ -98,10 +94,6 @@ class CategoryController extends Controller
|
|||||||
return response()->json($result);
|
return response()->json($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightIncomeNoCategory
|
|
||||||
*/
|
|
||||||
public function noCategory(GenericRequest $request): JsonResponse
|
public function noCategory(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ use Illuminate\Http\JsonResponse;
|
|||||||
*/
|
*/
|
||||||
class PeriodController extends Controller
|
class PeriodController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightIncomeTotal
|
|
||||||
*/
|
|
||||||
public function total(GenericRequest $request): JsonResponse
|
public function total(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$accounts = $request->getAssetAccounts();
|
$accounts = $request->getAssetAccounts();
|
||||||
|
|||||||
@@ -57,9 +57,6 @@ class TagController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightIncomeTag
|
|
||||||
*
|
|
||||||
* Expenses for no tag filtered by account.
|
* Expenses for no tag filtered by account.
|
||||||
*/
|
*/
|
||||||
public function noTag(GenericRequest $request): JsonResponse
|
public function noTag(GenericRequest $request): JsonResponse
|
||||||
@@ -109,9 +106,6 @@ class TagController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightIncomeNoTag
|
|
||||||
*
|
|
||||||
* Expenses per tag, possibly filtered by tag and account.
|
* Expenses per tag, possibly filtered by tag and account.
|
||||||
*/
|
*/
|
||||||
public function tag(GenericRequest $request): JsonResponse
|
public function tag(GenericRequest $request): JsonResponse
|
||||||
|
|||||||
@@ -56,10 +56,6 @@ class AccountController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightTransfers
|
|
||||||
*/
|
|
||||||
public function asset(GenericRequest $request): JsonResponse
|
public function asset(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
|
|||||||
@@ -63,10 +63,6 @@ class CategoryController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightTransferCategory
|
|
||||||
*/
|
|
||||||
public function category(GenericRequest $request): JsonResponse
|
public function category(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
@@ -98,10 +94,6 @@ class CategoryController extends Controller
|
|||||||
return response()->json($result);
|
return response()->json($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightTransferNoCategory
|
|
||||||
*/
|
|
||||||
public function noCategory(GenericRequest $request): JsonResponse
|
public function noCategory(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$start = $request->getStart();
|
$start = $request->getStart();
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ use Illuminate\Http\JsonResponse;
|
|||||||
*/
|
*/
|
||||||
class PeriodController extends Controller
|
class PeriodController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightTransferTotal
|
|
||||||
*/
|
|
||||||
public function total(GenericRequest $request): JsonResponse
|
public function total(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$accounts = $request->getAssetAccounts();
|
$accounts = $request->getAssetAccounts();
|
||||||
|
|||||||
@@ -56,10 +56,6 @@ class TagController extends Controller
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightTransferNoTag
|
|
||||||
*/
|
|
||||||
public function noTag(GenericRequest $request): JsonResponse
|
public function noTag(GenericRequest $request): JsonResponse
|
||||||
{
|
{
|
||||||
$accounts = $request->getAssetAccounts();
|
$accounts = $request->getAssetAccounts();
|
||||||
@@ -108,9 +104,6 @@ class TagController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/insight/insightTransferTag
|
|
||||||
*
|
|
||||||
* Transfers per tag, possibly filtered by tag and account.
|
* Transfers per tag, possibly filtered by tag and account.
|
||||||
*/
|
*/
|
||||||
public function tag(GenericRequest $request): JsonResponse
|
public function tag(GenericRequest $request): JsonResponse
|
||||||
|
|||||||
@@ -55,9 +55,6 @@ class DestroyController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/accounts/deleteAccount
|
|
||||||
*
|
|
||||||
* Remove the specified resource from storage.
|
* Remove the specified resource from storage.
|
||||||
*/
|
*/
|
||||||
public function destroy(Account $account): JsonResponse
|
public function destroy(Account $account): JsonResponse
|
||||||
|
|||||||
@@ -71,9 +71,6 @@ class ListController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/accounts/listAttachmentByAccount
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function attachments(Account $account): JsonResponse
|
public function attachments(Account $account): JsonResponse
|
||||||
@@ -100,9 +97,6 @@ class ListController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/accounts/listPiggyBankByAccount
|
|
||||||
*
|
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function piggyBanks(Account $account): JsonResponse
|
public function piggyBanks(Account $account): JsonResponse
|
||||||
@@ -140,9 +134,6 @@ class ListController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/accounts/listTransactionByAccount
|
|
||||||
*
|
|
||||||
* Show all transaction groups related to the account.
|
* Show all transaction groups related to the account.
|
||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
|||||||
@@ -67,9 +67,6 @@ class ShowController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This endpoint is documented at:
|
|
||||||
* https://api-docs.firefly-iii.org/?urls.primaryName=2.0.0%20(v1)#/accounts/listAccount
|
|
||||||
*
|
|
||||||
* Display a listing of the resource.
|
* Display a listing of the resource.
|
||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ use FireflyIII\Models\Budget;
|
|||||||
use FireflyIII\Models\BudgetLimit;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
|
use FireflyIII\Support\JsonApi\Enrichments\BudgetEnrichment;
|
||||||
use FireflyIII\Support\JsonApi\Enrichments\BudgetLimitEnrichment;
|
use FireflyIII\Support\JsonApi\Enrichments\BudgetLimitEnrichment;
|
||||||
use FireflyIII\Transformers\BudgetLimitTransformer;
|
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
@@ -76,6 +77,16 @@ class ShowController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function index(Budget $budget): JsonResponse
|
public function index(Budget $budget): JsonResponse
|
||||||
{
|
{
|
||||||
|
/** @var User $admin */
|
||||||
|
$admin = auth()->user();
|
||||||
|
// enrich budget:
|
||||||
|
$enrichment = new BudgetEnrichment();
|
||||||
|
$enrichment->setUser($admin);
|
||||||
|
$enrichment->setStart($this->parameters->get('start'));
|
||||||
|
$enrichment->setEnd($this->parameters->get('end'));
|
||||||
|
$budget = $enrichment->enrichSingle($budget);
|
||||||
|
|
||||||
|
|
||||||
$manager = $this->getManager();
|
$manager = $this->getManager();
|
||||||
$manager->parseIncludes('budget');
|
$manager->parseIncludes('budget');
|
||||||
$pageSize = $this->parameters->get('limit');
|
$pageSize = $this->parameters->get('limit');
|
||||||
@@ -85,10 +96,7 @@ class ShowController extends Controller
|
|||||||
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
|
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
|
||||||
$paginator->setPath(route('api.v1.budgets.limits.index', [$budget->id]).$this->buildParams());
|
$paginator->setPath(route('api.v1.budgets.limits.index', [$budget->id]).$this->buildParams());
|
||||||
|
|
||||||
|
|
||||||
// enrich
|
// enrich
|
||||||
/** @var User $admin */
|
|
||||||
$admin = auth()->user();
|
|
||||||
$enrichment = new BudgetLimitEnrichment();
|
$enrichment = new BudgetLimitEnrichment();
|
||||||
$enrichment->setUser($admin);
|
$enrichment->setUser($admin);
|
||||||
$budgetLimits = $enrichment->enrich($budgetLimits);
|
$budgetLimits = $enrichment->enrich($budgetLimits);
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ class ShowController extends Controller
|
|||||||
*
|
*
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function showDefault(): JsonResponse
|
public function showPrimary(): JsonResponse
|
||||||
{
|
{
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class StoreController extends Controller
|
|||||||
{
|
{
|
||||||
$currency = $this->repository->store($request->getAll());
|
$currency = $this->repository->store($request->getAll());
|
||||||
if (true === $request->boolean('default')) {
|
if (true === $request->boolean('default')) {
|
||||||
$this->repository->makeDefault($currency);
|
$this->repository->makePrimary($currency);
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
}
|
}
|
||||||
$manager = $this->getManager();
|
$manager = $this->getManager();
|
||||||
|
|||||||
@@ -101,12 +101,12 @@ class UpdateController extends Controller
|
|||||||
/**
|
/**
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function makeDefault(TransactionCurrency $currency): JsonResponse
|
public function makePrimary(TransactionCurrency $currency): JsonResponse
|
||||||
{
|
{
|
||||||
/** @var User $user */
|
/** @var User $user */
|
||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
$this->repository->enable($currency);
|
$this->repository->enable($currency);
|
||||||
$this->repository->makeDefault($currency);
|
$this->repository->makePrimary($currency);
|
||||||
|
|
||||||
app('preferences')->mark();
|
app('preferences')->mark();
|
||||||
|
|
||||||
|
|||||||
@@ -24,15 +24,18 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Controllers\System;
|
namespace FireflyIII\Api\V1\Controllers\System;
|
||||||
|
|
||||||
use FireflyIII\Support\Facades\FireflyConfig;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Illuminate\Support\Facades\Validator;
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
use FireflyIII\Api\V1\Requests\System\UpdateRequest;
|
use FireflyIII\Api\V1\Requests\System\UpdateRequest;
|
||||||
|
use FireflyIII\Enums\WebhookDelivery;
|
||||||
|
use FireflyIII\Enums\WebhookResponse;
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\Support\Binder\EitherConfigKey;
|
use FireflyIII\Support\Binder\EitherConfigKey;
|
||||||
|
use FireflyIII\Support\Facades\FireflyConfig;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,8 +110,8 @@ class ConfigurationController extends Controller
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
'is_demo_site' => $isDemoSite?->data,
|
'is_demo_site' => $isDemoSite?->data,
|
||||||
'permission_update_check' => null === $updateCheck ? null : (int) $updateCheck->data,
|
'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data,
|
||||||
'last_update_check' => null === $lastCheck ? null : (int) $lastCheck->data,
|
'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data,
|
||||||
'single_user_mode' => $singleUser?->data,
|
'single_user_mode' => $singleUser?->data,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -139,7 +142,20 @@ class ConfigurationController extends Controller
|
|||||||
'value' => $dynamic[$shortKey],
|
'value' => $dynamic[$shortKey],
|
||||||
'editable' => true,
|
'editable' => true,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
|
||||||
}
|
}
|
||||||
|
if (str_starts_with($configKey, 'webhook.')) {
|
||||||
|
$data = [
|
||||||
|
'title' => $configKey,
|
||||||
|
'value' => $this->getWebhookConfiguration($configKey),
|
||||||
|
'editable' => false,
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->api(['data' => $data])->header('Content-Type', self::JSON_CONTENT_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback
|
||||||
if (!str_starts_with($configKey, 'configuration.')) {
|
if (!str_starts_with($configKey, 'configuration.')) {
|
||||||
$data = [
|
$data = [
|
||||||
'title' => $configKey,
|
'title' => $configKey,
|
||||||
@@ -182,4 +198,39 @@ class ConfigurationController extends Controller
|
|||||||
|
|
||||||
return response()->api(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
|
return response()->api(['data' => $data])->header('Content-Type', self::CONTENT_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getWebhookConfiguration(string $configKey): array
|
||||||
|
{
|
||||||
|
switch ($configKey) {
|
||||||
|
case 'webhook.triggers':
|
||||||
|
$cases = WebhookTrigger::cases();
|
||||||
|
$data = [];
|
||||||
|
foreach ($cases as $c) {
|
||||||
|
$data[$c->name] = $c->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
|
||||||
|
case 'webhook.responses':
|
||||||
|
$cases = WebhookResponse::cases();
|
||||||
|
$data = [];
|
||||||
|
foreach ($cases as $c) {
|
||||||
|
$data[$c->name] = $c->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
|
||||||
|
case 'webhook.deliveries':
|
||||||
|
$cases = WebhookDelivery::cases();
|
||||||
|
$data = [];
|
||||||
|
foreach ($cases as $c) {
|
||||||
|
$data[$c->name] = $c->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new FireflyException(sprintf('Unknown webhook configuration key "%s".', $configKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Api\V1\Controllers\Webhook;
|
namespace FireflyIII\Api\V1\Controllers\Webhook;
|
||||||
|
|
||||||
use FireflyIII\Api\V1\Controllers\Controller;
|
use FireflyIII\Api\V1\Controllers\Controller;
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\Events\RequestedSendWebhookMessages;
|
use FireflyIII\Events\RequestedSendWebhookMessages;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
|
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
|
||||||
@@ -146,7 +147,7 @@ class ShowController extends Controller
|
|||||||
$engine->setUser(auth()->user());
|
$engine->setUser(auth()->user());
|
||||||
|
|
||||||
// tell the generator which trigger it should look for
|
// tell the generator which trigger it should look for
|
||||||
$engine->setTrigger($webhook->trigger);
|
$engine->setTrigger(WebhookTrigger::tryFrom($webhook->trigger));
|
||||||
// tell the generator which objects to process
|
// tell the generator which objects to process
|
||||||
$engine->setObjects(new Collection([$group]));
|
$engine->setObjects(new Collection([$group]));
|
||||||
// set the webhook to trigger
|
// set the webhook to trigger
|
||||||
|
|||||||
@@ -24,11 +24,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
|
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
|
||||||
|
|
||||||
|
use FireflyIII\Enums\WebhookResponse;
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\Models\Webhook;
|
use FireflyIII\Models\Webhook;
|
||||||
use FireflyIII\Rules\IsBoolean;
|
use FireflyIII\Rules\IsBoolean;
|
||||||
use FireflyIII\Support\Request\ChecksLogin;
|
use FireflyIII\Support\Request\ChecksLogin;
|
||||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||||
|
use Illuminate\Contracts\Validation\Validator;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class CreateRequest
|
* Class CreateRequest
|
||||||
@@ -55,9 +59,9 @@ class CreateRequest extends FormRequest
|
|||||||
|
|
||||||
// this is the way.
|
// this is the way.
|
||||||
$return = $this->getAllData($fields);
|
$return = $this->getAllData($fields);
|
||||||
$return['trigger'] = $triggers[$return['trigger']] ?? (int) $return['trigger'];
|
$return['trigger'] = $triggers[$return['trigger']] ?? (int)$return['trigger'];
|
||||||
$return['response'] = $responses[$return['response']] ?? (int) $return['response'];
|
$return['response'] = $responses[$return['response']] ?? (int)$return['response'];
|
||||||
$return['delivery'] = $deliveries[$return['delivery']] ?? (int) $return['delivery'];
|
$return['delivery'] = $deliveries[$return['delivery']] ?? (int)$return['delivery'];
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
@@ -81,4 +85,45 @@ class CreateRequest extends FormRequest
|
|||||||
'url' => ['required', sprintf('url:%s', $validProtocols), 'uniqueWebhook'],
|
'url' => ['required', sprintf('url:%s', $validProtocols), 'uniqueWebhook'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withValidator(Validator $validator): void
|
||||||
|
{
|
||||||
|
$validator->after(
|
||||||
|
function (Validator $validator): void {
|
||||||
|
Log::debug('Validating webhook');
|
||||||
|
$data = $validator->getData();
|
||||||
|
$trigger = $data['trigger'] ?? null;
|
||||||
|
$response = $data['response'] ?? null;
|
||||||
|
if (null === $trigger || null === $response) {
|
||||||
|
Log::debug('No trigger or response, return.');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$triggers = array_keys(Webhook::getTriggersForValidation());
|
||||||
|
$responses = array_keys(Webhook::getResponsesForValidation());
|
||||||
|
if (!in_array($trigger, $triggers, true) || !in_array($response, $responses, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// cannot deliver budget info.
|
||||||
|
if (is_int($trigger)) {
|
||||||
|
Log::debug(sprintf('Trigger was integer (%d).', $trigger));
|
||||||
|
$trigger = WebhookTrigger::from($trigger)->name;
|
||||||
|
}
|
||||||
|
if (is_int($response)) {
|
||||||
|
Log::debug(sprintf('Response was integer (%d).', $response));
|
||||||
|
$response = WebhookResponse::from($response)->name;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Trigger is %s, response is %s', $trigger, $response));
|
||||||
|
if (str_contains($trigger, 'TRANSACTION') && str_contains($response, 'BUDGET')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_budget_info'));
|
||||||
|
}
|
||||||
|
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'ACCOUNT')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_account_info'));
|
||||||
|
}
|
||||||
|
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'TRANSACTION')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_transaction_info'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,11 +24,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
|
namespace FireflyIII\Api\V1\Requests\Models\Webhook;
|
||||||
|
|
||||||
|
use FireflyIII\Enums\WebhookResponse;
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\Models\Webhook;
|
use FireflyIII\Models\Webhook;
|
||||||
use FireflyIII\Rules\IsBoolean;
|
use FireflyIII\Rules\IsBoolean;
|
||||||
use FireflyIII\Support\Request\ChecksLogin;
|
use FireflyIII\Support\Request\ChecksLogin;
|
||||||
use FireflyIII\Support\Request\ConvertsDataTypes;
|
use FireflyIII\Support\Request\ConvertsDataTypes;
|
||||||
|
use Illuminate\Contracts\Validation\Validator;
|
||||||
use Illuminate\Foundation\Http\FormRequest;
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class UpdateRequest
|
* Class UpdateRequest
|
||||||
@@ -94,4 +98,45 @@ class UpdateRequest extends FormRequest
|
|||||||
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)],
|
'url' => [sprintf('url:%s', $validProtocols), sprintf('uniqueExistingWebhook:%d', $webhook->id)],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function withValidator(Validator $validator): void
|
||||||
|
{
|
||||||
|
$validator->after(
|
||||||
|
function (Validator $validator): void {
|
||||||
|
Log::debug('Validating webhook');
|
||||||
|
$data = $validator->getData();
|
||||||
|
$trigger = $data['trigger'] ?? null;
|
||||||
|
$response = $data['response'] ?? null;
|
||||||
|
if (null === $trigger || null === $response) {
|
||||||
|
Log::debug('No trigger or response, return.');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$triggers = array_keys(Webhook::getTriggersForValidation());
|
||||||
|
$responses = array_keys(Webhook::getResponsesForValidation());
|
||||||
|
if (!in_array($trigger, $triggers, true) || !in_array($response, $responses, true)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// cannot deliver budget info.
|
||||||
|
if (is_int($trigger)) {
|
||||||
|
Log::debug(sprintf('Trigger was integer (%d).', $trigger));
|
||||||
|
$trigger = WebhookTrigger::from($trigger)->name;
|
||||||
|
}
|
||||||
|
if (is_int($response)) {
|
||||||
|
Log::debug(sprintf('Response was integer (%d).', $response));
|
||||||
|
$response = WebhookResponse::from($response)->name;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Trigger is %s, response is %s', $trigger, $response));
|
||||||
|
if (str_contains($trigger, 'TRANSACTION') && str_contains($response, 'BUDGET')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_budget_info'));
|
||||||
|
}
|
||||||
|
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'ACCOUNT')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_account_info'));
|
||||||
|
}
|
||||||
|
if (str_contains($trigger, 'BUDGET') && str_contains($response, 'TRANSACTION')) {
|
||||||
|
$validator->errors()->add('response', trans('validation.webhook_transaction_info'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,14 +49,23 @@ class ValidatesEnvironmentVariables extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle(): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
$this->validateLanguage();
|
$result = $this->validateLanguage();
|
||||||
$this->validateGuard();
|
if (false === $result) {
|
||||||
$this->validateStaticToken();
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
$result = $this->validateGuard();
|
||||||
|
if (false === $result) {
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
$result = $this->validateStaticToken();
|
||||||
|
if (false === $result) {
|
||||||
|
return Command::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
return Command::SUCCESS;
|
return Command::SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function validateLanguage(): void
|
private function validateLanguage(): bool
|
||||||
{
|
{
|
||||||
$language = config('firefly.default_language');
|
$language = config('firefly.default_language');
|
||||||
$locale = config('firefly.default_locale');
|
$locale = config('firefly.default_locale');
|
||||||
@@ -67,7 +76,7 @@ class ValidatesEnvironmentVariables extends Command
|
|||||||
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
||||||
$this->friendlyError(sprintf('Valid languages are: %s', implode(', ', $options)));
|
$this->friendlyError(sprintf('Valid languages are: %s', implode(', ', $options)));
|
||||||
|
|
||||||
exit(1);
|
return false;
|
||||||
}
|
}
|
||||||
$options[] = 'equal';
|
$options[] = 'equal';
|
||||||
if (!in_array($locale, $options, true)) {
|
if (!in_array($locale, $options, true)) {
|
||||||
@@ -75,11 +84,13 @@ class ValidatesEnvironmentVariables extends Command
|
|||||||
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
||||||
$this->friendlyError(sprintf('Valid locales are: %s', implode(', ', $options)));
|
$this->friendlyError(sprintf('Valid locales are: %s', implode(', ', $options)));
|
||||||
|
|
||||||
exit(1);
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function validateGuard(): void
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validateGuard(): bool
|
||||||
{
|
{
|
||||||
$guard = config('auth.defaults.guard');
|
$guard = config('auth.defaults.guard');
|
||||||
if ('web' !== $guard && 'remote_user_guard' !== $guard) {
|
if ('web' !== $guard && 'remote_user_guard' !== $guard) {
|
||||||
@@ -87,18 +98,22 @@ class ValidatesEnvironmentVariables extends Command
|
|||||||
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
||||||
$this->friendlyError('Valid guards are: web, remote_user_guard');
|
$this->friendlyError('Valid guards are: web, remote_user_guard');
|
||||||
|
|
||||||
exit(1);
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function validateStaticToken(): void
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validateStaticToken(): bool
|
||||||
{
|
{
|
||||||
$token = (string) config('firefly.static_cron_token');
|
$token = (string)config('firefly.static_cron_token');
|
||||||
if ('' !== $token && 32 !== strlen($token)) {
|
if ('' !== $token && 32 !== strlen($token)) {
|
||||||
$this->friendlyError('STATIC_CRON_TOKEN must be empty or a 32-character string.');
|
$this->friendlyError('STATIC_CRON_TOKEN must be empty or a 32-character string.');
|
||||||
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
$this->friendlyError('Please check your .env file and make sure you use a valid setting.');
|
||||||
|
|
||||||
exit(1);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
60
app/Console/Commands/System/ResetsErrorMailLimit.php
Normal file
60
app/Console/Commands/System/ResetsErrorMailLimit.php
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Console\Commands\System;
|
||||||
|
|
||||||
|
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Symfony\Component\Console\Command\Command as CommandAlias;
|
||||||
|
|
||||||
|
class ResetsErrorMailLimit extends Command
|
||||||
|
{
|
||||||
|
use ShowsFriendlyMessages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'firefly-iii:reset-error-mail-limit';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Resets the number of error mails sent.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle(): int
|
||||||
|
{
|
||||||
|
$file = storage_path('framework/cache/error-count.json');
|
||||||
|
$directory = storage_path('framework/cache');
|
||||||
|
$limits = [];
|
||||||
|
|
||||||
|
if (!is_writable($directory)) {
|
||||||
|
$this->friendlyError(sprintf('Cannot write to directory "%s", cannot rate limit errors.', $directory));
|
||||||
|
|
||||||
|
return CommandAlias::FAILURE;
|
||||||
|
}
|
||||||
|
if (!file_exists($file)) {
|
||||||
|
$this->friendlyInfo(sprintf('Created new limits file at "%s"', $file));
|
||||||
|
file_put_contents($file, json_encode($limits, JSON_PRETTY_PRINT));
|
||||||
|
|
||||||
|
return CommandAlias::SUCCESS;
|
||||||
|
}
|
||||||
|
if (!is_writable($file)) {
|
||||||
|
$this->friendlyError(sprintf('Cannot write to "%s", cannot rate limit errors.', $file));
|
||||||
|
|
||||||
|
return CommandAlias::FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->friendlyInfo(sprintf('Successfully reset the error rate-limits file located at "%s"', $file));
|
||||||
|
file_put_contents($file, json_encode($limits, JSON_PRETTY_PRINT));
|
||||||
|
|
||||||
|
return CommandAlias::SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,12 +29,16 @@ use FireflyIII\Models\Attachment;
|
|||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Contracts\Encryption\DecryptException;
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Illuminate\Support\Facades\Crypt;
|
use Illuminate\Support\Facades\Crypt;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Safe\Exceptions\FileinfoException;
|
||||||
|
use Safe\Exceptions\FilesystemException;
|
||||||
|
use Safe\Exceptions\StringsException;
|
||||||
|
|
||||||
use function Safe\tempnam;
|
|
||||||
use function Safe\file_put_contents;
|
use function Safe\file_put_contents;
|
||||||
use function Safe\md5_file;
|
use function Safe\md5_file;
|
||||||
use function Safe\mime_content_type;
|
use function Safe\mime_content_type;
|
||||||
|
use function Safe\tempnam;
|
||||||
|
|
||||||
class ScansAttachments extends Command
|
class ScansAttachments extends Command
|
||||||
{
|
{
|
||||||
@@ -46,6 +50,10 @@ class ScansAttachments extends Command
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @throws FilesystemException
|
||||||
|
* @throws StringsException
|
||||||
|
* @throws FileinfoException
|
||||||
*/
|
*/
|
||||||
public function handle(): int
|
public function handle(): int
|
||||||
{
|
{
|
||||||
@@ -57,7 +65,7 @@ class ScansAttachments extends Command
|
|||||||
$fileName = $attachment->fileName();
|
$fileName = $attachment->fileName();
|
||||||
$encryptedContent = $disk->get($fileName);
|
$encryptedContent = $disk->get($fileName);
|
||||||
if (null === $encryptedContent) {
|
if (null === $encryptedContent) {
|
||||||
app('log')->error(sprintf('No content for attachment #%d under filename "%s"', $attachment->id, $fileName));
|
Log::error(sprintf('No content for attachment #%d under filename "%s"', $attachment->id, $fileName));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -65,18 +73,13 @@ class ScansAttachments extends Command
|
|||||||
try {
|
try {
|
||||||
$decryptedContent = Crypt::decrypt($encryptedContent); // verified
|
$decryptedContent = Crypt::decrypt($encryptedContent); // verified
|
||||||
} catch (DecryptException $e) {
|
} catch (DecryptException $e) {
|
||||||
app('log')->error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage()));
|
Log::error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage()));
|
||||||
$decryptedContent = $encryptedContent;
|
$decryptedContent = $encryptedContent;
|
||||||
}
|
}
|
||||||
$tempFileName = tempnam(sys_get_temp_dir(), 'FireflyIII');
|
$tempFileName = tempnam(sys_get_temp_dir(), 'FireflyIII');
|
||||||
if (false === $tempFileName) {
|
|
||||||
app('log')->error(sprintf('Could not create temporary file for attachment #%d', $attachment->id));
|
|
||||||
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
file_put_contents($tempFileName, $decryptedContent);
|
file_put_contents($tempFileName, $decryptedContent);
|
||||||
$attachment->md5 = (string) md5_file($tempFileName);
|
$attachment->md5 = (string)md5_file($tempFileName);
|
||||||
$attachment->mime = (string) mime_content_type($tempFileName);
|
$attachment->mime = (string)mime_content_type($tempFileName);
|
||||||
$attachment->save();
|
$attachment->save();
|
||||||
$this->friendlyInfo(sprintf('Fixed attachment #%d', $attachment->id));
|
$this->friendlyInfo(sprintf('Fixed attachment #%d', $attachment->id));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class Cron extends Command
|
|||||||
{--download-cer : Download exchange rates. Other tasks will be skipped unless also requested.}
|
{--download-cer : Download exchange rates. Other tasks will be skipped unless also requested.}
|
||||||
{--create-recurring : Create recurring transactions. Other tasks will be skipped unless also requested.}
|
{--create-recurring : Create recurring transactions. Other tasks will be skipped unless also requested.}
|
||||||
{--create-auto-budgets : Create auto budgets. Other tasks will be skipped unless also requested.}
|
{--create-auto-budgets : Create auto budgets. Other tasks will be skipped unless also requested.}
|
||||||
{--send-bill-warnings : Send bill warnings. Other tasks will be skipped unless also requested.}
|
{--send-subscription-warnings : Send subscription warnings. Other tasks will be skipped unless also requested.}
|
||||||
{--send-webhook-messages : Sends any stray webhook messages (with a maximum of 5).}
|
{--send-webhook-messages : Sends any stray webhook messages (with a maximum of 5).}
|
||||||
';
|
';
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ class Cron extends Command
|
|||||||
$doAll = !$this->option('download-cer')
|
$doAll = !$this->option('download-cer')
|
||||||
&& !$this->option('create-recurring')
|
&& !$this->option('create-recurring')
|
||||||
&& !$this->option('create-auto-budgets')
|
&& !$this->option('create-auto-budgets')
|
||||||
&& !$this->option('send-bill-warnings')
|
&& !$this->option('send-subscription-warnings')
|
||||||
&& !$this->option('check-version')
|
&& !$this->option('check-version')
|
||||||
&& !$this->option('send-webhook-messages');
|
&& !$this->option('send-webhook-messages');
|
||||||
$date = null;
|
$date = null;
|
||||||
@@ -116,9 +116,9 @@ class Cron extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fire bill warning cron job
|
// Fire bill warning cron job
|
||||||
if ($doAll || $this->option('send-bill-warnings')) {
|
if ($doAll || $this->option('send-subscription-warnings')) {
|
||||||
try {
|
try {
|
||||||
$this->billWarningCronJob($force, $date);
|
$this->subscriptionWarningCronJob($force, $date);
|
||||||
} catch (FireflyException $e) {
|
} catch (FireflyException $e) {
|
||||||
app('log')->error($e->getMessage());
|
app('log')->error($e->getMessage());
|
||||||
app('log')->error($e->getTraceAsString());
|
app('log')->error($e->getTraceAsString());
|
||||||
@@ -231,25 +231,25 @@ class Cron extends Command
|
|||||||
/**
|
/**
|
||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
private function billWarningCronJob(bool $force, ?Carbon $date): void
|
private function subscriptionWarningCronJob(bool $force, ?Carbon $date): void
|
||||||
{
|
{
|
||||||
$autoBudget = new BillWarningCronjob();
|
$subscriptionWarningJob = new BillWarningCronjob();
|
||||||
$autoBudget->setForce($force);
|
$subscriptionWarningJob->setForce($force);
|
||||||
// set date in cron job:
|
// set date in cron job:
|
||||||
if ($date instanceof Carbon) {
|
if ($date instanceof Carbon) {
|
||||||
$autoBudget->setDate($date);
|
$subscriptionWarningJob->setDate($date);
|
||||||
}
|
}
|
||||||
|
|
||||||
$autoBudget->fire();
|
$subscriptionWarningJob->fire();
|
||||||
|
|
||||||
if ($autoBudget->jobErrored) {
|
if ($subscriptionWarningJob->jobErrored) {
|
||||||
$this->friendlyError(sprintf('Error in "bill warnings" cron: %s', $autoBudget->message));
|
$this->friendlyError(sprintf('Error in "subscription warnings" cron: %s', $subscriptionWarningJob->message));
|
||||||
}
|
}
|
||||||
if ($autoBudget->jobFired) {
|
if ($subscriptionWarningJob->jobFired) {
|
||||||
$this->friendlyInfo(sprintf('"Send bill warnings" cron fired: %s', $autoBudget->message));
|
$this->friendlyInfo(sprintf('"Send subscription warnings" cron fired: %s', $subscriptionWarningJob->message));
|
||||||
}
|
}
|
||||||
if ($autoBudget->jobSucceeded) {
|
if ($subscriptionWarningJob->jobSucceeded) {
|
||||||
$this->friendlyPositive(sprintf('"Send bill warnings" cron ran with success: %s', $autoBudget->message));
|
$this->friendlyPositive(sprintf('"Send subscription warnings" cron ran with success: %s', $subscriptionWarningJob->message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,5 +31,6 @@ enum WebhookResponse: int
|
|||||||
{
|
{
|
||||||
case TRANSACTIONS = 200;
|
case TRANSACTIONS = 200;
|
||||||
case ACCOUNTS = 210;
|
case ACCOUNTS = 210;
|
||||||
|
case BUDGET = 230;
|
||||||
case NONE = 220;
|
case NONE = 220;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,9 +30,10 @@ namespace FireflyIII\Enums;
|
|||||||
enum WebhookTrigger: int
|
enum WebhookTrigger: int
|
||||||
{
|
{
|
||||||
case STORE_TRANSACTION = 100;
|
case STORE_TRANSACTION = 100;
|
||||||
// case BEFORE_STORE_TRANSACTION = 101;
|
|
||||||
case UPDATE_TRANSACTION = 110;
|
case UPDATE_TRANSACTION = 110;
|
||||||
// case BEFORE_UPDATE_TRANSACTION = 111;
|
|
||||||
case DESTROY_TRANSACTION = 120;
|
case DESTROY_TRANSACTION = 120;
|
||||||
// case BEFORE_DESTROY_TRANSACTION = 121;
|
case STORE_BUDGET = 200;
|
||||||
|
case UPDATE_BUDGET = 210;
|
||||||
|
case DESTROY_BUDGET = 220;
|
||||||
|
case STORE_UPDATE_BUDGET_LIMIT = 230;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Created.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\Events\Model\BudgetLimit;
|
|
||||||
|
|
||||||
use FireflyIII\Events\Event;
|
|
||||||
use FireflyIII\Models\BudgetLimit;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Created
|
|
||||||
*/
|
|
||||||
class Created extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public function __construct(public BudgetLimit $budgetLimit) {}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Deleted.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\Events\Model\BudgetLimit;
|
|
||||||
|
|
||||||
use FireflyIII\Events\Event;
|
|
||||||
use FireflyIII\Models\BudgetLimit;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Deleted
|
|
||||||
*/
|
|
||||||
class Deleted extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public function __construct(public BudgetLimit $budgetLimit) {}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Updated.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\Events\Model\BudgetLimit;
|
|
||||||
|
|
||||||
use FireflyIII\Events\Event;
|
|
||||||
use FireflyIII\Models\BudgetLimit;
|
|
||||||
use Illuminate\Queue\SerializesModels;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class Updated
|
|
||||||
*/
|
|
||||||
class Updated extends Event
|
|
||||||
{
|
|
||||||
use SerializesModels;
|
|
||||||
|
|
||||||
public function __construct(public BudgetLimit $budgetLimit) {}
|
|
||||||
}
|
|
||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Generator\Webhook;
|
namespace FireflyIII\Generator\Webhook;
|
||||||
|
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ interface MessageGeneratorInterface
|
|||||||
|
|
||||||
public function setObjects(Collection $objects): void;
|
public function setObjects(Collection $objects): void;
|
||||||
|
|
||||||
public function setTrigger(int $trigger): void;
|
public function setTrigger(WebhookTrigger $trigger): void;
|
||||||
|
|
||||||
public function setUser(User $user): void;
|
public function setUser(User $user): void;
|
||||||
|
|
||||||
|
|||||||
@@ -27,13 +27,19 @@ namespace FireflyIII\Generator\Webhook;
|
|||||||
use FireflyIII\Enums\WebhookResponse;
|
use FireflyIII\Enums\WebhookResponse;
|
||||||
use FireflyIII\Enums\WebhookTrigger;
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Models\Transaction;
|
use FireflyIII\Models\Transaction;
|
||||||
use FireflyIII\Models\TransactionGroup;
|
use FireflyIII\Models\TransactionGroup;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Models\Webhook;
|
use FireflyIII\Models\Webhook;
|
||||||
use FireflyIII\Models\WebhookMessage;
|
use FireflyIII\Models\WebhookMessage;
|
||||||
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
|
||||||
|
use FireflyIII\Support\JsonApi\Enrichments\BudgetEnrichment;
|
||||||
|
use FireflyIII\Support\JsonApi\Enrichments\BudgetLimitEnrichment;
|
||||||
use FireflyIII\Transformers\AccountTransformer;
|
use FireflyIII\Transformers\AccountTransformer;
|
||||||
|
use FireflyIII\Transformers\BudgetLimitTransformer;
|
||||||
|
use FireflyIII\Transformers\BudgetTransformer;
|
||||||
use FireflyIII\Transformers\TransactionGroupTransformer;
|
use FireflyIII\Transformers\TransactionGroupTransformer;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
@@ -48,7 +54,7 @@ use Symfony\Component\HttpFoundation\ParameterBag;
|
|||||||
class StandardMessageGenerator implements MessageGeneratorInterface
|
class StandardMessageGenerator implements MessageGeneratorInterface
|
||||||
{
|
{
|
||||||
private Collection $objects;
|
private Collection $objects;
|
||||||
private int $trigger;
|
private WebhookTrigger $trigger;
|
||||||
private User $user;
|
private User $user;
|
||||||
private int $version = 0;
|
private int $version = 0;
|
||||||
private Collection $webhooks;
|
private Collection $webhooks;
|
||||||
@@ -68,9 +74,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
// do some debugging
|
// do some debugging
|
||||||
Log::debug(
|
Log::debug(sprintf('StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).', $this->objects->count(), $this->webhooks->count()));
|
||||||
sprintf('StandardMessageGenerator will generate messages for %d object(s) and %d webhook(s).', $this->objects->count(), $this->webhooks->count())
|
|
||||||
);
|
|
||||||
$this->run();
|
$this->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +83,9 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
return $this->user->webhooks()->where('active', true)->where('trigger', $this->trigger)->get(['webhooks.*']);
|
return $this->user->webhooks()->where('active', true)->where('trigger', $this->trigger)->get(['webhooks.*']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
private function run(): void
|
private function run(): void
|
||||||
{
|
{
|
||||||
Log::debug('Now in StandardMessageGenerator::run');
|
Log::debug('Now in StandardMessageGenerator::run');
|
||||||
@@ -111,13 +118,13 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
$class = $model::class;
|
$class = $model::class;
|
||||||
// Line is ignored because all of Firefly III's Models have an id property.
|
// Line is ignored because all of Firefly III's Models have an id property.
|
||||||
Log::debug(sprintf('Now in generateMessage(#%d, %s#%d)', $webhook->id, $class, $model->id));
|
Log::debug(sprintf('Now in generateMessage(#%d, %s#%d)', $webhook->id, $class, $model->id));
|
||||||
|
|
||||||
$uuid = Uuid::uuid4();
|
$uuid = Uuid::uuid4();
|
||||||
$basicMessage = [
|
$basicMessage = [
|
||||||
'uuid' => $uuid->toString(),
|
'uuid' => $uuid->toString(),
|
||||||
'user_id' => 0,
|
'user_id' => 0,
|
||||||
'trigger' => WebhookTrigger::from($webhook->trigger)->name,
|
'user_group_id' => 0,
|
||||||
'response' => WebhookResponse::from($webhook->response)->name,
|
'trigger' => WebhookTrigger::from((int)$webhook->trigger)->name,
|
||||||
|
'response' => WebhookResponse::from((int)$webhook->response)->name,
|
||||||
'url' => $webhook->url,
|
'url' => $webhook->url,
|
||||||
'version' => sprintf('v%d', $this->getVersion()),
|
'version' => sprintf('v%d', $this->getVersion()),
|
||||||
'content' => [],
|
'content' => [],
|
||||||
@@ -127,15 +134,27 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
switch ($class) {
|
switch ($class) {
|
||||||
default:
|
default:
|
||||||
// Line is ignored because all of Firefly III's Models have an id property.
|
// Line is ignored because all of Firefly III's Models have an id property.
|
||||||
Log::error(
|
Log::error(sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id));
|
||||||
sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case Budget::class:
|
||||||
|
/** @var Budget $model */
|
||||||
|
$basicMessage['user_id'] = $model->user_id;
|
||||||
|
$basicMessage['user_group_id'] = $model->user_group_id;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BudgetLimit::class:
|
||||||
|
$basicMessage['user_id'] = $model->budget->user_id;
|
||||||
|
$basicMessage['user_group_id'] = $model->budget->user_group_id;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case TransactionGroup::class:
|
case TransactionGroup::class:
|
||||||
/** @var TransactionGroup $model */
|
/** @var TransactionGroup $model */
|
||||||
$basicMessage['user_id'] = $model->user->id;
|
$basicMessage['user_id'] = $model->user_id;
|
||||||
|
$basicMessage['user_group_id'] = $model->user_group_id;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -143,12 +162,42 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
// then depends on the response what to put in the message:
|
// then depends on the response what to put in the message:
|
||||||
switch ($webhook->response) {
|
switch ($webhook->response) {
|
||||||
default:
|
default:
|
||||||
Log::error(
|
Log::error(sprintf('The response code for webhook #%d is "%d" and the message generator cant handle it. Soft fail.', $webhook->id, $webhook->response));
|
||||||
sprintf('The response code for webhook #%d is "%d" and the message generator cant handle it. Soft fail.', $webhook->id, $webhook->response)
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case WebhookResponse::BUDGET->value:
|
||||||
|
$basicMessage['content'] = [];
|
||||||
|
if ($model instanceof Budget) {
|
||||||
|
$enrichment = new BudgetEnrichment();
|
||||||
|
$enrichment->setUser($model->user);
|
||||||
|
$model = $enrichment->enrichSingle($model);
|
||||||
|
$transformer = new BudgetTransformer();
|
||||||
|
$basicMessage['content'] = $transformer->transform($model);
|
||||||
|
}
|
||||||
|
if ($model instanceof BudgetLimit) {
|
||||||
|
$user = $model->budget->user;
|
||||||
|
$enrichment = new BudgetEnrichment();
|
||||||
|
$enrichment->setUser($user);
|
||||||
|
$enrichment->setStart($model->start_date);
|
||||||
|
$enrichment->setEnd($model->end_date);
|
||||||
|
$budget = $enrichment->enrichSingle($model->budget);
|
||||||
|
|
||||||
|
$enrichment = new BudgetLimitEnrichment();
|
||||||
|
$enrichment->setUser($user);
|
||||||
|
|
||||||
|
$parameters = new ParameterBag();
|
||||||
|
$parameters->set('start', $model->start_date);
|
||||||
|
$parameters->set('end', $model->end_date);
|
||||||
|
|
||||||
|
$model = $enrichment->enrichSingle($model);
|
||||||
|
$transformer = new BudgetLimitTransformer();
|
||||||
|
$transformer->setParameters($parameters);
|
||||||
|
$basicMessage['content'] = $transformer->transform($model);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case WebhookResponse::NONE->value:
|
case WebhookResponse::NONE->value:
|
||||||
$basicMessage['content'] = [];
|
$basicMessage['content'] = [];
|
||||||
|
|
||||||
@@ -224,7 +273,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface
|
|||||||
$this->objects = $objects;
|
$this->objects = $objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTrigger(int $trigger): void
|
public function setTrigger(WebhookTrigger $trigger): void
|
||||||
{
|
{
|
||||||
$this->trigger = $trigger;
|
$this->trigger = $trigger;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class DestroyedGroupEventHandler
|
|||||||
$engine = app(MessageGeneratorInterface::class);
|
$engine = app(MessageGeneratorInterface::class);
|
||||||
$engine->setUser($user);
|
$engine->setUser($user);
|
||||||
$engine->setObjects(new Collection([$group]));
|
$engine->setObjects(new Collection([$group]));
|
||||||
$engine->setTrigger(WebhookTrigger::DESTROY_TRANSACTION->value);
|
$engine->setTrigger(WebhookTrigger::DESTROY_TRANSACTION);
|
||||||
$engine->generateMessages();
|
$engine->generateMessages();
|
||||||
|
|
||||||
event(new RequestedSendWebhookMessages());
|
event(new RequestedSendWebhookMessages());
|
||||||
|
|||||||
@@ -27,17 +27,7 @@ namespace FireflyIII\Handlers\Events\Model;
|
|||||||
use FireflyIII\Events\Model\BudgetLimit\Created;
|
use FireflyIII\Events\Model\BudgetLimit\Created;
|
||||||
use FireflyIII\Events\Model\BudgetLimit\Deleted;
|
use FireflyIII\Events\Model\BudgetLimit\Deleted;
|
||||||
use FireflyIII\Events\Model\BudgetLimit\Updated;
|
use FireflyIII\Events\Model\BudgetLimit\Updated;
|
||||||
use FireflyIII\Models\AvailableBudget;
|
|
||||||
use FireflyIII\Models\Budget;
|
|
||||||
use FireflyIII\Models\BudgetLimit;
|
|
||||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
|
||||||
use FireflyIII\User;
|
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
use Psr\Container\ContainerExceptionInterface;
|
|
||||||
use Psr\Container\NotFoundExceptionInterface;
|
|
||||||
use Spatie\Period\Boundaries;
|
|
||||||
use Spatie\Period\Period;
|
|
||||||
use Spatie\Period\Precision;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetLimitHandler
|
* Class BudgetLimitHandler
|
||||||
@@ -47,212 +37,9 @@ class BudgetLimitHandler
|
|||||||
public function created(Created $event): void
|
public function created(Created $event): void
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('BudgetLimitHandler::created(#%s)', $event->budgetLimit->id));
|
Log::debug(sprintf('BudgetLimitHandler::created(#%s)', $event->budgetLimit->id));
|
||||||
$this->updateAvailableBudget($event->budgetLimit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateAvailableBudget(BudgetLimit $budgetLimit): void
|
public function deleted(Deleted $event): void {}
|
||||||
{
|
|
||||||
Log::debug(sprintf('Now in updateAvailableBudget(limit #%d)', $budgetLimit->id));
|
|
||||||
|
|
||||||
/** @var null|Budget $budget */
|
public function updated(Updated $event): void {}
|
||||||
$budget = Budget::find($budgetLimit->budget_id);
|
|
||||||
if (null === $budget) {
|
|
||||||
Log::warning('Budget is null, probably deleted, find deleted version.');
|
|
||||||
|
|
||||||
/** @var null|Budget $budget */
|
|
||||||
$budget = Budget::withTrashed()->find($budgetLimit->budget_id);
|
|
||||||
}
|
|
||||||
if (null === $budget) {
|
|
||||||
Log::warning('Budget is still null, cannot continue, will delete budget limit.');
|
|
||||||
$budgetLimit->forceDelete();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var null|User $user */
|
|
||||||
$user = $budget->user;
|
|
||||||
|
|
||||||
// sanity check. It happens when the budget has been deleted so the original user is unknown.
|
|
||||||
if (null === $user) {
|
|
||||||
Log::warning('User is null, cannot continue.');
|
|
||||||
$budgetLimit->forceDelete();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// based on the view range of the user (month week quarter etc) the budget limit could
|
|
||||||
// either overlap multiple available budget periods or be contained in a single one.
|
|
||||||
// all have to be created or updated.
|
|
||||||
try {
|
|
||||||
$viewRange = app('preferences')->getForUser($user, 'viewRange', '1M')->data;
|
|
||||||
} catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) {
|
|
||||||
Log::error($e->getMessage());
|
|
||||||
$viewRange = '1M';
|
|
||||||
}
|
|
||||||
// safety catch
|
|
||||||
if (null === $viewRange || is_array($viewRange)) {
|
|
||||||
$viewRange = '1M';
|
|
||||||
}
|
|
||||||
$viewRange = (string) $viewRange;
|
|
||||||
|
|
||||||
$start = app('navigation')->startOfPeriod($budgetLimit->start_date, $viewRange);
|
|
||||||
$end = app('navigation')->startOfPeriod($budgetLimit->end_date, $viewRange);
|
|
||||||
$end = app('navigation')->endOfPeriod($end, $viewRange);
|
|
||||||
|
|
||||||
// limit period in total is:
|
|
||||||
$limitPeriod = Period::make($start, $end, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE());
|
|
||||||
Log::debug(sprintf('Limit period is from %s to %s', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
|
||||||
|
|
||||||
// from the start until the end of the budget limit, need to loop!
|
|
||||||
$current = clone $start;
|
|
||||||
while ($current <= $end) {
|
|
||||||
$currentEnd = app('navigation')->endOfPeriod($current, $viewRange);
|
|
||||||
|
|
||||||
// create or find AB for this particular period, and set the amount accordingly.
|
|
||||||
/** @var null|AvailableBudget $availableBudget */
|
|
||||||
$availableBudget = $user->availableBudgets()->where('start_date', $current->format('Y-m-d'))->where('end_date', $currentEnd->format('Y-m-d'))->where('transaction_currency_id', $budgetLimit->transaction_currency_id)->first();
|
|
||||||
|
|
||||||
if (null !== $availableBudget) {
|
|
||||||
Log::debug('Found 1 AB, will update.');
|
|
||||||
$this->calculateAmount($availableBudget);
|
|
||||||
}
|
|
||||||
if (null === $availableBudget) {
|
|
||||||
Log::debug('No AB found, will create.');
|
|
||||||
// if not exists:
|
|
||||||
$currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE());
|
|
||||||
$daily = $this->getDailyAmount($budgetLimit);
|
|
||||||
$amount = bcmul($daily, (string) $currentPeriod->length(), 12);
|
|
||||||
|
|
||||||
// no need to calculate if period is equal.
|
|
||||||
if ($currentPeriod->equals($limitPeriod)) {
|
|
||||||
$amount = 0 === $budgetLimit->id ? '0' : $budgetLimit->amount;
|
|
||||||
}
|
|
||||||
if (0 === bccomp($amount, '0')) {
|
|
||||||
Log::debug('Amount is zero, will not create AB.');
|
|
||||||
}
|
|
||||||
if (0 !== bccomp($amount, '0')) {
|
|
||||||
Log::debug(sprintf('Will create AB for period %s to %s', $current->format('Y-m-d'), $currentEnd->format('Y-m-d')));
|
|
||||||
$availableBudget = new AvailableBudget(
|
|
||||||
[
|
|
||||||
'user_id' => $user->id,
|
|
||||||
'user_group_id' => $user->user_group_id,
|
|
||||||
'transaction_currency_id' => $budgetLimit->transaction_currency_id,
|
|
||||||
'start_date' => $current,
|
|
||||||
'start_date_tz' => $current->format('e'),
|
|
||||||
'end_date' => $currentEnd,
|
|
||||||
'end_date_tz' => $currentEnd->format('e'),
|
|
||||||
'amount' => $amount,
|
|
||||||
]
|
|
||||||
);
|
|
||||||
$availableBudget->save();
|
|
||||||
Log::debug(sprintf('ID of new AB is #%d', $availableBudget->id));
|
|
||||||
$this->calculateAmount($availableBudget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// prep for next loop
|
|
||||||
$current = app('navigation')->addPeriod($current, $viewRange, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function calculateAmount(AvailableBudget $availableBudget): void
|
|
||||||
{
|
|
||||||
$repository = app(BudgetLimitRepositoryInterface::class);
|
|
||||||
$repository->setUser($availableBudget->user);
|
|
||||||
$newAmount = '0';
|
|
||||||
$abPeriod = Period::make($availableBudget->start_date, $availableBudget->end_date, Precision::DAY());
|
|
||||||
Log::debug(
|
|
||||||
sprintf(
|
|
||||||
'Now at AB #%d, ("%s" to "%s")',
|
|
||||||
$availableBudget->id,
|
|
||||||
$availableBudget->start_date->format('Y-m-d'),
|
|
||||||
$availableBudget->end_date->format('Y-m-d')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
// have to recalculate everything just in case.
|
|
||||||
$set = $repository->getAllBudgetLimitsByCurrency($availableBudget->transactionCurrency, $availableBudget->start_date, $availableBudget->end_date);
|
|
||||||
Log::debug(sprintf('Found %d interesting budget limit(s).', $set->count()));
|
|
||||||
|
|
||||||
/** @var BudgetLimit $budgetLimit */
|
|
||||||
foreach ($set as $budgetLimit) {
|
|
||||||
Log::debug(
|
|
||||||
sprintf(
|
|
||||||
'Found interesting budget limit #%d ("%s" to "%s")',
|
|
||||||
$budgetLimit->id,
|
|
||||||
$budgetLimit->start_date->format('Y-m-d'),
|
|
||||||
$budgetLimit->end_date->format('Y-m-d')
|
|
||||||
)
|
|
||||||
);
|
|
||||||
// overlap in days:
|
|
||||||
$limitPeriod = Period::make(
|
|
||||||
$budgetLimit->start_date,
|
|
||||||
$budgetLimit->end_date,
|
|
||||||
precision : Precision::DAY(),
|
|
||||||
boundaries: Boundaries::EXCLUDE_NONE()
|
|
||||||
);
|
|
||||||
// if both equal each other, amount from this BL must be added to the AB
|
|
||||||
if ($limitPeriod->equals($abPeriod)) {
|
|
||||||
Log::debug('This budget limit is equal to the available budget period.');
|
|
||||||
$newAmount = bcadd($newAmount, (string) $budgetLimit->amount);
|
|
||||||
}
|
|
||||||
// if budget limit period is inside AB period, it can be added in full.
|
|
||||||
if (!$limitPeriod->equals($abPeriod) && $abPeriod->contains($limitPeriod)) {
|
|
||||||
Log::debug('This budget limit is smaller than the available budget period.');
|
|
||||||
$newAmount = bcadd($newAmount, (string) $budgetLimit->amount);
|
|
||||||
}
|
|
||||||
if (!$limitPeriod->equals($abPeriod) && !$abPeriod->contains($limitPeriod) && $abPeriod->overlapsWith($limitPeriod)) {
|
|
||||||
Log::debug('This budget limit is something else entirely!');
|
|
||||||
$overlap = $abPeriod->overlap($limitPeriod);
|
|
||||||
if ($overlap instanceof Period) {
|
|
||||||
$length = $overlap->length();
|
|
||||||
$daily = bcmul($this->getDailyAmount($budgetLimit), (string) $length);
|
|
||||||
$newAmount = bcadd($newAmount, $daily);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (0 === bccomp('0', $newAmount)) {
|
|
||||||
Log::debug('New amount is zero, deleting AB.');
|
|
||||||
$availableBudget->delete();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Log::debug(sprintf('Concluded new amount for this AB must be %s', $newAmount));
|
|
||||||
$availableBudget->amount = app('steam')->bcround($newAmount, $availableBudget->transactionCurrency->decimal_places);
|
|
||||||
$availableBudget->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getDailyAmount(BudgetLimit $budgetLimit): string
|
|
||||||
{
|
|
||||||
if (0 === $budgetLimit->id) {
|
|
||||||
return '0';
|
|
||||||
}
|
|
||||||
$limitPeriod = Period::make(
|
|
||||||
$budgetLimit->start_date,
|
|
||||||
$budgetLimit->end_date,
|
|
||||||
precision : Precision::DAY(),
|
|
||||||
boundaries: Boundaries::EXCLUDE_NONE()
|
|
||||||
);
|
|
||||||
$days = $limitPeriod->length();
|
|
||||||
$amount = bcdiv($budgetLimit->amount, (string) $days, 12);
|
|
||||||
Log::debug(
|
|
||||||
sprintf('Total amount for budget limit #%d is %s. Nr. of days is %d. Amount per day is %s', $budgetLimit->id, $budgetLimit->amount, $days, $amount)
|
|
||||||
);
|
|
||||||
|
|
||||||
return $amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function deleted(Deleted $event): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('BudgetLimitHandler::deleted(#%s)', $event->budgetLimit->id));
|
|
||||||
$budgetLimit = $event->budgetLimit;
|
|
||||||
$budgetLimit->id = 0;
|
|
||||||
$this->updateAvailableBudget($event->budgetLimit);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function updated(Updated $event): void
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('BudgetLimitHandler::updated(#%s)', $event->budgetLimit->id));
|
|
||||||
$this->updateAvailableBudget($event->budgetLimit);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
|||||||
use FireflyIII\Services\Internal\Support\CreditRecalculateService;
|
use FireflyIII\Services\Internal\Support\CreditRecalculateService;
|
||||||
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
use FireflyIII\TransactionRules\Engine\RuleEngineInterface;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class StoredGroupEventHandler
|
* Class StoredGroupEventHandler
|
||||||
@@ -51,11 +52,11 @@ class StoredGroupEventHandler
|
|||||||
private function processRules(StoredTransactionGroup $storedGroupEvent): void
|
private function processRules(StoredTransactionGroup $storedGroupEvent): void
|
||||||
{
|
{
|
||||||
if (false === $storedGroupEvent->applyRules) {
|
if (false === $storedGroupEvent->applyRules) {
|
||||||
app('log')->info(sprintf('Will not run rules on group #%d', $storedGroupEvent->transactionGroup->id));
|
Log::info(sprintf('Will not run rules on group #%d', $storedGroupEvent->transactionGroup->id));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
app('log')->debug('Now in StoredGroupEventHandler::processRules()');
|
Log::debug('Now in StoredGroupEventHandler::processRules()');
|
||||||
|
|
||||||
$journals = $storedGroupEvent->transactionGroup->transactionJournals;
|
$journals = $storedGroupEvent->transactionGroup->transactionJournals;
|
||||||
$array = [];
|
$array = [];
|
||||||
@@ -65,7 +66,7 @@ class StoredGroupEventHandler
|
|||||||
$array[] = $journal->id;
|
$array[] = $journal->id;
|
||||||
}
|
}
|
||||||
$journalIds = implode(',', $array);
|
$journalIds = implode(',', $array);
|
||||||
app('log')->debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
Log::debug(sprintf('Add local operator for journal(s): %s', $journalIds));
|
||||||
|
|
||||||
// collect rules:
|
// collect rules:
|
||||||
$ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
$ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
|
||||||
@@ -98,10 +99,10 @@ class StoredGroupEventHandler
|
|||||||
*/
|
*/
|
||||||
private function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void
|
private function triggerWebhooks(StoredTransactionGroup $storedGroupEvent): void
|
||||||
{
|
{
|
||||||
app('log')->debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
$group = $storedGroupEvent->transactionGroup;
|
$group = $storedGroupEvent->transactionGroup;
|
||||||
if (false === $storedGroupEvent->fireWebhooks) {
|
if (false === $storedGroupEvent->fireWebhooks) {
|
||||||
app('log')->info(sprintf('Will not fire webhooks for transaction group #%d', $group->id));
|
Log::info(sprintf('Will not fire webhooks for transaction group #%d', $group->id));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,7 @@ class StoredGroupEventHandler
|
|||||||
$engine->setUser($user);
|
$engine->setUser($user);
|
||||||
|
|
||||||
// tell the generator which trigger it should look for
|
// tell the generator which trigger it should look for
|
||||||
$engine->setTrigger(WebhookTrigger::STORE_TRANSACTION->value);
|
$engine->setTrigger(WebhookTrigger::STORE_TRANSACTION);
|
||||||
// tell the generator which objects to process
|
// tell the generator which objects to process
|
||||||
$engine->setObjects(new Collection([$group]));
|
$engine->setObjects(new Collection([$group]));
|
||||||
// tell the generator to generate the messages
|
// tell the generator to generate the messages
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ class UpdatedGroupEventHandler
|
|||||||
$engine = app(MessageGeneratorInterface::class);
|
$engine = app(MessageGeneratorInterface::class);
|
||||||
$engine->setUser($user);
|
$engine->setUser($user);
|
||||||
$engine->setObjects(new Collection([$group]));
|
$engine->setObjects(new Collection([$group]));
|
||||||
$engine->setTrigger(WebhookTrigger::UPDATE_TRANSACTION->value);
|
$engine->setTrigger(WebhookTrigger::UPDATE_TRANSACTION);
|
||||||
$engine->generateMessages();
|
$engine->generateMessages();
|
||||||
|
|
||||||
event(new RequestedSendWebhookMessages());
|
event(new RequestedSendWebhookMessages());
|
||||||
|
|||||||
@@ -24,17 +24,36 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Handlers\Observer;
|
namespace FireflyIII\Handlers\Observer;
|
||||||
|
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
|
use FireflyIII\Events\RequestedSendWebhookMessages;
|
||||||
|
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
|
||||||
use FireflyIII\Models\BudgetLimit;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Support\Facades\Amount;
|
use FireflyIII\Support\Facades\Amount;
|
||||||
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
use FireflyIII\Support\Http\Api\ExchangeRateConverter;
|
||||||
|
use FireflyIII\Support\Observers\RecalculatesAvailableBudgetsTrait;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
class BudgetLimitObserver
|
class BudgetLimitObserver
|
||||||
{
|
{
|
||||||
|
use RecalculatesAvailableBudgetsTrait;
|
||||||
|
|
||||||
public function created(BudgetLimit $budgetLimit): void
|
public function created(BudgetLimit $budgetLimit): void
|
||||||
{
|
{
|
||||||
Log::debug('Observe "created" of a budget limit.');
|
Log::debug('Observe "created" of a budget limit.');
|
||||||
$this->updatePrimaryCurrencyAmount($budgetLimit);
|
$this->updatePrimaryCurrencyAmount($budgetLimit);
|
||||||
|
$this->updateAvailableBudget($budgetLimit);
|
||||||
|
|
||||||
|
$user = $budgetLimit->budget->user;
|
||||||
|
|
||||||
|
/** @var MessageGeneratorInterface $engine */
|
||||||
|
$engine = app(MessageGeneratorInterface::class);
|
||||||
|
$engine->setUser($user);
|
||||||
|
$engine->setObjects(new Collection()->push($budgetLimit));
|
||||||
|
$engine->setTrigger(WebhookTrigger::STORE_UPDATE_BUDGET_LIMIT);
|
||||||
|
$engine->generateMessages();
|
||||||
|
|
||||||
|
event(new RequestedSendWebhookMessages());
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updatePrimaryCurrencyAmount(BudgetLimit $budgetLimit): void
|
private function updatePrimaryCurrencyAmount(BudgetLimit $budgetLimit): void
|
||||||
@@ -60,5 +79,17 @@ class BudgetLimitObserver
|
|||||||
{
|
{
|
||||||
Log::debug('Observe "updated" of a budget limit.');
|
Log::debug('Observe "updated" of a budget limit.');
|
||||||
$this->updatePrimaryCurrencyAmount($budgetLimit);
|
$this->updatePrimaryCurrencyAmount($budgetLimit);
|
||||||
|
$this->updateAvailableBudget($budgetLimit);
|
||||||
|
|
||||||
|
$user = $budgetLimit->budget->user;
|
||||||
|
|
||||||
|
/** @var MessageGeneratorInterface $engine */
|
||||||
|
$engine = app(MessageGeneratorInterface::class);
|
||||||
|
$engine->setUser($user);
|
||||||
|
$engine->setObjects(new Collection()->push($budgetLimit));
|
||||||
|
$engine->setTrigger(WebhookTrigger::STORE_UPDATE_BUDGET_LIMIT);
|
||||||
|
$engine->generateMessages();
|
||||||
|
|
||||||
|
event(new RequestedSendWebhookMessages());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,19 +23,70 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Handlers\Observer;
|
namespace FireflyIII\Handlers\Observer;
|
||||||
|
|
||||||
|
use FireflyIII\Enums\WebhookTrigger;
|
||||||
|
use FireflyIII\Events\RequestedSendWebhookMessages;
|
||||||
|
use FireflyIII\Generator\Webhook\MessageGeneratorInterface;
|
||||||
use FireflyIII\Models\Attachment;
|
use FireflyIII\Models\Attachment;
|
||||||
use FireflyIII\Models\Budget;
|
use FireflyIII\Models\Budget;
|
||||||
use FireflyIII\Models\BudgetLimit;
|
use FireflyIII\Models\BudgetLimit;
|
||||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Observers\RecalculatesAvailableBudgetsTrait;
|
||||||
|
use Illuminate\Support\Collection;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class BudgetObserver
|
* Class BudgetObserver
|
||||||
*/
|
*/
|
||||||
class BudgetObserver
|
class BudgetObserver
|
||||||
{
|
{
|
||||||
|
use RecalculatesAvailableBudgetsTrait;
|
||||||
|
|
||||||
|
public function created(Budget $budget): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Observe "created" of budget #%d ("%s").', $budget->id, $budget->name));
|
||||||
|
|
||||||
|
// fire event.
|
||||||
|
$user = $budget->user;
|
||||||
|
|
||||||
|
/** @var MessageGeneratorInterface $engine */
|
||||||
|
$engine = app(MessageGeneratorInterface::class);
|
||||||
|
$engine->setUser($user);
|
||||||
|
$engine->setObjects(new Collection()->push($budget));
|
||||||
|
$engine->setTrigger(WebhookTrigger::STORE_BUDGET);
|
||||||
|
$engine->generateMessages();
|
||||||
|
|
||||||
|
event(new RequestedSendWebhookMessages());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updated(Budget $budget): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Observe "updated" of budget #%d ("%s").', $budget->id, $budget->name));
|
||||||
|
$user = $budget->user;
|
||||||
|
|
||||||
|
/** @var MessageGeneratorInterface $engine */
|
||||||
|
$engine = app(MessageGeneratorInterface::class);
|
||||||
|
$engine->setUser($user);
|
||||||
|
$engine->setObjects(new Collection()->push($budget));
|
||||||
|
$engine->setTrigger(WebhookTrigger::UPDATE_BUDGET);
|
||||||
|
$engine->generateMessages();
|
||||||
|
|
||||||
|
event(new RequestedSendWebhookMessages());
|
||||||
|
}
|
||||||
|
|
||||||
public function deleting(Budget $budget): void
|
public function deleting(Budget $budget): void
|
||||||
{
|
{
|
||||||
app('log')->debug('Observe "deleting" of a budget.');
|
Log::debug('Observe "deleting" of a budget.');
|
||||||
|
|
||||||
|
$user = $budget->user;
|
||||||
|
|
||||||
|
/** @var MessageGeneratorInterface $engine */
|
||||||
|
$engine = app(MessageGeneratorInterface::class);
|
||||||
|
$engine->setUser($user);
|
||||||
|
$engine->setObjects(new Collection()->push($budget));
|
||||||
|
$engine->setTrigger(WebhookTrigger::DESTROY_BUDGET);
|
||||||
|
$engine->generateMessages();
|
||||||
|
|
||||||
|
event(new RequestedSendWebhookMessages());
|
||||||
|
|
||||||
$repository = app(AttachmentRepositoryInterface::class);
|
$repository = app(AttachmentRepositoryInterface::class);
|
||||||
$repository->setUser($budget->user);
|
$repository->setUser($budget->user);
|
||||||
@@ -49,7 +100,10 @@ class BudgetObserver
|
|||||||
/** @var BudgetLimit $budgetLimit */
|
/** @var BudgetLimit $budgetLimit */
|
||||||
foreach ($budgetLimits as $budgetLimit) {
|
foreach ($budgetLimits as $budgetLimit) {
|
||||||
// this loop exists so several events are fired.
|
// this loop exists so several events are fired.
|
||||||
$budgetLimit->delete();
|
$copy = clone $budgetLimit;
|
||||||
|
$copy->id = 0;
|
||||||
|
$this->updateAvailableBudget($copy);
|
||||||
|
$budgetLimit->deleteQuietly(); // delete is quietly when in a loop.
|
||||||
}
|
}
|
||||||
|
|
||||||
$budget->notes()->delete();
|
$budget->notes()->delete();
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Handlers\Observer;
|
namespace FireflyIII\Handlers\Observer;
|
||||||
|
|
||||||
use FireflyIII\Models\TransactionGroup;
|
use FireflyIII\Models\TransactionGroup;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class TransactionGroup
|
* Class TransactionGroup
|
||||||
@@ -32,7 +33,7 @@ class TransactionGroupObserver
|
|||||||
{
|
{
|
||||||
public function deleting(TransactionGroup $transactionGroup): void
|
public function deleting(TransactionGroup $transactionGroup): void
|
||||||
{
|
{
|
||||||
app('log')->debug('Observe "deleting" of a transaction group.');
|
Log::debug('Observe "deleting" of a transaction group.');
|
||||||
foreach ($transactionGroup->transactionJournals()->get() as $journal) {
|
foreach ($transactionGroup->transactionJournals()->get() as $journal) {
|
||||||
$journal->delete();
|
$journal->delete();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ namespace FireflyIII\Handlers\Observer;
|
|||||||
use FireflyIII\Models\Attachment;
|
use FireflyIII\Models\Attachment;
|
||||||
use FireflyIII\Models\TransactionJournal;
|
use FireflyIII\Models\TransactionJournal;
|
||||||
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class TransactionJournalObserver
|
* Class TransactionJournalObserver
|
||||||
@@ -34,7 +35,7 @@ class TransactionJournalObserver
|
|||||||
{
|
{
|
||||||
public function deleting(TransactionJournal $transactionJournal): void
|
public function deleting(TransactionJournal $transactionJournal): void
|
||||||
{
|
{
|
||||||
app('log')->debug('Observe "deleting" of a transaction journal.');
|
Log::debug('Observe "deleting" of a transaction journal.');
|
||||||
|
|
||||||
$repository = app(AttachmentRepositoryInterface::class);
|
$repository = app(AttachmentRepositoryInterface::class);
|
||||||
$repository->setUser($transactionJournal->user);
|
$repository->setUser($transactionJournal->user);
|
||||||
|
|||||||
@@ -839,7 +839,7 @@ class GroupCollector implements GroupCollectorInterface
|
|||||||
return 'zzz';
|
return 'zzz';
|
||||||
}
|
}
|
||||||
|
|
||||||
exit('here we are 2');
|
return 'zzz';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ use Illuminate\Foundation\Auth\RegistersUsers;
|
|||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Routing\Redirector;
|
use Illuminate\Routing\Redirector;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
use Illuminate\View\View;
|
use Illuminate\View\View;
|
||||||
use Psr\Container\ContainerExceptionInterface;
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
@@ -94,7 +95,7 @@ class RegisterController extends Controller
|
|||||||
|
|
||||||
$this->validator($request->all())->validate();
|
$this->validator($request->all())->validate();
|
||||||
$user = $this->createUser($request->all());
|
$user = $this->createUser($request->all());
|
||||||
app('log')->info(sprintf('Registered new user %s', $user->email));
|
Log::info(sprintf('Registered new user %s', $user->email));
|
||||||
$owner = new OwnerNotifiable();
|
$owner = new OwnerNotifiable();
|
||||||
event(new RegisteredUser($owner, $user));
|
event(new RegisteredUser($owner, $user));
|
||||||
|
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ class NewUserController extends Controller
|
|||||||
$this->createCashWalletAccount($currency, $language); // create cash wallet account
|
$this->createCashWalletAccount($currency, $language); // create cash wallet account
|
||||||
|
|
||||||
// store currency preference:
|
// store currency preference:
|
||||||
$currencyRepository->makeDefault($currency);
|
$currencyRepository->makePrimary($currency);
|
||||||
|
|
||||||
// store frontpage preferences:
|
// store frontpage preferences:
|
||||||
$accounts = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
|
$accounts = $this->repository->getAccountsByType([AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
|
||||||
|
|||||||
@@ -29,9 +29,6 @@ use FireflyIII\Events\DestroyedTransactionGroup;
|
|||||||
use FireflyIII\Events\DetectedNewIPAddress;
|
use FireflyIII\Events\DetectedNewIPAddress;
|
||||||
use FireflyIII\Events\Model\Bill\WarnUserAboutBill;
|
use FireflyIII\Events\Model\Bill\WarnUserAboutBill;
|
||||||
use FireflyIII\Events\Model\Bill\WarnUserAboutOverdueSubscriptions;
|
use FireflyIII\Events\Model\Bill\WarnUserAboutOverdueSubscriptions;
|
||||||
use FireflyIII\Events\Model\BudgetLimit\Created;
|
|
||||||
use FireflyIII\Events\Model\BudgetLimit\Deleted;
|
|
||||||
use FireflyIII\Events\Model\BudgetLimit\Updated;
|
|
||||||
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
use FireflyIII\Events\Model\PiggyBank\ChangedAmount;
|
||||||
use FireflyIII\Events\Model\PiggyBank\ChangedName;
|
use FireflyIII\Events\Model\PiggyBank\ChangedName;
|
||||||
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
|
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
|
||||||
@@ -219,17 +216,6 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changedPiggyBankName',
|
'FireflyIII\Handlers\Events\Model\PiggyBankEventHandler@changedPiggyBankName',
|
||||||
],
|
],
|
||||||
|
|
||||||
// budget related events: CRUD budget limit
|
|
||||||
Created::class => [
|
|
||||||
'FireflyIII\Handlers\Events\Model\BudgetLimitHandler@created',
|
|
||||||
],
|
|
||||||
Updated::class => [
|
|
||||||
'FireflyIII\Handlers\Events\Model\BudgetLimitHandler@updated',
|
|
||||||
],
|
|
||||||
Deleted::class => [
|
|
||||||
'FireflyIII\Handlers\Events\Model\BudgetLimitHandler@deleted',
|
|
||||||
],
|
|
||||||
|
|
||||||
// rule actions
|
// rule actions
|
||||||
RuleActionFailedOnArray::class => [
|
RuleActionFailedOnArray::class => [
|
||||||
'FireflyIII\Handlers\Events\Model\RuleHandler@ruleActionFailedOnArray',
|
'FireflyIII\Handlers\Events\Model\RuleHandler@ruleActionFailedOnArray',
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
|
|||||||
|
|
||||||
// currency must be made default.
|
// currency must be made default.
|
||||||
if (true === $default) {
|
if (true === $default) {
|
||||||
$this->makeDefault($currency);
|
$this->makePrimary($currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var CurrencyUpdateService $service */
|
/** @var CurrencyUpdateService $service */
|
||||||
@@ -426,7 +426,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
|
|||||||
return $service->update($currency, $data);
|
return $service->update($currency, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function makeDefault(TransactionCurrency $currency): void
|
public function makePrimary(TransactionCurrency $currency): void
|
||||||
{
|
{
|
||||||
$current = app('amount')->getPrimaryCurrencyByUserGroup($this->userGroup);
|
$current = app('amount')->getPrimaryCurrencyByUserGroup($this->userGroup);
|
||||||
Log::debug(sprintf('Enabled + made default currency %s for user #%d', $currency->code, $this->userGroup->id));
|
Log::debug(sprintf('Enabled + made default currency %s for user #%d', $currency->code, $this->userGroup->id));
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ interface CurrencyRepositoryInterface
|
|||||||
|
|
||||||
public function isFallbackCurrency(TransactionCurrency $currency): bool;
|
public function isFallbackCurrency(TransactionCurrency $currency): bool;
|
||||||
|
|
||||||
public function makeDefault(TransactionCurrency $currency): void;
|
public function makePrimary(TransactionCurrency $currency): void;
|
||||||
|
|
||||||
public function searchCurrency(string $search, int $limit): Collection;
|
public function searchCurrency(string $search, int $limit): Collection;
|
||||||
|
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ class UserGroupRepository implements UserGroupRepositoryInterface, UserGroupInte
|
|||||||
$currency = $repository->find((int) $data['primary_currency_id']);
|
$currency = $repository->find((int) $data['primary_currency_id']);
|
||||||
}
|
}
|
||||||
if (null !== $currency) {
|
if (null !== $currency) {
|
||||||
$repository->makeDefault($currency);
|
$repository->makePrimary($currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -365,7 +365,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
|||||||
|
|
||||||
// currency must be made default.
|
// currency must be made default.
|
||||||
if (true === $default) {
|
if (true === $default) {
|
||||||
$this->makeDefault($currency);
|
$this->makePrimary($currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var CurrencyUpdateService $service */
|
/** @var CurrencyUpdateService $service */
|
||||||
@@ -374,7 +374,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface
|
|||||||
return $service->update($currency, $data);
|
return $service->update($currency, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function makeDefault(TransactionCurrency $currency): void
|
public function makePrimary(TransactionCurrency $currency): void
|
||||||
{
|
{
|
||||||
$current = app('amount')->getPrimaryCurrencyByUserGroup($this->userGroup);
|
$current = app('amount')->getPrimaryCurrencyByUserGroup($this->userGroup);
|
||||||
Log::debug(sprintf('Enabled + made default currency %s for user #%d', $currency->code, $this->userGroup->id));
|
Log::debug(sprintf('Enabled + made default currency %s for user #%d', $currency->code, $this->userGroup->id));
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ interface CurrencyRepositoryInterface
|
|||||||
|
|
||||||
public function isFallbackCurrency(TransactionCurrency $currency): bool;
|
public function isFallbackCurrency(TransactionCurrency $currency): bool;
|
||||||
|
|
||||||
public function makeDefault(TransactionCurrency $currency): void;
|
public function makePrimary(TransactionCurrency $currency): void;
|
||||||
|
|
||||||
public function searchCurrency(string $search, int $limit): Collection;
|
public function searchCurrency(string $search, int $limit): Collection;
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,11 @@ class EitherConfigKey
|
|||||||
'firefly.rule-actions',
|
'firefly.rule-actions',
|
||||||
'firefly.context-rule-actions',
|
'firefly.context-rule-actions',
|
||||||
'search.operators',
|
'search.operators',
|
||||||
|
|
||||||
|
// webhooks
|
||||||
|
'webhook.triggers',
|
||||||
|
'webhook.responses',
|
||||||
|
'webhook.deliveries',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -65,55 +65,27 @@ class FrontpageChartGenerator
|
|||||||
|
|
||||||
public function generate(): array
|
public function generate(): array
|
||||||
{
|
{
|
||||||
Log::debug('Now in generate()');
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
$categories = $this->repository->getCategories();
|
$categories = $this->repository->getCategories();
|
||||||
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]);
|
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::ASSET->value, AccountTypeEnum::DEFAULT->value]);
|
||||||
|
$collection = $this->collectExpensesAll($categories, $accounts);
|
||||||
// get expenses + income per category:
|
|
||||||
$collection = [];
|
|
||||||
|
|
||||||
/** @var Category $category */
|
|
||||||
foreach ($categories as $category) {
|
|
||||||
// get expenses
|
|
||||||
$collection[] = $this->collectExpenses($category, $accounts);
|
|
||||||
}
|
|
||||||
|
|
||||||
// collect for no-category:
|
// collect for no-category:
|
||||||
$collection[] = $this->collectNoCatExpenses($accounts);
|
$noCategory = $this->collectNoCatExpenses($accounts);
|
||||||
|
$collection = array_merge($collection, $noCategory);
|
||||||
$tempData = array_merge(...$collection);
|
|
||||||
|
|
||||||
// sort temp array by amount.
|
// sort temp array by amount.
|
||||||
$amounts = array_column($tempData, 'sum_float');
|
$amounts = array_column($collection, 'sum_float');
|
||||||
array_multisort($amounts, SORT_ASC, $tempData);
|
array_multisort($amounts, SORT_ASC, $collection);
|
||||||
|
|
||||||
$currencyData = $this->createCurrencyGroups($tempData);
|
$currencyData = $this->createCurrencyGroups($collection);
|
||||||
|
|
||||||
return $this->insertValues($currencyData, $tempData);
|
return $this->insertValues($currencyData, $collection);
|
||||||
}
|
|
||||||
|
|
||||||
private function collectExpenses(Category $category, Collection $accounts): array
|
|
||||||
{
|
|
||||||
Log::debug(sprintf('Collect expenses for category #%d ("%s")', $category->id, $category->name));
|
|
||||||
$spent = $this->opsRepos->sumExpenses($this->start, $this->end, $accounts, new Collection([$category]));
|
|
||||||
$tempData = [];
|
|
||||||
foreach ($spent as $currency) {
|
|
||||||
Log::debug(sprintf('Spent %s %s', $currency['currency_code'], $currency['sum']));
|
|
||||||
$this->addCurrency($currency);
|
|
||||||
$tempData[] = [
|
|
||||||
'name' => $category->name,
|
|
||||||
'sum' => $currency['sum'],
|
|
||||||
'sum_float' => round((float) $currency['sum'], $currency['currency_decimal_places']),
|
|
||||||
'currency_id' => (int) $currency['currency_id'],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $tempData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function addCurrency(array $currency): void
|
private function addCurrency(array $currency): void
|
||||||
{
|
{
|
||||||
$currencyId = (int) $currency['currency_id'];
|
$currencyId = (int)$currency['currency_id'];
|
||||||
|
|
||||||
$this->currencies[$currencyId] ??= [
|
$this->currencies[$currencyId] ??= [
|
||||||
'currency_id' => $currencyId,
|
'currency_id' => $currencyId,
|
||||||
@@ -133,8 +105,8 @@ class FrontpageChartGenerator
|
|||||||
$tempData[] = [
|
$tempData[] = [
|
||||||
'name' => trans('firefly.no_category'),
|
'name' => trans('firefly.no_category'),
|
||||||
'sum' => $currency['sum'],
|
'sum' => $currency['sum'],
|
||||||
'sum_float' => round((float) $currency['sum'], $currency['currency_decimal_places'] ?? 2), // intentional float
|
'sum_float' => round((float)$currency['sum'], $currency['currency_decimal_places'] ?? 2), // intentional float
|
||||||
'currency_id' => (int) $currency['currency_id'],
|
'currency_id' => (int)$currency['currency_id'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +124,7 @@ class FrontpageChartGenerator
|
|||||||
foreach ($this->currencies as $currencyId => $currency) {
|
foreach ($this->currencies as $currencyId => $currency) {
|
||||||
$key = sprintf('spent-%d', $currencyId);
|
$key = sprintf('spent-%d', $currencyId);
|
||||||
$return[$key] = [
|
$return[$key] = [
|
||||||
'label' => sprintf('%s (%s)', (string) trans('firefly.spent'), $currency['currency_name']),
|
'label' => sprintf('%s (%s)', (string)trans('firefly.spent'), $currency['currency_name']),
|
||||||
'type' => 'bar',
|
'type' => 'bar',
|
||||||
'currency_symbol' => $currency['currency_symbol'],
|
'currency_symbol' => $currency['currency_symbol'],
|
||||||
'entries' => $names,
|
'entries' => $names,
|
||||||
@@ -175,4 +147,28 @@ class FrontpageChartGenerator
|
|||||||
|
|
||||||
return $currencyData;
|
return $currencyData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function collectExpensesAll(Collection $categories, Collection $accounts): array
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Collect expenses for %d category(ies).', count($categories)));
|
||||||
|
$spent = $this->opsRepos->collectExpenses($this->start, $this->end, $accounts, $categories);
|
||||||
|
$tempData = [];
|
||||||
|
foreach ($categories as $category) {
|
||||||
|
$sums = $this->opsRepos->sumCollectedTransactionsByCategory($spent, $category, 'negative', $this->convertToPrimary);
|
||||||
|
if (0 === count($sums)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
foreach ($sums as $currency) {
|
||||||
|
$this->addCurrency($currency);
|
||||||
|
$tempData[] = [
|
||||||
|
'name' => $category->name,
|
||||||
|
'sum' => $currency['sum'],
|
||||||
|
'sum_float' => round((float)$currency['sum'], $currency['currency_decimal_places']),
|
||||||
|
'currency_id' => (int)$currency['currency_id'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $tempData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ use FireflyIII\Models\Rule;
|
|||||||
use FireflyIII\Models\RuleAction;
|
use FireflyIII\Models\RuleAction;
|
||||||
use FireflyIII\Models\RuleTrigger;
|
use FireflyIII\Models\RuleTrigger;
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
|
use FireflyIII\Models\UserGroup;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||||
@@ -84,6 +85,7 @@ class ExportDataGenerator
|
|||||||
private bool $exportTransactions;
|
private bool $exportTransactions;
|
||||||
private Carbon $start;
|
private Carbon $start;
|
||||||
private User $user;
|
private User $user;
|
||||||
|
private UserGroup $userGroup;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -906,4 +908,9 @@ class ExportDataGenerator
|
|||||||
{
|
{
|
||||||
$this->start = $start;
|
$this->start = $start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setUserGroup(UserGroup $userGroup): void
|
||||||
|
{
|
||||||
|
$this->userGroup = $userGroup;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ use Illuminate\Support\Facades\Log;
|
|||||||
trait ValidatesUserGroupTrait
|
trait ValidatesUserGroupTrait
|
||||||
{
|
{
|
||||||
protected ?UserGroup $userGroup = null;
|
protected ?UserGroup $userGroup = null;
|
||||||
|
protected ?User $user = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An "undocumented" filter
|
* An "undocumented" filter
|
||||||
@@ -101,6 +102,7 @@ trait ValidatesUserGroupTrait
|
|||||||
if ($user->hasRoleInGroupOrOwner($group, $role)) {
|
if ($user->hasRoleInGroupOrOwner($group, $role)) {
|
||||||
Log::debug(sprintf('validateUserGroup: User has role "%s" in group #%d, return the group.', $role->value, $groupId));
|
Log::debug(sprintf('validateUserGroup: User has role "%s" in group #%d, return the group.', $role->value, $groupId));
|
||||||
$this->userGroup = $group;
|
$this->userGroup = $group;
|
||||||
|
$this->user = $user;
|
||||||
|
|
||||||
return $group;
|
return $group;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,10 +73,12 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
|||||||
public function enrich(Collection $collection): Collection
|
public function enrich(Collection $collection): Collection
|
||||||
{
|
{
|
||||||
$this->collection = $collection;
|
$this->collection = $collection;
|
||||||
|
if ($this->collection->count() > 0) {
|
||||||
$this->collectIds();
|
$this->collectIds();
|
||||||
$this->collectCurrencies();
|
$this->collectCurrencies();
|
||||||
$this->collectSpentInfo();
|
$this->collectSpentInfo();
|
||||||
$this->appendCollectedData();
|
$this->appendCollectedData();
|
||||||
|
}
|
||||||
|
|
||||||
return $this->collection;
|
return $this->collection;
|
||||||
}
|
}
|
||||||
@@ -85,7 +87,7 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
|||||||
public function enrichSingle(array|Model $model): array|Model
|
public function enrichSingle(array|Model $model): array|Model
|
||||||
{
|
{
|
||||||
Log::debug(__METHOD__);
|
Log::debug(__METHOD__);
|
||||||
$collection = new Collection([$model]);
|
$collection = new Collection()->push($model);
|
||||||
$collection = $this->enrich($collection);
|
$collection = $this->enrich($collection);
|
||||||
|
|
||||||
return $collection->first();
|
return $collection->first();
|
||||||
@@ -119,8 +121,8 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
|||||||
|
|
||||||
private function collectSpentInfo(): void
|
private function collectSpentInfo(): void
|
||||||
{
|
{
|
||||||
$start = $this->collection->min('start_date');
|
$start = $this->collection->min('start_date') ?? Carbon::now()->startOfMonth();
|
||||||
$end = $this->collection->max('end_date');
|
$end = $this->collection->max('end_date') ?? Carbon::now()->endOfMonth();
|
||||||
$allActive = $this->repository->getActiveBudgets();
|
$allActive = $this->repository->getActiveBudgets();
|
||||||
$spentInBudgets = $this->opsRepository->collectExpenses($start, $end, null, $allActive, null);
|
$spentInBudgets = $this->opsRepository->collectExpenses($start, $end, null, $allActive, null);
|
||||||
$spentOutsideBudgets = $this->noBudgetRepository->collectExpenses($start, $end, null, null, null);
|
$spentOutsideBudgets = $this->noBudgetRepository->collectExpenses($start, $end, null, null, null);
|
||||||
@@ -139,14 +141,7 @@ class AvailableBudgetEnrichment implements EnrichmentInterface
|
|||||||
$this->pcSpentInBudgets[$id] = array_values($pcFilteredSpentInBudgets);
|
$this->pcSpentInBudgets[$id] = array_values($pcFilteredSpentInBudgets);
|
||||||
$this->pcSpentOutsideBudgets[$id] = array_values($pcFilteredSpentOutsideBudgets);
|
$this->pcSpentOutsideBudgets[$id] = array_values($pcFilteredSpentOutsideBudgets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// filter arrays on date.
|
|
||||||
// send them to sumCollection thing.
|
|
||||||
// save.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// first collect, then filter and append.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function appendCollectedData(): void
|
private function appendCollectedData(): void
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
|||||||
$this->collectCurrencies();
|
$this->collectCurrencies();
|
||||||
$this->collectNotes();
|
$this->collectNotes();
|
||||||
$this->collectBudgets();
|
$this->collectBudgets();
|
||||||
|
$this->stringifyIds();
|
||||||
$this->appendCollectedData();
|
$this->appendCollectedData();
|
||||||
|
|
||||||
return $this->collection;
|
return $this->collection;
|
||||||
@@ -74,8 +75,8 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
|||||||
|
|
||||||
private function collectIds(): void
|
private function collectIds(): void
|
||||||
{
|
{
|
||||||
$this->start = $this->collection->min('start_date');
|
$this->start = $this->collection->min('start_date') ?? Carbon::now()->startOfMonth();
|
||||||
$this->end = $this->collection->max('end_date');
|
$this->end = $this->collection->max('end_date') ?? Carbon::now()->endOfMonth();
|
||||||
|
|
||||||
/** @var BudgetLimit $limit */
|
/** @var BudgetLimit $limit */
|
||||||
foreach ($this->collection as $limit) {
|
foreach ($this->collection as $limit) {
|
||||||
@@ -155,4 +156,23 @@ class BudgetLimitEnrichment implements EnrichmentInterface
|
|||||||
$this->currencies[(int)$currency->id] = $currency;
|
$this->currencies[(int)$currency->id] = $currency;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function stringifyIds(): void
|
||||||
|
{
|
||||||
|
$this->expenses = array_map(function ($first) {
|
||||||
|
return array_map(function ($second) {
|
||||||
|
$second['currency_id'] = (string)($second['currency_id'] ?? 0);
|
||||||
|
|
||||||
|
return $second;
|
||||||
|
}, $first);
|
||||||
|
}, $this->expenses);
|
||||||
|
|
||||||
|
$this->pcExpenses = array_map(function ($first) {
|
||||||
|
return array_map(function ($second) {
|
||||||
|
$second['currency_id'] = (string)($second['currency_id'] ?? 0);
|
||||||
|
|
||||||
|
return $second;
|
||||||
|
}, $first);
|
||||||
|
}, $this->expenses);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ class PiggyBankEnrichment implements EnrichmentInterface
|
|||||||
// add object group if available
|
// add object group if available
|
||||||
if (array_key_exists($id, $this->mappedObjects)) {
|
if (array_key_exists($id, $this->mappedObjects)) {
|
||||||
$key = $this->mappedObjects[$id];
|
$key = $this->mappedObjects[$id];
|
||||||
$meta['object_group_id'] = $this->objectGroups[$key]['id'];
|
$meta['object_group_id'] = (string) $this->objectGroups[$key]['id'];
|
||||||
$meta['object_group_title'] = $this->objectGroups[$key]['title'];
|
$meta['object_group_title'] = $this->objectGroups[$key]['title'];
|
||||||
$meta['object_group_order'] = $this->objectGroups[$key]['order'];
|
$meta['object_group_order'] = $this->objectGroups[$key]['order'];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -464,7 +464,7 @@ class Navigation
|
|||||||
$displayFormat = (string) trans('config.month_and_day_js', [], $locale);
|
$displayFormat = (string) trans('config.month_and_day_js', [], $locale);
|
||||||
$diff = $start->diffInMonths($end, true);
|
$diff = $start->diffInMonths($end, true);
|
||||||
// increment by month (for year)
|
// increment by month (for year)
|
||||||
if ($diff >= 1.0001) {
|
if ($diff >= 1.0001 && $diff < 12.001) {
|
||||||
$increment = 'addMonth';
|
$increment = 'addMonth';
|
||||||
$displayFormat = (string) trans('config.month_js');
|
$displayFormat = (string) trans('config.month_js');
|
||||||
}
|
}
|
||||||
@@ -495,7 +495,7 @@ class Navigation
|
|||||||
$format = 'Y-m-d';
|
$format = 'Y-m-d';
|
||||||
$diff = $start->diffInMonths($end, true);
|
$diff = $start->diffInMonths($end, true);
|
||||||
// Log::debug(sprintf('preferredCarbonFormat(%s, %s) = %f', $start->format('Y-m-d'), $end->format('Y-m-d'), $diff));
|
// Log::debug(sprintf('preferredCarbonFormat(%s, %s) = %f', $start->format('Y-m-d'), $end->format('Y-m-d'), $diff));
|
||||||
if ($diff >= 1.001) {
|
if ($diff >= 1.001 && $diff < 12.001) {
|
||||||
// Log::debug(sprintf('Return Y-m because %s', $diff));
|
// Log::debug(sprintf('Return Y-m because %s', $diff));
|
||||||
$format = 'Y-m';
|
$format = 'Y-m';
|
||||||
}
|
}
|
||||||
@@ -566,7 +566,7 @@ class Navigation
|
|||||||
{
|
{
|
||||||
$locale = app('steam')->getLocale();
|
$locale = app('steam')->getLocale();
|
||||||
$diff = $start->diffInMonths($end, true);
|
$diff = $start->diffInMonths($end, true);
|
||||||
if ($diff >= 1.001) {
|
if ($diff >= 1.001 && $diff < 12.001) {
|
||||||
return (string) trans('config.month_js', [], $locale);
|
return (string) trans('config.month_js', [], $locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,7 +584,7 @@ class Navigation
|
|||||||
public function preferredEndOfPeriod(Carbon $start, Carbon $end): string
|
public function preferredEndOfPeriod(Carbon $start, Carbon $end): string
|
||||||
{
|
{
|
||||||
$diff = $start->diffInMonths($end, true);
|
$diff = $start->diffInMonths($end, true);
|
||||||
if ($diff >= 1.001) {
|
if ($diff >= 1.001 && $diff < 12.001) {
|
||||||
return 'endOfMonth';
|
return 'endOfMonth';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -602,7 +602,7 @@ class Navigation
|
|||||||
public function preferredRangeFormat(Carbon $start, Carbon $end): string
|
public function preferredRangeFormat(Carbon $start, Carbon $end): string
|
||||||
{
|
{
|
||||||
$diff = $start->diffInMonths($end, true);
|
$diff = $start->diffInMonths($end, true);
|
||||||
if ($diff >= 1.001) {
|
if ($diff >= 1.001 && $diff < 12.001) {
|
||||||
return '1M';
|
return '1M';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -620,7 +620,7 @@ class Navigation
|
|||||||
public function preferredSqlFormat(Carbon $start, Carbon $end): string
|
public function preferredSqlFormat(Carbon $start, Carbon $end): string
|
||||||
{
|
{
|
||||||
$diff = $start->diffInMonths($end, true);
|
$diff = $start->diffInMonths($end, true);
|
||||||
if ($diff >= 1.001) {
|
if ($diff >= 1.001 && $diff < 12.001) {
|
||||||
return '%Y-%m';
|
return '%Y-%m';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
212
app/Support/Observers/RecalculatesAvailableBudgetsTrait.php
Normal file
212
app/Support/Observers/RecalculatesAvailableBudgetsTrait.php
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Support\Observers;
|
||||||
|
|
||||||
|
use FireflyIII\Models\AvailableBudget;
|
||||||
|
use FireflyIII\Models\Budget;
|
||||||
|
use FireflyIII\Models\BudgetLimit;
|
||||||
|
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
|
||||||
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
|
use Spatie\Period\Boundaries;
|
||||||
|
use Spatie\Period\Period;
|
||||||
|
use Spatie\Period\Precision;
|
||||||
|
|
||||||
|
trait RecalculatesAvailableBudgetsTrait
|
||||||
|
{
|
||||||
|
private function updateAvailableBudget(BudgetLimit $budgetLimit): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in updateAvailableBudget(limit #%d)', $budgetLimit->id));
|
||||||
|
|
||||||
|
/** @var null|Budget $budget */
|
||||||
|
$budget = Budget::find($budgetLimit->budget_id);
|
||||||
|
if (null === $budget) {
|
||||||
|
Log::warning('Budget is null, probably deleted, find deleted version.');
|
||||||
|
|
||||||
|
/** @var null|Budget $budget */
|
||||||
|
$budget = Budget::withTrashed()->find($budgetLimit->budget_id);
|
||||||
|
}
|
||||||
|
if (null === $budget) {
|
||||||
|
Log::warning('Budget is still null, cannot continue, will delete budget limit.');
|
||||||
|
$budgetLimit->forceDelete();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var null|User $user */
|
||||||
|
$user = $budget->user;
|
||||||
|
|
||||||
|
// sanity check. It happens when the budget has been deleted so the original user is unknown.
|
||||||
|
if (null === $user) {
|
||||||
|
Log::warning('User is null, cannot continue.');
|
||||||
|
$budgetLimit->forceDelete();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// based on the view range of the user (month week quarter etc) the budget limit could
|
||||||
|
// either overlap multiple available budget periods or be contained in a single one.
|
||||||
|
// all have to be created or updated.
|
||||||
|
try {
|
||||||
|
$viewRange = app('preferences')->getForUser($user, 'viewRange', '1M')->data;
|
||||||
|
} catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
$viewRange = '1M';
|
||||||
|
}
|
||||||
|
// safety catch
|
||||||
|
if (null === $viewRange || is_array($viewRange)) {
|
||||||
|
$viewRange = '1M';
|
||||||
|
}
|
||||||
|
$viewRange = (string) $viewRange;
|
||||||
|
|
||||||
|
$start = app('navigation')->startOfPeriod($budgetLimit->start_date, $viewRange);
|
||||||
|
$end = app('navigation')->startOfPeriod($budgetLimit->end_date, $viewRange);
|
||||||
|
$end = app('navigation')->endOfPeriod($end, $viewRange);
|
||||||
|
|
||||||
|
// limit period in total is:
|
||||||
|
$limitPeriod = Period::make($start, $end, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE());
|
||||||
|
Log::debug(sprintf('Limit period is from %s to %s', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||||
|
|
||||||
|
// from the start until the end of the budget limit, need to loop!
|
||||||
|
$current = clone $start;
|
||||||
|
while ($current <= $end) {
|
||||||
|
$currentEnd = app('navigation')->endOfPeriod($current, $viewRange);
|
||||||
|
|
||||||
|
// create or find AB for this particular period, and set the amount accordingly.
|
||||||
|
/** @var null|AvailableBudget $availableBudget */
|
||||||
|
$availableBudget = $user->availableBudgets()->where('start_date', $current->format('Y-m-d'))->where('end_date', $currentEnd->format('Y-m-d'))->where('transaction_currency_id', $budgetLimit->transaction_currency_id)->first();
|
||||||
|
|
||||||
|
if (null !== $availableBudget) {
|
||||||
|
Log::debug('Found 1 AB, will update.');
|
||||||
|
$this->calculateAmount($availableBudget);
|
||||||
|
}
|
||||||
|
if (null === $availableBudget) {
|
||||||
|
Log::debug('No AB found, will create.');
|
||||||
|
// if not exists:
|
||||||
|
$currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE());
|
||||||
|
$daily = $this->getDailyAmount($budgetLimit);
|
||||||
|
$amount = bcmul($daily, (string) $currentPeriod->length(), 12);
|
||||||
|
|
||||||
|
// no need to calculate if period is equal.
|
||||||
|
if ($currentPeriod->equals($limitPeriod)) {
|
||||||
|
$amount = 0 === $budgetLimit->id ? '0' : $budgetLimit->amount;
|
||||||
|
}
|
||||||
|
if (0 === bccomp($amount, '0')) {
|
||||||
|
Log::debug('Amount is zero, will not create AB.');
|
||||||
|
}
|
||||||
|
if (0 !== bccomp($amount, '0')) {
|
||||||
|
Log::debug(sprintf('Will create AB for period %s to %s', $current->format('Y-m-d'), $currentEnd->format('Y-m-d')));
|
||||||
|
$availableBudget = new AvailableBudget(
|
||||||
|
[
|
||||||
|
'user_id' => $user->id,
|
||||||
|
'user_group_id' => $user->user_group_id,
|
||||||
|
'transaction_currency_id' => $budgetLimit->transaction_currency_id,
|
||||||
|
'start_date' => $current,
|
||||||
|
'start_date_tz' => $current->format('e'),
|
||||||
|
'end_date' => $currentEnd,
|
||||||
|
'end_date_tz' => $currentEnd->format('e'),
|
||||||
|
'amount' => $amount,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
$availableBudget->save();
|
||||||
|
Log::debug(sprintf('ID of new AB is #%d', $availableBudget->id));
|
||||||
|
$this->calculateAmount($availableBudget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// prep for next loop
|
||||||
|
$current = app('navigation')->addPeriod($current, $viewRange, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function calculateAmount(AvailableBudget $availableBudget): void
|
||||||
|
{
|
||||||
|
$repository = app(BudgetLimitRepositoryInterface::class);
|
||||||
|
$repository->setUser($availableBudget->user);
|
||||||
|
$newAmount = '0';
|
||||||
|
$abPeriod = Period::make($availableBudget->start_date, $availableBudget->end_date, Precision::DAY());
|
||||||
|
Log::debug(
|
||||||
|
sprintf(
|
||||||
|
'Now at AB #%d, ("%s" to "%s")',
|
||||||
|
$availableBudget->id,
|
||||||
|
$availableBudget->start_date->format('Y-m-d'),
|
||||||
|
$availableBudget->end_date->format('Y-m-d')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// have to recalculate everything just in case.
|
||||||
|
$set = $repository->getAllBudgetLimitsByCurrency($availableBudget->transactionCurrency, $availableBudget->start_date, $availableBudget->end_date);
|
||||||
|
Log::debug(sprintf('Found %d interesting budget limit(s).', $set->count()));
|
||||||
|
|
||||||
|
/** @var BudgetLimit $budgetLimit */
|
||||||
|
foreach ($set as $budgetLimit) {
|
||||||
|
Log::debug(
|
||||||
|
sprintf(
|
||||||
|
'Found interesting budget limit #%d ("%s" to "%s")',
|
||||||
|
$budgetLimit->id,
|
||||||
|
$budgetLimit->start_date->format('Y-m-d'),
|
||||||
|
$budgetLimit->end_date->format('Y-m-d')
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// overlap in days:
|
||||||
|
$limitPeriod = Period::make(
|
||||||
|
$budgetLimit->start_date,
|
||||||
|
$budgetLimit->end_date,
|
||||||
|
precision : Precision::DAY(),
|
||||||
|
boundaries: Boundaries::EXCLUDE_NONE()
|
||||||
|
);
|
||||||
|
// if both equal each other, amount from this BL must be added to the AB
|
||||||
|
if ($limitPeriod->equals($abPeriod)) {
|
||||||
|
Log::debug('This budget limit is equal to the available budget period.');
|
||||||
|
$newAmount = bcadd($newAmount, (string) $budgetLimit->amount);
|
||||||
|
}
|
||||||
|
// if budget limit period is inside AB period, it can be added in full.
|
||||||
|
if (!$limitPeriod->equals($abPeriod) && $abPeriod->contains($limitPeriod)) {
|
||||||
|
Log::debug('This budget limit is smaller than the available budget period.');
|
||||||
|
$newAmount = bcadd($newAmount, (string) $budgetLimit->amount);
|
||||||
|
}
|
||||||
|
if (!$limitPeriod->equals($abPeriod) && !$abPeriod->contains($limitPeriod) && $abPeriod->overlapsWith($limitPeriod)) {
|
||||||
|
Log::debug('This budget limit is something else entirely!');
|
||||||
|
$overlap = $abPeriod->overlap($limitPeriod);
|
||||||
|
if ($overlap instanceof Period) {
|
||||||
|
$length = $overlap->length();
|
||||||
|
$daily = bcmul($this->getDailyAmount($budgetLimit), (string) $length);
|
||||||
|
$newAmount = bcadd($newAmount, $daily);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (0 === bccomp('0', $newAmount)) {
|
||||||
|
Log::debug('New amount is zero, deleting AB.');
|
||||||
|
$availableBudget->delete();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Concluded new amount for this AB must be %s', $newAmount));
|
||||||
|
$availableBudget->amount = app('steam')->bcround($newAmount, $availableBudget->transactionCurrency->decimal_places);
|
||||||
|
$availableBudget->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDailyAmount(BudgetLimit $budgetLimit): string
|
||||||
|
{
|
||||||
|
if (0 === $budgetLimit->id) {
|
||||||
|
return '0';
|
||||||
|
}
|
||||||
|
$limitPeriod = Period::make(
|
||||||
|
$budgetLimit->start_date,
|
||||||
|
$budgetLimit->end_date,
|
||||||
|
precision : Precision::DAY(),
|
||||||
|
boundaries: Boundaries::EXCLUDE_NONE()
|
||||||
|
);
|
||||||
|
$days = $limitPeriod->length();
|
||||||
|
$amount = bcdiv($budgetLimit->amount, (string) $days, 12);
|
||||||
|
Log::debug(
|
||||||
|
sprintf('Total amount for budget limit #%d is %s. Nr. of days is %d. Amount per day is %s', $budgetLimit->id, $budgetLimit->amount, $days, $amount)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,14 +66,15 @@ trait UserGroupTrait
|
|||||||
if ($user instanceof User) {
|
if ($user instanceof User) {
|
||||||
$this->user = $user;
|
$this->user = $user;
|
||||||
if (null === $user->userGroup) {
|
if (null === $user->userGroup) {
|
||||||
throw new FireflyException(sprintf('User #%d has no user group.', $user->id));
|
throw new FireflyException(sprintf('User #%d ("%s") has no user group.', $user->id, $user->email));
|
||||||
}
|
}
|
||||||
$this->userGroup = $user->userGroup;
|
$this->userGroup = $user->userGroup;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
$class = null === $user ? 'NULL' : $user::class;
|
||||||
|
|
||||||
throw new FireflyException(sprintf('Object is of class %s, not User.', $user::class));
|
throw new FireflyException(sprintf('Object is %s, not User.', $class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getUserGroup(): ?UserGroup
|
public function getUserGroup(): ?UserGroup
|
||||||
|
|||||||
@@ -24,10 +24,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Support\Request;
|
namespace FireflyIII\Support\Request;
|
||||||
|
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
|
||||||
trait GetFilterInstructions
|
trait GetFilterInstructions
|
||||||
{
|
{
|
||||||
private const string INVALID_FILTER = '%INVALID_JAMES_%';
|
private const string INVALID_FILTER = '%INVALID_JAMES_%';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
final public function getFilterInstructions(string $key): array
|
final public function getFilterInstructions(string $key): array
|
||||||
{
|
{
|
||||||
$config = config(sprintf('firefly.filters.allowed.%s', $key));
|
$config = config(sprintf('firefly.filters.allowed.%s', $key));
|
||||||
@@ -48,7 +53,7 @@ trait GetFilterInstructions
|
|||||||
|
|
||||||
switch ($filterType) {
|
switch ($filterType) {
|
||||||
default:
|
default:
|
||||||
exit(sprintf('Do not support filter type "%s"', $filterType));
|
throw new FireflyException(sprintf('Do not support filter type "%s"', $filterType));
|
||||||
|
|
||||||
case 'boolean':
|
case 'boolean':
|
||||||
$filterValue = $this->booleanInstruction($filterValue);
|
$filterValue = $this->booleanInstruction($filterValue);
|
||||||
|
|||||||
@@ -356,8 +356,10 @@ class Steam
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$accountSum = array_values($accountSum)[0];
|
$accountSum = array_values($accountSum)[0];
|
||||||
|
$sumOfAmount = (string)$accountSum['sum_of_amount'];
|
||||||
|
$sumOfAmount = $this->floatalize('' === $sumOfAmount ? '0' : $sumOfAmount);
|
||||||
$sumsByCode = [
|
$sumsByCode = [
|
||||||
$accountSum['code'] => $accountSum['sum_of_amount'],
|
$accountSum['code'] => $sumOfAmount,
|
||||||
];
|
];
|
||||||
|
|
||||||
// Log::debug('All balances are (joined)', $others);
|
// Log::debug('All balances are (joined)', $others);
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ use FireflyIII\Models\BudgetLimit;
|
|||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Support\Facades\Amount;
|
use FireflyIII\Support\Facades\Amount;
|
||||||
use FireflyIII\Support\Facades\Steam;
|
use FireflyIII\Support\Facades\Steam;
|
||||||
|
use FireflyIII\Support\JsonApi\Enrichments\BudgetEnrichment;
|
||||||
use League\Fractal\Resource\Item;
|
use League\Fractal\Resource\Item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,7 +56,15 @@ class BudgetLimitTransformer extends AbstractTransformer
|
|||||||
*/
|
*/
|
||||||
public function includeBudget(BudgetLimit $limit)
|
public function includeBudget(BudgetLimit $limit)
|
||||||
{
|
{
|
||||||
return $this->item($limit->budget, new BudgetTransformer(), 'budgets');
|
// enrich budget
|
||||||
|
$budget = $limit->budget;
|
||||||
|
$enrichment = new BudgetEnrichment();
|
||||||
|
$enrichment->setStart($this->parameters->get('start'));
|
||||||
|
$enrichment->setEnd($this->parameters->get('end'));
|
||||||
|
$enrichment->setUser($budget->user);
|
||||||
|
$budget = $enrichment->enrichSingle($budget);
|
||||||
|
|
||||||
|
return $this->item($budget, new BudgetTransformer(), 'budgets');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -91,7 +100,7 @@ class BudgetLimitTransformer extends AbstractTransformer
|
|||||||
'currency_symbol' => $currency->symbol,
|
'currency_symbol' => $currency->symbol,
|
||||||
'currency_decimal_places' => $currency->decimal_places,
|
'currency_decimal_places' => $currency->decimal_places,
|
||||||
|
|
||||||
'primary_currency_id' => (int)$this->primaryCurrency->id,
|
'primary_currency_id' => (string) $this->primaryCurrency->id,
|
||||||
'primary_currency_name' => $this->primaryCurrency->name,
|
'primary_currency_name' => $this->primaryCurrency->name,
|
||||||
'primary_currency_code' => $this->primaryCurrency->code,
|
'primary_currency_code' => $this->primaryCurrency->code,
|
||||||
'primary_currency_symbol' => $this->primaryCurrency->symbol,
|
'primary_currency_symbol' => $this->primaryCurrency->symbol,
|
||||||
|
|||||||
@@ -79,8 +79,11 @@ class CategoryTransformer extends AbstractTransformer
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
private function beautify(array $array): array
|
private function beautify(?array $array): ?array
|
||||||
{
|
{
|
||||||
|
if (null === $array) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
$return = [];
|
$return = [];
|
||||||
foreach ($array as $data) {
|
foreach ($array as $data) {
|
||||||
$data['sum'] = Steam::bcround($data['sum'], (int)$data['currency_decimal_places']);
|
$data['sum'] = Steam::bcround($data['sum'], (int)$data['currency_decimal_places']);
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ class User extends Authenticatable
|
|||||||
use HasApiTokens;
|
use HasApiTokens;
|
||||||
use Notifiable;
|
use Notifiable;
|
||||||
use ReturnsIntegerIdTrait;
|
use ReturnsIntegerIdTrait;
|
||||||
protected $fillable = ['email', 'password', 'blocked', 'blocked_code'];
|
protected $fillable = ['email', 'password', 'blocked', 'blocked_code', 'user_group_id'];
|
||||||
protected $hidden = ['password', 'remember_token'];
|
protected $hidden = ['password', 'remember_token'];
|
||||||
protected $table = 'users';
|
protected $table = 'users';
|
||||||
|
|
||||||
|
|||||||
15
changelog.md
15
changelog.md
@@ -3,9 +3,20 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
## 6.3.0 - 2025-08-xx
|
## 6.3.1 - 2025-08-19
|
||||||
|
|
||||||
> ⚠️ Firefly III v6.3.0 introduces a lot of API changes that deal with multi-currency support. Make sure your beloved apps are updated to support this.
|
### Fixed
|
||||||
|
|
||||||
|
- [Discussion 10768](https://github.com/orgs/firefly-iii/discussions/10768) (Argument #1 ($start) must be of type Carbon\Carbon, null given) started by @tangodance
|
||||||
|
- [Issue 10771](https://github.com/firefly-iii/firefly-iii/issues/10771) (/v1/budgets/{id}/limits seems broken) reported by @Sceptorrh
|
||||||
|
- [Issue 10773](https://github.com/firefly-iii/firefly-iii/issues/10773) (API: Wrong Return types) reported by @dreautall
|
||||||
|
- [Issue 10775](https://github.com/firefly-iii/firefly-iii/issues/10775) (API: /v1/chart/account/overview broken) reported by @dreautall
|
||||||
|
- [Issue 10782](https://github.com/firefly-iii/firefly-iii/issues/10782) ([error'] /accounts/[asset,expense,revenue]) reported by @vkanev
|
||||||
|
|
||||||
|
## 6.3.0 - 2025-08-17
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> Firefly III v6.3.0 introduces a lot of API changes that deal with multi-currency support. Make sure your beloved apps are updated to support this.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
26
composer.lock
generated
26
composer.lock
generated
@@ -11771,16 +11771,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phpunit/phpunit",
|
"name": "phpunit/phpunit",
|
||||||
"version": "12.3.4",
|
"version": "12.3.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||||
"reference": "429095031bd38cb5070ca44166bd9dd5a9245dd6"
|
"reference": "f10ba5f12a256026ad3c7ee4894ffe47f60d7dc7"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/429095031bd38cb5070ca44166bd9dd5a9245dd6",
|
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f10ba5f12a256026ad3c7ee4894ffe47f60d7dc7",
|
||||||
"reference": "429095031bd38cb5070ca44166bd9dd5a9245dd6",
|
"reference": "f10ba5f12a256026ad3c7ee4894ffe47f60d7dc7",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -11802,7 +11802,7 @@
|
|||||||
"sebastian/cli-parser": "^4.0.0",
|
"sebastian/cli-parser": "^4.0.0",
|
||||||
"sebastian/comparator": "^7.1.2",
|
"sebastian/comparator": "^7.1.2",
|
||||||
"sebastian/diff": "^7.0.0",
|
"sebastian/diff": "^7.0.0",
|
||||||
"sebastian/environment": "^8.0.2",
|
"sebastian/environment": "^8.0.3",
|
||||||
"sebastian/exporter": "^7.0.0",
|
"sebastian/exporter": "^7.0.0",
|
||||||
"sebastian/global-state": "^8.0.0",
|
"sebastian/global-state": "^8.0.0",
|
||||||
"sebastian/object-enumerator": "^7.0.0",
|
"sebastian/object-enumerator": "^7.0.0",
|
||||||
@@ -11848,7 +11848,7 @@
|
|||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
|
||||||
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
|
||||||
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.4"
|
"source": "https://github.com/sebastianbergmann/phpunit/tree/12.3.5"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -11872,20 +11872,20 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-08-12T07:35:30+00:00"
|
"time": "2025-08-16T05:20:09+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "rector/rector",
|
"name": "rector/rector",
|
||||||
"version": "2.1.3",
|
"version": "2.1.4",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/rectorphp/rector.git",
|
"url": "https://github.com/rectorphp/rector.git",
|
||||||
"reference": "dd430c869fddf4965049c8fd6f5ee49f155cfddf"
|
"reference": "fe613c528819222f8686a9a037a315ef9d4915b3"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/rectorphp/rector/zipball/dd430c869fddf4965049c8fd6f5ee49f155cfddf",
|
"url": "https://api.github.com/repos/rectorphp/rector/zipball/fe613c528819222f8686a9a037a315ef9d4915b3",
|
||||||
"reference": "dd430c869fddf4965049c8fd6f5ee49f155cfddf",
|
"reference": "fe613c528819222f8686a9a037a315ef9d4915b3",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -11924,7 +11924,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/rectorphp/rector/issues",
|
"issues": "https://github.com/rectorphp/rector/issues",
|
||||||
"source": "https://github.com/rectorphp/rector/tree/2.1.3"
|
"source": "https://github.com/rectorphp/rector/tree/2.1.4"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -11932,7 +11932,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2025-08-13T11:43:04+00:00"
|
"time": "2025-08-15T14:41:36+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "sebastian/cli-parser",
|
"name": "sebastian/cli-parser",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user