Compare commits

...

98 Commits

Author SHA1 Message Date
James Cole
926665a8f5 Merge branch 'release/6.0.9' 2023-04-28 09:27:42 +02:00
James Cole
e35743ff42 Update meta files for new release. 2023-04-28 09:27:14 +02:00
James Cole
321743dbf6 Merge pull request #7439 from firefly-iii/fix-7394
Fix 7394
2023-04-28 09:06:48 +02:00
James Cole
c2e1e25489 Fix #7394 2023-04-28 09:06:05 +02:00
James Cole
222387adba Merge pull request #7438 from firefly-iii/division-by-zero
Fix division by zero
2023-04-28 08:39:54 +02:00
James Cole
335414f25a Fix division by zero 2023-04-28 08:39:30 +02:00
James Cole
ea903c105d Merge pull request #7437 from mindlessroman/patch-1
Update the links to the installation documentation
2023-04-27 17:16:39 +02:00
Hannah K
aab29852b4 Merge branch 'develop' into patch-1
Signed-off-by: Hannah K <7254163+mindlessroman@users.noreply.github.com>
2023-04-27 11:12:43 -04:00
Hannah K
aa17ea0b68 Update the links to the installation documentation
Signed-off-by: Hannah K <7254163+mindlessroman@users.noreply.github.com>
2023-04-27 11:02:38 -04:00
James Cole
deeb5bf118 Merge pull request #7435 from firefly-iii/better-ab-mgt
Remove dangerous eternal loop
2023-04-26 12:13:22 +02:00
James Cole
47d5e8d169 Remove dangerous eternal loop 2023-04-26 12:12:23 +02:00
James Cole
033d61abbb Merge pull request #7434 from firefly-iii/better-ab-mgt
Better management and calculation of available budgets.
2023-04-26 11:32:18 +02:00
James Cole
28efc15820 Better management and calculation of available budgets. 2023-04-26 11:31:46 +02:00
James Cole
1c7988fad2 Fix #7389 2023-04-26 06:59:42 +02:00
James Cole
c8077762ba Merge pull request #7433 from firefly-iii/remove-debug
Remove debug logging.
2023-04-26 06:41:53 +02:00
James Cole
ea53b34cbb Remove debug logging. 2023-04-26 06:41:06 +02:00
James Cole
270ac87e65 Merge pull request #7432 from firefly-iii/max-values
Add sensible maximum values.
2023-04-26 06:17:50 +02:00
James Cole
0a60f63bf8 Add sensible maximum values. 2023-04-26 06:17:04 +02:00
James Cole
38ed70243e Merge pull request #7431 from firefly-iii/fix-validation
Add validation check.
2023-04-26 06:00:56 +02:00
James Cole
0f2a9a9b37 Add validation check. 2023-04-26 06:00:04 +02:00
James Cole
ec525849fc Merge pull request #7430 from firefly-iii/fix-validation
Fix length validation
2023-04-26 05:56:20 +02:00
James Cole
dee1e1a79d Fix length validation 2023-04-26 05:55:31 +02:00
James Cole
98b5ed9e5b Merge pull request #7429 from firefly-iii/error-rate-bills
Add rule for notes and better escaping in errors.
2023-04-26 05:30:06 +02:00
James Cole
d8eb084240 Add rule for notes and better escaping in errors. 2023-04-26 05:29:28 +02:00
James Cole
c2f5fbe7d3 Merge pull request #7428 from noxonad/patch-1
Fixed misleading documentation links in readme.md
2023-04-25 16:16:29 +02:00
noxonad
60f6542a1b Fixed misleading documentation links in readme.md
Signed-off-by: noxonad <130460440+noxonad@users.noreply.github.com>
2023-04-25 13:11:34 +03:00
James Cole
93c2edf76c Merge pull request #7424 from firefly-iii/dependabot/composer/develop/guzzlehttp/guzzle-7.5.1
Bump guzzlehttp/guzzle from 7.5.0 to 7.5.1
2023-04-24 06:19:07 +02:00
James Cole
f74f4c5719 Merge pull request #7425 from firefly-iii/dependabot/npm_and_yarn/develop/axios-1.3.6
Bump axios from 1.3.5 to 1.3.6
2023-04-24 06:18:57 +02:00
James Cole
8c67c347e1 Merge pull request #7423 from firefly-iii/dependabot/composer/develop/nunomaduro/larastan-2.6.0
Bump nunomaduro/larastan from 2.5.1 to 2.6.0
2023-04-24 06:18:46 +02:00
dependabot[bot]
fcbc341f03 Bump nunomaduro/larastan from 2.5.1 to 2.6.0
Bumps [nunomaduro/larastan](https://github.com/nunomaduro/larastan) from 2.5.1 to 2.6.0.
- [Release notes](https://github.com/nunomaduro/larastan/releases)
- [Changelog](https://github.com/nunomaduro/larastan/blob/master/RELEASE.md)
- [Commits](https://github.com/nunomaduro/larastan/compare/2.5.1...v2.6.0)

---
updated-dependencies:
- dependency-name: nunomaduro/larastan
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 04:18:39 +00:00
dependabot[bot]
2dbce10483 Bump guzzlehttp/guzzle from 7.5.0 to 7.5.1
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 7.5.0 to 7.5.1.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/7.5/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/7.5.0...7.5.1)

---
updated-dependencies:
- dependency-name: guzzlehttp/guzzle
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 04:18:36 +00:00
James Cole
8504b3e3a9 Merge pull request #7422 from firefly-iii/dependabot/npm_and_yarn/develop/postcss-8.4.23
Bump postcss from 8.4.22 to 8.4.23
2023-04-24 06:18:36 +02:00
James Cole
d4ab5dcefd Merge pull request #7421 from firefly-iii/dependabot/composer/develop/diglactic/laravel-breadcrumbs-8.1.1
Bump diglactic/laravel-breadcrumbs from 8.1.0 to 8.1.1
2023-04-24 06:17:55 +02:00
James Cole
5d11e285bc Merge pull request #7420 from firefly-iii/dependabot/composer/develop/laravel/framework-10.8.0
Bump laravel/framework from 10.7.1 to 10.8.0
2023-04-24 06:10:25 +02:00
James Cole
259e1350d5 Merge pull request #7419 from firefly-iii/dependabot/composer/develop/phpstan/phpstan-1.10.14
Bump phpstan/phpstan from 1.10.13 to 1.10.14
2023-04-24 06:08:16 +02:00
dependabot[bot]
dd54ec6122 Bump axios from 1.3.5 to 1.3.6
Bumps [axios](https://github.com/axios/axios) from 1.3.5 to 1.3.6.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.3.5...v1.3.6)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:57:31 +00:00
dependabot[bot]
c2b3791336 Bump postcss from 8.4.22 to 8.4.23
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.22 to 8.4.23.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.22...8.4.23)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:57:08 +00:00
dependabot[bot]
fc1f15cc14 Bump diglactic/laravel-breadcrumbs from 8.1.0 to 8.1.1
Bumps [diglactic/laravel-breadcrumbs](https://github.com/diglactic/laravel-breadcrumbs) from 8.1.0 to 8.1.1.
- [Release notes](https://github.com/diglactic/laravel-breadcrumbs/releases)
- [Commits](https://github.com/diglactic/laravel-breadcrumbs/compare/v8.1.0...v8.1.1)

---
updated-dependencies:
- dependency-name: diglactic/laravel-breadcrumbs
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:57:00 +00:00
dependabot[bot]
5d74979f50 Bump laravel/framework from 10.7.1 to 10.8.0
Bumps [laravel/framework](https://github.com/laravel/framework) from 10.7.1 to 10.8.0.
- [Release notes](https://github.com/laravel/framework/releases)
- [Changelog](https://github.com/laravel/framework/blob/10.x/CHANGELOG.md)
- [Commits](https://github.com/laravel/framework/compare/v10.7.1...v10.8.0)

---
updated-dependencies:
- dependency-name: laravel/framework
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:56:49 +00:00
dependabot[bot]
5dea7e5b41 Bump phpstan/phpstan from 1.10.13 to 1.10.14
Bumps [phpstan/phpstan](https://github.com/phpstan/phpstan) from 1.10.13 to 1.10.14.
- [Release notes](https://github.com/phpstan/phpstan/releases)
- [Changelog](https://github.com/phpstan/phpstan/blob/1.11.x/CHANGELOG.md)
- [Commits](https://github.com/phpstan/phpstan/compare/1.10.13...1.10.14)

---
updated-dependencies:
- dependency-name: phpstan/phpstan
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-24 03:56:31 +00:00
James Cole
a53a8a8529 Merge pull request #7417 from firefly-iii/fix-7410
Fix #7410
2023-04-23 18:24:20 +02:00
James Cole
aac7a2691d Fix #7410 2023-04-23 18:23:02 +02:00
James Cole
10e7be1729 Merge branch 'main' into develop 2023-04-22 06:43:09 +02:00
James Cole
9b1319f970 Fix bad math in page counter. 2023-04-22 06:42:26 +02:00
James Cole
a38f909919 Add some debug. 2023-04-22 06:17:46 +02:00
James Cole
d8c0192f54 Merge pull request #7413 from firefly-iii/dependabot/composer/nyholm/psr7-1.7.0
Bump nyholm/psr7 from 1.6.0 to 1.7.0
2023-04-22 05:55:33 +02:00
dependabot[bot]
1e8d294b8d Bump nyholm/psr7 from 1.6.0 to 1.7.0
Bumps [nyholm/psr7](https://github.com/Nyholm/psr7) from 1.6.0 to 1.7.0.
- [Release notes](https://github.com/Nyholm/psr7/releases)
- [Changelog](https://github.com/Nyholm/psr7/blob/master/CHANGELOG.md)
- [Commits](https://github.com/Nyholm/psr7/compare/1.6.0...1.7.0)

---
updated-dependencies:
- dependency-name: nyholm/psr7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-21 20:52:03 +00:00
James Cole
d3be64114b Merge pull request #7403 from firefly-iii/dependabot/composer/guzzlehttp/psr7-2.5.0 2023-04-20 07:26:39 +02:00
dependabot[bot]
1bddd4da8e Bump guzzlehttp/psr7 from 2.4.4 to 2.5.0
Bumps [guzzlehttp/psr7](https://github.com/guzzle/psr7) from 2.4.4 to 2.5.0.
- [Release notes](https://github.com/guzzle/psr7/releases)
- [Changelog](https://github.com/guzzle/psr7/blob/2.5/CHANGELOG.md)
- [Commits](https://github.com/guzzle/psr7/compare/2.4.4...2.5.0)

---
updated-dependencies:
- dependency-name: guzzlehttp/psr7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-19 21:07:24 +00:00
James Cole
6b5ff2680b Update lock.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2023-04-19 10:12:51 +02:00
James Cole
efe17f638a Update lock.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2023-04-19 06:43:31 +02:00
James Cole
3c1f4b7377 Update lock.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2023-04-19 06:43:19 +02:00
James Cole
acfc214eb1 Update lock.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2023-04-19 06:42:00 +02:00
James Cole
fe1c605c11 Update lock.yml
Wonder if this works.

Signed-off-by: James Cole <james@firefly-iii.org>
2023-04-19 06:38:09 +02:00
James Cole
891cd94031 Merge branch 'main' into develop 2023-04-17 06:17:42 +02:00
James Cole
c620d57f42 Update lock.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2023-04-17 06:16:07 +02:00
James Cole
b076c92eb0 Update lock.yml
Signed-off-by: James Cole <james@firefly-iii.org>
2023-04-17 06:15:07 +02:00
James Cole
9e35216e98 Merge branch 'main' into develop 2023-04-17 06:09:33 +02:00
James Cole
3fa4734ba7 Merge pull request #7388 from firefly-iii/dependabot/npm_and_yarn/develop/postcss-8.4.22
Bump postcss from 8.4.21 to 8.4.22
2023-04-17 05:57:52 +02:00
dependabot[bot]
0144d09325 Bump postcss from 8.4.21 to 8.4.22
Bumps [postcss](https://github.com/postcss/postcss) from 8.4.21 to 8.4.22.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.4.21...8.4.22)

---
updated-dependencies:
- dependency-name: postcss
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-17 03:57:03 +00:00
James Cole
f28274aded Update stale.yml
Add epic

Signed-off-by: James Cole <james@firefly-iii.org>
2023-04-17 05:52:00 +02:00
James Cole
d5f5df82b6 Fix small commands 2023-04-16 08:01:40 +02:00
James Cole
49c27aff2d Merge pull request #7385 from firefly-iii/duplicate-commands
Remove duplicate commands.
2023-04-16 07:56:18 +02:00
James Cole
7b1b0cfef9 Remove duplicate commands. 2023-04-16 07:49:53 +02:00
James Cole
f728bdeb5a Merge pull request #7384 from firefly-iii/fix-commands
Fix method name
2023-04-16 07:39:47 +02:00
James Cole
4712a826d1 Fix method name 2023-04-16 07:38:54 +02:00
James Cole
d7335d71ea Merge pull request #7383 from firefly-iii/fix-commands
Fix start and upgrade commands
2023-04-16 07:33:37 +02:00
James Cole
e6a84ab387 Fix start and upgrade commands 2023-04-16 07:33:12 +02:00
James Cole
fd5269490d Merge pull request #7382 from firefly-iii/fix-7377
Another fix for #7377
2023-04-16 06:59:41 +02:00
James Cole
05e307136c Another fix for #7377 2023-04-16 06:59:19 +02:00
James Cole
2c41215e84 Merge pull request #7380 from firefly-iii/fix-7377
Fix #7377
2023-04-16 06:56:54 +02:00
James Cole
d9dc394e7f Fix #7377 2023-04-16 06:56:11 +02:00
James Cole
a63daf6166 Merge tag 'v6.0.8' into develop
v6.0.8
2023-04-15 10:46:24 +02:00
James Cole
f878af0d3b Merge branch 'release/v6.0.8' 2023-04-15 10:46:23 +02:00
James Cole
def0578421 Merge pull request #7371 from firefly-iii/release-608
Update meta-files for new release.
2023-04-15 10:45:36 +02:00
James Cole
a2e07b1518 Update meta-files for new release. 2023-04-15 10:44:58 +02:00
James Cole
dc26ce308d Add decrypt message. 2023-04-15 10:33:33 +02:00
James Cole
0189b91d3b Add deleted check to attachment filter 2023-04-15 10:19:54 +02:00
James Cole
fb6706648e Merge pull request #7370 from firefly-iii/fix-installer
Fix installer
2023-04-15 10:19:34 +02:00
James Cole
3c20fd7533 Fix installer 2023-04-15 10:14:14 +02:00
James Cole
82f89ef614 Merge pull request #7369 from firefly-iii/fix-date-fields
Fix date fields
2023-04-15 07:21:26 +02:00
James Cole
4d10ae91b7 Fix date fields 2023-04-15 07:21:06 +02:00
James Cole
aebb677c21 Add some debug info to transaction counter. 2023-04-15 07:17:48 +02:00
James Cole
abf9c65b21 Merge pull request #7358 from firefly-iii/fix-7355
Fix #7355
2023-04-12 19:58:19 +02:00
James Cole
524dcc7d97 Fix #7355 2023-04-12 06:18:05 +02:00
James Cole
0a4f6fd6b8 Merge pull request #7354 from firefly-iii/redirect
Redirect when unauthenticated.
2023-04-10 14:21:26 +02:00
James Cole
9c4beab0a7 Redirect when unauthenticated. 2023-04-10 14:21:10 +02:00
James Cole
b91e019416 Merge pull request #7353 from firefly-iii/migration-checks
Catch all possible migration errors
2023-04-10 08:29:49 +02:00
James Cole
ad97e33ec0 Catch all possible migration errors 2023-04-10 08:29:27 +02:00
James Cole
b1479b5dae Merge pull request #7352 from firefly-iii/force-commit
Add commit call to force the commands to go through.
2023-04-10 07:20:02 +02:00
James Cole
f1445b0132 Add commit call to force the commands to go through. 2023-04-10 07:19:10 +02:00
James Cole
456dbfd29d Merge pull request #7351 from firefly-iii/add-command
Add decimal command.
2023-04-09 20:29:57 +02:00
James Cole
0eea776b8b Add decimal command. 2023-04-09 20:29:35 +02:00
James Cole
853a97307b Merge pull request #7350 from firefly-iii/fix-7349
Fix 7349
2023-04-09 18:24:08 +02:00
James Cole
3b28b5d07a Fix #7349 2023-04-09 18:23:45 +02:00
James Cole
a7bfa503d9 Merge pull request #7348 from firefly-iii/fix-7347
Fix #7347
2023-04-09 13:45:22 +02:00
James Cole
a7c3d32370 Fix #7347 2023-04-09 13:45:01 +02:00
James Cole
c64ddbec1f Merge tag 'v6.0.7' into develop
v6.0.7
2023-04-08 08:58:40 +02:00
200 changed files with 4440 additions and 2693 deletions

View File

@@ -5,26 +5,15 @@ on:
schedule: schedule:
- cron: '0 0 * * *' - cron: '0 0 * * *'
permissions:
contents: read
jobs: jobs:
lock: lock:
permissions: permissions:
issues: write # for dessant/lock-threads to lock issues issues: write
pull-requests: write # for dessant/lock-threads to lock PRs pull-requests: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dessant/lock-threads@v4 - uses: JC5/lock-threads@main
with: with:
github-token: ${{ github.token }} github-token: ${{ github.token }}
issue-lock-inactive-days: '90' issue-inactive-days: 90
issue-comment: > pr-inactive-days: 90
Hi there! This is an automatic reply. `Share and enjoy`
This issue is now `locked` :lock:.
- If you feel there is more to be said about this specific issue, please feel free to open a new issue. Please refer to this issue for clarity.
- Follow-up questions and comments can also be posted in a new [discussion](https://github.com/firefly-iii/firefly-iii/discussions/)
Thank you for your consideration.

View File

@@ -31,4 +31,4 @@ jobs:
Thank you for your contributions. Thank you for your contributions.
days-before-stale: 14 days-before-stale: 14
days-before-close: 7 days-before-close: 7
exempt-issue-labels: 'enhancement,feature,bug,announcement,layout-v3' exempt-issue-labels: 'enhancement,feature,bug,announcement,epic'

View File

@@ -85,12 +85,11 @@ abstract class Controller extends BaseController
{ {
$bag = new ParameterBag(); $bag = new ParameterBag();
$page = (int)request()->get('page'); $page = (int)request()->get('page');
if ($page < 1) { if ($page < 1) {
$page = 1; $page = 1;
} }
if ($page > (2 ^ 16)) { if ($page > pow(2, 16)) {
$page = (2 ^ 16); $page = pow(2, 16);
} }
$bag->set('page', $page); $bag->set('page', $page);

View File

@@ -57,7 +57,7 @@ class DestroyRequest extends FormRequest
',not_assets_liabilities'; ',not_assets_liabilities';
return [ return [
'objects' => sprintf('required|min:1|string|in:%s', $valid), 'objects' => sprintf('required|max:255|min:1|string|in:%s', $valid),
'unused' => 'in:true,false', 'unused' => 'in:true,false',
]; ];
} }

View File

@@ -73,7 +73,7 @@ class ExportRequest extends FormRequest
{ {
return [ return [
'type' => 'in:csv', 'type' => 'in:csv',
'accounts' => 'min:1', 'accounts' => 'min:1|max:65536',
'start' => 'date|before:end', 'start' => 'date|before:end',
'end' => 'date|after:start', 'end' => 'date|after:start',
]; ];

View File

@@ -103,8 +103,8 @@ class StoreRequest extends FormRequest
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes'))); $ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
$type = $this->convertString('type'); $type = $this->convertString('type');
$rules = [ $rules = [
'name' => 'required|min:1|uniqueAccountForUser', 'name' => 'required|max:1024|min:1|uniqueAccountForUser',
'type' => 'required|min:1|'.sprintf('in:%s', $types), 'type' => 'required|max:1024|min:1|'.sprintf('in:%s', $types),
'iban' => ['iban', 'nullable', new UniqueIban(null, $type)], 'iban' => ['iban', 'nullable', new UniqueIban(null, $type)],
'bic' => 'bic|nullable', 'bic' => 'bic|nullable',
'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber(null, $type)], 'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber(null, $type)],
@@ -120,7 +120,7 @@ class StoreRequest extends FormRequest
'credit_card_type' => sprintf('nullable|in:%s|required_if:account_role,ccAsset', $ccPaymentTypes), 'credit_card_type' => sprintf('nullable|in:%s|required_if:account_role,ccAsset', $ccPaymentTypes),
'monthly_payment_date' => 'nullable|date|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull', 'monthly_payment_date' => 'nullable|date|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull',
'liability_type' => 'nullable|required_if:type,liability|required_if:type,liabilities|in:loan,debt,mortgage', 'liability_type' => 'nullable|required_if:type,liability|required_if:type,liabilities|in:loan,debt,mortgage',
'liability_amount' => 'required_with:liability_start_date|min:0|numeric', 'liability_amount' => 'required_with:liability_start_date|min:0|numeric|max:1000000000',
'liability_start_date' => 'required_with:liability_amount|date', 'liability_start_date' => 'required_with:liability_amount|date',
'liability_direction' => 'nullable|required_if:type,liability|required_if:type,liabilities|in:credit,debit', 'liability_direction' => 'nullable|required_if:type,liability|required_if:type,liabilities|in:credit,debit',
'interest' => 'between:0,100|numeric', 'interest' => 'between:0,100|numeric',

View File

@@ -94,7 +94,7 @@ class UpdateRequest extends FormRequest
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes'))); $ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
$rules = [ $rules = [
'name' => sprintf('min:1|uniqueAccountForUser:%d', $account->id), 'name' => sprintf('min:1|max:1024|uniqueAccountForUser:%d', $account->id),
'type' => sprintf('in:%s', $types), 'type' => sprintf('in:%s', $types),
'iban' => ['iban', 'nullable', new UniqueIban($account, $this->convertString('type'))], 'iban' => ['iban', 'nullable', new UniqueIban($account, $this->convertString('type'))],
'bic' => 'bic|nullable', 'bic' => 'bic|nullable',
@@ -104,7 +104,7 @@ class UpdateRequest extends FormRequest
'virtual_balance' => 'numeric|nullable', 'virtual_balance' => 'numeric|nullable',
'order' => 'numeric|nullable', 'order' => 'numeric|nullable',
'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', 'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
'active' => [new IsBoolean()], 'active' => [new IsBoolean()],
'include_net_worth' => [new IsBoolean()], 'include_net_worth' => [new IsBoolean()],
'account_role' => sprintf('in:%s|nullable|required_if:type,asset', $accountRoles), 'account_role' => sprintf('in:%s|nullable|required_if:type,asset', $accountRoles),

View File

@@ -67,7 +67,7 @@ class Request extends FormRequest
{ {
return [ return [
'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', 'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
'amount' => 'numeric|gt:0', 'amount' => 'numeric|gt:0',
'start' => 'date', 'start' => 'date',
'end' => 'date', 'end' => 'date',

View File

@@ -82,7 +82,7 @@ class StoreRequest extends FormRequest
'amount_min' => 'numeric|gt:0|required', 'amount_min' => 'numeric|gt:0|required',
'amount_max' => 'numeric|gt:0|required', 'amount_max' => 'numeric|gt:0|required',
'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', 'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
'date' => 'date|required', 'date' => 'date|required',
'end_date' => 'date|after:date', 'end_date' => 'date|after:date',
'extension_date' => 'date|after:date', 'extension_date' => 'date|after:date',

View File

@@ -84,7 +84,7 @@ class UpdateRequest extends FormRequest
'amount_min' => 'numeric|gt:0', 'amount_min' => 'numeric|gt:0',
'amount_max' => 'numeric|gt:0', 'amount_max' => 'numeric|gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', 'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
'date' => 'date', 'date' => 'date',
'end_date' => 'date|after:date', 'end_date' => 'date|after:date',
'extension_date' => 'date|after:date', 'extension_date' => 'date|after:date',

View File

@@ -65,7 +65,7 @@ class StoreRequest extends FormRequest
'end' => 'required|after:start|date', 'end' => 'required|after:start|date',
'amount' => 'required|gt:0', 'amount' => 'required|gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', 'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
]; ];
} }
} }

View File

@@ -69,7 +69,7 @@ class UpdateRequest extends FormRequest
'end' => 'date', 'end' => 'date',
'amount' => 'gt:0', 'amount' => 'gt:0',
'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_id' => 'numeric|exists:transaction_currencies,id',
'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', 'currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
]; ];
} }

View File

@@ -63,7 +63,7 @@ class UpdateRequest extends FormRequest
$objectGroup = $this->route()->parameter('objectGroup'); $objectGroup = $this->route()->parameter('objectGroup');
return [ return [
'title' => sprintf('min:1|uniqueObjectGroup:%d', $objectGroup->id), 'title' => sprintf('max:1024|min:1|uniqueObjectGroup:%d', $objectGroup->id),
'order' => 'numeric', 'order' => 'numeric',
]; ];
} }

View File

@@ -158,9 +158,9 @@ class StoreRequest extends FormRequest
'transactions.*.amount' => 'required|numeric|gt:0', 'transactions.*.amount' => 'required|numeric|gt:0',
'transactions.*.foreign_amount' => 'nullable|numeric|gt:0', 'transactions.*.foreign_amount' => 'nullable|numeric|gt:0',
'transactions.*.currency_id' => 'nullable|numeric|exists:transaction_currencies,id', 'transactions.*.currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
'transactions.*.currency_code' => 'nullable|min:3|max:3|exists:transaction_currencies,code', 'transactions.*.currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id', 'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
'transactions.*.foreign_currency_code' => 'nullable|min:3|max:3|exists:transaction_currencies,code', 'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.source_name' => 'between:1,255|nullable', 'transactions.*.source_name' => 'between:1,255|nullable',
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],

View File

@@ -172,9 +172,9 @@ class UpdateRequest extends FormRequest
'transactions.*.amount' => 'numeric|gt:0', 'transactions.*.amount' => 'numeric|gt:0',
'transactions.*.foreign_amount' => 'nullable|numeric|gt:0', 'transactions.*.foreign_amount' => 'nullable|numeric|gt:0',
'transactions.*.currency_id' => 'nullable|numeric|exists:transaction_currencies,id', 'transactions.*.currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
'transactions.*.currency_code' => 'nullable|min:3|max:3|exists:transaction_currencies,code', 'transactions.*.currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id', 'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
'transactions.*.foreign_currency_code' => 'nullable|min:3|max:3|exists:transaction_currencies,code', 'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()],
'transactions.*.source_name' => 'between:1,255|nullable', 'transactions.*.source_name' => 'between:1,255|nullable',
'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()],

View File

@@ -79,7 +79,7 @@ class StoreRequest extends FormRequest
$return[] = [ $return[] = [
'type' => $trigger['type'], 'type' => $trigger['type'],
'value' => $trigger['value'], 'value' => $trigger['value'],
'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')), 'active' => $this->convertBoolean((string)($trigger['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')), 'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')),
]; ];
} }
@@ -100,7 +100,7 @@ class StoreRequest extends FormRequest
$return[] = [ $return[] = [
'type' => $action['type'], 'type' => $action['type'],
'value' => $action['value'], 'value' => $action['value'],
'active' => $this->convertBoolean((string)($action['active'] ?? 'false')), 'active' => $this->convertBoolean((string)($action['active'] ?? 'true')),
'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')), 'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')),
]; ];
} }
@@ -130,7 +130,7 @@ class StoreRequest extends FormRequest
'rule_group_title' => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title', 'rule_group_title' => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title',
'trigger' => 'required|in:store-journal,update-journal', 'trigger' => 'required|in:store-journal,update-journal',
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), 'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue', 'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024',
'triggers.*.stop_processing' => [new IsBoolean()], 'triggers.*.stop_processing' => [new IsBoolean()],
'triggers.*.active' => [new IsBoolean()], 'triggers.*.active' => [new IsBoolean()],
'actions.*.type' => 'required|in:'.implode(',', $validActions), 'actions.*.type' => 'required|in:'.implode(',', $validActions),

View File

@@ -147,7 +147,7 @@ class UpdateRequest extends FormRequest
'rule_group_title' => 'nullable|between:1,255|belongsToUser:rule_groups,title', 'rule_group_title' => 'nullable|between:1,255|belongsToUser:rule_groups,title',
'trigger' => 'in:store-journal,update-journal', 'trigger' => 'in:store-journal,update-journal',
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), 'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue', 'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue|max:1024',
'triggers.*.stop_processing' => [new IsBoolean()], 'triggers.*.stop_processing' => [new IsBoolean()],
'triggers.*.active' => [new IsBoolean()], 'triggers.*.active' => [new IsBoolean()],
'actions.*.type' => 'required|in:'.implode(',', $validActions), 'actions.*.type' => 'required|in:'.implode(',', $validActions),

View File

@@ -65,8 +65,8 @@ class StoreRequest extends FormRequest
public function rules(): array public function rules(): array
{ {
$rules = [ $rules = [
'tag' => 'required|min:1|uniqueObjectForUser:tags,tag', 'tag' => 'required|min:1|uniqueObjectForUser:tags,tag|max:1024',
'description' => 'min:1|nullable', 'description' => 'min:1|nullable|max:65536',
'date' => 'date|nullable', 'date' => 'date|nullable',
]; ];

View File

@@ -71,8 +71,8 @@ class UpdateRequest extends FormRequest
$tag = $this->route()->parameter('tagOrId'); $tag = $this->route()->parameter('tagOrId');
// TODO check if uniqueObjectForUser is obsolete // TODO check if uniqueObjectForUser is obsolete
$rules = [ $rules = [
'tag' => 'min:1|uniqueObjectForUser:tags,tag,'.$tag->id, 'tag' => 'min:1|max:1024|uniqueObjectForUser:tags,tag,'.$tag->id,
'description' => 'min:1|nullable', 'description' => 'min:1|nullable|max:65536',
'date' => 'date|nullable', 'date' => 'date|nullable',
]; ];

View File

@@ -188,9 +188,9 @@ class StoreRequest extends FormRequest
// currency info // currency info
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|nullable', 'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code|nullable', 'transactions.*.currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id|nullable', 'transactions.*.foreign_currency_id' => 'numeric|exists:transaction_currencies,id|nullable',
'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code|nullable', 'transactions.*.foreign_currency_code' => 'min:3|max:51|exists:transaction_currencies,code|nullable',
// amount // amount
'transactions.*.amount' => 'required|numeric|gt:0', 'transactions.*.amount' => 'required|numeric|gt:0',
@@ -225,25 +225,25 @@ class StoreRequest extends FormRequest
// other interesting fields // other interesting fields
'transactions.*.reconciled' => [new IsBoolean()], 'transactions.*.reconciled' => [new IsBoolean()],
'transactions.*.notes' => 'min:1,max:50000|nullable', 'transactions.*.notes' => 'min:1|max:50000|nullable',
'transactions.*.tags' => 'between:0,255', 'transactions.*.tags' => 'between:0,255',
// meta info fields // meta info fields
'transactions.*.internal_reference' => 'min:1,max:255|nullable', 'transactions.*.internal_reference' => 'min:1|max:255|nullable',
'transactions.*.external_id' => 'min:1,max:255|nullable', 'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1,max:255|nullable', 'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1,max:255|nullable', 'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => 'min:1,max:255|nullable|url', 'transactions.*.external_url' => 'min:1|max:255|nullable|url',
// SEPA fields: // SEPA fields:
'transactions.*.sepa_cc' => 'min:1,max:255|nullable', 'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_op' => 'min:1,max:255|nullable', 'transactions.*.sepa_ct_op' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_id' => 'min:1,max:255|nullable', 'transactions.*.sepa_ct_id' => 'min:1|max:255|nullable',
'transactions.*.sepa_db' => 'min:1,max:255|nullable', 'transactions.*.sepa_db' => 'min:1|max:255|nullable',
'transactions.*.sepa_country' => 'min:1,max:255|nullable', 'transactions.*.sepa_country' => 'min:1|max:255|nullable',
'transactions.*.sepa_ep' => 'min:1,max:255|nullable', 'transactions.*.sepa_ep' => 'min:1|max:255|nullable',
'transactions.*.sepa_ci' => 'min:1,max:255|nullable', 'transactions.*.sepa_ci' => 'min:1|max:255|nullable',
'transactions.*.sepa_batch_id' => 'min:1,max:255|nullable', 'transactions.*.sepa_batch_id' => 'min:1|max:255|nullable',
// dates // dates
'transactions.*.interest_date' => 'date|nullable', 'transactions.*.interest_date' => 'date|nullable',
@@ -270,7 +270,9 @@ class StoreRequest extends FormRequest
$this->validateTransactionArray($validator); $this->validateTransactionArray($validator);
// must submit at least one transaction. // must submit at least one transaction.
Log::debug('Now going to validateOneTransaction');
$this->validateOneTransaction($validator); $this->validateOneTransaction($validator);
Log::debug('Now done with validateOneTransaction');
// all journals must have a description // all journals must have a description
$this->validateDescriptions($validator); $this->validateDescriptions($validator);

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\Transaction; namespace FireflyIII\Api\V1\Requests\Models\Transaction;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
use FireflyIII\Rules\BelongsUser; use FireflyIII\Rules\BelongsUser;
use FireflyIII\Rules\IsBoolean; use FireflyIII\Rules\IsBoolean;
@@ -61,6 +62,7 @@ class UpdateRequest extends FormRequest
*/ */
public function getAll(): array public function getAll(): array
{ {
Log::debug(sprintf('Now in %s', __METHOD__)); Log::debug(sprintf('Now in %s', __METHOD__));
$this->integerFields = [ $this->integerFields = [
'order', 'order',
@@ -163,6 +165,9 @@ class UpdateRequest extends FormRequest
/** @var array $transaction */ /** @var array $transaction */
foreach ($this->get('transactions') as $transaction) { foreach ($this->get('transactions') as $transaction) {
if(!is_array($transaction)) {
throw new FireflyException('Invalid data submitted: transaction is not array.');
}
// default response is to update nothing in the transaction: // default response is to update nothing in the transaction:
$current = []; $current = [];
$current = $this->getIntegerData($current, $transaction); $current = $this->getIntegerData($current, $transaction);
@@ -330,9 +335,9 @@ class UpdateRequest extends FormRequest
// currency info // currency info
'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id', 'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id',
'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code', 'transactions.*.currency_code' => 'min:3|max:51|exists:transaction_currencies,code',
'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id', 'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id',
'transactions.*.foreign_currency_code' => 'nullable|min:3|max:3|exists:transaction_currencies,code', 'transactions.*.foreign_currency_code' => 'nullable|min:3|max:51|exists:transaction_currencies,code',
// amount // amount
'transactions.*.amount' => 'numeric|gt:0|max:100000000000', 'transactions.*.amount' => 'numeric|gt:0|max:100000000000',
@@ -359,25 +364,25 @@ class UpdateRequest extends FormRequest
// other interesting fields // other interesting fields
'transactions.*.reconciled' => [new IsBoolean()], 'transactions.*.reconciled' => [new IsBoolean()],
'transactions.*.notes' => 'min:1,max:50000|nullable', 'transactions.*.notes' => 'min:1|max:50000|nullable',
'transactions.*.tags' => 'between:0,255', 'transactions.*.tags' => 'between:0,255',
// meta info fields // meta info fields
'transactions.*.internal_reference' => 'min:1,max:255|nullable', 'transactions.*.internal_reference' => 'min:1|max:255|nullable',
'transactions.*.external_id' => 'min:1,max:255|nullable', 'transactions.*.external_id' => 'min:1|max:255|nullable',
'transactions.*.recurrence_id' => 'min:1,max:255|nullable', 'transactions.*.recurrence_id' => 'min:1|max:255|nullable',
'transactions.*.bunq_payment_id' => 'min:1,max:255|nullable', 'transactions.*.bunq_payment_id' => 'min:1|max:255|nullable',
'transactions.*.external_url' => 'min:1,max:255|nullable|url', 'transactions.*.external_url' => 'min:1|max:255|nullable|url',
// SEPA fields: // SEPA fields:
'transactions.*.sepa_cc' => 'min:1,max:255|nullable', 'transactions.*.sepa_cc' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_op' => 'min:1,max:255|nullable', 'transactions.*.sepa_ct_op' => 'min:1|max:255|nullable',
'transactions.*.sepa_ct_id' => 'min:1,max:255|nullable', 'transactions.*.sepa_ct_id' => 'min:1|max:255|nullable',
'transactions.*.sepa_db' => 'min:1,max:255|nullable', 'transactions.*.sepa_db' => 'min:1|max:255|nullable',
'transactions.*.sepa_country' => 'min:1,max:255|nullable', 'transactions.*.sepa_country' => 'min:1|max:255|nullable',
'transactions.*.sepa_ep' => 'min:1,max:255|nullable', 'transactions.*.sepa_ep' => 'min:1|max:255|nullable',
'transactions.*.sepa_ci' => 'min:1,max:255|nullable', 'transactions.*.sepa_ci' => 'min:1|max:255|nullable',
'transactions.*.sepa_batch_id' => 'min:1,max:255|nullable', 'transactions.*.sepa_batch_id' => 'min:1|max:255|nullable',
// dates // dates
'transactions.*.interest_date' => 'date|nullable', 'transactions.*.interest_date' => 'date|nullable',
@@ -398,6 +403,7 @@ class UpdateRequest extends FormRequest
*/ */
public function withValidator(Validator $validator): void public function withValidator(Validator $validator): void
{ {
Log::debug('Now in withValidator');
/** @var TransactionGroup $transactionGroup */ /** @var TransactionGroup $transactionGroup */
$transactionGroup = $this->route()->parameter('transactionGroup'); $transactionGroup = $this->route()->parameter('transactionGroup');
$validator->after( $validator->after(

View File

@@ -75,7 +75,7 @@ class StoreRequest extends FormRequest
'name' => 'required|between:1,255|unique:transaction_currencies,name', 'name' => 'required|between:1,255|unique:transaction_currencies,name',
'code' => 'required|between:3,51|unique:transaction_currencies,code', 'code' => 'required|between:3,51|unique:transaction_currencies,code',
'symbol' => 'required|between:1,51|unique:transaction_currencies,symbol', 'symbol' => 'required|between:1,51|unique:transaction_currencies,symbol',
'decimal_places' => 'between:0,20|numeric|min:0|max:20', 'decimal_places' => 'between:0,20|numeric|min:0|max:12',
'enabled' => [new IsBoolean()], 'enabled' => [new IsBoolean()],
'default' => [new IsBoolean()], 'default' => [new IsBoolean()],

View File

@@ -74,7 +74,7 @@ class UpdateRequest extends FormRequest
'name' => sprintf('between:1,255|unique:transaction_currencies,name,%d', $currency->id), 'name' => sprintf('between:1,255|unique:transaction_currencies,name,%d', $currency->id),
'code' => sprintf('between:3,51|unique:transaction_currencies,code,%d', $currency->id), 'code' => sprintf('between:3,51|unique:transaction_currencies,code,%d', $currency->id),
'symbol' => sprintf('between:1,51|unique:transaction_currencies,symbol,%d', $currency->id), 'symbol' => sprintf('between:1,51|unique:transaction_currencies,symbol,%d', $currency->id),
'decimal_places' => 'between:0,20|numeric|min:0|max:20', 'decimal_places' => 'between:0,20|numeric|min:0|max:12',
'enabled' => [new IsBoolean()], 'enabled' => [new IsBoolean()],
'default' => [new IsBoolean()], 'default' => [new IsBoolean()],
]; ];

View File

@@ -59,9 +59,9 @@ class StoreRequest extends FormRequest
public function rules(): array public function rules(): array
{ {
return [ return [
'name' => 'required|unique:link_types,name|min:1', 'name' => 'required|unique:link_types,name|min:1|max:1024',
'outward' => 'required|unique:link_types,outward|min:1|different:inward', 'outward' => 'required|unique:link_types,outward|min:1|different:inward|max:1024',
'inward' => 'required|unique:link_types,inward|min:1|different:outward', 'inward' => 'required|unique:link_types,inward|min:1|different:outward|max:1024',
]; ];
} }
} }

View File

@@ -64,9 +64,9 @@ class UpdateRequest extends FormRequest
$linkType = $this->route()->parameter('linkType'); $linkType = $this->route()->parameter('linkType');
return [ return [
'name' => [Rule::unique('link_types', 'name')->ignore($linkType->id), 'min:1'], 'name' => [Rule::unique('link_types', 'name')->ignore($linkType->id), 'min:1','max:1024'],
'outward' => ['different:inward', Rule::unique('link_types', 'outward')->ignore($linkType->id), 'min:1'], 'outward' => ['different:inward', Rule::unique('link_types', 'outward')->ignore($linkType->id), 'min:1','max:1024'],
'inward' => ['different:outward', Rule::unique('link_types', 'inward')->ignore($linkType->id), 'min:1'], 'inward' => ['different:outward', Rule::unique('link_types', 'inward')->ignore($linkType->id), 'min:1','max:1024'],
]; ];
} }
} }

View File

@@ -0,0 +1,263 @@
<?php
/*
* CorrectAmounts.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\AutoBudget;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\Bill;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\RuleTrigger;
use Illuminate\Console\Command;
/**
* Class ReportSkeleton
*/
class CorrectAmounts extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'This command makes sure positive and negative amounts are recorded correctly.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:fix-amount-pos-neg';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
// auto budgets must be positive
$this->fixAutoBudgets();
// available budgets must be positive
$this->fixAvailableBudgets();
// bills must be positive (both amounts)
$this->fixBills();
// budget limits must be positive
$this->fixBudgetLimits();
// currency_exchange_rates must be positive
$this->fixExchangeRates();
// piggy_bank_repetitions must be positive
$this->fixRepetitions();
// piggy_banks must be positive
$this->fixPiggyBanks();
// recurrences_transactions amount must be positive
$this->fixRecurrences();
// rule_triggers must be positive or zero (amount_less, amount_more, amount_is)
$this->fixRuleTriggers();
return 0;
}
/**
* @return void
*/
private function fixAutoBudgets(): void
{
$set = AutoBudget::where('amount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->info('Correct: All auto budget amounts are positive.');
return;
}
/** @var AutoBudget $item */
foreach ($set as $item) {
$item->amount = app('steam')->positive((string)$item->amount);
$item->save();
}
$this->line(sprintf('Corrected %d auto budget amount(s).', $count));
}
/**
* @return void
*/
private function fixAvailableBudgets(): void
{
$set = AvailableBudget::where('amount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->info('Correct: All available budget amounts are positive.');
return;
}
/** @var AvailableBudget $item */
foreach ($set as $item) {
$item->amount = app('steam')->positive((string)$item->amount);
$item->save();
}
$this->line(sprintf('Corrected %d available budget amount(s).', $count));
}
/**
* @return void
*/
private function fixBills(): void
{
$set = Bill::where('amount_min', '<', 0)->orWhere('amount_max', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->info('Correct: All bill amounts are positive.');
return;
}
/** @var Bill $item */
foreach ($set as $item) {
$item->amount_min = app('steam')->positive((string)$item->amount_min);
$item->amount_max = app('steam')->positive((string)$item->amount_max);
$item->save();
}
}
/**
* @return void
*/
private function fixBudgetLimits(): void
{
$set = BudgetLimit::where('amount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->info('Correct: All budget limit amounts are positive.');
return;
}
/** @var BudgetLimit $item */
foreach ($set as $item) {
$item->amount = app('steam')->positive((string)$item->amount);
$item->save();
}
$this->line(sprintf('Corrected %d budget limit amount(s).', $count));
}
/**
* @return void
*/
private function fixExchangeRates(): void
{
$set = CurrencyExchangeRate::where('rate', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->info('Correct: All currency exchange rates are positive.');
return;
}
/** @var BudgetLimit $item */
foreach ($set as $item) {
$item->rate = app('steam')->positive((string)$item->rate);
$item->save();
}
$this->line(sprintf('Corrected %d currency exchange rate(s).', $count));
}
/**
* @return void
*/
private function fixRepetitions(): void
{
$set = PiggyBankRepetition::where('currentamount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->info('Correct: All piggy bank repetition amounts are positive.');
return;
}
/** @var PiggyBankRepetition $item */
foreach ($set as $item) {
$item->currentamount = app('steam')->positive((string)$item->currentamount);
$item->save();
}
$this->line(sprintf('Corrected %d piggy bank repetition amount(s).', $count));
}
/**
* @return void
*/
private function fixPiggyBanks(): void
{
$set = PiggyBank::where('targetamount', '<', 0)->get();
$count = $set->count();
if (0 === $count) {
$this->info('Correct: All piggy bank amounts are positive.');
return;
}
/** @var PiggyBankRepetition $item */
foreach ($set as $item) {
$item->targetamount = app('steam')->positive((string)$item->targetamount);
$item->save();
}
$this->line(sprintf('Corrected %d piggy bank amount(s).', $count));
}
/**
* @return void
*/
private function fixRecurrences(): void
{
$set = RecurrenceTransaction::where('amount', '<', 0)
->orWhere('foreign_amount', '<', 0)
->get();
$count = $set->count();
if (0 === $count) {
$this->info('Correct: All recurring transaction amounts are positive.');
return;
}
/** @var PiggyBankRepetition $item */
foreach ($set as $item) {
$item->amount = app('steam')->positive((string)$item->amount);
$item->foreign_amount = app('steam')->positive((string)$item->foreign_amount);
$item->save();
}
$this->line(sprintf('Corrected %d recurring transaction amount(s).', $count));
}
/**
* @return void
*/
private function fixRuleTriggers(): void
{
$set = RuleTrigger::whereIn('trigger_type', ['amount_less', 'amount_more', 'amount_is'])->get();
$fixed = 0;
/** @var RuleTrigger $item */
foreach ($set as $item) {
// basic check:
if (-1 === bccomp((string)$item->trigger_value, '0')) {
$fixed++;
$item->trigger_value = app('steam')->positive((string)$item->trigger_value);
$item->save();
}
}
if (0 === $fixed) {
$this->info('Correct: All rule trigger amounts are positive.');
return;
}
$this->line(sprintf('Corrected %d rule trigger amount(s).', $fixed));
}
}

View File

@@ -52,8 +52,10 @@ class CorrectDatabase extends Command
*/ */
public function handle(): int public function handle(): int
{ {
$this->line('Handle Firefly III database correction commands.');
// if table does not exist, return false // if table does not exist, return false
if (!Schema::hasTable('users')) { if (!Schema::hasTable('users')) {
$this->error('No "users"-table, will not continue.');
return 1; return 1;
} }
$commands = [ $commands = [
@@ -61,7 +63,7 @@ class CorrectDatabase extends Command
'firefly-iii:create-link-types', 'firefly-iii:create-link-types',
'firefly-iii:create-access-tokens', 'firefly-iii:create-access-tokens',
'firefly-iii:remove-bills', 'firefly-iii:remove-bills',
'firefly-iii:fix-negative-limits', 'firefly-iii:fix-amount-pos-neg',
'firefly-iii:enable-currencies', 'firefly-iii:enable-currencies',
'firefly-iii:fix-transfer-budgets', 'firefly-iii:fix-transfer-budgets',
'firefly-iii:fix-uneven-amount', 'firefly-iii:fix-uneven-amount',
@@ -76,16 +78,16 @@ class CorrectDatabase extends Command
'firefly-iii:fix-ob-currencies', 'firefly-iii:fix-ob-currencies',
'firefly-iii:fix-long-descriptions', 'firefly-iii:fix-long-descriptions',
'firefly-iii:fix-recurring-transactions', 'firefly-iii:fix-recurring-transactions',
'firefly-iii:restore-oauth-keys',
'firefly-iii:upgrade-group-information', 'firefly-iii:upgrade-group-information',
'firefly-iii:fix-transaction-types', 'firefly-iii:fix-transaction-types',
'firefly-iii:fix-frontpage-accounts', 'firefly-iii:fix-frontpage-accounts',
// new!
'firefly-iii:unify-group-accounts',
'firefly-iii:trigger-credit-recalculation'
]; ];
foreach ($commands as $command) { foreach ($commands as $command) {
$this->line(sprintf('Now executing %s', $command)); $this->line(sprintf('Now executing command "%s"', $command));
Artisan::call($command); $this->call($command);
$result = Artisan::output();
echo $result;
} }
return 0; return 0;

View File

@@ -1,67 +0,0 @@
<?php
/*
* FixBudgetLimits.php
* Copyright (c) 2022 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction;
use DB;
use FireflyIII\Models\BudgetLimit;
use Illuminate\Console\Command;
/**
* Class CorrectionSkeleton
*/
class FixBudgetLimits extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Fixes negative budget limits';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:fix-negative-limits';
/**
* Execute the console command.
*
* @return int
*/
public function handle(): int
{
$set = BudgetLimit::where('amount', '<', '0')->get();
if (0 === $set->count()) {
$this->info('All budget limits are OK.');
return 0;
}
$count = BudgetLimit::where('amount', '<', '0')->update(['amount' => DB::raw('amount * -1')]);
$this->info(sprintf('Fixed %d budget limit(s)', $count));
return 0;
}
}

View File

@@ -25,7 +25,9 @@ declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Collection;
/** /**
* Class FixIbans * Class FixIbans
@@ -53,6 +55,52 @@ class FixIbans extends Command
public function handle(): int public function handle(): int
{ {
$accounts = Account::whereNotNull('iban')->get(); $accounts = Account::whereNotNull('iban')->get();
$this->filterIbans($accounts);
$this->countAndCorrectIbans($accounts);
return 0;
}
/**
* @param Collection $accounts
* @return void
*/
private function countAndCorrectIbans(Collection $accounts): void
{
$set = [];
/** @var Account $account */
foreach($accounts as $account) {
$userId = (int)$account->user_id;
$set[$userId] = $set[$userId] ?? [];
$iban = (string)$account->iban;
$type = $account->accountType->type;
if(in_array($type, [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], true)) {
$type = 'liabilities';
}
if(array_key_exists($iban, $set[$userId])) {
// iban already in use! two exceptions exist:
if(
!(AccountType::EXPENSE === $set[$userId][$iban] && AccountType::REVENUE === $type) && // allowed combination
!(AccountType::REVENUE === $set[$userId][$iban] && AccountType::EXPENSE === $type) // also allowed combination.
) {
$this->line(sprintf('IBAN "%s" is used more than once and will be removed from %s #%d ("%s")', $iban, $account->accountType->type, $account->id, $account->name));
$account->iban = null;
$account->save();
}
}
if(!array_key_exists($iban, $set[$userId])) {
$set[$userId][$iban] = $type;
}
}
}
/**
* @param Collection $accounts
* @return void
*/
private function filterIbans(Collection $accounts): void
{
/** @var Account $account */ /** @var Account $account */
foreach ($accounts as $account) { foreach ($accounts as $account) {
$iban = $account->iban; $iban = $account->iban;
@@ -65,7 +113,5 @@ class FixIbans extends Command
} }
} }
} }
return 0;
} }
} }

View File

@@ -57,14 +57,15 @@ class ReportIntegrity extends Command
return 1; return 1;
} }
$commands = [ $commands = [
'firefly-iii:create-group-memberships',
'firefly-iii:report-empty-objects', 'firefly-iii:report-empty-objects',
'firefly-iii:report-sum', 'firefly-iii:report-sum',
'firefly-iii:restore-oauth-keys',
'firefly-iii:upgrade-group-information'
]; ];
foreach ($commands as $command) { foreach ($commands as $command) {
$this->line(sprintf('Now executing %s', $command)); $this->line(sprintf('Now executing %s', $command));
Artisan::call($command); $this->call($command);
$result = Artisan::output();
echo $result;
} }
return 0; return 0;

View File

@@ -1,8 +1,8 @@
<?php <?php
/** /*
* CreateDatabase.php * CreateDatabase.php
* Copyright (c) 2020 james@firefly-iii.org * Copyright (c) 2023 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
* *
@@ -22,7 +22,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace FireflyIII\Console\Commands; namespace FireflyIII\Console\Commands\System;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use PDO; use PDO;

View File

@@ -2,7 +2,7 @@
/* /*
* CreateFirstUser.php * CreateFirstUser.php
* Copyright (c) 2021 james@firefly-iii.org * Copyright (c) 2023 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
* *
@@ -22,7 +22,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace FireflyIII\Console\Commands; namespace FireflyIII\Console\Commands\System;
use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface;
use Illuminate\Console\Command; use Illuminate\Console\Command;

View File

@@ -0,0 +1,107 @@
<?php
/*
* ForceDecimalSize.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands\System;
use FireflyIII\Console\Commands\VerifiesAccessToken;
use FireflyIII\Exceptions\FireflyException;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
class ForceDecimalSize extends Command
{
use VerifiesAccessToken;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:force-decimal-size
{--user=1 : The user ID.}
{--token= : The user\'s access token.}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'This command resizes DECIMAL columns in MySQL or PostgreSQL.';
/**
* Execute the console command.
* @throws FireflyException
*/
public function handle(): int
{
if (!$this->verifyAccessToken()) {
$this->error('Invalid access token.');
return 1;
}
$this->error('Running this command is dangerous and can cause data loss.');
$this->error('Please do not continue.');
$question = $this->confirm('Do you want to continue?');
if (true === $question) {
$user = $this->getUser();
Log::channel('audit')->info(sprintf('User #%d ("%s") forced DECIMAL size.', $user->id, $user->email));
$this->updateDecimals();
return 0;
}
$this->line('Done!');
return 0;
}
private function updateDecimals(): void
{
$this->info('Going to force the size of DECIMAL columns. Please hold.');
$tables = [
'accounts' => ['virtual_balance'],
'auto_budgets' => ['amount'],
'available_budgets' => ['amount'],
'bills' => ['amount_min', 'amount_max'],
'budget_limits' => ['amount'],
'currency_exchange_rates' => ['rate', 'user_rate'],
'limit_repetitions' => ['amount'],
'piggy_bank_events' => ['amount'],
'piggy_bank_repetitions' => ['currentamount'],
'piggy_banks' => ['targetamount'],
'recurrences_transactions' => ['amount', 'foreign_amount'],
'transactions' => ['amount', 'foreign_amount'],
];
/**
* @var string $name
* @var array $fields
*/
foreach($tables as $name => $fields) {
/** @var string $field */
foreach($fields as $field) {
$this->line(sprintf('Updating table "%s", field "%s"...', $name, $field));
$query = sprintf('ALTER TABLE %s CHANGE COLUMN %s %s DECIMAL(32, 12);', $name, $field, $field);
DB::select($query);
sleep(1);
}
}
}
}

