Compare commits

..

57 Commits

Author SHA1 Message Date
github-actions[bot]
3c904c9017 Merge pull request #11286 from firefly-iii/release-1764136451
🤖 Automatically merge the PR into the develop branch.
2025-11-26 06:54:20 +01:00
JC5
d8bdbf2842 🤖 Auto commit for release 'develop' on 2025-11-26 2025-11-26 06:54:11 +01:00
James Cole
d08966d141 Add new correction command. 2025-11-26 06:50:29 +01:00
James Cole
bd71095e40 Merge branch 'main' into develop 2025-11-25 20:13:04 +01:00
James Cole
d7967a81e3 Fix https://github.com/firefly-iii/firefly-iii/issues/11284 2025-11-25 20:12:35 +01:00
James Cole
fa018e80c0 Replace classes 2025-11-25 20:12:23 +01:00
James Cole
eb4b9659cf Merge pull request #11278 from firefly-iii/dependabot/github_actions/actions/checkout-6
Bump actions/checkout from 5 to 6
2025-11-24 08:49:23 +01:00
github-actions[bot]
7b7b9118cd Merge pull request #11279 from firefly-iii/release-1763955257
🤖 Automatically merge the PR into the develop branch.
2025-11-24 04:34:26 +01:00
JC5
373e5c3733 🤖 Auto commit for release 'develop' on 2025-11-24 2025-11-24 04:34:17 +01:00
dependabot[bot]
4e0b1bf65d Bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-24 03:17:24 +00:00
James Cole
521a496c17 Fix #11267 2025-11-23 21:03:53 +01:00
James Cole
5fea35d5b1 Allow command to be forced. 2025-11-23 08:44:01 +01:00
James Cole
21a6892601 Fix #11265 2025-11-23 06:55:54 +01:00
James Cole
3f386b9003 Fix #11191 2025-11-19 06:26:40 +01:00
github-actions[bot]
72fb534eb4 Merge pull request #11249 from firefly-iii/release-1763402892
🤖 Automatically merge the PR into the develop branch.
2025-11-17 19:08:20 +01:00
JC5
69b46af245 🤖 Auto commit for release 'develop' on 2025-11-17 2025-11-17 19:08:12 +01:00
James Cole
4a901a1b42 Add a bunch of debug #11247 2025-11-17 19:01:38 +01:00
James Cole
a8fffc25c0 Merge pull request #11241 from firefly-iii/dependabot/composer/develop/bacon/bacon-qr-code-3.0.2
Bump bacon/bacon-qr-code from 3.0.1 to 3.0.2
2025-11-17 06:48:36 +01:00
mergify[bot]
d0dab136b1 Merge branch 'develop' into dependabot/composer/develop/bacon/bacon-qr-code-3.0.2 2025-11-17 05:47:38 +00:00
James Cole
91184489da Merge pull request #11242 from firefly-iii/dependabot/npm_and_yarn/develop/alpinejs-3.15.2
Bump alpinejs from 3.15.1 to 3.15.2
2025-11-17 06:46:55 +01:00
mergify[bot]
e4e6cc71c3 Merge branch 'develop' into dependabot/composer/develop/bacon/bacon-qr-code-3.0.2 2025-11-17 03:30:51 +00:00
mergify[bot]
33d637e618 Merge branch 'develop' into dependabot/npm_and_yarn/develop/alpinejs-3.15.2 2025-11-17 03:30:49 +00:00
github-actions[bot]
42eb4410f8 Merge pull request #11243 from firefly-iii/release-1763350179
🤖 Automatically merge the PR into the develop branch.
2025-11-17 04:29:45 +01:00
JC5
5f6b345c79 🤖 Auto commit for release 'develop' on 2025-11-17 2025-11-17 04:29:39 +01:00
dependabot[bot]
30b48a479c Bump alpinejs from 3.15.1 to 3.15.2
Bumps [alpinejs](https://github.com/alpinejs/alpine/tree/HEAD/packages/alpinejs) from 3.15.1 to 3.15.2.
- [Release notes](https://github.com/alpinejs/alpine/releases)
- [Commits](https://github.com/alpinejs/alpine/commits/v3.15.2/packages/alpinejs)

---
updated-dependencies:
- dependency-name: alpinejs
  dependency-version: 3.15.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-17 03:01:12 +00:00
dependabot[bot]
55d23af802 Bump bacon/bacon-qr-code from 3.0.1 to 3.0.2
Bumps [bacon/bacon-qr-code](https://github.com/Bacon/BaconQrCode) from 3.0.1 to 3.0.2.
- [Release notes](https://github.com/Bacon/BaconQrCode/releases)
- [Changelog](https://github.com/Bacon/BaconQrCode/blob/main/CHANGELOG.md)
- [Commits](https://github.com/Bacon/BaconQrCode/compare/v3.0.1...v3.0.2)

---
updated-dependencies:
- dependency-name: bacon/bacon-qr-code
  dependency-version: 3.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-17 03:00:53 +00:00
James Cole
34bfeba63a Fix #11211 2025-11-13 20:32:02 +01:00
github-actions[bot]
761c20b670 Merge pull request #11234 from firefly-iii/release-1763009724
🤖 Automatically merge the PR into the develop branch.
2025-11-13 05:55:30 +01:00
JC5
d756977ee0 🤖 Auto commit for release 'develop' on 2025-11-13 2025-11-13 05:55:24 +01:00
github-actions[bot]
40fe0d9c57 Merge pull request #11233 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2025-11-13 05:42:18 +01:00
github-actions[bot]
09b3fa1a52 Merge pull request #11232 from firefly-iii/release-1763008922
🤖 Automatically merge the PR into the develop branch.
2025-11-13 05:42:11 +01:00
JC5
bab767a447 🤖 Auto commit for release 'v6.4.8' on 2025-11-13 2025-11-13 05:42:02 +01:00
James Cole
341ab69939 Merge branch 'main' into develop 2025-11-13 05:37:15 +01:00
James Cole
479b90d9fc Expand changelog. 2025-11-13 05:36:59 +01:00
James Cole
91889332b4 Merge pull request #11231 from firefly-iii/dependabot/composer/composer-da8c4f16ae 2025-11-13 05:09:28 +01:00
dependabot[bot]
22b623c561 Bump symfony/http-foundation in the composer group across 1 directory
Bumps the composer group with 1 update in the / directory: [symfony/http-foundation](https://github.com/symfony/http-foundation).


Updates `symfony/http-foundation` from 7.3.6 to 7.3.7
- [Release notes](https://github.com/symfony/http-foundation/releases)
- [Changelog](https://github.com/symfony/http-foundation/blob/7.3/CHANGELOG.md)
- [Commits](https://github.com/symfony/http-foundation/compare/v7.3.6...v7.3.7)

---
updated-dependencies:
- dependency-name: symfony/http-foundation
  dependency-version: 7.3.7
  dependency-type: indirect
  dependency-group: composer
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-12 23:42:25 +00:00
github-actions[bot]
75932a9671 Merge pull request #11229 from firefly-iii/release-1762967310
🤖 Automatically merge the PR into the develop branch.
2025-11-12 18:08:37 +01:00
JC5
3ec528812b 🤖 Auto commit for release 'develop' on 2025-11-12 2025-11-12 18:08:30 +01:00
James Cole
78de800777 Fix #11228 2025-11-12 18:02:24 +01:00
github-actions[bot]
4456b00cae Merge pull request #11223 from firefly-iii/develop
🤖 Automatically merge the PR into the main branch.
2025-11-12 05:50:16 +01:00
github-actions[bot]
a3c02d7e07 Merge pull request #11222 from firefly-iii/release-1762923004
🤖 Automatically merge the PR into the develop branch.
2025-11-12 05:50:11 +01:00
JC5
d9ff71b1a5 🤖 Auto commit for release 'v6.4.7' on 2025-11-12 2025-11-12 05:50:05 +01:00
James Cole
2e5528167c Don't do comment. 2025-11-12 05:46:21 +01:00
github-actions[bot]
377486d5c7 Merge pull request #11221 from firefly-iii/release-1762922569
🤖 Automatically merge the PR into the develop branch.
2025-11-12 05:42:58 +01:00
JC5
c91845a0f2 🤖 Auto commit for release 'develop' on 2025-11-12 2025-11-12 05:42:49 +01:00
James Cole
0934de09bb Fix #11206 2025-11-12 05:38:31 +01:00
James Cole
55c045c791 Fix #11172 2025-11-12 05:37:33 +01:00
James Cole
8ff2f817c6 Merge branch 'main' into develop 2025-11-12 05:36:57 +01:00
James Cole
49b42538f5 Improve automated reply message for debug info
Signed-off-by: James Cole <james@firefly-iii.org>
2025-11-11 09:37:30 +01:00
James Cole
3fd31bdf70 Fix workflows. 2025-11-11 07:01:30 +01:00
James Cole
24e144df5d Merge branch 'main' into develop 2025-11-11 06:18:49 +01:00
James Cole
abfa2af278 Expand tests. 2025-11-11 06:16:36 +01:00
James Cole
e3efb275a9 Merge pull request #11213 from firefly-iii/JC5-patch-2
Fix typo in automated reply message
2025-11-10 14:41:12 +01:00
James Cole
122a389a95 Fix typo in automated reply message
Signed-off-by: James Cole <james@firefly-iii.org>
2025-11-10 14:40:41 +01:00
James Cole
b54d7d5c7b Enhance issue reply condition for old versions
Updated condition to check for additional version variables in issue body.

Signed-off-by: James Cole <james@firefly-iii.org>
2025-11-10 09:02:57 +01:00
James Cole
897c80c2d8 Merge pull request #11209 from firefly-iii/JC5-patch-1
Update issues-reply-old-versions.yml
2025-11-10 09:00:46 +01:00
James Cole
9448402d9f Update issues-reply-old-versions.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2025-11-10 09:00:33 +01:00
52 changed files with 901 additions and 635 deletions

View File

@@ -402,16 +402,16 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.89.2",
"version": "v3.90.0",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "7569658f91e475ec93b99bd5964b059ad1336dcf"
"reference": "ad732c2e9299c9743f9c55ae53cc0e7642ab1155"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/7569658f91e475ec93b99bd5964b059ad1336dcf",
"reference": "7569658f91e475ec93b99bd5964b059ad1336dcf",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/ad732c2e9299c9743f9c55ae53cc0e7642ab1155",
"reference": "ad732c2e9299c9743f9c55ae53cc0e7642ab1155",
"shasum": ""
},
"require": {
@@ -429,17 +429,17 @@
"react/socket": "^1.16",
"react/stream": "^1.4",
"sebastian/diff": "^4.0.6 || ^5.1.1 || ^6.0.2 || ^7.0",
"symfony/console": "^5.4.47 || ^6.4.24 || ^7.0",
"symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0",
"symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0",
"symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0",
"symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0",
"symfony/console": "^5.4.47 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/event-dispatcher": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/polyfill-mbstring": "^1.33",
"symfony/polyfill-php80": "^1.33",
"symfony/polyfill-php81": "^1.33",
"symfony/polyfill-php84": "^1.33",
"symfony/process": "^5.4.47 || ^6.4.24 || ^7.2",
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0"
"symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0",
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0"
},
"require-dev": {
"facile-it/paraunit": "^1.3.1 || ^2.7",
@@ -451,8 +451,8 @@
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.6",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.6",
"phpunit/phpunit": "^9.6.25 || ^10.5.53 || ^11.5.34",
"symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2",
"symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2"
"symfony/var-dumper": "^5.4.48 || ^6.4.24 || ^7.3.2 || ^8.0",
"symfony/yaml": "^5.4.45 || ^6.4.24 || ^7.3.2 || ^8.0"
},
"suggest": {
"ext-dom": "For handling output formats in XML",
@@ -493,7 +493,7 @@
],
"support": {
"issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues",
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.89.2"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.90.0"
},
"funding": [
{
@@ -501,7 +501,7 @@
"type": "github"
}
],
"time": "2025-11-06T21:12:50+00:00"
"time": "2025-11-20T15:15:16+00:00"
},
{
"name": "psr/container",
@@ -805,16 +805,16 @@
},
{
"name": "react/dns",
"version": "v1.13.0",
"version": "v1.14.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/dns.git",
"reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5"
"reference": "7562c05391f42701c1fccf189c8225fece1cd7c3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/dns/zipball/eb8ae001b5a455665c89c1df97f6fb682f8fb0f5",
"reference": "eb8ae001b5a455665c89c1df97f6fb682f8fb0f5",
"url": "https://api.github.com/repos/reactphp/dns/zipball/7562c05391f42701c1fccf189c8225fece1cd7c3",
"reference": "7562c05391f42701c1fccf189c8225fece1cd7c3",
"shasum": ""
},
"require": {
@@ -869,7 +869,7 @@
],
"support": {
"issues": "https://github.com/reactphp/dns/issues",
"source": "https://github.com/reactphp/dns/tree/v1.13.0"
"source": "https://github.com/reactphp/dns/tree/v1.14.0"
},
"funding": [
{
@@ -877,20 +877,20 @@
"type": "open_collective"
}
],
"time": "2024-06-13T14:18:03+00:00"
"time": "2025-11-18T19:34:28+00:00"
},
{
"name": "react/event-loop",
"version": "v1.5.0",
"version": "v1.6.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/event-loop.git",
"reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354"
"reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/event-loop/zipball/bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354",
"reference": "bbe0bd8c51ffc05ee43f1729087ed3bdf7d53354",
"url": "https://api.github.com/repos/reactphp/event-loop/zipball/ba276bda6083df7e0050fd9b33f66ad7a4ac747a",
"reference": "ba276bda6083df7e0050fd9b33f66ad7a4ac747a",
"shasum": ""
},
"require": {
@@ -941,7 +941,7 @@
],
"support": {
"issues": "https://github.com/reactphp/event-loop/issues",
"source": "https://github.com/reactphp/event-loop/tree/v1.5.0"
"source": "https://github.com/reactphp/event-loop/tree/v1.6.0"
},
"funding": [
{
@@ -949,7 +949,7 @@
"type": "open_collective"
}
],
"time": "2023-11-13T13:48:05+00:00"
"time": "2025-11-17T20:46:25+00:00"
},
{
"name": "react/promise",
@@ -1026,16 +1026,16 @@
},
{
"name": "react/socket",
"version": "v1.16.0",
"version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/reactphp/socket.git",
"reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1"
"reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/reactphp/socket/zipball/23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1",
"reference": "23e4ff33ea3e160d2d1f59a0e6050e4b0fb0eac1",
"url": "https://api.github.com/repos/reactphp/socket/zipball/ef5b17b81f6f60504c539313f94f2d826c5faa08",
"reference": "ef5b17b81f6f60504c539313f94f2d826c5faa08",
"shasum": ""
},
"require": {
@@ -1094,7 +1094,7 @@
],
"support": {
"issues": "https://github.com/reactphp/socket/issues",
"source": "https://github.com/reactphp/socket/tree/v1.16.0"
"source": "https://github.com/reactphp/socket/tree/v1.17.0"
},
"funding": [
{
@@ -1102,7 +1102,7 @@
"type": "open_collective"
}
],
"time": "2024-07-26T10:38:09+00:00"
"time": "2025-11-19T20:47:34+00:00"
},
{
"name": "react/stream",
@@ -2675,5 +2675,5 @@
"prefer-lowest": false,
"platform": {},
"platform-dev": {},
"plugin-api-version": "2.6.0"
"plugin-api-version": "2.9.0"
}

View File

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout repository'
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: 'Dependency review'

View File

@@ -32,18 +32,82 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
- run: |
ISSUE_BODY=$(gh issue view $NUMBER --json body)
if [[ $ISSUE_BODY == *"MZ2udTpin6FL"* && $ISSUE_BODY != *${{ steps.ff3version.outputs.release }}* && $ISSUE_BODY != *${{ steps.importerversion.outputs.release }}* ]]; then
# sure this can be done in a single step but still.
FFNOV="${{ steps.ff3version.outputs.release }}"
FFNOV="${FFNOV:1}"
DDNOV="${{ steps.importerversion.outputs.release }}"
DDNOV="${DDNOV:1}"
echo "Firefly III version is ${{ steps.ff3version.outputs.release }}, without v is $FFNOV"
echo "Data importer version is ${{ steps.ff3version.outputs.release }}, without v is $FFNOV"
# user includes no debug info at all, and does not mention current version.
# user includes no debug info at all, but does mention current version
# user includes debug info, but not the current version.
# user includes debug info, and the current version.
# first test: user includes no debug info at all, and does not mention current version.
if [[ $ISSUE_BODY == *"MZ2udTpin6FL"* && $ISSUE_BODY != *"Debug information generated at"* && $ISSUE_BODY != *${{ steps.ff3version.outputs.release }}* && $ISSUE_BODY != *${{ steps.importerversion.outputs.release }}* && $ISSUE_BODY != *$FFNOV* && $ISSUE_BODY != *$DDNOV* ]]; then
MESSAGE="Hi there!
This is an automated reply. \`Share and enjoy\`
You triggered an automated reply, because it looks like you didn't include the output from the \`/debug\` page. Would you be so kind as to do that? It helps the developers debug your issue more easily.
If you *did* include debug information or of if the debug information isn't relevant (or even reachable), my apologies for the intrusion."
gh issue comment "$NUMBER" --body "$MESSAGE"
echo "Triggered on first test"
exit 0
fi
# second test: user includes no debug info at all, but does mention current version
if [[ $ISSUE_BODY == *"MZ2udTpin6FL"* && $ISSUE_BODY != *"Debug information generated at"* && ( $ISSUE_BODY == *${{ steps.ff3version.outputs.release }}* || $ISSUE_BODY == *${{ steps.importerversion.outputs.release }}* || $ISSUE_BODY == *$FFNOV* || $ISSUE_BODY == *$DDNOV* ) ]]; then
MESSAGE="Hi there!
This is an automated reply. \`Share and enjoy\`
Thank you for running the latest version of Firefly III (or the data importer). You triggered an automated reply, because it looks like you didn't include the output from the \`/debug\` page. Would you be so kind as to do that? It helps the developers debug your issue more easily.
If you *did* include debug information or of if the debug information isn't relevant (or even reachable), my apologies for the intrusion."
gh issue comment "$NUMBER" --body "$MESSAGE"
echo "Triggered on second test"
exit 0
fi
# third test: user includes debug info, but not the current version.
if [[ $ISSUE_BODY == *"MZ2udTpin6FL"* && $ISSUE_BODY == *"Debug information generated at"* && $ISSUE_BODY != *${{ steps.ff3version.outputs.release }}* && $ISSUE_BODY != *${{ steps.importerversion.outputs.release }}* && $ISSUE_BODY != *$FFNOV* && $ISSUE_BODY != *$DDNOV* ]]; then
MESSAGE="Hi there!
This is an automated reply. \`Share and enjoy\`
You triggered an automated reply, because it looks like you're not running Firefly III version **${{ steps.ff3version.outputs.release }}** or version **${{ steps.importerversion.outputs.release }}** of the data importer.
Thank you for including debug information. You triggered an automated reply, because it looks like you're not running Firefly III version **${{ steps.ff3version.outputs.release }}** or version **${{ steps.importerversion.outputs.release }}** of the data importer.
Please be so kind as to include the output from the \`/debug\`-page, if you have not done so already. If you already included the debug information, plase make sure to upgrade to the latest version of Firefly III (or the data importer) *first*. This may already solve your issue.
Please make sure to upgrade to the latest version of Firefly III (or the data importer) *first*. This may already solve your issue.
If you *are* running the latest version, and this message is wrong, my apologies for the intrusion."
If you are running the latest version, and this message is wrong, my apologies for the intrusion."
gh issue comment "$NUMBER" --body "$MESSAGE"
echo "Triggered on third test"
exit 0
fi
# fourth test: user includes debug info, and the current version.
if [[ $ISSUE_BODY == *"MZ2udTpin6FL"* && $ISSUE_BODY == *"Debug information generated at"* && ( $ISSUE_BODY == *${{ steps.ff3version.outputs.release }}* || $ISSUE_BODY == *${{ steps.importerversion.outputs.release }}* || $ISSUE_BODY == *$FFNOV* || $ISSUE_BODY == *$DDNOV* ) ]]; then
MESSAGE="Hi there!
This is an automated reply. \`Share and enjoy\`
Thank you for running the latest version of Firefly III (or the data importer)."
# gh issue comment "$NUMBER" --body "$MESSAGE"
echo "Triggered on fourth test"
exit 0
fi
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -29,7 +29,7 @@ jobs:
env:
version: ${{ github.event_name == 'schedule' && 'develop' || inputs.version }}
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Import GPG key

View File

@@ -40,7 +40,7 @@ class IndexController extends Controller
{
use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'currency_exchange_rates';
public const string RESOURCE_KEY = 'exchange-rates';
protected array $acceptedRoles = [UserRoleEnum::OWNER];
private ExchangeRateRepositoryInterface $repository;

View File

@@ -23,15 +23,16 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Generic;
use Override;
use Illuminate\Contracts\Validation\Validator;
use FireflyIII\Api\V1\Requests\ApiRequest;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use FireflyIII\Rules\Account\IsValidAccountTypeList;
use FireflyIII\Rules\TransactionType\IsValidTransactionTypeList;
use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter;
use Illuminate\Contracts\Validation\Validator;
use Override;
use RuntimeException;
class ObjectTypeApiRequest extends ApiRequest
@@ -88,7 +89,11 @@ class ObjectTypeApiRequest extends ApiRequest
// no break
case Account::class:
$this->attributes->set('types', $this->mapAccountTypes($type));
$types = $this->mapAccountTypes($type);
// remove system account types because autocomplete doesn't need them.
$types = array_values(array_diff($types, [AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::RECONCILIATION->value, AccountTypeEnum::LIABILITY_CREDIT->value]));
$this->attributes->set('types', $types);
break;

View File

@@ -74,6 +74,7 @@ class CorrectsDatabase extends Command
'correction:group-accounts',
'correction:recalculates-liabilities',
'correction:preferences',
'correction:corrects-inverted-budget-limits',
// 'correction:transaction-types', // resource heavy, disabled.
'correction:recalculate-pc-amounts',
'correction:remove-links-to-deleted-objects',

View File

@@ -0,0 +1,80 @@
<?php
declare(strict_types=1);
/*
* CorrectsInversedBudgetLimits.php
* Copyright (c) 2025 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/>.
*/
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Console\Commands\ShowsFriendlyMessages;
use FireflyIII\Models\BudgetLimit;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class CorrectsInvertedBudgetLimits extends Command
{
use ShowsFriendlyMessages;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'correction:corrects-inverted-budget-limits';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Reverse budget limits where the dates are inverted.';
/**
* Execute the console command.
*/
public function handle(): int
{
$set = BudgetLimit::where('start_date', '>', DB::raw('end_date'))->get();
if (0 === $set->count()) {
Log::debug('No inverted budget limits found.');
return Command::SUCCESS;
}
/** @var BudgetLimit $budgetLimit */
foreach ($set as $budgetLimit) {
$start = $budgetLimit->start_date->copy();
$end = $budgetLimit->end_date->copy();
$budgetLimit->start_date = $end;
$budgetLimit->end_date = $start;
$budgetLimit->saveQuietly();
}
if (1 === $set->count()) {
$this->friendlyInfo('Corrected one budget limit to have the right start/end dates.');
return Command::SUCCESS;
}
$this->friendlyInfo(sprintf('Corrected %d budget limits to have the right start/end dates.', count($set)));
return Command::SUCCESS;
}
}

View File

@@ -56,7 +56,7 @@ class ForcesDecimalSize extends Command
use ShowsFriendlyMessages;
protected $description = 'This command resizes DECIMAL columns in MySQL or PostgreSQL and correct amounts (only MySQL).';
protected $signature = 'firefly-iii:force-decimal-size';
protected $signature = 'firefly-iii:force-decimal-size {--force}';
private string $cast;
private array $classes
= [
@@ -98,9 +98,14 @@ class ForcesDecimalSize extends Command
Log::debug('Now in ForceDecimalSize::handle()');
$this->determineDatabaseType();
$this->friendlyError('Running this command is dangerous and can cause data loss.');
$this->friendlyError('Please do not continue.');
$question = $this->confirm('Do you want to continue?');
$force = $this->option('force');
$question = true;
if (false === $force) {
$this->friendlyError('Running this command is dangerous and can cause data loss.');
$this->friendlyError('Please make sure you have a backup.');
$question = $this->confirm('Do you want to continue?');
}
if (true === $question) {
$this->correctAmounts();
$this->updateDecimals();
@@ -131,17 +136,17 @@ class ForcesDecimalSize extends Command
private function correctAmounts(): void
{
// if sqlite, add function?
if ('sqlite' === (string) config('database.default')) {
if ('sqlite' === (string)config('database.default')) {
DB::connection()->getPdo()->sqliteCreateFunction('REGEXP', static function ($pattern, $value): int {
mb_regex_encoding('UTF-8');
$pattern = trim($pattern, '"');
return (mb_ereg($pattern, (string) $value)) ? 1 : 0;
return (mb_ereg($pattern, (string)$value)) ? 1 : 0;
});
}
if (!in_array((string) config('database.default'), ['mysql', 'pgsql', 'sqlite'], true)) {
$this->friendlyWarning(sprintf('Skip correcting amounts, does not support "%s"...', (string) config('database.default')));
if (!in_array((string)config('database.default'), ['mysql', 'pgsql', 'sqlite'], true)) {
$this->friendlyWarning(sprintf('Skip correcting amounts, does not support "%s"...', (string)config('database.default')));
return;
}
@@ -236,7 +241,7 @@ class ForcesDecimalSize extends Command
/** @var Builder $query */
$query = Account::leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id')
->where('account_meta.name', 'currency_id')
->where('account_meta.data', json_encode((string) $currency->id))
->where('account_meta.data', json_encode((string)$currency->id))
;
$query->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void {
foreach ($fields as $field) {
@@ -264,7 +269,7 @@ class ForcesDecimalSize extends Command
}
// fix $field by rounding it down correctly.
$pow = 10 ** $currency->decimal_places;
$correct = bcdiv((string) round($value * $pow), (string) $pow, 12);
$correct = bcdiv((string)round($value * $pow), (string)$pow, 12);
$this->friendlyInfo(sprintf('Account #%d has %s with value "%s", this has been corrected to "%s".', $account->id, $field, $value, $correct));
/** @var null|Account $updateAccount */
@@ -316,7 +321,7 @@ class ForcesDecimalSize extends Command
}
// fix $field by rounding it down correctly.
$pow = 10 ** $currency->decimal_places;
$correct = bcdiv((string) round($value * $pow), (string) $pow, 12);
$correct = bcdiv((string)round($value * $pow), (string)$pow, 12);
$this->friendlyWarning(sprintf('%s #%d has %s with value "%s", this has been corrected to "%s".', $table, $item->id, $field, $value, $correct));
/** @var null|Model $model */
@@ -340,7 +345,7 @@ class ForcesDecimalSize extends Command
->leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id')
->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id')
->where('account_meta.name', 'currency_id')
->where('account_meta.data', json_encode((string) $currency->id))
->where('account_meta.data', json_encode((string)$currency->id))
->where(static function (Builder $q) use ($fields, $currency, $cast, $operator, $regularExpression): void {
foreach ($fields as $field) {
$q->orWhere(
@@ -369,7 +374,7 @@ class ForcesDecimalSize extends Command
}
// fix $field by rounding it down correctly.
$pow = 10 ** $currency->decimal_places;
$correct = bcdiv((string) round($value * $pow), (string) $pow, 12);
$correct = bcdiv((string)round($value * $pow), (string)$pow, 12);
$this->friendlyWarning(
sprintf('Piggy bank event #%d has %s with value "%s", this has been corrected to "%s".', $item->id, $field, $value, $correct)
);
@@ -396,7 +401,7 @@ class ForcesDecimalSize extends Command
->leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id')
->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id')
->where('account_meta.name', 'currency_id')
->where('account_meta.data', json_encode((string) $currency->id))
->where('account_meta.data', json_encode((string)$currency->id))
->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void {
foreach ($fields as $field) {
$q->orWhere(
@@ -425,7 +430,7 @@ class ForcesDecimalSize extends Command
}
// fix $field by rounding it down correctly.
$pow = 10 ** $currency->decimal_places;
$correct = bcdiv((string) round($value * $pow), (string) $pow, 12);
$correct = bcdiv((string)round($value * $pow), (string)$pow, 12);
$this->friendlyWarning(
sprintf('Piggy bank repetition #%d has %s with value "%s", this has been corrected to "%s".', $item->id, $field, $value, $correct)
);
@@ -450,7 +455,7 @@ class ForcesDecimalSize extends Command
$query = PiggyBank::leftJoin('accounts', 'piggy_banks.account_id', '=', 'accounts.id')
->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id')
->where('account_meta.name', 'currency_id')
->where('account_meta.data', json_encode((string) $currency->id))
->where('account_meta.data', json_encode((string)$currency->id))
->where(static function (Builder $q) use ($fields, $currency, $operator, $cast, $regularExpression): void {
foreach ($fields as $field) {
$q->orWhere(
@@ -479,7 +484,7 @@ class ForcesDecimalSize extends Command
}
// fix $field by rounding it down correctly.
$pow = 10 ** $currency->decimal_places;
$correct = bcdiv((string) round($value * $pow), (string) $pow, 12);
$correct = bcdiv((string)round($value * $pow), (string)$pow, 12);
$this->friendlyWarning(sprintf('Piggy bank #%d has %s with value "%s", this has been corrected to "%s".', $item->id, $field, $value, $correct));
/** @var null|PiggyBank $piggyBank */
@@ -515,7 +520,7 @@ class ForcesDecimalSize extends Command
}
// fix $field by rounding it down correctly.
$pow = 10.0 ** $currency->decimal_places;
$correct = bcdiv((string) round((float) $value * $pow), (string) $pow, 12);
$correct = bcdiv((string)round((float)$value * $pow), (string)$pow, 12);
$this->friendlyWarning(sprintf('Transaction #%d has amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct));
/** @var null|Transaction $transaction */
@@ -546,7 +551,7 @@ class ForcesDecimalSize extends Command
}
// fix $field by rounding it down correctly.
$pow = 10.0 ** $currency->decimal_places;
$correct = bcdiv((string) round((float) $value * $pow), (string) $pow, 12);
$correct = bcdiv((string)round((float)$value * $pow), (string)$pow, 12);
$this->friendlyWarning(
sprintf('Transaction #%d has foreign amount with value "%s", this has been corrected to "%s".', $item->id, $value, $correct)
);
@@ -560,7 +565,7 @@ class ForcesDecimalSize extends Command
private function updateDecimals(): void
{
$this->friendlyInfo('Going to force the size of DECIMAL columns. Please hold.');
$type = (string) config('database.default');
$type = (string)config('database.default');
/**
* @var string $name

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Helpers\Report;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Helpers\Fiscal\FiscalHelperInterface;
@@ -81,7 +82,7 @@ class ReportHelper implements ReportHelperInterface
/** @var Carbon $expectedStart */
foreach ($expectedDates as $expectedStart) {
$expectedEnd = app('navigation')->endOfX($expectedStart, $bill->repeat_freq, null);
$expectedEnd = Navigation::endOfX($expectedStart, $bill->repeat_freq, null);
// is paid in this period maybe?
/** @var GroupCollectorInterface $collector */

View File

@@ -167,12 +167,17 @@ class IndexController extends Controller
/** @var Carbon $end */
$end = clone session('end', today(config('app.timezone'))->endOfMonth());
$now = now();
if ($now->gt($end) || $now->lt($start)) {
$now = $end;
}
$ids = $accounts->pluck('id')->toArray();
Log::debug(sprintf('index: accountsBalancesInRange("%s", "%s")', $start->format('Y-m-d H:i:s'), $end->format('Y-m-d H:i:s')));
[
$startBalances,
$endBalances,
] = Steam::accountsBalancesInRange($accounts, $start, $end, $this->primaryCurrency, $this->convertToPrimary);
] = Steam::accountsBalancesInRange($accounts, $start, $now, $this->primaryCurrency, $this->convertToPrimary);
$activities = Steam::getLastActivities($ids);

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Account;
use FireflyIII\Support\Facades\Navigation;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;
use FireflyIII\Enums\AccountTypeEnum;
@@ -91,20 +92,20 @@ class ReconcileController extends Controller
$currency = $this->accountRepos->getAccountCurrency($account) ?? $this->primaryCurrency;
// no start or end:
$range = app('navigation')->getViewRange(false);
$range = Navigation::getViewRange(false);
// get start and end
if (!$start instanceof Carbon && !$end instanceof Carbon) {
/** @var Carbon $start */
$start = clone session('start', app('navigation')->startOfPeriod(new Carbon(), $range));
$start = clone session('start', Navigation::startOfPeriod(new Carbon(), $range));
/** @var Carbon $end */
$end = clone session('end', app('navigation')->endOfPeriod(new Carbon(), $range));
$end = clone session('end', Navigation::endOfPeriod(new Carbon(), $range));
}
if (null === $end) {
/** @var Carbon $end */
$end = app('navigation')->endOfPeriod($start, $range);
$end = Navigation::endOfPeriod($start, $range);
}
if ($end->lt($start)) {

View File

@@ -164,7 +164,7 @@ class ShowController extends Controller
$timer->stop('collection');
$groups->setPath(route('accounts.show', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]));
$showAll = false;
$now = today()->endOfDay();
$now = now();
if ($now->gt($end) || $now->lt($start)) {
$now = $end;
}
@@ -173,10 +173,7 @@ class ShowController extends Controller
$balances = Steam::accountsBalancesOptimized(new Collection()->push($account), $now)[$account->id];
// $balances = Steam::filterAccountBalance(Steam::finalAccountBalance($account, $now), $account, $this->convertToPrimary, $accountCurrency);
return view(
'accounts.show',
['account' => $account, 'showAll' => $showAll, 'objectType' => $objectType, 'currency' => $currency, 'today' => $today, 'periods' => $periods, 'subTitleIcon' => $subTitleIcon, 'groups' => $groups, 'attachments' => $attachments, 'subTitle' => $subTitle, 'start' => $start, 'end' => $end, 'chartUrl' => $chartUrl, 'location' => $location, 'balances' => $balances]
);
return view('accounts.show', ['account' => $account, 'showAll' => $showAll, 'objectType' => $objectType, 'currency' => $currency, 'today' => $today, 'periods' => $periods, 'subTitleIcon' => $subTitleIcon, 'groups' => $groups, 'attachments' => $attachments, 'subTitle' => $subTitle, 'start' => $start, 'end' => $end, 'chartUrl' => $chartUrl, 'location' => $location, 'balances' => $balances]);
}
/**
@@ -224,14 +221,16 @@ class ShowController extends Controller
// correct
Log::debug(sprintf('showAll: Call accountsBalancesOptimized with date/time "%s"', $end->toIso8601String()));
$now = now();
if ($now->gt($end) || $now->lt($start)) {
$now = $end;
}
// 2025-10-08 replace finalAccountBalance with accountsBalancesOptimized.
// $balances = Steam::finalAccountBalance($account, $end);
// $balances = Steam::filterAccountBalance($balances, $account, $this->convertToPrimary, $accountCurrency);
$balances = Steam::accountsBalancesOptimized(new Collection()->push($account), $end)[$account->id];
$balances = Steam::accountsBalancesOptimized(new Collection()->push($account), $now)[$account->id];
return view(
'accounts.show',
['account' => $account, 'showAll' => $showAll, 'location' => $location, 'objectType' => $objectType, 'isLiability' => $isLiability, 'attachments' => $attachments, 'currency' => $currency, 'today' => $today, 'chartUrl' => $chartUrl, 'periods' => $periods, 'subTitleIcon' => $subTitleIcon, 'groups' => $groups, 'subTitle' => $subTitle, 'start' => $start, 'end' => $end, 'balances' => $balances]
);
return view('accounts.show', ['account' => $account, 'showAll' => $showAll, 'location' => $location, 'objectType' => $objectType, 'isLiability' => $isLiability, 'attachments' => $attachments, 'currency' => $currency, 'today' => $today, 'chartUrl' => $chartUrl, 'periods' => $periods, 'subTitleIcon' => $subTitleIcon, 'groups' => $groups, 'subTitle' => $subTitle, 'start' => $start, 'end' => $end, 'balances' => $balances]);
}
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Bill;
use FireflyIII\Support\Facades\Navigation;
use Illuminate\Support\Facades\Log;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Bill;
@@ -151,7 +152,7 @@ class IndexController extends Controller
private function getSums(array $bills): array
{
$sums = [];
$range = app('navigation')->getViewRange(true);
$range = Navigation::getViewRange(true);
/** @var array $group */
foreach ($bills as $groupOrder => $group) {

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Bill;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Http\Controllers\Controller;
@@ -139,8 +140,8 @@ class ShowController extends Controller
$manager->parseIncludes(['attachments', 'notes']);
// add another period to end, could fix 8163
$range = app('navigation')->getViewRange(true);
$end = app('navigation')->addPeriod($end, $range);
$range = Navigation::getViewRange(true);
$end = Navigation::addPeriod($end, $range);
// Make a resource out of the data and
$parameters = new ParameterBag();

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Budget;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
@@ -94,11 +95,11 @@ class IndexController extends Controller
Log::debug(sprintf('Start of IndexController::index("%s", "%s")', $start?->format('Y-m-d'), $end?->format('Y-m-d')));
// collect some basic vars:
$range = app('navigation')->getViewRange(true);
$range = Navigation::getViewRange(true);
$isCustomRange = session('is_custom_range', false);
if (false === $isCustomRange) {
$start ??= session('start', today(config('app.timezone'))->startOfMonth());
$end ??= app('navigation')->endOfPeriod($start, $range);
$end ??= Navigation::endOfPeriod($start, $range);
}
// overrule start and end if necessary:
@@ -112,7 +113,7 @@ class IndexController extends Controller
$spent = '0';
// new period stuff:
$periodTitle = app('navigation')->periodShow($start, $range);
$periodTitle = Navigation::periodShow($start, $range);
$prevLoop = $this->getPreviousPeriods($start, $range);
$nextLoop = $this->getNextPeriods($start, $range);

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Chart;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
@@ -514,7 +515,7 @@ class AccountController extends Controller
// have to make sure this chart is always based on the balance at the END of the period.
// This period depends on the size of the chart
$current = clone $start;
$current = app('navigation')->endOfX($current, $step, null);
$current = Navigation::endOfX($current, $step, null);
$format = (string)trans('config.month_and_day_js', [], $locale);
$accountCurrency = $this->accountRepository->getAccountCurrency($account);
Log::debug('Get and filter balance for entire range start');
@@ -574,9 +575,9 @@ class AccountController extends Controller
$label = $current->isoFormat($format);
$return[$key]['entries'][$label] = $amount;
}
$current = app('navigation')->addPeriod($current, $step);
$current = Navigation::addPeriod($current, $step);
// here too, to fix #8041, the data is corrected to the end of the period.
$current = app('navigation')->endOfX($current, $step, null);
$current = Navigation::endOfX($current, $step, null);
}
Log::debug('End of chart loop.');
// second loop (yes) to create nice array with info! Yay!

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Chart;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
use FireflyIII\Http\Controllers\Controller;
@@ -81,8 +82,8 @@ class CategoryController extends Controller
/** @var CategoryRepositoryInterface $repository */
$repository = app(CategoryRepositoryInterface::class);
$start = $repository->firstUseDate($category) ?? $this->getDate();
$range = app('navigation')->getViewRange(false);
$start = app('navigation')->startOfPeriod($start, $range);
$range = Navigation::getViewRange(false);
$start = Navigation::startOfPeriod($start, $range);
$end = $this->getDate();
/** @var WholePeriodChartGenerator $chartGenerator */
@@ -178,8 +179,8 @@ class CategoryController extends Controller
$income = $opsRepository->listIncome($start, $end, $accounts, $collection);
}
$currencies = array_unique(array_merge(array_keys($income), array_keys($expenses)));
$periods = app('navigation')->listOfPeriods($start, $end);
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
$periods = Navigation::listOfPeriods($start, $end);
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
$chartData = [];
// make empty data array:
// double foreach (bad) to make empty array:
@@ -260,8 +261,8 @@ class CategoryController extends Controller
*/
public function specificPeriod(Category $category, Carbon $date): JsonResponse
{
$range = app('navigation')->getViewRange(false);
$start = app('navigation')->startOfPeriod($date, $range);
$range = Navigation::getViewRange(false);
$start = Navigation::startOfPeriod($date, $range);
$end = session()->get('end');
if ($end < $start) {
[$end, $start] = [$start, $end];

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Chart;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
use FireflyIII\Http\Controllers\Controller;
@@ -210,7 +211,7 @@ class CategoryReportController extends Controller
$chartData = [];
$spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection()->push($category));
$earned = $this->opsRepository->listIncome($start, $end, $accounts, new Collection()->push($category));
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
// loop expenses.
foreach ($spent as $currency) {
// add things to chart Data for each currency:
@@ -276,11 +277,11 @@ class CategoryReportController extends Controller
private function makeEntries(Carbon $start, Carbon $end): array
{
$return = [];
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
$preferredRange = app('navigation')->preferredRangeFormat($start, $end);
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
$preferredRange = Navigation::preferredRangeFormat($start, $end);
$currentStart = clone $start;
while ($currentStart <= $end) {
$currentEnd = app('navigation')->endOfPeriod($currentStart, $preferredRange);
$currentEnd = Navigation::endOfPeriod($currentStart, $preferredRange);
$key = $currentStart->isoFormat($format);
$return[$key] = '0';
$currentStart = clone $currentEnd;

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Chart;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
use FireflyIII\Http\Controllers\Controller;
@@ -154,7 +155,7 @@ class DoubleReportController extends Controller
$accounts = $accounts->merge($opposing);
$spent = $this->opsRepository->listExpenses($start, $end, $accounts);
$earned = $this->opsRepository->listIncome($start, $end, $accounts);
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
// loop expenses.
foreach ($spent as $currency) {
@@ -238,11 +239,11 @@ class DoubleReportController extends Controller
private function makeEntries(Carbon $start, Carbon $end): array
{
$return = [];
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
$preferredRange = app('navigation')->preferredRangeFormat($start, $end);
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
$preferredRange = Navigation::preferredRangeFormat($start, $end);
$currentStart = clone $start;
while ($currentStart <= $end) {
$currentEnd = app('navigation')->endOfPeriod($currentStart, $preferredRange);
$currentEnd = Navigation::endOfPeriod($currentStart, $preferredRange);
$key = $currentStart->isoFormat($format);
$return[$key] = '0';
$currentStart = clone $currentEnd;

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Chart;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
use FireflyIII\Http\Controllers\Controller;
@@ -83,8 +84,8 @@ class ExpenseReportController extends Controller
return response()->json($cache->get());
}
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
$function = app('navigation')->preferredEndOfPeriod($start, $end);
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
$function = Navigation::preferredEndOfPeriod($start, $end);
$chartData = [];
$currentStart = clone $start;
$combined = $this->combineAccounts($expense);

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Chart;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
use FireflyIII\Http\Controllers\Controller;
@@ -92,7 +93,7 @@ class PiggyBankController extends Controller
$currentSum = $filtered->sum('amount');
$label = $oldest->isoFormat((string) trans('config.month_and_day_js', [], $locale));
$chartData[$label] = $currentSum;
$oldest = app('navigation')->addPeriod($oldest, $step);
$oldest = Navigation::addPeriod($oldest, $step);
}
$finalFiltered = $set->filter(
static fn (PiggyBankEvent $event) => $event->date->lte($today)

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Chart;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
@@ -154,9 +155,9 @@ class ReportController extends Controller
Log::debug('Going to do operations for accounts ', $accounts->pluck('id')->toArray());
Log::debug(sprintf('Period: %s to %s', $start->toW3cString(), $end->toW3cString()));
$format = app('navigation')->preferredCarbonFormat($start, $end);
$titleFormat = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
$preferredRange = app('navigation')->preferredRangeFormat($start, $end);
$format = Navigation::preferredCarbonFormat($start, $end);
$titleFormat = Navigation::preferredCarbonLocalizedFormat($start, $end);
$preferredRange = Navigation::preferredRangeFormat($start, $end);
$ids = $accounts->pluck('id')->toArray();
$data = [];
$chartData = [];
@@ -242,7 +243,7 @@ class ReportController extends Controller
// #8374. Sloppy fix for yearly charts. Not really interested in a better fix with v2 layout and all.
if ('1Y' === $preferredRange) {
$currentEnd = app('navigation')->endOfPeriod($currentEnd, $preferredRange);
$currentEnd = Navigation::endOfPeriod($currentEnd, $preferredRange);
}
Log::debug('Start of sub-loop');
while ($currentStart <= $currentEnd) {
@@ -260,7 +261,7 @@ class ReportController extends Controller
$expense['entries'][$title] = '0';
}
$currentStart = app('navigation')->addPeriod($currentStart, $preferredRange);
$currentStart = Navigation::addPeriod($currentStart, $preferredRange);
}
Log::debug('End of sub-loop');

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Chart;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
use FireflyIII\Http\Controllers\Controller;
@@ -214,7 +215,7 @@ class TagReportController extends Controller
$chartData = [];
$spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection()->push($tag));
$earned = $this->opsRepository->listIncome($start, $end, $accounts, new Collection()->push($tag));
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
// loop expenses.
foreach ($spent as $currency) {
@@ -281,11 +282,11 @@ class TagReportController extends Controller
private function makeEntries(Carbon $start, Carbon $end): array
{
$return = [];
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
$preferredRange = app('navigation')->preferredRangeFormat($start, $end);
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
$preferredRange = Navigation::preferredRangeFormat($start, $end);
$currentStart = clone $start;
while ($currentStart <= $end) {
$currentEnd = app('navigation')->endOfPeriod($currentStart, $preferredRange);
$currentEnd = Navigation::endOfPeriod($currentStart, $preferredRange);
$key = $currentStart->isoFormat($format);
$return[$key] = '0';
$currentStart = clone $currentEnd;

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency;
@@ -101,7 +102,7 @@ class PreferencesController extends Controller
/** @var array<int, int> $accountIds */
$accountIds = $accounts->pluck('id')->toArray();
$viewRange = app('navigation')->getViewRange(false);
$viewRange = Navigation::getViewRange(false);
$frontpageAccountsPref = Preferences::get('frontpageAccounts', $accountIds);
$frontpageAccounts = $frontpageAccountsPref->data;
if (!is_array($frontpageAccounts)) {

View File

@@ -173,15 +173,15 @@ class EditController extends Controller
*/
public function update(RecurrenceFormRequest $request, Recurrence $recurrence)
{
$data = $request->getAll();
$this->repository->update($recurrence, $data);
$data = $request->getAll();
$recurrence = $this->repository->update($recurrence, $data);
$request->session()->flash('success', (string) trans('firefly.updated_recurrence', ['title' => $recurrence->title]));
Log::channel('audit')->info(sprintf('Updated recurrence #%d.', $recurrence->id), $data);
// store new attachment(s):
/** @var null|array $files */
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
if (null !== $files && !auth()->user()->hasRole('demo')) {
$this->attachments->saveAttachmentsForModel($recurrence, $files);
}
@@ -194,7 +194,7 @@ class EditController extends Controller
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments'));
}
app('preferences')->mark();
$redirect = redirect($this->getPreviousUrl('recurrences.edit.url'));
$redirect = redirect($this->getPreviousUrl('recurrences.edit.url'));
if (1 === (int) $request->get('return_to_edit')) {
// set value so edit routine will not overwrite URL:
$request->session()->put('recurrences.edit.fromUpdate', true);

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Report;
use FireflyIII\Support\Facades\Navigation;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
@@ -485,7 +486,7 @@ class CategoryController extends Controller
// depending on the carbon format (a reliable way to determine the general date difference)
// change the "listOfPeriods" call so the entire period gets included correctly.
$format = app('navigation')->preferredCarbonFormat($start, $end);
$format = Navigation::preferredCarbonFormat($start, $end);
if ('Y' === $format) {
$start->startOfYear();
@@ -494,7 +495,7 @@ class CategoryController extends Controller
$start->startOfMonth();
}
$periods = app('navigation')->listOfPeriods($start, $end);
$periods = Navigation::listOfPeriods($start, $end);
$data = [];
$with = $this->opsRepository->listExpenses($start, $end, $accounts);
$without = $this->noCatRepository->listExpenses($start, $end, $accounts);
@@ -559,7 +560,7 @@ class CategoryController extends Controller
// depending on the carbon format (a reliable way to determine the general date difference)
// change the "listOfPeriods" call so the entire period gets included correctly.
$format = app('navigation')->preferredCarbonFormat($start, $end);
$format = Navigation::preferredCarbonFormat($start, $end);
if ('Y' === $format) {
$start->startOfYear();
@@ -568,7 +569,7 @@ class CategoryController extends Controller
$start->startOfMonth();
}
$periods = app('navigation')->listOfPeriods($start, $end);
$periods = Navigation::listOfPeriods($start, $end);
$data = [];
$with = $this->opsRepository->listIncome($start, $end, $accounts);
$without = $this->noCatRepository->listIncome($start, $end, $accounts);

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Middleware;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use Closure;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
@@ -75,8 +76,8 @@ class Range
}
$today = today(config('app.timezone'));
$start = app('navigation')->updateStartDate((string) $viewRange, $today);
$end = app('navigation')->updateEndDate((string) $viewRange, $start);
$start = Navigation::updateStartDate((string) $viewRange, $today);
$end = Navigation::updateEndDate((string) $viewRange, $start);
app('session')->put('start', $start);
app('session')->put('end', $end);

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Jobs;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Enums\AutoBudgetType;
use FireflyIII\Exceptions\FireflyException;
@@ -122,8 +123,8 @@ class CreateAutoBudgetLimits implements ShouldQueue
);
// get date range for budget limit, based on range in auto-budget
$start = app('navigation')->startOfPeriod($this->date, $autoBudget->period);
$end = app('navigation')->endOfPeriod($start, $autoBudget->period);
$start = Navigation::startOfPeriod($this->date, $autoBudget->period);
$end = Navigation::endOfPeriod($start, $autoBudget->period);
// find budget limit:
$budgetLimit = $this->findBudgetLimit($autoBudget->budget, $start, $end);
@@ -237,12 +238,12 @@ class CreateAutoBudgetLimits implements ShouldQueue
{
Log::debug(sprintf('Will now manage rollover for auto budget #%d', $autoBudget->id));
// current period:
$start = app('navigation')->startOfPeriod($this->date, $autoBudget->period);
$end = app('navigation')->endOfPeriod($start, $autoBudget->period);
$start = Navigation::startOfPeriod($this->date, $autoBudget->period);
$end = Navigation::endOfPeriod($start, $autoBudget->period);
// which means previous period:
$previousStart = app('navigation')->subtractPeriod($start, $autoBudget->period);
$previousEnd = app('navigation')->endOfPeriod($previousStart, $autoBudget->period);
$previousStart = Navigation::subtractPeriod($start, $autoBudget->period);
$previousEnd = Navigation::endOfPeriod($previousStart, $autoBudget->period);
Log::debug(
sprintf(
@@ -297,12 +298,12 @@ class CreateAutoBudgetLimits implements ShouldQueue
{
Log::debug(sprintf('Will now manage rollover for auto budget #%d', $autoBudget->id));
// current period:
$start = app('navigation')->startOfPeriod($this->date, $autoBudget->period);
$end = app('navigation')->endOfPeriod($start, $autoBudget->period);
$start = Navigation::startOfPeriod($this->date, $autoBudget->period);
$end = Navigation::endOfPeriod($start, $autoBudget->period);
// which means previous period:
$previousStart = app('navigation')->subtractPeriod($start, $autoBudget->period);
$previousEnd = app('navigation')->endOfPeriod($previousStart, $autoBudget->period);
$previousStart = Navigation::subtractPeriod($start, $autoBudget->period);
$previousEnd = Navigation::endOfPeriod($previousStart, $autoBudget->period);
Log::debug(
sprintf(

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Bill;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\BillFactory;
@@ -463,11 +464,11 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
while ($start < $date) {
Log::debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d H:i:s'), $date->format('Y-m-d H:i:s')));
$start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
$start = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
Log::debug('Start is now '.$start->format('Y-m-d H:i:s'));
}
$end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
$end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
$end->endOfDay();
// see if the bill was paid in this period.
@@ -477,7 +478,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
// this period had in fact a bill. The new start is the current end, and we create a new end.
Log::debug(sprintf('Journal count is %d, so start becomes %s', $journalCount, $end->format('Y-m-d')));
$start = clone $end;
$end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
$end = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
}
Log::debug('nextExpectedMatch: Final start is '.$start->format('Y-m-d'));
Log::debug('nextExpectedMatch: Matching end is '.$end->format('Y-m-d'));
@@ -681,7 +682,7 @@ class BillRepository implements BillRepositoryInterface, UserGroupInterface
$start = clone $bill->date;
while ($start < $date) {
$start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip);
$start = Navigation::addPeriod($start, $bill->repeat_freq, $bill->skip);
}
$cache->store($start);

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Budget;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Enums\AutoBudgetType;
use FireflyIII\Enums\TransactionTypeEnum;
@@ -790,8 +791,8 @@ class BudgetRepository implements BudgetRepositoryInterface, UserGroupInterface
// create initial budget limit.
$today = today(config('app.timezone'));
$start = app('navigation')->startOfPeriod($today, $autoBudget->period);
$end = app('navigation')->endOfPeriod($start, $autoBudget->period);
$start = Navigation::startOfPeriod($today, $autoBudget->period);
$end = Navigation::endOfPeriod($start, $autoBudget->period);
$limitRepos = app(BudgetLimitRepositoryInterface::class);
$limitRepos->setUser($this->user);

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Budget;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
@@ -45,7 +46,7 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface, UserGroupInterf
#[Deprecated]
public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array
{
$carbonFormat = app('navigation')->preferredCarbonFormat($start, $end);
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Budget;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use Deprecated;
use FireflyIII\Enums\TransactionTypeEnum;
@@ -82,7 +83,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
#[Deprecated]
public function getBudgetPeriodReport(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array
{
$carbonFormat = app('navigation')->preferredCarbonFormat($start, $end);
$carbonFormat = Navigation::preferredCarbonFormat($start, $end);
$data = [];
// get all transactions:

View File

@@ -76,7 +76,6 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
*/
public function firstNull(): ?TransactionJournal
{
/** @var null|TransactionJournal $entry */
return $this->user->transactionJournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']);
}
@@ -113,7 +112,6 @@ class JournalRepository implements JournalRepositoryInterface, UserGroupInterfac
public function getLast(): ?TransactionJournal
{
/** @var null|TransactionJournal $entry */
return $this->user->transactionJournals()->orderBy('date', 'DESC')->first(['transaction_journals.*']);
}

View File

@@ -48,7 +48,7 @@ class IsValidAccountTypeList implements ValidationRule
$keys = array_keys($this->types);
foreach ($values as $entry) {
if (!in_array($entry, $keys, true)) {
$fail('validation.invalid_account_list')->translate();
$fail('validation.invalid_account_list')->translate(['value' => $entry]);
}
}
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Support\Chart\Category;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Models\Category;
@@ -59,10 +60,10 @@ class WholePeriodChartGenerator
while ($current <= $end) {
$key = $current->format('Y-m-d');
$currentEnd = app('navigation')->endOfPeriod($current, $step);
$currentEnd = Navigation::endOfPeriod($current, $step);
$spent[$key] = $opsRepository->sumExpenses($current, $currentEnd, $accounts, $collection);
$earned[$key] = $opsRepository->sumIncome($current, $currentEnd, $accounts, $collection);
$current = app('navigation')->addPeriod($current, $step);
$current = Navigation::addPeriod($current, $step);
}
$currencies = $this->extractCurrencies($spent) + $this->extractCurrencies($earned);
@@ -91,7 +92,7 @@ class WholePeriodChartGenerator
while ($current <= $end) {
$key = $current->format('Y-m-d');
$label = app('navigation')->periodShow($current, $step);
$label = Navigation::periodShow($current, $step);
/** @var array $currency */
foreach ($currencies as $currency) {
@@ -104,7 +105,7 @@ class WholePeriodChartGenerator
$chartData[$spentInfoKey]['entries'][$label] = app('steam')->bcround($spentAmount, $currency['currency_decimal_places']);
$chartData[$earnedInfoKey]['entries'][$label] = app('steam')->bcround($earnedAmount, $currency['currency_decimal_places']);
}
$current = app('navigation')->addPeriod($current, $step);
$current = Navigation::addPeriod($current, $step);
}
return $chartData;

View File

@@ -33,7 +33,7 @@ trait AccountFilter
{
protected array $types
= [
'all' => [
'all' => [
AccountTypeEnum::DEFAULT->value,
AccountTypeEnum::CASH->value,
AccountTypeEnum::ASSET->value,
@@ -47,41 +47,50 @@ trait AccountFilter
AccountTypeEnum::DEBT->value,
AccountTypeEnum::MORTGAGE->value,
],
'asset' => [AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value],
'cash' => [AccountTypeEnum::CASH->value],
'expense' => [AccountTypeEnum::EXPENSE->value, AccountTypeEnum::BENEFICIARY->value],
'revenue' => [AccountTypeEnum::REVENUE->value],
'special' => [AccountTypeEnum::CASH->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::RECONCILIATION->value],
'hidden' => [AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::RECONCILIATION->value],
'liability' => [AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::CREDITCARD->value],
'liabilities' => [AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::CREDITCARD->value],
AccountTypeEnum::DEFAULT->value => [AccountTypeEnum::DEFAULT->value],
AccountTypeEnum::CASH->value => [AccountTypeEnum::CASH->value],
AccountTypeEnum::ASSET->value => [AccountTypeEnum::ASSET->value],
AccountTypeEnum::EXPENSE->value => [AccountTypeEnum::EXPENSE->value],
AccountTypeEnum::REVENUE->value => [AccountTypeEnum::REVENUE->value],
AccountTypeEnum::INITIAL_BALANCE->value => [AccountTypeEnum::INITIAL_BALANCE->value],
AccountTypeEnum::BENEFICIARY->value => [AccountTypeEnum::BENEFICIARY->value],
AccountTypeEnum::IMPORT->value => [AccountTypeEnum::IMPORT->value],
AccountTypeEnum::RECONCILIATION->value => [AccountTypeEnum::RECONCILIATION->value],
AccountTypeEnum::LOAN->value => [AccountTypeEnum::LOAN->value],
AccountTypeEnum::MORTGAGE->value => [AccountTypeEnum::MORTGAGE->value],
AccountTypeEnum::DEBT->value => [AccountTypeEnum::DEBT->value],
AccountTypeEnum::CREDITCARD->value => [AccountTypeEnum::CREDITCARD->value],
'default account' => [AccountTypeEnum::DEFAULT->value],
'cash account' => [AccountTypeEnum::CASH->value],
'asset account' => [AccountTypeEnum::ASSET->value],
'expense account' => [AccountTypeEnum::EXPENSE->value],
'revenue account' => [AccountTypeEnum::REVENUE->value],
'initial balance account' => [AccountTypeEnum::INITIAL_BALANCE->value],
'reconciliation' => [AccountTypeEnum::RECONCILIATION->value],
'loan' => [AccountTypeEnum::LOAN->value],
'mortgage' => [AccountTypeEnum::MORTGAGE->value],
'debt' => [AccountTypeEnum::DEBT->value],
'credit card' => [AccountTypeEnum::CREDITCARD->value],
'credit-card' => [AccountTypeEnum::CREDITCARD->value],
'creditcard' => [AccountTypeEnum::CREDITCARD->value],
'cc' => [AccountTypeEnum::CREDITCARD->value],
'normal' => [
AccountTypeEnum::ASSET->value,
AccountTypeEnum::EXPENSE->value,
AccountTypeEnum::REVENUE->value,
AccountTypeEnum::LOAN->value,
AccountTypeEnum::DEBT->value,
AccountTypeEnum::MORTGAGE->value,
],
'asset' => [AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value],
'cash' => [AccountTypeEnum::CASH->value],
'expense' => [AccountTypeEnum::EXPENSE->value, AccountTypeEnum::BENEFICIARY->value],
'revenue' => [AccountTypeEnum::REVENUE->value],
'special' => [AccountTypeEnum::CASH->value, AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::RECONCILIATION->value],
'hidden' => [AccountTypeEnum::INITIAL_BALANCE->value, AccountTypeEnum::IMPORT->value, AccountTypeEnum::RECONCILIATION->value],
'liability' => [AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::CREDITCARD->value],
'liabilities' => [AccountTypeEnum::DEBT->value, AccountTypeEnum::LOAN->value, AccountTypeEnum::MORTGAGE->value, AccountTypeEnum::CREDITCARD->value],
AccountTypeEnum::DEFAULT->value => [AccountTypeEnum::DEFAULT->value],
AccountTypeEnum::CASH->value => [AccountTypeEnum::CASH->value],
AccountTypeEnum::ASSET->value => [AccountTypeEnum::ASSET->value],
AccountTypeEnum::EXPENSE->value => [AccountTypeEnum::EXPENSE->value],
AccountTypeEnum::REVENUE->value => [AccountTypeEnum::REVENUE->value],
AccountTypeEnum::INITIAL_BALANCE->value => [AccountTypeEnum::INITIAL_BALANCE->value],
AccountTypeEnum::BENEFICIARY->value => [AccountTypeEnum::BENEFICIARY->value],
AccountTypeEnum::IMPORT->value => [AccountTypeEnum::IMPORT->value],
AccountTypeEnum::RECONCILIATION->value => [AccountTypeEnum::RECONCILIATION->value],
AccountTypeEnum::LOAN->value => [AccountTypeEnum::LOAN->value],
AccountTypeEnum::MORTGAGE->value => [AccountTypeEnum::MORTGAGE->value],
AccountTypeEnum::DEBT->value => [AccountTypeEnum::DEBT->value],
AccountTypeEnum::CREDITCARD->value => [AccountTypeEnum::CREDITCARD->value],
AccountTypeEnum::LIABILITY_CREDIT->value => [AccountTypeEnum::LIABILITY_CREDIT->value],
'default account' => [AccountTypeEnum::DEFAULT->value],
'cash account' => [AccountTypeEnum::CASH->value],
'asset account' => [AccountTypeEnum::ASSET->value],
'expense account' => [AccountTypeEnum::EXPENSE->value],
'revenue account' => [AccountTypeEnum::REVENUE->value],
'initial balance account' => [AccountTypeEnum::INITIAL_BALANCE->value],
'reconciliation' => [AccountTypeEnum::RECONCILIATION->value],
'loan' => [AccountTypeEnum::LOAN->value],
'mortgage' => [AccountTypeEnum::MORTGAGE->value],
'debt' => [AccountTypeEnum::DEBT->value],
'credit card' => [AccountTypeEnum::CREDITCARD->value],
'credit-card' => [AccountTypeEnum::CREDITCARD->value],
'creditcard' => [AccountTypeEnum::CREDITCARD->value],
'cc' => [AccountTypeEnum::CREDITCARD->value],
];
/**
@@ -89,6 +98,18 @@ trait AccountFilter
*/
protected function mapAccountTypes(string $type): array
{
return $this->types[$type] ?? $this->types['all'];
$return = [];
$parts = explode(',', $type);
foreach ($parts as $part) {
if (array_key_exists($part, $this->types)) {
$return = array_merge($return, $this->types[$part]);
}
}
if (0 === count($return)) {
return $this->types['normal'];
}
return $return;
}
}

View File

@@ -74,6 +74,9 @@ trait TransactionFilter
$return = array_merge($return, $this->transactionTypes[$part]);
}
}
if (0 === count($return)) {
$return = $this->transactionTypes['all'];
}
return array_unique($return);
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Support\Http\Controllers;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
/**
@@ -93,18 +94,18 @@ trait DateCalculation
$loop = [];
/** @var Carbon $current */
$current = app('navigation')->startOfPeriod($date, $range);
$current = app('navigation')->endOfPeriod($current, $range);
$current = Navigation::startOfPeriod($date, $range);
$current = Navigation::endOfPeriod($current, $range);
$current->addDay();
$count = 0;
while ($count < 12) {
$current = app('navigation')->endOfPeriod($current, $range);
$currentStart = app('navigation')->startOfPeriod($current, $range);
$current = Navigation::endOfPeriod($current, $range);
$currentStart = Navigation::startOfPeriod($current, $range);
$loop[] = [
'label' => $current->format('Y-m-d'),
'title' => app('navigation')->periodShow($current, $range),
'title' => Navigation::periodShow($current, $range),
'start' => clone $currentStart,
'end' => clone $current,
];
@@ -125,15 +126,15 @@ trait DateCalculation
$loop = [];
/** @var Carbon $current */
$current = app('navigation')->startOfPeriod($date, $range);
$current = Navigation::startOfPeriod($date, $range);
$count = 0;
while ($count < 12) {
$current->subDay();
$current = app('navigation')->startOfPeriod($current, $range);
$currentEnd = app('navigation')->endOfPeriod($current, $range);
$current = Navigation::startOfPeriod($current, $range);
$currentEnd = Navigation::endOfPeriod($current, $range);
$loop[] = [
'label' => $current->format('Y-m-d'),
'title' => app('navigation')->periodShow($current, $range),
'title' => Navigation::periodShow($current, $range),
'start' => clone $current,
'end' => clone $currentEnd,
];

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Support\Http\Controllers;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Support\Facades\FireflyConfig;
@@ -82,7 +83,7 @@ trait GetConfigurationData
*/
protected function getDateRangeConfig(): array // get configuration + get preferences.
{
$viewRange = app('navigation')->getViewRange(false);
$viewRange = Navigation::getViewRange(false);
Log::debug(sprintf('dateRange: the view range is "%s"', $viewRange));
@@ -105,32 +106,32 @@ trait GetConfigurationData
// when current range is a custom range, add the current period as the next range.
if ($isCustom) {
$index = app('navigation')->periodShow($start, $viewRange);
$customPeriodStart = app('navigation')->startOfPeriod($start, $viewRange);
$customPeriodEnd = app('navigation')->endOfPeriod($customPeriodStart, $viewRange);
$index = Navigation::periodShow($start, $viewRange);
$customPeriodStart = Navigation::startOfPeriod($start, $viewRange);
$customPeriodEnd = Navigation::endOfPeriod($customPeriodStart, $viewRange);
$ranges[$index] = [$customPeriodStart, $customPeriodEnd];
}
// then add previous range and next range, but skip this for the lastX and YTD stuff.
if (!in_array($viewRange, config('firefly.dynamic_date_ranges', []), true)) {
$previousDate = app('navigation')->subtractPeriod($start, $viewRange);
$index = app('navigation')->periodShow($previousDate, $viewRange);
$previousStart = app('navigation')->startOfPeriod($previousDate, $viewRange);
$previousEnd = app('navigation')->endOfPeriod($previousStart, $viewRange);
$previousDate = Navigation::subtractPeriod($start, $viewRange);
$index = Navigation::periodShow($previousDate, $viewRange);
$previousStart = Navigation::startOfPeriod($previousDate, $viewRange);
$previousEnd = Navigation::endOfPeriod($previousStart, $viewRange);
$ranges[$index] = [$previousStart, $previousEnd];
$nextDate = app('navigation')->addPeriod($start, $viewRange);
$index = app('navigation')->periodShow($nextDate, $viewRange);
$nextStart = app('navigation')->startOfPeriod($nextDate, $viewRange);
$nextEnd = app('navigation')->endOfPeriod($nextStart, $viewRange);
$nextDate = Navigation::addPeriod($start, $viewRange);
$index = Navigation::periodShow($nextDate, $viewRange);
$nextStart = Navigation::startOfPeriod($nextDate, $viewRange);
$nextEnd = Navigation::endOfPeriod($nextStart, $viewRange);
$ranges[$index] = [$nextStart, $nextEnd];
}
// today:
/** @var Carbon $todayStart */
$todayStart = app('navigation')->startOfPeriod($today, $viewRange);
$todayStart = Navigation::startOfPeriod($today, $viewRange);
/** @var Carbon $todayEnd */
$todayEnd = app('navigation')->endOfPeriod($todayStart, $viewRange);
$todayEnd = Navigation::endOfPeriod($todayStart, $viewRange);
if ($todayStart->ne($start) || $todayEnd->ne($end)) {
$ranges[ucfirst((string)trans('firefly.today'))] = [$todayStart, $todayEnd];

View File

@@ -56,23 +56,23 @@ use function Safe\json_decode;
class RecurringEnrichment implements EnrichmentInterface
{
private array $accounts = [];
private array $accounts = [];
private Collection $collection;
// private array $transactionTypeIds = [];
// private array $transactionTypes = [];
private readonly bool $convertToPrimary;
private array $currencies = [];
private array $currencyIds = [];
private array $destinationAccountIds = [];
private array $foreignCurrencyIds = [];
private array $ids = [];
private string $language = 'en_US';
private array $notes = [];
private readonly bool $convertToPrimary;
private array $currencies = [];
private array $currencyIds = [];
private array $destinationAccountIds = [];
private array $foreignCurrencyIds = [];
private array $ids = [];
private string $language = 'en_US';
private array $notes = [];
private readonly TransactionCurrency $primaryCurrency;
private array $recurrenceIds = [];
private array $repetitions = [];
private array $sourceAccountIds = [];
private array $transactions = [];
private array $recurrenceByTransaction = [];
private array $repetitions = [];
private array $sourceAccountIds = [];
private array $transactions = [];
private User $user;
private UserGroup $userGroup;
@@ -84,6 +84,7 @@ class RecurringEnrichment implements EnrichmentInterface
public function enrich(Collection $collection): Collection
{
Log::debug(__METHOD__);
$this->collection = $collection;
$this->collectIds();
$this->collectRepetitions();
@@ -194,6 +195,7 @@ class RecurringEnrichment implements EnrichmentInterface
foreach ($accounts as $account) {
$id = (int)$account->id;
$this->accounts[$id] = $account;
Log::debug(sprintf('Collected account #%d', $id));
}
}
@@ -279,6 +281,7 @@ class RecurringEnrichment implements EnrichmentInterface
foreach ($currencies as $currency) {
$id = (int)$currency->id;
$this->currencies[$id] = $currency;
Log::debug(sprintf('Collected currency #%d', $id));
}
}
@@ -287,18 +290,11 @@ class RecurringEnrichment implements EnrichmentInterface
/** @var Recurrence $recurrence */
foreach ($this->collection as $recurrence) {
$id = (int)$recurrence->id;
// $typeId = (int)$recurrence->transaction_type_id;
$this->ids[] = $id;
// $this->transactionTypeIds[$id] = $typeId;
Log::debug(sprintf('Collected recurrence id #%d', $id));
}
$this->ids = array_unique($this->ids);
// collect transaction types.
// $transactionTypes = TransactionType::whereIn('id', array_unique($this->transactionTypeIds))->get();
// foreach ($transactionTypes as $transactionType) {
// $id = (int)$transactionType->id;
// $this->transactionTypes[$id] = TransactionTypeEnum::from($transactionType->type);
// }
Log::debug('Final array:', $this->ids);
}
private function collectNotes(): void
@@ -306,10 +302,12 @@ class RecurringEnrichment implements EnrichmentInterface
$notes = Note::query()->whereIn('noteable_id', $this->ids)
->whereNotNull('notes.text')
->where('notes.text', '!=', '')
->where('noteable_type', Recurrence::class)->get(['notes.noteable_id', 'notes.text'])->toArray()
->where('noteable_type', Recurrence::class)->get(['notes.id', 'notes.noteable_id', 'notes.text'])->toArray()
;
foreach ($notes as $note) {
$this->notes[(int)$note['noteable_id']] = (string)$note['text'];
$notableId = (int)$note['noteable_id'];
$this->notes[$notableId] = (string)$note['text'];
Log::debug(sprintf('Collected note #%d for recurrence #%d', $note['id'], $notableId));
}
Log::debug(sprintf('Enrich with %d note(s)', count($this->notes)));
}
@@ -341,22 +339,23 @@ class RecurringEnrichment implements EnrichmentInterface
/** @var RecurrenceRepetition $repetition */
foreach ($set as $repetition) {
$recurrence = $this->collection->filter(fn (Recurrence $item): bool => (int)$item->id === (int)$repetition->recurrence_id)->first();
$fromDate = clone ($recurrence->latest_date ?? $recurrence->first_date);
$id = (int)$repetition->recurrence_id;
$repId = (int)$repetition->id;
$this->repetitions[$id] ??= [];
$recurrence = $this->collection->filter(fn (Recurrence $item): bool => (int)$item->id === (int)$repetition->recurrence_id)->first();
$fromDate = clone ($recurrence->latest_date ?? $recurrence->first_date);
$recurrenceId = (int)$repetition->recurrence_id;
$repId = (int)$repetition->id;
$this->repetitions[$recurrenceId] ??= [];
Log::debug(sprintf('Collected repetition #%d of recurrence #%d.', $repId, $recurrenceId));
// get the (future) occurrences for this specific type of repetition:
$amount = 'daily' === $repetition->repetition_type ? 9 : 5;
$set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount);
$occurrences = [];
$amount = 'daily' === $repetition->repetition_type ? 9 : 5;
$set = $repository->getXOccurrencesSince($repetition, $fromDate, now(config('app.timezone')), $amount);
$occurrences = [];
/** @var Carbon $carbon */
foreach ($set as $carbon) {
$occurrences[] = $carbon->toAtomString();
}
$this->repetitions[$id][$repId] = [
$this->repetitions[$recurrenceId][$repId] = [
'id' => (string)$repId,
'created_at' => $repetition->created_at->toAtomString(),
'updated_at' => $repetition->updated_at->toAtomString(),
@@ -373,8 +372,11 @@ class RecurringEnrichment implements EnrichmentInterface
private function collectTransactionMetaData(): void
{
$ids = array_keys($this->transactions);
$meta = RecurrenceTransactionMeta::whereNull('deleted_at')->whereIn('rt_id', $ids)->get();
$rtIds = [];
foreach ($this->ids as $recurrenceId) {
$rtIds = array_merge($rtIds, array_keys($this->transactions[$recurrenceId]));
}
$meta = RecurrenceTransactionMeta::whereNull('deleted_at')->whereIn('rt_id', $rtIds)->get();
// other meta-data to be collected:
$billIds = [];
$piggyBankIds = [];
@@ -386,10 +388,11 @@ class RecurringEnrichment implements EnrichmentInterface
$transactionId = (int)$entry->rt_id;
// this should refer to another array, were rtIds can be used to find the recurrence.
$recurrenceId = $this->recurrenceIds[$transactionId] ?? 0;
$recurrenceId = $this->recurrenceByTransaction[$transactionId] ?? 0;
Log::debug(sprintf('Collecting meta data entry #%d for recurrence transaction #%d, for recurrence #%d ', $id, $transactionId, $recurrenceId));
$name = (string)($entry->name ?? '');
if (0 === $recurrenceId) {
Log::error(sprintf('Could not find recurrence ID for recurrence transaction ID %d', $transactionId));
Log::error(sprintf('Could not find recurrence ID for recurrence transaction ID #%d', $transactionId));
continue;
}
@@ -487,16 +490,16 @@ class RecurringEnrichment implements EnrichmentInterface
/** @var RecurrenceTransaction $transaction */
foreach ($set as $transaction) {
$id = (int)$transaction->recurrence_id;
$transactionId = (int)$transaction->id;
$this->recurrenceIds[$transactionId] = $id;
$this->transactions[$id] ??= [];
$amount = $transaction->amount;
$foreignAmount = $transaction->foreign_amount;
$recurrenceId = (int)$transaction->recurrence_id;
$transactionId = (int)$transaction->id;
$this->recurrenceByTransaction[$transactionId] = $recurrenceId;
$this->transactions[$recurrenceId] ??= [];
$amount = $transaction->amount;
$foreignAmount = $transaction->foreign_amount;
Log::debug(sprintf('Collected transaction #%d of recurrence #%d', $transactionId, $recurrenceId));
$this->transactions[$id][$transactionId] = [
$this->transactions[$recurrenceId][$transactionId] = [
'id' => (string)$transactionId,
// 'recurrence_id' => $id,
'transaction_currency_id' => (int)$transaction->transaction_currency_id,
'foreign_currency_id' => null === $transaction->foreign_currency_id ? null : (int)$transaction->foreign_currency_id,
'source_id' => (int)$transaction->source_id,
@@ -518,10 +521,10 @@ class RecurringEnrichment implements EnrichmentInterface
'subscription_name' => null,
];
// collect all kinds of meta data to be collected later.
$this->currencyIds[$transactionId] = (int)$transaction->transaction_currency_id;
$this->sourceAccountIds[$transactionId] = (int)$transaction->source_id;
$this->destinationAccountIds[$transactionId] = (int)$transaction->destination_id;
// collect all kinds of meta-data to be collected later.
$this->currencyIds[$transactionId] = (int)$transaction->transaction_currency_id;
$this->sourceAccountIds[$transactionId] = (int)$transaction->source_id;
$this->destinationAccountIds[$transactionId] = (int)$transaction->destination_id;
if (null !== $transaction->foreign_currency_id) {
$this->foreignCurrencyIds[$transactionId] = (int)$transaction->foreign_currency_id;
}

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Support\Models;
use FireflyIII\Support\Facades\Navigation;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
@@ -49,7 +50,7 @@ class BillDateCalculator
Log::debug(sprintf('Dates must be between %s and %s.', $earliest->format('Y-m-d'), $latest->format('Y-m-d')));
Log::debug(sprintf('Bill started on %s, period is "%s", skip is %d, last paid = "%s".', $billStart->format('Y-m-d'), $period, $skip, $lastPaid?->format('Y-m-d')));
$daysUntilEOM = app('navigation')->daysUntilEndOfMonth($billStart);
$daysUntilEOM = Navigation::daysUntilEndOfMonth($billStart);
Log::debug(sprintf('For bill start, days until end of month is %d', $daysUntilEOM));
$set = new Collection();
@@ -94,7 +95,7 @@ class BillDateCalculator
// the next expected month because that month has only 28 days (i.e. february).
// this applies to leap years as well.
if ($daysUntilEOM < 4) {
$nextUntilEOM = app('navigation')->daysUntilEndOfMonth($nextExpectedMatch);
$nextUntilEOM = Navigation::daysUntilEndOfMonth($nextExpectedMatch);
$diffEOM = $daysUntilEOM - $nextUntilEOM;
if ($diffEOM > 0) {
Log::debug(sprintf('Bill start is %d days from the end of the month. nextExceptedMatch is %d days from the end of the month.', $daysUntilEOM, $nextUntilEOM));
@@ -140,7 +141,7 @@ class BillDateCalculator
return $billStartDate;
}
$steps = app('navigation')->diffInPeriods($period, $skip, $earliest, $billStartDate);
$steps = Navigation::diffInPeriods($period, $skip, $earliest, $billStartDate);
if ($steps === $this->diffInMonths) {
Log::debug(sprintf('Steps is %d, which is the same as diffInMonths (%d), so we add another 1.', $steps, $this->diffInMonths));
++$steps;
@@ -150,7 +151,7 @@ class BillDateCalculator
if ($steps > 0) {
--$steps;
Log::debug(sprintf('Steps is %d, because addPeriod already adds 1.', $steps));
$result = app('navigation')->addPeriod($billStartDate, $period, $steps);
$result = Navigation::addPeriod($billStartDate, $period, $steps);
}
Log::debug(sprintf('Number of steps is %d, added to %s, result is %s', $steps, $billStartDate->format('Y-m-d'), $result->format('Y-m-d')));

View File

@@ -121,8 +121,8 @@ class Navigation
if ($workEnd->gt($start)) {
while ($workEnd->gt($start) && $loopCount < 20) {
// make range:
$workStart = app('navigation')->startOfPeriod($workStart, '1Y');
$workEnd = app('navigation')->endOfPeriod($workStart, '1Y');
$workStart = Facades\Navigation::startOfPeriod($workStart, '1Y');
$workEnd = Facades\Navigation::endOfPeriod($workStart, '1Y');
// make sure we don't go overboard
if ($workEnd->gt($start)) {

View File

@@ -29,11 +29,13 @@ use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Support\Facades\Navigation;
use FireflyIII\User;
use Illuminate\Support\Facades\Log;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
use Spatie\Period\Boundaries;
use Spatie\Period\Exceptions\InvalidPeriod;
use Spatie\Period\Period;
use Spatie\Period\Precision;
@@ -171,9 +173,16 @@ trait RecalculatesAvailableBudgetsTrait
}
$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);
$start = Navigation::startOfPeriod($budgetLimit->start_date, $viewRange);
$end = Navigation::startOfPeriod($budgetLimit->end_date, $viewRange);
$end = Navigation::endOfPeriod($end, $viewRange);
if ($end < $start) {
[$start, $end] = [$end, $start];
$budgetLimit->start_date = $start;
$budgetLimit->end_date = $end;
$budgetLimit->saveQuietly();
}
// limit period in total is:
$limitPeriod = Period::make($start, $end, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE());
@@ -182,7 +191,7 @@ trait RecalculatesAvailableBudgetsTrait
// 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);
$currentEnd = Navigation::endOfPeriod($current, $viewRange);
// create or find AB for this particular period, and set the amount accordingly.
/** @var null|AvailableBudget $availableBudget */
@@ -194,10 +203,18 @@ trait RecalculatesAvailableBudgetsTrait
}
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((string) $daily, (string)$currentPeriod->length(), 12);
try {
$currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE());
} catch (InvalidPeriod $e) {
Log::error('Tried to make invalid period.');
Log::error($e->getMessage());
continue;
}
$daily = $this->getDailyAmount($budgetLimit);
$amount = bcmul((string)$daily, (string)$currentPeriod->length(), 12);
// no need to calculate if period is equal.
if ($currentPeriod->equals($limitPeriod)) {
@@ -227,7 +244,7 @@ trait RecalculatesAvailableBudgetsTrait
}
// prep for next loop
$current = app('navigation')->addPeriod($current, $viewRange);
$current = Navigation::addPeriod($current, $viewRange);
}
}
}

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\TransactionRules\Actions;
use FireflyIII\Enums\TransactionTypeEnum;
use Illuminate\Support\Facades\Log;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\TriggeredAuditLog;
@@ -54,6 +55,13 @@ class AddTag implements ActionInterface
$tagName = $this->action->getValue($journal);
$tag = $factory->findOrCreate($tagName);
$type = $journal['transaction_type_type'];
if (TransactionTypeEnum::OPENING_BALANCE->value === $type || TransactionTypeEnum::LIABILITY_CREDIT->value === $type || TransactionTypeEnum::INVALID->value === $type) {
// fail silently on invalid transaction types.
return false;
}
if (null === $tag) {
// could not find, could not create tag.
event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.find_or_create_tag_failed', ['tag' => $tagName])));
@@ -61,11 +69,7 @@ class AddTag implements ActionInterface
return false;
}
$count = DB::table('tag_transaction_journal')
->where('tag_id', $tag->id)
->where('transaction_journal_id', $journal['transaction_journal_id'])
->count()
;
$count = DB::table('tag_transaction_journal')->where('tag_id', $tag->id)->where('transaction_journal_id', $journal['transaction_journal_id'])->count();
if (0 === $count) {
// add to journal:
DB::table('tag_transaction_journal')->insert(['tag_id' => $tag->id, 'transaction_journal_id' => $journal['transaction_journal_id']]);

View File

@@ -3,7 +3,30 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## 6.4.6 - 2025-11-09
## 6.4.9 - 2025-11-xx
### Fixed
- [Discussion 11211](https://github.com/orgs/firefly-iii/discussions/11211) (question about Transaction journal ID) started by @zhiiwg
- [Issue 11267](https://github.com/firefly-iii/firefly-iii/issues/11267) (Tags can be added to elements that can't be removed) reported by @Fmstrat
### API
- [Issue 11265](https://github.com/firefly-iii/firefly-iii/issues/11265) (Inconsistent object type in exchange rates API) reported by @jfpedroza
## 6.4.8 - 2025-11-14
### Fixed
- [Issue 11228](https://github.com/firefly-iii/firefly-iii/issues/11228) (Autocomplete fails when the requested account type list includes hidden account types) reported by @jgmm81
## 6.4.7
### Fixed
- [Issue 11206](https://github.com/firefly-iii/firefly-iii/issues/11206) (New transaction shows additional option in input) reported by @zhiiwg
## 6.4.6 - 2025-11-13
### Fixed

361
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -78,8 +78,8 @@ return [
'running_balance_column' => env('USE_RUNNING_BALANCE', false),
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2025-11-10',
'build_time' => 1762745365,
'version' => 'develop/2025-11-26',
'build_time' => 1764136346,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.

350
package-lock.json generated
View File

@@ -2589,9 +2589,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.1.tgz",
"integrity": "sha512-bxZtughE4VNVJlL1RdoSE545kc4JxL7op57KKoi59/gwuU5rV6jLWFXXc8jwgFoT6vtj+ZjO+Z2C5nrY0Cl6wA==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz",
"integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==",
"cpu": [
"arm"
],
@@ -2603,9 +2603,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.1.tgz",
"integrity": "sha512-44a1hreb02cAAfAKmZfXVercPFaDjqXCK+iKeVOlJ9ltvnO6QqsBHgKVPTu+MJHSLLeMEUbeG2qiDYgbFPU48g==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz",
"integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==",
"cpu": [
"arm64"
],
@@ -2617,9 +2617,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.1.tgz",
"integrity": "sha512-usmzIgD0rf1syoOZ2WZvy8YpXK5G1V3btm3QZddoGSa6mOgfXWkkv+642bfUUldomgrbiLQGrPryb7DXLovPWQ==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz",
"integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==",
"cpu": [
"arm64"
],
@@ -2631,9 +2631,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.1.tgz",
"integrity": "sha512-is3r/k4vig2Gt8mKtTlzzyaSQ+hd87kDxiN3uDSDwggJLUV56Umli6OoL+/YZa/KvtdrdyNfMKHzL/P4siOOmg==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz",
"integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==",
"cpu": [
"x64"
],
@@ -2645,9 +2645,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-arm64": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.1.tgz",
"integrity": "sha512-QJ1ksgp/bDJkZB4daldVmHaEQkG4r8PUXitCOC2WRmRaSaHx5RwPoI3DHVfXKwDkB+Sk6auFI/+JHacTekPRSw==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz",
"integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==",
"cpu": [
"arm64"
],
@@ -2659,9 +2659,9 @@
]
},
"node_modules/@rollup/rollup-freebsd-x64": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.1.tgz",
"integrity": "sha512-J6ma5xgAzvqsnU6a0+jgGX/gvoGokqpkx6zY4cWizRrm0ffhHDpJKQgC8dtDb3+MqfZDIqs64REbfHDMzxLMqQ==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz",
"integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==",
"cpu": [
"x64"
],
@@ -2673,9 +2673,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.1.tgz",
"integrity": "sha512-JzWRR41o2U3/KMNKRuZNsDUAcAVUYhsPuMlx5RUldw0E4lvSIXFUwejtYz1HJXohUmqs/M6BBJAUBzKXZVddbg==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz",
"integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==",
"cpu": [
"arm"
],
@@ -2687,9 +2687,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.1.tgz",
"integrity": "sha512-L8kRIrnfMrEoHLHtHn+4uYA52fiLDEDyezgxZtGUTiII/yb04Krq+vk3P2Try+Vya9LeCE9ZHU8CXD6J9EhzHQ==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz",
"integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==",
"cpu": [
"arm"
],
@@ -2701,9 +2701,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.1.tgz",
"integrity": "sha512-ysAc0MFRV+WtQ8li8hi3EoFi7us6d1UzaS/+Dp7FYZfg3NdDljGMoVyiIp6Ucz7uhlYDBZ/zt6XI0YEZbUO11Q==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz",
"integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==",
"cpu": [
"arm64"
],
@@ -2715,9 +2715,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.1.tgz",
"integrity": "sha512-UV6l9MJpDbDZZ/fJvqNcvO1PcivGEf1AvKuTcHoLjVZVFeAMygnamCTDikCVMRnA+qJe+B3pSbgX2+lBMqgBhA==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz",
"integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==",
"cpu": [
"arm64"
],
@@ -2729,9 +2729,9 @@
]
},
"node_modules/@rollup/rollup-linux-loong64-gnu": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.1.tgz",
"integrity": "sha512-UDUtelEprkA85g95Q+nj3Xf0M4hHa4DiJ+3P3h4BuGliY4NReYYqwlc0Y8ICLjN4+uIgCEvaygYlpf0hUj90Yg==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz",
"integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==",
"cpu": [
"loong64"
],
@@ -2743,9 +2743,9 @@
]
},
"node_modules/@rollup/rollup-linux-ppc64-gnu": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.1.tgz",
"integrity": "sha512-vrRn+BYhEtNOte/zbc2wAUQReJXxEx2URfTol6OEfY2zFEUK92pkFBSXRylDM7aHi+YqEPJt9/ABYzmcrS4SgQ==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz",
"integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==",
"cpu": [
"ppc64"
],
@@ -2757,9 +2757,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.1.tgz",
"integrity": "sha512-gto/1CxHyi4A7YqZZNznQYrVlPSaodOBPKM+6xcDSCMVZN/Fzb4K+AIkNz/1yAYz9h3Ng+e2fY9H6bgawVq17w==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz",
"integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==",
"cpu": [
"riscv64"
],
@@ -2771,9 +2771,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-musl": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.1.tgz",
"integrity": "sha512-KZ6Vx7jAw3aLNjFR8eYVcQVdFa/cvBzDNRFM3z7XhNNunWjA03eUrEwJYPk0G8V7Gs08IThFKcAPS4WY/ybIrQ==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz",
"integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==",
"cpu": [
"riscv64"
],
@@ -2785,9 +2785,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.1.tgz",
"integrity": "sha512-HvEixy2s/rWNgpwyKpXJcHmE7om1M89hxBTBi9Fs6zVuLU4gOrEMQNbNsN/tBVIMbLyysz/iwNiGtMOpLAOlvA==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz",
"integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==",
"cpu": [
"s390x"
],
@@ -2799,9 +2799,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.1.tgz",
"integrity": "sha512-E/n8x2MSjAQgjj9IixO4UeEUeqXLtiA7pyoXCFYLuXpBA/t2hnbIdxHfA7kK9BFsYAoNU4st1rHYdldl8dTqGA==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz",
"integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==",
"cpu": [
"x64"
],
@@ -2813,9 +2813,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.1.tgz",
"integrity": "sha512-IhJ087PbLOQXCN6Ui/3FUkI9pWNZe/Z7rEIVOzMsOs1/HSAECCvSZ7PkIbkNqL/AZn6WbZvnoVZw/qwqYMo4/w==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz",
"integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==",
"cpu": [
"x64"
],
@@ -2827,9 +2827,9 @@
]
},
"node_modules/@rollup/rollup-openharmony-arm64": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.1.tgz",
"integrity": "sha512-0++oPNgLJHBblreu0SFM7b3mAsBJBTY0Ksrmu9N6ZVrPiTkRgda52mWR7TKhHAsUb9noCjFvAw9l6ZO1yzaVbA==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz",
"integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==",
"cpu": [
"arm64"
],
@@ -2841,9 +2841,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.1.tgz",
"integrity": "sha512-VJXivz61c5uVdbmitLkDlbcTk9Or43YC2QVLRkqp86QoeFSqI81bNgjhttqhKNMKnQMWnecOCm7lZz4s+WLGpQ==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz",
"integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==",
"cpu": [
"arm64"
],
@@ -2855,9 +2855,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.1.tgz",
"integrity": "sha512-NmZPVTUOitCXUH6erJDzTQ/jotYw4CnkMDjCYRxNHVD9bNyfrGoIse684F9okwzKCV4AIHRbUkeTBc9F2OOH5Q==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz",
"integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==",
"cpu": [
"ia32"
],
@@ -2869,9 +2869,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-gnu": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.1.tgz",
"integrity": "sha512-2SNj7COIdAf6yliSpLdLG8BEsp5lgzRehgfkP0Av8zKfQFKku6JcvbobvHASPJu4f3BFxej5g+HuQPvqPhHvpQ==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz",
"integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==",
"cpu": [
"x64"
],
@@ -2883,9 +2883,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.1.tgz",
"integrity": "sha512-rLarc1Ofcs3DHtgSzFO31pZsCh8g05R2azN1q3fF+H423Co87My0R+tazOEvYVKXSLh8C4LerMK41/K7wlklcg==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz",
"integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==",
"cpu": [
"x64"
],
@@ -3173,9 +3173,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.10.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.0.tgz",
"integrity": "sha512-qzQZRBqkFsYyaSWXuEHc2WR9c0a0CXwiE5FWUvn7ZM+vdy1uZLfCunD38UzhuB7YN/J11ndbDBcTmOdxJo9Q7A==",
"version": "24.10.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz",
"integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -3291,42 +3291,42 @@
}
},
"node_modules/@vue/compiler-core": {
"version": "3.5.24",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.24.tgz",
"integrity": "sha512-eDl5H57AOpNakGNAkFDH+y7kTqrQpJkZFXhWZQGyx/5Wh7B1uQYvcWkvZi11BDhscPgj8N7XV3oRwiPnx1Vrig==",
"version": "3.5.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.25.tgz",
"integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.28.5",
"@vue/shared": "3.5.24",
"@vue/shared": "3.5.25",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.1"
}
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.24",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.24.tgz",
"integrity": "sha512-1QHGAvs53gXkWdd3ZMGYuvQFXHW4ksKWPG8HP8/2BscrbZ0brw183q2oNWjMrSWImYLHxHrx1ItBQr50I/q2zw==",
"version": "3.5.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.25.tgz",
"integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-core": "3.5.24",
"@vue/shared": "3.5.24"
"@vue/compiler-core": "3.5.25",
"@vue/shared": "3.5.25"
}
},
"node_modules/@vue/compiler-sfc": {
"version": "3.5.24",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.24.tgz",
"integrity": "sha512-8EG5YPRgmTB+YxYBM3VXy8zHD9SWHUJLIGPhDovo3Z8VOgvP+O7UP5vl0J4BBPWYD9vxtBabzW1EuEZ+Cqs14g==",
"version": "3.5.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.25.tgz",
"integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.28.5",
"@vue/compiler-core": "3.5.24",
"@vue/compiler-dom": "3.5.24",
"@vue/compiler-ssr": "3.5.24",
"@vue/shared": "3.5.24",
"@vue/compiler-core": "3.5.25",
"@vue/compiler-dom": "3.5.25",
"@vue/compiler-ssr": "3.5.25",
"@vue/shared": "3.5.25",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.21",
"postcss": "^8.5.6",
@@ -3334,14 +3334,14 @@
}
},
"node_modules/@vue/compiler-ssr": {
"version": "3.5.24",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.24.tgz",
"integrity": "sha512-trOvMWNBMQ/odMRHW7Ae1CdfYx+7MuiQu62Jtu36gMLXcaoqKvAyh+P73sYG9ll+6jLB6QPovqoKGGZROzkFFg==",
"version": "3.5.25",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.25.tgz",
"integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==",
"dev": true,
"license": "MIT",
"dependencies": {
"@vue/compiler-dom": "3.5.24",
"@vue/shared": "3.5.24"
"@vue/compiler-dom": "3.5.25",
"@vue/shared": "3.5.25"
}
},
"node_modules/@vue/component-compiler-utils": {
@@ -3423,9 +3423,9 @@
"license": "MIT"
},
"node_modules/@vue/shared": {
"version": "3.5.24",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.24.tgz",
"integrity": "sha512-9cwHL2EsJBdi8NY22pngYYWzkTDhld6fAD6jlaeloNGciNSJL6bLpbxVgXl96X00Jtc6YWQv96YA/0sxex/k1A==",
"version": "3.5.25",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.25.tgz",
"integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==",
"dev": true,
"license": "MIT"
},
@@ -3776,9 +3776,9 @@
}
},
"node_modules/alpinejs": {
"version": "3.15.1",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.1.tgz",
"integrity": "sha512-HLO1TtiE92VajFHtLLPK8BWaK1YepV/uj31UrfoGnQ00lyFOJZ+oVY3F0DghPAwvg8sLU79pmjGQSytERa2gEg==",
"version": "3.15.2",
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.15.2.tgz",
"integrity": "sha512-2kYF2aG+DTFkE6p0rHG5XmN4VEb6sO9b02aOdU4+i8QN6rL0DbRZQiypDE1gBcGO65yDcqMz5KKYUYgMUxgNkw==",
"license": "MIT",
"dependencies": {
"@vue/reactivity": "~3.1.1"
@@ -3909,9 +3909,9 @@
"license": "MIT"
},
"node_modules/autoprefixer": {
"version": "10.4.21",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.21.tgz",
"integrity": "sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ==",
"version": "10.4.22",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz",
"integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==",
"dev": true,
"funding": [
{
@@ -3929,9 +3929,9 @@
],
"license": "MIT",
"dependencies": {
"browserslist": "^4.24.4",
"caniuse-lite": "^1.0.30001702",
"fraction.js": "^4.3.7",
"browserslist": "^4.27.0",
"caniuse-lite": "^1.0.30001754",
"fraction.js": "^5.3.4",
"normalize-range": "^0.1.2",
"picocolors": "^1.1.1",
"postcss-value-parser": "^4.2.0"
@@ -4075,9 +4075,9 @@
"license": "MIT"
},
"node_modules/baseline-browser-mapping": {
"version": "2.8.25",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.25.tgz",
"integrity": "sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA==",
"version": "2.8.31",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.31.tgz",
"integrity": "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -4360,9 +4360,9 @@
}
},
"node_modules/browserslist": {
"version": "4.27.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz",
"integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==",
"version": "4.28.0",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz",
"integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==",
"dev": true,
"funding": [
{
@@ -4380,10 +4380,10 @@
],
"license": "MIT",
"dependencies": {
"baseline-browser-mapping": "^2.8.19",
"caniuse-lite": "^1.0.30001751",
"electron-to-chromium": "^1.5.238",
"node-releases": "^2.0.26",
"baseline-browser-mapping": "^2.8.25",
"caniuse-lite": "^1.0.30001754",
"electron-to-chromium": "^1.5.249",
"node-releases": "^2.0.27",
"update-browserslist-db": "^1.1.4"
},
"bin": {
@@ -4521,9 +4521,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001754",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz",
"integrity": "sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg==",
"version": "1.0.30001757",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz",
"integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==",
"dev": true,
"funding": [
{
@@ -4966,13 +4966,13 @@
"license": "MIT"
},
"node_modules/core-js-compat": {
"version": "3.46.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz",
"integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==",
"version": "3.47.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz",
"integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"browserslist": "^4.26.3"
"browserslist": "^4.28.0"
},
"funding": {
"type": "opencollective",
@@ -5365,9 +5365,9 @@
}
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"dev": true,
"license": "MIT"
},
@@ -5736,9 +5736,9 @@
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.249",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.249.tgz",
"integrity": "sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg==",
"version": "1.5.260",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.260.tgz",
"integrity": "sha512-ov8rBoOBhVawpzdre+Cmz4FB+y66Eqrk6Gwqd8NGxuhv99GQ8XqMAr351KEkOt7gukXWDg6gJWEMKgL2RLMPtA==",
"dev": true,
"license": "ISC"
},
@@ -6443,9 +6443,9 @@
}
},
"node_modules/form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
"integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -6470,16 +6470,16 @@
}
},
"node_modules/fraction.js": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
"integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
"integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "*"
},
"funding": {
"type": "patreon",
"type": "github",
"url": "https://github.com/sponsors/rawify"
}
},
@@ -7088,9 +7088,9 @@
}
},
"node_modules/i18next": {
"version": "25.6.1",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.6.1.tgz",
"integrity": "sha512-yUWvdXtalZztmKrKw3yz/AvSP3yKyqIkVPx/wyvoYy9lkLmwzItLxp0iHZLG5hfVQ539Jor4XLO+U+NHIXg7pw==",
"version": "25.6.3",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-25.6.3.tgz",
"integrity": "sha512-AEQvoPDljhp67a1+NsnG/Wb1Nh6YoSvtrmeEd24sfGn3uujCtXCF3cXpr7ulhMywKNFF7p3TX1u2j7y+caLOJg==",
"funding": [
{
"type": "individual",
@@ -7107,7 +7107,7 @@
],
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.27.6"
"@babel/runtime": "^7.28.4"
},
"peerDependencies": {
"typescript": "^5"
@@ -8400,9 +8400,9 @@
}
},
"node_modules/node-forge": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz",
"integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==",
"dev": true,
"license": "(BSD-3-Clause OR GPL-2.0)",
"engines": {
@@ -10110,9 +10110,9 @@
}
},
"node_modules/rollup": {
"version": "4.53.1",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.1.tgz",
"integrity": "sha512-n2I0V0lN3E9cxxMqBCT3opWOiQBzRN7UG60z/WDKqdX2zHUS/39lezBcsckZFsV6fUTSnfqI7kHf60jDAPGKug==",
"version": "4.53.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz",
"integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -10126,28 +10126,28 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.53.1",
"@rollup/rollup-android-arm64": "4.53.1",
"@rollup/rollup-darwin-arm64": "4.53.1",
"@rollup/rollup-darwin-x64": "4.53.1",
"@rollup/rollup-freebsd-arm64": "4.53.1",
"@rollup/rollup-freebsd-x64": "4.53.1",
"@rollup/rollup-linux-arm-gnueabihf": "4.53.1",
"@rollup/rollup-linux-arm-musleabihf": "4.53.1",
"@rollup/rollup-linux-arm64-gnu": "4.53.1",
"@rollup/rollup-linux-arm64-musl": "4.53.1",
"@rollup/rollup-linux-loong64-gnu": "4.53.1",
"@rollup/rollup-linux-ppc64-gnu": "4.53.1",
"@rollup/rollup-linux-riscv64-gnu": "4.53.1",
"@rollup/rollup-linux-riscv64-musl": "4.53.1",
"@rollup/rollup-linux-s390x-gnu": "4.53.1",
"@rollup/rollup-linux-x64-gnu": "4.53.1",
"@rollup/rollup-linux-x64-musl": "4.53.1",
"@rollup/rollup-openharmony-arm64": "4.53.1",
"@rollup/rollup-win32-arm64-msvc": "4.53.1",
"@rollup/rollup-win32-ia32-msvc": "4.53.1",
"@rollup/rollup-win32-x64-gnu": "4.53.1",
"@rollup/rollup-win32-x64-msvc": "4.53.1",
"@rollup/rollup-android-arm-eabi": "4.53.3",
"@rollup/rollup-android-arm64": "4.53.3",
"@rollup/rollup-darwin-arm64": "4.53.3",
"@rollup/rollup-darwin-x64": "4.53.3",
"@rollup/rollup-freebsd-arm64": "4.53.3",
"@rollup/rollup-freebsd-x64": "4.53.3",
"@rollup/rollup-linux-arm-gnueabihf": "4.53.3",
"@rollup/rollup-linux-arm-musleabihf": "4.53.3",
"@rollup/rollup-linux-arm64-gnu": "4.53.3",
"@rollup/rollup-linux-arm64-musl": "4.53.3",
"@rollup/rollup-linux-loong64-gnu": "4.53.3",
"@rollup/rollup-linux-ppc64-gnu": "4.53.3",
"@rollup/rollup-linux-riscv64-gnu": "4.53.3",
"@rollup/rollup-linux-riscv64-musl": "4.53.3",
"@rollup/rollup-linux-s390x-gnu": "4.53.3",
"@rollup/rollup-linux-x64-gnu": "4.53.3",
"@rollup/rollup-linux-x64-musl": "4.53.3",
"@rollup/rollup-openharmony-arm64": "4.53.3",
"@rollup/rollup-win32-arm64-msvc": "4.53.3",
"@rollup/rollup-win32-ia32-msvc": "4.53.3",
"@rollup/rollup-win32-x64-gnu": "4.53.3",
"@rollup/rollup-win32-x64-msvc": "4.53.3",
"fsevents": "~2.3.2"
}
},
@@ -10203,9 +10203,9 @@
"license": "MIT"
},
"node_modules/sass": {
"version": "1.93.3",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.93.3.tgz",
"integrity": "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg==",
"version": "1.94.2",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.94.2.tgz",
"integrity": "sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11517,9 +11517,9 @@
}
},
"node_modules/vite": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.2.2.tgz",
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
"version": "7.2.4",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.2.4.tgz",
"integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11840,9 +11840,9 @@
"license": "BSD-2-Clause"
},
"node_modules/webpack": {
"version": "5.102.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.102.1.tgz",
"integrity": "sha512-7h/weGm9d/ywQ6qzJ+Xy+r9n/3qgp/thalBbpOi5i223dPXKi04IBtqPN9nTd+jBc7QKfvDbaBnFipYp4sJAUQ==",
"version": "5.103.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.103.0.tgz",
"integrity": "sha512-HU1JOuV1OavsZ+mfigY0j8d1TgQgbZ6M+J75zDkpEAwYeXjWSqrGJtgnPblJjd/mAyTNQ7ygw0MiKOn6etz8yw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -11863,7 +11863,7 @@
"glob-to-regexp": "^0.4.1",
"graceful-fs": "^4.2.11",
"json-parse-even-better-errors": "^2.3.1",
"loader-runner": "^4.2.0",
"loader-runner": "^4.3.1",
"mime-types": "^2.1.27",
"neo-async": "^2.6.2",
"schema-utils": "^4.3.3",
@@ -12507,7 +12507,7 @@
"@fortawesome/fontawesome-free": "^7",
"@popperjs/core": "^2.11.8",
"admin-lte": "^4.0.0-rc4",
"alpinejs": "^3.13.7",
"alpinejs": "^3.15.2",
"bootstrap": "^5",
"bootstrap5-autocomplete": "^1",
"bootstrap5-tags": "^1",

View File

@@ -19,7 +19,7 @@
"@fortawesome/fontawesome-free": "^7",
"@popperjs/core": "^2.11.8",
"admin-lte": "^4.0.0-rc4",
"alpinejs": "^3.13.7",
"alpinejs": "^3.15.2",
"bootstrap": "^5",
"bootstrap5-autocomplete": "^1",
"bootstrap5-tags": "^1",

View File

@@ -24,7 +24,7 @@
declare(strict_types=1);
return [
'invalid_account_list' => 'Invalid account type list',
'invalid_account_list' => 'Invalid account type list entry ":value"',
'invalid_transaction_type_list' => 'Invalid transaction type list',
'limit_exists' => 'There is already a budget limit (amount) for this budget and currency in the given period.',
'invalid_sort_instruction' => 'The sort instruction is invalid for an object of type ":object".',

View File

@@ -62,6 +62,10 @@
<div class="box-body no-padding">
<table class="table table-hover">
<tbody>
<tr>
<td style="width:40%;">{{ trans('list.id') }}</td>
<td>#{{ transactionGroup.id }}</td>
</tr>
<tr>
<td style="width:40%;">{{ trans('list.type') }}</td>
<td>{{ first.transaction_type_type|_ }}</td>