Compare commits

...

157 Commits

Author SHA1 Message Date
github-actions[bot]
bf1b0ee3c2 Merge pull request #10749 from firefly-iii/release-1755022724
🤖 Automatically merge the PR into the develop branch.
2025-08-12 20:18:52 +02:00
JC5
ffec4bbfba 🤖 Auto commit for release 'develop' on 2025-08-12 2025-08-12 20:18:44 +02:00
James Cole
ae6e103c09 Fix translation. 2025-08-12 20:13:48 +02:00
James Cole
99d4471f75 Merge branch 'main' into develop 2025-08-11 19:19:22 +02:00
James Cole
7f1fb72298 Merge pull request #10744 from firefly-iii/dependabot/github_actions/github/command-2.0.2
Bump github/command from 2.0.1 to 2.0.2
2025-08-11 09:43:28 +02:00
dependabot[bot]
009c2ed5d9 Bump github/command from 2.0.1 to 2.0.2
Bumps [github/command](https://github.com/github/command) from 2.0.1 to 2.0.2.
- [Release notes](https://github.com/github/command/releases)
- [Commits](https://github.com/github/command/compare/v2.0.1...v2.0.2)

---
updated-dependencies:
- dependency-name: github/command
  dependency-version: 2.0.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-11 05:23:27 +00:00
github-actions[bot]
44fc00299c Merge pull request #10742 from firefly-iii/release-1754883400
🤖 Automatically merge the PR into the develop branch.
2025-08-11 05:36:47 +02:00
JC5
774fc4281c 🤖 Auto commit for release 'develop' on 2025-08-11 2025-08-11 05:36:40 +02:00
github-actions[bot]
c47955c069 Merge pull request #10741 from firefly-iii/release-1754821000
🤖 Automatically merge the PR into the develop branch.
2025-08-10 12:16:47 +02:00
JC5
e7569644f7 🤖 Auto commit for release 'develop' on 2025-08-10 2025-08-10 12:16:41 +02:00
James Cole
c567474043 Optimize balance collection. 2025-08-10 12:12:30 +02:00
github-actions[bot]
9f394e92fe Merge pull request #10740 from firefly-iii/release-1754804137
🤖 Automatically merge the PR into the develop branch.
2025-08-10 07:35:46 +02:00
JC5
66befc7e44 🤖 Auto commit for release 'develop' on 2025-08-10 2025-08-10 07:35:37 +02:00
James Cole
c3a28fc698 Fix three years ago. 2025-08-10 07:31:10 +02:00
github-actions[bot]
ef317d5b3c Merge pull request #10739 from firefly-iii/release-1754802161
🤖 Automatically merge the PR into the develop branch.
2025-08-10 07:02:58 +02:00
JC5
152301f9ee 🤖 Auto commit for release 'develop' on 2025-08-10 2025-08-10 07:02:41 +02:00
James Cole
645e9ba1f7 Go back 3 years max. 2025-08-10 06:58:06 +02:00
James Cole
56487c3a33 Fix equation. 2025-08-10 06:54:04 +02:00
James Cole
b8062a915c Fix equation. 2025-08-10 06:53:21 +02:00
James Cole
5780c9512a Optimize convert all balances. 2025-08-10 06:53:08 +02:00
github-actions[bot]
71d39707d9 Merge pull request #10738 from firefly-iii/release-1754800979
🤖 Automatically merge the PR into the develop branch.
2025-08-10 06:43:10 +02:00
JC5
9ccb8ae692 🤖 Auto commit for release 'develop' on 2025-08-10 2025-08-10 06:42:59 +02:00
James Cole
8cd50bb5bd Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-08-10 06:38:34 +02:00
James Cole
ae9e1278e5 Expand some timers, fix reports. 2025-08-10 06:38:23 +02:00
github-actions[bot]
58c03797b2 Merge pull request #10737 from firefly-iii/release-1754766186
🤖 Automatically merge the PR into the develop branch.
2025-08-09 21:03:19 +02:00
JC5
7db38b4c6c 🤖 Auto commit for release 'develop' on 2025-08-09 2025-08-09 21:03:06 +02:00
James Cole
da6b447e64 Add some extra debug info. 2025-08-09 20:42:49 +02:00
github-actions[bot]
c19ac2b0f3 Merge pull request #10736 from firefly-iii/release-1754764141
🤖 Automatically merge the PR into the develop branch.
2025-08-09 20:29:09 +02:00
JC5
d5ca2171b3 🤖 Auto commit for release 'develop' on 2025-08-09 2025-08-09 20:29:01 +02:00
James Cole
20972cb29f Merge errors. 2025-08-09 20:24:45 +02:00
James Cole
7b714d0866 Add some time logs. 2025-08-09 20:24:15 +02:00
github-actions[bot]
240ae8fa57 Merge pull request #10735 from firefly-iii/release-1754763336
🤖 Automatically merge the PR into the develop branch.
2025-08-09 20:16:11 +02:00
JC5
5a2f6b2652 🤖 Auto commit for release 'develop' on 2025-08-09 2025-08-09 20:15:36 +02:00
James Cole
4196ce31f0 Fix account thing overview. 2025-08-09 20:10:40 +02:00
James Cole
be8ca5db50 Update changelog. 2025-08-09 19:58:59 +02:00
github-actions[bot]
30a417ea3c Merge pull request #10734 from firefly-iii/release-1754750646
🤖 Automatically merge the PR into the develop branch.
2025-08-09 16:44:16 +02:00
JC5
695ed940e0 🤖 Auto commit for release 'develop' on 2025-08-09 2025-08-09 16:44:06 +02:00
James Cole
1353554cf8 Remove expensive call from loop. 2025-08-09 16:38:32 +02:00
James Cole
e1ba2732af Remove non-optimized method. 2025-08-09 16:34:25 +02:00
James Cole
42b57c0e0e Migrate to optimized method. 2025-08-09 16:31:11 +02:00
James Cole
a6072753b2 Remove PR 2025-08-09 16:01:44 +02:00
github-actions[bot]
e92c224c39 Merge pull request #10733 from firefly-iii/release-1754748022
🤖 Automatically merge the PR into the develop branch.
2025-08-09 16:00:30 +02:00
JC5
a3ed7ec8f6 🤖 Auto commit for release 'develop' on 2025-08-09 2025-08-09 16:00:22 +02:00
James Cole
17a2f99dff Order and palce in changelog. 2025-08-09 15:55:29 +02:00
James Cole
c14971543c Update changelog. 2025-08-09 15:43:36 +02:00
James Cole
55f899608d Add multi currency to piggy overview. 2025-08-09 15:33:03 +02:00
github-actions[bot]
83be63f27e Merge pull request #10731 from firefly-iii/release-1754731244
🤖 Automatically merge the PR into the develop branch.
2025-08-09 11:20:53 +02:00
JC5
ed48d190e5 🤖 Auto commit for release 'develop' on 2025-08-09 2025-08-09 11:20:44 +02:00
James Cole
3c3b6615e6 Make message singular / plural 2025-08-09 11:16:46 +02:00
James Cole
e71e5a877b Fix count for overdue bills. 2025-08-09 11:13:03 +02:00
James Cole
b2a65dc660 Small change in text. 2025-08-09 08:48:25 +02:00
James Cole
d66dccd076 Fix bad slack URL 2025-08-09 08:47:22 +02:00
github-actions[bot]
c1128b28f2 Merge pull request #10730 from firefly-iii/release-1754721510
🤖 Automatically merge the PR into the develop branch.
2025-08-09 08:38:39 +02:00
JC5
da8e78c28d 🤖 Auto commit for release 'develop' on 2025-08-09 2025-08-09 08:38:30 +02:00
James Cole
f50aa6b0ce Fix spam whoopsie. 2025-08-09 08:34:18 +02:00
github-actions[bot]
661e4e53e6 Merge pull request #10729 from firefly-iii/release-1754719442
🤖 Automatically merge the PR into the develop branch.
2025-08-09 08:04:11 +02:00
JC5
3eeda4a6aa 🤖 Auto commit for release 'develop' on 2025-08-09 2025-08-09 08:04:02 +02:00
James Cole
4dba9cea21 Fire warnings for bills and expand webhook message cron job (#10696 and #10703 and #6836) 2025-08-09 07:59:38 +02:00
James Cole
6aab5fab05 Fix #9650 2025-08-09 06:59:55 +02:00
github-actions[bot]
4b0597d19a Merge pull request #10728 from firefly-iii/release-1754679825
🤖 Automatically merge the PR into the develop branch.
2025-08-08 21:03:55 +02:00
JC5
92f534bcb3 🤖 Auto commit for release 'develop' on 2025-08-08 2025-08-08 21:03:45 +02:00
James Cole
76e91be4dc Optimize array. 2025-08-08 20:59:24 +02:00
James Cole
deca4fed56 Clean up API and display of transactions. 2025-08-08 20:18:04 +02:00
James Cole
73512b0365 Add a basic singleton to save on queries. 2025-08-08 15:44:15 +02:00
github-actions[bot]
aaffc125e7 Merge pull request #10724 from firefly-iii/release-1754630264
🤖 Automatically merge the PR into the develop branch.
2025-08-08 07:17:53 +02:00
JC5
41a48c39a0 🤖 Auto commit for release 'develop' on 2025-08-08 2025-08-08 07:17:44 +02:00
James Cole
2d96bd84b5 Fix #9640 2025-08-08 06:43:05 +02:00
James Cole
ad1c1d2254 Fix #10071 2025-08-08 06:42:54 +02:00
github-actions[bot]
813206766d Merge pull request #10723 from firefly-iii/release-1754591858
🤖 Automatically merge the PR into the develop branch.
2025-08-07 20:37:46 +02:00
JC5
bb25d4a82a 🤖 Auto commit for release 'develop' on 2025-08-07 2025-08-07 20:37:38 +02:00
James Cole
f3b78beecc Fix another null 2025-08-07 20:33:24 +02:00
github-actions[bot]
64073768fe Merge pull request #10722 from firefly-iii/release-1754590638
🤖 Automatically merge the PR into the develop branch.
2025-08-07 20:17:25 +02:00
JC5
fe6dd0f901 🤖 Auto commit for release 'develop' on 2025-08-07 2025-08-07 20:17:19 +02:00
James Cole
aac8d11ff6 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-08-07 20:13:35 +02:00
James Cole
afa99a35b5 Fix NULLs 2025-08-07 20:13:29 +02:00
James Cole
e9cb0a51d7 Catch NULL. 2025-08-07 20:11:46 +02:00
github-actions[bot]
9fbcccfd02 Merge pull request #10721 from firefly-iii/release-1754589876
🤖 Automatically merge the PR into the develop branch.
2025-08-07 20:04:43 +02:00
JC5
468c9c9d56 🤖 Auto commit for release 'develop' on 2025-08-07 2025-08-07 20:04:36 +02:00
James Cole
f76b27a73d Fix #10565 and fix #10600 2025-08-07 19:59:02 +02:00
James Cole
579fe81616 Fix #10656 2025-08-07 19:52:12 +02:00
James Cole
ec9ba53690 Fix #10678 2025-08-07 19:48:00 +02:00
James Cole
85337c53d4 Fix currency collection. 2025-08-07 19:37:36 +02:00
James Cole
eb6d585bb2 Fix a variety of code. 2025-08-07 19:09:25 +02:00
James Cole
378ffbc609 Fix #10720 2025-08-07 17:55:25 +02:00
James Cole
3b3c8e5bcd Add object group to various items. 2025-08-07 07:46:49 +02:00
github-actions[bot]
75cbdb6a57 Merge pull request #10719 from firefly-iii/release-1754540665
🤖 Automatically merge the PR into the develop branch.
2025-08-07 06:24:32 +02:00
JC5
cdaff0d983 🤖 Auto commit for release 'develop' on 2025-08-07 2025-08-07 06:24:25 +02:00
James Cole
dda3863889 Fix account_id key. 2025-08-07 06:20:36 +02:00
github-actions[bot]
57dc423b3f Merge pull request #10718 from firefly-iii/release-1754540258
🤖 Automatically merge the PR into the develop branch.
2025-08-07 06:17:51 +02:00
JC5
c0570bc3b2 🤖 Auto commit for release 'develop' on 2025-08-07 2025-08-07 06:17:38 +02:00
James Cole
65110d1666 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-08-07 06:12:02 +02:00
James Cole
5a10b29402 Set to zero instead of null. 2025-08-07 06:11:56 +02:00
github-actions[bot]
028544ca2e Merge pull request #10717 from firefly-iii/release-1754539541
🤖 Automatically merge the PR into the develop branch.
2025-08-07 06:05:53 +02:00
JC5
af46729372 🤖 Auto commit for release 'develop' on 2025-08-07 2025-08-07 06:05:41 +02:00
James Cole
4c7789a668 Add missing access rights. 2025-08-07 06:01:14 +02:00
James Cole
292908048c Add enrichment to recurring 2025-08-07 05:59:26 +02:00
James Cole
e300314e05 Catch NULL. 2025-08-07 05:56:31 +02:00
James Cole
4f1f360346 Add primary to array. 2025-08-07 05:55:15 +02:00
James Cole
bff856aeff Rename method, remove 0. 2025-08-07 05:52:56 +02:00
James Cole
7f5a1bda8d Catch null 2025-08-06 20:53:30 +02:00
github-actions[bot]
b506281bd6 Merge pull request #10716 from firefly-iii/release-1754505595
🤖 Automatically merge the PR into the develop branch.
2025-08-06 20:40:02 +02:00
JC5
dfe9b3e787 🤖 Auto commit for release 'develop' on 2025-08-06 2025-08-06 20:39:55 +02:00
James Cole
2428a2a7c5 Expand API test code. 2025-08-06 20:27:59 +02:00
James Cole
0e8f608e00 Optimize available budgets. 2025-08-06 20:23:58 +02:00
James Cole
70071767ab Collect account balances, optimized. 2025-08-06 20:15:02 +02:00
James Cole
0ad6beb66c Optimize recurrence enrichment. 2025-08-06 15:35:29 +02:00
James Cole
1197f65589 Start work on recurring transaction enrichment. 2025-08-06 10:46:23 +02:00
James Cole
7bbf2dcc6f Add enrichment. 2025-08-06 09:18:29 +02:00
James Cole
d4ab69ebe6 Expand piggy bank enrichment. 2025-08-06 09:15:54 +02:00
James Cole
c8c552602e Expand piggy bank events. 2025-08-05 19:49:13 +02:00
James Cole
1921a8050b Fix #10709 2025-08-05 18:56:31 +02:00
James Cole
f488feda93 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-08-05 17:57:57 +02:00
James Cole
d90c033b83 Fix #10708 2025-08-05 17:57:52 +02:00
github-actions[bot]
9f256253f2 Merge pull request #10707 from firefly-iii/release-1754394813
🤖 Automatically merge the PR into the develop branch.
2025-08-05 13:53:39 +02:00
JC5
489b7c12e5 🤖 Auto commit for release 'develop' on 2025-08-05 2025-08-05 13:53:33 +02:00
Sander Dorigo
1049a8314d Fix lang 2025-08-05 13:48:58 +02:00
Sander Dorigo
48301b6b9c Add missing classes 2025-08-05 13:40:46 +02:00
Sander Dorigo
5a92215921 Fix #10706 2025-08-05 12:50:05 +02:00
Sander Dorigo
ccfc75852a Fix #10702 2025-08-05 11:02:26 +02:00
Sander Dorigo
9804cffff3 Fix #10704 2025-08-05 10:41:54 +02:00
James Cole
901e113fef Fix #10700 2025-08-05 05:55:45 +02:00
James Cole
a4021ff056 Enrich categories. 2025-08-04 20:55:31 +02:00
James Cole
902d91ad29 Add moment JS 2025-08-04 20:19:09 +02:00
James Cole
fa2cf22e73 Add locale files 2025-08-04 20:17:11 +02:00
James Cole
970dad4c49 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-08-04 20:11:57 +02:00
James Cole
9d01c7bdb8 Add language 2025-08-04 20:11:51 +02:00
github-actions[bot]
dc7d4fb258 Merge pull request #10698 from firefly-iii/release-1754331101
🤖 Automatically merge the PR into the develop branch.
2025-08-04 20:11:50 +02:00
JC5
a807ca5002 🤖 Auto commit for release 'develop' on 2025-08-04 2025-08-04 20:11:41 +02:00
github-actions[bot]
d59d326841 Merge pull request #10693 from firefly-iii/release-1754278961
🤖 Automatically merge the PR into the develop branch.
2025-08-04 05:42:50 +02:00
JC5
b915548e82 🤖 Auto commit for release 'develop' on 2025-08-04 2025-08-04 05:42:41 +02:00
James Cole
8200a81840 Add enrichment. 2025-08-03 20:19:07 +02:00
James Cole
6a49918707 Add budget transformer and enrichment. 2025-08-03 20:17:50 +02:00
James Cole
e55fc483bd Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2025-08-03 17:42:13 +02:00
James Cole
4ff5f5883d Improve budget limit. 2025-08-03 17:42:07 +02:00
github-actions[bot]
eda2eae04a Merge pull request #10689 from firefly-iii/release-1754232349
🤖 Automatically merge the PR into the develop branch.
2025-08-03 16:45:56 +02:00
JC5
c07c30ea17 🤖 Auto commit for release 'develop' on 2025-08-03 2025-08-03 16:45:49 +02:00
James Cole
56f1eb03e0 Add missing field. 2025-08-03 10:24:49 +02:00
James Cole
d4e14dd262 Move account balance logic to enrichment. 2025-08-03 10:22:12 +02:00
James Cole
0c7f04fb17 Expand bill transformer. 2025-08-03 08:12:19 +02:00
James Cole
061c01da53 Remove unnecessary setters. 2025-08-03 08:02:13 +02:00
James Cole
716d72d8af Optimize available budgets. 2025-08-03 07:53:36 +02:00
James Cole
3233ca4a4c Fix badly named field. 2025-08-03 07:13:57 +02:00
James Cole
1041030b1e First start on optimized available balance enrichment. 2025-08-03 07:12:06 +02:00
James Cole
bb3b06cf08 Fix #10687 2025-08-02 19:17:37 +02:00
James Cole
f35e361915 Match fields for 6.3.0 2025-08-02 14:21:22 +02:00
James Cole
47d697c7dc Remove references to "balances". 2025-08-02 11:07:35 +02:00
James Cole
3745d79f1f Clean up account transformer. 2025-08-02 07:16:30 +02:00
github-actions[bot]
04cbff4b9a Merge pull request #10684 from firefly-iii/release-1754070963
🤖 Automatically merge the PR into the develop branch.
2025-08-01 19:56:12 +02:00
JC5
0c2ca4b97c 🤖 Auto commit for release 'develop' on 2025-08-01 2025-08-01 19:56:03 +02:00
James Cole
3918665cd1 Move all endpoints to v1. 2025-08-01 19:41:36 +02:00
James Cole
9eb8869649 Fix files. 2025-08-01 19:33:30 +02:00
github-actions[bot]
62221af591 Merge pull request #10683 from firefly-iii/release-1754069211
🤖 Automatically merge the PR into the develop branch.
2025-08-01 19:26:58 +02:00
JC5
4d013a44ce 🤖 Auto commit for release 'develop' on 2025-08-01 2025-08-01 19:26:51 +02:00
Sander Dorigo
c55cfd1acf Rename file 2025-08-01 15:30:45 +02:00
github-actions[bot]
b2652b83ce Merge pull request #10682 from firefly-iii/release-1754049870
🤖 Automatically merge the PR into the develop branch.
2025-08-01 14:04:37 +02:00
JC5
3d28932216 🤖 Auto commit for release 'develop' on 2025-08-01 2025-08-01 14:04:30 +02:00
Sander Dorigo
87567d5a31 Rename default to primary 2025-08-01 13:48:32 +02:00
236 changed files with 5648 additions and 2388 deletions

View File

@@ -13,7 +13,7 @@ jobs:
close_duplicates: close_duplicates:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: github/command@v2.0.1 - uses: github/command@v2.0.2
id: command id: command
with: with:
allowed_contexts: "issue" allowed_contexts: "issue"

View File

@@ -31,6 +31,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Debug\Timer; use FireflyIII\Support\Debug\Timer;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Api\AccountFilter; use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\User; use FireflyIII\User;
@@ -84,12 +85,15 @@ class AccountController extends Controller
$query = $data['query']; $query = $data['query'];
$date = $data['date'] ?? today(config('app.timezone')); $date = $data['date'] ?? today(config('app.timezone'));
$return = []; $return = [];
Timer::start(sprintf('AC accounts "%s"', $query)); $timer = Timer::getInstance();
$timer->start(sprintf('AC accounts "%s"', $query));
$result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit')); $result = $this->repository->searchAccount((string) $query, $types, $this->parameters->get('limit'));
// set date to subday + end-of-day for account balance. so it is at $date 23:59:59 // set date to subday + end-of-day for account balance. so it is at $date 23:59:59
$date->endOfDay(); $date->endOfDay();
$allBalances = Steam::accountsBalancesOptimized($result, $date, $this->primaryCurrency, $this->convertToPrimary);
/** @var Account $account */ /** @var Account $account */
foreach ($result as $account) { foreach ($result as $account) {
$nameWithBalance = $account->name; $nameWithBalance = $account->name;
@@ -98,15 +102,11 @@ class AccountController extends Controller
if (in_array($account->accountType->type, $this->balanceTypes, true)) { if (in_array($account->accountType->type, $this->balanceTypes, true)) {
// this one is correct. // this one is correct.
Log::debug(sprintf('accounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); Log::debug(sprintf('accounts: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
$balance = Steam::finalAccountBalance($account, $date); $balance = $allBalances[$account->id] ?? [];
$key = $this->convertToPrimary && $currency->id !== $this->primaryCurrency->id ? 'pc_balance' : 'balance'; $key = $this->convertToPrimary && $currency->id !== $this->primaryCurrency->id ? 'pc_balance' : 'balance';
$useCurrency = $this->convertToPrimary && $currency->id !== $this->primaryCurrency->id ? $this->primaryCurrency : $currency; $useCurrency = $this->convertToPrimary && $currency->id !== $this->primaryCurrency->id ? $this->primaryCurrency : $currency;
$amount = $balance[$key] ?? '0'; $amount = $balance[$key] ?? '0';
$nameWithBalance = sprintf( $nameWithBalance = sprintf('%s (%s)', $account->name, Amount::formatAnything($useCurrency, $amount, false));
'%s (%s)',
$account->name,
app('amount')->formatAnything($useCurrency, $amount, false)
);
} }
$return[] = [ $return[] = [
@@ -138,7 +138,7 @@ class AccountController extends Controller
return $posA - $posB; return $posA - $posB;
} }
); );
Timer::stop(sprintf('AC accounts "%s"', $query)); $timer->stop(sprintf('AC accounts "%s"', $query));
return response()->api($return); return response()->api($return);
} }

View File

@@ -0,0 +1,97 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Chart;
use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Chart\ChartRequest;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Chart\ChartData;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Http\Api\AccountBalanceGrouped;
use FireflyIII\Support\Http\Api\CleansChartData;
use FireflyIII\Support\Http\Api\CollectsAccountsFromFilter;
use Illuminate\Http\JsonResponse;
/**
* Class BalanceController
*/
class BalanceController extends Controller
{
use CleansChartData;
use CollectsAccountsFromFilter;
private ChartData $chartData;
private GroupCollectorInterface $collector;
private AccountRepositoryInterface $repository;
// private TransactionCurrency $default;
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
$this->collector = app(GroupCollectorInterface::class);
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
$this->collector->setUserGroup($userGroup);
$this->chartData = new ChartData();
// $this->default = app('amount')->getPrimaryCurrency();
return $next($request);
}
);
}
/**
* The code is practically a duplicate of ReportController::operations.
*
* Currency is up to the account/transactions in question, but conversion to the default
* currency is possible.
*
* If the transaction being processed is already in native currency OR if the
* foreign amount is in the native currency, the amount will not be converted.
*
* @throws FireflyException
*/
public function balance(ChartRequest $request): JsonResponse
{
$queryParameters = $request->getParameters();
$accounts = $this->getAccountList($queryParameters);
// prepare for currency conversion and data collection:
/** @var TransactionCurrency $primary */
$primary = Amount::getPrimaryCurrency();
// get journals for entire period:
$this->collector->setRange($queryParameters['start'], $queryParameters['end'])
->withAccountInformation()
->setXorAccounts($accounts)
->setTypes([TransactionTypeEnum::WITHDRAWAL->value, TransactionTypeEnum::DEPOSIT->value, TransactionTypeEnum::RECONCILIATION->value, TransactionTypeEnum::TRANSFER->value])
;
$journals = $this->collector->getExtractedJournals();
$object = new AccountBalanceGrouped();
$object->setPreferredRange($queryParameters['period']);
$object->setPrimary($primary);
$object->setAccounts($accounts);
$object->setJournals($journals);
$object->setStart($queryParameters['start']);
$object->setEnd($queryParameters['end']);
$object->groupByCurrencyAndPeriod();
$data = $object->convertToChartData();
foreach ($data as $entry) {
$this->chartData->add($entry);
}
return response()->json($this->chartData->render());
}
}

View File

@@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Generic\DateRequest; use FireflyIII\Api\V1\Requests\Data\DateRequest;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
@@ -291,7 +291,7 @@ class BudgetController extends Controller
} }
if ($current->transaction_currency_id !== $this->primaryCurrency->id) { if ($current->transaction_currency_id !== $this->primaryCurrency->id) {
// convert and then add it. // convert and then add it.
$converted = $converter->convert($current->transactionCurrency, $this->primaryCurrency, $limit->start_date, $limit->amount); $converted = $converter->convert($current->transactionCurrency, $this->primaryCurrency, $current->start_date, $current->amount);
$amount = bcadd($amount, $converted); $amount = bcadd($amount, $converted);
Log::debug(sprintf('Budgeted in limit #%d: %s %s, converted to %s %s', $current->id, $current->transactionCurrency->code, $current->amount, $this->primaryCurrency->code, $converted)); Log::debug(sprintf('Budgeted in limit #%d: %s %s, converted to %s %s', $current->id, $current->transactionCurrency->code, $current->amount, $this->primaryCurrency->code, $converted));
Log::debug(sprintf('Set amount in limit to %s', $amount)); Log::debug(sprintf('Set amount in limit to %s', $amount));

View File

@@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Chart;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Request\Generic\DateRequest; use FireflyIII\Api\V1\Requests\Data\DateRequest;
use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;

View File

@@ -30,6 +30,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
use FireflyIII\Transformers\AttachmentTransformer; use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\PiggyBankTransformer; use FireflyIII\Transformers\PiggyBankTransformer;
@@ -117,6 +118,13 @@ class ListController extends Controller
$count = $collection->count(); $count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new PiggyBankEnrichment();
$enrichment->setUser($admin);
$piggyBanks = $enrichment->enrich($piggyBanks);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.accounts.piggy-banks', [$account->id]).$this->buildParams()); $paginator->setPath(route('api.v1.accounts.piggy-banks', [$account->id]).$this->buildParams());
@@ -125,7 +133,7 @@ class ListController extends Controller
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks'); $resource = new FractalCollection($piggyBanks, $transformer, 'piggy-banks');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);

View File

@@ -96,8 +96,8 @@ class ShowController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);
// make paginator: // make paginator:
@@ -131,8 +131,8 @@ class ShowController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$account = $enrichment->enrichSingle($account); $account = $enrichment->enrichSingle($account);

View File

@@ -75,8 +75,8 @@ class StoreController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate(null);
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$account = $enrichment->enrichSingle($account); $account = $enrichment->enrichSingle($account);
/** @var AccountTransformer $transformer */ /** @var AccountTransformer $transformer */

View File

@@ -80,8 +80,8 @@ class UpdateController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate(null);
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$account = $enrichment->enrichSingle($account); $account = $enrichment->enrichSingle($account);
/** @var AccountTransformer $transformer */ /** @var AccountTransformer $transformer */

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\AvailableBudget; use FireflyIII\Models\AvailableBudget;
use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\AvailableBudgetEnrichment;
use FireflyIII\Transformers\AvailableBudgetTransformer; use FireflyIII\Transformers\AvailableBudgetTransformer;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -75,7 +76,6 @@ class ShowController extends Controller
// types to get, page size: // types to get, page size:
$pageSize = $this->parameters->get('limit'); $pageSize = $this->parameters->get('limit');
$start = $this->parameters->get('start'); $start = $this->parameters->get('start');
$end = $this->parameters->get('end'); $end = $this->parameters->get('end');
@@ -84,6 +84,13 @@ class ShowController extends Controller
$count = $collection->count(); $count = $collection->count();
$availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new AvailableBudgetEnrichment();
$enrichment->setUser($admin);
$availableBudgets = $enrichment->enrich($availableBudgets);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.available-budgets.index').$this->buildParams()); $paginator->setPath(route('api.v1.available-budgets.index').$this->buildParams());
@@ -107,11 +114,23 @@ class ShowController extends Controller
public function show(AvailableBudget $availableBudget): JsonResponse public function show(AvailableBudget $availableBudget): JsonResponse
{ {
$manager = $this->getManager(); $manager = $this->getManager();
$start = $this->parameters->get('start');
$end = $this->parameters->get('end');
/** @var AvailableBudgetTransformer $transformer */ /** @var AvailableBudgetTransformer $transformer */
$transformer = app(AvailableBudgetTransformer::class); $transformer = app(AvailableBudgetTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new AvailableBudgetEnrichment();
$enrichment->setUser($admin);
$enrichment->setStart($start);
$enrichment->setEnd($end);
$availableBudget = $enrichment->enrichSingle($availableBudget);
$resource = new Item($availableBudget, $transformer, 'available_budgets'); $resource = new Item($availableBudget, $transformer, 'available_budgets');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);

View File

@@ -83,8 +83,6 @@ class ShowController extends Controller
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new SubscriptionEnrichment(); $enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start')); $enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end')); $enrichment->setEnd($this->parameters->get('end'));
$bills = $enrichment->enrich($bills); $bills = $enrichment->enrich($bills);
@@ -114,8 +112,6 @@ class ShowController extends Controller
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new SubscriptionEnrichment(); $enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start')); $enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end')); $enrichment->setEnd($this->parameters->get('end'));
$bill = $enrichment->enrichSingle($bill); $bill = $enrichment->enrichSingle($bill);