View File

@@ -1,9 +1,29 @@
<?php <?php
/*
* ForceMigration.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1); declare(strict_types=1);
namespace FireflyIII\Console\Commands; namespace FireflyIII\Console\Commands\System;
use FireflyIII\Console\Commands\VerifiesAccessToken;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\Artisan;
@@ -57,6 +77,7 @@ class ForceMigration extends Command
private function forceMigration(): void private function forceMigration(): void
{ {
DB::commit();
$this->line('Dropping "migrations" table...'); $this->line('Dropping "migrations" table...');
sleep(2); sleep(2);
Schema::dropIfExists('migrations'); Schema::dropIfExists('migrations');

View File

@@ -1,7 +1,7 @@
<?php <?php
/** /*
* ScanAttachments.php * ScanAttachments.php
* Copyright (c) 2020 james@firefly-iii.org * Copyright (c) 2023 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
* *
@@ -21,7 +21,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace FireflyIII\Console\Commands; namespace FireflyIII\Console\Commands\System;
use Crypt; use Crypt;
use FireflyIII\Models\Attachment; use FireflyIII\Models\Attachment;
@@ -42,7 +42,7 @@ class ScanAttachments extends Command
* *
* @var string * @var string
*/ */
protected $description = 'Rescan all attachments and re-set the MD5 hash and mime.'; protected $description = 'Rescan all attachments and re-set the correct MD5 hash and mime.';
/** /**
* The name and signature of the console command. * The name and signature of the console command.

View File

@@ -1,8 +1,8 @@
<?php <?php
/** /*
* SetLatestVersion.php * SetLatestVersion.php
* Copyright (c) 2020 james@firefly-iii.org * Copyright (c) 2023 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
* *
@@ -22,7 +22,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace FireflyIII\Console\Commands; namespace FireflyIII\Console\Commands\System;
use Illuminate\Console\Command; use Illuminate\Console\Command;

View File

@@ -1,7 +1,7 @@
<?php <?php
/** /*
* UpgradeFireflyInstructions.php * UpgradeFireflyInstructions.php
* Copyright (c) 2020 james@firefly-iii.org * Copyright (c) 2023 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
* *
@@ -21,11 +21,13 @@
declare(strict_types=1); declare(strict_types=1);
namespace FireflyIII\Console\Commands; namespace FireflyIII\Console\Commands\System;
use FireflyIII\Support\System\GeneratesInstallationId; use FireflyIII\Support\System\GeneratesInstallationId;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use function FireflyIII\Console\Commands\str_starts_with;
/** /**
* Class UpgradeFireflyInstructions. * Class UpgradeFireflyInstructions.
* *
@@ -75,14 +77,15 @@ class UpgradeFireflyInstructions extends Command
$text = ''; $text = '';
foreach (array_keys($config) as $compare) { foreach (array_keys($config) as $compare) {
// if string starts with: // if string starts with:
if (str_starts_with($version, $compare)) { if (\str_starts_with($version, $compare)) {
$text = $config[$compare]; $text = $config[$compare];
} }
} }
$this->showLine(); $this->showLine();
$this->boxed(''); $this->boxed('');
if (null === $text) { if (null === $text || '' === $text) {
$this->boxed(sprintf('Thank you for updating to Firefly III, v%s', $version)); $this->boxed(sprintf('Thank you for updating to Firefly III, v%s', $version));
$this->boxedInfo('There are no extra upgrade instructions.'); $this->boxedInfo('There are no extra upgrade instructions.');
$this->boxed('Firefly III should be ready for use.'); $this->boxed('Firefly III should be ready for use.');
@@ -146,13 +149,13 @@ class UpgradeFireflyInstructions extends Command
$text = ''; $text = '';
foreach (array_keys($config) as $compare) { foreach (array_keys($config) as $compare) {
// if string starts with: // if string starts with:
if (str_starts_with($version, $compare)) { if (\str_starts_with($version, $compare)) {
$text = $config[$compare]; $text = $config[$compare];
} }
} }
$this->showLine(); $this->showLine();
$this->boxed(''); $this->boxed('');
if (null === $text) { if (null === $text || '' === $text) {
$this->boxed(sprintf('Thank you for installing Firefly III, v%s!', $version)); $this->boxed(sprintf('Thank you for installing Firefly III, v%s!', $version));
$this->boxedInfo('There are no extra installation instructions.'); $this->boxedInfo('There are no extra installation instructions.');
$this->boxed('Firefly III should be ready for use.'); $this->boxed('Firefly III should be ready for use.');

View File

@@ -2,7 +2,7 @@
/* /*
* VerifySecurityAlerts.php * VerifySecurityAlerts.php
* Copyright (c) 2021 james@firefly-iii.org * Copyright (c) 2023 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
* *
@@ -22,12 +22,12 @@
declare(strict_types=1); declare(strict_types=1);
namespace FireflyIII\Console\Commands; namespace FireflyIII\Console\Commands\System;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use League\Flysystem\FilesystemException;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use League\Flysystem\FilesystemException;
use Storage; use Storage;
/** /**

View File

@@ -1,8 +1,8 @@
<?php <?php
/** /*
* DecryptDatabase.php * DecryptDatabase.php
* Copyright (c) 2020 james@firefly-iii.org * Copyright (c) 2023 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
* *
@@ -22,7 +22,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace FireflyIII\Console\Commands; namespace FireflyIII\Console\Commands\Upgrade;
use Crypt; use Crypt;
use DB; use DB;
@@ -30,8 +30,8 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Contracts\Encryption\DecryptException;
use JsonException;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use JsonException;
use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface; use Psr\Container\NotFoundExceptionInterface;
use stdClass; use stdClass;

View File

@@ -2,7 +2,7 @@
/* /*
* FixPostgresSequences.php * FixPostgresSequences.php
* Copyright (c) 2021 james@firefly-iii.org * Copyright (c) 2023 james@firefly-iii.org
* *
* This file is part of Firefly III (https://github.com/firefly-iii). * This file is part of Firefly III (https://github.com/firefly-iii).
* *
@@ -22,7 +22,7 @@
declare(strict_types=1); declare(strict_types=1);
namespace FireflyIII\Console\Commands\Correction; namespace FireflyIII\Console\Commands\Upgrade;
use DB; use DB;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -76,10 +76,8 @@ class FixPostgresSequences extends Command
'category_transaction_journal', 'category_transaction_journal',
'configuration', 'configuration',
'currency_exchange_rates', 'currency_exchange_rates',
'export_jobs',
'failed_jobs', 'failed_jobs',
'group_journals', 'group_journals',
'import_jobs',
'jobs', 'jobs',
'journal_links', 'journal_links',
'journal_meta', 'journal_meta',

View File

@@ -57,7 +57,6 @@ class UpgradeDatabase extends Command
{ {
$this->callInitialCommands(); $this->callInitialCommands();
$commands = [ $commands = [
// there are 14 upgrade commands.
'firefly-iii:transaction-identifiers', 'firefly-iii:transaction-identifiers',
'firefly-iii:migrate-to-groups', 'firefly-iii:migrate-to-groups',
'firefly-iii:account-currencies', 'firefly-iii:account-currencies',
@@ -75,41 +74,7 @@ class UpgradeDatabase extends Command
'firefly-iii:migrate-recurrence-type', 'firefly-iii:migrate-recurrence-type',
'firefly-iii:upgrade-liabilities', 'firefly-iii:upgrade-liabilities',
'firefly-iii:liabilities-600', 'firefly-iii:liabilities-600',
'firefly-iii:budget-limit-periods',
// there are 16 verify commands.
'firefly-iii:fix-piggies',
'firefly-iii:create-link-types',
'firefly-iii:create-access-tokens',
'firefly-iii:remove-bills',
'firefly-iii:fix-negative-limits',
'firefly-iii:enable-currencies',
'firefly-iii:fix-transfer-budgets',
'firefly-iii:fix-uneven-amount',
'firefly-iii:delete-zero-amount',
'firefly-iii:delete-orphaned-transactions',
'firefly-iii:delete-empty-journals',
'firefly-iii:delete-empty-groups',
'firefly-iii:fix-account-types',
'firefly-iii:fix-account-order',
'firefly-iii:rename-meta-fields',
'firefly-iii:fix-ob-currencies',
'firefly-iii:fix-long-descriptions',
'firefly-iii:fix-recurring-transactions',
'firefly-iii:unify-group-accounts',
'firefly-iii:fix-transaction-types',
'firefly-iii:fix-frontpage-accounts',
'firefly-iii:fix-ibans',
'firefly-iii:create-group-memberships',
'firefly-iii:upgrade-group-information',
// two report commands
'firefly-iii:report-empty-objects',
'firefly-iii:report-sum',
'firefly-iii:restore-oauth-keys',
// instructions
'firefly:instructions update',
'firefly-iii:verify-security-alerts',
]; ];
$args = []; $args = [];
if ($this->option('force')) { if ($this->option('force')) {
@@ -117,9 +82,7 @@ class UpgradeDatabase extends Command
} }
foreach ($commands as $command) { foreach ($commands as $command) {
$this->line(sprintf('Now executing %s', $command)); $this->line(sprintf('Now executing %s', $command));
Artisan::call($command, $args); $this->call($command, $args);
$result = Artisan::output();
echo $result;
} }
// set new DB version. // set new DB version.
app('fireflyconfig')->set('db_version', (int)config('firefly.db_version')); app('fireflyconfig')->set('db_version', (int)config('firefly.db_version'));
@@ -129,22 +92,19 @@ class UpgradeDatabase extends Command
return 0; return 0;
} }
/**
* @return void
*/
private function callInitialCommands(): void private function callInitialCommands(): void
{ {
$this->line('Now seeding the database...'); $this->line('Now seeding the database...');
Artisan::call('migrate', ['--seed' => true, '--force' => true]); $this->call('migrate', ['--seed' => true, '--force' => true,'--no-interaction' => true]);
$result = Artisan::output();
echo $result;
$this->line('Fix PostgreSQL sequences.'); $this->line('Fix PostgreSQL sequences.');
Artisan::call('firefly-iii:fix-pgsql-sequences'); $this->call('firefly-iii:fix-pgsql-sequences');
$result = Artisan::output();
echo $result;
$this->line('Now decrypting the database (if necessary)...'); $this->line('Now decrypting the database (if necessary)...');
Artisan::call('firefly-iii:decrypt-all'); $this->call('firefly-iii:decrypt-all');
$result = Artisan::output();
echo $result;
$this->line('Done!'); $this->line('Done!');
} }

View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
/*
* Created.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Events\Model\BudgetLimit;
use FireflyIII\Events\Event;
use FireflyIII\Models\BudgetLimit;
use Illuminate\Queue\SerializesModels;
/**
* Class Created
*/
class Created extends Event
{
use SerializesModels;
public BudgetLimit $budgetLimit;
/**
* @param BudgetLimit $budgetLimit
*/
public function __construct(BudgetLimit $budgetLimit)
{
$this->budgetLimit = $budgetLimit;
}
}

View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
/*
* Created.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Events\Model\BudgetLimit;
use FireflyIII\Events\Event;
use FireflyIII\Models\BudgetLimit;
use Illuminate\Queue\SerializesModels;
/**
* Class Deleted
*/
class Deleted extends Event
{
use SerializesModels;
public BudgetLimit $budgetLimit;
/**
* @param BudgetLimit $budgetLimit
*/
public function __construct(BudgetLimit $budgetLimit)
{
$this->budgetLimit = $budgetLimit;
}
}

View File

@@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
/*
* Created.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Events\Model\BudgetLimit;
use FireflyIII\Events\Event;
use FireflyIII\Models\BudgetLimit;
use Illuminate\Queue\SerializesModels;
/**
* Class Updated
*/
class Updated extends Event
{
use SerializesModels;
public BudgetLimit $budgetLimit;
/**
* @param BudgetLimit $budgetLimit
*/
public function __construct(BudgetLimit $budgetLimit)
{
$this->budgetLimit = $budgetLimit;
}
}