View File

@@ -79,8 +79,6 @@ class StoreController extends Controller
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new SubscriptionEnrichment(); $enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start')); $enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end')); $enrichment->setEnd($this->parameters->get('end'));
$bill = $enrichment->enrichSingle($bill); $bill = $enrichment->enrichSingle($bill);

View File

@@ -74,8 +74,6 @@ class UpdateController extends Controller
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new SubscriptionEnrichment(); $enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start')); $enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end')); $enrichment->setEnd($this->parameters->get('end'));
$bill = $enrichment->enrichSingle($bill); $bill = $enrichment->enrichSingle($bill);

View File

@@ -32,6 +32,7 @@ use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Support\JsonApi\Enrichments\BudgetLimitEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
use FireflyIII\Transformers\AttachmentTransformer; use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\BudgetLimitTransformer; use FireflyIII\Transformers\BudgetLimitTransformer;
@@ -117,6 +118,14 @@ class ListController extends Controller
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.budget-limits', [$budget->id]).$this->buildParams()); $paginator->setPath(route('api.v1.budgets.budget-limits', [$budget->id]).$this->buildParams());
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetLimitEnrichment();
$enrichment->setUser($admin);
$budgetLimits = $enrichment->enrich($budgetLimits);
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -29,7 +29,9 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\BudgetEnrichment;
use FireflyIII\Transformers\BudgetTransformer; use FireflyIII\Transformers\BudgetTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
@@ -82,6 +84,15 @@ class ShowController extends Controller
$count = $collection->count(); $count = $collection->count();
$budgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $budgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetEnrichment();
$enrichment->setUser($admin);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$budgets = $enrichment->enrich($budgets);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($budgets, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($budgets, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.index').$this->buildParams()); $paginator->setPath(route('api.v1.budgets.index').$this->buildParams());
@@ -103,6 +114,15 @@ class ShowController extends Controller
{ {
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetEnrichment();
$enrichment->setUser($admin);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$budget = $enrichment->enrichSingle($budget);
/** @var BudgetTransformer $transformer */ /** @var BudgetTransformer $transformer */
$transformer = app(BudgetTransformer::class); $transformer = app(BudgetTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Budget\StoreRequest; use FireflyIII\Api\V1\Requests\Models\Budget\StoreRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\BudgetEnrichment;
use FireflyIII\Transformers\BudgetTransformer; use FireflyIII\Transformers\BudgetTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
@@ -69,6 +71,13 @@ class StoreController extends Controller
$budget->refresh(); $budget->refresh();
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetEnrichment();
$enrichment->setUser($admin);
$budget = $enrichment->enrichSingle($budget);
/** @var BudgetTransformer $transformer */ /** @var BudgetTransformer $transformer */
$transformer = app(BudgetTransformer::class); $transformer = app(BudgetTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Budget\UpdateRequest; use FireflyIII\Api\V1\Requests\Models\Budget\UpdateRequest;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\BudgetEnrichment;
use FireflyIII\Transformers\BudgetTransformer; use FireflyIII\Transformers\BudgetTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
@@ -67,6 +69,13 @@ class UpdateController extends Controller
$budget = $this->repository->update($budget, $data); $budget = $this->repository->update($budget, $data);
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetEnrichment();
$enrichment->setUser($admin);
$budget = $enrichment->enrichSingle($budget);
/** @var BudgetTransformer $transformer */ /** @var BudgetTransformer $transformer */
$transformer = app(BudgetTransformer::class); $transformer = app(BudgetTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -31,6 +31,7 @@ use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\BudgetLimitEnrichment;
use FireflyIII\Transformers\BudgetLimitTransformer; use FireflyIII\Transformers\BudgetLimitTransformer;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -84,6 +85,14 @@ class ShowController extends Controller
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budgets.limits.index', [$budget->id]).$this->buildParams()); $paginator->setPath(route('api.v1.budgets.limits.index', [$budget->id]).$this->buildParams());
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetLimitEnrichment();
$enrichment->setUser($admin);
$budgetLimits = $enrichment->enrich($budgetLimits);
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
@@ -113,6 +122,13 @@ class ShowController extends Controller
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.budget-limits.index').$this->buildParams()); $paginator->setPath(route('api.v1.budget-limits.index').$this->buildParams());
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetLimitEnrichment();
$enrichment->setUser($admin);
$budgetLimits = $enrichment->enrich($budgetLimits);
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
@@ -137,6 +153,13 @@ class ShowController extends Controller
// continue! // continue!
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetLimitEnrichment();
$enrichment->setUser($admin);
$budgetLimit = $enrichment->enrichSingle($budgetLimit);
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\BudgetLimit\StoreRequest; use FireflyIII\Api\V1\Requests\Models\BudgetLimit\StoreRequest;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\BudgetLimitEnrichment;
use FireflyIII\Transformers\BudgetLimitTransformer; use FireflyIII\Transformers\BudgetLimitTransformer;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -74,6 +75,13 @@ class StoreController extends Controller
$budgetLimit = $this->blRepository->store($data); $budgetLimit = $this->blRepository->store($data);
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetLimitEnrichment();
$enrichment->setUser($admin);
$budgetLimit = $enrichment->enrichSingle($budgetLimit);
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -30,6 +30,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\BudgetLimit;
use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\BudgetLimitEnrichment;
use FireflyIII\Transformers\BudgetLimitTransformer; use FireflyIII\Transformers\BudgetLimitTransformer;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -80,6 +81,13 @@ class UpdateController extends Controller
$budgetLimit = $this->blRepository->update($budgetLimit, $data); $budgetLimit = $this->blRepository->update($budgetLimit, $data);
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetLimitEnrichment();
$enrichment->setUser($admin);
$budgetLimit = $enrichment->enrich($budgetLimit);
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\CategoryEnrichment;
use FireflyIII\Transformers\CategoryTransformer; use FireflyIII\Transformers\CategoryTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
@@ -78,6 +80,15 @@ class ShowController extends Controller
$count = $collection->count(); $count = $collection->count();
$categories = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $categories = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new CategoryEnrichment();
$enrichment->setUser($admin);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$categories = $enrichment->enrich($categories);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($categories, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($categories, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.categories.index').$this->buildParams()); $paginator->setPath(route('api.v1.categories.index').$this->buildParams());
@@ -105,6 +116,15 @@ class ShowController extends Controller
$transformer = app(CategoryTransformer::class); $transformer = app(CategoryTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new CategoryEnrichment();
$enrichment->setUser($admin);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$category = $enrichment->enrichSingle($category);
$resource = new Item($category, $transformer, 'categories'); $resource = new Item($category, $transformer, 'categories');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Category\StoreRequest; use FireflyIII\Api\V1\Requests\Models\Category\StoreRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\CategoryEnrichment;
use FireflyIII\Transformers\CategoryTransformer; use FireflyIII\Transformers\CategoryTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
@@ -72,6 +74,15 @@ class StoreController extends Controller
$transformer = app(CategoryTransformer::class); $transformer = app(CategoryTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new CategoryEnrichment();
$enrichment->setUser($admin);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$category = $enrichment->enrichSingle($category);
$resource = new Item($category, $transformer, 'categories'); $resource = new Item($category, $transformer, 'categories');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Category\UpdateRequest; use FireflyIII\Api\V1\Requests\Models\Category\UpdateRequest;
use FireflyIII\Models\Category; use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\CategoryEnrichment;
use FireflyIII\Transformers\CategoryTransformer; use FireflyIII\Transformers\CategoryTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
@@ -71,6 +73,15 @@ class UpdateController extends Controller
$transformer = app(CategoryTransformer::class); $transformer = app(CategoryTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new CategoryEnrichment();
$enrichment->setUser($admin);
$enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end'));
$category = $enrichment->enrichSingle($category);
$resource = new Item($category, $transformer, 'categories'); $resource = new Item($category, $transformer, 'categories');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate; namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface; use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\ExchangeRateTransformer; use FireflyIII\Transformers\ExchangeRateTransformer;
@@ -39,7 +40,7 @@ class IndexController extends Controller
use ValidatesUserGroupTrait; use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'currency_exchange_rates'; public const string RESOURCE_KEY = 'currency_exchange_rates';
protected array $acceptedRoles = [UserRoleEnum::OWNER];
private ExchangeRateRepositoryInterface $repository; private ExchangeRateRepositoryInterface $repository;
public function __construct() public function __construct()

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate; namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\CurrencyExchangeRate; use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface; use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
@@ -41,7 +42,7 @@ class ShowController extends Controller
use ValidatesUserGroupTrait; use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates'; public const string RESOURCE_KEY = 'exchange-rates';
protected array $acceptedRoles = [UserRoleEnum::OWNER];
private ExchangeRateRepositoryInterface $repository; private ExchangeRateRepositoryInterface $repository;
public function __construct() public function __construct()

View File

@@ -24,6 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate; namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\CurrencyExchangeRate; use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\StoreRequest; use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\StoreRequest;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
@@ -37,7 +38,7 @@ class StoreController extends Controller
use ValidatesUserGroupTrait; use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates'; public const string RESOURCE_KEY = 'exchange-rates';
protected array $acceptedRoles = [UserRoleEnum::OWNER];
private ExchangeRateRepositoryInterface $repository; private ExchangeRateRepositoryInterface $repository;
public function __construct() public function __construct()

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V1\Controllers\Models\CurrencyExchangeRate;
use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\UpdateRequest; use FireflyIII\Api\V1\Requests\Models\CurrencyExchangeRate\UpdateRequest;
use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\CurrencyExchangeRate; use FireflyIII\Models\CurrencyExchangeRate;
use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface; use FireflyIII\Repositories\ExchangeRate\ExchangeRateRepositoryInterface;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
@@ -37,7 +38,7 @@ class UpdateController extends Controller
use ValidatesUserGroupTrait; use ValidatesUserGroupTrait;
public const string RESOURCE_KEY = 'exchange-rates'; public const string RESOURCE_KEY = 'exchange-rates';
protected array $acceptedRoles = [UserRoleEnum::OWNER];
private ExchangeRateRepositoryInterface $repository; private ExchangeRateRepositoryInterface $repository;
public function __construct() public function __construct()

View File

@@ -28,6 +28,7 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\ObjectGroup; use FireflyIII\Models\ObjectGroup;
use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface; use FireflyIII\Repositories\ObjectGroup\ObjectGroupRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment; use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
use FireflyIII\Transformers\BillTransformer; use FireflyIII\Transformers\BillTransformer;
use FireflyIII\Transformers\PiggyBankTransformer; use FireflyIII\Transformers\PiggyBankTransformer;
@@ -85,8 +86,6 @@ class ListController extends Controller
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new SubscriptionEnrichment(); $enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start')); $enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end')); $enrichment->setEnd($this->parameters->get('end'));
$bills = $enrichment->enrich($bills); $bills = $enrichment->enrich($bills);
@@ -126,6 +125,13 @@ class ListController extends Controller
$count = $collection->count(); $count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new PiggyBankEnrichment();
$enrichment->setUser($admin);
$piggyBanks = $enrichment->enrich($piggyBanks);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.object-groups.piggy-banks', [$objectGroup->id]).$this->buildParams()); $paginator->setPath(route('api.v1.object-groups.piggy-banks', [$objectGroup->id]).$this->buildParams());
@@ -134,7 +140,7 @@ class ListController extends Controller
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks'); $resource = new FractalCollection($piggyBanks, $transformer, 'piggy-banks');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);

View File

@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEventEnrichment;
use FireflyIII\Transformers\AccountTransformer; use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\Transformers\AttachmentTransformer; use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\PiggyBankEventTransformer; use FireflyIII\Transformers\PiggyBankEventTransformer;
@@ -83,8 +84,8 @@ class ListController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);
// make paginator: // make paginator:
@@ -148,6 +149,13 @@ class ListController extends Controller
$count = $collection->count(); $count = $collection->count();
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new PiggyBankEventEnrichment();
$enrichment->setUser($admin);
$events = $enrichment->enrich($events);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy-banks.events', [$piggyBank->id]).$this->buildParams()); $paginator->setPath(route('api.v1.piggy-banks.events', [$piggyBank->id]).$this->buildParams());
@@ -156,7 +164,7 @@ class ListController extends Controller
$transformer = app(PiggyBankEventTransformer::class); $transformer = app(PiggyBankEventTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
$resource = new FractalCollection($events, $transformer, 'piggy_bank_events'); $resource = new FractalCollection($events, $transformer, sprintf('piggy-banks/%d/events', $piggyBank->id));
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
use FireflyIII\Transformers\PiggyBankTransformer; use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
@@ -77,6 +79,13 @@ class ShowController extends Controller
$count = $collection->count(); $count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new PiggyBankEnrichment();
$enrichment->setUser($admin);
$piggyBanks = $enrichment->enrich($piggyBanks);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.piggy-banks.index').$this->buildParams()); $paginator->setPath(route('api.v1.piggy-banks.index').$this->buildParams());
@@ -85,7 +94,7 @@ class ShowController extends Controller
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
$resource = new FractalCollection($piggyBanks, $transformer, 'piggy_banks'); $resource = new FractalCollection($piggyBanks, $transformer, 'piggy-banks');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
@@ -101,11 +110,19 @@ class ShowController extends Controller
{ {
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new PiggyBankEnrichment();
$enrichment->setUser($admin);
$piggyBank = $enrichment->enrichSingle($piggyBank);
/** @var PiggyBankTransformer $transformer */ /** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
$resource = new Item($piggyBank, $transformer, 'piggy_banks'); $resource = new Item($piggyBank, $transformer, 'piggy-banks');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
} }

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\PiggyBank\StoreRequest; use FireflyIII\Api\V1\Requests\Models\PiggyBank\StoreRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
use FireflyIII\Transformers\PiggyBankTransformer; use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
@@ -68,6 +70,13 @@ class StoreController extends Controller
$piggyBank = $this->repository->store($request->getAll()); $piggyBank = $this->repository->store($request->getAll());
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new PiggyBankEnrichment();
$enrichment->setUser($admin);
$piggyBank = $enrichment->enrichSingle($piggyBank);
/** @var PiggyBankTransformer $transformer */ /** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\PiggyBank\UpdateRequest; use FireflyIII\Api\V1\Requests\Models\PiggyBank\UpdateRequest;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
use FireflyIII\Transformers\PiggyBankTransformer; use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
@@ -70,13 +72,20 @@ class UpdateController extends Controller
$this->repository->setCurrentAmount($piggyBank, $data['current_amount']); $this->repository->setCurrentAmount($piggyBank, $data['current_amount']);
} }
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new PiggyBankEnrichment();
$enrichment->setUser($admin);
$piggyBank = $enrichment->enrichSingle($piggyBank);
$manager = $this->getManager(); $manager = $this->getManager();
/** @var PiggyBankTransformer $transformer */ /** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
$resource = new Item($piggyBank, $transformer, 'piggy_banks'); $resource = new Item($piggyBank, $transformer, 'piggy-banks');
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
} }

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Recurrence; use FireflyIII\Models\Recurrence;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
use FireflyIII\Transformers\RecurrenceTransformer; use FireflyIII\Transformers\RecurrenceTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Pagination\IlluminatePaginatorAdapter;
@@ -76,17 +78,24 @@ class ShowController extends Controller
// get list of budgets. Count it and split it. // get list of budgets. Count it and split it.
$collection = $this->repository->get(); $collection = $this->repository->get();
$count = $collection->count(); $count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $recurrences = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new RecurringEnrichment();
$enrichment->setUser($admin);
$recurrences = $enrichment->enrich($recurrences);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($recurrences, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.recurrences.index').$this->buildParams()); $paginator->setPath(route('api.v1.recurrences.index').$this->buildParams());
/** @var RecurrenceTransformer $transformer */ /** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class); $transformer = app(RecurrenceTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
$resource = new FractalCollection($piggyBanks, $transformer, 'recurrences'); $resource = new FractalCollection($recurrences, $transformer, 'recurrences');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);
@@ -102,6 +111,13 @@ class ShowController extends Controller
{ {
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new RecurringEnrichment();
$enrichment->setUser($admin);
$recurrence = $enrichment->enrichSingle($recurrence);
/** @var RecurrenceTransformer $transformer */ /** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class); $transformer = app(RecurrenceTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Recurrence\StoreRequest; use FireflyIII\Api\V1\Requests\Models\Recurrence\StoreRequest;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
use FireflyIII\Transformers\RecurrenceTransformer; use FireflyIII\Transformers\RecurrenceTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
@@ -69,6 +71,13 @@ class StoreController extends Controller
$recurrence = $this->repository->store($data); $recurrence = $this->repository->store($data);
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new RecurringEnrichment();
$enrichment->setUser($admin);
$recurrence = $enrichment->enrichSingle($recurrence);
/** @var RecurrenceTransformer $transformer */ /** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class); $transformer = app(RecurrenceTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -28,7 +28,9 @@ use FireflyIII\Api\V1\Controllers\Controller;
use FireflyIII\Api\V1\Requests\Models\Recurrence\UpdateRequest; use FireflyIII\Api\V1\Requests\Models\Recurrence\UpdateRequest;
use FireflyIII\Models\Recurrence; use FireflyIII\Models\Recurrence;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
use FireflyIII\Transformers\RecurrenceTransformer; use FireflyIII\Transformers\RecurrenceTransformer;
use FireflyIII\User;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use League\Fractal\Resource\Item; use League\Fractal\Resource\Item;
@@ -67,6 +69,13 @@ class UpdateController extends Controller
$recurrence = $this->repository->update($recurrence, $data); $recurrence = $this->repository->update($recurrence, $data);
$manager = $this->getManager(); $manager = $this->getManager();
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new RecurringEnrichment();
$enrichment->setUser($admin);
$recurrence = $enrichment->enrichSingle($recurrence);
/** @var RecurrenceTransformer $transformer */ /** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class); $transformer = app(RecurrenceTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);

View File

@@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalAPIRepositoryInterface; use FireflyIII\Repositories\Journal\JournalAPIRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEventEnrichment;
use FireflyIII\Transformers\AttachmentTransformer; use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\PiggyBankEventTransformer; use FireflyIII\Transformers\PiggyBankEventTransformer;
use FireflyIII\Transformers\TransactionLinkTransformer; use FireflyIII\Transformers\TransactionLinkTransformer;
@@ -113,6 +114,14 @@ class ListController extends Controller
} }
$count = $collection->count(); $count = $collection->count();
$events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new PiggyBankEventEnrichment();
$enrichment->setUser($admin);
$events = $enrichment->enrich($events);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.transactions.piggy-bank-events', [$transactionGroup->id]).$this->buildParams()); $paginator->setPath(route('api.v1.transactions.piggy-bank-events', [$transactionGroup->id]).$this->buildParams());

View File

@@ -43,6 +43,8 @@ use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Support\Http\Api\AccountFilter; use FireflyIII\Support\Http\Api\AccountFilter;
use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Support\Http\Api\TransactionFilter;
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\BudgetLimitEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment; use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment; use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
use FireflyIII\Transformers\AccountTransformer; use FireflyIII\Transformers\AccountTransformer;
@@ -107,8 +109,8 @@ class ListController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);
// make paginator: // make paginator:
@@ -188,8 +190,6 @@ class ListController extends Controller
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new SubscriptionEnrichment(); $enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$enrichment->setStart($this->parameters->get('start')); $enrichment->setStart($this->parameters->get('start'));
$enrichment->setEnd($this->parameters->get('end')); $enrichment->setEnd($this->parameters->get('end'));
$bills = $enrichment->enrichSingle($bills); $bills = $enrichment->enrichSingle($bills);
@@ -229,6 +229,13 @@ class ListController extends Controller
$paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.budget-limits', [$currency->code]).$this->buildParams()); $paginator->setPath(route('api.v1.currencies.budget-limits', [$currency->code]).$this->buildParams());
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new BudgetLimitEnrichment();
$enrichment->setUser($admin);
$budgetLimits = $enrichment->enrich($budgetLimits);
/** @var BudgetLimitTransformer $transformer */ /** @var BudgetLimitTransformer $transformer */
$transformer = app(BudgetLimitTransformer::class); $transformer = app(BudgetLimitTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
@@ -270,17 +277,24 @@ class ListController extends Controller
} }
); );
$count = $collection->count(); $count = $collection->count();
$piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $recurrences = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new RecurringEnrichment();
$enrichment->setUser($admin);
$recurrences = $enrichment->enrich($recurrences);
// make paginator: // make paginator:
$paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); $paginator = new LengthAwarePaginator($recurrences, $count, $pageSize, $this->parameters->get('page'));
$paginator->setPath(route('api.v1.currencies.recurrences', [$currency->code]).$this->buildParams()); $paginator->setPath(route('api.v1.currencies.recurrences', [$currency->code]).$this->buildParams());
/** @var RecurrenceTransformer $transformer */ /** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class); $transformer = app(RecurrenceTransformer::class);
$transformer->setParameters($this->parameters); $transformer->setParameters($this->parameters);
$resource = new FractalCollection($piggyBanks, $transformer, 'recurrences'); $resource = new FractalCollection($recurrences, $transformer, 'recurrences');
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE);

View File

@@ -88,8 +88,8 @@ class AccountController extends Controller
/** @var User $admin */ /** @var User $admin */
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate($this->parameters->get('date'));
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);
/** @var AccountTransformer $transformer */ /** @var AccountTransformer $transformer */

View File

@@ -248,10 +248,10 @@ class BasicController extends Controller
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId]['sum'] ?? '0', false), 'value_parsed' => Amount::formatAnything($currency, $sums[$currencyId]['sum'] ?? '0', false),
'local_icon' => 'balance-scale', 'local_icon' => 'balance-scale',
'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId]['sum'] ?? '0', false) 'sub_title' => Amount::formatAnything($currency, $expenses[$currencyId]['sum'] ?? '0', false)
.' + '.app('amount')->formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false), .' + '.Amount::formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false),
]; ];
$return[] = [ $return[] = [
'key' => sprintf('spent-in-%s', $currency->code), 'key' => sprintf('spent-in-%s', $currency->code),
@@ -261,7 +261,7 @@ class BasicController extends Controller
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatAnything($currency, $expenses[$currencyId]['sum'] ?? '0', false), 'value_parsed' => Amount::formatAnything($currency, $expenses[$currencyId]['sum'] ?? '0', false),
'local_icon' => 'balance-scale', 'local_icon' => 'balance-scale',
'sub_title' => '', 'sub_title' => '',
]; ];
@@ -273,7 +273,7 @@ class BasicController extends Controller
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false), 'value_parsed' => Amount::formatAnything($currency, $incomes[$currencyId]['sum'] ?? '0', false),
'local_icon' => 'balance-scale', 'local_icon' => 'balance-scale',
'sub_title' => '', 'sub_title' => '',
]; ];
@@ -289,10 +289,10 @@ class BasicController extends Controller
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatAnything($currency, '0', false), 'value_parsed' => Amount::formatAnything($currency, '0', false),
'local_icon' => 'balance-scale', 'local_icon' => 'balance-scale',
'sub_title' => app('amount')->formatAnything($currency, '0', false) 'sub_title' => Amount::formatAnything($currency, '0', false)
.' + '.app('amount')->formatAnything($currency, '0', false), .' + '.Amount::formatAnything($currency, '0', false),
]; ];
$return[] = [ $return[] = [
'key' => sprintf('spent-in-%s', $currency->code), 'key' => sprintf('spent-in-%s', $currency->code),
@@ -302,7 +302,7 @@ class BasicController extends Controller
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatAnything($currency, '0', false), 'value_parsed' => Amount::formatAnything($currency, '0', false),
'local_icon' => 'balance-scale', 'local_icon' => 'balance-scale',
'sub_title' => '', 'sub_title' => '',
]; ];
@@ -314,7 +314,7 @@ class BasicController extends Controller
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatAnything($currency, '0', false), 'value_parsed' => Amount::formatAnything($currency, '0', false),
'local_icon' => 'balance-scale', 'local_icon' => 'balance-scale',
'sub_title' => '', 'sub_title' => '',
]; ];
@@ -405,7 +405,7 @@ class BasicController extends Controller
'currency_code' => $info['code'], 'currency_code' => $info['code'],
'currency_symbol' => $info['symbol'], 'currency_symbol' => $info['symbol'],
'currency_decimal_places' => $info['decimal_places'], 'currency_decimal_places' => $info['decimal_places'],
'value_parsed' => app('amount')->formatFlat($info['symbol'], $info['decimal_places'], $amount, false), 'value_parsed' => Amount::formatFlat($info['symbol'], $info['decimal_places'], $amount, false),
'local_icon' => 'check', 'local_icon' => 'check',
'sub_title' => '', 'sub_title' => '',
]; ];
@@ -424,7 +424,7 @@ class BasicController extends Controller
'currency_code' => $info['code'], 'currency_code' => $info['code'],
'currency_symbol' => $info['symbol'], 'currency_symbol' => $info['symbol'],
'currency_decimal_places' => $info['decimal_places'], 'currency_decimal_places' => $info['decimal_places'],
'value_parsed' => app('amount')->formatFlat($info['symbol'], $info['decimal_places'], $amount, false), 'value_parsed' => Amount::formatFlat($info['symbol'], $info['decimal_places'], $amount, false),
'local_icon' => 'calendar-o', 'local_icon' => 'calendar-o',
'sub_title' => '', 'sub_title' => '',
]; ];
@@ -443,7 +443,7 @@ class BasicController extends Controller
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatFlat($currency->symbol, $currency->decimal_places, '0', false), 'value_parsed' => Amount::formatFlat($currency->symbol, $currency->decimal_places, '0', false),
'local_icon' => 'check', 'local_icon' => 'check',
'sub_title' => '', 'sub_title' => '',
]; ];
@@ -455,7 +455,7 @@ class BasicController extends Controller
'currency_code' => $currency->code, 'currency_code' => $currency->code,
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
'currency_decimal_places' => $currency->decimal_places, 'currency_decimal_places' => $currency->decimal_places,
'value_parsed' => app('amount')->formatFlat($currency->symbol, $currency->decimal_places, '0', false), 'value_parsed' => Amount::formatFlat($currency->symbol, $currency->decimal_places, '0', false),
'local_icon' => 'calendar-o', 'local_icon' => 'calendar-o',
'sub_title' => '', 'sub_title' => '',
]; ];
@@ -493,14 +493,9 @@ class BasicController extends Controller
'currency_code' => $currencies[$currencyId]->code, 'currency_code' => $currencies[$currencyId]->code,
'currency_symbol' => $currencies[$currencyId]->symbol, 'currency_symbol' => $currencies[$currencyId]->symbol,
'currency_decimal_places' => $currencies[$currencyId]->decimal_places, 'currency_decimal_places' => $currencies[$currencyId]->decimal_places,
'value_parsed' => app('amount')->formatFlat($currencies[$currencyId]->symbol, $currencies[$currencyId]->decimal_places, $availableBudget, false), 'value_parsed' => Amount::formatFlat($currencies[$currencyId]->symbol, $currencies[$currencyId]->decimal_places, $availableBudget, false),
'local_icon' => 'money', 'local_icon' => 'money',
'sub_title' => app('amount')->formatFlat( 'sub_title' => Amount::formatFlat($currencies[$currencyId]->symbol, $currencies[$currencyId]->decimal_places, $availableBudget, false),
$currencies[$currencyId]->symbol,
$currencies[$currencyId]->decimal_places,
$availableBudget,
false
),
]; ];
} }
foreach ($spent as $row) { foreach ($spent as $row) {
@@ -529,18 +524,14 @@ class BasicController extends Controller
'currency_code' => $row['currency_code'], 'currency_code' => $row['currency_code'],
'currency_symbol' => $row['currency_symbol'], 'currency_symbol' => $row['currency_symbol'],
'currency_decimal_places' => $row['currency_decimal_places'], 'currency_decimal_places' => $row['currency_decimal_places'],
'value_parsed' => app('amount')->formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $leftToSpend, false), 'value_parsed' => Amount::formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $leftToSpend, false),
'local_icon' => 'money', 'local_icon' => 'money',
'sub_title' => app('amount')->formatFlat( 'sub_title' => Amount::formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $perDay, false),
$row['currency_symbol'],
$row['currency_decimal_places'],
$perDay,
false
),
]; ];
} }
unset($leftToSpend); unset($leftToSpend);
if (0 === count($return)) { if (0 === count($return)) {
$days = (int) $start->diffInDays($end, true) + 1;
// a small trick to get every expense in this period, regardless of budget. // a small trick to get every expense in this period, regardless of budget.
$spent = $this->opsRepository->sumExpenses($start, $end, null, new Collection()); $spent = $this->opsRepository->sumExpenses($start, $end, null, new Collection());
foreach ($spent as $row) { foreach ($spent as $row) {
@@ -563,14 +554,9 @@ class BasicController extends Controller
'currency_code' => $row['currency_code'], 'currency_code' => $row['currency_code'],
'currency_symbol' => $row['currency_symbol'], 'currency_symbol' => $row['currency_symbol'],
'currency_decimal_places' => $row['currency_decimal_places'], 'currency_decimal_places' => $row['currency_decimal_places'],
'value_parsed' => app('amount')->formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $spentInCurrency, false), 'value_parsed' => Amount::formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $spentInCurrency, false),
'local_icon' => 'money', 'local_icon' => 'money',
'sub_title' => app('amount')->formatFlat( 'sub_title' => Amount::formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $perDay, false),
$row['currency_symbol'],
$row['currency_decimal_places'],
$perDay,
false
),
]; ];
} }
@@ -587,9 +573,9 @@ class BasicController extends Controller
// 'currency_code' => $currency->code, // 'currency_code' => $currency->code,
// 'currency_symbol' => $currency->symbol, // 'currency_symbol' => $currency->symbol,
// 'currency_decimal_places' => $currency->decimal_places, // 'currency_decimal_places' => $currency->decimal_places,
// 'value_parsed' => app('amount')->formatFlat($currency->symbol, $currency->decimal_places, '0', false), // 'value_parsed' => Amount::formatFlat($currency->symbol, $currency->decimal_places, '0', false),
// 'local_icon' => 'money', // 'local_icon' => 'money',
// 'sub_title' => app('amount')->formatFlat( // 'sub_title' => Amount::formatFlat(
// $currency->symbol, // $currency->symbol,
// $currency->decimal_places, // $currency->decimal_places,
// '0', // '0',
@@ -642,7 +628,7 @@ class BasicController extends Controller
'currency_code' => $data['currency_code'], 'currency_code' => $data['currency_code'],
'currency_symbol' => $data['currency_symbol'], 'currency_symbol' => $data['currency_symbol'],
'currency_decimal_places' => $data['currency_decimal_places'], 'currency_decimal_places' => $data['currency_decimal_places'],
'value_parsed' => app('amount')->formatFlat($data['currency_symbol'], $data['currency_decimal_places'], $data['balance'], false), 'value_parsed' => Amount::formatFlat($data['currency_symbol'], $data['currency_decimal_places'], $data['balance'], false),
'local_icon' => 'line-chart', 'local_icon' => 'line-chart',
'sub_title' => '', 'sub_title' => '',
]; ];
@@ -656,7 +642,7 @@ class BasicController extends Controller
'currency_code' => $this->primaryCurrency->code, 'currency_code' => $this->primaryCurrency->code,
'currency_symbol' => $this->primaryCurrency->symbol, 'currency_symbol' => $this->primaryCurrency->symbol,
'currency_decimal_places' => $this->primaryCurrency->decimal_places, 'currency_decimal_places' => $this->primaryCurrency->decimal_places,
'value_parsed' => app('amount')->formatFlat($this->primaryCurrency->symbol, $this->primaryCurrency->decimal_places, '0', false), 'value_parsed' => Amount::formatFlat($this->primaryCurrency->symbol, $this->primaryCurrency->decimal_places, '0', false),
'local_icon' => 'line-chart', 'local_icon' => 'line-chart',
'sub_title' => '', 'sub_title' => '',
]; ];

View File

@@ -54,6 +54,7 @@ class CronController extends Controller
$return['exchange_rates'] = $this->exchangeRatesCronJob($config['force'], $config['date']); $return['exchange_rates'] = $this->exchangeRatesCronJob($config['force'], $config['date']);
} }
$return['bill_notifications'] = $this->billWarningCronJob($config['force'], $config['date']); $return['bill_notifications'] = $this->billWarningCronJob($config['force'], $config['date']);
$return['webhooks'] = $this->webhookCronJob($config['force'], $config['date']);
return response()->api($return); return response()->api($return);
} }

View File

@@ -1,62 +0,0 @@
<?php
/*
* DateRequest.php
* Copyright (c) 2021 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Generic;
use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest;
/**
* Request class for end points that require date parameters.
*
* Class DateRequest
*/
class DateRequest extends FormRequest
{
use ChecksLogin;
use ConvertsDataTypes;
/**
* Get all data from the request.
*/
public function getAll(): array
{
return [
'start' => $this->getCarbonDate('start')->startOfDay(),
'end' => $this->getCarbonDate('end')->endOfDay(),
];
}
/**
* The rules that the incoming request must be matched against.
*/
public function rules(): array
{
return [
'start' => 'required|date|after:1970-01-02|before:2038-01-17',
'end' => 'required|date|after_or_equal:start|before:2038-01-17|after:1970-01-02',
];
}
}

View File

@@ -25,7 +25,6 @@ declare(strict_types=1);
namespace FireflyIII\Api\V1\Requests\Models\PiggyBank; namespace FireflyIII\Api\V1\Requests\Models\PiggyBank;
use Illuminate\Contracts\Validation\Validator; use Illuminate\Contracts\Validation\Validator;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Rules\IsValidZeroOrMoreAmount; use FireflyIII\Rules\IsValidZeroOrMoreAmount;
@@ -96,7 +95,10 @@ class StoreRequest extends FormRequest
function (Validator $validator): void { function (Validator $validator): void {
// validate start before end only if both are there. // validate start before end only if both are there.
$data = $validator->getData(); $data = $validator->getData();
$currency = $this->getCurrencyFromData($data); $currency = $this->getCurrencyFromData($validator, $data);
if (null === $currency) {
return;
}
$targetAmount = (string) ($data['target_amount'] ?? '0'); $targetAmount = (string) ($data['target_amount'] ?? '0');
$currentAmount = '0'; $currentAmount = '0';
if (array_key_exists('accounts', $data) && is_array($data['accounts'])) { if (array_key_exists('accounts', $data) && is_array($data['accounts'])) {
@@ -130,7 +132,7 @@ class StoreRequest extends FormRequest
} }
} }
private function getCurrencyFromData(array $data): TransactionCurrency private function getCurrencyFromData(Validator $validator, array $data): ?TransactionCurrency
{ {
if (array_key_exists('transaction_currency_code', $data) && '' !== (string) $data['transaction_currency_code']) { if (array_key_exists('transaction_currency_code', $data) && '' !== (string) $data['transaction_currency_code']) {
$currency = TransactionCurrency::whereCode($data['transaction_currency_code'])->first(); $currency = TransactionCurrency::whereCode($data['transaction_currency_code'])->first();
@@ -144,7 +146,8 @@ class StoreRequest extends FormRequest
return $currency; return $currency;
} }
} }
$validator->errors()->add('transaction_currency_id', trans('validation.require_currency_id_code'));
throw new FireflyException('Unexpected empty currency.'); return null;
} }
} }

View File

@@ -63,10 +63,10 @@ class CorrectsCurrencies extends Command
$repos = app(CurrencyRepositoryInterface::class); $repos = app(CurrencyRepositoryInterface::class);
// first check if the user has any default currency (not necessarily the case, so can be forced). // first check if the user has any default currency (not necessarily the case, so can be forced).
$defaultCurrency = app('amount')->getPrimaryCurrencyByUserGroup($userGroup); $primaryCurrency = app('amount')->getPrimaryCurrencyByUserGroup($userGroup);
Log::debug(sprintf('Now correcting currencies for user group #%d', $userGroup->id)); Log::debug(sprintf('Now correcting currencies for user group #%d', $userGroup->id));
$found = [$defaultCurrency->id]; $found = [$primaryCurrency->id];
// get all meta entries // get all meta entries
$meta = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id') $meta = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id')

View File