View File

@@ -122,7 +122,7 @@ class ChartJsGenerator implements GeneratorInterface
foreach ($data as $set) { foreach ($data as $set) {
$currentSet = [ $currentSet = [
'label' => $set['label'], 'label' => $set['label'] ?? '(no label)',
'type' => $set['type'] ?? 'line', 'type' => $set['type'] ?? 'line',
'data' => array_values($set['entries']), 'data' => array_values($set['entries']),
]; ];

View File

@@ -0,0 +1,218 @@
<?php
declare(strict_types=1);
/*
* BudgetLimitHandler.php
* Copyright (c) 2023 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace FireflyIII\Handlers\Events\Model;
use FireflyIII\Events\Model\BudgetLimit\Created;
use FireflyIII\Events\Model\BudgetLimit\Deleted;
use FireflyIII\Events\Model\BudgetLimit\Updated;
use FireflyIII\Models\AvailableBudget;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use Illuminate\Support\Facades\Log;
use Spatie\Period\Boundaries;
use Spatie\Period\Period;
use Spatie\Period\Precision;
/**
* Class BudgetLimitHandler
*/
class BudgetLimitHandler
{
/**
* @param Created $event
* @return void
*/
public function created(Created $event): void
{
Log::debug(sprintf('BudgetLimitHandler::created(%s)', $event->budgetLimit->id));
$this->updateAvailableBudget($event->budgetLimit);
}
/**
* @param Updated $event
* @return void
*/
public function updated(Updated $event): void
{
Log::debug(sprintf('BudgetLimitHandler::updated(%s)', $event->budgetLimit->id));
$this->updateAvailableBudget($event->budgetLimit);
}
/**
* @param Deleted $event
* @return void
*/
public function deleted(Deleted $event): void
{
Log::debug(sprintf('BudgetLimitHandler::deleted(%s)', $event->budgetLimit->id));
$this->updateAvailableBudget($event->budgetLimit);
}
/**
* @param AvailableBudget $availableBudget
* @return void
*/
private function calculateAmount(AvailableBudget $availableBudget): void
{
$repository = app(BudgetLimitRepositoryInterface::class);
$repository->setUser($availableBudget->user);
$newAmount = '0';
$abPeriod = Period::make($availableBudget->start_date, $availableBudget->end_date, Precision::DAY());
Log::debug(
sprintf(
'Now at AB #%d, ("%s" to "%s")',
$availableBudget->id,
$availableBudget->start_date->format('Y-m-d'),
$availableBudget->end_date->format('Y-m-d')
)
);
// have to recalc everything just in case.
$set = $repository->getAllBudgetLimitsByCurrency($availableBudget->transactionCurrency, $availableBudget->start_date, $availableBudget->end_date);
Log::debug(sprintf('Found %d interesting budget limit(s).', $set->count()));
/** @var BudgetLimit $budgetLimit */
foreach ($set as $budgetLimit) {
Log::debug(
sprintf(
'Found interesting budget limit #%d ("%s" to "%s")',
$budgetLimit->id,
$budgetLimit->start_date->format('Y-m-d'),
$budgetLimit->end_date->format('Y-m-d')
)
);
// overlap in days:
$limitPeriod = Period::make(
$budgetLimit->start_date,
$budgetLimit->end_date,
precision: Precision::DAY(),
boundaries: Boundaries::EXCLUDE_NONE()
);
// if both equal eachother, amount from this BL must be added to the AB
if ($limitPeriod->equals($abPeriod)) {
$newAmount = bcadd($newAmount, $budgetLimit->amount);
}
// if budget limit period inside AB period, can be added in full.
if (!$limitPeriod->equals($abPeriod) && $abPeriod->contains($limitPeriod)) {
$newAmount = bcadd($newAmount, $budgetLimit->amount);
}
if (!$limitPeriod->equals($abPeriod) && $abPeriod->overlapsWith($limitPeriod)) {
$overlap = $abPeriod->overlap($limitPeriod);
if (null !== $overlap) {
$length = $overlap->length();
$daily = bcmul($this->getDailyAmount($budgetLimit), (string)$length);
$newAmount = bcadd($newAmount, $daily);
}
}
}
Log::debug(sprintf('Concluded new amount for this AB must be %s', $newAmount));
$availableBudget->amount = $newAmount;
$availableBudget->save();
}
/**
* @param BudgetLimit $budgetLimit
* @return string
*/
private function getDailyAmount(BudgetLimit $budgetLimit): string
{
$limitPeriod = Period::make(
$budgetLimit->start_date,
$budgetLimit->end_date,
precision: Precision::DAY(),
boundaries: Boundaries::EXCLUDE_NONE()
);
$days = $limitPeriod->length();
$amount = bcdiv((string)$budgetLimit->amount, (string)$days, 12);
Log::debug(
sprintf('Total amount for budget limit #%d is %s. Nr. of days is %d. Amount per day is %s', $budgetLimit->id, $budgetLimit->amount, $days, $amount)
);
return $amount;
}
/**
* @param BudgetLimit $budgetLimit
* @return void
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \Psr\Container\ContainerExceptionInterface
* @throws \Psr\Container\NotFoundExceptionInterface
*/
private function updateAvailableBudget(BudgetLimit $budgetLimit): void
{
Log::debug(sprintf('Now in updateAvailableBudget(#%d)', $budgetLimit->id));
// based on the view range of the user (month week quarter etc) the budget limit could
// either overlap multiple available budget periods or be contained in a single one.
// all have to be created or updated.
$viewRange = app('preferences')->get('viewRange', '1M')->data;
$start = app('navigation')->startOfPeriod($budgetLimit->start_date, $viewRange);
$end = app('navigation')->startOfPeriod($budgetLimit->end_date, $viewRange);
$end = app('navigation')->endOfPeriod($end, $viewRange);
$user = $budgetLimit->budget->user;
// limit period in total is:
$limitPeriod = Period::make($start, $end, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE());
// from the start until the end of the budget limit, need to loop!
$current = clone $start;
while ($current <= $end) {
$currentEnd = app('navigation')->endOfPeriod($current, $viewRange);
// create or find AB for this particular period, and set the amount accordingly.
/** @var AvailableBudget $availableBudget */
$availableBudget = $user->availableBudgets()->where('start_date', $current->format('Y-m-d'))->where(
'end_date',
$currentEnd->format('Y-m-d')
)->where('transaction_currency_id', $budgetLimit->transaction_currency_id)->first();
if (null !== $availableBudget) {
Log::debug('Found 1 AB, will update.');
$this->calculateAmount($availableBudget);
}
if (null === $availableBudget) {
// if not exists:
$currentPeriod = Period::make($current, $currentEnd, precision: Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE());
$daily = $this->getDailyAmount($budgetLimit);
$amount = bcmul($daily, (string)$currentPeriod->length(), 12);
// no need to calculate if period is equal.
if ($currentPeriod->equals($limitPeriod)) {
$amount = $budgetLimit->amount;
}
Log::debug(sprintf('Will create AB for period %s to %s', $current->format('Y-m-d'), $currentEnd->format('Y-m-d')));
$availableBudget = new AvailableBudget(
[
'user_id' => $budgetLimit->budget->user->id,
'transaction_currency_id' => $budgetLimit->transaction_currency_id,
'start_date' => $current,
'end_date' => $currentEnd,
'amount' => $amount,
]
);
$availableBudget->save();
}
// prep for next loop
$current = app('navigation')->addPeriod($current, $viewRange, 0);
}
}
}

View File

@@ -92,7 +92,8 @@ trait AttachmentCollection
->where( ->where(
static function (EloquentBuilder $q1) { static function (EloquentBuilder $q1) {
$q1->where('attachments.attachable_type', TransactionJournal::class); $q1->where('attachments.attachable_type', TransactionJournal::class);
//$q1->where('attachments.uploaded', true); $q1->where('attachments.uploaded', true);
$q1->whereNull('attachments.deleted_at');
$q1->orWhereNull('attachments.attachable_type'); $q1->orWhereNull('attachments.attachable_type');
} }
); );

View File

@@ -41,7 +41,6 @@ trait UpdateTrait
* 'level' => 'info' / 'success' / 'error' * 'level' => 'info' / 'success' / 'error'
* *
* @return array * @return array
* @throws FireflyException
* @throws ContainerExceptionInterface * @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface * @throws NotFoundExceptionInterface
*/ */

View File

@@ -89,12 +89,13 @@ class BudgetLimitController extends Controller
$collection = $this->currencyRepos->get(); $collection = $this->currencyRepos->get();
$budgetLimits = $this->blRepository->getBudgetLimits($budget, $start, $end); $budgetLimits = $this->blRepository->getBudgetLimits($budget, $start, $end);
// remove already budgeted currencies: // remove already budgeted currencies with the same date range
$currencies = $collection->filter( $currencies = $collection->filter(
static function (TransactionCurrency $currency) use ($budgetLimits) { static function (TransactionCurrency $currency) use ($budgetLimits, $start, $end) {
/** @var AvailableBudget $budget */ /** @var BudgetLimit $limit */
foreach ($budgetLimits as $budget) { foreach ($budgetLimits as $limit) {
if ($budget->transaction_currency_id === $currency->id) { if ($limit->transaction_currency_id === $currency->id && $limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end)
) {
return false; return false;
} }
} }

View File

@@ -40,9 +40,9 @@ use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use JsonException; use JsonException;
use Illuminate\Support\Facades\Log;
use Psr\Container\ContainerExceptionInterface; use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface; use Psr\Container\NotFoundExceptionInterface;
@@ -101,12 +101,23 @@ class IndexController extends Controller
*/ */
public function index(Request $request, Carbon $start = null, Carbon $end = null) public function index(Request $request, Carbon $start = null, Carbon $end = null)
{ {
Log::debug('Start of IndexController::index()'); Log::debug(sprintf('Start of IndexController::index("%s", "%s")', $start?->format('Y-m-d'), $end?->format('Y-m-d')));
// collect some basic vars: // collect some basic vars:
$range = app('navigation')->getViewRange(true); $range = app('navigation')->getViewRange(true);
$start = $start ?? session('start', today(config('app.timezone'))->startOfMonth()); $isCustomRange = session('is_custom_range', false);
$end = $end ?? app('navigation')->endOfPeriod($start, $range); if (false === $isCustomRange) {
$start = $start ?? session('start', today(config('app.timezone'))->startOfMonth());
$end = $end ?? app('navigation')->endOfPeriod($start, $range);
}
// overrule start and end if necessary:
if (true === $isCustomRange) {
$start = $start ?? session('start', today(config('app.timezone'))->startOfMonth());
$end = $end ?? session('end', today(config('app.timezone'))->endOfMonth());
}
$defaultCurrency = app('amount')->getDefaultCurrency(); $defaultCurrency = app('amount')->getDefaultCurrency();
$currencies = $this->currencyRepository->get(); $currencies = $this->currencyRepository->get();
$budgeted = '0'; $budgeted = '0';

View File

@@ -82,8 +82,10 @@ class BudgetController extends Controller
$percentage = '0'; $percentage = '0';
if (null !== $availableBudget) { if (null !== $availableBudget) {
$available = $availableBudget->amount; $available = $availableBudget->amount;
$percentage = bcmul(bcdiv($budgeted, $available), '100'); if (0 !== bccomp($available, '0')) {
$percentage = bcmul(bcdiv($budgeted, $available), '100');
}
} }
// if available, get the AB for this period + currency, so the bar can be redrawn. // if available, get the AB for this period + currency, so the bar can be redrawn.

View File

@@ -33,9 +33,9 @@ use FireflyIII\Support\Http\Controllers\GetConfigurationData;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use Laravel\Passport\Passport; use Laravel\Passport\Passport;
use Illuminate\Support\Facades\Log;
use phpseclib3\Crypt\RSA; use phpseclib3\Crypt\RSA;
/** /**
@@ -60,61 +60,15 @@ class InstallController extends Controller
{ {
// empty on purpose. // empty on purpose.
$this->upgradeCommands = [ $this->upgradeCommands = [
// there are 3 initial commands // there are 5 initial commands
'migrate' => ['--seed' => true, '--force' => true], // Check 4 places: InstallController, Docker image, UpgradeDatabase, composer.json
'firefly-iii:fix-pgsql-sequences' => [], 'migrate' => ['--seed' => true, '--force' => true],
'firefly-iii:decrypt-all' => [], 'generate-keys' => [], // an exception :(
'firefly-iii:restore-oauth-keys' => [], 'firefly-iii:upgrade-database' => [],
'generate-keys' => [], // an exception :( 'firefly-iii:correct-database' => [],
'firefly-iii:report-integrity' => [],
// upgrade commands 'firefly-iii:set-latest-version' => ['--james-is-cool' => true],
'firefly-iii:transaction-identifiers' => [], 'firefly-iii:verify-security-alerts' => [],
'firefly-iii:migrate-to-groups' => [],
'firefly-iii:account-currencies' => [],
'firefly-iii:transfer-currencies' => [],
'firefly-iii:other-currencies' => [],
'firefly-iii:migrate-notes' => [],
'firefly-iii:migrate-attachments' => [],
'firefly-iii:bills-to-rules' => [],
'firefly-iii:bl-currency' => [],
'firefly-iii:cc-liabilities' => [],
'firefly-iii:back-to-journals' => [],
'firefly-iii:rename-account-meta' => [],
'firefly-iii:migrate-recurrence-meta' => [],
'firefly-iii:migrate-tag-locations' => [],
'firefly-iii:migrate-recurrence-type' => [],
'firefly-iii:upgrade-liabilities' => [],
'firefly-iii:liabilities-600' => [],
// verify commands
'firefly-iii:fix-piggies' => [],
'firefly-iii:create-link-types' => [],
'firefly-iii:create-access-tokens' => [],
'firefly-iii:remove-bills' => [],
'firefly-iii:fix-negative-limits' => [],
'firefly-iii:enable-currencies' => [],
'firefly-iii:fix-transfer-budgets' => [],
'firefly-iii:fix-uneven-amount' => [],
'firefly-iii:delete-zero-amount' => [],
'firefly-iii:delete-orphaned-transactions' => [],
'firefly-iii:delete-empty-journals' => [],
'firefly-iii:delete-empty-groups' => [],
'firefly-iii:fix-account-types' => [],
'firefly-iii:fix-account-order' => [],
'firefly-iii:rename-meta-fields' => [],
'firefly-iii:fix-ob-currencies' => [],
'firefly-iii:fix-long-descriptions' => [],
'firefly-iii:fix-recurring-transactions' => [],
'firefly-iii:unify-group-accounts' => [],
'firefly-iii:fix-transaction-types' => [],
'firefly-iii:fix-frontpage-accounts' => [],
'firefly-iii:fix-ibans' => [],
'firefly-iii:create-group-memberships' => [],
'firefly-iii:upgrade-group-information' => [],
// final command to set the latest version in DB
'firefly-iii:set-latest-version' => ['--james-is-cool' => true],
'firefly-iii:verify-security-alerts' => [],
]; ];
$this->lastError = ''; $this->lastError = '';
@@ -127,6 +81,7 @@ class InstallController extends Controller
*/ */
public function index() public function index()
{ {
app('view')->share('FF_VERSION', config('firefly.version'));
// index will set FF3 version. // index will set FF3 version.
app('fireflyconfig')->set('ff3_version', (string)config('firefly.version')); app('fireflyconfig')->set('ff3_version', (string)config('firefly.version'));
@@ -147,27 +102,19 @@ class InstallController extends Controller
$response = [ $response = [
'hasNextCommand' => false, 'hasNextCommand' => false,
'done' => true, 'done' => true,
'next' => 0,
'previous' => null, 'previous' => null,
'error' => false, 'error' => false,
'errorMessage' => null, 'errorMessage' => null,
]; ];
Log::debug(sprintf('Will now run commands. Request index is %d', $requestIndex)); Log::debug(sprintf('Will now run commands. Request index is %d', $requestIndex));
$index = 0; $indexes = array_values(array_keys($this->upgradeCommands));
/** if (array_key_exists($requestIndex, $indexes)) {
* @var string $command $command = $indexes[$requestIndex];
* @var array $args $parameters = $this->upgradeCommands[$command];
*/ Log::debug(sprintf('Will now execute command "%s" with parameters', $command), $parameters);
foreach ($this->upgradeCommands as $command => $args) {
Log::debug(sprintf('Current command is "%s", index is %d', $command, $index));
if ($index < $requestIndex) {
Log::debug('Will not execute.');
$index++;
continue;
}
try { try {
$result = $this->executeCommand($command, $args); $result = $this->executeCommand($command, $parameters);
} catch (FireflyException $e) { } catch (FireflyException $e) {
Log::error($e->getMessage()); Log::error($e->getMessage());
Log::error($e->getTraceAsString()); Log::error($e->getTraceAsString());
@@ -180,15 +127,11 @@ class InstallController extends Controller
if (false === $result) { if (false === $result) {
$response['errorMessage'] = $this->lastError; $response['errorMessage'] = $this->lastError;
$response['error'] = true; $response['error'] = true;
return response()->json($response); return response()->json($response);
} }
$index++; $response['hasNextCommand'] = array_key_exists($requestIndex + 1, $indexes);
$response['hasNextCommand'] = true;
$response['previous'] = $command; $response['previous'] = $command;
} }
$response['next'] = $index;
return response()->json($response); return response()->json($response);
} }

View File

@@ -87,13 +87,10 @@ class Authenticate
*/ */
protected function authenticate($request, array $guards) protected function authenticate($request, array $guards)
{ {
Log::debug(sprintf('Now in %s', __METHOD__));
if (0 === count($guards)) { if (0 === count($guards)) {
Log::debug('No guards present.');
// go for default guard: // go for default guard:
/** @noinspection PhpUndefinedMethodInspection */ /** @noinspection PhpUndefinedMethodInspection */
if ($this->auth->check()) { if ($this->auth->check()) {
Log::debug('Default guard says user is authenticated.');
// do an extra check on user object. // do an extra check on user object.
/** @noinspection PhpUndefinedMethodInspection */ /** @noinspection PhpUndefinedMethodInspection */
/** @var User $user */ /** @var User $user */
@@ -104,18 +101,13 @@ class Authenticate
/** @noinspection PhpUndefinedMethodInspection */ /** @noinspection PhpUndefinedMethodInspection */
return $this->auth->authenticate(); return $this->auth->authenticate();
} }
Log::debug('Guard array is not empty.');
foreach ($guards as $guard) { foreach ($guards as $guard) {
Log::debug(sprintf('Now in guard loop, guard is "%s"', $guard));
if ('api' !== $guard) { if ('api' !== $guard) {
Log::debug('Guard is "api", call authenticate()');
$this->auth->guard($guard)->authenticate(); $this->auth->guard($guard)->authenticate();
} }
$result = $this->auth->guard($guard)->check(); $result = $this->auth->guard($guard)->check();
Log::debug(sprintf('Result is %s', var_export($result, true)));
if ($result) { if ($result) {
Log::debug('Guard says user is authenticated.');
$user = $this->auth->guard($guard)->user(); $user = $this->auth->guard($guard)->user();
$this->validateBlockedUser($user, $guards); $this->validateBlockedUser($user, $guards);
// According to PHPstan the method returns void, but we'll see. // According to PHPstan the method returns void, but we'll see.
@@ -134,7 +126,6 @@ class Authenticate
*/ */
private function validateBlockedUser(?User $user, array $guards): void private function validateBlockedUser(?User $user, array $guards): void
{ {
Log::debug(sprintf('Now in %s', __METHOD__));
if (null === $user) { if (null === $user) {
Log::warning('User is null, throw exception?'); Log::warning('User is null, throw exception?');
} }

View File

@@ -110,7 +110,7 @@ class AccountFormRequest extends FormRequest
$ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes'))); $ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes')));
$rules = [ $rules = [
'administration_id' => 'min:1|max:16777216|numeric', 'administration_id' => 'min:1|max:16777216|numeric',
'name' => 'required|min:1|uniqueAccountForUser', 'name' => 'required|max:1024|min:1|uniqueAccountForUser',
'opening_balance' => 'numeric|nullable|max:1000000000', 'opening_balance' => 'numeric|nullable|max:1000000000',
'opening_balance_date' => 'date|required_with:opening_balance|nullable', 'opening_balance_date' => 'date|required_with:opening_balance|nullable',
'iban' => ['iban', 'nullable', new UniqueIban(null, $this->convertString('objectType'))], 'iban' => ['iban', 'nullable', new UniqueIban(null, $this->convertString('objectType'))],
@@ -133,7 +133,7 @@ class AccountFormRequest extends FormRequest
if (null !== $account) { if (null !== $account) {
// add rules: // add rules:
$rules['id'] = 'belongsToUser:accounts'; $rules['id'] = 'belongsToUser:accounts';
$rules['name'] = 'required|min:1|uniqueAccountForUser:'.$account->id; $rules['name'] = 'required|max:1024|min:1|uniqueAccountForUser:'.$account->id;
$rules['iban'] = ['iban', 'nullable', new UniqueIban($account, $account->accountType->type)]; $rules['iban'] = ['iban', 'nullable', new UniqueIban($account, $account->accountType->type)];
} }

View File

@@ -81,6 +81,7 @@ class BillUpdateRequest extends FormRequest
'repeat_freq' => sprintf('required|in:%s', join(',', config('firefly.bill_periods'))), 'repeat_freq' => sprintf('required|in:%s', join(',', config('firefly.bill_periods'))),
'skip' => 'required|integer|gte:0|lte:31', 'skip' => 'required|integer|gte:0|lte:31',
'active' => 'boolean', 'active' => 'boolean',
'notes' => 'between:1,65536|nullable',
]; ];
} }
} }

View File

@@ -43,7 +43,7 @@ class LinkTypeFormRequest extends FormRequest
public function rules(): array public function rules(): array
{ {
// fixed // fixed
$nameRule = 'required|min:1|unique:link_types,name'; $nameRule = 'required|max:255|min:1|unique:link_types,name';
$idRule = ''; $idRule = '';
// get parameter link: // get parameter link:
@@ -51,14 +51,14 @@ class LinkTypeFormRequest extends FormRequest
if (null !== $link) { if (null !== $link) {
$idRule = 'exists:link_types,id'; $idRule = 'exists:link_types,id';
$nameRule = 'required|min:1'; $nameRule = 'required|max:255|min:1';
} }
return [ return [
'id' => $idRule, 'id' => $idRule,
'name' => $nameRule, 'name' => $nameRule,
'inward' => 'required|min:1|different:outward', 'inward' => 'required|max:255|min:1|different:outward',
'outward' => 'required|min:1|different:inward', 'outward' => 'required|max:255|min:1|different:inward',
]; ];
} }
} }

View File

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

View File

@@ -70,7 +70,7 @@ class PiggyBankUpdateRequest extends FormRequest
'targetamount' => 'nullable|numeric|max:1000000000', 'targetamount' => 'nullable|numeric|max:1000000000',
'startdate' => 'date', 'startdate' => 'date',
'targetdate' => 'date|nullable', 'targetdate' => 'date|nullable',
'order' => 'integer|min:1', 'order' => 'integer|max:65536|min:1',
'object_group' => 'min:0|max:255', 'object_group' => 'min:0|max:255',
]; ];
} }

View File

@@ -157,9 +157,9 @@ class RuleFormRequest extends FormRequest
'rule_group_id' => 'required|belongsToUser:rule_groups', 'rule_group_id' => 'required|belongsToUser:rule_groups',
'trigger' => 'required|in:store-journal,update-journal', 'trigger' => 'required|in:store-journal,update-journal',
'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), 'triggers.*.type' => 'required|in:'.implode(',', $validTriggers),
'triggers.*.value' => sprintf('required_if:triggers.*.type,%s|min:1|ruleTriggerValue', $contextTriggers), 'triggers.*.value' => sprintf('required_if:triggers.*.type,%s|max:1024|min:1|ruleTriggerValue', $contextTriggers),
'actions.*.type' => 'required|in:'.implode(',', $validActions), 'actions.*.type' => 'required|in:'.implode(',', $validActions),
'actions.*.value' => sprintf('required_if:actions.*.type,%s|min:0|max:255|ruleActionValue', $contextActions), 'actions.*.value' => sprintf('required_if:actions.*.type,%s|min:0|max:1024|ruleActionValue', $contextActions),
'strict' => 'in:0,1', 'strict' => 'in:0,1',
]; ];

View File

@@ -66,17 +66,18 @@ class TagFormRequest extends FormRequest
/** @var Tag $tag */ /** @var Tag $tag */
$tag = $this->route()->parameter('tag'); $tag = $this->route()->parameter('tag');
$tagRule = 'required|min:1|uniqueObjectForUser:tags,tag'; $tagRule = 'required|max:1024|min:1|uniqueObjectForUser:tags,tag';
if (null !== $tag) { if (null !== $tag) {
$idRule = 'belongsToUser:tags'; $idRule = 'belongsToUser:tags';
$tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,'.$tag->id; $tagRule = 'required|max:1024|min:1|uniqueObjectForUser:tags,tag,'.$tag->id;
} }
$rules = [ $rules = [
'tag' => $tagRule, 'tag' => $tagRule,
'id' => $idRule, 'id' => $idRule,
'description' => 'min:1|nullable', 'description' => 'max:65536|min:1|nullable',
'date' => 'date|nullable', 'date' => 'date|nullable',
]; ];
return Location::requestRules($rules); return Location::requestRules($rules);

View File

@@ -49,8 +49,8 @@ class TestRuleFormRequest extends FormRequest
$validTriggers = $this->getTriggers(); $validTriggers = $this->getTriggers();
return [ return [
'rule-trigger.*' => 'required|min:1|in:'.implode(',', $validTriggers), 'rule-trigger.*' => 'required|max:1024|min:1|in:'.implode(',', $validTriggers),
'rule-trigger-value.*' => 'required|min:1|ruleTriggerValue', 'rule-trigger-value.*' => 'required|max:1024|min:1|ruleTriggerValue',
]; ];
} }
} }