@@ -40,6 +40,7 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\UserGroup; use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface; use FireflyIII\Repositories\UserGroup\UserGroupRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Preferences; use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Http\Api\ExchangeRateConverter; use FireflyIII\Support\Http\Api\ExchangeRateConverter;
use Illuminate\Console\Command; use Illuminate\Console\Command;
@@ -72,6 +73,8 @@ class CorrectsPrimaryCurrencyAmounts extends Command
/** @var UserGroupRepositoryInterface $repository */ /** @var UserGroupRepositoryInterface $repository */
$repository = app(UserGroupRepositoryInterface::class); $repository = app(UserGroupRepositoryInterface::class);
Preferences::mark();
/** @var UserGroup $userGroup */ /** @var UserGroup $userGroup */
foreach ($repository->getAll() as $userGroup) { foreach ($repository->getAll() as $userGroup) {
$this->recalculateForGroup($userGroup); $this->recalculateForGroup($userGroup);
@@ -87,8 +90,7 @@ class CorrectsPrimaryCurrencyAmounts extends Command
$this->recalculateAccounts($userGroup); $this->recalculateAccounts($userGroup);
// do a check with the group's currency so we can skip some stuff. // do a check with the group's currency so we can skip some stuff.
Preferences::mark(); $currency = Amount::getPrimaryCurrencyByUserGroup($userGroup);
$currency = app('amount')->getPrimaryCurrencyByUserGroup($userGroup);
$this->recalculatePiggyBanks($userGroup, $currency); $this->recalculatePiggyBanks($userGroup, $currency);
$this->recalculateBudgets($userGroup, $currency); $this->recalculateBudgets($userGroup, $currency);

View File

@@ -32,6 +32,7 @@ use FireflyIII\Support\Cronjobs\BillWarningCronjob;
use FireflyIII\Support\Cronjobs\ExchangeRatesCronjob; use FireflyIII\Support\Cronjobs\ExchangeRatesCronjob;
use FireflyIII\Support\Cronjobs\RecurringCronjob; use FireflyIII\Support\Cronjobs\RecurringCronjob;
use FireflyIII\Support\Cronjobs\UpdateCheckCronjob; use FireflyIII\Support\Cronjobs\UpdateCheckCronjob;
use FireflyIII\Support\Cronjobs\WebhookCronjob;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use InvalidArgumentException; use InvalidArgumentException;
@@ -50,6 +51,7 @@ class Cron extends Command
{--create-recurring : Create recurring transactions. Other tasks will be skipped unless also requested.} {--create-recurring : Create recurring transactions. Other tasks will be skipped unless also requested.}
{--create-auto-budgets : Create auto budgets. Other tasks will be skipped unless also requested.} {--create-auto-budgets : Create auto budgets. Other tasks will be skipped unless also requested.}
{--send-bill-warnings : Send bill warnings. Other tasks will be skipped unless also requested.} {--send-bill-warnings : Send bill warnings. Other tasks will be skipped unless also requested.}
{--send-webhook-messages : Sends any stray webhook messages (with a maximum of 5).}
'; ';
public function handle(): int public function handle(): int
@@ -58,7 +60,8 @@ class Cron extends Command
&& !$this->option('create-recurring') && !$this->option('create-recurring')
&& !$this->option('create-auto-budgets') && !$this->option('create-auto-budgets')
&& !$this->option('send-bill-warnings') && !$this->option('send-bill-warnings')
&& !$this->option('check-version'); && !$this->option('check-version')
&& !$this->option('send-webhook-messages');
$date = null; $date = null;
try { try {
@@ -122,6 +125,16 @@ class Cron extends Command
$this->friendlyError($e->getMessage()); $this->friendlyError($e->getMessage());
} }
} }
// Fire webhook messages cron job.
if ($doAll || $this->option('send-webhook-messages')) {
try {
$this->webhookCronJob($force, $date);
} catch (FireflyException $e) {
app('log')->error($e->getMessage());
app('log')->error($e->getTraceAsString());
$this->friendlyError($e->getMessage());
}
}
$this->friendlyInfo('More feedback on the cron jobs can be found in the log files.'); $this->friendlyInfo('More feedback on the cron jobs can be found in the log files.');
@@ -239,4 +252,26 @@ class Cron extends Command
$this->friendlyPositive(sprintf('"Send bill warnings" cron ran with success: %s', $autoBudget->message)); $this->friendlyPositive(sprintf('"Send bill warnings" cron ran with success: %s', $autoBudget->message));
} }
} }
private function webhookCronJob(bool $force, ?Carbon $date): void
{
$webhook = new WebhookCronjob();
$webhook->setForce($force);
// set date in cron job:
if ($date instanceof Carbon) {
$webhook->setDate($date);
}
$webhook->fire();
if ($webhook->jobErrored) {
$this->friendlyError(sprintf('Error in "webhook" cron: %s', $webhook->message));
}
if ($webhook->jobFired) {
$this->friendlyInfo(sprintf('"Webhook" cron fired: %s', $webhook->message));
}
if ($webhook->jobSucceeded) {
$this->friendlyPositive(sprintf('"Webhook" cron ran with success: %s', $webhook->message));
}
}
} }

View File

@@ -108,11 +108,11 @@ class UpgradesAccountCurrencies extends Command
$accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value]); $accounts = $this->accountRepos->getAccountsByType([AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value]);
// get user's currency preference: // get user's currency preference:
$defaultCurrency = app('amount')->getPrimaryCurrencyByUserGroup($user->userGroup); $primaryCurrency = app('amount')->getPrimaryCurrencyByUserGroup($user->userGroup);
/** @var Account $account */ /** @var Account $account */
foreach ($accounts as $account) { foreach ($accounts as $account) {
$this->updateAccount($account, $defaultCurrency); $this->updateAccount($account, $primaryCurrency);
} }
} }

View File

@@ -117,13 +117,13 @@ class UpgradesCurrencyPreferences extends Command
// set the default currency for the user and for the group: // set the default currency for the user and for the group:
$preference = $this->getPreference($user); $preference = $this->getPreference($user);
$defaultCurrency = TransactionCurrency::where('code', $preference)->first(); $primaryCurrency = TransactionCurrency::where('code', $preference)->first();
if (null === $defaultCurrency) { if (null === $primaryCurrency) {
// get EUR // get EUR
$defaultCurrency = TransactionCurrency::where('code', 'EUR')->first(); $primaryCurrency = TransactionCurrency::where('code', 'EUR')->first();
} }
$user->currencies()->updateExistingPivot($defaultCurrency->id, ['user_default' => true]); $user->currencies()->updateExistingPivot($primaryCurrency->id, ['user_default' => true]);
$user->userGroup->currencies()->updateExistingPivot($defaultCurrency->id, ['group_default' => true]); $user->userGroup->currencies()->updateExistingPivot($primaryCurrency->id, ['group_default' => true]);
} }
private function getPreference(User $user): string private function getPreference(User $user): string

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Events\Model\Bill;
use FireflyIII\Events\Event;
use FireflyIII\Models\Bill;
use Illuminate\Queue\SerializesModels;
/**
* Class WarnUserAboutBill.
*/
class WarnUserAboutBill extends Event
{
use SerializesModels;
public function __construct(public Bill $bill, public string $field, public int $diff) {}
}

View File

@@ -0,0 +1,17 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Events\Model\Bill;
use FireflyIII\Events\Event;
use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
class WarnUserAboutOverdueSubscriptions extends Event
{
use SerializesModels;
public function __construct(public User $user, public array $overdue) {}
}

View File

@@ -1,7 +1,7 @@
<?php <?php
/* /*
* UserGroupChangedDefaultCurrency.php * UserGroupChangedPrimaryCurrency.php
* Copyright (c) 2024 james@firefly-iii.org. * Copyright (c) 2024 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).
@@ -29,12 +29,12 @@ use FireflyIII\Models\UserGroup;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
class UserGroupChangedDefaultCurrency extends Event class UserGroupChangedPrimaryCurrency extends Event
{ {
use SerializesModels; use SerializesModels;
public function __construct(public UserGroup $userGroup) public function __construct(public UserGroup $userGroup)
{ {
Log::debug('User group changed default currency.'); Log::debug('User group changed primary currency.');
} }
} }

View File

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

View File

@@ -126,7 +126,7 @@ class PiggyBankFactory
private function getCurrency(array $data): TransactionCurrency private function getCurrency(array $data): TransactionCurrency
{ {
// currency: // currency:
$defaultCurrency = app('amount')->getPrimaryCurrency(); $primaryCurrency = app('amount')->getPrimaryCurrency();
$currency = null; $currency = null;
if (array_key_exists('transaction_currency_code', $data)) { if (array_key_exists('transaction_currency_code', $data)) {
$currency = $this->currencyRepository->findByCode((string)($data['transaction_currency_code'] ?? '')); $currency = $this->currencyRepository->findByCode((string)($data['transaction_currency_code'] ?? ''));
@@ -134,7 +134,7 @@ class PiggyBankFactory
if (array_key_exists('transaction_currency_id', $data)) { if (array_key_exists('transaction_currency_id', $data)) {
$currency = $this->currencyRepository->find((int)($data['transaction_currency_id'] ?? 0)); $currency = $this->currencyRepository->find((int)($data['transaction_currency_id'] ?? 0));
} }
$currency ??= $defaultCurrency; $currency ??= $primaryCurrency;
return $currency; return $currency;
} }

View File

@@ -141,8 +141,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
Log::debug(sprintf('getAuditReport: Call finalAccountBalance with date/time "%s"', $date->toIso8601String())); Log::debug(sprintf('getAuditReport: Call finalAccountBalance with date/time "%s"', $date->toIso8601String()));
$dayBeforeBalance = Steam::finalAccountBalance($account, $date); $dayBeforeBalance = Steam::finalAccountBalance($account, $date);
$startBalance = $dayBeforeBalance['balance']; $startBalance = $dayBeforeBalance['balance'];
$defaultCurrency = app('amount')->getPrimaryCurrencyByUserGroup($account->user->userGroup); $primaryCurrency = app('amount')->getPrimaryCurrencyByUserGroup($account->user->userGroup);
$currency = $accountRepository->getAccountCurrency($account) ?? $defaultCurrency; $currency = $accountRepository->getAccountCurrency($account) ?? $primaryCurrency;
foreach ($journals as $index => $journal) { foreach ($journals as $index => $journal) {
$journals[$index]['balance_before'] = $startBalance; $journals[$index]['balance_before'] = $startBalance;

View File

@@ -32,7 +32,6 @@ use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\Webhook; use FireflyIII\Models\Webhook;
use FireflyIII\Models\WebhookMessage; use FireflyIII\Models\WebhookMessage;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use FireflyIII\Transformers\AccountTransformer; use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\Transformers\TransactionGroupTransformer;
@@ -176,8 +175,8 @@ class StandardMessageGenerator implements MessageGeneratorInterface
/** @var TransactionGroup $model */ /** @var TransactionGroup $model */
$accounts = $this->collectAccounts($model); $accounts = $this->collectAccounts($model);
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setDate(null);
$enrichment->setUser($model->user); $enrichment->setUser($model->user);
$enrichment->setPrimaryCurrency(Amount::getPrimaryCurrencyByUserGroup($model->userGroup));
$accounts = $enrichment->enrich($accounts); $accounts = $enrichment->enrich($accounts);
foreach ($accounts as $account) { foreach ($accounts as $account) {
$transformer = new AccountTransformer(); $transformer = new AccountTransformer();

View File

@@ -24,48 +24,118 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Events; namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\WarnUserAboutBill;
use FireflyIII\Notifications\User\BillReminder;
use Illuminate\Support\Facades\Notification;
use Exception; use Exception;
use FireflyIII\Events\Model\Bill\WarnUserAboutBill;
use FireflyIII\Events\Model\Bill\WarnUserAboutOverdueSubscriptions;
use FireflyIII\Models\Bill;
use FireflyIII\Notifications\User\BillReminder;
use FireflyIII\Notifications\User\SubscriptionsOverdueReminder;
use FireflyIII\Support\Facades\Preferences;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
/** /**
* Class BillEventHandler * Class BillEventHandler
*/ */
class BillEventHandler class BillEventHandler
{ {
public function warnAboutOverdueSubscriptions(WarnUserAboutOverdueSubscriptions $event): void
{
Log::debug(sprintf('Now in %s', __METHOD__));
// make sure user does not get the warning twice.
$overdue = $event->overdue;
$user = $event->user;
$toBeWarned = [];
Log::debug(sprintf('%d bills to warn about.', count($overdue)));
foreach ($overdue as $item) {
/** @var Bill $bill */
$bill = $item['bill'];
$key = sprintf('bill_overdue_%s_%s', $bill->id, substr(hash('sha256', json_encode($item['dates']['pay_dates'], JSON_THROW_ON_ERROR)), 0, 10));
$pref = Preferences::getForUser($bill->user, $key, false);
if (true === $pref->data) {
Log::debug(sprintf('User #%d has already been warned about overdue subscription #%d.', $bill->user->id, $bill->id));
continue;
}
$toBeWarned[] = $item;
}
unset($bill);
Log::debug(sprintf('Now %d bills to warn about.', count($toBeWarned)));
/** @var bool $sendNotification */
$sendNotification = Preferences::getForUser($user, 'notification_bill_reminder', true)->data;
if (false === $sendNotification) {
Log::debug('User has disabled bill reminders.');
return;
}
Log::debug(sprintf('Will warn about %d overdue subscription(s).', count($toBeWarned)));
if (0 === count($toBeWarned)) {
Log::debug('No overdue subscriptions to warn about.');
return;
}
foreach ($toBeWarned as $item) {
/** @var Bill $bill */
$bill = $item['bill'];
$key = sprintf('bill_overdue_%s_%s', $bill->id, substr(hash('sha256', json_encode($item['dates']['pay_dates'], JSON_THROW_ON_ERROR)), 0, 10));
Preferences::setForUser($bill->user, $key, true);
}
Log::warning('should hit this ONCE');
try {
Notification::send($user, new SubscriptionsOverdueReminder($toBeWarned));
} catch (Exception $e) {
$message = $e->getMessage();
if (str_contains($message, 'Bcc')) {
Log::warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
if (str_contains($message, 'RFC 2822')) {
Log::warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return;
}
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
}
public function warnAboutBill(WarnUserAboutBill $event): void public function warnAboutBill(WarnUserAboutBill $event): void
{ {
app('log')->debug(sprintf('Now in %s', __METHOD__)); Log::debug(sprintf('Now in %s', __METHOD__));
$bill = $event->bill; $bill = $event->bill;
/** @var bool $preference */ /** @var bool $preference */
$preference = app('preferences')->getForUser($bill->user, 'notification_bill_reminder', true)->data; Preferences::getForUser($bill->user, 'notification_bill_reminder', true)->data;
if (true === $preference) { if (true === $preference) {
app('log')->debug('Bill reminder is true!'); Log::debug('Bill reminder is true!');
try { try {
Notification::send($bill->user, new BillReminder($bill, $event->field, $event->diff)); Notification::send($bill->user, new BillReminder($bill, $event->field, $event->diff));
} catch (Exception $e) { } catch (Exception $e) {
$message = $e->getMessage(); $message = $e->getMessage();
if (str_contains($message, 'Bcc')) { if (str_contains($message, 'Bcc')) {
app('log')->warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.'); Log::warning('[Bcc] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return; return;
} }
if (str_contains($message, 'RFC 2822')) { if (str_contains($message, 'RFC 2822')) {
app('log')->warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.'); Log::warning('[RFC] Could not send notification. Please validate your email settings, use the .env.example file as a guide.');
return; return;
} }
app('log')->error($e->getMessage()); Log::error($e->getMessage());
app('log')->error($e->getTraceAsString()); Log::error($e->getTraceAsString());
} }
return;
} }
if (false === $preference) { Log::debug('User has disabled bill reminders.');
app('log')->debug('User has disabled bill reminders.');
}
} }
} }

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Events; namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\Preferences\UserGroupChangedDefaultCurrency; use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\UserGroup; use FireflyIII\Models\UserGroup;
@@ -38,7 +38,7 @@ use Illuminate\Support\Facades\Log;
class PreferencesEventHandler class PreferencesEventHandler
{ {
public function resetPrimaryCurrencyAmounts(UserGroupChangedDefaultCurrency $event): void public function resetPrimaryCurrencyAmounts(UserGroupChangedPrimaryCurrency $event): void
{ {
// Reset the primary currency amounts for all objects that have it. // Reset the primary currency amounts for all objects that have it.
Log::debug('Resetting primary currency amounts for all objects.'); Log::debug('Resetting primary currency amounts for all objects.');
@@ -73,6 +73,7 @@ class PreferencesEventHandler
$repository = app(PiggyBankRepositoryInterface::class); $repository = app(PiggyBankRepositoryInterface::class);
$repository->setUserGroup($userGroup); $repository->setUserGroup($userGroup);
$piggyBanks = $repository->getPiggyBanks(); $piggyBanks = $repository->getPiggyBanks();
Log::debug(sprintf('Resetting %d piggy bank(s).', $piggyBanks->count()));
/** @var PiggyBank $piggyBank */ /** @var PiggyBank $piggyBank */
foreach ($piggyBanks as $piggyBank) { foreach ($piggyBanks as $piggyBank) {
@@ -104,6 +105,8 @@ class PreferencesEventHandler
$repository->setUserGroup($userGroup); $repository->setUserGroup($userGroup);
$set = $repository->getBudgets(); $set = $repository->getBudgets();
Log::debug(sprintf('Resetting %d budget(s).', $set->count()));
/** @var Budget $budget */ /** @var Budget $budget */
foreach ($set as $budget) { foreach ($set as $budget) {
foreach ($budget->autoBudgets as $autoBudget) { foreach ($budget->autoBudgets as $autoBudget) {

View File

@@ -77,8 +77,8 @@ class NetWorth implements NetWorthInterface
Log::debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d H:i:s'))); Log::debug(sprintf('Now in byAccounts("%s", "%s")', $ids, $date->format('Y-m-d H:i:s')));
$primary = Amount::getPrimaryCurrency(); $primary = Amount::getPrimaryCurrency();
$netWorth = []; $netWorth = [];
Log::debug(sprintf('NetWorth: finalAccountsBalance("%s")', $date->format('Y-m-d H:i:s'))); Log::debug(sprintf('NetWorth: accountsBalancesOptimized("%s")', $date->format('Y-m-d H:i:s')));
$balances = Steam::finalAccountsBalance($accounts, $date); $balances = Steam::accountsBalancesOptimized($accounts, $date, null, $convertToPrimary);
/** @var Account $account */ /** @var Account $account */
foreach ($accounts as $account) { foreach ($accounts as $account) {
@@ -143,8 +143,8 @@ class NetWorth implements NetWorthInterface
*/ */
$accounts = $this->getAccounts(); $accounts = $this->getAccounts();
$return = []; $return = [];
Log::debug(sprintf('SumNetWorth: finalAccountsBalance("%s")', $date->format('Y-m-d H:i:s'))); Log::debug(sprintf('SumNetWorth: accountsBalancesOptimized("%s")', $date->format('Y-m-d H:i:s')));
$balances = Steam::finalAccountsBalance($accounts, $date); $balances = Steam::accountsBalancesOptimized($accounts, $date);
foreach ($accounts as $account) { foreach ($accounts as $account) {
$currency = $this->accountRepository->getAccountCurrency($account); $currency = $this->accountRepository->getAccountCurrency($account);
$balance = $balances[$account->id]['balance'] ?? '0'; $balance = $balances[$account->id]['balance'] ?? '0';

View File

@@ -93,10 +93,10 @@ class IndexController extends Controller
$start->subSecond(); $start->subSecond();
$ids = $accounts->pluck('id')->toArray(); $ids = $accounts->pluck('id')->toArray();
Log::debug(sprintf('inactive start: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s'))); Log::debug(sprintf('inactive start: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
Log::debug(sprintf('inactive end: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s'))); Log::debug(sprintf('inactive end: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
$startBalances = Steam::finalAccountsBalance($accounts, $start); $startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
$endBalances = Steam::finalAccountsBalance($accounts, $end); $endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
$activities = Steam::getLastActivities($ids); $activities = Steam::getLastActivities($ids);
@@ -170,10 +170,10 @@ class IndexController extends Controller
$start->subSecond(); $start->subSecond();
$ids = $accounts->pluck('id')->toArray(); $ids = $accounts->pluck('id')->toArray();
Log::debug(sprintf('index start: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s'))); Log::debug(sprintf('index start: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
Log::debug(sprintf('index end: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s'))); Log::debug(sprintf('index end: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
$startBalances = Steam::finalAccountsBalance($accounts, $start); $startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
$endBalances = Steam::finalAccountsBalance($accounts, $end); $endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
$activities = Steam::getLastActivities($ids); $activities = Steam::getLastActivities($ids);

View File

@@ -40,6 +40,7 @@ use Illuminate\Routing\Redirector;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Illuminate\View\View; use Illuminate\View\View;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/** /**
* Class ShowController * Class ShowController
@@ -81,7 +82,9 @@ class ShowController extends Controller
* */ * */
public function show(Request $request, Account $account, ?Carbon $start = null, ?Carbon $end = null) public function show(Request $request, Account $account, ?Carbon $start = null, ?Carbon $end = null)
{ {
if (0 === $account->id) {
throw new NotFoundHttpException();
}
$objectType = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type)); $objectType = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type));
if (!$this->isEditableAccount($account)) { if (!$this->isEditableAccount($account)) {
@@ -115,20 +118,27 @@ class ShowController extends Controller
$chartUrl = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]); $chartUrl = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]);
$firstTransaction = $this->repository->oldestJournalDate($account) ?? $start; $firstTransaction = $this->repository->oldestJournalDate($account) ?? $start;
Log::debug('Start period overview'); // go back max 3 years.
Timer::start('period-overview'); $threeYearsAgo = clone $start;
$threeYearsAgo->startOfYear()->subYears(3);
if ($firstTransaction->lt($threeYearsAgo)) {
$firstTransaction = clone $threeYearsAgo;
}
Log::debug('Start period overview');
$timer = Timer::getInstance();
$timer->start('period-overview');
$periods = $this->getAccountPeriodOverview($account, $firstTransaction, $end); $periods = $this->getAccountPeriodOverview($account, $firstTransaction, $end);
Log::debug('End period overview'); Log::debug('End period overview');
Timer::stop('period-overview'); $timer->stop('period-overview');
// if layout = v2, overrule the page title. // if layout = v2, overrule the page title.
if ('v1' !== config('view.layout')) { if ('v1' !== config('view.layout')) {
$subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]); $subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]);
} }
Log::debug('Collect transactions'); Log::debug('Collect transactions');
Timer::start('collection'); $timer->start('collection');
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
@@ -136,6 +146,7 @@ class ShowController extends Controller
->setAccounts(new Collection([$account])) ->setAccounts(new Collection([$account]))
->setLimit($pageSize) ->setLimit($pageSize)
->setPage($page) ->setPage($page)
->withAttachmentInformation()
->withAPIInformation() ->withAPIInformation()
->setRange($start, $end) ->setRange($start, $end)
; ;
@@ -146,7 +157,7 @@ class ShowController extends Controller
Log::debug('End collect transactions'); Log::debug('End collect transactions');
Timer::stop('collection'); $timer->stop('collection');
// enrich data in arrays. // enrich data in arrays.

View File

@@ -77,7 +77,7 @@ class CreateController extends Controller
$periods[$current] = (string) trans('firefly.repeat_freq_'.$current); $periods[$current] = (string) trans('firefly.repeat_freq_'.$current);
} }
$subTitle = (string) trans('firefly.create_new_bill'); $subTitle = (string) trans('firefly.create_new_bill');
$defaultCurrency = $this->primaryCurrency; $primaryCurrency = $this->primaryCurrency;
// put previous url in session if not redirect from store (not "create another"). // put previous url in session if not redirect from store (not "create another").
if (true !== session('bills.create.fromStore')) { if (true !== session('bills.create.fromStore')) {
@@ -85,7 +85,7 @@ class CreateController extends Controller
} }
$request->session()->forget('bills.create.fromStore'); $request->session()->forget('bills.create.fromStore');
return view('bills.create', compact('periods', 'subTitle', 'defaultCurrency')); return view('bills.create', compact('periods', 'subTitle', 'primaryCurrency'));
} }
/** /**

View File

@@ -88,7 +88,7 @@ class EditController extends Controller
$bill->amount_min = app('steam')->bcround($bill->amount_min, $bill->transactionCurrency->decimal_places); $bill->amount_min = app('steam')->bcround($bill->amount_min, $bill->transactionCurrency->decimal_places);
$bill->amount_max = app('steam')->bcround($bill->amount_max, $bill->transactionCurrency->decimal_places); $bill->amount_max = app('steam')->bcround($bill->amount_max, $bill->transactionCurrency->decimal_places);
$rules = $this->repository->getRulesForBill($bill); $rules = $this->repository->getRulesForBill($bill);
$defaultCurrency = $this->primaryCurrency; $primaryCurrency = $this->primaryCurrency;
// code to handle active-checkboxes // code to handle active-checkboxes
$hasOldInput = null !== $request->old('_token'); $hasOldInput = null !== $request->old('_token');
@@ -105,7 +105,7 @@ class EditController extends Controller
$request->session()->flash('preFilled', $preFilled); $request->session()->flash('preFilled', $preFilled);
$request->session()->forget('bills.edit.fromUpdate'); $request->session()->forget('bills.edit.fromUpdate');
return view('bills.edit', compact('subTitle', 'periods', 'rules', 'bill', 'defaultCurrency', 'preFilled')); return view('bills.edit', compact('subTitle', 'periods', 'rules', 'bill', 'primaryCurrency', 'preFilled'));
} }
/** /**

View File

@@ -57,7 +57,7 @@ class IndexController extends Controller
$this->middleware( $this->middleware(
function ($request, $next) { function ($request, $next) {
app('view')->share('title', (string) trans('firefly.bills')); app('view')->share('title', (string)trans('firefly.bills'));
app('view')->share('mainTitleIcon', 'fa-calendar-o'); app('view')->share('mainTitleIcon', 'fa-calendar-o');
$this->repository = app(BillRepositoryInterface::class); $this->repository = app(BillRepositoryInterface::class);
@@ -79,7 +79,6 @@ class IndexController extends Controller
$total = $collection->count(); $total = $collection->count();
$parameters = new ParameterBag(); $parameters = new ParameterBag();
// sub one day from temp start so the last paid date is one day before it should be. // sub one day from temp start so the last paid date is one day before it should be.
$tempStart = clone $start; $tempStart = clone $start;
@@ -91,8 +90,6 @@ class IndexController extends Controller
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new SubscriptionEnrichment(); $enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$enrichment->setStart($tempStart); $enrichment->setStart($tempStart);
$enrichment->setEnd($end); $enrichment->setEnd($end);
$collection = $enrichment->enrich($collection); $collection = $enrichment->enrich($collection);
@@ -101,7 +98,7 @@ class IndexController extends Controller
$parameters->set('start', $tempStart); $parameters->set('start', $tempStart);
$parameters->set('end', $end); $parameters->set('end', $end);
$parameters->set('convertToPrimary', $this->convertToPrimary); $parameters->set('convertToPrimary', $this->convertToPrimary);
$parameters->set('defaultCurrency', $this->primaryCurrency); $parameters->set('primaryCurrency', $this->primaryCurrency);
/** @var BillTransformer $transformer */ /** @var BillTransformer $transformer */
$transformer = app(BillTransformer::class); $transformer = app(BillTransformer::class);
@@ -114,7 +111,7 @@ class IndexController extends Controller
$bills = [ $bills = [
0 => [ // the index is the order, not the ID. 0 => [ // the index is the order, not the ID.
'object_group_id' => 0, 'object_group_id' => 0,
'object_group_title' => (string) trans('firefly.default_group_title_name'), 'object_group_title' => (string)trans('firefly.default_group_title_name'),
'bills' => [], 'bills' => [],
], ],
]; ];
@@ -122,7 +119,7 @@ class IndexController extends Controller
/** @var Bill $bill */ /** @var Bill $bill */
foreach ($collection as $bill) { foreach ($collection as $bill) {
$array = $transformer->transform($bill); $array = $transformer->transform($bill);
$groupOrder = (int) $array['object_group_order']; $groupOrder = (int)$array['object_group_order'];
// make group array if necessary: // make group array if necessary:
$bills[$groupOrder] ??= [ $bills[$groupOrder] ??= [
'object_group_id' => $array['object_group_id'], 'object_group_id' => $array['object_group_id'],
@@ -175,16 +172,28 @@ class IndexController extends Controller
'currency_symbol' => $bill['currency_symbol'], 'currency_symbol' => $bill['currency_symbol'],
'currency_decimal_places' => $bill['currency_decimal_places'], 'currency_decimal_places' => $bill['currency_decimal_places'],
'avg' => '0', 'avg' => '0',
'total_left_to_pay' => '0',
'period' => $range, 'period' => $range,
'per_period' => '0', 'per_period' => '0',
]; ];
// only fill in avg when bill is active. // only fill in avg when bill is active.
if (null !== $bill['next_expected_match']) { if (null !== $bill['next_expected_match']) {
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2'); $avg = bcdiv(bcadd((string)$bill['amount_min'], (string)$bill['amount_max']), '2');
$avg = bcmul($avg, (string) count($bill['pay_dates'])); $avg = bcmul($avg, (string)count($bill['pay_dates']));
$sums[$groupOrder][$currencyId]['avg'] = bcadd($sums[$groupOrder][$currencyId]['avg'], $avg); $sums[$groupOrder][$currencyId]['avg'] = bcadd($sums[$groupOrder][$currencyId]['avg'], $avg);
} }
// only fill in total_left_to_pay when bill is not yet paid.
if (count($bill['paid_dates']) < count($bill['pay_dates'])) {
$count = count($bill['pay_dates']) - count($bill['paid_dates']);
if ($count > 0) {
$avg = bcdiv(bcadd((string)$bill['amount_min'], (string)$bill['amount_max']), '2');
$avg = bcmul($avg, (string)$count);
$sums[$groupOrder][$currencyId]['total_left_to_pay'] = bcadd($sums[$groupOrder][$currencyId]['total_left_to_pay'], $avg);
}
}
// fill in per period regardless: // fill in per period regardless:
$sums[$groupOrder][$currencyId]['per_period'] = bcadd($sums[$groupOrder][$currencyId]['per_period'], $this->amountPerPeriod($bill, $range)); $sums[$groupOrder][$currencyId]['per_period'] = bcadd($sums[$groupOrder][$currencyId]['per_period'], $this->amountPerPeriod($bill, $range));
} }
@@ -195,7 +204,7 @@ class IndexController extends Controller
private function amountPerPeriod(array $bill, string $range): string private function amountPerPeriod(array $bill, string $range): string
{ {
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2'); $avg = bcdiv(bcadd((string)$bill['amount_min'], (string)$bill['amount_max']), '2');
app('log')->debug(sprintf('Amount per period for bill #%d "%s"', $bill['id'], $bill['name'])); app('log')->debug(sprintf('Amount per period for bill #%d "%s"', $bill['id'], $bill['name']));
app('log')->debug(sprintf('Average is %s', $avg)); app('log')->debug(sprintf('Average is %s', $avg));
@@ -208,8 +217,8 @@ class IndexController extends Controller
'weekly' => '52.17', 'weekly' => '52.17',
'daily' => '365.24', 'daily' => '365.24',
]; ];
$yearAmount = bcmul($avg, bcdiv($multiplies[$bill['repeat_freq']], (string) ($bill['skip'] + 1))); $yearAmount = bcmul($avg, bcdiv($multiplies[$bill['repeat_freq']], (string)($bill['skip'] + 1)));
app('log')->debug(sprintf('Amount per year is %s (%s * %s / %s)', $yearAmount, $avg, $multiplies[$bill['repeat_freq']], (string) ($bill['skip'] + 1))); app('log')->debug(sprintf('Amount per year is %s (%s * %s / %s)', $yearAmount, $avg, $multiplies[$bill['repeat_freq']], (string)($bill['skip'] + 1)));
// per period: // per period:
$division = [ $division = [
@@ -260,8 +269,8 @@ class IndexController extends Controller
'period' => $entry['period'], 'period' => $entry['period'],
'per_period' => '0', 'per_period' => '0',
]; ];
$totals[$currencyId]['avg'] = bcadd($totals[$currencyId]['avg'], (string) $entry['avg']); $totals[$currencyId]['avg'] = bcadd($totals[$currencyId]['avg'], (string)$entry['avg']);
$totals[$currencyId]['per_period'] = bcadd($totals[$currencyId]['per_period'], (string) $entry['per_period']); $totals[$currencyId]['per_period'] = bcadd($totals[$currencyId]['per_period'], (string)$entry['per_period']);
} }
} }
@@ -273,8 +282,8 @@ class IndexController extends Controller
*/ */
public function setOrder(Request $request, Bill $bill): JsonResponse public function setOrder(Request $request, Bill $bill): JsonResponse
{ {
$objectGroupTitle = (string) $request->get('objectGroupTitle'); $objectGroupTitle = (string)$request->get('objectGroupTitle');
$newOrder = (int) $request->get('order'); $newOrder = (int)$request->get('order');
$this->repository->setOrder($bill, $newOrder); $this->repository->setOrder($bill, $newOrder);
if ('' !== $objectGroupTitle) { if ('' !== $objectGroupTitle) {
$this->repository->setObjectGroup($bill, $objectGroupTitle); $this->repository->setObjectGroup($bill, $objectGroupTitle);

View File

@@ -149,10 +149,10 @@ class ShowController extends Controller
$admin = auth()->user(); $admin = auth()->user();
$enrichment = new SubscriptionEnrichment(); $enrichment = new SubscriptionEnrichment();
$enrichment->setUser($admin); $enrichment->setUser($admin);
$enrichment->setConvertToPrimary($this->convertToPrimary);
$enrichment->setPrimaryCurrency($this->primaryCurrency);
$enrichment->setStart($start); $enrichment->setStart($start);
$enrichment->setEnd($end); $enrichment->setEnd($end);
/** @var Bill $bill */
$bill = $enrichment->enrichSingle($bill); $bill = $enrichment->enrichSingle($bill);
/** @var BillTransformer $transformer */ /** @var BillTransformer $transformer */

View File

@@ -95,6 +95,7 @@ class EditController extends Controller
$preFilled = [ $preFilled = [
'active' => $hasOldInput ? (bool) $request->old('active') : $budget->active, 'active' => $hasOldInput ? (bool) $request->old('active') : $budget->active,
'auto_budget_currency_id' => $hasOldInput ? (int) $request->old('auto_budget_currency_id') : $this->primaryCurrency->id, 'auto_budget_currency_id' => $hasOldInput ? (int) $request->old('auto_budget_currency_id') : $this->primaryCurrency->id,
'notes' => $this->repository->getNoteText($budget),
]; ];
if ($autoBudget instanceof AutoBudget) { if ($autoBudget instanceof AutoBudget) {
$amount = $hasOldInput ? $request->old('auto_budget_amount') : $autoBudget->amount; $amount = $hasOldInput ? $request->old('auto_budget_amount') : $autoBudget->amount;

View File

@@ -136,7 +136,7 @@ class IndexController extends Controller
// get all inactive budgets, and simply list them: // get all inactive budgets, and simply list them:
$inactive = $this->repository->getInactiveBudgets(); $inactive = $this->repository->getInactiveBudgets();
$defaultCurrency = $this->primaryCurrency; $primaryCurrency = $this->primaryCurrency;
return view( return view(
'budgets.index', 'budgets.index',
@@ -149,7 +149,7 @@ class IndexController extends Controller
'budgets', 'budgets',
'currencies', 'currencies',
'periodTitle', 'periodTitle',
'defaultCurrency', 'primaryCurrency',
'activeDaysPassed', 'activeDaysPassed',
'activeDaysLeft', 'activeDaysLeft',
'inactive', 'inactive',
@@ -194,7 +194,7 @@ class IndexController extends Controller
return $availableBudgets; return $availableBudgets;
} }
private function getAllBudgets(Carbon $start, Carbon $end, Collection $currencies, TransactionCurrency $defaultCurrency): array private function getAllBudgets(Carbon $start, Carbon $end, Collection $currencies, TransactionCurrency $primaryCurrency): array
{ {
// get all budgets, and paginate them into $budgets. // get all budgets, and paginate them into $budgets.
$collection = $this->repository->getActiveBudgets(); $collection = $this->repository->getActiveBudgets();
@@ -216,7 +216,7 @@ class IndexController extends Controller
/** @var BudgetLimit $limit */ /** @var BudgetLimit $limit */
foreach ($budgetLimits as $limit) { foreach ($budgetLimits as $limit) {
Log::debug(sprintf('Working on budget limit #%d', $limit->id)); Log::debug(sprintf('Working on budget limit #%d', $limit->id));
$currency = $limit->transactionCurrency ?? $defaultCurrency; $currency = $limit->transactionCurrency ?? $primaryCurrency;
$amount = app('steam')->bcround($limit->amount, $currency->decimal_places); $amount = app('steam')->bcround($limit->amount, $currency->decimal_places);
$array['budgeted'][] = [ $array['budgeted'][] = [
'id' => $limit->id, 'id' => $limit->id,

View File

@@ -35,6 +35,7 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\CacheProperties; use FireflyIII\Support\CacheProperties;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Controllers\AugumentData; use FireflyIII\Support\Http\Controllers\AugumentData;
use FireflyIII\Support\Http\Controllers\ChartGeneration; use FireflyIII\Support\Http\Controllers\ChartGeneration;
@@ -78,6 +79,7 @@ class AccountController extends Controller
/** /**
* Shows the balances for all the user's expense accounts (on the front page). * Shows the balances for all the user's expense accounts (on the front page).
* 2025-08-06 validated for multi (primary) currency
* *
* This chart is (multi) currency aware. * This chart is (multi) currency aware.
*/ */
@@ -112,11 +114,11 @@ class AccountController extends Controller
$accountNames = $this->extractNames($accounts); $accountNames = $this->extractNames($accounts);
// grab all balances // grab all balances
Log::debug(sprintf('expenseAccounts: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s'))); Log::debug(sprintf('expenseAccounts: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
Log::debug(sprintf('expenseAccounts: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s'))); Log::debug(sprintf('expenseAccounts: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
$startBalances = Steam::finalAccountsBalance($accounts, $start); $startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
$endBalances = Steam::finalAccountsBalance($accounts, $end); $endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
Log::debug('Done collecting balances');
// loop the accounts, then check for balance and currency info. // loop the accounts, then check for balance and currency info.
foreach ($accounts as $account) { foreach ($accounts as $account) {
// Log::debug(sprintf('[a] Now in account #%d ("%s")', $account->id, $account->name)); // Log::debug(sprintf('[a] Now in account #%d ("%s")', $account->id, $account->name));
@@ -157,7 +159,7 @@ class AccountController extends Controller
$tempData[] = [ $tempData[] = [
'name' => $accountNames[$account->id], 'name' => $accountNames[$account->id],
'difference' => $diff, 'difference' => $diff,
'diff_float' => (float) $diff, // intentional float 'diff_float' => (float)$diff, // intentional float
'currency_id' => $currencies[$searchCode]->id, 'currency_id' => $currencies[$searchCode]->id,
]; ];
} }
@@ -182,7 +184,7 @@ class AccountController extends Controller
foreach ($currencies as $currencyId => $currency) { foreach ($currencies as $currencyId => $currency) {
$dataSet $dataSet
= [ = [
'label' => (string) trans('firefly.spent'), 'label' => (string)trans('firefly.spent'),
'type' => 'bar', 'type' => 'bar',
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
'currency_code' => $currency->code, 'currency_code' => $currency->code,
@@ -195,7 +197,7 @@ class AccountController extends Controller
foreach ($tempData as $entry) { foreach ($tempData as $entry) {
$currencyId = $entry['currency_id']; $currencyId = $entry['currency_id'];
$name = $entry['name']; $name = $entry['name'];
$chartData[$currencyId]['entries'][$name] = (float) $entry['difference']; $chartData[$currencyId]['entries'][$name] = (float)$entry['difference'];
} }
$data = $this->generator->multiSet($chartData); $data = $this->generator->multiSet($chartData);
@@ -223,6 +225,7 @@ class AccountController extends Controller
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($account->id); $cache->addProperty($account->id);
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($this->convertToPrimary);
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty('chart.account.expense-budget'); $cache->addProperty('chart.account.expense-budget');
if ($cache->has()) { if ($cache->has()) {
@@ -231,7 +234,10 @@ class AccountController extends Controller
/** @var GroupCollectorInterface $collector */ /** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->withBudgetInformation()->setTypes([TransactionTypeEnum::WITHDRAWAL->value]); $collector->setAccounts(new Collection([$account]))
->setRange($start, $end)
->withBudgetInformation()->setTypes([TransactionTypeEnum::WITHDRAWAL->value])
;
$journals = $collector->getExtractedJournals(); $journals = $collector->getExtractedJournals();
$chartData = []; $chartData = [];
$result = []; $result = [];
@@ -239,19 +245,37 @@ class AccountController extends Controller
/** @var array $journal */ /** @var array $journal */
foreach ($journals as $journal) { foreach ($journals as $journal) {
$budgetId = (int) $journal['budget_id']; $budgetId = (int)$journal['budget_id'];
$key = sprintf('%d-%d', $budgetId, $journal['currency_id']); $key = sprintf('%d-%d', $budgetId, $journal['currency_id']);
$budgetIds[] = $budgetId; $budgetIds[] = $budgetId;
// currency info:
$currencyId = (int)$journal['currency_id'];
$currencyName = $journal['currency_name'];
$currencySymbol = $journal['currency_symbol'];
$currencyCode = $journal['currency_code'];
$currencyDecimalPlaces = $journal['currency_decimal_places'];
$field = 'amount';
if ($this->convertToPrimary && $this->primaryCurrency->id !== $currencyId) {
$field = 'pc_amount';
$currencyName = $this->primaryCurrency->name;
$currencySymbol = $this->primaryCurrency->symbol;
$currencyCode = $this->primaryCurrency->code;
$currencyDecimalPlaces = $this->primaryCurrency->decimal_places;
}
if (!array_key_exists($key, $result)) { if (!array_key_exists($key, $result)) {
$result[$key] = [ $result[$key] = [
'total' => '0', 'total' => '0',
'budget_id' => $budgetId, 'budget_id' => $budgetId,
'currency_name' => $journal['currency_name'], 'currency_name' => $currencyName,
'currency_symbol' => $journal['currency_symbol'], 'currency_symbol' => $currencySymbol,
'currency_code' => $journal['currency_code'], 'currency_code' => $currencyCode,
'currency_decimal_places' => $currencyDecimalPlaces,
]; ];
} }
$result[$key]['total'] = bcadd((string) $journal['amount'], $result[$key]['total']); $result[$key]['total'] = bcadd((string)$journal[$field], $result[$key]['total']);
} }
$names = $this->getBudgetNames($budgetIds); $names = $this->getBudgetNames($budgetIds);
@@ -259,7 +283,7 @@ class AccountController extends Controller
foreach ($result as $row) { foreach ($result as $row) {
$budgetId = $row['budget_id']; $budgetId = $row['budget_id'];
$name = $names[$budgetId]; $name = $names[$budgetId];
$label = (string) trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]); $label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]);
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']]; $chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']];
} }
@@ -289,6 +313,7 @@ class AccountController extends Controller
$cache->addProperty($account->id); $cache->addProperty($account->id);
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty($this->convertToPrimary);
$cache->addProperty('chart.account.expense-category'); $cache->addProperty('chart.account.expense-category');
if ($cache->has()) { if ($cache->has()) {
return response()->json($cache->get()); return response()->json($cache->get());
@@ -305,22 +330,39 @@ class AccountController extends Controller
foreach ($journals as $journal) { foreach ($journals as $journal) {
$key = sprintf('%d-%d', $journal['category_id'], $journal['currency_id']); $key = sprintf('%d-%d', $journal['category_id'], $journal['currency_id']);
if (!array_key_exists($key, $result)) { if (!array_key_exists($key, $result)) {
// currency info:
$currencyId = (int)$journal['currency_id'];
$currencyName = $journal['currency_name'];
$currencySymbol = $journal['currency_symbol'];
$currencyCode = $journal['currency_code'];
$currencyDecimalPlaces = $journal['currency_decimal_places'];
$field = 'amount';
if ($this->convertToPrimary && $this->primaryCurrency->id !== $currencyId) {
$field = 'pc_amount';
$currencyName = $this->primaryCurrency->name;
$currencySymbol = $this->primaryCurrency->symbol;
$currencyCode = $this->primaryCurrency->code;
$currencyDecimalPlaces = $this->primaryCurrency->decimal_places;
}
$result[$key] = [ $result[$key] = [
'total' => '0', 'total' => '0',
'category_id' => (int) $journal['category_id'], 'category_id' => (int)$journal['category_id'],
'currency_name' => $journal['currency_name'], 'currency_name' => $currencyName,
'currency_symbol' => $journal['currency_symbol'], 'currency_code' => $currencyCode,
'currency_code' => $journal['currency_code'], 'currency_symbol' => $currencySymbol,
'currency_decimal_places' => $currencyDecimalPlaces,
]; ];
} }
$result[$key]['total'] = bcadd((string) $journal['amount'], $result[$key]['total']); $result[$key]['total'] = bcadd((string)$journal[$field], $result[$key]['total']);
} }
$names = $this->getCategoryNames(array_keys($result)); $names = $this->getCategoryNames(array_keys($result));
foreach ($result as $row) { foreach ($result as $row) {
$categoryId = $row['category_id']; $categoryId = $row['category_id'];
$name = $names[$categoryId] ?? '(unknown)'; $name = $names[$categoryId] ?? '(unknown)';
$label = (string) trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]); $label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]);
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']]; $chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']];
} }
@@ -341,11 +383,11 @@ class AccountController extends Controller
$end = clone session('end', today(config('app.timezone'))->endOfMonth()); $end = clone session('end', today(config('app.timezone'))->endOfMonth());
$defaultSet = $repository->getAccountsByType([AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value])->pluck('id')->toArray(); $defaultSet = $repository->getAccountsByType([AccountTypeEnum::DEFAULT->value, AccountTypeEnum::ASSET->value])->pluck('id')->toArray();
// Log::debug('Default set is ', $defaultSet); // Log::debug('Default set is ', $defaultSet);
$frontpage = app('preferences')->get('frontpageAccounts', $defaultSet); $frontpage = Preferences::get('frontpageAccounts', $defaultSet);
$frontpageArray = !is_array($frontpage->data) ? [] : $frontpage->data; $frontpageArray = !is_array($frontpage->data) ? [] : $frontpage->data;
Log::debug('Frontpage preference set is ', $frontpageArray); Log::debug('Frontpage preference set is ', $frontpageArray);
if (0 === count($frontpageArray)) { if (0 === count($frontpageArray)) {
app('preferences')->set('frontpageAccounts', $defaultSet); Preferences::set('frontpageAccounts', $defaultSet);
Log::debug('frontpage set is empty!'); Log::debug('frontpage set is empty!');
} }
$accounts = $repository->getAccountsById($frontpageArray); $accounts = $repository->getAccountsById($frontpageArray);
@@ -375,6 +417,7 @@ class AccountController extends Controller
$cache = new CacheProperties(); $cache = new CacheProperties();
$cache->addProperty($account->id); $cache->addProperty($account->id);
$cache->addProperty($start); $cache->addProperty($start);
$cache->addProperty($this->convertToPrimary);
$cache->addProperty($end); $cache->addProperty($end);
$cache->addProperty('chart.account.income-category'); $cache->addProperty('chart.account.income-category');
if ($cache->has()) { if ($cache->has()) {
@@ -394,22 +437,39 @@ class AccountController extends Controller
foreach ($journals as $journal) { foreach ($journals as $journal) {
$key = sprintf('%d-%d', $journal['category_id'], $journal['currency_id']); $key = sprintf('%d-%d', $journal['category_id'], $journal['currency_id']);
if (!array_key_exists($key, $result)) { if (!array_key_exists($key, $result)) {
// currency info:
$currencyId = (int)$journal['currency_id'];
$currencyName = $journal['currency_name'];
$currencySymbol = $journal['currency_symbol'];
$currencyCode = $journal['currency_code'];
$currencyDecimalPlaces = $journal['currency_decimal_places'];
$field = 'amount';
if ($this->convertToPrimary && $this->primaryCurrency->id !== $currencyId) {
$field = 'pc_amount';
$currencyName = $this->primaryCurrency->name;
$currencySymbol = $this->primaryCurrency->symbol;
$currencyCode = $this->primaryCurrency->code;
$currencyDecimalPlaces = $this->primaryCurrency->decimal_places;
}
$result[$key] = [ $result[$key] = [
'total' => '0', 'total' => '0',
'category_id' => $journal['category_id'], 'category_id' => $journal['category_id'],
'currency_name' => $journal['currency_name'], 'currency_name' => $currencyName,
'currency_symbol' => $journal['currency_symbol'], 'currency_code' => $currencyCode,
'currency_code' => $journal['currency_code'], 'currency_symbol' => $currencySymbol,
'currency_decimal_places' => $currencyDecimalPlaces,
]; ];
} }
$result[$key]['total'] = bcadd((string) $journal['amount'], $result[$key]['total']); $result[$key]['total'] = bcadd((string)$journal[$field], $result[$key]['total']);
} }
$names = $this->getCategoryNames(array_keys($result)); $names = $this->getCategoryNames(array_keys($result));
foreach ($result as $row) { foreach ($result as $row) {
$categoryId = $row['category_id']; $categoryId = $row['category_id'];
$name = $names[$categoryId] ?? '(unknown)'; $name = $names[$categoryId] ?? '(unknown)';
$label = (string) trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]); $label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]);
$chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']]; $chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']];
} }
$data = $this->generator->multiCurrencyPieChart($chartData); $data = $this->generator->multiCurrencyPieChart($chartData);
@@ -450,7 +510,7 @@ class AccountController extends Controller
// This period depends on the size of the chart // This period depends on the size of the chart
$current = clone $start; $current = clone $start;
$current = app('navigation')->endOfX($current, $step, null); $current = app('navigation')->endOfX($current, $step, null);
$format = (string) trans('config.month_and_day_js', [], $locale); $format = (string)trans('config.month_and_day_js', [], $locale);
$accountCurrency = $this->accountRepository->getAccountCurrency($account); $accountCurrency = $this->accountRepository->getAccountCurrency($account);
$range = Steam::finalAccountBalanceInRange($account, $start, $end, $this->convertToPrimary); $range = Steam::finalAccountBalanceInRange($account, $start, $end, $this->convertToPrimary);
@@ -512,7 +572,7 @@ class AccountController extends Controller
foreach ($return as $key => $info) { foreach ($return as $key => $info) {
if ('balance' !== $key && 'pc_balance' !== $key) { if ('balance' !== $key && 'pc_balance' !== $key) {
// assume it's a currency: // assume it's a currency:
$setCurrency = $this->currencyRepository->findByCode((string) $key); $setCurrency = $this->currencyRepository->findByCode((string)$key);
$info['currency_symbol'] = $setCurrency->symbol; $info['currency_symbol'] = $setCurrency->symbol;
$info['currency_code'] = $setCurrency->code; $info['currency_code'] = $setCurrency->code;
$info['label'] = sprintf('%s (%s)', $account->name, $setCurrency->symbol); $info['label'] = sprintf('%s (%s)', $account->name, $setCurrency->symbol);
@@ -525,7 +585,7 @@ class AccountController extends Controller
if ('pc_balance' === $key) { if ('pc_balance' === $key) {
$info['currency_symbol'] = $this->primaryCurrency->symbol; $info['currency_symbol'] = $this->primaryCurrency->symbol;
$info['currency_code'] = $this->primaryCurrency->code; $info['currency_code'] = $this->primaryCurrency->code;
$info['label'] = sprintf('%s (%s) (%s)', $account->name, (string) trans('firefly.sum'), $this->primaryCurrency->symbol); $info['label'] = sprintf('%s (%s) (%s)', $account->name, (string)trans('firefly.sum'), $this->primaryCurrency->symbol);
} }
$chartData[] = $info; $chartData[] = $info;
} }
@@ -594,10 +654,10 @@ class AccountController extends Controller
$accountNames = $this->extractNames($accounts); $accountNames = $this->extractNames($accounts);
// grab all balances // grab all balances
Log::debug(sprintf('revAccounts: finalAccountsBalance("%s")', $start->format('Y-m-d H:i:s'))); Log::debug(sprintf('revAccounts: accountsBalancesOptimized("%s")', $start->format('Y-m-d H:i:s')));
Log::debug(sprintf('revAccounts: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s'))); Log::debug(sprintf('revAccounts: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
$startBalances = Steam::finalAccountsBalance($accounts, $start); $startBalances = Steam::accountsBalancesOptimized($accounts, $start, $this->primaryCurrency, $this->convertToPrimary);
$endBalances = Steam::finalAccountsBalance($accounts, $end); $endBalances = Steam::accountsBalancesOptimized($accounts, $end, $this->primaryCurrency, $this->convertToPrimary);
// loop the accounts, then check for balance and currency info. // loop the accounts, then check for balance and currency info.
@@ -640,7 +700,7 @@ class AccountController extends Controller
$tempData[] = [ $tempData[] = [
'name' => $accountNames[$account->id], 'name' => $accountNames[$account->id],
'difference' => $diff, 'difference' => $diff,
'diff_float' => (float) $diff, // intentional float 'diff_float' => (float)$diff, // intentional float
'currency_id' => $currencies[$searchCode]->id, 'currency_id' => $currencies[$searchCode]->id,
]; ];
} }
@@ -667,7 +727,7 @@ class AccountController extends Controller
foreach ($currencies as $currencyId => $currency) { foreach ($currencies as $currencyId => $currency) {
$dataSet $dataSet
= [ = [
'label' => (string) trans('firefly.earned'), 'label' => (string)trans('firefly.earned'),
'type' => 'bar', 'type' => 'bar',
'currency_symbol' => $currency->symbol, 'currency_symbol' => $currency->symbol,
'currency_code' => $currency->code, 'currency_code' => $currency->code,

View File

@@ -210,7 +210,6 @@ class CategoryReportController extends Controller
$spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection([$category])); $spent = $this->opsRepository->listExpenses($start, $end, $accounts, new Collection([$category]));
$earned = $this->opsRepository->listIncome($start, $end, $accounts, new Collection([$category])); $earned = $this->opsRepository->listIncome($start, $end, $accounts, new Collection([$category]));
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end); $format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
// loop expenses. // loop expenses.
foreach ($spent as $currency) { foreach ($spent as $currency) {
// add things to chart Data for each currency: // add things to chart Data for each currency:

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use FireflyIII\Events\RequestedSendWebhookMessages;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\Steam; use FireflyIII\Support\Facades\Steam;
@@ -33,6 +34,7 @@ use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController; use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Config; use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\View; use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
@@ -141,6 +143,14 @@ abstract class Controller extends BaseController
View::share('shownDemo', $shownDemo); View::share('shownDemo', $shownDemo);
View::share('current_route_name', $page); View::share('current_route_name', $page);
View::share('original_route_name', Route::currentRouteName()); View::share('original_route_name', Route::currentRouteName());
// lottery to send any remaining webhooks:
if (7 === random_int(1, 10)) {
// trigger event to send them:
Log::debug('send event RequestedSendWebhookMessages through lottery');
event(new RequestedSendWebhookMessages());
}
} }
View::share('darkMode', $darkMode); View::share('darkMode', $darkMode);

View File

@@ -157,6 +157,11 @@ class DebugController extends Controller
return view('debug', compact('table', 'now', 'logContent')); return view('debug', compact('table', 'now', 'logContent'));
} }
public function apiTest()
{
return view('test.api-test');
}
private function generateTable(): string private function generateTable(): string
{ {
// system information: // system information:

View File

@@ -32,8 +32,10 @@ use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups; use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment; use FireflyIII\Support\JsonApi\Enrichments\AccountEnrichment;
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
use FireflyIII\Transformers\AccountTransformer; use FireflyIII\Transformers\AccountTransformer;
use FireflyIII\Transformers\PiggyBankTransformer; use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
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;
@@ -114,6 +116,13 @@ class IndexController extends Controller
$transformer->setParameters(new ParameterBag()); $transformer->setParameters(new ParameterBag());
$piggyBanks = []; $piggyBanks = [];
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new PiggyBankEnrichment();
$enrichment->setUser($admin);
$collection = $enrichment->enrich($collection);
/** @var PiggyBank $piggy */ /** @var PiggyBank $piggy */
foreach ($collection as $piggy) { foreach ($collection as $piggy) {
$array = $transformer->transform($piggy); $array = $transformer->transform($piggy);
@@ -148,7 +157,7 @@ class IndexController extends Controller
// enrich each account. // enrich each account.
$enrichment = new AccountEnrichment(); $enrichment = new AccountEnrichment();
$enrichment->setUser(auth()->user()); $enrichment->setUser(auth()->user());
$enrichment->setPrimaryCurrency($this->primaryCurrency); $enrichment->setDate($end);
$return = []; $return = [];
/** @var PiggyBank $piggy */ /** @var PiggyBank $piggy */
@@ -170,14 +179,6 @@ class IndexController extends Controller
$return[$accountId]['target'] = '0'; $return[$accountId]['target'] = '0';
$return[$accountId]['to_save'] = '0'; $return[$accountId]['to_save'] = '0';
} }
// calculate new interesting fields:
// $return[$accountId]['left'] -= $array['current_amount'];
// $return[$accountId]['saved'] += $array['current_amount'];
// $return[$accountId]['target'] += $array['target_amount'];
// $return[$accountId]['to_save'] += ($array['target_amount'] - $array['current_amount']);
// $return['account_name'] = $account['name'];
} }
} }
@@ -193,7 +194,7 @@ class IndexController extends Controller
// loop all accounts in this piggy bank subtract the current amount from "left to save" in the $accounts array. // loop all accounts in this piggy bank subtract the current amount from "left to save" in the $accounts array.
/** @var array $piggyAccount */ /** @var array $piggyAccount */
foreach ($piggyBank['accounts'] as $piggyAccount) { foreach ($piggyBank['accounts'] as $piggyAccount) {
$accountId = $piggyAccount['id']; $accountId = $piggyAccount['account_id'];
if (array_key_exists($accountId, $accounts)) { if (array_key_exists($accountId, $accounts)) {
$accounts[$accountId]['left'] = bcsub((string) $accounts[$accountId]['left'], (string) $piggyAccount['current_amount']); $accounts[$accountId]['left'] = bcsub((string) $accounts[$accountId]['left'], (string) $piggyAccount['current_amount']);
$accounts[$accountId]['saved'] = bcadd((string) $accounts[$accountId]['saved'], (string) $piggyAccount['current_amount']); $accounts[$accountId]['saved'] = bcadd((string) $accounts[$accountId]['saved'], (string) $piggyAccount['current_amount']);

View File

@@ -29,7 +29,9 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBank;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\PiggyBankEnrichment;
use FireflyIII\Transformers\PiggyBankTransformer; use FireflyIII\Transformers\PiggyBankTransformer;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\View\View; use Illuminate\View\View;
use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\ParameterBag;
@@ -75,6 +77,13 @@ class ShowController extends Controller
$parameters = new ParameterBag(); $parameters = new ParameterBag();
$parameters->set('end', $end); $parameters->set('end', $end);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new PiggyBankEnrichment();
$enrichment->setUser($admin);
$piggyBank = $enrichment->enrichSingle($piggyBank);
/** @var PiggyBankTransformer $transformer */ /** @var PiggyBankTransformer $transformer */
$transformer = app(PiggyBankTransformer::class); $transformer = app(PiggyBankTransformer::class);
$transformer->setParameters($parameters); $transformer->setParameters($parameters);

View File

@@ -23,10 +23,11 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use FireflyIII\Support\Singleton\PreferencesSingleton;
use JsonException; use JsonException;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Enums\AccountTypeEnum; use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Events\Preferences\UserGroupChangedDefaultCurrency; use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency;
use FireflyIII\Events\Test\UserTestNotificationChannel; use FireflyIII\Events\Test\UserTestNotificationChannel;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Requests\PreferencesRequest; use FireflyIII\Http\Requests\PreferencesRequest;
@@ -44,7 +45,6 @@ use Illuminate\View\View;
use function Safe\json_decode; use function Safe\json_decode;
use function Safe\file_get_contents; use function Safe\file_get_contents;
use function Safe\strtotime;
/** /**
* Class PreferencesController. * Class PreferencesController.
@@ -270,17 +270,19 @@ class PreferencesController extends Controller
if ($convertToPrimary && !$this->convertToPrimary) { if ($convertToPrimary && !$this->convertToPrimary) {
// set to true! // set to true!
Log::debug('User sets convertToPrimary to true.'); Log::debug('User sets convertToPrimary to true.');
Preferences::set('convert_to_primary', $convertToPrimary); Preferences::set('convert_to_primary', true);
event(new UserGroupChangedDefaultCurrency(auth()->user()->userGroup)); $singleton = PreferencesSingleton::getInstance();
$singleton->resetPreferences();
event(new UserGroupChangedPrimaryCurrency(auth()->user()->userGroup));
} }
Preferences::set('convert_to_primary', $convertToPrimary); Preferences::set('convert_to_primary', $convertToPrimary);
// custom fiscal year // custom fiscal year
$customFiscalYear = 1 === (int) $request->get('customFiscalYear'); $customFiscalYear = 1 === (int) $request->get('customFiscalYear');
$string = strtotime((string) $request->get('fiscalYearStart'));
if (false !== $string) {
$fiscalYearStart = Carbon::createFromTimestamp($string)->format('m-d');
Preferences::set('customFiscalYear', $customFiscalYear); Preferences::set('customFiscalYear', $customFiscalYear);
$fiscalYearString = (string) $request->get('fiscalYearStart');
if ('' !== $fiscalYearString) {
$fiscalYearStart = Carbon::parse($fiscalYearString, config('app.timezone'))->format('m-d');
Preferences::set('fiscalYearStart', $fiscalYearStart); Preferences::set('fiscalYearStart', $fiscalYearStart);
} }

View File

@@ -84,7 +84,7 @@ class CreateController extends Controller
{ {
$budgets = app('expandedform')->makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets()); $budgets = app('expandedform')->makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets());
$bills = app('expandedform')->makeSelectListWithEmpty($this->billRepository->getActiveBills()); $bills = app('expandedform')->makeSelectListWithEmpty($this->billRepository->getActiveBills());
$defaultCurrency = $this->primaryCurrency; $primaryCurrency = $this->primaryCurrency;
$tomorrow = today(config('app.timezone')); $tomorrow = today(config('app.timezone'));
$oldRepetitionType = $request->old('repetition_type'); $oldRepetitionType = $request->old('repetition_type');
$tomorrow->addDay(); $tomorrow->addDay();
@@ -116,7 +116,7 @@ class CreateController extends Controller
return view( return view(
'recurring.create', 'recurring.create',
compact('tomorrow', 'oldRepetitionType', 'bills', 'weekendResponses', 'preFilled', 'repetitionEnds', 'defaultCurrency', 'budgets') compact('tomorrow', 'oldRepetitionType', 'bills', 'weekendResponses', 'preFilled', 'repetitionEnds', 'primaryCurrency', 'budgets')
); );
} }
@@ -129,7 +129,7 @@ class CreateController extends Controller
{ {
$budgets = app('expandedform')->makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets()); $budgets = app('expandedform')->makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets());
$bills = app('expandedform')->makeSelectListWithEmpty($this->billRepository->getActiveBills()); $bills = app('expandedform')->makeSelectListWithEmpty($this->billRepository->getActiveBills());
$defaultCurrency = $this->primaryCurrency; $primaryCurrency = $this->primaryCurrency;
$tomorrow = today(config('app.timezone')); $tomorrow = today(config('app.timezone'));
$oldRepetitionType = $request->old('repetition_type'); $oldRepetitionType = $request->old('repetition_type');
$tomorrow->addDay(); $tomorrow->addDay();
@@ -210,7 +210,7 @@ class CreateController extends Controller
return view( return view(
'recurring.create', 'recurring.create',
compact('tomorrow', 'oldRepetitionType', 'bills', 'weekendResponses', 'preFilled', 'repetitionEnds', 'defaultCurrency', 'budgets') compact('tomorrow', 'oldRepetitionType', 'bills', 'weekendResponses', 'preFilled', 'repetitionEnds', 'primaryCurrency', 'budgets')
); );
} }

View File

@@ -34,7 +34,10 @@ use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Support\Facades\ExpandedForm;
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
use FireflyIII\Transformers\RecurrenceTransformer; use FireflyIII\Transformers\RecurrenceTransformer;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
@@ -92,13 +95,20 @@ class EditController extends Controller
throw new FireflyException('This recurring transaction has no meta-data. You will have to delete it and recreate it. Sorry!'); throw new FireflyException('This recurring transaction has no meta-data. You will have to delete it and recreate it. Sorry!');
} }
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new RecurringEnrichment();
$enrichment->setUser($admin);
$recurrence = $enrichment->enrichSingle($recurrence);
/** @var RecurrenceTransformer $transformer */ /** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class); $transformer = app(RecurrenceTransformer::class);
$transformer->setParameters(new ParameterBag()); $transformer->setParameters(new ParameterBag());
$array = $transformer->transform($recurrence); $array = $transformer->transform($recurrence);
$budgets = app('expandedform')->makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets()); $budgets = ExpandedForm::makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets());
$bills = app('expandedform')->makeSelectListWithEmpty($this->billRepository->getActiveBills()); $bills = ExpandedForm::makeSelectListWithEmpty($this->billRepository->getActiveBills());
/** @var RecurrenceRepetition $repetition */ /** @var RecurrenceRepetition $repetition */
$repetition = $recurrence->recurrenceRepetitions()->first(); $repetition = $recurrence->recurrenceRepetitions()->first();

View File

@@ -29,7 +29,9 @@ use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Recurrence; use FireflyIII\Models\Recurrence;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Support\Http\Controllers\GetConfigurationData; use FireflyIII\Support\Http\Controllers\GetConfigurationData;
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
use FireflyIII\Transformers\RecurrenceTransformer; use FireflyIII\Transformers\RecurrenceTransformer;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Pagination\LengthAwarePaginator;
@@ -85,6 +87,13 @@ class IndexController extends Controller
$total = $collection->count(); $total = $collection->count();
$recurrences = $collection->slice(($page - 1) * $pageSize, $pageSize); $recurrences = $collection->slice(($page - 1) * $pageSize, $pageSize);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new RecurringEnrichment();
$enrichment->setUser($admin);
$recurrences = $enrichment->enrich($recurrences);
/** @var RecurrenceTransformer $transformer */ /** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class); $transformer = app(RecurrenceTransformer::class);
$transformer->setParameters(new ParameterBag()); $transformer->setParameters(new ParameterBag());

View File

@@ -32,8 +32,10 @@ use FireflyIII\Models\Recurrence;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Support\Http\Controllers\GetConfigurationData; use FireflyIII\Support\Http\Controllers\GetConfigurationData;
use FireflyIII\Support\JsonApi\Enrichments\RecurringEnrichment;
use FireflyIII\Transformers\AttachmentTransformer; use FireflyIII\Transformers\AttachmentTransformer;
use FireflyIII\Transformers\RecurrenceTransformer; use FireflyIII\Transformers\RecurrenceTransformer;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\View\View; use Illuminate\View\View;
use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\ParameterBag;
@@ -80,6 +82,13 @@ class ShowController extends Controller
{ {
$repos = app(AttachmentRepositoryInterface::class); $repos = app(AttachmentRepositoryInterface::class);
// enrich
/** @var User $admin */
$admin = auth()->user();
$enrichment = new RecurringEnrichment();
$enrichment->setUser($admin);
$recurrence = $enrichment->enrichSingle($recurrence);
/** @var RecurrenceTransformer $transformer */ /** @var RecurrenceTransformer $transformer */
$transformer = app(RecurrenceTransformer::class); $transformer = app(RecurrenceTransformer::class);
$transformer->setParameters(new ParameterBag()); $transformer->setParameters(new ParameterBag());

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Report; namespace FireflyIII\Http\Controllers\Report;
use FireflyIII\Support\Facades\Navigation;
use Throwable; use Throwable;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
@@ -290,11 +291,12 @@ class BudgetController extends Controller
$cache->addProperty('budget-period-report'); $cache->addProperty('budget-period-report');
$cache->addProperty($accounts->pluck('id')->toArray()); $cache->addProperty($accounts->pluck('id')->toArray());
if ($cache->has()) { if ($cache->has()) {
return $cache->get(); // return $cache->get();
} }
$periods = app('navigation')->listOfPeriods($start, $end); $periods = Navigation::listOfPeriods($start, $end);
$keyFormat = app('navigation')->preferredCarbonFormat($start, $end); $keyFormat = Navigation::preferredCarbonFormat($start, $end);
// list expenses for budgets in account(s) // list expenses for budgets in account(s)
$expenses = $this->opsRepository->listExpenses($start, $end, $accounts); $expenses = $this->opsRepository->listExpenses($start, $end, $accounts);
@@ -303,6 +305,17 @@ class BudgetController extends Controller
foreach ($currency['budgets'] as $budget) { foreach ($currency['budgets'] as $budget) {
$count = 0; $count = 0;
foreach ($budget['transaction_journals'] as $journal) { foreach ($budget['transaction_journals'] as $journal) {
// #10678
// skip transactions between two asset / liability accounts.
if (
in_array($journal['source_account_type'], config('firefly.valid_currency_account_types'), true)
&& in_array($journal['destination_account_type'], config('firefly.valid_currency_account_types'), true)
) {
continue;
}
++$count; ++$count;
$key = sprintf('%d-%d', $budget['id'], $currency['currency_id']); $key = sprintf('%d-%d', $budget['id'], $currency['currency_id']);
$dateKey = $journal['date']->format($keyFormat); $dateKey = $journal['date']->format($keyFormat);

View File

@@ -188,16 +188,7 @@ class ReportController extends Controller
$start->endOfDay(); // end of day so the final balance is at the end of that day. $start->endOfDay(); // end of day so the final balance is at the end of that day.
$end->endOfDay(); $end->endOfDay();
app('view')->share( app('view')->share('subTitle', trans('firefly.report_default', ['start' => $start->isoFormat($this->monthAndDayFormat), 'end' => $end->isoFormat($this->monthAndDayFormat)]));
'subTitle',
trans(
'firefly.report_default',
[
'start' => $start->isoFormat($this->monthAndDayFormat),
'end' => $end->isoFormat($this->monthAndDayFormat),
]
)
);
$generator = ReportGeneratorFactory::reportGenerator('Standard', $start, $end); $generator = ReportGeneratorFactory::reportGenerator('Standard', $start, $end);
$generator->setAccounts($accounts); $generator->setAccounts($accounts);
@@ -222,16 +213,7 @@ class ReportController extends Controller
$start->endOfDay(); // end of day so the final balance is at the end of that day. $start->endOfDay(); // end of day so the final balance is at the end of that day.
$end->endOfDay(); $end->endOfDay();
app('view')->share( app('view')->share('subTitle', trans('firefly.report_double', ['start' => $start->isoFormat($this->monthAndDayFormat), 'end' => $end->isoFormat($this->monthAndDayFormat)]));
'subTitle',
trans(
'firefly.report_double',
[
'start' => $start->isoFormat($this->monthAndDayFormat),
'end' => $end->isoFormat($this->monthAndDayFormat),
]
)
);
$generator = ReportGeneratorFactory::reportGenerator('Account', $start, $end); $generator = ReportGeneratorFactory::reportGenerator('Account', $start, $end);
$generator->setAccounts($accounts); $generator->setAccounts($accounts);

View File

@@ -270,6 +270,7 @@ class CreateController extends Controller
$data = $request->getRuleData(); $data = $request->getRuleData();
$rule = $this->ruleRepos->store($data); $rule = $this->ruleRepos->store($data);
session()->flash('success_url', route('rules.select-transactions', [$rule->id]));
session()->flash('success', (string) trans('firefly.stored_new_rule', ['title' => $rule->title])); session()->flash('success', (string) trans('firefly.stored_new_rule', ['title' => $rule->title]));
app('preferences')->mark(); app('preferences')->mark();

View File

@@ -252,6 +252,7 @@ class TagController extends Controller
$collector->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withAccountInformation() $collector->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withAccountInformation()
->setTag($tag)->withBudgetInformation()->withCategoryInformation() ->setTag($tag)->withBudgetInformation()->withCategoryInformation()
->withAttachmentInformation()
; ;
$groups = $collector->getPaginatedGroups(); $groups = $collector->getPaginatedGroups();
$groups->setPath($path); $groups->setPath($path);
@@ -283,6 +284,7 @@ class TagController extends Controller
$collector = app(GroupCollectorInterface::class); $collector = app(GroupCollectorInterface::class);
$collector->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withAccountInformation() $collector->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withAccountInformation()
->setTag($tag)->withBudgetInformation()->withCategoryInformation() ->setTag($tag)->withBudgetInformation()->withCategoryInformation()
->withAttachmentInformation()
; ;
$groups = $collector->getPaginatedGroups(); $groups = $collector->getPaginatedGroups();
$groups->setPath($path); $groups->setPath($path);

View File

@@ -117,7 +117,7 @@ class CreateController extends Controller
$optionalFields = app('preferences')->get('transaction_journal_optional_fields', [])->data; $optionalFields = app('preferences')->get('transaction_journal_optional_fields', [])->data;
$allowedOpposingTypes = config('firefly.allowed_opposing_types'); $allowedOpposingTypes = config('firefly.allowed_opposing_types');
$accountToTypes = config('firefly.account_to_transaction'); $accountToTypes = config('firefly.account_to_transaction');
$defaultCurrency = $this->primaryCurrency; $primaryCurrency = $this->primaryCurrency;
$previousUrl = $this->rememberPreviousUrl('transactions.create.url'); $previousUrl = $this->rememberPreviousUrl('transactions.create.url');
$parts = parse_url((string) $previousUrl); $parts = parse_url((string) $previousUrl);
$search = sprintf('?%s', $parts['query'] ?? ''); $search = sprintf('?%s', $parts['query'] ?? '');
@@ -156,7 +156,7 @@ class CreateController extends Controller
'objectType', 'objectType',
'optionalDateFields', 'optionalDateFields',
'subTitle', 'subTitle',
'defaultCurrency', 'primaryCurrency',
'previousUrl', 'previousUrl',
'optionalFields', 'optionalFields',
'preFilled', 'preFilled',

View File

@@ -84,7 +84,7 @@ class EditController extends Controller
$title = $transactionGroup->transactionJournals()->count() > 1 ? $transactionGroup->title : $transactionGroup->transactionJournals()->first()->description; $title = $transactionGroup->transactionJournals()->count() > 1 ? $transactionGroup->title : $transactionGroup->transactionJournals()->first()->description;
$subTitle = (string) trans('firefly.edit_transaction_title', ['description' => $title]); $subTitle = (string) trans('firefly.edit_transaction_title', ['description' => $title]);
$subTitleIcon = 'fa-plus'; $subTitleIcon = 'fa-plus';
$defaultCurrency = $this->primaryCurrency; $primaryCurrency = $this->primaryCurrency;
$cash = $repository->getCashAccount(); $cash = $repository->getCashAccount();
$previousUrl = $this->rememberPreviousUrl('transactions.edit.url'); $previousUrl = $this->rememberPreviousUrl('transactions.edit.url');
$parts = parse_url((string) $previousUrl); $parts = parse_url((string) $previousUrl);
@@ -130,7 +130,7 @@ class EditController extends Controller
'transactionGroup', 'transactionGroup',
'allowedOpposingTypes', 'allowedOpposingTypes',
'accountToTypes', 'accountToTypes',
'defaultCurrency', 'primaryCurrency',
'previousUrl' 'previousUrl'
) )
); );

View File

@@ -25,16 +25,20 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Transaction; namespace FireflyIII\Http\Controllers\Transaction;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\AuditLogEntry\ALERepositoryInterface; use FireflyIII\Repositories\AuditLogEntry\ALERepositoryInterface;
use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface;
use FireflyIII\Support\JsonApi\Enrichments\TransactionGroupEnrichment;
use FireflyIII\Transformers\TransactionGroupTransformer; use FireflyIII\Transformers\TransactionGroupTransformer;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\Factory;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\View\View; use Illuminate\View\View;
use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\ParameterBag;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/** /**
* Class ShowController * Class ShowController
@@ -57,7 +61,7 @@ class ShowController extends Controller
$this->repository = app(TransactionGroupRepositoryInterface::class); $this->repository = app(TransactionGroupRepositoryInterface::class);
$this->aleRepository = app(ALERepositoryInterface::class); $this->aleRepository = app(ALERepositoryInterface::class);
app('view')->share('title', (string) trans('firefly.transactions')); app('view')->share('title', (string)trans('firefly.transactions'));
app('view')->share('mainTitleIcon', 'fa-exchange'); app('view')->share('mainTitleIcon', 'fa-exchange');
return $next($request); return $next($request);
@@ -80,38 +84,62 @@ class ShowController extends Controller
*/ */
public function show(TransactionGroup $transactionGroup) public function show(TransactionGroup $transactionGroup)
{ {
/** @var User $admin */
$admin = auth()->user();
// use new group collector:
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($admin)->setTransactionGroup($transactionGroup)->withAPIInformation();
$selectedGroup = $collector->getGroups()->first();
if (null === $selectedGroup) {
throw new NotFoundHttpException();
}
// enrich
$enrichment = new TransactionGroupEnrichment();
$enrichment->setUser($admin);
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
/** @var null|TransactionJournal $first */ /** @var null|TransactionJournal $first */
$first = $transactionGroup->transactionJournals()->first(['transaction_journals.*']); $first = $transactionGroup->transactionJournals()->first(['transaction_journals.*']);
$splits = $transactionGroup->transactionJournals()->count(); $splits = $transactionGroup->transactionJournals()->count();
$splits = count($selectedGroup['transactions']);
$keys = array_keys($selectedGroup['transactions']);
$first = $selectedGroup['transactions'][array_shift($keys)];
unset($keys);
if (null === $first) { if (null === $first) {
throw new FireflyException('This transaction is broken :(.'); throw new FireflyException('This transaction is broken :(.');
} }
$type = (string)trans(sprintf('firefly.%s', $first['transaction_type_type']));
$type = (string) trans(sprintf('firefly.%s', $first->transactionType->type)); $title = 1 === $splits ? $first['description'] : $selectedGroup['title'];
$title = 1 === $splits ? $first->description : $transactionGroup->title;
$subTitle = sprintf('%s: "%s"', $type, $title); $subTitle = sprintf('%s: "%s"', $type, $title);
// enrich
$enrichment = new TransactionGroupEnrichment();
$enrichment->setUser($admin);
$selectedGroup = $enrichment->enrichSingle($selectedGroup);
/** @var TransactionGroupTransformer $transformer */ /** @var TransactionGroupTransformer $transformer */
$transformer = app(TransactionGroupTransformer::class); $transformer = app(TransactionGroupTransformer::class);
$transformer->setParameters(new ParameterBag()); $transformer->setParameters(new ParameterBag());
$groupArray = $transformer->transformObject($transactionGroup); $groupArray = $transformer->transformObject($transactionGroup);
// do some calculations: // do some calculations:
$amounts = $this->getAmounts($groupArray); $amounts = $this->getAmounts($selectedGroup);
$accounts = $this->getAccounts($groupArray); $accounts = $this->getAccounts($selectedGroup);
foreach (array_keys($groupArray['transactions']) as $index) { foreach (array_keys($selectedGroup['transactions']) as $index) {
$groupArray['transactions'][$index]['tags'] = $this->repository->getTagObjects( $selectedGroup['transactions'][$index]['tags'] = $this->repository->getTagObjects((int)$selectedGroup['transactions'][$index]['transaction_journal_id']);
(int) $groupArray['transactions'][$index]['transaction_journal_id']
);
} }
// get audit log entries: // get audit log entries:
$groupLogEntries = $this->aleRepository->getForObject($transactionGroup); $groupLogEntries = $this->aleRepository->getForObject($transactionGroup);
$logEntries = []; $logEntries = [];
foreach ($transactionGroup->transactionJournals as $journal) { foreach ($selectedGroup['transactions'] as $journal) {
$logEntries[$journal->id] = $this->aleRepository->getForObject($journal); $logEntries[$journal['transaction_journal_id']] = $this->aleRepository->getForId(TransactionJournal::class, $journal['transaction_journal_id']);
} }
$events = $this->repository->getPiggyEvents($transactionGroup); $events = $this->repository->getPiggyEvents($transactionGroup);
@@ -129,6 +157,7 @@ class ShowController extends Controller
'groupLogEntries', 'groupLogEntries',
'subTitle', 'subTitle',
'splits', 'splits',
'selectedGroup',
'groupArray', 'groupArray',
'events', 'events',
'attachments', 'attachments',
@@ -142,34 +171,38 @@ class ShowController extends Controller
{ {
$amounts = []; $amounts = [];
foreach ($group['transactions'] as $transaction) { foreach ($group['transactions'] as $transaction) {
// add normal amount:
$symbol = $transaction['currency_symbol']; $symbol = $transaction['currency_symbol'];
if (!array_key_exists($symbol, $amounts)) { $amounts[$symbol] ??= [
$amounts[$symbol] = [
'amount' => '0', 'amount' => '0',
'symbol' => $symbol, 'symbol' => $symbol,
'decimal_places' => $transaction['currency_decimal_places'], 'decimal_places' => $transaction['currency_decimal_places'],
]; ];
} $amounts[$symbol]['amount'] = bcadd($amounts[$symbol]['amount'], (string)$transaction['amount']);
$amounts[$symbol]['amount'] = bcadd($amounts[$symbol]['amount'], (string) $transaction['amount']);
if (null !== $transaction['foreign_amount'] && '' !== $transaction['foreign_amount'] // add foreign amount:
&& 0 !== bccomp( if (null !== $transaction['foreign_amount'] && '' !== $transaction['foreign_amount'] && 0 !== bccomp('0', (string)$transaction['foreign_amount'])) {
'0',
(string) $transaction['foreign_amount']
)) {
// same for foreign currency: // same for foreign currency:
$foreignSymbol = $transaction['foreign_currency_symbol']; $foreignSymbol = $transaction['foreign_currency_symbol'];
if (!array_key_exists($foreignSymbol, $amounts)) { $amounts[$foreignSymbol] ??= [
$amounts[$foreignSymbol] = [
'amount' => '0', 'amount' => '0',
'symbol' => $foreignSymbol, 'symbol' => $foreignSymbol,
'decimal_places' => $transaction['foreign_currency_decimal_places'], 'decimal_places' => $transaction['foreign_currency_decimal_places'],
]; ];
$amounts[$foreignSymbol]['amount'] = bcadd($amounts[$foreignSymbol]['amount'], (string)$transaction['foreign_amount']);
} }
$amounts[$foreignSymbol]['amount'] = bcadd( // add primary currency amount
$amounts[$foreignSymbol]['amount'], if (null !== $transaction['pc_amount'] && $transaction['currency_id'] !== $this->primaryCurrency->id) {
(string) $transaction['foreign_amount'] // same for foreign currency:
); $primarySymbol = $this->primaryCurrency->symbol;
$amounts[$primarySymbol] ??= [
'amount' => '0',
'symbol' => $this->primaryCurrency->symbol,
'decimal_places' => $this->primaryCurrency->decimal_places,
];
$amounts[$primarySymbol]['amount'] = bcadd($amounts[$primarySymbol]['amount'], (string)$transaction['pc_amount']);
} }
} }
return $amounts; return $amounts;
@@ -184,16 +217,16 @@ class ShowController extends Controller
foreach ($group['transactions'] as $transaction) { foreach ($group['transactions'] as $transaction) {
$accounts['source'][] = [ $accounts['source'][] = [
'type' => $transaction['source_type'], 'type' => $transaction['source_account_type'],
'id' => $transaction['source_id'], 'id' => $transaction['source_account_id'],
'name' => $transaction['source_name'], 'name' => $transaction['source_account_name'],
'iban' => $transaction['source_iban'], 'iban' => $transaction['source_account_iban'],
]; ];
$accounts['destination'][] = [ $accounts['destination'][] = [
'type' => $transaction['destination_type'], 'type' => $transaction['destination_account_type'],
'id' => $transaction['destination_id'], 'id' => $transaction['destination_account_id'],
'name' => $transaction['destination_name'], 'name' => $transaction['destination_account_name'],
'iban' => $transaction['destination_iban'], 'iban' => $transaction['destination_account_iban'],
]; ];
} }

View File

@@ -120,7 +120,7 @@ class Range
// save some formats: // save some formats:
$monthAndDayFormat = (string) trans('config.month_and_day_js', [], $locale); $monthAndDayFormat = (string) trans('config.month_and_day_js', [], $locale);
$dateTimeFormat = (string) trans('config.date_time_js', [], $locale); $dateTimeFormat = (string) trans('config.date_time_js', [], $locale);
$defaultCurrency = Amount::getPrimaryCurrency(); $primaryCurrency = Amount::getPrimaryCurrency();
// also format for moment JS: // also format for moment JS:
$madMomentJS = (string) trans('config.month_and_day_moment_js', [], $locale); $madMomentJS = (string) trans('config.month_and_day_moment_js', [], $locale);
@@ -128,7 +128,7 @@ class Range
app('view')->share('madMomentJS', $madMomentJS); app('view')->share('madMomentJS', $madMomentJS);
app('view')->share('monthAndDayFormat', $monthAndDayFormat); app('view')->share('monthAndDayFormat', $monthAndDayFormat);
app('view')->share('dateTimeFormat', $dateTimeFormat); app('view')->share('dateTimeFormat', $dateTimeFormat);
app('view')->share('defaultCurrency', $defaultCurrency); app('view')->share('primaryCurrency', $primaryCurrency);
} }
/** /**

View File

@@ -53,6 +53,7 @@ class BudgetFormUpdateRequest extends FormRequest
'currency_id' => $this->convertInteger('auto_budget_currency_id'), 'currency_id' => $this->convertInteger('auto_budget_currency_id'),
'auto_budget_amount' => $this->convertString('auto_budget_amount'), 'auto_budget_amount' => $this->convertString('auto_budget_amount'),
'auto_budget_period' => $this->convertString('auto_budget_period'), 'auto_budget_period' => $this->convertString('auto_budget_period'),
'notes' => $this->stringWithNewlines('notes'),
]; ];
} }

View File

@@ -25,13 +25,18 @@ declare(strict_types=1);
namespace FireflyIII\Jobs; namespace FireflyIII\Jobs;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Events\WarnUserAboutBill; use FireflyIII\Events\Model\Bill\WarnUserAboutBill;
use FireflyIII\Events\Model\Bill\WarnUserAboutOverdueSubscriptions;
use FireflyIII\Models\Bill; use FireflyIII\Models\Bill;
use FireflyIII\Support\Facades\Navigation;
use FireflyIII\Support\JsonApi\Enrichments\SubscriptionEnrichment;
use FireflyIII\User;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable; use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
/** /**
* Class WarnAboutBills * Class WarnAboutBills
@@ -63,7 +68,7 @@ class WarnAboutBills implements ShouldQueue
$this->force = false; $this->force = false;
app('log')->debug(sprintf('Created new WarnAboutBills("%s")', $this->date->format('Y-m-d'))); Log::debug(sprintf('Created new WarnAboutBills("%s")', $this->date->format('Y-m-d')));
} }
/** /**
@@ -71,12 +76,18 @@ class WarnAboutBills implements ShouldQueue
*/ */
public function handle(): void public function handle(): void
{ {
app('log')->debug(sprintf('Now at start of WarnAboutBills() job for %s.', $this->date->format('D d M Y'))); Log::debug(sprintf('Now at start of WarnAboutBills() job for %s.', $this->date->format('D d M Y')));
$bills = Bill::all(); foreach (User::all() as $user) {
$bills = $user->bills()->where('active', true)->get();
$overdue = [];
/** @var Bill $bill */ /** @var Bill $bill */
foreach ($bills as $bill) { foreach ($bills as $bill) {
app('log')->debug(sprintf('Now checking bill #%d ("%s")', $bill->id, $bill->name)); Log::debug(sprintf('Now checking bill #%d ("%s")', $bill->id, $bill->name));
$dates = $this->getDates($bill);
if ($this->needsOverdueAlert($dates)) {
$overdue[] = ['bill' => $bill, 'dates' => $dates];
}
if ($this->hasDateFields($bill)) { if ($this->hasDateFields($bill)) {
if ($this->needsWarning($bill, 'end_date')) { if ($this->needsWarning($bill, 'end_date')) {
$this->sendWarning($bill, 'end_date'); $this->sendWarning($bill, 'end_date');
@@ -86,21 +97,21 @@ class WarnAboutBills implements ShouldQueue
} }
} }
} }
app('log')->debug('Done with handle()'); $this->sendOverdueAlerts($user, $overdue);
}
Log::debug('Done with handle()');
// clear cache:
app('preferences')->mark();
} }
private function hasDateFields(Bill $bill): bool private function hasDateFields(Bill $bill): bool
{ {
if (false === $bill->active) { if (false === $bill->active) {
app('log')->debug('Bill is not active.'); Log::debug('Bill is not active.');
return false; return false;
} }
if (null === $bill->end_date && null === $bill->extension_date) { if (null === $bill->end_date && null === $bill->extension_date) {
app('log')->debug('Bill has no date fields.'); Log::debug('Bill has no date fields.');
return false; return false;
} }
@@ -115,7 +126,7 @@ class WarnAboutBills implements ShouldQueue
} }
$diff = $this->getDiff($bill, $field); $diff = $this->getDiff($bill, $field);
$list = config('firefly.bill_reminder_periods'); $list = config('firefly.bill_reminder_periods');
app('log')->debug(sprintf('Difference in days for field "%s" ("%s") is %d day(s)', $field, $bill->{$field}->format('Y-m-d'), $diff)); Log::debug(sprintf('Difference in days for field "%s" ("%s") is %d day(s)', $field, $bill->{$field}->format('Y-m-d'), $diff));
if (in_array($diff, $list, true)) { if (in_array($diff, $list, true)) {
return true; return true;
} }
@@ -128,13 +139,13 @@ class WarnAboutBills implements ShouldQueue
$today = clone $this->date; $today = clone $this->date;
$carbon = clone $bill->{$field}; $carbon = clone $bill->{$field};
return (int) $today->diffInDays($carbon); return (int)$today->diffInDays($carbon);
} }
private function sendWarning(Bill $bill, string $field): void private function sendWarning(Bill $bill, string $field): void
{ {
$diff = $this->getDiff($bill, $field); $diff = $this->getDiff($bill, $field);
app('log')->debug('Will now send warning!'); Log::debug('Will now send warning!');
event(new WarnUserAboutBill($bill, $field, $diff)); event(new WarnUserAboutBill($bill, $field, $diff));
} }
@@ -149,4 +160,49 @@ class WarnAboutBills implements ShouldQueue
{ {
$this->force = $force; $this->force = $force;
} }
private function getDates(Bill $bill): array
{
$start = clone $this->date;
$start = Navigation::startOfPeriod($start, $bill->repeat_freq);
$end = clone $start;
$end = Navigation::endOfPeriod($end, $bill->repeat_freq);
$enrichment = new SubscriptionEnrichment();
$enrichment->setUser($bill->user);
$enrichment->setStart($start);
$enrichment->setEnd($end);
$single = $enrichment->enrichSingle($bill);
return [
'pay_dates' => $single->meta['pay_dates'] ?? [],
'paid_dates' => $single->meta['paid_dates'] ?? [],
];
}
private function needsOverdueAlert(array $dates): bool
{
$count = count($dates['pay_dates']) - count($dates['paid_dates']);
if (0 === $count || 0 === count($dates['pay_dates'])) {
return false;
}
// the earliest date in the list of pay dates must be 48hrs or more ago.
$earliest = new Carbon($dates['pay_dates'][0]);
$earliest->startOfDay();
Log::debug(sprintf('Earliest expected pay date is %s', $earliest->toAtomString()));
$diff = $earliest->diffInDays($this->date);
Log::debug(sprintf('Difference in days is %s', $diff));
if ($diff < 2) {
return false;
}
return true;
}
private function sendOverdueAlerts(User $user, array $overdue): void
{
if (count($overdue) > 0) {
Log::debug(sprintf('Will now send warning about overdue bill for user #%d.', $user->id));
event(new WarnUserAboutOverdueSubscriptions($user, $overdue));
}
}
} }

View File

@@ -0,0 +1,113 @@
<?php
declare(strict_types=1);
namespace FireflyIII\Notifications\User;
use Carbon\Carbon;
use FireflyIII\Notifications\ReturnsAvailableChannels;
use FireflyIII\Notifications\ReturnsSettings;
use FireflyIII\User;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use NotificationChannels\Pushover\PushoverMessage;
class SubscriptionsOverdueReminder extends Notification
{
use Queueable;
public function __construct(private array $overdue) {}
/**
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function toArray(User $notifiable): array
{
return [
];
}
/**
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function toMail(User $notifiable): MailMessage
{
// format the data
$info = [];
$count = 0;
foreach ($this->overdue as $item) {
$current = [
'bill' => $item['bill'],
];
$current['pay_dates'] = array_map(
static function (string $date): string {
return new Carbon($date)->isoFormat((string)trans('config.month_and_day_moment_js'));
},
$item['dates']['pay_dates']
);
$info[] = $current;
++$count;
}
return new MailMessage()
->markdown('emails.subscriptions-overdue-warning', ['info' => $info, 'count' => $count])
->subject($this->getSubject())
;
}
private function getSubject(): string
{
if (count($this->overdue) > 1) {
return (string)trans('email.subscriptions_overdue_subject_multi', ['count' => count($this->overdue)]);
}
return (string)trans('email.subscriptions_overdue_subject_single');
}
public function toNtfy(User $notifiable): Message
{
$settings = ReturnsSettings::getSettings('ntfy', 'user', $notifiable);
$message = new Message();
$message->topic($settings['ntfy_topic']);
$message->title($this->getSubject());
$message->body((string)trans('email.bill_warning_please_action'));
return $message;
}
/**
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function toPushover(User $notifiable): PushoverMessage
{
return PushoverMessage::create((string)trans('email.bill_warning_please_action'))
->title($this->getSubject())
;
}
/**
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function toSlack(User $notifiable): SlackMessage
{
$url = route('bills.index');
return new SlackMessage()
->warning()
->attachment(static function ($attachment) use ($url): void {
$attachment->title((string)trans('firefly.visit_bills'), $url);
})
->content($this->getSubject())
;
}
/**
* @SuppressWarnings("PHPMD.UnusedFormalParameter")
*/
public function via(User $notifiable): array
{
return ReturnsAvailableChannels::returnChannels('user', $notifiable);
}
}

View File

@@ -27,6 +27,8 @@ use FireflyIII\Events\ActuallyLoggedIn;
use FireflyIII\Events\Admin\InvitationCreated; use FireflyIII\Events\Admin\InvitationCreated;
use FireflyIII\Events\DestroyedTransactionGroup; use FireflyIII\Events\DestroyedTransactionGroup;
use FireflyIII\Events\DetectedNewIPAddress; use FireflyIII\Events\DetectedNewIPAddress;
use FireflyIII\Events\Model\Bill\WarnUserAboutBill;
use FireflyIII\Events\Model\Bill\WarnUserAboutOverdueSubscriptions;
use FireflyIII\Events\Model\BudgetLimit\Created; use FireflyIII\Events\Model\BudgetLimit\Created;
use FireflyIII\Events\Model\BudgetLimit\Deleted; use FireflyIII\Events\Model\BudgetLimit\Deleted;
use FireflyIII\Events\Model\BudgetLimit\Updated; use FireflyIII\Events\Model\BudgetLimit\Updated;
@@ -35,7 +37,7 @@ use FireflyIII\Events\Model\PiggyBank\ChangedName;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray;
use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject; use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject;
use FireflyIII\Events\NewVersionAvailable; use FireflyIII\Events\NewVersionAvailable;
use FireflyIII\Events\Preferences\UserGroupChangedDefaultCurrency; use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency;
use FireflyIII\Events\RegisteredUser; use FireflyIII\Events\RegisteredUser;
use FireflyIII\Events\RequestedNewPassword; use FireflyIII\Events\RequestedNewPassword;
use FireflyIII\Events\RequestedReportOnJournals; use FireflyIII\Events\RequestedReportOnJournals;
@@ -58,7 +60,6 @@ use FireflyIII\Events\TriggeredAuditLog;
use FireflyIII\Events\UpdatedAccount; 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\Handlers\Observer\AccountObserver; use FireflyIII\Handlers\Observer\AccountObserver;
use FireflyIII\Handlers\Observer\AttachmentObserver; use FireflyIII\Handlers\Observer\AttachmentObserver;
use FireflyIII\Handlers\Observer\AutoBudgetObserver; use FireflyIII\Handlers\Observer\AutoBudgetObserver;
@@ -202,6 +203,9 @@ class EventServiceProvider extends ServiceProvider
WarnUserAboutBill::class => [ WarnUserAboutBill::class => [
'FireflyIII\Handlers\Events\BillEventHandler@warnAboutBill', 'FireflyIII\Handlers\Events\BillEventHandler@warnAboutBill',
], ],
WarnUserAboutOverdueSubscriptions::class => [
'FireflyIII\Handlers\Events\BillEventHandler@warnAboutOverdueSubscriptions',
],
// audit log events: // audit log events:
TriggeredAuditLog::class => [ TriggeredAuditLog::class => [
@@ -257,7 +261,7 @@ class EventServiceProvider extends ServiceProvider
'FireflyIII\Handlers\Events\Security\MFAHandler@sendMFAFailedAttemptsMail', 'FireflyIII\Handlers\Events\Security\MFAHandler@sendMFAFailedAttemptsMail',
], ],
// preferences // preferences
UserGroupChangedDefaultCurrency::class => [ UserGroupChangedPrimaryCurrency::class => [
'FireflyIII\Handlers\Events\PreferencesEventHandler@resetPrimaryCurrencyAmounts', 'FireflyIII\Handlers\Events\PreferencesEventHandler@resetPrimaryCurrencyAmounts',
], ],
]; ];

View File

@@ -562,7 +562,13 @@ class AccountRepository implements AccountRepositoryInterface, UserGroupInterfac
'foreign_currencies.decimal_places as foreign_currency_decimal_places', 'foreign_currencies.decimal_places as foreign_currency_decimal_places',
// fields // fields
'transaction_journals.date', 'transaction_types.type', 'transaction_journals.transaction_currency_id', 'transactions.amount']) 'transaction_journals.date',
'transaction_types.type',
'transaction_journals.transaction_currency_id',
'transactions.amount',
'transactions.native_amount as pc_amount',
'transactions.foreign_amount',
])
->toArray() ->toArray()
; ;

View File

@@ -50,10 +50,10 @@ class AccountTasker implements AccountTaskerInterface, UserGroupInterface
$yesterday = clone $start; $yesterday = clone $start;
$yesterday->subDay()->endOfDay(); // exactly up until $start but NOT including. $yesterday->subDay()->endOfDay(); // exactly up until $start but NOT including.
$end->endOfDay(); // needs to be end of day to be correct. $end->endOfDay(); // needs to be end of day to be correct.
Log::debug(sprintf('getAccountReport: finalAccountsBalance("%s")', $yesterday->format('Y-m-d H:i:s'))); Log::debug(sprintf('getAccountReport: accountsBalancesOptimized("%s")', $yesterday->format('Y-m-d H:i:s')));
Log::debug(sprintf('getAccountReport: finalAccountsBalance("%s")', $end->format('Y-m-d H:i:s'))); Log::debug(sprintf('getAccountReport: accountsBalancesOptimized("%s")', $end->format('Y-m-d H:i:s')));
$startSet = Steam::finalAccountsBalance($accounts, $yesterday); $startSet = Steam::accountsBalancesOptimized($accounts, $yesterday);
$endSet = Steam::finalAccountsBalance($accounts, $end); $endSet = Steam::accountsBalancesOptimized($accounts, $end);
Log::debug('Start of accountreport'); Log::debug('Start of accountreport');
/** @var AccountRepositoryInterface $repository */ /** @var AccountRepositoryInterface $repository */

View File

@@ -52,4 +52,10 @@ class ALERepository implements ALERepositoryInterface
return $auditLogEntry; return $auditLogEntry;
} }
public function getForId(string $model, int $modelId): Collection
{
// all Models have an ID.
return AuditLogEntry::where('auditable_id', $modelId)->where('auditable_type', $model)->get();
}
} }

View File

@@ -46,5 +46,7 @@ interface ALERepositoryInterface
{ {
public function getForObject(Model $model): Collection; public function getForObject(Model $model): Collection;
public function getForId(string $model, int $modelId): Collection;
public function store(array $data): AuditLogEntry; public function store(array $data): AuditLogEntry;
} }

View File

@@ -32,6 +32,7 @@ use FireflyIII\Support\Report\Summarizer\TransactionSummarizer;
use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface; use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface;
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Override;
/** /**
* Class NoBudgetRepository * Class NoBudgetRepository
@@ -98,4 +99,23 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface, UserGroupInterf
return $summarizer->groupByCurrencyId($journals); return $summarizer->groupByCurrencyId($journals);
} }
#[Override]
public function collectExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array
{
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
if ($accounts instanceof Collection && $accounts->count() > 0) {
$collector->setAccounts($accounts);
}
if ($currency instanceof TransactionCurrency) {
$collector->setCurrency($currency);
}
$collector->withoutBudget();
$collector->withBudgetInformation();
return $collector->getExtractedJournals();
}
} }

View File

@@ -49,4 +49,6 @@ interface NoBudgetRepositoryInterface
public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array; public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array;
public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array; public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array;
public function collectExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array;
} }

View File

@@ -39,6 +39,7 @@ use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface;
use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait; use FireflyIII\Support\Repositories\UserGroup\UserGroupTrait;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
use Override;
/** /**
* Class OperationsRepository * Class OperationsRepository
@@ -57,17 +58,17 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
$total = '0'; $total = '0';
$count = 0; $count = 0;
foreach ($budget->budgetlimits as $limit) { foreach ($budget->budgetlimits as $limit) {
$diff = (int)$limit->start_date->diffInDays($limit->end_date, true); $diff = (int) $limit->start_date->diffInDays($limit->end_date, true);
$diff = 0 === $diff ? 1 : $diff; $diff = 0 === $diff ? 1 : $diff;
$amount = $limit->amount; $amount = $limit->amount;
$perDay = bcdiv((string)$amount, (string)$diff); $perDay = bcdiv((string) $amount, (string) $diff);
$total = bcadd($total, $perDay); $total = bcadd($total, $perDay);
++$count; ++$count;
app('log')->debug(sprintf('Found %d budget limits. Per day is %s, total is %s', $count, $perDay, $total)); app('log')->debug(sprintf('Found %d budget limits. Per day is %s, total is %s', $count, $perDay, $total));
} }
$avg = $total; $avg = $total;
if ($count > 0) { if ($count > 0) {
$avg = bcdiv($total, (string)$count); $avg = bcdiv($total, (string) $count);
} }
app('log')->debug(sprintf('%s / %d = %s = average.', $total, $count, $avg)); app('log')->debug(sprintf('%s / %d = %s = average.', $total, $count, $avg));
@@ -95,9 +96,9 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
/** @var array $journal */ /** @var array $journal */
foreach ($journals as $journal) { foreach ($journals as $journal) {
// prep data array for currency: // prep data array for currency:
$budgetId = (int)$journal['budget_id']; $budgetId = (int) $journal['budget_id'];
$budgetName = $journal['budget_name']; $budgetName = $journal['budget_name'];
$currencyId = (int)$journal['currency_id']; $currencyId = (int) $journal['currency_id'];
$key = sprintf('%d-%d', $budgetId, $currencyId); $key = sprintf('%d-%d', $budgetId, $currencyId);
$data[$key] ??= [ $data[$key] ??= [
@@ -112,7 +113,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
'entries' => [], 'entries' => [],
]; ];
$date = $journal['date']->format($carbonFormat); $date = $journal['date']->format($carbonFormat);
$data[$key]['entries'][$date] = bcadd($data[$key]['entries'][$date] ?? '0', (string)$journal['amount']); $data[$key]['entries'][$date] = bcadd($data[$key]['entries'][$date] ?? '0', (string) $journal['amount']);
} }
return $data; return $data;
@@ -156,7 +157,7 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
foreach ($journals as $journal) { foreach ($journals as $journal) {
$amount = app('steam')->negative($journal['amount']); $amount = app('steam')->negative($journal['amount']);
$journalCurrencyId = (int)$journal['currency_id']; $journalCurrencyId = (int) $journal['currency_id'];
if (false === $convertToPrimary) { if (false === $convertToPrimary) {
$currencyId = $journalCurrencyId; $currencyId = $journalCurrencyId;
$currencyName = $journal['currency_name']; $currencyName = $journal['currency_name'];
@@ -169,8 +170,8 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
$amount = $converter->convert($currencies[$journalCurrencyId], $primaryCurrency, $journal['date'], $amount); $amount = $converter->convert($currencies[$journalCurrencyId], $primaryCurrency, $journal['date'], $amount);
} }
$budgetId = (int)$journal['budget_id']; $budgetId = (int) $journal['budget_id'];
$budgetName = (string)$journal['budget_name']; $budgetName = (string) $journal['budget_name'];
// catch "no budget" entries. // catch "no budget" entries.
if (0 === $budgetId) { if (0 === $budgetId) {
@@ -196,13 +197,16 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
// add journal to array: // add journal to array:
// only a subset of the fields. // only a subset of the fields.
$journalId = (int)$journal['transaction_journal_id']; $journalId = (int) $journal['transaction_journal_id'];
$array[$currencyId]['budgets'][$budgetId]['transaction_journals'][$journalId] = [ $array[$currencyId]['budgets'][$budgetId]['transaction_journals'][$journalId] = [
'amount' => $amount, 'amount' => $amount,
'destination_account_id' => $journal['destination_account_id'], 'destination_account_id' => $journal['destination_account_id'],
'destination_account_name' => $journal['destination_account_name'], 'destination_account_name' => $journal['destination_account_name'],
'destination_account_type' => $journal['destination_account_type'],
'currency_id' => $journalCurrencyId,
'source_account_id' => $journal['source_account_id'], 'source_account_id' => $journal['source_account_id'],
'source_account_name' => $journal['source_account_name'], 'source_account_name' => $journal['source_account_name'],
'source_account_type' => $journal['source_account_type'],
'category_name' => $journal['category_name'], 'category_name' => $journal['category_name'],
'description' => $journal['description'], 'description' => $journal['description'],
'transaction_group_id' => $journal['transaction_group_id'], 'transaction_group_id' => $journal['transaction_group_id'],
@@ -282,4 +286,77 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
return $summarizer->groupByCurrencyId($journals, 'negative', false); return $summarizer->groupByCurrencyId($journals, 'negative', false);
} }
public function sumCollectedExpenses(array $expenses, Carbon $start, Carbon $end, TransactionCurrency $transactionCurrency, bool $convertToPrimary = false): array
{
Log::debug(sprintf('Start of %s.', __METHOD__));
$summarizer = new TransactionSummarizer($this->user);
$summarizer->setConvertToPrimary($convertToPrimary);
// filter $journals by range AND currency if it is present.
$expenses = array_filter($expenses, static function (array $expense) use ($start, $end, $transactionCurrency): bool {
return $expense['date']->between($start, $end) && $expense['currency_id'] === $transactionCurrency->id;
});
return $summarizer->groupByCurrencyId($expenses, 'negative', false);
}
public function sumCollectedExpensesByBudget(array $expenses, Budget $budget, bool $convertToPrimary = false): array
{
Log::debug(sprintf('Start of %s.', __METHOD__));
$summarizer = new TransactionSummarizer($this->user);
$summarizer->setConvertToPrimary($convertToPrimary);
// filter $journals by range AND currency if it is present.
$expenses = array_filter($expenses, static function (array $expense) use ($budget): bool {
return $expense['budget_id'] === $budget->id;
});
return $summarizer->groupByCurrencyId($expenses, 'negative', false);
}
#[Override]
public function collectExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null): array
{
Log::debug(sprintf('Start of %s(date, date, array, array, "%s").', __METHOD__, $currency?->code));
// this collector excludes all transfers TO liabilities (which are also withdrawals)
// because those expenses only become expenses once they move from the liability to the friend.
// 2024-12-24 disable the exclusion for now.
$repository = app(AccountRepositoryInterface::class);
$repository->setUser($this->user);
$subset = $repository->getAccountsByType(config('firefly.valid_liabilities'));
$selection = new Collection();
/** @var Account $account */
foreach ($subset as $account) {
if ('credit' === $repository->getMetaValue($account, 'liability_direction')) {
$selection->push($account);
}
}
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)
->setRange($start, $end)
// ->excludeDestinationAccounts($selection)
->setTypes([TransactionTypeEnum::WITHDRAWAL->value])
;
if ($accounts instanceof Collection) {
$collector->setAccounts($accounts);
}
if (!$budgets instanceof Collection) {
$budgets = $this->getBudgets();
}
if ($currency instanceof TransactionCurrency) {
Log::debug(sprintf('Limit to normal currency %s', $currency->code));
$collector->setNormalCurrency($currency);
}
if ($budgets->count() > 0) {
$collector->setBudgets($budgets);
}
return $collector->getExtractedJournals();
}
} }

View File

@@ -24,8 +24,8 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Budget; namespace FireflyIII\Repositories\Budget;
use Deprecated;
use Carbon\Carbon; use Carbon\Carbon;
use Deprecated;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Budget; use FireflyIII\Models\Budget;
use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionCurrency;
@@ -73,4 +73,10 @@ interface OperationsRepositoryInterface
?TransactionCurrency $currency = null, ?TransactionCurrency $currency = null,
bool $convertToPrimary = false bool $convertToPrimary = false
): array; ): array;
public function sumCollectedExpenses(array $expenses, Carbon $start, Carbon $end, TransactionCurrency $transactionCurrency, bool $convertToPrimary = false): array;
public function sumCollectedExpensesByBudget(array $expenses, Budget $budget, bool $convertToPrimary = false): array;
public function collectExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null): array;
} }

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Repositories\Category;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Helpers\Collector\GroupCollectorInterface;
use FireflyIII\Models\Category;
use FireflyIII\Support\Facades\Amount; use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Report\Summarizer\TransactionSummarizer; use FireflyIII\Support\Report\Summarizer\TransactionSummarizer;
use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface; use FireflyIII\Support\Repositories\UserGroup\UserGroupInterface;
@@ -444,4 +445,74 @@ class OperationsRepository implements OperationsRepositoryInterface, UserGroupIn
return $array; return $array;
} }
public function collectExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array
{
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionTypeEnum::WITHDRAWAL->value]);
if ($accounts instanceof Collection && $accounts->count() > 0) {
$collector->setAccounts($accounts);
}
if (!$categories instanceof Collection || 0 === $categories->count()) {
$categories = $this->getCategories();
}
$collector->setCategories($categories);
$collector->withCategoryInformation();
return $collector->getExtractedJournals();
}
public function collectIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array
{
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)->setRange($start, $end)
->setTypes([TransactionTypeEnum::DEPOSIT->value])
;
if ($accounts instanceof Collection && $accounts->count() > 0) {
$collector->setAccounts($accounts);
}
if (!$categories instanceof Collection || 0 === $categories->count()) {
$categories = $this->getCategories();
}
$collector->setCategories($categories);
return $collector->getExtractedJournals();
}
public function collectTransfers(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array
{
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user)->setRange($start, $end)
->setTypes([TransactionTypeEnum::TRANSFER->value])
;
if ($accounts instanceof Collection && $accounts->count() > 0) {
$collector->setAccounts($accounts);
}
if (!$categories instanceof Collection || 0 === $categories->count()) {
$categories = $this->getCategories();
}
$collector->setCategories($categories);
return $collector->getExtractedJournals();
}
public function sumCollectedTransactionsByCategory(array $expenses, Category $category, string $method, bool $convertToPrimary = false): array
{
Log::debug(sprintf('Start of %s.', __METHOD__));
$summarizer = new TransactionSummarizer($this->user);
$summarizer->setConvertToPrimary($convertToPrimary);
// filter $journals by range AND currency if it is present.
$expenses = array_filter($expenses, static function (array $expense) use ($category): bool {
return $expense['category_id'] === $category->id;
});
return $summarizer->groupByCurrencyId($expenses, $method, false);
}
} }

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Repositories\Category;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Category;
use FireflyIII\Models\UserGroup; use FireflyIII\Models\UserGroup;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Contracts\Auth\Authenticatable; use Illuminate\Contracts\Auth\Authenticatable;
@@ -78,6 +79,14 @@ interface OperationsRepositoryInterface
*/ */
public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array; public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array;
public function collectExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array;
public function collectIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array;
public function collectTransfers(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $categories = null): array;
public function sumCollectedTransactionsByCategory(array $expenses, Category $category, string $method, bool $convertToPrimary = false): array;
/** /**
* Sum of income journals in period for a set of categories, grouped per currency. Amounts are always positive. * Sum of income journals in period for a set of categories, grouped per currency. Amounts are always positive.
*/ */