View File

@@ -24,6 +24,9 @@ declare(strict_types=1);
namespace FireflyIII\Models; namespace FireflyIII\Models;
use Eloquent; use Eloquent;
use FireflyIII\Events\Model\BudgetLimit\Created;
use FireflyIII\Events\Model\BudgetLimit\Deleted;
use FireflyIII\Events\Model\BudgetLimit\Updated;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@@ -81,6 +84,12 @@ class BudgetLimit extends Model
/** @var array Fields that can be filled */ /** @var array Fields that can be filled */
protected $fillable = ['budget_id', 'start_date', 'end_date', 'amount', 'transaction_currency_id']; protected $fillable = ['budget_id', 'start_date', 'end_date', 'amount', 'transaction_currency_id'];
protected $dispatchesEvents = [
'created' => Created::class,
'updated' => Updated::class,
'deleted' => Deleted::class,
];
/** /**
* Route binder. Converts the key in the URL to the specified object (or throw 404). * Route binder. Converts the key in the URL to the specified object (or throw 404).
* *

View File

@@ -52,6 +52,8 @@ use Illuminate\Support\Carbon;
* @property-read Collection<int, \FireflyIII\Models\Account> $accounts * @property-read Collection<int, \FireflyIII\Models\Account> $accounts
* @property-read int|null $accounts_count * @property-read int|null $accounts_count
* @property-read Collection<int, \FireflyIII\Models\Account> $accounts * @property-read Collection<int, \FireflyIII\Models\Account> $accounts
* @property-read Collection<int, \FireflyIII\Models\Account> $accounts
* @property-read Collection<int, \FireflyIII\Models\Account> $accounts
* @mixin Eloquent * @mixin Eloquent
*/ */
class UserGroup extends Model class UserGroup extends Model

View File

@@ -29,6 +29,9 @@ use FireflyIII\Events\AdminRequestedTestMessage;
use FireflyIII\Events\ChangedPiggyBankAmount; use FireflyIII\Events\ChangedPiggyBankAmount;
use FireflyIII\Events\DestroyedTransactionGroup; use FireflyIII\Events\DestroyedTransactionGroup;
use FireflyIII\Events\DetectedNewIPAddress; use FireflyIII\Events\DetectedNewIPAddress;
use FireflyIII\Events\Model\BudgetLimit\Created;
use FireflyIII\Events\Model\BudgetLimit\Deleted;
use FireflyIII\Events\Model\BudgetLimit\Updated;
use FireflyIII\Events\NewVersionAvailable; use FireflyIII\Events\NewVersionAvailable;
use FireflyIII\Events\RegisteredUser; use FireflyIII\Events\RegisteredUser;
use FireflyIII\Events\RequestedNewPassword; use FireflyIII\Events\RequestedNewPassword;
@@ -42,6 +45,7 @@ use FireflyIII\Events\UpdatedAccount;
use FireflyIII\Events\UpdatedTransactionGroup; use FireflyIII\Events\UpdatedTransactionGroup;
use FireflyIII\Events\UserChangedEmail; use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Events\WarnUserAboutBill; use FireflyIII\Events\WarnUserAboutBill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition; use FireflyIII\Models\PiggyBankRepetition;
@@ -160,6 +164,17 @@ class EventServiceProvider extends ServiceProvider
ChangedPiggyBankAmount::class => [ ChangedPiggyBankAmount::class => [
'FireflyIII\Handlers\Events\PiggyBankEventHandler@changePiggyAmount', 'FireflyIII\Handlers\Events\PiggyBankEventHandler@changePiggyAmount',
], ],
// budget related events: CRUD budget limit
Created::class => [
'FireflyIII\Handlers\Events\Model\BudgetLimitHandler@created',
],
Updated::class => [
'FireflyIII\Handlers\Events\Model\BudgetLimitHandler@updated',
],
Deleted::class => [
'FireflyIII\Handlers\Events\Model\BudgetLimitHandler@deleted',
],
]; ];
/** /**
@@ -169,7 +184,6 @@ class EventServiceProvider extends ServiceProvider
{ {
parent::boot(); parent::boot();
$this->registerCreateEvents(); $this->registerCreateEvents();
$this->registerBudgetEvents();
} }
/** /**
@@ -188,57 +202,4 @@ class EventServiceProvider extends ServiceProvider
} }
); );
} }
/**
* TODO needs a dedicated method.
*/
protected function registerBudgetEvents(): void
{
$func = static function (BudgetLimit $limit) {
Log::debug('Trigger budget limit event.');
// find available budget with same period and same currency or create it.
// then set it or add money:
$user = $limit->budget->user;
$availableBudget = $user
->availableBudgets()
->where('start_date', $limit->start_date->format('Y-m-d'))
->where('end_date', $limit->end_date->format('Y-m-d'))
->where('transaction_currency_id', $limit->transaction_currency_id)
->first();
// update!
if (null !== $availableBudget) {
$repository = app(BudgetLimitRepositoryInterface::class);
$repository->setUser($user);
$set = $repository->getAllBudgetLimitsByCurrency($limit->transactionCurrency, $limit->start_date, $limit->end_date);
$sum = (string)$set->sum('amount');
Log::debug(
sprintf(
'Because budget limit #%d had its amount changed to %s, available budget limit #%d will be updated.',
$limit->id,
$limit->amount,
$availableBudget->id
)
);
$availableBudget->amount = $sum;
$availableBudget->save();
return;
}
Log::debug('Does not exist, create it.');
// create it.
$data = [
'amount' => $limit->amount,
'start' => $limit->start_date,
'end' => $limit->end_date,
'currency_id' => $limit->transaction_currency_id,
];
$repository = app(AvailableBudgetRepositoryInterface::class);
$repository->setUser($user);
$repository->store($data);
};
BudgetLimit::created($func);
BudgetLimit::updated($func);
}
} }

View File

@@ -84,10 +84,10 @@ class AttachmentRepository implements AttachmentRepositoryInterface
if ($disk->exists($file)) { if ($disk->exists($file)) {
$encryptedContent = (string)$disk->get($file); $encryptedContent = (string)$disk->get($file);
try { try {
$unencryptedContent = Crypt::decrypt($encryptedContent); // verified $unencryptedContent = Crypt::decrypt($encryptedContent); // verified
} catch (DecryptException $e) { } catch (DecryptException $e) {
Log::debug(sprintf('Could not decrypt attachment #%d but this is fine: %s', $attachment->id, $e->getMessage()));
$unencryptedContent = $encryptedContent; $unencryptedContent = $encryptedContent;
} }
} }

View File