View File

@@ -24,7 +24,7 @@ declare(strict_types=1);
namespace FireflyIII\Repositories\Currency; namespace FireflyIII\Repositories\Currency;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Events\Preferences\UserGroupChangedDefaultCurrency; use FireflyIII\Events\Preferences\UserGroupChangedPrimaryCurrency;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Factory\TransactionCurrencyFactory; use FireflyIII\Factory\TransactionCurrencyFactory;
use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountMeta;
@@ -438,7 +438,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
if ($current->id !== $currency->id) { if ($current->id !== $currency->id) {
Log::debug('Trigger on a different default currency.'); Log::debug('Trigger on a different default currency.');
// clear all primary currency amounts through an event. // clear all primary currency amounts through an event.
event(new UserGroupChangedDefaultCurrency($this->userGroup)); event(new UserGroupChangedPrimaryCurrency($this->userGroup));
} }
} }
} }

View File

@@ -131,7 +131,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface, UserGroupInte
/** /**
* Get current amount saved in piggy bank. * Get current amount saved in piggy bank.
*/ */
public function getCurrentPrimaryAmount(PiggyBank $piggyBank, ?Account $account = null): string public function getCurrentPrimaryCurrencyAmount(PiggyBank $piggyBank, ?Account $account = null): string
{ {
$sum = '0'; $sum = '0';
foreach ($piggyBank->accounts as $current) { foreach ($piggyBank->accounts as $current) {

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