@@ -23,18 +23,20 @@ declare(strict_types=1);
namespace FireflyIII\Rules; namespace FireflyIII\Rules;
use Closure;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use Illuminate\Contracts\Validation\Rule; use Illuminate\Contracts\Validation\Rule;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
/** /**
* Class UniqueIban * Class UniqueIban
*/ */
class UniqueIban implements Rule class UniqueIban implements ValidationRule
{ {
private ?Account $account; private ?Account $account;
private ?string $expectedType; private array $expectedTypes;
/** /**
* Create a new rule instance. * Create a new rule instance.
@@ -45,17 +47,24 @@ class UniqueIban implements Rule
*/ */
public function __construct(?Account $account, ?string $expectedType) public function __construct(?Account $account, ?string $expectedType)
{ {
$this->account = $account; $this->account = $account;
$this->expectedType = $expectedType; $this->expectedTypes = [];
if (null === $expectedType) {
return;
}
$this->expectedTypes = [$expectedType];
// a very basic fix to make sure we get the correct account type: // a very basic fix to make sure we get the correct account type:
if ('expense' === $expectedType) { if ('expense' === $expectedType) {
$this->expectedType = AccountType::EXPENSE; $this->expectedTypes = [AccountType::EXPENSE];
} }
if ('revenue' === $expectedType) { if ('revenue' === $expectedType) {
$this->expectedType = AccountType::REVENUE; $this->expectedTypes = [AccountType::REVENUE];
} }
if ('asset' === $expectedType) { if ('asset' === $expectedType) {
$this->expectedType = AccountType::ASSET; $this->expectedTypes = [AccountType::ASSET];
}
if ('liabilities' === $expectedType) {
$this->expectedTypes = [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
} }
} }
@@ -84,7 +93,7 @@ class UniqueIban implements Rule
if (!auth()->check()) { if (!auth()->check()) {
return true; return true;
} }
if (null === $this->expectedType) { if (0 === count($this->expectedTypes)) {
return true; return true;
} }
$maxCounts = $this->getMaxOccurrences(); $maxCounts = $this->getMaxOccurrences();
@@ -95,11 +104,11 @@ class UniqueIban implements Rule
if ($count > $max) { if ($count > $max) {
Log::debug( Log::debug(
sprintf( sprintf(
'IBAN "%s" is in use with %d account(s) of type "%s", which is too much for expected type "%s"', 'IBAN "%s" is in use with %d account(s) of type "%s", which is too much for expected types "%s"',
$value, $value,
$count, $count,
$type, $type,
$this->expectedType join(', ', $this->expectedTypes)
) )
); );
@@ -120,14 +129,15 @@ class UniqueIban implements Rule
AccountType::ASSET => 0, AccountType::ASSET => 0,
AccountType::EXPENSE => 0, AccountType::EXPENSE => 0,
AccountType::REVENUE => 0, AccountType::REVENUE => 0,
'liabilities' => 0,
]; ];
if ('expense' === $this->expectedType || AccountType::EXPENSE === $this->expectedType) { if (in_array('expense', $this->expectedTypes, true) || in_array(AccountType::EXPENSE, $this->expectedTypes, true)) {
// IBAN should be unique amongst expense and asset accounts. // IBAN should be unique amongst expense and asset accounts.
// may appear once in revenue accounts // may appear once in revenue accounts
$maxCounts[AccountType::REVENUE] = 1; $maxCounts[AccountType::REVENUE] = 1;
} }
if ('revenue' === $this->expectedType || AccountType::REVENUE === $this->expectedType) { if (in_array('revenue', $this->expectedTypes, true) || in_array(AccountType::REVENUE, $this->expectedTypes, true)) {
// IBAN should be unique amongst revenue and asset accounts. // IBAN should be unique amongst revenue and asset accounts.
// may appear once in expense accounts // may appear once in expense accounts
$maxCounts[AccountType::EXPENSE] = 1; $maxCounts[AccountType::EXPENSE] = 1;
@@ -144,12 +154,16 @@ class UniqueIban implements Rule
*/ */
private function countHits(string $type, string $iban): int private function countHits(string $type, string $iban): int
{ {
$typesArray = [$type];
if ('liabilities' === $type) {
$typesArray = [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE];
}
$query $query
= auth()->user() = auth()->user()
->accounts() ->accounts()
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') ->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('accounts.iban', $iban) ->where('accounts.iban', $iban)
->where('account_types.type', $type); ->whereIn('account_types.type', $typesArray);
if (null !== $this->account) { if (null !== $this->account) {
$query->where('accounts.id', '!=', $this->account->id); $query->where('accounts.id', '!=', $this->account->id);
@@ -157,4 +171,14 @@ class UniqueIban implements Rule
return $query->count(); return $query->count();
} }
/**
* @inheritDoc
*/
public function validate(string $attribute, mixed $value, Closure $fail): void
{
if (!$this->passes($attribute, $value)) {
$fail((string)trans('validation.unique_iban_for_user'));
}
}
} }

View File

@@ -856,12 +856,12 @@ class OperatorQuerySearch implements SearchInterface
break; break;
case '-tag_is_not': case '-tag_is_not':
case 'tag_is': case 'tag_is':
$result = $this->tagRepository->searchTag($value); $result = $this->tagRepository->findByTag($value);
if ($result->count() > 0) { if (null !== $result) {
$this->collector->setTags($result); $this->collector->setTags(new Collection([$result]));
} }
// no tags found means search must result in nothing. // no tags found means search must result in nothing.
if (0 === $result->count()) { if (null === $result) {
Log::info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator)); Log::info(sprintf('No valid tags in "%s"-operator, so search will not return ANY results.', $operator));
$this->collector->findNothing(); $this->collector->findNothing();
} }

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Validation; namespace FireflyIII\Validation;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
use Illuminate\Validation\Validator; use Illuminate\Validation\Validator;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -53,6 +54,9 @@ trait GroupValidation
]; ];
/** @var array $transaction */ /** @var array $transaction */
foreach ($transactions as $index => $transaction) { foreach ($transactions as $index => $transaction) {
if(!is_array($transaction)) {
throw new FireflyException('Invalid data submitted: transaction is not array.');
}
$hasAccountInfo = false; $hasAccountInfo = false;
$hasJournalId = array_key_exists('transaction_journal_id', $transaction); $hasJournalId = array_key_exists('transaction_journal_id', $transaction);
foreach ($keys as $key) { foreach ($keys as $key) {

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Validation; namespace FireflyIII\Validation;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
@@ -30,8 +31,8 @@ use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Illuminate\Validation\Validator;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Validator;
/** /**
* Trait TransactionValidation * Trait TransactionValidation
@@ -74,19 +75,22 @@ trait TransactionValidation
*/ */
protected function getTransactionsArray(Validator $validator): array protected function getTransactionsArray(Validator $validator): array
{ {
Log::debug('Now in getTransactionsArray');
$data = $validator->getData(); $data = $validator->getData();
$transactions = $data['transactions'] ?? []; $transactions = [];
if (is_array($data) && array_key_exists('transactions', $data) && is_array($data['transactions'])) {
Log::debug('Transactions key exists and is array.');
$transactions = $data['transactions'];
}
if (is_array($data) && array_key_exists('transactions', $data) && !is_array($data['transactions'])) {
Log::debug(sprintf('Transactions key exists but is NOT array, its a %s', gettype($data['transactions'])));
}
// should be impossible to hit this:
if (!is_countable($transactions)) { if (!is_countable($transactions)) {
Log::error(sprintf('Transactions array is not countable, because its a %s', gettype($transactions))); Log::error(sprintf('Transactions array is not countable, because its a %s', gettype($transactions)));
return [];
}
// a superfluous check but you never know.
if (!is_array($transactions)) {
Log::error(sprintf('Transactions array is not an array, because its a %s', gettype($transactions)));
return []; return [];
} }
Log::debug('Returning transactions.', $transactions);
return $transactions; return $transactions;
} }
@@ -355,6 +359,9 @@ trait TransactionValidation
* @var array $transaction * @var array $transaction
*/ */
foreach ($transactions as $index => $transaction) { foreach ($transactions as $index => $transaction) {
if(!is_int($index)) {
throw new FireflyException('Invalid data submitted: transaction is not array.');
}
$this->validateSingleUpdate($validator, $index, $transaction, $transactionGroup); $this->validateSingleUpdate($validator, $index, $transaction, $transactionGroup);
} }
} }
@@ -489,10 +496,11 @@ trait TransactionValidation
*/ */
public function validateOneTransaction(Validator $validator): void public function validateOneTransaction(Validator $validator): void
{ {
Log::debug('Now in validateOneTransaction');
if ($validator->errors()->count() > 0) { if ($validator->errors()->count() > 0) {
Log::debug('Validator already has errors, so return.');
return; return;
} }
Log::debug('Now in validateOneTransaction()');
$transactions = $this->getTransactionsArray($validator); $transactions = $this->getTransactionsArray($validator);
// need at least one transaction // need at least one transaction
if (0 === count($transactions)) { if (0 === count($transactions)) {

View File

@@ -2,6 +2,39 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/). This project adheres to [Semantic Versioning](http://semver.org/).
## 6.0.9 - 2023-04-29
### Added
- Better length validation for text fields.
### Changed
- Better calculation of available budget
### Fixed
- [Issue 7377](https://github.com/firefly-iii/firefly-iii/issues/7377) Tag search was broken
- [Issue 7389](https://github.com/firefly-iii/firefly-iii/issues/7389) Bug in charts
- [Issue 7394](https://github.com/firefly-iii/firefly-iii/issues/7394) unique iban check was broken
- [Issue 7427](https://github.com/firefly-iii/firefly-iii/issues/7427) API would not accept page 18 and up.
- [Issue 7410](https://github.com/firefly-iii/firefly-iii/issues/7410) Various dark mode color fixes
- Old documentation links fixed by @mindlessroman and @noxonad!
## 6.0.8 - 2023-04-16
### Added
- [Issue 7351](https://github.com/firefly-iii/firefly-iii/issues/7351) Optional command to force the decimal size.
- [Issue 7352](https://github.com/firefly-iii/firefly-iii/issues/7352) Optional command to force the migrations.
- [Issue 7354](https://github.com/firefly-iii/firefly-iii/issues/7354) The new v3 layout will redirect to the index when unauthenticated, thanks @corcom!
### Fixed
- [Issue 7349](https://github.com/firefly-iii/firefly-iii/issues/7349) Missing tables in PostgreSQL script.
- [Issue 7358](https://github.com/firefly-iii/firefly-iii/issues/7358) Could not create liabilities with a pre-set amount.
- Fix date field in bill warning mail.
- Fix installer script.
- Remove attachment paperclip from transactions with deleted attachments.
### API
- [Issue 7347](https://github.com/firefly-iii/firefly-iii/issues/7347) API made rules would be inactive by default.
## v6.0.7 - 2023-04-09 ## v6.0.7 - 2023-04-09
### Added ### Added

View File

@@ -82,7 +82,7 @@
"ext-xml": "*", "ext-xml": "*",
"ext-xmlwriter": "*", "ext-xmlwriter": "*",
"bacon/bacon-qr-code": "2.*", "bacon/bacon-qr-code": "2.*",
"diglactic/laravel-breadcrumbs": "^8.0", "diglactic/laravel-breadcrumbs": "^8.1",
"doctrine/dbal": "3.*", "doctrine/dbal": "3.*",
"gdbots/query-parser": "^3.0", "gdbots/query-parser": "^3.0",
"guzzlehttp/guzzle": "^7.5", "guzzlehttp/guzzle": "^7.5",
@@ -104,6 +104,7 @@
"ramsey/uuid": "^4.7", "ramsey/uuid": "^4.7",
"rcrowe/twigbridge": "^0.14", "rcrowe/twigbridge": "^0.14",
"spatie/laravel-ignition": "^2", "spatie/laravel-ignition": "^2",
"spatie/period": "^2.4",
"symfony/http-client": "^6.0", "symfony/http-client": "^6.0",
"symfony/mailgun-mailer": "^6.0", "symfony/mailgun-mailer": "^6.0",
"therobfonz/laravel-mandrill-driver": "^5.0" "therobfonz/laravel-mandrill-driver": "^5.0"
@@ -114,7 +115,7 @@
"fakerphp/faker": "1.*", "fakerphp/faker": "1.*",
"filp/whoops": "2.*", "filp/whoops": "2.*",
"mockery/mockery": "1.*", "mockery/mockery": "1.*",
"nunomaduro/larastan": "^2.5", "nunomaduro/larastan": "^2.6",
"phpstan/phpstan": "^1.10", "phpstan/phpstan": "^1.10",
"phpstan/phpstan-deprecation-rules": "^1.1", "phpstan/phpstan-deprecation-rules": "^1.1",
"phpstan/phpstan-strict-rules": "^1.4", "phpstan/phpstan-strict-rules": "^1.4",
@@ -155,57 +156,17 @@
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump" "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump"
], ],
"post-update-cmd": [ "post-update-cmd": [
"@php artisan config:clear",
"@php artisan route:clear",
"@php artisan twig:clean",
"@php artisan view:clear",
"@php artisan clear-compiled",
"@php artisan cache:clear", "@php artisan cache:clear",
"@php artisan firefly-iii:fix-pgsql-sequences", "@php artisan firefly-iii:upgrade-database",
"@php artisan firefly-iii:decrypt-all", "@php artisan firefly-iii:correct-database",
"@php artisan firefly-iii:transaction-identifiers", "@php artisan firefly-iii:report-integrity",
"@php artisan firefly-iii:migrate-to-groups", "@php artisan passport:install",
"@php artisan firefly-iii:account-currencies", "@php artisan firefly:instructions update"
"@php artisan firefly-iii:transfer-currencies",
"@php artisan firefly-iii:other-currencies",
"@php artisan firefly-iii:migrate-notes",
"@php artisan firefly-iii:migrate-attachments",
"@php artisan firefly-iii:bills-to-rules",
"@php artisan firefly-iii:bl-currency",
"@php artisan firefly-iii:cc-liabilities",
"@php artisan firefly-iii:back-to-journals",
"@php artisan firefly-iii:rename-account-meta",
"@php artisan firefly-iii:migrate-recurrence-meta",
"@php artisan firefly-iii:migrate-tag-locations",
"@php artisan firefly-iii:migrate-recurrence-type",
"@php artisan firefly-iii:upgrade-liabilities",
"@php artisan firefly-iii:liabilities-600",
"@php artisan firefly-iii:fix-piggies",
"@php artisan firefly-iii:create-link-types",
"@php artisan firefly-iii:create-access-tokens",
"@php artisan firefly-iii:remove-bills",
"@php artisan firefly-iii:fix-negative-limits",
"@php artisan firefly-iii:enable-currencies",
"@php artisan firefly-iii:fix-transfer-budgets",
"@php artisan firefly-iii:fix-uneven-amount",
"@php artisan firefly-iii:delete-zero-amount",
"@php artisan firefly-iii:delete-orphaned-transactions",
"@php artisan firefly-iii:delete-empty-journals",
"@php artisan firefly-iii:delete-empty-groups",
"@php artisan firefly-iii:fix-account-types",
"@php artisan firefly-iii:fix-account-order",
"@php artisan firefly-iii:rename-meta-fields",
"@php artisan firefly-iii:fix-ob-currencies",
"@php artisan firefly-iii:fix-long-descriptions",
"@php artisan firefly-iii:fix-recurring-transactions",
"@php artisan firefly-iii:unify-group-accounts",
"@php artisan firefly-iii:fix-transaction-types",
"@php artisan firefly-iii:fix-frontpage-accounts",
"@php artisan firefly-iii:fix-ibans",
"@php artisan firefly-iii:create-group-memberships",
"@php artisan firefly-iii:report-empty-objects",
"@php artisan firefly-iii:report-sum",
"@php artisan firefly-iii:restore-oauth-keys",
"@php artisan firefly-iii:upgrade-group-information",
"@php artisan firefly-iii:set-latest-version --james-is-cool",
"@php artisan firefly:instructions update",
"@php artisan firefly-iii:verify-security-alerts",
"@php artisan passport:install"
], ],
"post-install-cmd": [ "post-install-cmd": [
"@php artisan firefly:instructions install", "@php artisan firefly:instructions install",

529
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -107,7 +107,7 @@ return [
'webhooks' => true, 'webhooks' => true,
'handle_debts' => true, 'handle_debts' => true,
], ],
'version' => '6.0.7', 'version' => '6.0.9',
'api_version' => '2.0.1', 'api_version' => '2.0.1',
'db_version' => 19, 'db_version' => 19,
@@ -879,7 +879,7 @@ return [
], ],
'can_have_virtual_amounts' => [AccountType::ASSET], 'can_have_virtual_amounts' => [AccountType::ASSET],
'can_have_opening_balance' => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], 'can_have_opening_balance' => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE],
'dynamic_creation_allowed' => [AccountType::EXPENSE, AccountType::REVENUE, AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION], 'dynamic_creation_allowed' => [AccountType::EXPENSE, AccountType::REVENUE, AccountType::INITIAL_BALANCE, AccountType::RECONCILIATION, AccountType::LIABILITY_CREDIT],
'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'], 'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'], 'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'],
'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'], 'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'],

View File

@@ -45,28 +45,32 @@ class FixNullables extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if (!Schema::hasColumn('rule_groups', 'description')) {
Schema::table( try {
'rule_groups', Schema::table(
static function (Blueprint $table) { 'rule_groups',
$table->text('description')->nullable()->change(); static function (Blueprint $table) {
} $table->text('description')->nullable()->change();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not update table: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not update table: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try { if (!Schema::hasColumn('rules', 'description')) {
Schema::table( try {
'rules', Schema::table(
static function (Blueprint $table) { 'rules',
$table->text('description')->nullable()->change(); static function (Blueprint $table) {
} $table->text('description')->nullable()->change();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -38,16 +38,18 @@ class ExpandTransactionsTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if (Schema::hasColumn('transactions', 'identifier')) {
Schema::table( try {
'transactions', Schema::table(
static function (Blueprint $table) { 'transactions',
$table->dropColumn('identifier'); static function (Blueprint $table) {
} $table->dropColumn('identifier');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not drop column "extended_status": %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column does not exist, this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not drop column "identifier": %s', $e->getMessage()));
Log::error('If the column does not exist, this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -57,16 +59,18 @@ class ExpandTransactionsTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if (!Schema::hasColumn('transactions', 'identifier')) {
Schema::table( try {
'transactions', Schema::table(
static function (Blueprint $table) { 'transactions',
$table->smallInteger('identifier', false, true)->default(0); static function (Blueprint $table) {
} $table->smallInteger('identifier', false, true)->default(0);
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -46,22 +46,24 @@ class ChangesForV410 extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasTable('notes')) {
Schema::create( try {
'notes', Schema::create(
static function (Blueprint $table) { 'notes',
$table->increments('id'); static function (Blueprint $table) {
$table->timestamps(); $table->increments('id');
$table->softDeletes(); $table->timestamps();
$table->integer('noteable_id', false, true); $table->softDeletes();
$table->string('noteable_type'); $table->integer('noteable_id', false, true);
$table->string('title')->nullable(); $table->string('noteable_type');
$table->text('text')->nullable(); $table->string('title')->nullable();
} $table->text('text')->nullable();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not create table "notes": %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error(sprintf('Could not create table "notes": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
} }
} }

View File

@@ -37,16 +37,18 @@ class ChangesForV420 extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if (Schema::hasColumn('journal_meta', 'deleted_at')) {
Schema::table( try {
'journal_meta', Schema::table(
static function (Blueprint $table) { 'journal_meta',
$table->dropSoftDeletes(); static function (Blueprint $table) {
} $table->dropSoftDeletes();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -56,16 +58,18 @@ class ChangesForV420 extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if (!Schema::hasColumn('journal_meta', 'deleted_at')) {
Schema::table( try {
'journal_meta', Schema::table(
static function (Blueprint $table) { 'journal_meta',
$table->softDeletes(); static function (Blueprint $table) {
} $table->softDeletes();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -46,26 +46,28 @@ class ChangesForV430 extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if (!Schema::hasTable('available_budgets')) {
Schema::create( try {
'available_budgets', Schema::create(
static function (Blueprint $table) { 'available_budgets',
$table->increments('id'); static function (Blueprint $table) {
$table->timestamps(); $table->increments('id');
$table->softDeletes(); $table->timestamps();
$table->integer('user_id', false, true); $table->softDeletes();
$table->integer('transaction_currency_id', false, true); $table->integer('user_id', false, true);
$table->decimal('amount', 32, 12); $table->integer('transaction_currency_id', false, true);
$table->date('start_date'); $table->decimal('amount', 32, 12);
$table->date('end_date'); $table->date('start_date');
$table->date('end_date');
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade'); $table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
} }
); );
} catch (QueryException $e) { } catch (QueryException $e) {
Log::error(sprintf('Could not create table "available_budgets": %s', $e->getMessage())); Log::error(sprintf('Could not create table "available_budgets": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
} }
} }

View File

@@ -39,65 +39,74 @@ class ChangesForV431 extends Migration
public function down(): void public function down(): void
{ {
// reinstate "repeats" and "repeat_freq". // reinstate "repeats" and "repeat_freq".
try { if (!Schema::hasColumn('budget_limits', 'repeat_freq')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
$table->string('repeat_freq', 30)->nullable(); static function (Blueprint $table) {
} $table->string('repeat_freq', 30)->nullable();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try { if (!Schema::hasColumn('budget_limits', 'repeats')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
$table->boolean('repeats')->default(0); static function (Blueprint $table) {
} $table->boolean('repeats')->default(0);
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
// change field "start_date" to "startdate" // change field "start_date" to "startdate"
try { if (Schema::hasColumn('budget_limits', 'start_date') && !Schema::hasColumn('budget_limits', 'startdate')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
$table->renameColumn('start_date', 'startdate'); static function (Blueprint $table) {
} $table->renameColumn('start_date', 'startdate');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
// remove date field "end_date" // remove date field "end_date"
try { if (Schema::hasColumn('budget_limits', 'end_date')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
$table->dropColumn('end_date'); static function (Blueprint $table) {
} $table->dropColumn('end_date');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
// remove decimal places // remove decimal places
try { if (Schema::hasColumn('transaction_currencies', 'decimal_places')) {
Schema::table( try {
'transaction_currencies', Schema::table(
static function (Blueprint $table) { 'transaction_currencies',
$table->dropColumn('decimal_places'); static function (Blueprint $table) {
} $table->dropColumn('decimal_places');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -108,66 +117,76 @@ class ChangesForV431 extends Migration
public function up(): void public function up(): void
{ {
// add decimal places to "transaction currencies". // add decimal places to "transaction currencies".
try { if (!Schema::hasColumn('transaction_currencies', 'decimal_places')) {
Schema::table( try {
'transaction_currencies', Schema::table(
static function (Blueprint $table) { 'transaction_currencies',
$table->smallInteger('decimal_places', false, true)->default(2); static function (Blueprint $table) {
} $table->smallInteger('decimal_places', false, true)->default(2);
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
// change field "startdate" to "start_date" // change field "startdate" to "start_date"
try { if (Schema::hasColumn('budget_limits', 'startdate') && !Schema::hasColumn('budget_limits', 'start_date')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
$table->renameColumn('startdate', 'start_date'); static function (Blueprint $table) {
} $table->renameColumn('startdate', 'start_date');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
// add date field "end_date" after "start_date" // add date field "end_date" after "start_date"
try { if (!Schema::hasColumn('budget_limits', 'end_date')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
$table->date('end_date')->nullable()->after('start_date'); static function (Blueprint $table) {
} $table->date('end_date')->nullable()->after('start_date');
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
// drop "repeats" and "repeat_freq". // drop "repeats" and "repeat_freq".
try { if (Schema::hasColumn('budget_limits', 'repeats')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
$table->dropColumn('repeats'); static function (Blueprint $table) {
} $table->dropColumn('repeats');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try { if (Schema::hasColumn('budget_limits', 'repeat_freq')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
$table->dropColumn('repeat_freq'); static function (Blueprint $table) {
} $table->dropColumn('repeat_freq');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -89,20 +89,21 @@ class ChangesForV440 extends Migration
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
} }
} }
if(!Schema::hasColumn('transactions', 'transaction_currency_id')) {
try { try {
Schema::table( Schema::table(
'transactions', 'transactions',
static function (Blueprint $table) { static function (Blueprint $table) {
if (!Schema::hasColumn('transactions', 'transaction_currency_id')) { if (!Schema::hasColumn('transactions', 'transaction_currency_id')) {
$table->integer('transaction_currency_id', false, true)->after('description')->nullable(); $table->integer('transaction_currency_id', false, true)->after('description')->nullable();
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null'); $table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null');
}
} }
} );
); } catch (QueryException $e) {
} catch (QueryException $e) { Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); }
} }
} }
} }

View File

@@ -39,16 +39,18 @@ class ChangesForV450 extends Migration
public function down(): void public function down(): void
{ {
// split up for sqlite compatibility // split up for sqlite compatibility
try { if(Schema::hasColumn('transactions', 'foreign_amount')) {
Schema::table( try {
'transactions', Schema::table(
static function (Blueprint $table) { 'transactions',
$table->dropColumn('foreign_amount'); static function (Blueprint $table) {
} $table->dropColumn('foreign_amount');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try { try {
@@ -65,17 +67,18 @@ class ChangesForV450 extends Migration
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
if(Schema::hasColumn('transactions', 'foreign_currency_id')) {
try { try {
Schema::table( Schema::table(
'transactions', 'transactions',
static function (Blueprint $table) { static function (Blueprint $table) {
$table->dropColumn('foreign_currency_id'); $table->dropColumn('foreign_currency_id');
} }
); );
} catch (QueryException|ColumnDoesNotExist $e) { } catch (QueryException|ColumnDoesNotExist $e) {
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -86,30 +89,34 @@ class ChangesForV450 extends Migration
public function up(): void public function up(): void
{ {
// add "foreign_amount" to transactions // add "foreign_amount" to transactions
try { if(!Schema::hasColumn('transactions', 'foreign_amount')) {
Schema::table( try {
'transactions', Schema::table(
static function (Blueprint $table) { 'transactions',
$table->decimal('foreign_amount', 32, 12)->nullable()->after('amount'); static function (Blueprint $table) {
} $table->decimal('foreign_amount', 32, 12)->nullable()->after('amount');
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
// add foreign transaction currency id to transactions (is nullable): // add foreign transaction currency id to transactions (is nullable):
try { if(!Schema::hasColumn('transactions', 'foreign_currency_id')) {
Schema::table( try {
'transactions', Schema::table(
static function (Blueprint $table) { 'transactions',
$table->integer('foreign_currency_id', false, true)->default(null)->after('foreign_amount')->nullable(); static function (Blueprint $table) {
$table->foreign('foreign_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null'); $table->integer('foreign_currency_id', false, true)->default(null)->after('foreign_amount')->nullable();
} $table->foreign('foreign_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null');
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -39,16 +39,18 @@ class ChangesForV470a extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if (Schema::hasColumn('transactions', 'reconciled')) {
Schema::table( try {
'transactions', Schema::table(
static function (Blueprint $table) { 'transactions',
$table->dropColumn('reconciled'); static function (Blueprint $table) {
} $table->dropColumn('reconciled');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -58,16 +60,18 @@ class ChangesForV470a extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if (!Schema::hasColumn('transactions', 'reconciled')) {
Schema::table( try {
'transactions', Schema::table(
static function (Blueprint $table) { 'transactions',
$table->boolean('reconciled')->after('deleted_at')->default(0); static function (Blueprint $table) {
} $table->boolean('reconciled')->after('deleted_at')->default(0);
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -47,21 +47,23 @@ class CreateOauthAuthCodesTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasTable('oauth_auth_codes')) {
Schema::create( try {
'oauth_auth_codes', Schema::create(
static function (Blueprint $table) { 'oauth_auth_codes',
$table->string('id', 100)->primary(); static function (Blueprint $table) {
$table->integer('user_id'); $table->string('id', 100)->primary();
$table->integer('client_id'); $table->integer('user_id');
$table->text('scopes')->nullable(); $table->integer('client_id');
$table->boolean('revoked'); $table->text('scopes')->nullable();
$table->dateTime('expires_at')->nullable(); $table->boolean('revoked');
} $table->dateTime('expires_at')->nullable();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not create table "oauth_auth_codes": %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error(sprintf('Could not create table "oauth_auth_codes": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
} }
} }

View File

@@ -47,23 +47,25 @@ class CreateOauthAccessTokensTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasTable('oauth_access_tokens')) {
Schema::create( try {
'oauth_access_tokens', Schema::create(
static function (Blueprint $table) { 'oauth_access_tokens',
$table->string('id', 100)->primary(); static function (Blueprint $table) {
$table->integer('user_id')->index()->nullable(); $table->string('id', 100)->primary();
$table->integer('client_id'); $table->integer('user_id')->index()->nullable();
$table->string('name')->nullable(); $table->integer('client_id');
$table->text('scopes')->nullable(); $table->string('name')->nullable();
$table->boolean('revoked'); $table->text('scopes')->nullable();
$table->timestamps(); $table->boolean('revoked');
$table->dateTime('expires_at')->nullable(); $table->timestamps();
} $table->dateTime('expires_at')->nullable();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not create table "oauth_access_tokens": %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error(sprintf('Could not create table "oauth_access_tokens": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
} }
} }

View File

@@ -47,19 +47,21 @@ class CreateOauthRefreshTokensTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasTable('oauth_refresh_tokens')) {
Schema::create( try {
'oauth_refresh_tokens', Schema::create(
static function (Blueprint $table) { 'oauth_refresh_tokens',
$table->string('id', 100)->primary(); static function (Blueprint $table) {
$table->string('access_token_id', 100)->index(); $table->string('id', 100)->primary();
$table->boolean('revoked'); $table->string('access_token_id', 100)->index();
$table->dateTime('expires_at')->nullable(); $table->boolean('revoked');
} $table->dateTime('expires_at')->nullable();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not create table "oauth_refresh_tokens": %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error(sprintf('Could not create table "oauth_refresh_tokens": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
} }
} }

View File

@@ -47,24 +47,26 @@ class CreateOauthClientsTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasTable('oauth_clients')) {
Schema::create( try {
'oauth_clients', Schema::create(
static function (Blueprint $table) { 'oauth_clients',
$table->increments('id'); static function (Blueprint $table) {
$table->integer('user_id')->index()->nullable(); $table->increments('id');
$table->string('name'); $table->integer('user_id')->index()->nullable();
$table->string('secret', 100); $table->string('name');
$table->text('redirect'); $table->string('secret', 100);
$table->boolean('personal_access_client'); $table->text('redirect');
$table->boolean('password_client'); $table->boolean('personal_access_client');
$table->boolean('revoked'); $table->boolean('password_client');
$table->timestamps(); $table->boolean('revoked');
} $table->timestamps();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not create table "oauth_clients": %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error(sprintf('Could not create table "oauth_clients": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
} }
} }

View File

@@ -47,18 +47,20 @@ class CreateOauthPersonalAccessClientsTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasTable('oauth_personal_access_clients')) {
Schema::create( try {
'oauth_personal_access_clients', Schema::create(
static function (Blueprint $table) { 'oauth_personal_access_clients',
$table->increments('id'); static function (Blueprint $table) {
$table->integer('client_id')->index(); $table->increments('id');
$table->timestamps(); $table->integer('client_id')->index();
} $table->timestamps();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not create table "oauth_personal_access_clients": %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error(sprintf('Could not create table "oauth_personal_access_clients": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
} }
} }

View File

@@ -41,28 +41,32 @@ class ChangesForV472 extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if(!Schema::hasColumn('attachments', 'notes')) {
Schema::table( try {
'attachments', Schema::table(
static function (Blueprint $table) { 'attachments',
$table->text('notes')->nullable(); static function (Blueprint $table) {
} $table->text('notes')->nullable();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try { if(Schema::hasColumn('transactions', 'order')) {
Schema::table( try {
'budgets', Schema::table(
static function (Blueprint $table) { 'budgets',
$table->dropColumn('order'); static function (Blueprint $table) {
} $table->dropColumn('order');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -73,28 +77,32 @@ class ChangesForV472 extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(Schema::hasColumn('attachments', 'notes')) {
Schema::table( try {
'attachments', Schema::table(
static function (Blueprint $table) { 'attachments',
$table->dropColumn('notes'); static function (Blueprint $table) {
} $table->dropColumn('notes');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try { if(!Schema::hasColumn('budgets', 'order')) {
Schema::table( try {
'budgets', Schema::table(
static function (Blueprint $table) { 'budgets',
$table->mediumInteger('order', false, true)->default(0); static function (Blueprint $table) {
} $table->mediumInteger('order', false, true)->default(0);
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -42,33 +42,36 @@ class ChangesForV473 extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if(!Schema::hasColumn('bills', 'transaction_currency_id')) {
Schema::table( try {
'bills', Schema::table(
static function (Blueprint $table) { 'bills',
// cannot drop foreign keys in SQLite: static function (Blueprint $table) {
if ('sqlite' !== config('database.default')) { // cannot drop foreign keys in SQLite:
$table->dropForeign('bills_transaction_currency_id_foreign'); if ('sqlite' !== config('database.default')) {
$table->dropForeign('bills_transaction_currency_id_foreign');
}
$table->dropColumn('transaction_currency_id');
} }
$table->dropColumn('transaction_currency_id'); );
} } catch (QueryException|ColumnDoesNotExist $e) {
); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
} catch (QueryException|ColumnDoesNotExist $e) { Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); }
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
if(!Schema::hasColumn('rules', 'strict')) {
try { try {
Schema::table( Schema::table(
'rules', 'rules',
static function (Blueprint $table) { static function (Blueprint $table) {
$table->dropColumn('strict'); $table->dropColumn('strict');
} }
); );
} catch (QueryException|ColumnDoesNotExist $e) { } catch (QueryException|ColumnDoesNotExist $e) {
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -79,28 +82,32 @@ class ChangesForV473 extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasColumn('bills', 'transaction_currency_id')) {
Schema::table( try {
'bills', Schema::table(
static function (Blueprint $table) { 'bills',
$table->integer('transaction_currency_id', false, true)->nullable()->after('user_id'); static function (Blueprint $table) {
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null'); $table->integer('transaction_currency_id', false, true)->nullable()->after('user_id');
} $table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null');
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try { if(!Schema::hasColumn('rules', 'strict')) {
Schema::table( try {
'rules', Schema::table(
static function (Blueprint $table) { 'rules',
$table->boolean('strict')->default(true); static function (Blueprint $table) {
} $table->boolean('strict')->default(true);
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -54,122 +54,133 @@ class ChangesForV475 extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if (!Schema::hasTable('recurrences')) {
Schema::create( try {
'recurrences', Schema::create(
static function (Blueprint $table) { 'recurrences',
$table->increments('id'); static function (Blueprint $table) {
$table->timestamps(); $table->increments('id');
$table->softDeletes(); $table->timestamps();
$table->integer('user_id', false, true); $table->softDeletes();
$table->integer('transaction_type_id', false, true); $table->integer('user_id', false, true);
$table->integer('transaction_type_id', false, true);
$table->string('title', 1024); $table->string('title', 1024);
$table->text('description'); $table->text('description');
$table->date('first_date'); $table->date('first_date');
$table->date('repeat_until')->nullable(); $table->date('repeat_until')->nullable();
$table->date('latest_date')->nullable(); $table->date('latest_date')->nullable();
$table->smallInteger('repetitions', false, true); $table->smallInteger('repetitions', false, true);
$table->boolean('apply_rules')->default(true); $table->boolean('apply_rules')->default(true);
$table->boolean('active')->default(true); $table->boolean('active')->default(true);
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->foreign('transaction_type_id')->references('id')->on('transaction_types')->onDelete('cascade'); $table->foreign('transaction_type_id')->references('id')->on('transaction_types')->onDelete('cascade');
} }
); );
} catch (QueryException $e) { } catch (QueryException $e) {
Log::error(sprintf('Could not create table "recurrences": %s', $e->getMessage())); Log::error(sprintf('Could not create table "recurrences": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
try { if (!Schema::hasTable('recurrences_transactions')) {
Schema::create( try {
'recurrences_transactions', Schema::create(
static function (Blueprint $table) { 'recurrences_transactions',
$table->increments('id'); static function (Blueprint $table) {
$table->timestamps(); $table->increments('id');
$table->softDeletes(); $table->timestamps();
$table->integer('recurrence_id', false, true); $table->softDeletes();
$table->integer('transaction_currency_id', false, true); $table->integer('recurrence_id', false, true);
$table->integer('foreign_currency_id', false, true)->nullable(); $table->integer('transaction_currency_id', false, true);
$table->integer('source_id', false, true); $table->integer('foreign_currency_id', false, true)->nullable();
$table->integer('destination_id', false, true); $table->integer('source_id', false, true);
$table->integer('destination_id', false, true);
$table->decimal('amount', 32, 12); $table->decimal('amount', 32, 12);
$table->decimal('foreign_amount', 32, 12)->nullable(); $table->decimal('foreign_amount', 32, 12)->nullable();
$table->string('description', 1024); $table->string('description', 1024);
$table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade'); $table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade');
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade'); $table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade');
$table->foreign('foreign_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null'); $table->foreign('foreign_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null');
$table->foreign('source_id')->references('id')->on('accounts')->onDelete('cascade'); $table->foreign('source_id')->references('id')->on('accounts')->onDelete('cascade');
$table->foreign('destination_id')->references('id')->on('accounts')->onDelete('cascade'); $table->foreign('destination_id')->references('id')->on('accounts')->onDelete('cascade');
} }
); );
} catch (QueryException $e) { } catch (QueryException $e) {
Log::error(sprintf('Could not create table "recurrences_transactions": %s', $e->getMessage())); Log::error(sprintf('Could not create table "recurrences_transactions": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
try { if (!Schema::hasTable('recurrences_repetitions')) {
Schema::create( try {
'recurrences_repetitions', Schema::create(
static function (Blueprint $table) { 'recurrences_repetitions',
$table->increments('id'); static function (Blueprint $table) {
$table->timestamps(); $table->increments('id');
$table->softDeletes(); $table->timestamps();
$table->integer('recurrence_id', false, true); $table->softDeletes();
$table->string('repetition_type', 50); $table->integer('recurrence_id', false, true);
$table->string('repetition_moment', 50); $table->string('repetition_type', 50);
$table->smallInteger('repetition_skip', false, true); $table->string('repetition_moment', 50);
$table->smallInteger('weekend', false, true); $table->smallInteger('repetition_skip', false, true);
$table->smallInteger('weekend', false, true);
$table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade'); $table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade');
} }
); );
} catch (QueryException $e) { } catch (QueryException $e) {
Log::error(sprintf('Could not create table "recurrences_repetitions": %s', $e->getMessage())); Log::error(sprintf('Could not create table "recurrences_repetitions": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
try { if (!Schema::hasTable('recurrences_meta')) {
Schema::create( try {
'recurrences_meta', Schema::create(
static function (Blueprint $table) { 'recurrences_meta',
$table->increments('id'); static function (Blueprint $table) {
$table->timestamps(); $table->increments('id');
$table->softDeletes(); $table->timestamps();
$table->integer('recurrence_id', false, true); $table->softDeletes();
$table->integer('recurrence_id', false, true);
$table->string('name', 50); $table->string('name', 50);
$table->text('value'); $table->text('value');
$table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade'); $table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade');
} }
); );
} catch (QueryException $e) { } catch (QueryException $e) {
Log::error(sprintf('Could not create table "recurrences_meta": %s', $e->getMessage())); Log::error(sprintf('Could not create table "recurrences_meta": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
try {
Schema::create(
'rt_meta',
static function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->softDeletes();
$table->integer('rt_id', false, true);
$table->string('name', 50); if (!Schema::hasTable('rt_meta')) {
$table->text('value'); try {
Schema::create(
'rt_meta',
static function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->softDeletes();
$table->integer('rt_id', false, true);
$table->foreign('rt_id')->references('id')->on('recurrences_transactions')->onDelete('cascade'); $table->string('name', 50);
} $table->text('value');
);
} catch (QueryException $e) { $table->foreign('rt_id')->references('id')->on('recurrences_transactions')->onDelete('cascade');
Log::error(sprintf('Could not create table "rt_meta": %s', $e->getMessage())); }
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); );
} catch (QueryException $e) {
Log::error(sprintf('Could not create table "rt_meta": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
} }
} }

View File

@@ -41,21 +41,23 @@ class ChangesForV477 extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if(Schema::hasColumn('budget_limits', 'transaction_currency_id')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
// cannot drop foreign keys in SQLite: static function (Blueprint $table) {
if ('sqlite' !== config('database.default')) { // cannot drop foreign keys in SQLite:
$table->dropForeign('budget_limits_transaction_currency_id_foreign'); if ('sqlite' !== config('database.default')) {
} $table->dropForeign('budget_limits_transaction_currency_id_foreign');
}
$table->dropColumn(['transaction_currency_id']); $table->dropColumn(['transaction_currency_id']);
} }
); );
} catch (QueryException|ColumnDoesNotExist $e) { } catch (QueryException|ColumnDoesNotExist $e) {
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -66,17 +68,19 @@ class ChangesForV477 extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasColumn('budget_limits', 'transaction_currency_id')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
$table->integer('transaction_currency_id', false, true)->nullable()->after('budget_id'); static function (Blueprint $table) {
$table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null'); $table->integer('transaction_currency_id', false, true)->nullable()->after('budget_id');
} $table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null');
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -41,16 +41,18 @@ class ChangesForV479 extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if(Schema::hasColumn('transaction_currencies', 'enabled')) {
Schema::table( try {
'transaction_currencies', Schema::table(
static function (Blueprint $table) { 'transaction_currencies',
$table->dropColumn(['enabled']); static function (Blueprint $table) {
} $table->dropColumn(['enabled']);
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -61,16 +63,18 @@ class ChangesForV479 extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasColumn('transaction_currencies', 'enabled')) {
Schema::table( try {
'transaction_currencies', Schema::table(
static function (Blueprint $table) { 'transaction_currencies',
$table->boolean('enabled')->default(0)->after('deleted_at'); static function (Blueprint $table) {
} $table->boolean('enabled')->default(0)->after('deleted_at');
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -41,16 +41,18 @@ class FixLdapConfiguration extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if(Schema::hasColumn('users', 'objectguid')) {
Schema::table( try {
'users', Schema::table(
static function (Blueprint $table) { 'users',
$table->dropColumn(['objectguid']); static function (Blueprint $table) {
} $table->dropColumn(['objectguid']);
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -65,16 +67,18 @@ class FixLdapConfiguration extends Migration
* ADLdap2 appears to require the ability to store an objectguid for LDAP users * ADLdap2 appears to require the ability to store an objectguid for LDAP users
* now. To support this, we add the column. * now. To support this, we add the column.
*/ */
try { if(!Schema::hasColumn('users', 'objectguid')) {
Schema::table( try {
'users', Schema::table(
static function (Blueprint $table) { 'users',
$table->uuid('objectguid')->nullable()->after('id'); static function (Blueprint $table) {
} $table->uuid('objectguid')->nullable()->after('id');
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -40,65 +40,74 @@ class ChangesForV480 extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { // remove group ID
Schema::table( if(Schema::hasColumn('transaction_journals', 'transaction_group_id')) {
'transaction_journals', try {
static function (Blueprint $table) { Schema::table(
// drop transaction_group_id + foreign key. 'transaction_journals',
// cannot drop foreign keys in SQLite: static function (Blueprint $table) {
if ('sqlite' !== config('database.default')) { // drop transaction_group_id + foreign key.
// cannot drop foreign keys in SQLite:
if ('sqlite' !== config('database.default')) {
try {
$table->dropForeign('transaction_journals_transaction_group_id_foreign');
} catch (QueryException $e) {
Log::error(sprintf('Could not drop foreign ID: %s', $e->getMessage()));
Log::error('If the foreign ID does not exist (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
}
try { try {
$table->dropForeign('transaction_journals_transaction_group_id_foreign'); $table->dropColumn('transaction_group_id');
} catch (QueryException $e) { } catch (QueryException|ColumnDoesNotExist $e) {
Log::error(sprintf('Could not drop foreign ID: %s', $e->getMessage())); Log::error(sprintf('Could not drop column: %s', $e->getMessage()));
Log::error('If the foreign ID does not exist (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error('If the column does not exist, this is not an problem. Otherwise, please open a GitHub discussion.');
} }
} }
try { );
$table->dropColumn('transaction_group_id'); } catch (QueryException $e) {
} catch (QueryException|ColumnDoesNotExist $e) { Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error(sprintf('Could not drop column: %s', $e->getMessage())); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
Log::error('If the column does not exist, this is not an problem. Otherwise, please open a GitHub discussion.'); }
}
}
);
} catch (QueryException $e) {
Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
try { // remove 'stop processing' column
Schema::table( if(Schema::hasColumn('rule_groups', 'stop_processing')) {
'rule_groups', try {
static function (Blueprint $table) { Schema::table(
try { 'rule_groups',
$table->dropColumn('stop_processing'); static function (Blueprint $table) {
} catch (QueryException|ColumnDoesNotExist $e) { try {
Log::error(sprintf('Could not drop column: %s', $e->getMessage())); $table->dropColumn('stop_processing');
Log::error('If the column does not exist, this is not an problem. Otherwise, please open a GitHub discussion.'); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error(sprintf('Could not drop column: %s', $e->getMessage()));
Log::error('If the column does not exist, this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} );
); } catch (QueryException $e) {
} catch (QueryException $e) { Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); }
} }
try { // remove 'mfa_secret' column
Schema::table( if(Schema::hasColumn('users', 'mfa_secret')) {
'users', try {
static function (Blueprint $table) { Schema::table(
try { 'users',
$table->dropColumn('mfa_secret'); static function (Blueprint $table) {
} catch (QueryException|ColumnDoesNotExist $e) { try {
Log::error(sprintf('Could not drop column: %s', $e->getMessage())); $table->dropColumn('mfa_secret');
Log::error('If the column does not exist, this is not an problem. Otherwise, please open a GitHub discussion.'); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error(sprintf('Could not drop column: %s', $e->getMessage()));
Log::error('If the column does not exist, this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} );
); } catch (QueryException $e) {
} catch (QueryException $e) { Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); }
} }
} }
@@ -109,52 +118,63 @@ class ChangesForV480 extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { // add currency_id
Schema::table( if(!Schema::hasColumn('transaction_journals', 'transaction_group_id')) {
'transaction_journals', try {
static function (Blueprint $table) { Schema::table(
$table->integer('transaction_currency_id', false, true)->nullable()->change(); 'transaction_journals',
static function (Blueprint $table) {
$table->integer('transaction_currency_id', false, true)->nullable()->change();
// add column "group_id" after "transaction_type_id" // add column "group_id" after "transaction_type_id"
$table->integer('transaction_group_id', false, true) $table->integer('transaction_group_id', false, true)
->nullable()->default(null)->after('transaction_type_id'); ->nullable()->default(null)->after('transaction_type_id');
// add foreign key for "transaction_group_id" // add foreign key for "transaction_group_id"
try { try {
$table->foreign('transaction_group_id')->references('id')->on('transaction_groups')->onDelete('cascade'); $table->foreign('transaction_group_id')->references('id')->on('transaction_groups')->onDelete('cascade');
} catch (QueryException $e) { } catch (QueryException $e) {
Log::error(sprintf('Could not create foreign index: %s', $e->getMessage())); Log::error(sprintf('Could not create foreign index: %s', $e->getMessage()));
Log::error( Log::error(
'If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.' 'If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'
); );
}
} }
} );
); } catch (QueryException $e) {
} catch (QueryException $e) { Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); }
} }
try {
Schema::table( // add 'stop processing' column
'rule_groups', if(!Schema::hasColumn('rule_groups', 'stop_processing')) {
static function (Blueprint $table) { try {
$table->boolean('stop_processing')->default(false); Schema::table(
} 'rule_groups',
); static function (Blueprint $table) {
} catch (QueryException $e) { $table->boolean('stop_processing')->default(false);
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); }
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); );
} catch (QueryException $e) {
Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try {
Schema::table( // add 'mfa_secret' column
'users', if(!Schema::hasColumn('users', 'mfa_secret')) {
static function (Blueprint $table) { try {
$table->string('mfa_secret', 50)->nullable(); Schema::table(
} 'users',
); static function (Blueprint $table) {
} catch (QueryException $e) { $table->string('mfa_secret', 50)->nullable();
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); }
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); );
} catch (QueryException $e) {
Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -51,25 +51,27 @@ class MakeLocationsTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if (!Schema::hasTable('locations')) {
Schema::create( try {
'locations', Schema::create(
static function (Blueprint $table) { 'locations',
$table->bigIncrements('id'); static function (Blueprint $table) {
$table->timestamps(); $table->bigIncrements('id');
$table->softDeletes(); $table->timestamps();
$table->softDeletes();
$table->integer('locatable_id', false, true); $table->integer('locatable_id', false, true);
$table->string('locatable_type', 255); $table->string('locatable_type', 255);
$table->decimal('latitude', 12, 8)->nullable(); $table->decimal('latitude', 12, 8)->nullable();
$table->decimal('longitude', 12, 8)->nullable(); $table->decimal('longitude', 12, 8)->nullable();
$table->smallInteger('zoom_level', false, true)->nullable(); $table->smallInteger('zoom_level', false, true)->nullable();
} }
); );
} catch (QueryException $e) { } catch (QueryException $e) {
Log::error(sprintf('Could not create table "locations": %s', $e->getMessage())); Log::error(sprintf('Could not create table "locations": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
} }
} }

View File

@@ -42,16 +42,18 @@ class ChangesForV530a extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if(Schema::hasColumn('bills', 'order')) {
Schema::table( try {
'bills', Schema::table(
static function (Blueprint $table) { 'bills',
$table->dropColumn('order'); static function (Blueprint $table) {
} $table->dropColumn('order');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -62,16 +64,18 @@ class ChangesForV530a extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasColumn('bills', 'order')) {
Schema::table( try {
'bills', Schema::table(
static function (Blueprint $table) { 'bills',
$table->integer('order', false, true)->default(0); static function (Blueprint $table) {
} $table->integer('order', false, true)->default(0);
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

View File

@@ -42,42 +42,47 @@ class ChangesForV540 extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if(Schema::hasColumn('oauth_clients', 'provider')) {
Schema::table( try {
'oauth_clients', Schema::table(
static function (Blueprint $table) { 'oauth_clients',
$table->dropColumn('provider'); static function (Blueprint $table) {
} $table->dropColumn('provider');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try { if(Schema::hasColumn('accounts', 'order')) {
Schema::table( try {
'accounts', Schema::table(
static function (Blueprint $table) { 'accounts',
$table->dropColumn('order'); static function (Blueprint $table) {
} $table->dropColumn('order');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
if(Schema::hasColumn('bills', 'end_date') && Schema::hasColumn('bills', 'extension_date')) {
try {
Schema::table(
'bills',
static function (Blueprint $table) {
$table->dropColumn('end_date');
try { $table->dropColumn('extension_date');
Schema::table( }
'bills', );
static function (Blueprint $table) { } catch (QueryException|ColumnDoesNotExist $e) {
$table->dropColumn('end_date'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
$table->dropColumn('extension_date'); }
}
);
} catch (QueryException|ColumnDoesNotExist $e) {
Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
} }
@@ -88,40 +93,49 @@ class ChangesForV540 extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasColumn('accounts', 'order')) {
Schema::table( try {
'accounts', Schema::table(
static function (Blueprint $table) { 'accounts',
$table->integer('order', false, true)->default(0); static function (Blueprint $table) {
} $table->integer('order', false, true)->default(0);
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try {
Schema::table( if(!Schema::hasColumn('oauth_clients', 'provider')) {
'oauth_clients', try {
static function (Blueprint $table) { Schema::table(
$table->string('provider')->nullable(); 'oauth_clients',
} static function (Blueprint $table) {
); $table->string('provider')->nullable();
} catch (QueryException $e) { }
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); );
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); } catch (QueryException $e) {
Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
try {
Schema::table( if(!Schema::hasColumn('bills', 'end_date') && !Schema::hasColumn('bills', 'extension_date')) {
'bills', try {
static function (Blueprint $table) { Schema::table(
$table->date('end_date')->nullable()->after('date'); 'bills',
$table->date('extension_date')->nullable()->after('end_date'); static function (Blueprint $table) {
} $table->date('end_date')->nullable()->after('date');
); $table->date('extension_date')->nullable()->after('end_date');
} catch (QueryException $e) { }
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); );
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); } catch (QueryException $e) {
Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
// make column nullable: // make column nullable:
try { try {
Schema::table( Schema::table(

View File

@@ -43,57 +43,65 @@ class ChangesForV550 extends Migration
// recreate jobs table. // recreate jobs table.
Schema::dropIfExists('jobs'); Schema::dropIfExists('jobs');
try { if (!Schema::hasTable('jobs')) {
Schema::create( try {
'jobs', Schema::create(
static function (Blueprint $table) { 'jobs',
// straight from Laravel (this is the OLD table) static function (Blueprint $table) {
$table->bigIncrements('id'); // straight from Laravel (this is the OLD table)
$table->string('queue'); $table->bigIncrements('id');
$table->longText('payload'); $table->string('queue');
$table->tinyInteger('attempts')->unsigned(); $table->longText('payload');
$table->tinyInteger('reserved')->unsigned(); $table->tinyInteger('attempts')->unsigned();
$table->unsignedInteger('reserved_at')->nullable(); $table->tinyInteger('reserved')->unsigned();
$table->unsignedInteger('available_at'); $table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('created_at'); $table->unsignedInteger('available_at');
$table->index(['queue', 'reserved', 'reserved_at']); $table->unsignedInteger('created_at');
} $table->index(['queue', 'reserved', 'reserved_at']);
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not create table "jobs": %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error(sprintf('Could not create table "jobs": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
// expand budget / transaction journal table. // expand budget / transaction journal table.
try { if(Schema::hasColumn('budget_transaction_journal', 'budget_limit_id')) {
Schema::table( try {
'budget_transaction_journal', Schema::table(
function (Blueprint $table) { 'budget_transaction_journal',
$table->dropForeign('budget_id_foreign'); function (Blueprint $table) {
$table->dropColumn('budget_limit_id'); $table->dropForeign('budget_id_foreign');
} $table->dropColumn('budget_limit_id');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
// drop failed jobs table. // drop failed jobs table.
Schema::dropIfExists('failed_jobs'); Schema::dropIfExists('failed_jobs');
// drop fields from budget limits // drop fields from budget limits
try { if(Schema::hasColumn('budget_limits', 'period') && Schema::hasColumn('budget_limits', 'generated')) {
Schema::table( try {
'budget_limits', Schema::table(
static function (Blueprint $table) { 'budget_limits',
$table->dropColumn('period'); static function (Blueprint $table) {
$table->dropColumn('generated'); $table->dropColumn('period');
} $table->dropColumn('generated');
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
// drop other tables
Schema::dropIfExists('webhook_attempts'); Schema::dropIfExists('webhook_attempts');
Schema::dropIfExists('webhook_messages'); Schema::dropIfExists('webhook_messages');
Schema::dropIfExists('webhooks'); Schema::dropIfExists('webhooks');
@@ -109,63 +117,70 @@ class ChangesForV550 extends Migration
// drop and recreate jobs table. // drop and recreate jobs table.
Schema::dropIfExists('jobs'); Schema::dropIfExists('jobs');
// this is the NEW table // this is the NEW table
try { if (!Schema::hasTable('jobs')) {
Schema::create( try {
'jobs', Schema::create(
function (Blueprint $table) { 'jobs',
$table->bigIncrements('id'); function (Blueprint $table) {
$table->string('queue')->index(); $table->bigIncrements('id');
$table->longText('payload'); $table->string('queue')->index();
$table->unsignedTinyInteger('attempts'); $table->longText('payload');
$table->unsignedInteger('reserved_at')->nullable(); $table->unsignedTinyInteger('attempts');
$table->unsignedInteger('available_at'); $table->unsignedInteger('reserved_at')->nullable();
$table->unsignedInteger('created_at'); $table->unsignedInteger('available_at');
} $table->unsignedInteger('created_at');
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not create table "jobs": %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error(sprintf('Could not create table "jobs": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
// drop failed jobs table. // drop failed jobs table.
Schema::dropIfExists('failed_jobs'); Schema::dropIfExists('failed_jobs');
// create new failed_jobs table. // create new failed_jobs table.
try { if (!Schema::hasTable('failed_jobs')) {
Schema::create( try {
'failed_jobs', Schema::create(
function (Blueprint $table) { 'failed_jobs',
$table->bigIncrements('id'); function (Blueprint $table) {
$table->string('uuid')->unique(); $table->bigIncrements('id');
$table->text('connection'); $table->string('uuid')->unique();
$table->text('queue'); $table->text('connection');
$table->longText('payload'); $table->text('queue');
$table->longText('exception'); $table->longText('payload');
$table->timestamp('failed_at')->useCurrent(); $table->longText('exception');
} $table->timestamp('failed_at')->useCurrent();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not create table "failed_jobs": %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.'); Log::error(sprintf('Could not create table "failed_jobs": %s', $e->getMessage()));
Log::error('If this table exists already (see the error message), this is not a problem. Other errors? Please open a discussion on GitHub.');
}
} }
// update budget / transaction journal table. // update budget / transaction journal table.
try { if(!Schema::hasColumn('budget_transaction_journal', 'budget_limit_id')) {
Schema::table( try {
'budget_transaction_journal', Schema::table(
function (Blueprint $table) { 'budget_transaction_journal',
if (!Schema::hasColumn('budget_transaction_journal', 'budget_limit_id')) { function (Blueprint $table) {
$table->integer('budget_limit_id', false, true)->nullable()->default(null)->after('budget_id'); if (!Schema::hasColumn('budget_transaction_journal', 'budget_limit_id')) {
$table->foreign('budget_limit_id', 'budget_id_foreign')->references('id')->on('budget_limits')->onDelete('set null'); $table->integer('budget_limit_id', false, true)->nullable()->default(null)->after('budget_id');
$table->foreign('budget_limit_id', 'budget_id_foreign')->references('id')->on('budget_limits')->onDelete('set null');
}
} }
} );
); } catch (QueryException $e) {
} catch (QueryException $e) { Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); }
} }
// append budget limits table. // append budget limits table.
// i swear I dropped & recreated this field 15 times already. // I swear I dropped & recreated this field 15 times already.
try { try {
Schema::table( Schema::table(
'budget_limits', 'budget_limits',

View File

@@ -40,19 +40,21 @@ class ChangesForV550b2 extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if(Schema::hasColumn('recurrences_transactions', 'transaction_type_id')) {
Schema::table( try {
'recurrences_transactions', Schema::table(
function (Blueprint $table) { 'recurrences_transactions',
$table->dropForeign('type_foreign'); function (Blueprint $table) {
if (Schema::hasColumn('recurrences_transactions', 'transaction_type_id')) { $table->dropForeign('type_foreign');
$table->dropColumn('transaction_type_id'); if (Schema::hasColumn('recurrences_transactions', 'transaction_type_id')) {
$table->dropColumn('transaction_type_id');
}
} }
} );
); } catch (QueryException|ColumnDoesNotExist $e) {
} catch (QueryException|ColumnDoesNotExist $e) { Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); }
} }
} }
@@ -64,19 +66,21 @@ class ChangesForV550b2 extends Migration
public function up(): void public function up(): void
{ {
// expand recurrence transaction table // expand recurrence transaction table
try { if(!Schema::hasColumn('recurrences_transactions', 'transaction_type_id')) {
Schema::table( try {
'recurrences_transactions', Schema::table(
function (Blueprint $table) { 'recurrences_transactions',
if (!Schema::hasColumn('recurrences_transactions', 'transaction_type_id')) { function (Blueprint $table) {
$table->integer('transaction_type_id', false, true)->nullable()->after('transaction_currency_id'); if (!Schema::hasColumn('recurrences_transactions', 'transaction_type_id')) {
$table->foreign('transaction_type_id', 'type_foreign')->references('id')->on('transaction_types')->onDelete('set null'); $table->integer('transaction_type_id', false, true)->nullable()->after('transaction_currency_id');
$table->foreign('transaction_type_id', 'type_foreign')->references('id')->on('transaction_types')->onDelete('set null');
}
} }
} );
); } catch (QueryException $e) {
} catch (QueryException $e) { Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); }
} }
} }
} }

View File

@@ -35,16 +35,18 @@ class AddLdapColumnsToUsersTable extends Migration
*/ */
public function down(): void public function down(): void
{ {
try { if(Schema::hasColumn('users', 'domain')) {
Schema::table( try {
'users', Schema::table(
function (Blueprint $table) { 'users',
$table->dropColumn(['domain']); function (Blueprint $table) {
} $table->dropColumn(['domain']);
); }
} catch (QueryException|ColumnDoesNotExist $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException|ColumnDoesNotExist $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
@@ -53,16 +55,18 @@ class AddLdapColumnsToUsersTable extends Migration
*/ */
public function up(): void public function up(): void
{ {
try { if(!Schema::hasColumn('users', 'domain')) {
Schema::table( try {
'users', Schema::table(
function (Blueprint $table) { 'users',
$table->string('domain')->nullable(); function (Blueprint $table) {
} $table->string('domain')->nullable();
); }
} catch (QueryException $e) { );
Log::error(sprintf('Could not execute query: %s', $e->getMessage())); } catch (QueryException $e) {
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); Log::error(sprintf('Could not execute query: %s', $e->getMessage()));
Log::error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
}
} }
} }
} }

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