mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-08-23 13:45:14 +00:00
Compare commits
379 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
23faef845c | ||
|
daf859b977 | ||
|
f47ba6c977 | ||
|
4b9b207d92 | ||
|
875cbf66af | ||
|
412d6d4fd7 | ||
|
91c6deeb1f | ||
|
6d1978fd9a | ||
|
52d23b6ef5 | ||
|
0656ccbdd9 | ||
|
e774ebd0a3 | ||
|
edbda32a84 | ||
|
721fa04e3c | ||
|
9fd8d8915d | ||
|
7a9f5ebdd1 | ||
|
a3423f0321 | ||
|
c37e9a4467 | ||
|
6157d82a0b | ||
|
38b27fec92 | ||
|
c43439bb68 | ||
|
8d9561d7a5 | ||
|
2a72cce3b7 | ||
|
d3bbb6fb1f | ||
|
7b6723e9a2 | ||
|
1ee741460d | ||
|
967b0b493b | ||
|
b53aaf7dde | ||
|
714c13bdbf | ||
|
651a4fd3cc | ||
|
505aee22bb | ||
|
ca3d59dc33 | ||
|
13890e32a1 | ||
|
df8976eabe | ||
|
3e01daa172 | ||
|
f6999f355b | ||
|
5c06b45eb1 | ||
|
1802bb967a | ||
|
d8d92f147f | ||
|
4a95bdd8ba | ||
|
db5d94d956 | ||
|
06f2e34bb5 | ||
|
2ef7a01945 | ||
|
d3f642551d | ||
|
490997157e | ||
|
2432af7883 | ||
|
7abeece3f0 | ||
|
3851652821 | ||
|
1d67d2250a | ||
|
37f40d8637 | ||
|
0224d1d59b | ||
|
587b94153d | ||
|
5124ce0302 | ||
|
950c4045b0 | ||
|
9c8ba66873 | ||
|
25d1d1be1b | ||
|
339c352505 | ||
|
c587081fe4 | ||
|
8f9b1b866b | ||
|
ff5ecf6182 | ||
|
05670cf393 | ||
|
f10f5d30bf | ||
|
0d336727e8 | ||
|
bf354275b3 | ||
|
1932bf277a | ||
|
192db4bb6e | ||
|
701efb943d | ||
|
b2674971f1 | ||
|
c907cb4cf1 | ||
|
bb1462b4d9 | ||
|
1035f0e139 | ||
|
8475757716 | ||
|
20ffd8d61b | ||
|
8601428c4c | ||
|
59998573ee | ||
|
293cd72001 | ||
|
22ab9ebb2f | ||
|
9136e592d3 | ||
|
ed8e392616 | ||
|
e57ce6e644 | ||
|
8204e46086 | ||
|
9e365d9f80 | ||
|
6b40a933e9 | ||
|
8520a5002f | ||
|
b38ed06f6e | ||
|
48427b1143 | ||
|
5d505f4ed0 | ||
|
0c02a08954 | ||
|
0221bd0f80 | ||
|
28216cbcb5 | ||
|
3e08a8cd6b | ||
|
67fafdeef7 | ||
|
cc82505b66 | ||
|
fd5f075f63 | ||
|
a115960411 | ||
|
e9fa4ca816 | ||
|
75d92bc7f0 | ||
|
74aa6e911e | ||
|
9d000c1898 | ||
|
b2254875b2 | ||
|
78d04230d5 | ||
|
1c04477393 | ||
|
2a9679c94e | ||
|
6009f8ecde | ||
|
35cdbec70a | ||
|
0faef542c1 | ||
|
8b085af6a1 | ||
|
e3b11a9eb2 | ||
|
72fc88f3c6 | ||
|
a5b759f268 | ||
|
6a9ffae25d | ||
|
64c031c7fe | ||
|
720926c50d | ||
|
36ec974284 | ||
|
cff77c39e2 | ||
|
056a0a1736 | ||
|
f301da83c6 | ||
|
5362231efa | ||
|
4bb14cad73 | ||
|
7f5188f5a4 | ||
|
a80b7aac6c | ||
|
83f32478fa | ||
|
7578ec6801 | ||
|
e14a32f76f | ||
|
58faa189ac | ||
|
9b4f87d44a | ||
|
7830a64170 | ||
|
8f0fa02107 | ||
|
e000fb5d80 | ||
|
566fadad15 | ||
|
cf23858c10 | ||
|
216a223617 | ||
|
638f38d823 | ||
|
98ee70f04e | ||
|
b365db5a4b | ||
|
02e55496df | ||
|
e11e53913a | ||
|
f8a5fb4225 | ||
|
3a49450461 | ||
|
3c375fb955 | ||
|
011fea2cc6 | ||
|
a079eec2cb | ||
|
776b37f4ea | ||
|
a4d8bbe3da | ||
|
72166743fa | ||
|
c4312c0b11 | ||
|
38ba645415 | ||
|
ac12a47071 | ||
|
bea321939e | ||
|
210f84b6ea | ||
|
d4c642741f | ||
|
e6b1b58379 | ||
|
8d982c1a90 | ||
|
be10e836dc | ||
|
9be05e7e17 | ||
|
bd96b2819f | ||
|
f601af3da0 | ||
|
70a01c082b | ||
|
bcf066ead7 | ||
|
24dd3578ed | ||
|
d5c39d54d8 | ||
|
6e3f6abc67 | ||
|
463201df2c | ||
|
a7501c396f | ||
|
4c8bc49a7e | ||
|
f254674f88 | ||
|
a97c267378 | ||
|
eaa947894b | ||
|
fb3a26510b | ||
|
bfe8b14e49 | ||
|
afb47eb742 | ||
|
ba97f96288 | ||
|
ecbafb8f4b | ||
|
12d3800d67 | ||
|
d586b82372 | ||
|
ba9877c9b4 | ||
|
907933f3df | ||
|
2e91d21a88 | ||
|
dca395a018 | ||
|
625070a5b9 | ||
|
f875c7cbf5 | ||
|
eed88fc103 | ||
|
6fc54d1d27 | ||
|
0ef52bf909 | ||
|
95e34af6ef | ||
|
650b99ead2 | ||
|
57941a19de | ||
|
6157db0b6a | ||
|
c9358acf5d | ||
|
ed29eb8a5d | ||
|
bcf7452312 | ||
|
b9000519e4 | ||
|
2694297466 | ||
|
53ff5c1490 | ||
|
32a036b076 | ||
|
aae2ab2693 | ||
|
4ef23e28a3 | ||
|
38beb7f8d2 | ||
|
0129a66906 | ||
|
45bced7b34 | ||
|
7f5a55dffb | ||
|
80289df6d3 | ||
|
2115c3ced8 | ||
|
1c2d0e6618 | ||
|
ea4f7f79ce | ||
|
b17f8ac311 | ||
|
6870d13b72 | ||
|
81fa304fd2 | ||
|
a663ddb0d9 | ||
|
f7969afc22 | ||
|
52ce4cd313 | ||
|
247175881f | ||
|
fcf5009338 | ||
|
12542d8f63 | ||
|
e94194e28b | ||
|
115499f3b2 | ||
|
12af05b94f | ||
|
88b83d8164 | ||
|
fcc22c692a | ||
|
a876e8005c | ||
|
2288e3705a | ||
|
e8b58154e0 | ||
|
4393475af3 | ||
|
3fc560597c | ||
|
9f9af0b693 | ||
|
a83fe2caea | ||
|
30c5376217 | ||
|
6dddd6629d | ||
|
f80de12cb5 | ||
|
544ffca3a5 | ||
|
e0730c7b39 | ||
|
3d59d141c4 | ||
|
ccddc2623d | ||
|
fcc47b58b4 | ||
|
f67ac2e25e | ||
|
26127c9ccf | ||
|
d624efa799 | ||
|
ed3d40a4e0 | ||
|
6e90ce5496 | ||
|
ab851b1be4 | ||
|
340de53825 | ||
|
a867b60af0 | ||
|
26eafb0bd2 | ||
|
0dbe44764b | ||
|
2159df6802 | ||
|
23389b9f17 | ||
|
6d3e3b894a | ||
|
55340aefa3 | ||
|
94bc751e41 | ||
|
89259c11e2 | ||
|
6bbaf1523c | ||
|
fa3f18b60f | ||
|
3dc794002f | ||
|
f50b133f2e | ||
|
1d6f6d28c9 | ||
|
c913de3c8b | ||
|
bbc7b54a38 | ||
|
05fa1b40d1 | ||
|
6a88c8634d | ||
|
8ae1efa230 | ||
|
ab8df4c8ab | ||
|
c259a46ed3 | ||
|
5dc0677599 | ||
|
7ed662ecc2 | ||
|
4361cc69d4 | ||
|
461cbcbc28 | ||
|
09ae6c488b | ||
|
271a0ade26 | ||
|
4b076d227a | ||
|
3c4e7158a1 | ||
|
0b16765f37 | ||
|
20c2ff3443 | ||
|
96f2e598f4 | ||
|
7374f0f9dd | ||
|
ccc44a74a0 | ||
|
66cd63a68d | ||
|
decf7e5485 | ||
|
063c8025aa | ||
|
2fa7d2bd56 | ||
|
e55e7bce74 | ||
|
f572445a65 | ||
|
8b4f656d90 | ||
|
6c1e093ebd | ||
|
6dd1b4537a | ||
|
39ca9bea72 | ||
|
999103277e | ||
|
3cc57ab89c | ||
|
4e830079de | ||
|
ea7231e9fe | ||
|
ddfaca6d0c | ||
|
3b11bd0593 | ||
|
3f89057528 | ||
|
2f1073712f | ||
|
678e504c48 | ||
|
e69545fd95 | ||
|
a7ed025cd6 | ||
|
3d8e1f2484 | ||
|
c38c9608da | ||
|
2396b75e3c | ||
|
e5c19b7562 | ||
|
114788567d | ||
|
17ae4b7d2a | ||
|
12d652bd0e | ||
|
ff1bed97b8 | ||
|
56490f0e84 | ||
|
0b028a8923 | ||
|
43ac541cb8 | ||
|
5218443678 | ||
|
d9028ed9b7 | ||
|
9b9bd11ebb | ||
|
07011ec5f7 | ||
|
c3990ac32f | ||
|
081ff3ff55 | ||
|
93996ada96 | ||
|
a60671d4c1 | ||
|
3f716cc369 | ||
|
9f23cffd1b | ||
|
07c416cfbf | ||
|
389fcc1c8d | ||
|
fa07811375 | ||
|
fc91a50979 | ||
|
f9c518f321 | ||
|
015b439f0d | ||
|
0675622508 | ||
|
e9969bdd5f | ||
|
1139f950ed | ||
|
284732c7a6 | ||
|
0cb0720d8b | ||
|
8ad1ede0c5 | ||
|
a349aac8a4 | ||
|
83b169c6ef | ||
|
49c37baac5 | ||
|
8d62088576 | ||
|
f5437a17f8 | ||
|
92af4e5c96 | ||
|
0619adb0cd | ||
|
65a5107854 | ||
|
0fcc1e252b | ||
|
4b7f817475 | ||
|
0439599971 | ||
|
fa344d5308 | ||
|
f0316f09ed | ||
|
b1af6bab28 | ||
|
ad2aebb54d | ||
|
23fc652092 | ||
|
f0a5756f25 | ||
|
14c7ad201a | ||
|
08ca3c89d3 | ||
|
edda470bf8 | ||
|
7183d72e5c | ||
|
5e38ebfce5 | ||
|
56e36847a5 | ||
|
6dba916d02 | ||
|
fd57086ffd | ||
|
d98d366eea | ||
|
b261b0b447 | ||
|
c6042a9053 | ||
|
ae1245abec | ||
|
e26d2376fc | ||
|
bb36ad64a7 | ||
|
262d4f92d4 | ||
|
675530458c | ||
|
19e34b460f | ||
|
dddb8cdbc0 | ||
|
0d0df5f143 | ||
|
d1cf683f57 | ||
|
d099c33e5b | ||
|
21fb41545b | ||
|
4c56814785 | ||
|
cffe05e22b | ||
|
4237850299 | ||
|
b5fc36a8e1 | ||
|
4586c1ef52 | ||
|
2722f0b749 | ||
|
d6cf7c4872 | ||
|
3aedfed432 | ||
|
edeaf13259 | ||
|
c1290c4e9b | ||
|
b2c1527b17 | ||
|
a4a65ea56e |
@@ -1,3 +1,3 @@
|
||||
src_dir: .
|
||||
coverage_clover: tests/_output/coverage.xml
|
||||
json_path: tests/_output/coveralls-upload.json
|
||||
coverage_clover: storage/coverage/clover.xml
|
||||
json_path: storage/coverage/coveralls-upload.json
|
||||
|
@@ -1,5 +1,5 @@
|
||||
APP_ENV=local
|
||||
APP_DEBUG=true
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
APP_KEY=SomeRandomString
|
||||
|
||||
DB_CONNECTION=mysql
|
||||
@@ -12,5 +12,7 @@ CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
EMAIL_SMTP=
|
||||
EMAIL_DRIVER=smtp
|
||||
EMAIL_USERNAME=
|
||||
EMAIL_PASSWORD=
|
||||
ANALYTICS_ID=
|
@@ -11,3 +11,7 @@ DB_PASSWORD=secret
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
EMAIL_SMTP=
|
||||
EMAIL_USERNAME=
|
||||
EMAIL_PASSWORD=
|
||||
ANALYTICS_ID=ABC
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -25,3 +25,6 @@ c3.php
|
||||
db.sqlite-journal
|
||||
tests/_output/*
|
||||
.env
|
||||
clover.xml
|
||||
node_modules/
|
||||
addNewLines.php
|
||||
|
12
.travis.yml
12
.travis.yml
@@ -1,4 +1,6 @@
|
||||
language: php
|
||||
sudo: false
|
||||
|
||||
|
||||
php:
|
||||
- 5.5
|
||||
@@ -9,18 +11,12 @@ addons:
|
||||
repo_token: 26489f9e854fcdf7e7660ba29c1455694685465b1f90329a79f7d2bf448acb61
|
||||
|
||||
install:
|
||||
- rm composer.lock
|
||||
- composer install
|
||||
- composer update
|
||||
- php artisan env
|
||||
- mv -v .env.testing .env
|
||||
|
||||
script:
|
||||
- ./tests/_data/db.sh
|
||||
- php vendor/bin/codecept build
|
||||
- php vendor/bin/codecept run --coverage --coverage-xml --no-exit
|
||||
- phpunit --debug
|
||||
|
||||
after_script:
|
||||
- cp -v tests/_output/coverage.xml build/logs/clover.xml
|
||||
- php vendor/bin/coveralls
|
||||
- vendor/bin/test-reporter --stdout > codeclimate.json
|
||||
- "curl -X POST -d @codeclimate.json -H 'Content-Type: application/json' -H 'User-Agent: Code Climate (PHP Test Reporter v0.1.1)' https://codeclimate.com/test_reports"
|
30
README.md
30
README.md
@@ -1,11 +1,12 @@
|
||||
Firefly III (v3.3)
|
||||
Firefly III (v3.3.8)
|
||||
===========
|
||||
|
||||
[](https://travis-ci.org/JC5/firefly-iii)
|
||||
[](http://stillmaintained.com/JC5/firefly-iii)
|
||||
[](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102)
|
||||
[](https://codeclimate.com/github/JC5/firefly-iii)
|
||||
[](https://codeclimate.com/github/JC5/firefly-iii)
|
||||
[](https://coveralls.io/r/JC5/firefly-iii?branch=master)
|
||||
[](https://coveralls.io/r/JC5/firefly-iii?branch=develop)
|
||||
|
||||
[](https://packagist.org/packages/grumpydictator/firefly-iii)
|
||||
[](https://packagist.org/packages/grumpydictator/firefly-iii)
|
||||
@@ -18,16 +19,25 @@ Firefly Mark III is a new version of Firefly built upon best practices and lesso
|
||||
from building [Firefly](https://github.com/JC5/Firefly). It's Mark III since the original Firefly never made it outside of my
|
||||
laptop and [Firefly II](https://github.com/JC5/Firefly) is live.
|
||||
|
||||
If you're not sure if this tool is for you, please read the [full description](https://github.com/JC5/firefly-iii/wiki/full-description).
|
||||
|
||||
To install and use Firefly III, please read [the installation guide](https://github.com/JC5/firefly-iii/wiki/Installation),
|
||||
[the upgrade guide](https://github.com/JC5/firefly-iii/wiki/Upgrade-instructions) (if applicable) and the **[first use guide](https://github.com/JC5/firefly-iii/wiki/First-use)**
|
||||
|
||||
## Current features
|
||||
|
||||
- [A double-entry bookkeeping system](http://en.wikipedia.org/wiki/Double-entry_bookkeeping_system);
|
||||
- [A double-entry bookkeeping system](https://en.wikipedia.org/wiki/Double-entry_bookkeeping_system);
|
||||
- You can store, edit and remove withdrawals, deposits and transfers. This allows you full financial management;
|
||||
- It's possible to create, change and manage money using _budgets_;
|
||||
- You can manage different types of accounts
|
||||
- Asset accounts
|
||||
- Shared asset accounts (household accounts)
|
||||
- Saving accounts
|
||||
- Credit cards
|
||||
- It's possible to create, change and manage money using _[budgets](https://en.wikipedia.org/wiki/Envelope_system)_;
|
||||
- Organize transactions using categories;
|
||||
- Save towards a goal using piggy banks;
|
||||
- Predict and anticipate large expenses using "repeated expenses" (ie. yearly taxes);
|
||||
- Predict and anticipate bills using "recurring transactions" (rent for example);
|
||||
- View basic income / expense reports.
|
||||
- Predict and anticipate bills;
|
||||
- View income / expense reports;
|
||||
- Lots of help text in case you don't get it;
|
||||
|
||||
Everything is organised:
|
||||
@@ -44,9 +54,7 @@ Firefly III will feature, but does not feature yet:
|
||||
|
||||
|
||||
- More control over other resources outside of personal finance
|
||||
- Accounts shared with a partner (household accounts)
|
||||
- Debts
|
||||
- Credit cards
|
||||
- More test-coverage;
|
||||
- Firefly will be able to split transactions; a single purchase can be split in multiple entries, for more fine-grained control.
|
||||
- Firefly will be able to join transactions.
|
||||
@@ -55,7 +63,6 @@ Firefly III will feature, but does not feature yet:
|
||||
Some stuff has been removed:
|
||||
|
||||
- The nesting of budgets, categories and beneficiaries is removed because it was pretty pointless.
|
||||
- Firefly will not encrypt the content of the (MySQL) tables. Old versions of Firefly had this capability but it sucks when searching, sorting and organizing entries.
|
||||
|
||||
## Screenshots
|
||||
|
||||
@@ -70,7 +77,4 @@ Some stuff has been removed:
|
||||
## Current state
|
||||
I have the basics up and running. Test coverage is currently coming, slowly.
|
||||
|
||||
Although I have not checked extensively, some forms and views have CSRF vulnerabilities. This is because not all
|
||||
views escape all characters by default. Will be fixed.
|
||||
|
||||
Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)!
|
||||
|
@@ -1,37 +0,0 @@
|
||||
<?php namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Foundation\Inspiring;
|
||||
|
||||
/**
|
||||
* Class Inspire
|
||||
*
|
||||
* @package FireflyIII\Console\Commands
|
||||
*/
|
||||
class Inspire extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Display an inspiring quote';
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name = 'inspire';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->comment(PHP_EOL . Inspiring::quote() . PHP_EOL);
|
||||
}
|
||||
|
||||
}
|
@@ -18,7 +18,6 @@ class Kernel extends ConsoleKernel
|
||||
*/
|
||||
protected $commands
|
||||
= [
|
||||
'FireflyIII\Console\Commands\Inspire',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -30,8 +29,6 @@ class Kernel extends ConsoleKernel
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$schedule->command('inspire')
|
||||
->hourly();
|
||||
}
|
||||
|
||||
}
|
||||
|
32
app/Events/JournalCreated.php
Normal file
32
app/Events/JournalCreated.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
/**
|
||||
* Class JournalCreated
|
||||
*
|
||||
* @package FireflyIII\Events
|
||||
*/
|
||||
class JournalCreated extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public $journal;
|
||||
public $piggyBankId;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(TransactionJournal $journal, $piggyBankId)
|
||||
{
|
||||
//
|
||||
$this->journal = $journal;
|
||||
$this->piggyBankId = $piggyBankId;
|
||||
|
||||
}
|
||||
|
||||
}
|
24
app/Events/JournalSaved.php
Normal file
24
app/Events/JournalSaved.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class JournalSaved extends Event
|
||||
{
|
||||
|
||||
use SerializesModels;
|
||||
|
||||
public $journal;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(TransactionJournal $journal)
|
||||
{
|
||||
//
|
||||
$this->journal = $journal;
|
||||
}
|
||||
|
||||
}
|
83
app/Handlers/Events/ConnectJournalToPiggyBank.php
Normal file
83
app/Handlers/Events/ConnectJournalToPiggyBank.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Events\JournalCreated;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class ConnectJournalToPiggyBank
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class ConnectJournalToPiggyBank
|
||||
{
|
||||
|
||||
/**
|
||||
* Create the event handler.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event when journal is saved.
|
||||
*
|
||||
* @param JournalCreated $event
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(JournalCreated $event)
|
||||
{
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = $event->journal;
|
||||
$piggyBankId = $event->piggyBankId;
|
||||
if (intval($piggyBankId) < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log::debug('JournalCreated event: ' . $journal->id . ', ' . $piggyBankId);
|
||||
|
||||
/** @var PiggyBank $piggyBank */
|
||||
$piggyBank = Auth::user()->piggybanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
|
||||
|
||||
if (is_null($piggyBank) || $journal->transactionType->type != 'Transfer') {
|
||||
return;
|
||||
}
|
||||
Log::debug('Found a piggy bank');
|
||||
$amount = $journal->amount;
|
||||
Log::debug('Amount: ' . $amount);
|
||||
if ($amount == 0) {
|
||||
return;
|
||||
}
|
||||
// update piggy bank rep for date of transaction journal.
|
||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||
if (is_null($repetition)) {
|
||||
Log::debug('Found no repetition for piggy bank for date ' . $journal->date->format('Y M d'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Log::debug('Found rep! ' . $repetition->id);
|
||||
$repetition->currentamount += $amount;
|
||||
$repetition->save();
|
||||
|
||||
PiggyBankEvent::create(
|
||||
[
|
||||
'piggy_bank_id' => $piggyBank->id,
|
||||
'transaction_journal_id' => $journal->id,
|
||||
'date' => $journal->date,
|
||||
'amount' => $amount
|
||||
]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,16 +1,18 @@
|
||||
<?php namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\JournalDeleted;
|
||||
use Illuminate\Contracts\Queue\ShouldBeQueued;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
|
||||
/**
|
||||
* Class JournalDeletedHandler
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class JournalDeletedHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* Create the event handler.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
53
app/Handlers/Events/RescanJournal.php
Normal file
53
app/Handlers/Events/RescanJournal.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use App;
|
||||
use FireflyIII\Events\JournalSaved;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class RescanJournal
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class RescanJournal
|
||||
{
|
||||
|
||||
/**
|
||||
* Create the event handler.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param JournalSaved $event
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(JournalSaved $event)
|
||||
{
|
||||
$journal = $event->journal;
|
||||
|
||||
Log::debug('Triggered saved event for journal #' . $journal->id . ' (' . $journal->description . ')');
|
||||
|
||||
/** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */
|
||||
$repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface');
|
||||
$list = $journal->user->bills()->where('active', 1)->where('automatch', 1)->get();
|
||||
|
||||
Log::debug('Found ' . $list->count() . ' bills to check.');
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($list as $bill) {
|
||||
Log::debug('Now calling bill #' . $bill->id . ' (' . $bill->name . ')');
|
||||
$repository->scan($bill, $journal);
|
||||
}
|
||||
|
||||
Log::debug('Done!');
|
||||
}
|
||||
|
||||
}
|
59
app/Handlers/Events/UpdateJournalConnection.php
Normal file
59
app/Handlers/Events/UpdateJournalConnection.php
Normal file
@@ -0,0 +1,59 @@
|
||||
<?php namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyIII\Events\JournalSaved;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Models\Transaction;
|
||||
|
||||
/**
|
||||
* Class UpdateJournalConnection
|
||||
*
|
||||
* @package FireflyIII\Handlers\Events
|
||||
*/
|
||||
class UpdateJournalConnection
|
||||
{
|
||||
|
||||
/**
|
||||
* Create the event handler.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the event.
|
||||
*
|
||||
* @param JournalSaved $event
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle(JournalSaved $event)
|
||||
{
|
||||
$journal = $event->journal;
|
||||
|
||||
// get the event connected to this journal:
|
||||
/** @var PiggyBankEvent $event */
|
||||
$event = PiggyBankEvent::where('transaction_journal_id', $journal->id)->first();
|
||||
if (is_null($event)) {
|
||||
return;
|
||||
}
|
||||
$piggyBank = $event->piggyBank()->first();
|
||||
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
|
||||
|
||||
if (is_null($repetition)) {
|
||||
return;
|
||||
}
|
||||
$amount = $journal->amount;
|
||||
$diff = $amount - $event->amount;// update current repetition
|
||||
|
||||
$repetition->currentamount += $diff;
|
||||
$repetition->save();
|
||||
|
||||
|
||||
$event->amount = $amount;
|
||||
$event->save();
|
||||
}
|
||||
|
||||
}
|
85
app/Helpers/Help/Help.php
Normal file
85
app/Helpers/Help/Help.php
Normal file
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Help;
|
||||
|
||||
use Cache;
|
||||
use ErrorException;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
use Log;
|
||||
use Route;
|
||||
|
||||
/**
|
||||
* Class Help
|
||||
*
|
||||
* @package FireflyIII\Helpers\Help
|
||||
*/
|
||||
class Help implements HelpInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFromCache($key)
|
||||
{
|
||||
return Cache::get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $route
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFromGithub($route)
|
||||
{
|
||||
$uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md';
|
||||
$content = [
|
||||
'text' => '<p>There is no help for this route!</p>',
|
||||
'title' => $route,
|
||||
];
|
||||
try {
|
||||
$content['text'] = file_get_contents($uri);
|
||||
} catch (ErrorException $e) {
|
||||
Log::error(trim($e->getMessage()));
|
||||
}
|
||||
if (strlen(trim($content['text'])) == 0) {
|
||||
$content['text'] = '<p>There is no help for this route.</p>';
|
||||
}
|
||||
$converter = new CommonMarkConverter();
|
||||
$content['text'] = $converter->convertToHtml($content['text']);
|
||||
|
||||
return $content;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasRoute($route)
|
||||
{
|
||||
return Route::has($route);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $title
|
||||
* @param array $content
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function putInCache($route, array $content)
|
||||
{
|
||||
Cache::put('help.' . $route . '.text', $content['text'], 10080); // a week.
|
||||
Cache::put('help.' . $route . '.title', $content['title'], 10080);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $route
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function inCache($route)
|
||||
{
|
||||
return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text');
|
||||
}
|
||||
}
|
46
app/Helpers/Help/HelpInterface.php
Normal file
46
app/Helpers/Help/HelpInterface.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Help;
|
||||
|
||||
/**
|
||||
* Interface HelpInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Help
|
||||
*/
|
||||
interface HelpInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFromCache($key);
|
||||
|
||||
/**
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasRoute($route);
|
||||
|
||||
/**
|
||||
* @param $route
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFromGithub($route);
|
||||
|
||||
/**
|
||||
* @param $route
|
||||
* @param array $content
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function putInCache($route, array $content);
|
||||
|
||||
/**
|
||||
* @param $route
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function inCache($route);
|
||||
}
|
145
app/Helpers/Reminders/ReminderHelper.php
Normal file
145
app/Helpers/Reminders/ReminderHelper.php
Normal file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Reminders;
|
||||
|
||||
use Amount;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use Navigation;
|
||||
|
||||
/**
|
||||
* Class ReminderHelper
|
||||
*
|
||||
* @package FireflyIII\Helpers\Reminders
|
||||
*/
|
||||
class ReminderHelper implements ReminderHelperInterface
|
||||
{
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Reminder
|
||||
*/
|
||||
public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end)
|
||||
{
|
||||
$reminder = Auth::user()->reminders()->where('remindersable_id', $piggyBank->id)->onDates($start, $end)->first();
|
||||
if (is_null($reminder)) {
|
||||
|
||||
if (!is_null($piggyBank->targetdate)) {
|
||||
// get ranges again, but now for the start date
|
||||
$ranges = $this->getReminderRanges($piggyBank, $start);
|
||||
$currentRep = $piggyBank->currentRelevantRep();
|
||||
$left = $piggyBank->targetamount - $currentRep->currentamount;
|
||||
$perReminder = $left / count($ranges);
|
||||
} else {
|
||||
$perReminder = null;
|
||||
$ranges = [];
|
||||
$left = 0;
|
||||
}
|
||||
$metaData = [
|
||||
'perReminder' => $perReminder,
|
||||
'rangesCount' => count($ranges),
|
||||
'ranges' => $ranges,
|
||||
'leftToSave' => $left,
|
||||
];
|
||||
|
||||
|
||||
// create one:
|
||||
$reminder = new Reminder;
|
||||
$reminder->user()->associate(Auth::user());
|
||||
$reminder->startdate = $start;
|
||||
$reminder->enddate = $end;
|
||||
$reminder->active = true;
|
||||
$reminder->metadata = $metaData;
|
||||
$reminder->notnow = false;
|
||||
$reminder->remindersable()->associate($piggyBank);
|
||||
$reminder->save();
|
||||
|
||||
return $reminder;
|
||||
|
||||
} else {
|
||||
return $reminder;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This routine will return an array consisting of two dates which indicate the start
|
||||
* and end date for each reminder that this piggy bank will have, if the piggy bank has
|
||||
* any reminders. For example:
|
||||
*
|
||||
* [12 mar - 15 mar]
|
||||
* [15 mar - 18 mar]
|
||||
*
|
||||
* etcetera.
|
||||
*
|
||||
* Array is filled with tiny arrays with Carbon objects in them.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param Carbon $date ;
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getReminderRanges(PiggyBank $piggyBank, Carbon $date = null)
|
||||
{
|
||||
$ranges = [];
|
||||
if (is_null($date)) {
|
||||
$date = new Carbon;
|
||||
}
|
||||
|
||||
if ($piggyBank->remind_me === false) {
|
||||
return $ranges;
|
||||
}
|
||||
|
||||
if (!is_null($piggyBank->targetdate)) {
|
||||
// count back until now.
|
||||
$start = $piggyBank->targetdate;
|
||||
$end = $piggyBank->startdate;
|
||||
|
||||
while ($start > $end) {
|
||||
$currentEnd = clone $start;
|
||||
$start = Navigation::subtractPeriod($start, $piggyBank->reminder, 1);
|
||||
$currentStart = clone $start;
|
||||
$ranges[] = ['start' => clone $currentStart, 'end' => clone $currentEnd];
|
||||
}
|
||||
} else {
|
||||
$start = clone $piggyBank->startdate;
|
||||
while ($start < $date) {
|
||||
$currentStart = clone $start;
|
||||
$start = Navigation::addPeriod($start, $piggyBank->reminder, 0);
|
||||
$currentEnd = clone $start;
|
||||
$ranges[] = ['start' => clone $currentStart, 'end' => clone $currentEnd];
|
||||
}
|
||||
}
|
||||
|
||||
return $ranges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a reminder, finds the piggy bank and tells you what to do now.
|
||||
* Aka how much money to put in.
|
||||
*
|
||||
*
|
||||
* @param Reminder $reminder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReminderText(Reminder $reminder)
|
||||
{
|
||||
/** @var PiggyBank $piggyBank */
|
||||
$piggyBank = $reminder->remindersable;
|
||||
|
||||
if (is_null($piggyBank)) {
|
||||
return 'Piggy bank no longer exists.';
|
||||
}
|
||||
|
||||
if (is_null($piggyBank->targetdate)) {
|
||||
return 'Add money to this piggy bank to reach your target of ' . Amount::format($piggyBank->targetamount);
|
||||
}
|
||||
|
||||
return 'Add ' . Amount::format($reminder->metadata->perReminder) . ' to fill this piggy bank on ' . $piggyBank->targetdate->format('jS F Y');
|
||||
|
||||
}
|
||||
}
|
52
app/Helpers/Reminders/ReminderHelperInterface.php
Normal file
52
app/Helpers/Reminders/ReminderHelperInterface.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Helpers\Reminders;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
|
||||
/**
|
||||
* Interface ReminderHelperInterface
|
||||
*
|
||||
* @package FireflyIII\Helpers\Reminders
|
||||
*/
|
||||
interface ReminderHelperInterface
|
||||
{
|
||||
/**
|
||||
* Takes a reminder, finds the piggy bank and tells you what to do now.
|
||||
* Aka how much money to put in.
|
||||
*
|
||||
* @param Reminder $reminder
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getReminderText(Reminder $reminder);
|
||||
|
||||
/**
|
||||
* This routine will return an array consisting of two dates which indicate the start
|
||||
* and end date for each reminder that this piggy bank will have, if the piggy bank has
|
||||
* any reminders. For example:
|
||||
*
|
||||
* [12 mar - 15 mar]
|
||||
* [15 mar - 18 mar]
|
||||
*
|
||||
* etcetera.
|
||||
*
|
||||
* Array is filled with tiny arrays with Carbon objects in them.
|
||||
*
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getReminderRanges(PiggyBank $piggyBank);
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Reminder
|
||||
*/
|
||||
public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end);
|
||||
}
|
@@ -2,11 +2,13 @@
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
* Class ReportHelper
|
||||
@@ -35,57 +37,47 @@ class ReportHelper implements ReportHelperInterface
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function firstDate()
|
||||
{
|
||||
$journal = Auth::user()->transactionjournals()->orderBy('date', 'ASC')->first();
|
||||
if ($journal) {
|
||||
return $journal->date;
|
||||
}
|
||||
|
||||
return Carbon::now();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method gets some kind of list for a monthly overview.
|
||||
*
|
||||
* @param Carbon $date
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBudgetsForMonth(Carbon $date)
|
||||
public function getBudgetsForMonth(Carbon $date, $showSharedReports = false)
|
||||
{
|
||||
/** @var \FireflyIII\Helpers\Report\ReportQueryInterface $query */
|
||||
$query = App::make('FireflyIII\Helpers\Report\ReportQueryInterface');
|
||||
|
||||
$start = clone $date;
|
||||
$start->startOfMonth();
|
||||
$end = clone $date;
|
||||
$end->endOfMonth();
|
||||
// all budgets
|
||||
$set = \Auth::user()->budgets()
|
||||
->leftJoin(
|
||||
'budget_limits', function (JoinClause $join) use ($date) {
|
||||
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
|
||||
}
|
||||
)
|
||||
->get(['budgets.*', 'budget_limits.amount as amount']);
|
||||
$set = Auth::user()->budgets()->orderBy('budgets.name', 'ASC')
|
||||
->leftJoin(
|
||||
'budget_limits', function (JoinClause $join) use ($date) {
|
||||
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
|
||||
}
|
||||
)
|
||||
->get(['budgets.*', 'budget_limits.amount as queryAmount']);
|
||||
|
||||
$budgets = Steam::makeArray($set);
|
||||
$amountSet = $query->journalsByBudget($start, $end, $showSharedReports);
|
||||
$amounts = Steam::makeArray($amountSet);
|
||||
$budgets = Steam::mergeArrays($budgets, $amounts);
|
||||
$budgets[0]['spent'] = isset($budgets[0]['spent']) ? $budgets[0]['spent'] : 0.0;
|
||||
$budgets[0]['queryAmount'] = isset($budgets[0]['queryAmount']) ? $budgets[0]['queryAmount'] : 0.0;
|
||||
$budgets[0]['name'] = 'No budget';
|
||||
|
||||
$budgets = $this->_helper->makeArray($set);
|
||||
$amountSet = $this->_queries->journalsByBudget($start, $end);
|
||||
$amounts = $this->_helper->makeArray($amountSet);
|
||||
$combined = $this->_helper->mergeArrays($budgets, $amounts);
|
||||
$combined[0]['spent'] = isset($combined[0]['spent']) ? $combined[0]['spent'] : 0.0;
|
||||
$combined[0]['amount'] = isset($combined[0]['amount']) ? $combined[0]['amount'] : 0.0;
|
||||
$combined[0]['name'] = 'No budget';
|
||||
|
||||
// find transactions to shared expense accounts, which are without a budget by default:
|
||||
$transfers = $this->_queries->sharedExpenses($start, $end);
|
||||
foreach ($transfers as $transfer) {
|
||||
$combined[0]['spent'] += floatval($transfer->amount) * -1;
|
||||
// find transactions to shared asset accounts, which are without a budget by default:
|
||||
// which is only relevant when shared asset accounts are hidden.
|
||||
if ($showSharedReports === false) {
|
||||
$transfers = $query->sharedExpenses($start, $end)->sum('queryAmount');
|
||||
$budgets[0]['spent'] += floatval($transfers) * -1;
|
||||
}
|
||||
|
||||
return $combined;
|
||||
return $budgets;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +91,8 @@ class ReportHelper implements ReportHelperInterface
|
||||
$end = Carbon::now();
|
||||
$months = [];
|
||||
while ($start <= $end) {
|
||||
$months[] = [
|
||||
$year = $start->format('Y');
|
||||
$months[$year][] = [
|
||||
'formatted' => $start->format('F Y'),
|
||||
'month' => intval($start->format('m')),
|
||||
'year' => intval($start->format('Y')),
|
||||
@@ -124,52 +117,62 @@ class ReportHelper implements ReportHelperInterface
|
||||
$years[] = $start->format('Y');
|
||||
$start->addYear();
|
||||
}
|
||||
$years[] = Carbon::now()->format('Y');
|
||||
// force the current year.
|
||||
$years = array_unique($years);
|
||||
|
||||
return $years;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearBalanceReport(Carbon $date)
|
||||
public function yearBalanceReport(Carbon $date, $showSharedReports = false)
|
||||
{
|
||||
$start = clone $date;
|
||||
$end = clone $date;
|
||||
$sharedAccounts = [];
|
||||
$sharedCollection = \Auth::user()->accounts()
|
||||
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
|
||||
->where('account_meta.name', '=', 'accountRole')
|
||||
->where('account_meta.data', '=', json_encode('sharedExpense'))
|
||||
->get(['accounts.id']);
|
||||
$start = clone $date;
|
||||
$end = clone $date;
|
||||
$sharedAccounts = [];
|
||||
if ($showSharedReports === false) {
|
||||
$sharedCollection = \Auth::user()->accounts()
|
||||
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
|
||||
->where('account_meta.name', '=', 'accountRole')
|
||||
->where('account_meta.data', '=', json_encode('sharedAsset'))
|
||||
->get(['accounts.id']);
|
||||
|
||||
foreach ($sharedCollection as $account) {
|
||||
$sharedAccounts[] = $account->id;
|
||||
foreach ($sharedCollection as $account) {
|
||||
$sharedAccounts[] = $account->id;
|
||||
}
|
||||
}
|
||||
|
||||
$accounts = \Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*'])->filter(
|
||||
function (Account $account) use ($sharedAccounts) {
|
||||
if (!in_array($account->id, $sharedAccounts)) {
|
||||
return $account;
|
||||
}
|
||||
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*'])
|
||||
->filter(
|
||||
function (Account $account) use ($sharedAccounts) {
|
||||
if (!in_array($account->id, $sharedAccounts)) {
|
||||
return $account;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
return null;
|
||||
}
|
||||
);
|
||||
$report = [];
|
||||
$start->startOfYear()->subDay();
|
||||
$end->endOfYear();
|
||||
|
||||
foreach ($accounts as $account) {
|
||||
$report[] = [
|
||||
'start' => \Steam::balance($account, $start),
|
||||
'end' => \Steam::balance($account, $end),
|
||||
$startBalance = Steam::balance($account, $start);
|
||||
$endBalance = Steam::balance($account, $end);
|
||||
$report[] = [
|
||||
'start' => $startBalance,
|
||||
'end' => $endBalance,
|
||||
'hide' => ($startBalance == 0 && $endBalance == 0),
|
||||
'account' => $account,
|
||||
'shared' => $account->accountRole == 'sharedExpense'
|
||||
'shared' => $account->accountRole == 'sharedAsset'
|
||||
];
|
||||
}
|
||||
|
||||
return $report;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,32 +14,6 @@ interface ReportHelperInterface
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function firstDate();
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listOfMonths(Carbon $date);
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listOfYears(Carbon $date);
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearBalanceReport(Carbon $date);
|
||||
|
||||
/**
|
||||
* This methods fails to take in account transfers FROM shared accounts.
|
||||
*
|
||||
@@ -59,4 +33,26 @@ interface ReportHelperInterface
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBudgetsForMonth(Carbon $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listOfMonths(Carbon $date);
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function listOfYears(Carbon $date);
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function yearBalanceReport(Carbon $date, $showSharedReports = false);
|
||||
}
|
||||
|
@@ -1,19 +1,15 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 22/02/15
|
||||
* Time: 18:30
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Helpers\Report;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Crypt;
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
use Steam;
|
||||
@@ -29,26 +25,33 @@ class ReportQuery implements ReportQueryInterface
|
||||
/**
|
||||
* This query retrieves a list of accounts that are active and not shared.
|
||||
*
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function accountList()
|
||||
public function accountList($showSharedReports = false)
|
||||
{
|
||||
return Auth::user()->accounts()
|
||||
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', "accountRole");
|
||||
}
|
||||
)
|
||||
->whereIn('account_types.type', ['Default account', 'Cash account', 'Asset account'])
|
||||
->where('active', 1)
|
||||
->where(
|
||||
function (Builder $query) {
|
||||
$query->where('account_meta.data', '!=', '"sharedExpense"');
|
||||
$query->orWhereNull('account_meta.data');
|
||||
}
|
||||
)
|
||||
->get(['accounts.*']);
|
||||
$query = Auth::user()->accounts();
|
||||
if ($showSharedReports === false) {
|
||||
|
||||
$query->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', "accountRole");
|
||||
}
|
||||
)->where(
|
||||
function (Builder $query) {
|
||||
$query->where('account_meta.data', '!=', '"sharedAsset"');
|
||||
$query->orWhereNull('account_meta.data');
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
$query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
|
||||
->whereIn('account_types.type', ['Default account', 'Cash account', 'Asset account'])
|
||||
->where('active', 1)
|
||||
->orderBy('accounts.name', 'ASC');
|
||||
|
||||
return $query->get(['accounts.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,22 +85,37 @@ class ReportQuery implements ReportQueryInterface
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'otherJournals.id')
|
||||
->before($end)->after($start)
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->where('transaction_journals.user_id', \Auth::user()->id)
|
||||
->where('transaction_journals.user_id', Auth::user()->id)
|
||||
->whereNull('budget_transaction_journal.budget_id')->whereNull('transaction_journals.deleted_at')
|
||||
->whereNull('otherJournals.deleted_at')
|
||||
->where('transactions.account_id', $account->id)
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->whereNotNull('transaction_group_transaction_journal.transaction_group_id')
|
||||
->first(
|
||||
->get(
|
||||
[
|
||||
DB::Raw('SUM(`transactions`.`amount`) as `amount`')
|
||||
'transaction_journals.*',
|
||||
'transactions.amount as queryAmount'
|
||||
]
|
||||
);
|
||||
$sum = 0;
|
||||
if (!is_null($set)) {
|
||||
$sum = floatval($set->amount);
|
||||
}
|
||||
|
||||
return $sum;
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will get the sum of all expenses in a certain time period that have no budget
|
||||
* and are balanced by a transfer to make up for it.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
return floatval($this->balancedTransactionsList($account, $start, $end)->sum('queryAmount'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,25 +123,31 @@ class ReportQuery implements ReportQueryInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAllAccounts(Carbon $start, Carbon $end)
|
||||
public function getAllAccounts(Carbon $start, Carbon $end, $showSharedReports = false)
|
||||
{
|
||||
$set = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')
|
||||
->accountTypeIn(['Default account', 'Asset account', 'Cash account'])
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->where(
|
||||
function (Builder $query) {
|
||||
$query->where('account_meta.data', '!=', '"sharedExpense"');
|
||||
$query->orWhereNull('account_meta.data');
|
||||
}
|
||||
)
|
||||
->get(['accounts.*']);
|
||||
$query = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')
|
||||
->accountTypeIn(['Default account', 'Asset account', 'Cash account']);
|
||||
if ($showSharedReports === false) {
|
||||
$query->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->orderBy('accounts.name', 'ASC')
|
||||
->where(
|
||||
function (Builder $query) {
|
||||
|
||||
$query->where('account_meta.data', '!=', '"sharedAsset"');
|
||||
$query->orWhereNull('account_meta.data');
|
||||
|
||||
}
|
||||
);
|
||||
}
|
||||
$set = $query->get(['accounts.*']);
|
||||
$set->each(
|
||||
function (Account $account) use ($start, $end) {
|
||||
/** @noinspection PhpParamsInspection */
|
||||
@@ -146,28 +170,27 @@ class ReportQuery implements ReportQueryInterface
|
||||
*/
|
||||
public function getBudgetSummary(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$set = TransactionJournal::
|
||||
leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->before($end)
|
||||
->after($start)
|
||||
->where('accounts.id', $account->id)
|
||||
->where('transaction_journals.user_id', Auth::user()->id)
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('budgets.id')
|
||||
->orderBy('budgets.name', 'ASC')
|
||||
->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `amount`')]);
|
||||
$query = $this->queryJournalsNoBudget($account, $start, $end);
|
||||
|
||||
return $set;
|
||||
return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `queryAmount`')]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of transaction journals that have no budget, filtered for the specified account
|
||||
* and the specified date range.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getTransactionsWithoutBudget(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$query = $this->queryJournalsNoBudget($account, $start, $end);
|
||||
|
||||
return $query->get(['budgets.name', 'transactions.amount as queryAmount', 'transaction_journals.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,62 +200,59 @@ class ReportQuery implements ReportQueryInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function incomeByPeriod(Carbon $start, Carbon $end)
|
||||
public function incomeByPeriod(Carbon $start, Carbon $end, $showSharedReports = false)
|
||||
{
|
||||
return TransactionJournal::
|
||||
leftJoin(
|
||||
'transactions as t_from', function (JoinClause $join) {
|
||||
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
|
||||
$query = $this->queryJournalsWithTransactions($start, $end);
|
||||
if ($showSharedReports === false) {
|
||||
// only get deposits not to a shared account
|
||||
// and transfers to a shared account.
|
||||
$query->where(
|
||||
function (Builder $query) {
|
||||
$query->where(
|
||||
function (Builder $q) {
|
||||
$q->where('transaction_types.type', 'Deposit');
|
||||
$q->where('acm_to.data', '!=', '"sharedAsset"');
|
||||
}
|
||||
);
|
||||
$query->orWhere(
|
||||
function (Builder $q) {
|
||||
$q->where('transaction_types.type', 'Transfer');
|
||||
$q->where('acm_from.data', '=', '"sharedAsset"');
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// any deposit is fine.
|
||||
$query->where('transaction_types.type', 'Deposit');
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')
|
||||
->leftJoin(
|
||||
'account_meta as acm_from', function (JoinClause $join) {
|
||||
$join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions as t_to', function (JoinClause $join) {
|
||||
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')
|
||||
->leftJoin(
|
||||
'account_meta as acm_to', function (JoinClause $join) {
|
||||
$join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->where(
|
||||
function ($query) {
|
||||
$query->where(
|
||||
function ($q) {
|
||||
$q->where('transaction_types.type', 'Deposit');
|
||||
$q->where('acm_to.data', '!=', '"sharedExpense"');
|
||||
}
|
||||
);
|
||||
$query->orWhere(
|
||||
function ($q) {
|
||||
$q->where('transaction_types.type', 'Transfer');
|
||||
$q->where('acm_from.data', '=', '"sharedExpense"');
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
->before($end)->after($start)
|
||||
->where('transaction_journals.user_id', Auth::user()->id)
|
||||
->groupBy('t_from.account_id')->orderBy('transaction_journals.date')
|
||||
->get(
|
||||
['transaction_journals.id',
|
||||
'transaction_journals.description',
|
||||
'transaction_journals.encrypted',
|
||||
'transaction_types.type',
|
||||
't_to.amount', 'transaction_journals.date', 't_from.account_id as account_id',
|
||||
'ac_from.name as name']
|
||||
);
|
||||
$query->groupBy('t_from.account_id')->orderBy('transaction_journals.date');
|
||||
|
||||
// get everything, decrypt and return
|
||||
$data = $query->get(
|
||||
['transaction_journals.id',
|
||||
'transaction_journals.description',
|
||||
'transaction_journals.encrypted',
|
||||
'transaction_types.type',
|
||||
DB::Raw('SUM(`t_to`.`amount`) as `queryAmount`'),
|
||||
'transaction_journals.date',
|
||||
't_from.account_id as account_id',
|
||||
'ac_from.name as name',
|
||||
'ac_from.encrypted as account_encrypted'
|
||||
]
|
||||
);
|
||||
|
||||
$data->each(
|
||||
function (Model $object) {
|
||||
$object->name = intval($object->account_encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
|
||||
}
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,33 +260,37 @@ class ReportQuery implements ReportQueryInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByBudget(Carbon $start, Carbon $end)
|
||||
public function journalsByBudget(Carbon $start, Carbon $end, $showSharedReports = false)
|
||||
{
|
||||
return Auth::user()->transactionjournals()
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('account_meta.data', '!=', '"sharedExpense"')
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('budgets.id')
|
||||
->orderBy('budgets.name', 'ASC')
|
||||
->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) AS `spent`')]);
|
||||
$query = Auth::user()->transactionjournals()
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id');
|
||||
if ($showSharedReports === false) {
|
||||
|
||||
$query->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)->where('account_meta.data', '!=', '"sharedAsset"');
|
||||
}
|
||||
$query->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('budgets.id')
|
||||
->orderBy('budgets.name', 'ASC');
|
||||
|
||||
return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) AS `spent`')]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,35 +299,46 @@ class ReportQuery implements ReportQueryInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByCategory(Carbon $start, Carbon $end)
|
||||
public function journalsByCategory(Carbon $start, Carbon $end, $showSharedReports = false)
|
||||
{
|
||||
return Auth::user()->transactionjournals()
|
||||
->leftJoin(
|
||||
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)
|
||||
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('account_meta.data', '!=', '"sharedExpense"')
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('categories.id')
|
||||
->orderBy('amount')
|
||||
->get(['categories.id', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `amount`')]);
|
||||
$query = Auth::user()->transactionjournals()
|
||||
->leftJoin(
|
||||
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)
|
||||
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id');
|
||||
if ($showSharedReports === false) {
|
||||
$query->leftJoin(
|
||||
'account_meta', function (JoinClause $join) {
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)->where('account_meta.data', '!=', '"sharedAsset"');
|
||||
}
|
||||
$query->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('categories.id')
|
||||
->orderBy('queryAmount');
|
||||
|
||||
$data = $query->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `queryAmount`')]);
|
||||
// decrypt data:
|
||||
$data->each(
|
||||
function (Model $object) {
|
||||
$object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
|
||||
}
|
||||
);
|
||||
|
||||
return $data;
|
||||
|
||||
}
|
||||
|
||||
@@ -315,57 +350,51 @@ class ReportQuery implements ReportQueryInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByExpenseAccount(Carbon $start, Carbon $end)
|
||||
public function journalsByExpenseAccount(Carbon $start, Carbon $end, $showSharedReports = false)
|
||||
{
|
||||
return TransactionJournal::
|
||||
leftJoin(
|
||||
'transactions as t_from', function (JoinClause $join) {
|
||||
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
|
||||
$query = $this->queryJournalsWithTransactions($start, $end);
|
||||
if ($showSharedReports === false) {
|
||||
// get all withdrawals not from a shared accounts
|
||||
// and all transfers to a shared account
|
||||
$query->where(
|
||||
function (Builder $query) {
|
||||
$query->where(
|
||||
function (Builder $q) {
|
||||
$q->where('transaction_types.type', 'Withdrawal');
|
||||
$q->where('acm_from.data', '!=', '"sharedAsset"');
|
||||
}
|
||||
);
|
||||
$query->orWhere(
|
||||
function (Builder $q) {
|
||||
$q->where('transaction_types.type', 'Transfer');
|
||||
$q->where('acm_to.data', '=', '"sharedAsset"');
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// any withdrawal goes:
|
||||
$query->where('transaction_types.type', 'Withdrawal');
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')
|
||||
->leftJoin(
|
||||
'account_meta as acm_from', function (JoinClause $join) {
|
||||
$join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions as t_to', function (JoinClause $join) {
|
||||
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')
|
||||
->leftJoin(
|
||||
'account_meta as acm_to', function (JoinClause $join) {
|
||||
$join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->where(
|
||||
function ($query) {
|
||||
$query->where(
|
||||
function ($q) {
|
||||
$q->where('transaction_types.type', 'Withdrawal');
|
||||
$q->where('acm_from.data', '!=', '"sharedExpense"');
|
||||
}
|
||||
);
|
||||
$query->orWhere(
|
||||
function ($q) {
|
||||
$q->where('transaction_types.type', 'Transfer');
|
||||
$q->where('acm_to.data', '=', '"sharedExpense"');
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
->before($end)
|
||||
->after($start)
|
||||
->where('transaction_journals.user_id', Auth::user()->id)
|
||||
->groupBy('t_to.account_id')
|
||||
->orderBy('amount', 'DESC')
|
||||
->get(['t_to.account_id as id', 'ac_to.name as name', DB::Raw('SUM(t_to.amount) as `amount`')]);
|
||||
$query->before($end)->after($start)
|
||||
->where('transaction_journals.user_id', Auth::user()->id)
|
||||
->groupBy('t_to.account_id')
|
||||
->orderBy('queryAmount', 'DESC');
|
||||
|
||||
$data = $query->get(['t_to.account_id as id', 'ac_to.name as name', 'ac_to.encrypted', DB::Raw('SUM(t_to.amount) as `queryAmount`')]);
|
||||
|
||||
// decrypt
|
||||
$data->each(
|
||||
function (Model $object) {
|
||||
$object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
|
||||
}
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -373,55 +402,51 @@ class ReportQuery implements ReportQueryInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByRevenueAccount(Carbon $start, Carbon $end)
|
||||
public function journalsByRevenueAccount(Carbon $start, Carbon $end, $showSharedReports = false)
|
||||
{
|
||||
return TransactionJournal::
|
||||
leftJoin(
|
||||
'transactions as t_from', function (JoinClause $join) {
|
||||
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
|
||||
$query = $this->queryJournalsWithTransactions($start, $end);
|
||||
if ($showSharedReports === false) {
|
||||
|
||||
// show queries where transfer type is deposit, and its not to a shared account
|
||||
// or where its a transfer and its from a shared account (both count as incomes)
|
||||
$query->where(
|
||||
function (Builder $query) {
|
||||
$query->where(
|
||||
function (Builder $q) {
|
||||
$q->where('transaction_types.type', 'Deposit');
|
||||
$q->where('acm_to.data', '!=', '"sharedAsset"');
|
||||
}
|
||||
);
|
||||
$query->orWhere(
|
||||
function (Builder $q) {
|
||||
$q->where('transaction_types.type', 'Transfer');
|
||||
$q->where('acm_from.data', '=', '"sharedAsset"');
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// any deposit goes:
|
||||
$query->where('transaction_types.type', 'Deposit');
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')
|
||||
->leftJoin(
|
||||
'account_meta as acm_from', function (JoinClause $join) {
|
||||
$join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions as t_to', function (JoinClause $join) {
|
||||
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')
|
||||
->leftJoin(
|
||||
'account_meta as acm_to', function (JoinClause $join) {
|
||||
$join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->where(
|
||||
function ($query) {
|
||||
$query->where(
|
||||
function ($q) {
|
||||
$q->where('transaction_types.type', 'Deposit');
|
||||
$q->where('acm_to.data', '!=', '"sharedExpense"');
|
||||
}
|
||||
);
|
||||
$query->orWhere(
|
||||
function ($q) {
|
||||
$q->where('transaction_types.type', 'Transfer');
|
||||
$q->where('acm_from.data', '=', '"sharedExpense"');
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
->before($end)->after($start)
|
||||
->where('transaction_journals.user_id', Auth::user()->id)
|
||||
->groupBy('t_from.account_id')->orderBy('amount')
|
||||
->get(['t_from.account_id as account_id', 'ac_from.name as name', DB::Raw('SUM(t_from.amount) as `amount`')]);
|
||||
|
||||
$query->groupBy('t_from.account_id')->orderBy('queryAmount');
|
||||
|
||||
$data = $query->get(
|
||||
['t_from.account_id as account_id', 'ac_from.name as name', 'ac_from.encrypted as encrypted', DB::Raw('SUM(t_from.amount) as `queryAmount`')]
|
||||
);
|
||||
// decrypt
|
||||
$data->each(
|
||||
function (Model $object) {
|
||||
$object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
|
||||
}
|
||||
);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -450,14 +475,14 @@ class ReportQuery implements ReportQueryInterface
|
||||
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->where('account_meta.data', '"sharedExpense"')
|
||||
->where('account_meta.data', '"sharedAsset"')
|
||||
->after($start)
|
||||
->before($end)
|
||||
->where('transaction_types.type', 'Transfer')
|
||||
->where('transaction_journals.user_id', Auth::user()->id)
|
||||
->get(
|
||||
['transaction_journals.id', 'transaction_journals.description', 'transactions.account_id', 'accounts.name',
|
||||
'transactions.amount']
|
||||
'transactions.amount as queryAmount']
|
||||
);
|
||||
|
||||
}
|
||||
@@ -492,7 +517,7 @@ class ReportQuery implements ReportQueryInterface
|
||||
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)
|
||||
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
|
||||
->where('account_meta.data', '"sharedExpense"')
|
||||
->where('account_meta.data', '"sharedAsset"')
|
||||
->after($start)
|
||||
->before($end)
|
||||
->where('transaction_types.type', 'Transfer')
|
||||
@@ -502,9 +527,79 @@ class ReportQuery implements ReportQueryInterface
|
||||
[
|
||||
'categories.id',
|
||||
'categories.name as name',
|
||||
DB::Raw('SUM(`transactions`.`amount`) * -1 AS `amount`')
|
||||
DB::Raw('SUM(`transactions`.`amount`) * -1 AS `queryAmount`')
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
*
|
||||
* This query will get all transaction journals and budget information for a specified account
|
||||
* in a certain date range, where the transaction journal does not have a budget.
|
||||
* There is no get() specified, this is up to the method itself.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
protected function queryJournalsNoBudget(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
return TransactionJournal::
|
||||
leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
|
||||
->before($end)
|
||||
->after($start)
|
||||
->where('accounts.id', $account->id)
|
||||
->where('transaction_journals.user_id', Auth::user()->id)
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('budgets.id')
|
||||
->orderBy('budgets.name', 'ASC');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Builder
|
||||
*/
|
||||
protected function queryJournalsWithTransactions(Carbon $start, Carbon $end)
|
||||
{
|
||||
$query = TransactionJournal::
|
||||
leftJoin(
|
||||
'transactions as t_from', function (JoinClause $join) {
|
||||
$join->on('t_from.transaction_journal_id', '=', 'transaction_journals.id')->where('t_from.amount', '<', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts as ac_from', 't_from.account_id', '=', 'ac_from.id')
|
||||
->leftJoin(
|
||||
'account_meta as acm_from', function (JoinClause $join) {
|
||||
$join->on('ac_from.id', '=', 'acm_from.account_id')->where('acm_from.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions as t_to', function (JoinClause $join) {
|
||||
$join->on('t_to.transaction_journal_id', '=', 'transaction_journals.id')->where('t_to.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin('accounts as ac_to', 't_to.account_id', '=', 'ac_to.id')
|
||||
->leftJoin(
|
||||
'account_meta as acm_to', function (JoinClause $join) {
|
||||
$join->on('ac_to.id', '=', 'acm_to.account_id')->where('acm_to.name', '=', 'accountRole');
|
||||
}
|
||||
)
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id');
|
||||
$query->before($end)->after($start)->where('transaction_journals.user_id', Auth::user()->id);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -17,19 +17,69 @@ interface ReportQueryInterface
|
||||
/**
|
||||
* This query retrieves a list of accounts that are active and not shared.
|
||||
*
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function accountList();
|
||||
public function accountList($showSharedReports = false);
|
||||
|
||||
/**
|
||||
* This method will get a list of all expenses in a certain time period that have no budget
|
||||
* and are balanced by a transfer to make up for it.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* This method will get the sum of all expenses in a certain time period that have no budget
|
||||
* and are balanced by a transfer to make up for it.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* Get a users accounts combined with various meta-data related to the start and end date.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAllAccounts(Carbon $start, Carbon $end);
|
||||
public function getAllAccounts(Carbon $start, Carbon $end, $showSharedReports = false);
|
||||
|
||||
/**
|
||||
* Grabs a summary of all expenses grouped by budget, related to the account.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBudgetSummary(Account $account, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* Get a list of transaction journals that have no budget, filtered for the specified account
|
||||
* and the specified date range.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getTransactionsWithoutBudget(Account $account, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* This method returns all "income" journals in a certain period, which are both transfers from a shared account
|
||||
@@ -38,20 +88,22 @@ interface ReportQueryInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function incomeByPeriod(Carbon $start, Carbon $end);
|
||||
public function incomeByPeriod(Carbon $start, Carbon $end, $showSharedReports = false);
|
||||
|
||||
/**
|
||||
* Gets a list of expenses grouped by the budget they were filed under.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByBudget(Carbon $start, Carbon $end);
|
||||
public function journalsByBudget(Carbon $start, Carbon $end, $showSharedReports = false);
|
||||
|
||||
/**
|
||||
* Gets a list of categories and the expenses therein, grouped by the relevant category.
|
||||
@@ -59,10 +111,11 @@ interface ReportQueryInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByCategory(Carbon $start, Carbon $end);
|
||||
public function journalsByCategory(Carbon $start, Carbon $end, $showSharedReports = false);
|
||||
|
||||
/**
|
||||
* Gets a list of expense accounts and the expenses therein, grouped by that expense account.
|
||||
@@ -72,20 +125,22 @@ interface ReportQueryInterface
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByExpenseAccount(Carbon $start, Carbon $end);
|
||||
public function journalsByExpenseAccount(Carbon $start, Carbon $end, $showSharedReports = false);
|
||||
|
||||
/**
|
||||
* This method returns all deposits into asset accounts, grouped by the revenue account,
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
* @param bool $showSharedReports
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function journalsByRevenueAccount(Carbon $start, Carbon $end);
|
||||
public function journalsByRevenueAccount(Carbon $start, Carbon $end, $showSharedReports = false);
|
||||
|
||||
/**
|
||||
* With an equally misleading name, this query returns are transfers to shared accounts. These are considered
|
||||
@@ -108,27 +163,4 @@ interface ReportQueryInterface
|
||||
* @return Collection
|
||||
*/
|
||||
public function sharedExpensesByCategory(Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* Grabs a summary of all expenses grouped by budget, related to the account.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBudgetSummary(Account $account, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* This method will get a list of all expenses in a certain time period that have no budget
|
||||
* and are balanced by a transfer to make up for it.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end);
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,5 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
@@ -11,6 +10,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Input;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use Steam;
|
||||
use View;
|
||||
|
||||
/**
|
||||
@@ -36,7 +36,7 @@ class AccountController extends Controller
|
||||
*/
|
||||
public function create($what = 'asset')
|
||||
{
|
||||
$subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $what);
|
||||
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
|
||||
$subTitle = 'Create a new ' . e($what) . ' account';
|
||||
|
||||
return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle'));
|
||||
@@ -74,8 +74,15 @@ class AccountController extends Controller
|
||||
return Redirect::route('accounts.index', $typeName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function edit(Account $account, AccountRepositoryInterface $repository)
|
||||
{
|
||||
|
||||
$what = Config::get('firefly.shortNamesByFullName')[$account->accountType->type];
|
||||
$subTitle = 'Edit ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
|
||||
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
|
||||
@@ -85,15 +92,19 @@ class AccountController extends Controller
|
||||
|
||||
// the opening balance is tricky:
|
||||
$openingBalanceAmount = null;
|
||||
|
||||
if ($openingBalance) {
|
||||
$transaction = $openingBalance->transactions()->where('account_id', $account->id)->first();
|
||||
$transaction = $repository->getFirstTransaction($openingBalance, $account);
|
||||
$openingBalanceAmount = $transaction->amount;
|
||||
}
|
||||
|
||||
$preFilled = [
|
||||
'accountRole' => $account->getMeta('accountRole'),
|
||||
'openingBalanceDate' => $openingBalance ? $openingBalance->date->format('Y-m-d') : null,
|
||||
'openingBalance' => $openingBalanceAmount
|
||||
'accountRole' => $account->getMeta('accountRole'),
|
||||
'ccType' => $account->getMeta('ccType'),
|
||||
'ccMonthlyPaymentDate' => $account->getMeta('ccMonthlyPaymentDate'),
|
||||
'openingBalanceDate' => $openingBalance ? $openingBalance->date->format('Y-m-d') : null,
|
||||
'openingBalance' => $openingBalanceAmount,
|
||||
'virtualBalance' => floatval($account->virtual_balance)
|
||||
];
|
||||
Session::flash('preFilled', $preFilled);
|
||||
|
||||
@@ -101,38 +112,51 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $what
|
||||
* @param $what
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index($what = 'default')
|
||||
public function index($what, AccountRepositoryInterface $repository)
|
||||
{
|
||||
$subTitle = Config::get('firefly.subTitlesByIdentifier.' . $what);
|
||||
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
|
||||
$types = Config::get('firefly.accountTypesByIdentifier.' . $what);
|
||||
$accounts = Auth::user()->accounts()->accountTypeIn($types)->get(['accounts.*']);
|
||||
$accounts = $repository->getAccounts($types);
|
||||
// last activity:
|
||||
/**
|
||||
* HERE WE ARE
|
||||
*/
|
||||
$start = clone Session::get('start', Carbon::now()->startOfMonth());
|
||||
$start->subDay();
|
||||
$accounts->each(
|
||||
function (Account $account) use ($start, $repository) {
|
||||
$account->lastActivityDate = $repository->getLastActivity($account);
|
||||
$account->startBalance = Steam::balance($account, $start);
|
||||
$account->endBalance = Steam::balance($account, clone Session::get('end', Carbon::now()->endOfMonth()));
|
||||
}
|
||||
);
|
||||
|
||||
return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param string $range
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
* @return View
|
||||
*/
|
||||
public function show(Account $account, $range = 'session')
|
||||
public function show(Account $account, AccountRepositoryInterface $repository)
|
||||
{
|
||||
/** @var \FireflyIII\Repositories\Account\AccountRepositoryInterface $repository */
|
||||
$repository = App::make('FireflyIII\Repositories\Account\AccountRepositoryInterface');
|
||||
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
|
||||
$subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type);
|
||||
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
|
||||
$journals = $repository->getJournals($account, $page, $range);
|
||||
$journals = $repository->getJournals($account, $page);
|
||||
$subTitle = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
|
||||
$journals->setPath('accounts/show/' . $account->id);
|
||||
|
||||
return view('accounts.show', compact('account', 'what', 'range', 'subTitleIcon', 'journals', 'subTitle'));
|
||||
|
||||
return view('accounts.show', compact('account', 'what', 'subTitleIcon', 'journals', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,6 +170,7 @@ class AccountController extends Controller
|
||||
$accountData = [
|
||||
'name' => $request->input('name'),
|
||||
'accountType' => $request->input('what'),
|
||||
'virtualBalance' => floatval($request->input('virtualBalance')),
|
||||
'active' => true,
|
||||
'user' => Auth::user()->id,
|
||||
'accountRole' => $request->input('accountRole'),
|
||||
@@ -158,6 +183,10 @@ class AccountController extends Controller
|
||||
|
||||
Session::flash('success', 'New account "' . $account->name . '" stored!');
|
||||
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
return Redirect::route('accounts.create', $request->input('what'))->withInput();
|
||||
}
|
||||
|
||||
return Redirect::route('accounts.index', $request->input('what'));
|
||||
|
||||
}
|
||||
@@ -177,15 +206,22 @@ class AccountController extends Controller
|
||||
'active' => $request->input('active'),
|
||||
'user' => Auth::user()->id,
|
||||
'accountRole' => $request->input('accountRole'),
|
||||
'virtualBalance' => floatval($request->input('virtualBalance')),
|
||||
'openingBalance' => floatval($request->input('openingBalance')),
|
||||
'openingBalanceDate' => new Carbon($request->input('openingBalanceDate')),
|
||||
'openingBalanceCurrency' => intval($request->input('balance_currency_id')),
|
||||
'ccType' => $request->input('ccType'),
|
||||
'ccMonthlyPaymentDate' => $request->input('ccMonthlyPaymentDate'),
|
||||
];
|
||||
|
||||
$repository->update($account, $accountData);
|
||||
|
||||
Session::flash('success', 'Account "' . $account->name . '" updated.');
|
||||
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
return Redirect::route('accounts.edit', $account->id);
|
||||
}
|
||||
|
||||
return Redirect::route('accounts.index', $what);
|
||||
|
||||
}
|
||||
|
@@ -4,6 +4,10 @@ use FireflyIII\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Contracts\Auth\Registrar;
|
||||
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Mail\Message;
|
||||
use Mail;
|
||||
use Session;
|
||||
|
||||
/**
|
||||
* Class AuthController
|
||||
@@ -43,4 +47,45 @@ class AuthController extends Controller
|
||||
$this->middleware('guest', ['except' => 'getLogout']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a registration request for the application.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function postRegister(Request $request)
|
||||
{
|
||||
$validator = $this->registrar->validator($request->all());
|
||||
|
||||
if ($validator->fails()) {
|
||||
$this->throwValidationException(
|
||||
$request, $validator
|
||||
);
|
||||
}
|
||||
|
||||
$data = $request->all();
|
||||
$data['password'] = bcrypt($data['password']);
|
||||
|
||||
$this->auth->login($this->registrar->create($data));
|
||||
|
||||
// get the email address
|
||||
$email = $this->auth->user()->email;
|
||||
|
||||
// send email.
|
||||
Mail::send(
|
||||
'emails.registered', [], function (Message $message) use ($email) {
|
||||
$message->to($email, $email)->subject('Welcome to Firefly III!');
|
||||
}
|
||||
);
|
||||
|
||||
// set flash message
|
||||
Session::flash('success', 'You have registered successfully!');
|
||||
Session::flash('gaEventCategory', 'user');
|
||||
Session::flash('gaEventAction', 'new-registration');
|
||||
|
||||
|
||||
return redirect($this->redirectPath());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,13 +1,16 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Requests\BillFormRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use Input;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use URL;
|
||||
@@ -21,18 +24,64 @@ use View;
|
||||
class BillController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
View::share('title', 'Bills');
|
||||
View::share('mainTitleIcon', 'fa-calendar-o');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function add(Bill $bill, AccountRepositoryInterface $repository)
|
||||
{
|
||||
$matches = explode(',', $bill->match);
|
||||
$description = [];
|
||||
$expense = null;
|
||||
|
||||
// get users expense accounts:
|
||||
$accounts = $repository->getAccounts(Config::get('firefly.accountTypesByIdentifier.expense'));
|
||||
|
||||
foreach ($matches as $match) {
|
||||
$match = strtolower($match);
|
||||
// find expense account for each word if not found already:
|
||||
if (is_null($expense)) {
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
$name = strtolower($account->name);
|
||||
if (!(strpos($name, $match) === false)) {
|
||||
$expense = $account;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if (is_null($expense)) {
|
||||
$description[] = $match;
|
||||
}
|
||||
}
|
||||
$parameters = [
|
||||
'description' => ucfirst(join(' ', $description)),
|
||||
'expense_account' => is_null($expense) ? '' : $expense->name,
|
||||
'amount' => round(($bill->amount_min + $bill->amount_max), 2),
|
||||
];
|
||||
Session::put('preFilled', $parameters);
|
||||
|
||||
return Redirect::to(route('transactions.create', 'withdrawal'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$periods = \Config::get('firefly.periods_to_text');
|
||||
$periods = Config::get('firefly.periods_to_text');
|
||||
|
||||
return view('bills.create')->with('periods', $periods)->with('subTitle', 'Create new');
|
||||
}
|
||||
@@ -52,9 +101,10 @@ class BillController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(Bill $bill)
|
||||
public function destroy(Bill $bill, BillRepositoryInterface $repository)
|
||||
{
|
||||
$bill->delete();
|
||||
$repository->destroy($bill);
|
||||
|
||||
Session::flash('success', 'The bill was deleted.');
|
||||
|
||||
return Redirect::route('bills.index');
|
||||
@@ -68,7 +118,7 @@ class BillController extends Controller
|
||||
*/
|
||||
public function edit(Bill $bill)
|
||||
{
|
||||
$periods = \Config::get('firefly.periods_to_text');
|
||||
$periods = Config::get('firefly.periods_to_text');
|
||||
|
||||
return view('bills.edit')->with('periods', $periods)->with('bill', $bill)->with('subTitle', 'Edit "' . e($bill->name) . '"');
|
||||
}
|
||||
@@ -80,15 +130,11 @@ class BillController extends Controller
|
||||
*/
|
||||
public function index(BillRepositoryInterface $repository)
|
||||
{
|
||||
$bills = Auth::user()->bills()->get();
|
||||
$bills = $repository->getBills();
|
||||
$bills->each(
|
||||
function (Bill $bill) use ($repository) {
|
||||
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill);
|
||||
$last = $bill->transactionjournals()->orderBy('date', 'DESC')->first();
|
||||
$bill->lastFoundMatch = null;
|
||||
if ($last) {
|
||||
$bill->lastFoundMatch = $last->date;
|
||||
}
|
||||
$bill->lastFoundMatch = $repository->lastFoundMatch($bill);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -105,23 +151,15 @@ class BillController extends Controller
|
||||
if (intval($bill->active) == 0) {
|
||||
Session::flash('warning', 'Inactive bills cannot be scanned.');
|
||||
|
||||
return Redirect::intended('/');
|
||||
return Redirect::to(URL::previous());
|
||||
}
|
||||
|
||||
$set = \DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max)->get(['transaction_journal_id']);
|
||||
$ids = [];
|
||||
$journals = $repository->getPossiblyRelatedJournals($bill);
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$repository->scan($bill, $journal);
|
||||
}
|
||||
|
||||
/** @var Transaction $entry */
|
||||
foreach ($set as $entry) {
|
||||
$ids[] = intval($entry->transaction_journal_id);
|
||||
}
|
||||
if (count($ids) > 0) {
|
||||
$journals = Auth::user()->transactionjournals()->whereIn('id',$ids)->get();
|
||||
/** @var TransactionJournal $journal */
|
||||
foreach ($journals as $journal) {
|
||||
$repository->scan($bill, $journal);
|
||||
}
|
||||
}
|
||||
|
||||
Session::flash('success', 'Rescanned everything.');
|
||||
|
||||
@@ -135,11 +173,10 @@ class BillController extends Controller
|
||||
*/
|
||||
public function show(Bill $bill, BillRepositoryInterface $repository)
|
||||
{
|
||||
$journals = $bill->transactionjournals()->withRelevantData()->orderBy('date', 'DESC')->get();
|
||||
$journals = $repository->getJournals($bill);
|
||||
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill);
|
||||
$hideBill = true;
|
||||
|
||||
|
||||
return view('bills.show', compact('journals', 'hideBill', 'bill'))->with('subTitle', e($bill->name));
|
||||
}
|
||||
|
||||
@@ -148,26 +185,14 @@ class BillController extends Controller
|
||||
*/
|
||||
public function store(BillFormRequest $request, BillRepositoryInterface $repository)
|
||||
{
|
||||
|
||||
var_dump($request->all());
|
||||
|
||||
$billData = [
|
||||
'name' => $request->get('name'),
|
||||
'match' => $request->get('match'),
|
||||
'amount_min' => floatval($request->get('amount_min')),
|
||||
'amount_currency_id' => floatval($request->get('amount_currency_id')),
|
||||
'amount_max' => floatval($request->get('amount_max')),
|
||||
'date' => new Carbon($request->get('date')),
|
||||
'user' => Auth::user()->id,
|
||||
'repeat_freq' => $request->get('repeat_freq'),
|
||||
'skip' => intval($request->get('skip')),
|
||||
'automatch' => intval($request->get('automatch')) === 1,
|
||||
'active' => intval($request->get('active')) === 1,
|
||||
];
|
||||
|
||||
$bill = $repository->store($billData);
|
||||
$billData = $request->getBillData();
|
||||
$bill = $repository->store($billData);
|
||||
Session::flash('success', 'Bill "' . e($bill->name) . '" stored.');
|
||||
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
return Redirect::route('bills.create')->withInput();
|
||||
}
|
||||
|
||||
return Redirect::route('bills.index');
|
||||
|
||||
}
|
||||
@@ -179,62 +204,17 @@ class BillController extends Controller
|
||||
*/
|
||||
public function update(Bill $bill, BillFormRequest $request, BillRepositoryInterface $repository)
|
||||
{
|
||||
$billData = [
|
||||
'name' => $request->get('name'),
|
||||
'match' => $request->get('match'),
|
||||
'amount_min' => floatval($request->get('amount_min')),
|
||||
'amount_currency_id' => floatval($request->get('amount_currency_id')),
|
||||
'amount_max' => floatval($request->get('amount_max')),
|
||||
'date' => new Carbon($request->get('date')),
|
||||
'user' => Auth::user()->id,
|
||||
'repeat_freq' => $request->get('repeat_freq'),
|
||||
'skip' => intval($request->get('skip')),
|
||||
'automatch' => intval($request->get('automatch')) === 1,
|
||||
'active' => intval($request->get('active')) === 1,
|
||||
];
|
||||
$billData = $request->getBillData();
|
||||
$bill = $repository->update($bill, $billData);
|
||||
|
||||
$bill = $repository->update($bill, $billData);
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
return Redirect::route('bills.edit', $bill->id);
|
||||
}
|
||||
|
||||
Session::flash('success', 'Bill "' . e($bill->name) . '" updated.');
|
||||
|
||||
return Redirect::route('bills.index');
|
||||
|
||||
|
||||
// $data = Input::except('_token');
|
||||
// $data['active'] = intval(Input::get('active'));
|
||||
// $data['automatch'] = intval(Input::get('automatch'));
|
||||
// $data['user_id'] = Auth::user()->id;
|
||||
//
|
||||
// // always validate:
|
||||
// $messages = $this->_repository->validate($data);
|
||||
//
|
||||
// // flash messages:
|
||||
// Session::flash('warnings', $messages['warnings']);
|
||||
// Session::flash('successes', $messages['successes']);
|
||||
// Session::flash('errors', $messages['errors']);
|
||||
// if ($messages['errors']->count() > 0) {
|
||||
// Session::flash('error', 'Could not update bill: ' . $messages['errors']->first());
|
||||
//
|
||||
// return Redirect::route('bills.edit', $bill->id)->withInput();
|
||||
// }
|
||||
//
|
||||
// // return to update screen:
|
||||
// if ($data['post_submit_action'] == 'validate_only') {
|
||||
// return Redirect::route('bills.edit', $bill->id)->withInput();
|
||||
// }
|
||||
//
|
||||
// // update
|
||||
// $this->_repository->update($bill, $data);
|
||||
// Session::flash('success', 'Bill "' . e($data['name']) . '" updated.');
|
||||
//
|
||||
// // go back to list
|
||||
// if ($data['post_submit_action'] == 'update') {
|
||||
// return Redirect::route('bills.index');
|
||||
// }
|
||||
//
|
||||
// // go back to update screen.
|
||||
// return Redirect::route('bills.edit', $bill->id)->withInput(['post_submit_action' => 'return_to_edit']);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ use Carbon\Carbon;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Requests\BudgetFormRequest;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use Input;
|
||||
@@ -12,6 +13,7 @@ use Preferences;
|
||||
use Redirect;
|
||||
use Response;
|
||||
use Session;
|
||||
use URL;
|
||||
use View;
|
||||
|
||||
/**
|
||||
@@ -22,6 +24,9 @@ use View;
|
||||
class BudgetController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
View::share('title', 'Budgets');
|
||||
@@ -32,7 +37,6 @@ class BudgetController extends Controller
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws Exception
|
||||
*/
|
||||
public function amount(Budget $budget, BudgetRepositoryInterface $repository)
|
||||
{
|
||||
@@ -49,6 +53,12 @@ class BudgetController extends Controller
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (Session::get('budgets.create.fromStore') !== true) {
|
||||
Session::put('budgets.create.url', URL::previous());
|
||||
}
|
||||
Session::forget('budgets.create.fromStore');
|
||||
|
||||
return view('budgets.create')->with('subTitle', 'Create a new budget');
|
||||
}
|
||||
|
||||
@@ -61,6 +71,9 @@ class BudgetController extends Controller
|
||||
{
|
||||
$subTitle = 'Delete budget' . e($budget->name) . '"';
|
||||
|
||||
// put previous url in session
|
||||
Session::put('budgets.delete.url', URL::previous());
|
||||
|
||||
return view('budgets.delete', compact('budget', 'subTitle'));
|
||||
}
|
||||
|
||||
@@ -75,9 +88,10 @@ class BudgetController extends Controller
|
||||
$name = $budget->name;
|
||||
$repository->destroy($budget);
|
||||
|
||||
|
||||
Session::flash('success', 'The budget "' . e($name) . '" was deleted.');
|
||||
|
||||
return Redirect::route('budgets.index');
|
||||
return Redirect::to(Session::get('budgets.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,6 +103,12 @@ class BudgetController extends Controller
|
||||
{
|
||||
$subTitle = 'Edit budget "' . e($budget->name) . '"';
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (Session::get('budgets.edit.fromUpdate') !== true) {
|
||||
Session::put('budgets.edit.url', URL::previous());
|
||||
}
|
||||
Session::forget('budgets.edit.fromUpdate');
|
||||
|
||||
return view('budgets.edit', compact('budget', 'subTitle'));
|
||||
|
||||
}
|
||||
@@ -98,44 +118,44 @@ class BudgetController extends Controller
|
||||
*/
|
||||
public function index(BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$budgets = Auth::user()->budgets()->get();
|
||||
$budgets = $repository->getActiveBudgets();
|
||||
$inactive = $repository->getInactiveBudgets();
|
||||
|
||||
/**
|
||||
* Do some cleanup:
|
||||
*/
|
||||
$repository->cleanupBudgets();
|
||||
|
||||
|
||||
// loop the budgets:
|
||||
$budgets->each(
|
||||
function (Budget $budget) use ($repository) {
|
||||
$date = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$budget->spent = $repository->spentInMonth($budget, $date);
|
||||
$budget->currentRep = $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']);
|
||||
$budget->currentRep = $repository->getCurrentRepetition($budget, $date);
|
||||
}
|
||||
);
|
||||
|
||||
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
|
||||
$dateAsString = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
|
||||
$spent = $budgets->sum('spent');
|
||||
$amount = Preferences::get('budgetIncomeTotal' . $date, 1000)->data;
|
||||
$amount = Preferences::get('budgetIncomeTotal' . $dateAsString, 1000)->data;
|
||||
$overspent = $spent > $amount;
|
||||
$spentPCT = $overspent ? ceil($amount / $spent * 100) : ceil($spent / $amount * 100);
|
||||
$budgetMax = Preferences::get('budgetMaximum', 1000);
|
||||
$budgetMaximum = $budgetMax->data;
|
||||
|
||||
return view('budgets.index', compact('budgetMaximum', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount'));
|
||||
return view('budgets.index', compact('budgetMaximum', 'inactive', 'budgets', 'spent', 'spentPCT', 'overspent', 'amount'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function noBudget()
|
||||
public function noBudget(BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$start = \Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = \Session::get('end', Carbon::now()->startOfMonth());
|
||||
$list = Auth::user()
|
||||
->transactionjournals()
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNull('budget_transaction_journal.id')
|
||||
->before($end)
|
||||
->after($start)
|
||||
->orderBy('transaction_journals.date')
|
||||
->get(['transaction_journals.*']);
|
||||
$subTitle = 'Transactions without a budget in ' . $start->format('F Y');
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->startOfMonth());
|
||||
$list = $repository->getWithoutBudget($start, $end);
|
||||
$subTitle = 'Transactions without a budget between ' . $start->format('jS F Y') . ' and ' . $end->format('jS F Y');
|
||||
|
||||
return view('budgets.noBudget', compact('list', 'subTitle'));
|
||||
}
|
||||
@@ -152,20 +172,6 @@ class BudgetController extends Controller
|
||||
return Redirect::route('budgets.index');
|
||||
}
|
||||
|
||||
public function store(BudgetFormRequest $request, BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$budgetData = [
|
||||
'name' => $request->input('name'),
|
||||
'user' => Auth::user()->id,
|
||||
];
|
||||
$budget = $repository->store($budgetData);
|
||||
|
||||
Session::flash('success', 'New budget "' . $budget->name . '" stored!');
|
||||
|
||||
return Redirect::route('budgets.index');
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Budget $budget
|
||||
@@ -181,12 +187,40 @@ class BudgetController extends Controller
|
||||
|
||||
$hideBudget = true; // used in transaction list.
|
||||
$journals = $repository->getJournals($budget, $repetition);
|
||||
$limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $budget->budgetLimits()->orderBy('startdate', 'DESC')->get();
|
||||
$limits = !is_null($repetition->id) ? [$repetition->budgetLimit] : $repository->getBudgetLimits($budget);
|
||||
$subTitle = !is_null($repetition->id) ? e($budget->name) . ' in ' . $repetition->startdate->format('F Y') : e($budget->name);
|
||||
|
||||
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BudgetFormRequest $request
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(BudgetFormRequest $request, BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$budgetData = [
|
||||
'name' => $request->input('name'),
|
||||
'user' => Auth::user()->id,
|
||||
];
|
||||
$budget = $repository->store($budgetData);
|
||||
|
||||
Session::flash('success', 'New budget "' . $budget->name . '" stored!');
|
||||
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
// set value so create routine will not overwrite URL:
|
||||
Session::put('budgets.create.fromStore', true);
|
||||
|
||||
return Redirect::route('budgets.create')->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('budgets.create.url'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param BudgetFormRequest $request
|
||||
@@ -197,14 +231,23 @@ class BudgetController extends Controller
|
||||
public function update(Budget $budget, BudgetFormRequest $request, BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$budgetData = [
|
||||
'name' => $request->input('name'),
|
||||
'name' => $request->input('name'),
|
||||
'active' => intval($request->input('active')) == 1
|
||||
];
|
||||
|
||||
$repository->update($budget, $budgetData);
|
||||
|
||||
Session::flash('success', 'Budget "' . $budget->name . '" updated.');
|
||||
|
||||
return Redirect::route('budgets.index');
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('budgets.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('budgets.edit', $budget->id)->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('budgets.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@@ -7,11 +7,11 @@ use FireflyIII\Http\Requests\CategoryFormRequest;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Input;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use URL;
|
||||
use View;
|
||||
use Input;
|
||||
|
||||
|
||||
/**
|
||||
* Class CategoryController
|
||||
@@ -35,47 +35,15 @@ class CategoryController extends Controller
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (Session::get('categories.create.fromStore') !== true) {
|
||||
Session::put('categories.create.url', URL::previous());
|
||||
}
|
||||
Session::forget('categories.create.fromStore');
|
||||
|
||||
return view('categories.create')->with('subTitle', 'Create a new category');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function show(Category $category, CategoryRepositoryInterface $repository)
|
||||
{
|
||||
$hideCategory = true; // used in list.
|
||||
$page = intval(Input::get('page'));
|
||||
$offset = $page > 0 ? $page * 50 : 0;
|
||||
$set = $category->transactionJournals()->withRelevantData()->take(50)->offset($offset)->orderBy('date', 'DESC')->get(['transaction_journals.*']);
|
||||
$count = $category->transactionJournals()->count();
|
||||
|
||||
$journals = new LengthAwarePaginator($set, $count, 50, $page);
|
||||
|
||||
return view('categories.show', compact('category', 'journals', 'hideCategory'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function noCategory()
|
||||
{
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->startOfMonth());
|
||||
$list = Auth::user()
|
||||
->transactionjournals()
|
||||
->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNull('category_transaction_journal.id')
|
||||
->before($end)
|
||||
->after($start)
|
||||
->orderBy('transaction_journals.date')
|
||||
->get(['transaction_journals.*']);
|
||||
$subTitle = 'Transactions without a category in ' . $start->format('F Y');
|
||||
|
||||
return view('categories.noCategory', compact('list', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
@@ -85,6 +53,9 @@ class CategoryController extends Controller
|
||||
{
|
||||
$subTitle = 'Delete category' . e($category->name) . '"';
|
||||
|
||||
// put previous url in session
|
||||
Session::put('categories.delete.url', URL::previous());
|
||||
|
||||
return view('categories.delete', compact('category', 'subTitle'));
|
||||
}
|
||||
|
||||
@@ -101,7 +72,7 @@ class CategoryController extends Controller
|
||||
|
||||
Session::flash('success', 'The category "' . e($name) . '" was deleted.');
|
||||
|
||||
return Redirect::route('categories.index');
|
||||
return Redirect::to(Session::get('categories.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,20 +84,63 @@ class CategoryController extends Controller
|
||||
{
|
||||
$subTitle = 'Edit category "' . e($category->name) . '"';
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (Session::get('categories.edit.fromUpdate') !== true) {
|
||||
Session::put('categories.edit.url', URL::previous());
|
||||
}
|
||||
Session::forget('categories.edit.fromUpdate');
|
||||
|
||||
return view('categories.edit', compact('category', 'subTitle'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*
|
||||
*/
|
||||
public function index()
|
||||
public function index(CategoryRepositoryInterface $repository)
|
||||
{
|
||||
$categories = Auth::user()->categories()->get();
|
||||
$categories = $repository->getCategories();
|
||||
|
||||
$categories->each(
|
||||
function (Category $category) use ($repository) {
|
||||
$category->lastActivity = $repository->getLatestActivity($category);
|
||||
}
|
||||
);
|
||||
|
||||
return view('categories.index', compact('categories'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function noCategory(CategoryRepositoryInterface $repository)
|
||||
{
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->startOfMonth());
|
||||
$list = $repository->getWithoutCategory($start, $end);
|
||||
$subTitle = 'Transactions without a category between ' . $start->format('jS F Y') . ' and ' . $end->format('jS F Y');
|
||||
|
||||
return view('categories.noCategory', compact('list', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function show(Category $category, CategoryRepositoryInterface $repository)
|
||||
{
|
||||
$hideCategory = true; // used in list.
|
||||
$page = intval(Input::get('page'));
|
||||
$set = $repository->getJournals($category, $page);
|
||||
$count = $repository->countJournals($category);
|
||||
$journals = new LengthAwarePaginator($set, $count, 50, $page);
|
||||
$journals->setPath('categories/show/' . $category->id);
|
||||
|
||||
return view('categories.show', compact('category', 'journals', 'hideCategory'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param CategoryFormRequest $request
|
||||
* @param CategoryRepositoryInterface $repository
|
||||
@@ -143,8 +157,13 @@ class CategoryController extends Controller
|
||||
|
||||
Session::flash('success', 'New category "' . $category->name . '" stored!');
|
||||
|
||||
return Redirect::route('categories.index');
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
Session::put('categories.create.fromStore', true);
|
||||
|
||||
return Redirect::route('categories.create')->withInput();
|
||||
}
|
||||
|
||||
return Redirect::route('categories.index');
|
||||
}
|
||||
|
||||
|
||||
@@ -165,7 +184,14 @@ class CategoryController extends Controller
|
||||
|
||||
Session::flash('success', 'Category "' . $category->name . '" updated.');
|
||||
|
||||
return Redirect::route('categories.index');
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
Session::put('categories.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('categories.edit', $category->id);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('categories.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@@ -1,14 +1,17 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Cache;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Requests\CurrencyFormRequest;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use URL;
|
||||
use View;
|
||||
use Cache;
|
||||
|
||||
/**
|
||||
* Class CurrencyController
|
||||
@@ -37,6 +40,12 @@ class CurrencyController extends Controller
|
||||
$subTitleIcon = 'fa-plus';
|
||||
$subTitle = 'Create a new currency';
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (Session::get('currency.create.fromStore') !== true) {
|
||||
Session::put('currency.create.url', URL::previous());
|
||||
}
|
||||
Session::forget('currency.create.fromStore');
|
||||
|
||||
return view('currency.create', compact('subTitleIcon', 'subTitle'));
|
||||
}
|
||||
|
||||
@@ -48,9 +57,7 @@ class CurrencyController extends Controller
|
||||
public function defaultCurrency(TransactionCurrency $currency)
|
||||
{
|
||||
|
||||
$currencyPreference = Preferences::get('currencyPreference', 'EUR');
|
||||
$currencyPreference->data = $currency->code;
|
||||
$currencyPreference->save();
|
||||
Preferences::set('currencyPreference', $currency->code);
|
||||
|
||||
Session::flash('success', $currency->name . ' is now the default currency.');
|
||||
Cache::forget('FFCURRENCYSYMBOL');
|
||||
@@ -65,14 +72,18 @@ class CurrencyController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
|
||||
*/
|
||||
public function delete(TransactionCurrency $currency)
|
||||
public function delete(TransactionCurrency $currency, CurrencyRepositoryInterface $repository)
|
||||
{
|
||||
if ($currency->transactionJournals()->count() > 0) {
|
||||
|
||||
if ($repository->countJournals($currency) > 0) {
|
||||
Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.');
|
||||
|
||||
return Redirect::route('currency.index');
|
||||
}
|
||||
|
||||
// put previous url in session
|
||||
Session::put('currency.delete.url', URL::previous());
|
||||
|
||||
|
||||
return view('currency.delete', compact('currency'));
|
||||
}
|
||||
@@ -82,10 +93,10 @@ class CurrencyController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(TransactionCurrency $currency)
|
||||
public function destroy(TransactionCurrency $currency, CurrencyRepositoryInterface $repository)
|
||||
{
|
||||
if ($currency->transactionJournals()->count() > 0) {
|
||||
Session::flash('error', 'Cannot delete ' . e($currency->name) . ' because there are still transactions attached to it.');
|
||||
if ($repository->countJournals($currency) > 0) {
|
||||
Session::flash('error', 'Cannot destroy ' . e($currency->name) . ' because there are still transactions attached to it.');
|
||||
|
||||
return Redirect::route('currency.index');
|
||||
}
|
||||
@@ -94,7 +105,7 @@ class CurrencyController extends Controller
|
||||
|
||||
$currency->delete();
|
||||
|
||||
return Redirect::route('currency.index');
|
||||
return Redirect::to(Session::get('currency.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,6 +119,12 @@ class CurrencyController extends Controller
|
||||
$subTitle = 'Edit currency "' . e($currency->name) . '"';
|
||||
$currency->symbol = htmlentities($currency->symbol);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (Session::get('currency.edit.fromUpdate') !== true) {
|
||||
Session::put('currency.edit.url', URL::previous());
|
||||
}
|
||||
Session::forget('currency.edit.fromUpdate');
|
||||
|
||||
return view('currency.edit', compact('currency', 'subTitle', 'subTitleIcon'));
|
||||
|
||||
}
|
||||
@@ -115,12 +132,10 @@ class CurrencyController extends Controller
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
public function index(CurrencyRepositoryInterface $repository)
|
||||
{
|
||||
$currencies = TransactionCurrency::get();
|
||||
$currencyPreference = Preferences::get('currencyPreference', 'EUR');
|
||||
$defaultCurrency = TransactionCurrency::whereCode($currencyPreference->data)->first();
|
||||
|
||||
$currencies = $repository->get();
|
||||
$defaultCurrency = $repository->getCurrencyByPreference(Preferences::get('currencyPreference', 'EUR'));
|
||||
|
||||
return view('currency.index', compact('currencies', 'defaultCurrency'));
|
||||
}
|
||||
@@ -130,22 +145,22 @@ class CurrencyController extends Controller
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(CurrencyFormRequest $request)
|
||||
public function store(CurrencyFormRequest $request, CurrencyRepositoryInterface $repository)
|
||||
{
|
||||
$data = $request->getCurrencyData();
|
||||
$currency = $repository->store($data);
|
||||
|
||||
|
||||
// no repository, because the currency controller is relatively simple.
|
||||
$currency = TransactionCurrency::create(
|
||||
[
|
||||
'name' => $request->get('name'),
|
||||
'code' => $request->get('code'),
|
||||
'symbol' => $request->get('symbol'),
|
||||
]
|
||||
);
|
||||
|
||||
Session::flash('success', 'Currency "' . $currency->name . '" created');
|
||||
|
||||
return Redirect::route('currency.index');
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
Session::put('currency.create.fromStore', true);
|
||||
|
||||
return Redirect::route('currency.create')->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('currency.create.url'));
|
||||
|
||||
|
||||
}
|
||||
@@ -155,17 +170,22 @@ class CurrencyController extends Controller
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(TransactionCurrency $currency, CurrencyFormRequest $request)
|
||||
public function update(TransactionCurrency $currency, CurrencyFormRequest $request, CurrencyRepositoryInterface $repository)
|
||||
{
|
||||
$data = $request->getCurrencyData();
|
||||
$currency = $repository->update($currency, $data);
|
||||
|
||||
$currency->code = $request->get('code');
|
||||
$currency->symbol = $request->get('symbol');
|
||||
$currency->name = $request->get('name');
|
||||
$currency->save();
|
||||
Session::flash('success', 'Currency "' . e($currency->name) . '" updated.');
|
||||
|
||||
Session::flash('success', 'Currency "' . e($currency->namename) . '" updated.');
|
||||
|
||||
return Redirect::route('currency.index');
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
Session::put('currency.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('currency.edit', $currency->id);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('currency.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@@ -1,29 +1,28 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Crypt;
|
||||
use Exception;
|
||||
use FireflyIII\Helpers\Report\ReportQueryInterface;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use Grumpydictator\Gchart\GChart;
|
||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
use DB;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
@@ -41,31 +40,20 @@ class GoogleChartController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function accountBalanceChart(Account $account, $view = 'session', GChart $chart)
|
||||
public function accountBalanceChart(Account $account, GChart $chart)
|
||||
{
|
||||
$chart->addColumn('Day of month', 'date');
|
||||
$chart->addColumn('Balance for ' . $account->name, 'number');
|
||||
$chart->addCertainty(1);
|
||||
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$count = $account->transactions()->count();
|
||||
|
||||
if ($view == 'all' && $count > 0) {
|
||||
$first = $account->transactions()->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->orderBy(
|
||||
'date', 'ASC'
|
||||
)->first(['transaction_journals.date']);
|
||||
$last = $account->transactions()->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')->orderBy(
|
||||
'date', 'DESC'
|
||||
)->first(['transaction_journals.date']);
|
||||
$start = new Carbon($first->date);
|
||||
$end = new Carbon($last->date);
|
||||
}
|
||||
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$current = clone $start;
|
||||
$today = new Carbon;
|
||||
|
||||
while ($end >= $current) {
|
||||
$chart->addRow(clone $current, Steam::balance($account, $current), false);
|
||||
$certain = $current < $today;
|
||||
$chart->addRow(clone $current, Steam::balance($account, $current), $certain);
|
||||
$current->addDay();
|
||||
}
|
||||
|
||||
@@ -80,19 +68,15 @@ class GoogleChartController extends Controller
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function allAccountsBalanceChart(GChart $chart)
|
||||
public function allAccountsBalanceChart(GChart $chart, AccountRepositoryInterface $repository)
|
||||
{
|
||||
$chart->addColumn('Day of the month', 'date');
|
||||
|
||||
$frontPage = Preferences::get('frontPageAccounts', []);
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$accounts = $repository->getFrontpageAccounts($frontPage);
|
||||
|
||||
if ($frontPage->data == []) {
|
||||
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']);
|
||||
} else {
|
||||
$accounts = Auth::user()->accounts()->whereIn('id', $frontPage->data)->get(['accounts.*']);
|
||||
}
|
||||
$index = 1;
|
||||
/** @var Account $account */
|
||||
foreach ($accounts as $account) {
|
||||
@@ -126,22 +110,16 @@ class GoogleChartController extends Controller
|
||||
*/
|
||||
public function allBudgetsAndSpending($year, GChart $chart, BudgetRepositoryInterface $repository)
|
||||
{
|
||||
try {
|
||||
new Carbon('01-01-' . $year);
|
||||
} catch (Exception $e) {
|
||||
return view('error')->with('message', 'Invalid year.');
|
||||
}
|
||||
$budgets = Auth::user()->budgets()->get();
|
||||
$budgets->sortBy('name');
|
||||
$budgets = $repository->getBudgets();
|
||||
$chart->addColumn('Month', 'date');
|
||||
foreach ($budgets as $budget) {
|
||||
$chart->addColumn($budget->name, 'number');
|
||||
}
|
||||
|
||||
$start = Carbon::createFromDate(intval($year), 1, 1);
|
||||
$end = clone $start;
|
||||
$end->endOfYear();
|
||||
|
||||
|
||||
while ($start <= $end) {
|
||||
$row = [clone $start];
|
||||
foreach ($budgets as $budget) {
|
||||
@@ -152,7 +130,6 @@ class GoogleChartController extends Controller
|
||||
$start->addMonth();
|
||||
}
|
||||
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return Response::json($chart->getData());
|
||||
@@ -164,64 +141,44 @@ class GoogleChartController extends Controller
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function allBudgetsHomeChart(GChart $chart)
|
||||
public function allBudgetsHomeChart(GChart $chart, BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$chart->addColumn('Budget', 'string');
|
||||
$chart->addColumn('Budgeted', 'number');
|
||||
$chart->addColumn('Spent', 'number');
|
||||
|
||||
$budgets = Auth::user()->budgets()->orderBy('name', 'DESC')->get();
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$budgets = $repository->getBudgets();
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$allEntries = new Collection;
|
||||
|
||||
/** @var Budget $budget */
|
||||
foreach ($budgets as $budget) {
|
||||
|
||||
/** @var \LimitRepetition $repetition */
|
||||
$repetition = LimitRepetition::
|
||||
leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
|
||||
->where('limit_repetitions.startdate', $start->format('Y-m-d 00:00:00'))
|
||||
->where('budget_limits.budget_id', $budget->id)
|
||||
->first(['limit_repetitions.*']);
|
||||
if (is_null($repetition)) { // use the session start and end for our search query
|
||||
$searchStart = $start;
|
||||
$searchEnd = $end;
|
||||
$limit = 0; // the limit is zero:
|
||||
} else {
|
||||
// use the limit's start and end for our search query
|
||||
$searchStart = $repetition->startdate;
|
||||
$searchEnd = $repetition->enddate;
|
||||
$limit = floatval($repetition->amount); // the limit is the repetitions limit:
|
||||
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
|
||||
if ($repetitions->count() == 0) {
|
||||
$expenses = $repository->sumBudgetExpensesInPeriod($budget, $start, $end);
|
||||
$allEntries->push([$budget->name, 0, $expenses]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$expenses = floatval($budget->transactionjournals()->before($searchEnd)->after($searchStart)->lessThan(0)->sum('amount')) * -1;
|
||||
if ($expenses > 0) {
|
||||
$chart->addRow($budget->name, $limit, $expenses);
|
||||
/** @var LimitRepetition $repetition */
|
||||
foreach ($repetitions as $repetition) {
|
||||
$expenses = $repository->sumBudgetExpensesInPeriod($budget, $repetition->startdate, $repetition->enddate);
|
||||
$allEntries->push([$budget->name . ' (' . $repetition->startdate->format('j M Y') . ')', floatval($repetition->amount), $expenses]);
|
||||
}
|
||||
}
|
||||
|
||||
$noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end);
|
||||
$allEntries->push(['(no budget)', 0, $noBudgetExpenses]);
|
||||
|
||||
foreach ($allEntries as $entry) {
|
||||
if ($entry[2] > 0) {
|
||||
$chart->addRow($entry[0], $entry[1], $entry[2]);
|
||||
}
|
||||
}
|
||||
|
||||
$noBudgetSet = Auth::user()
|
||||
->transactionjournals()
|
||||
->whereNotIn(
|
||||
'transaction_journals.id', function (QueryBuilder $query) use ($start, $end) {
|
||||
$query
|
||||
->select('transaction_journals.id')
|
||||
->from('transaction_journals')
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
)
|
||||
->before($end)
|
||||
->after($start)
|
||||
->lessThan(0)
|
||||
->transactionTypes(['Withdrawal'])
|
||||
->get();
|
||||
$sum = $noBudgetSet->sum('amount') * -1;
|
||||
$chart->addRow('No budget', 0, $sum);
|
||||
$chart->generate();
|
||||
|
||||
return Response::json($chart->getData());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,35 +186,20 @@ class GoogleChartController extends Controller
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function allCategoriesHomeChart(GChart $chart)
|
||||
public function allCategoriesHomeChart(GChart $chart, CategoryRepositoryInterface $repository)
|
||||
{
|
||||
$chart->addColumn('Category', 'string');
|
||||
$chart->addColumn('Spent', 'number');
|
||||
|
||||
// query!
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$set = TransactionJournal::leftJoin(
|
||||
'transactions',
|
||||
function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)
|
||||
->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->before($end)
|
||||
->after($start)
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('categories.id')
|
||||
->orderBy('sum', 'DESC')
|
||||
->get(['categories.id', 'categories.name', \DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]);
|
||||
$set = $repository->getCategoriesAndExpenses($start, $end);
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$entry->name = strlen($entry->name) == 0 ? '(no category)' : $entry->name;
|
||||
$chart->addRow($entry->name, floatval($entry->sum));
|
||||
$isEncrypted = intval($entry->encrypted) == 1 ? true : false;
|
||||
$name = strlen($entry->name) == 0 ? '(no category)' : $entry->name;
|
||||
$name = $isEncrypted ? Crypt::decrypt($name) : $name;
|
||||
$chart->addRow($name, floatval($entry->sum));
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
@@ -267,41 +209,24 @@ class GoogleChartController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param Bill $bill
|
||||
* @param GChart $chart
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function billOverview(Bill $bill, GChart $chart)
|
||||
public function billOverview(Bill $bill, GChart $chart, BillRepositoryInterface $repository)
|
||||
{
|
||||
|
||||
$chart->addColumn('Date', 'date');
|
||||
$chart->addColumn('Max amount', 'number');
|
||||
$chart->addColumn('Min amount', 'number');
|
||||
$chart->addColumn('Current entry', 'number');
|
||||
$chart->addColumn('Recorded bill entry', 'number');
|
||||
|
||||
// get first transaction or today for start:
|
||||
$first = $bill->transactionjournals()->orderBy('date', 'ASC')->first();
|
||||
if ($first) {
|
||||
$start = $first->date;
|
||||
} else {
|
||||
$start = new Carbon;
|
||||
}
|
||||
$end = new Carbon;
|
||||
while ($start <= $end) {
|
||||
$result = $bill->transactionjournals()->before($end)->after($start)->first();
|
||||
if ($result) {
|
||||
/** @var Transaction $tr */
|
||||
foreach ($result->transactions()->get() as $tr) {
|
||||
if (floatval($tr->amount) > 0) {
|
||||
$amount = floatval($tr->amount);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$amount = 0;
|
||||
}
|
||||
unset($result);
|
||||
$chart->addRow(clone $start, $bill->amount_max, $bill->amount_min, $amount);
|
||||
$start = Navigation::addPeriod($start, $bill->repeat_freq, 0);
|
||||
$results = $repository->getJournals($bill);
|
||||
/** @var TransactionJournal $result */
|
||||
foreach ($results as $result) {
|
||||
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
@@ -315,51 +240,78 @@ class GoogleChartController extends Controller
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function billsOverview(GChart $chart)
|
||||
public function billsOverview(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
|
||||
{
|
||||
$paid = ['items' => [], 'amount' => 0];
|
||||
$unpaid = ['items' => [], 'amount' => 0];
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
|
||||
$chart->addColumn('Name', 'string');
|
||||
$chart->addColumn('Amount', 'number');
|
||||
|
||||
$set = Bill::
|
||||
leftJoin(
|
||||
'transaction_journals', function (JoinClause $join) use ($start, $end) {
|
||||
$join->on('bills.id', '=', 'transaction_journals.bill_id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'));
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->where('active', 1)
|
||||
->groupBy('bills.id')
|
||||
->get(
|
||||
['bills.id', 'bills.name', 'transaction_journals.description',
|
||||
'transaction_journals.encrypted',
|
||||
'transaction_journals.id as journalId',
|
||||
\DB::Raw('SUM(`bills`.`amount_min` + `bills`.`amount_max`) / 2 as `averageAmount`'),
|
||||
'transactions.amount AS actualAmount']
|
||||
);
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$bills = $repository->getActiveBills();
|
||||
$paid = new Collection; // journals.
|
||||
$unpaid = new Collection; // bills
|
||||
// loop paid and create single entry:
|
||||
$paidDescriptions = [];
|
||||
$paidAmount = 0;
|
||||
$unpaidDescriptions = [];
|
||||
$unpaidAmount = 0;
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
$ranges = $repository->getRanges($bill, $start, $end);
|
||||
|
||||
foreach ($ranges as $range) {
|
||||
// paid a bill in this range?
|
||||
$journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']);
|
||||
if ($journals->count() == 0) {
|
||||
$unpaid->push([$bill, $range['start']]);
|
||||
} else {
|
||||
$paid = $paid->merge($journals);
|
||||
}
|
||||
|
||||
foreach ($set as $entry) {
|
||||
if (intval($entry->journalId) == 0) {
|
||||
$unpaid['items'][] = $entry->name;
|
||||
$unpaid['amount'] += floatval($entry->averageAmount);
|
||||
} else {
|
||||
$description = intval($entry->encrypted) == 1 ? Crypt::decrypt($entry->description) : $entry->description;
|
||||
$paid['items'][] = $description;
|
||||
$paid['amount'] += floatval($entry->actualAmount);
|
||||
}
|
||||
}
|
||||
$chart->addRow('Unpaid: ' . join(', ', $unpaid['items']), $unpaid['amount']);
|
||||
$chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']);
|
||||
|
||||
$creditCards = $accounts->getCreditCards();
|
||||
foreach ($creditCards as $creditCard) {
|
||||
$balance = Steam::balance($creditCard, null, true);
|
||||
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
|
||||
if ($balance < 0) {
|
||||
// unpaid! create a fake bill that matches the amount.
|
||||
$description = $creditCard->name;
|
||||
$amount = $balance * -1;
|
||||
$fakeBill = $repository->createFakeBill($description, $date, $amount);
|
||||
unset($description, $amount);
|
||||
$unpaid->push([$fakeBill, $date]);
|
||||
}
|
||||
if ($balance == 0) {
|
||||
// find transfer(s) TO the credit card which should account for
|
||||
// anything paid. If not, the CC is not yet used.
|
||||
$journals = $accounts->getTransfersInRange($creditCard, $start, $end);
|
||||
$paid = $paid->merge($journals);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @var TransactionJournal $entry */
|
||||
foreach ($paid as $entry) {
|
||||
|
||||
$paidDescriptions[] = $entry->description;
|
||||
$paidAmount += floatval($entry->amount);
|
||||
}
|
||||
|
||||
// loop unpaid:
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) {
|
||||
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
|
||||
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
|
||||
$unpaidDescriptions[] = $description;
|
||||
$unpaidAmount += $amount;
|
||||
unset($amount, $description);
|
||||
}
|
||||
|
||||
$chart->addRow('Unpaid: ' . join(', ', $unpaidDescriptions), $unpaidAmount);
|
||||
$chart->addRow('Paid: ' . join(', ', $paidDescriptions), $paidAmount);
|
||||
$chart->generate();
|
||||
|
||||
return Response::json($chart->getData());
|
||||
@@ -372,7 +324,7 @@ class GoogleChartController extends Controller
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function budgetLimitSpending(Budget $budget, LimitRepetition $repetition, GChart $chart)
|
||||
public function budgetLimitSpending(Budget $budget, LimitRepetition $repetition, GChart $chart, BudgetRepositoryInterface $repository)
|
||||
{
|
||||
$start = clone $repetition->startdate;
|
||||
$end = $repetition->enddate;
|
||||
@@ -387,7 +339,7 @@ class GoogleChartController extends Controller
|
||||
/*
|
||||
* Sum of expenses on this day:
|
||||
*/
|
||||
$sum = floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($start)->sum('amount'));
|
||||
$sum = $repository->expensesOnDay($budget, $start);
|
||||
$amount += $sum;
|
||||
$chart->addRow(clone $start, $amount);
|
||||
$start->addDay();
|
||||
@@ -399,37 +351,22 @@ class GoogleChartController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param int $year
|
||||
* @param GChart $chart
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
*
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @param int $year
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function budgetsAndSpending(Budget $budget, $year = 0)
|
||||
public function budgetsAndSpending(Budget $budget, $year = 0, GChart $chart, BudgetRepositoryInterface $repository)
|
||||
{
|
||||
|
||||
$chart = App::make('Grumpydictator\Gchart\GChart');
|
||||
$repository = App::make('FireflyIII\Repositories\Budget\BudgetRepository');
|
||||
$chart->addColumn('Month', 'date');
|
||||
$chart->addColumn('Budgeted', 'number');
|
||||
$chart->addColumn('Spent', 'number');
|
||||
if ($year == 0) {
|
||||
// grab the first budgetlimit ever:
|
||||
$firstLimit = $budget->budgetlimits()->orderBy('startdate', 'ASC')->first();
|
||||
if ($firstLimit) {
|
||||
$start = new Carbon($firstLimit->startdate);
|
||||
} else {
|
||||
$start = Carbon::now()->startOfYear();
|
||||
}
|
||||
|
||||
// grab the last budget limit ever:
|
||||
$lastLimit = $budget->budgetlimits()->orderBy('startdate', 'DESC')->first();
|
||||
if ($lastLimit) {
|
||||
$end = new Carbon($lastLimit->startdate);
|
||||
} else {
|
||||
$end = Carbon::now()->endOfYear();
|
||||
}
|
||||
if ($year == 0) {
|
||||
$start = $repository->getFirstBudgetLimitDate($budget);
|
||||
$end = $repository->getLastBudgetLimitDate($budget);
|
||||
} else {
|
||||
$start = Carbon::createFromDate(intval($year), 1, 1);
|
||||
$end = clone $start;
|
||||
@@ -437,19 +374,8 @@ class GoogleChartController extends Controller
|
||||
}
|
||||
|
||||
while ($start <= $end) {
|
||||
$spent = $repository->spentInMonth($budget, $start);
|
||||
$repetition = LimitRepetition::leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
|
||||
->where('limit_repetitions.startdate', $start->format('Y-m-d 00:00:00'))
|
||||
->where('budget_limits.budget_id', $budget->id)
|
||||
->first(['limit_repetitions.*']);
|
||||
|
||||
if ($repetition) {
|
||||
$budgeted = floatval($repetition->amount);
|
||||
\Log::debug('Found a repetition on ' . $start->format('Y-m-d') . ' for budget ' . $budget->name . '!');
|
||||
} else {
|
||||
\Log::debug('No repetition on ' . $start->format('Y-m-d') . ' for budget ' . $budget->name);
|
||||
$budgeted = null;
|
||||
}
|
||||
$spent = $repository->spentInMonth($budget, $start);
|
||||
$budgeted = $repository->getLimitAmountOnDate($budget, $start);
|
||||
$chart->addRow(clone $start, $budgeted, $spent);
|
||||
$start->addMonth();
|
||||
}
|
||||
@@ -463,39 +389,33 @@ class GoogleChartController extends Controller
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Category $category
|
||||
* @param $year
|
||||
* @param Category $category
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function categoriesAndSpending(Category $category, $year, GChart $chart)
|
||||
public function categoryOverviewChart(Category $category, GChart $chart, CategoryRepositoryInterface $repository)
|
||||
{
|
||||
try {
|
||||
new Carbon('01-01-' . $year);
|
||||
} catch (Exception $e) {
|
||||
return view('error')->with('message', 'Invalid year.');
|
||||
}
|
||||
// oldest transaction in category:
|
||||
$start = $repository->getFirstActivityDate($category);
|
||||
|
||||
$chart->addColumn('Month', 'date');
|
||||
$chart->addColumn('Budgeted', 'number');
|
||||
/** @var Preference $range */
|
||||
$range = Preferences::get('viewRange', '1M');
|
||||
// jump to start of week / month / year / etc (TODO).
|
||||
$start = Navigation::startOfPeriod($start, $range->data);
|
||||
|
||||
$chart->addColumn('Period', 'date');
|
||||
$chart->addColumn('Spent', 'number');
|
||||
|
||||
$start = new Carbon('01-01-' . $year);
|
||||
$end = clone $start;
|
||||
$end->endOfYear();
|
||||
$end = new Carbon;
|
||||
while ($start <= $end) {
|
||||
|
||||
$currentEnd = clone $start;
|
||||
$currentEnd->endOfMonth();
|
||||
$spent = floatval($category->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1;
|
||||
$budgeted = null;
|
||||
$currentEnd = Navigation::endOfPeriod($start, $range->data);
|
||||
$spent = $repository->spentInPeriodSum($category, $start, $currentEnd);
|
||||
$chart->addRow(clone $start, $spent);
|
||||
|
||||
$chart->addRow(clone $start, $budgeted, $spent);
|
||||
|
||||
$start->addMonth();
|
||||
$start = Navigation::addPeriod($start, $range->data, 0);
|
||||
}
|
||||
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return Response::json($chart->getData());
|
||||
@@ -503,20 +423,50 @@ class GoogleChartController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Category $category
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function categoryPeriodChart(Category $category, GChart $chart, CategoryRepositoryInterface $repository)
|
||||
{
|
||||
$start = clone Session::get('start', Carbon::now()->startOfMonth());
|
||||
$chart->addColumn('Period', 'date');
|
||||
$chart->addColumn('Spent', 'number');
|
||||
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
while ($start <= $end) {
|
||||
$spent = $repository->spentOnDaySum($category, $start);
|
||||
$chart->addRow(clone $start, $spent);
|
||||
$start->addDay();
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
|
||||
return Response::json($chart->getData());
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function piggyBankHistory(PiggyBank $piggyBank, GChart $chart)
|
||||
public function piggyBankHistory(PiggyBank $piggyBank, GChart $chart, PiggyBankRepositoryInterface $repository)
|
||||
{
|
||||
$chart->addColumn('Date', 'date');
|
||||
$chart->addColumn('Balance', 'number');
|
||||
|
||||
$set = \DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]);
|
||||
/** @var Collection $set */
|
||||
$set = $repository->getEventSummarySet($piggyBank);
|
||||
$sum = 0;
|
||||
|
||||
foreach ($set as $entry) {
|
||||
$chart->addRow(new Carbon($entry->date), floatval($entry->sum));
|
||||
$sum += floatval($entry->sum);
|
||||
$chart->addRow(new Carbon($entry->date), $sum);
|
||||
}
|
||||
|
||||
$chart->generate();
|
||||
@@ -533,15 +483,14 @@ class GoogleChartController extends Controller
|
||||
*/
|
||||
public function yearInExp($year, GChart $chart, ReportQueryInterface $query)
|
||||
{
|
||||
try {
|
||||
$start = new Carbon('01-01-' . $year);
|
||||
} catch (Exception $e) {
|
||||
return view('error')->with('message', 'Invalid year.');
|
||||
}
|
||||
$start = new Carbon('01-01-' . $year);
|
||||
$chart->addColumn('Month', 'date');
|
||||
$chart->addColumn('Income', 'number');
|
||||
$chart->addColumn('Expenses', 'number');
|
||||
|
||||
$pref = Preferences::get('showSharedReports', false);
|
||||
$showSharedReports = $pref->data;
|
||||
|
||||
// get report query interface.
|
||||
|
||||
$end = clone $start;
|
||||
@@ -549,19 +498,9 @@ class GoogleChartController extends Controller
|
||||
while ($start < $end) {
|
||||
$currentEnd = clone $start;
|
||||
$currentEnd->endOfMonth();
|
||||
// total income:
|
||||
$income = $query->incomeByPeriod($start, $currentEnd);
|
||||
$incomeSum = 0;
|
||||
foreach ($income as $entry) {
|
||||
$incomeSum += floatval($entry->amount);
|
||||
}
|
||||
|
||||
// total expenses:
|
||||
$expense = $query->journalsByExpenseAccount($start, $currentEnd);
|
||||
$expenseSum = 0;
|
||||
foreach ($expense as $entry) {
|
||||
$expenseSum += floatval($entry->amount);
|
||||
}
|
||||
// total income && total expenses:
|
||||
$incomeSum = floatval($query->incomeByPeriod($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
|
||||
$expenseSum = floatval($query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
|
||||
|
||||
$chart->addRow(clone $start, $incomeSum, $expenseSum);
|
||||
$start->addMonth();
|
||||
@@ -582,15 +521,14 @@ class GoogleChartController extends Controller
|
||||
*/
|
||||
public function yearInExpSum($year, GChart $chart, ReportQueryInterface $query)
|
||||
{
|
||||
try {
|
||||
$start = new Carbon('01-01-' . $year);
|
||||
} catch (Exception $e) {
|
||||
return view('error')->with('message', 'Invalid year.');
|
||||
}
|
||||
$start = new Carbon('01-01-' . $year);
|
||||
$chart->addColumn('Summary', 'string');
|
||||
$chart->addColumn('Income', 'number');
|
||||
$chart->addColumn('Expenses', 'number');
|
||||
|
||||
$pref = Preferences::get('showSharedReports', false);
|
||||
$showSharedReports = $pref->data;
|
||||
|
||||
$income = 0;
|
||||
$expense = 0;
|
||||
$count = 0;
|
||||
@@ -601,18 +539,9 @@ class GoogleChartController extends Controller
|
||||
$currentEnd = clone $start;
|
||||
$currentEnd->endOfMonth();
|
||||
// total income:
|
||||
$incomeResult = $query->incomeByPeriod($start, $currentEnd);
|
||||
$incomeSum = 0;
|
||||
foreach ($incomeResult as $entry) {
|
||||
$incomeSum += floatval($entry->amount);
|
||||
}
|
||||
|
||||
$incomeSum = floatval($query->incomeByPeriod($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
|
||||
// total expenses:
|
||||
$expenseResult = $query->journalsByExpenseAccount($start, $currentEnd);
|
||||
$expenseSum = 0;
|
||||
foreach ($expenseResult as $entry) {
|
||||
$expenseSum += floatval($entry->amount);
|
||||
}
|
||||
$expenseSum = floatval($query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
|
||||
|
||||
$income += $incomeSum;
|
||||
$expense += $expenseSum;
|
||||
|
@@ -1,94 +1,54 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use ErrorException;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
use Route;
|
||||
use Response;
|
||||
use Cache;
|
||||
use ErrorException;
|
||||
use FireflyIII\Helpers\Help\HelpInterface;
|
||||
use League\CommonMark\CommonMarkConverter;
|
||||
use Log;
|
||||
use Response;
|
||||
use Route;
|
||||
|
||||
/**
|
||||
* Class HelpController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class HelpController extends Controller {
|
||||
class HelpController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $route
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function show($route)
|
||||
public function show($route, HelpInterface $help)
|
||||
{
|
||||
$content = [
|
||||
'text' => '<p>There is no help for this route!</p>',
|
||||
'title' => 'Help',
|
||||
];
|
||||
|
||||
if (!Route::has($route)) {
|
||||
\Log::error('No such route: ' . $route);
|
||||
if (!$help->hasRoute($route)) {
|
||||
Log::error('No such route: ' . $route);
|
||||
|
||||
return Response::json($content);
|
||||
}
|
||||
|
||||
if ($this->_inCache($route)) {
|
||||
if ($help->inCache($route)) {
|
||||
$content = [
|
||||
'text' => Cache::get('help.' . $route . '.text'),
|
||||
'title' => Cache::get('help.' . $route . '.title'),
|
||||
'text' => $help->getFromCache('help.' . $route . '.text'),
|
||||
'title' => $help->getFromCache('help.' . $route . '.title'),
|
||||
];
|
||||
|
||||
return Response::json($content);
|
||||
}
|
||||
$content = $this->_getFromGithub($route);
|
||||
$content = $help->getFromGithub($route);
|
||||
|
||||
|
||||
Cache::put('help.' . $route . '.text', $content['text'], 10080); // a week.
|
||||
Cache::put('help.' . $route . '.title', $content['title'], 10080);
|
||||
$help->putInCache($route, $content);
|
||||
|
||||
return Response::json($content);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $route
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function _inCache($route)
|
||||
{
|
||||
return Cache::has('help.' . $route . '.title') && Cache::has('help.' . $route . '.text');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $route
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function _getFromGithub($route)
|
||||
{
|
||||
$uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md';
|
||||
$content = [
|
||||
'text' => '<p>There is no help for this route!</p>',
|
||||
'title' => $route,
|
||||
];
|
||||
try {
|
||||
$content['text'] = file_get_contents($uri);
|
||||
} catch (ErrorException $e) {
|
||||
\Log::error(trim($e->getMessage()));
|
||||
}
|
||||
if (strlen(trim($content['text'])) == 0) {
|
||||
$content['text'] = '<p>There is no help for this route.</p>';
|
||||
}
|
||||
$converter = new CommonMarkConverter();
|
||||
$content['text'] = $converter->convertToHtml($content['text']);
|
||||
|
||||
return $content;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,13 +1,13 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Cache;
|
||||
use Carbon\Carbon;
|
||||
use Navigation;
|
||||
use Config;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use Input;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use URL;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
* Class HomeController
|
||||
@@ -17,11 +17,19 @@ use URL;
|
||||
class HomeController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
public function dateRange()
|
||||
{
|
||||
$start = new Carbon(Input::get('start'));
|
||||
$end = new Carbon(Input::get('end'));
|
||||
|
||||
$diff = $start->diffInDays($end);
|
||||
|
||||
if ($diff > 50) {
|
||||
Session::flash('warning', $diff . ' days of data may take a while to load.');
|
||||
}
|
||||
|
||||
Session::put('start', $start);
|
||||
Session::put('end', $end);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -29,96 +37,57 @@ class HomeController extends Controller
|
||||
*/
|
||||
public function flush()
|
||||
{
|
||||
Cache::flush();
|
||||
Session::clear();
|
||||
|
||||
return Redirect::route('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param AccountRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
public function index(AccountRepositoryInterface $repository)
|
||||
{
|
||||
$count = Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->count();
|
||||
$title = 'Firefly';
|
||||
$subTitle = 'What\'s playing?';
|
||||
$mainTitleIcon = 'fa-fire';
|
||||
$transactions = [];
|
||||
$frontPage = Preferences::get('frontPageAccounts', []);
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
|
||||
if ($frontPage->data == []) {
|
||||
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']);
|
||||
} else {
|
||||
$accounts = Auth::user()->accounts()->whereIn('id', $frontPage->data)->get(['accounts.*']);
|
||||
$types = Config::get('firefly.accountTypesByIdentifier.asset');
|
||||
$count = $repository->countAccounts($types);
|
||||
$title = 'Firefly';
|
||||
$subTitle = 'What\'s playing?';
|
||||
$mainTitleIcon = 'fa-fire';
|
||||
$transactions = [];
|
||||
$frontPage = Preferences::get('frontPageAccounts', []);
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$accounts = $repository->getFrontpageAccounts($frontPage);
|
||||
$savings = $repository->getSavingsAccounts();
|
||||
$piggyBankAccounts = $repository->getPiggyBankAccounts();
|
||||
|
||||
|
||||
$savingsTotal = 0;
|
||||
foreach ($savings as $savingAccount) {
|
||||
$savingsTotal += Steam::balance($savingAccount, $end);
|
||||
}
|
||||
|
||||
// check if all books are correct.
|
||||
$sum = $repository->sumOfEverything();
|
||||
if ($sum != 0) {
|
||||
Session::flash(
|
||||
'error', 'Your transactions are unbalanced. This means a'
|
||||
. ' withdrawal, deposit or transfer was not stored properly. '
|
||||
. 'Please check your accounts and transactions for errors.'
|
||||
);
|
||||
}
|
||||
|
||||
foreach ($accounts as $account) {
|
||||
$set = Auth::user()
|
||||
->transactionjournals()
|
||||
->with(['transactions', 'transactioncurrency', 'transactiontype'])
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $account->id)
|
||||
->where('date', '>=', $start->format('Y-m-d'))
|
||||
->where('date', '<=', $end->format('Y-m-d'))
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->take(10)
|
||||
->get(['transaction_journals.*']);
|
||||
$set = $repository->getFrontpageTransactions($account, $start, $end);
|
||||
if (count($set) > 0) {
|
||||
$transactions[] = [$set, $account];
|
||||
}
|
||||
}
|
||||
|
||||
// var_dump($transactions);
|
||||
|
||||
return view('index', compact('count', 'title', 'subTitle', 'mainTitleIcon', 'transactions'));
|
||||
return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal','piggyBankAccounts'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $range
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function rangeJump($range)
|
||||
{
|
||||
|
||||
$valid = ['1D', '1W', '1M', '3M', '6M', '1Y',];
|
||||
|
||||
if (in_array($range, $valid)) {
|
||||
Preferences::set('viewRange', $range);
|
||||
Session::forget('range');
|
||||
}
|
||||
|
||||
return Redirect::to(URL::previous());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function sessionNext()
|
||||
{
|
||||
$range = Session::get('range');
|
||||
$start = Session::get('start');
|
||||
|
||||
Session::put('start', Navigation::jumpToNext($range, clone $start));
|
||||
|
||||
return Redirect::to(URL::previous());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function sessionPrev()
|
||||
{
|
||||
$range = Session::get('range');
|
||||
$start = Session::get('start');
|
||||
|
||||
Session::put('start', Navigation::jumpToPrevious($range, clone $start));
|
||||
|
||||
return Redirect::to(URL::previous());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,36 +1,166 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Response;
|
||||
use Amount;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Report\ReportQueryInterface;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
* Class JsonController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class JsonController extends Controller {
|
||||
class JsonController extends Controller
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param BillRepositoryInterface $repository
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function boxBillsPaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository)
|
||||
{
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$amount = 0;
|
||||
|
||||
// these two functions are the same as the chart TODO
|
||||
$bills = $repository->getActiveBills();
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
$ranges = $repository->getRanges($bill, $start, $end);
|
||||
|
||||
foreach ($ranges as $range) {
|
||||
// paid a bill in this range?
|
||||
$amount += $repository->getJournalsInRange($bill, $range['start'], $range['end'])->sum('amount');
|
||||
}
|
||||
}
|
||||
unset($ranges, $bill, $range, $bills);
|
||||
|
||||
/**
|
||||
* Find credit card accounts and possibly unpaid credit card bills.
|
||||
*/
|
||||
$creditCards = $accountRepository->getCreditCards();
|
||||
// if the balance is not zero, the monthly payment is still underway.
|
||||
/** @var Account $creditCard */
|
||||
foreach ($creditCards as $creditCard) {
|
||||
$balance = Steam::balance($creditCard, null, true);
|
||||
if ($balance == 0) {
|
||||
// find a transfer TO the credit card which should account for
|
||||
// anything paid. If not, the CC is not yet used.
|
||||
$amount += $accountRepository->getTransfersInRange($creditCard, $start, $end)->sum('amount');
|
||||
}
|
||||
}
|
||||
|
||||
return Response::json(['box' => 'bills-paid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param BillRepositoryInterface $repository
|
||||
* @param AccountRepositoryInterface $accountRepository
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function boxBillsUnpaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository)
|
||||
{
|
||||
$amount = 0;
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$bills = $repository->getActiveBills();
|
||||
$unpaid = new Collection; // bills
|
||||
|
||||
/** @var Bill $bill */
|
||||
foreach ($bills as $bill) {
|
||||
$ranges = $repository->getRanges($bill, $start, $end);
|
||||
|
||||
foreach ($ranges as $range) {
|
||||
$journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']);
|
||||
if ($journals->count() == 0) {
|
||||
$unpaid->push([$bill, $range['start']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($bill, $bills, $range, $ranges);
|
||||
|
||||
$creditCards = $accountRepository->getCreditCards();
|
||||
foreach ($creditCards as $creditCard) {
|
||||
$balance = Steam::balance($creditCard, null, true);
|
||||
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
|
||||
if ($balance < 0) {
|
||||
// unpaid! create a fake bill that matches the amount.
|
||||
$description = $creditCard->name;
|
||||
$fakeAmount = $balance * -1;
|
||||
$fakeBill = $repository->createFakeBill($description, $date, $fakeAmount);
|
||||
$unpaid->push([$fakeBill, $date]);
|
||||
}
|
||||
}
|
||||
/** @var Bill $entry */
|
||||
foreach ($unpaid as $entry) {
|
||||
$current = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
|
||||
$amount += $current;
|
||||
}
|
||||
|
||||
return Response::json(['box' => 'bills-unpaid', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReportQueryInterface $reportQuery
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function boxIn(ReportQueryInterface $reportQuery)
|
||||
{
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$amount = $reportQuery->incomeByPeriod($start, $end, true)->sum('queryAmount');
|
||||
|
||||
return Response::json(['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ReportQueryInterface $reportQuery
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function boxOut(ReportQueryInterface $reportQuery)
|
||||
{
|
||||
$start = Session::get('start', Carbon::now()->startOfMonth());
|
||||
$end = Session::get('end', Carbon::now()->endOfMonth());
|
||||
$amount = $reportQuery->journalsByExpenseAccount($start, $end, true)->sum('queryAmount');
|
||||
|
||||
return Response::json(['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of categories.
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function categories()
|
||||
public function categories(CategoryRepositoryInterface $repository)
|
||||
{
|
||||
$list = Auth::user()->categories()->orderBy('name','ASC')->get();
|
||||
$return = [];
|
||||
$list = $repository->getCategories();
|
||||
$return = [];
|
||||
foreach ($list as $entry) {
|
||||
$return[] = $entry->name;
|
||||
}
|
||||
sort($return);
|
||||
|
||||
return Response::json($return);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,10 +168,10 @@ class JsonController extends Controller {
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function expenseAccounts()
|
||||
public function expenseAccounts(AccountRepositoryInterface $accountRepository)
|
||||
{
|
||||
$list = Auth::user()->accounts()->accountTypeIn(['Expense account', 'Beneficiary account'])->get();
|
||||
$return = [];
|
||||
$list = $accountRepository->getAccounts(['Expense account', 'Beneficiary account']);
|
||||
$return = [];
|
||||
foreach ($list as $entry) {
|
||||
$return[] = $entry->name;
|
||||
}
|
||||
@@ -53,10 +183,10 @@ class JsonController extends Controller {
|
||||
/**
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function revenueAccounts()
|
||||
public function revenueAccounts(AccountRepositoryInterface $accountRepository)
|
||||
{
|
||||
$list = Auth::user()->accounts()->accountTypeIn(['Revenue account'])->get();
|
||||
$return = [];
|
||||
$list = $accountRepository->getAccounts(['Revenue account']);
|
||||
$return = [];
|
||||
foreach ($list as $entry) {
|
||||
$return[] = $entry->name;
|
||||
}
|
||||
@@ -65,4 +195,50 @@ class JsonController extends Controller {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function setSharedReports()
|
||||
{
|
||||
$pref = Preferences::get('showSharedReports', false);
|
||||
$new = !$pref->data;
|
||||
Preferences::set('showSharedReports', $new);
|
||||
|
||||
|
||||
return Response::json(['value' => $new]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function showSharedReports()
|
||||
{
|
||||
$pref = Preferences::get('showSharedReports', false);
|
||||
|
||||
return Response::json(['value' => $pref->data]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $what
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
public function transactionJournals($what, JournalRepositoryInterface $repository)
|
||||
{
|
||||
$descriptions = [];
|
||||
$dbType = $repository->getTransactionType($what);
|
||||
|
||||
$journals = $repository->getJournalsOfType($dbType);
|
||||
foreach ($journals as $j) {
|
||||
$descriptions[] = $j->description;
|
||||
}
|
||||
|
||||
$descriptions = array_unique($descriptions);
|
||||
sort($descriptions);
|
||||
|
||||
return Response::json($descriptions);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -7,8 +7,8 @@ use Config;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Requests\PiggyBankFormRequest;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankEvent;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -16,6 +16,7 @@ use Input;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use Steam;
|
||||
use URL;
|
||||
use View;
|
||||
|
||||
/**
|
||||
@@ -49,9 +50,6 @@ class PiggyBankController extends Controller
|
||||
$leftToSave = $piggyBank->targetamount - $savedSoFar;
|
||||
$maxAmount = min($leftOnAccount, $leftToSave);
|
||||
|
||||
|
||||
\Log::debug('Now going to view for piggy bank #' . $piggyBank->id . ' (' . $piggyBank->name . ')');
|
||||
|
||||
return view('piggy-banks.add', compact('piggyBank', 'maxAmount'));
|
||||
}
|
||||
|
||||
@@ -62,10 +60,18 @@ class PiggyBankController extends Controller
|
||||
{
|
||||
|
||||
$periods = Config::get('firefly.piggy_bank_periods');
|
||||
$accounts = ExpandedForm::makeSelectList(Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']));
|
||||
$accounts = ExpandedForm::makeSelectList(
|
||||
Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*'])
|
||||
);
|
||||
$subTitle = 'Create new piggy bank';
|
||||
$subTitleIcon = 'fa-plus';
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (Session::get('piggy-banks.create.fromStore') !== true) {
|
||||
Session::put('piggy-banks.create.url', URL::previous());
|
||||
}
|
||||
Session::forget('piggy-banks.create.fromStore');
|
||||
|
||||
return view('piggy-banks.create', compact('accounts', 'periods', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
@@ -78,7 +84,10 @@ class PiggyBankController extends Controller
|
||||
{
|
||||
$subTitle = 'Delete "' . e($piggyBank->name) . '"';
|
||||
|
||||
return view('piggy_banks.delete', compact('piggyBank', 'subTitle'));
|
||||
// put previous url in session
|
||||
Session::put('piggy-banks.delete.url', URL::previous());
|
||||
|
||||
return view('piggy-banks.delete', compact('piggyBank', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,9 +99,9 @@ class PiggyBankController extends Controller
|
||||
{
|
||||
|
||||
Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.');
|
||||
$this->_repository->destroy($piggyBank);
|
||||
$piggyBank->delete();
|
||||
|
||||
return Redirect::route('piggy_banks.index');
|
||||
return Redirect::to(Session::get('piggy-banks.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,7 +115,9 @@ class PiggyBankController extends Controller
|
||||
{
|
||||
|
||||
$periods = Config::get('firefly.piggy_bank_periods');
|
||||
$accounts = ExpandedForm::makeSelectList(Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']));
|
||||
$accounts = ExpandedForm::makeSelectList(
|
||||
Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*'])
|
||||
);
|
||||
$subTitle = 'Edit piggy bank "' . e($piggyBank->name) . '"';
|
||||
$subTitleIcon = 'fa-pencil';
|
||||
|
||||
@@ -124,21 +135,26 @@ class PiggyBankController extends Controller
|
||||
'targetamount' => $piggyBank->targetamount,
|
||||
'targetdate' => $targetDate,
|
||||
'reminder' => $piggyBank->reminder,
|
||||
'remind_me' => intval($piggyBank->remind_me) == 1 || !is_null($piggyBank->reminder) ? true : false
|
||||
'remind_me' => intval($piggyBank->remind_me) == 1 && !is_null($piggyBank->reminder) ? true : false
|
||||
];
|
||||
Session::flash('preFilled', $preFilled);
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (Session::get('piggy-banks.edit.fromUpdate') !== true) {
|
||||
Session::put('piggy-banks.edit.url', URL::previous());
|
||||
}
|
||||
Session::forget('piggy-banks.edit.fromUpdate');
|
||||
|
||||
return view('piggy-banks.edit', compact('subTitle', 'subTitleIcon', 'piggyBank', 'accounts', 'periods', 'preFilled'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function index(AccountRepositoryInterface $repository)
|
||||
{
|
||||
/** @var Collection $piggyBanks */
|
||||
$piggyBanks = Auth::user()->piggyBanks()->where('repeats', 0)->get();
|
||||
$piggyBanks = Auth::user()->piggyBanks()->orderBy('order', 'ASC')->get();
|
||||
|
||||
$accounts = [];
|
||||
/** @var PiggyBank $piggyBank */
|
||||
@@ -154,7 +170,7 @@ class PiggyBankController extends Controller
|
||||
if (!isset($accounts[$account->id])) {
|
||||
$accounts[$account->id] = [
|
||||
'name' => $account->name,
|
||||
'balance' => Steam::balance($account),
|
||||
'balance' => Steam::balance($account, null, true),
|
||||
'leftForPiggyBanks' => $repository->leftOnAccount($account),
|
||||
'sumOfSaved' => $piggyBank->savedSoFar,
|
||||
'sumOfTargets' => floatval($piggyBank->targetamount),
|
||||
@@ -170,6 +186,22 @@ class PiggyBankController extends Controller
|
||||
return view('piggy-banks.index', compact('piggyBanks', 'accounts'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow user to order piggy banks.
|
||||
*/
|
||||
public function order(PiggyBankRepositoryInterface $repository)
|
||||
{
|
||||
$data = Input::get('order');
|
||||
|
||||
// set all users piggy banks to zero:
|
||||
$repository->reset();
|
||||
|
||||
if (is_array($data)) {
|
||||
foreach ($data as $order => $id) {
|
||||
$repository->setOrder(intval($id), (intval($order) + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POST add money to piggy bank
|
||||
@@ -191,6 +223,9 @@ class PiggyBankController extends Controller
|
||||
$repetition->currentamount += $amount;
|
||||
$repetition->save();
|
||||
|
||||
// create event.
|
||||
PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount, 'piggy_bank_id' => $piggyBank->id]);
|
||||
|
||||
/*
|
||||
* Create event!
|
||||
*/
|
||||
@@ -220,6 +255,8 @@ class PiggyBankController extends Controller
|
||||
$repetition->currentamount -= $amount;
|
||||
$repetition->save();
|
||||
|
||||
PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount * -1, 'piggy_bank_id' => $piggyBank->id]);
|
||||
|
||||
/*
|
||||
* Create event!
|
||||
*/
|
||||
@@ -266,25 +303,36 @@ class PiggyBankController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBankFormRequest $request
|
||||
* @param PiggyBankRepositoryInterface $repository
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
|
||||
{
|
||||
$piggyBankData = [
|
||||
'repeats' => false,
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => new Carbon,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => floatval($request->get('targetamount')),
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
'reminder' => $request->get('reminder'),
|
||||
'remind_me' => $request->get('remind_me'),
|
||||
];
|
||||
|
||||
$piggyBank = $repository->store($piggyBankData);
|
||||
|
||||
Session::flash('success', 'Stored piggy bank "' . e($piggyBank->name) . '".');
|
||||
|
||||
return Redirect::route('piggy-banks.index');
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
Session::put('piggy-banks.create.fromStore', true);
|
||||
|
||||
return Redirect::route('piggy-banks.create')->withInput();
|
||||
}
|
||||
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('piggy-banks.create.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,23 +345,32 @@ class PiggyBankController extends Controller
|
||||
public function update(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request)
|
||||
{
|
||||
$piggyBankData = [
|
||||
'repeats' => false,
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => is_null($piggyBank->startdate) ? $piggyBank->created_at : $piggyBank->startdate,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => floatval($request->get('targetamount')),
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
'reminder' => $request->get('reminder'),
|
||||
'remind_me' => $request->get('remind_me')
|
||||
];
|
||||
|
||||
|
||||
$piggyBank = $repository->update($piggyBank, $piggyBankData);
|
||||
|
||||
Session::flash('success', 'Updated piggy bank "' . e($piggyBank->name) . '".');
|
||||
|
||||
return Redirect::route('piggy-banks.index');
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
Session::put('piggy-banks.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('piggy-banks.edit', $piggyBank->id);
|
||||
}
|
||||
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('piggy-banks.edit.url'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@@ -1,21 +1,19 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use View;
|
||||
use Auth;
|
||||
use Preferences;
|
||||
use Input;
|
||||
use Session;
|
||||
use Preferences;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class PreferencesController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class PreferencesController extends Controller {
|
||||
class PreferencesController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -32,7 +30,7 @@ class PreferencesController extends Controller {
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']);
|
||||
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
|
||||
$viewRange = Preferences::get('viewRange', '1M');
|
||||
$viewRangeValue = $viewRange->data;
|
||||
$frontPage = Preferences::get('frontPageAccounts', []);
|
||||
|
@@ -45,7 +45,7 @@ class ProfileController extends Controller
|
||||
|
||||
return Redirect::route('change-password');
|
||||
}
|
||||
$result = $this->_validatePassword($request->get('current_password'), $request->get('new_password'), $request->get('new_password_confirmation'));
|
||||
$result = $this->validatePassword($request->get('current_password'), $request->get('new_password'), $request->get('new_password_confirmation'));
|
||||
if (!($result === true)) {
|
||||
Session::flash('error', $result);
|
||||
|
||||
@@ -70,7 +70,7 @@ class ProfileController extends Controller
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
protected function _validatePassword($old, $new1, $new2)
|
||||
protected function validatePassword($old, $new1, $new2)
|
||||
{
|
||||
if (strlen($new1) == 0 || strlen($new2) == 0) {
|
||||
return 'Do fill in a password!';
|
||||
|
@@ -1,15 +1,15 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Amount;
|
||||
use Auth;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionGroup;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Response;
|
||||
use Input;
|
||||
use Redirect;
|
||||
use Response;
|
||||
use URL;
|
||||
|
||||
/**
|
||||
* Class RelatedController
|
||||
@@ -37,26 +37,42 @@ class RelatedController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
$unique = array_unique($ids);
|
||||
$unique = array_unique($ids);
|
||||
$journals = new Collection;
|
||||
if (count($unique) > 0) {
|
||||
|
||||
$set = Auth::user()->transactionjournals()->whereIn('id', $unique)->get();
|
||||
$set->each(
|
||||
function (TransactionJournal $journal) {
|
||||
/** @var Transaction $t */
|
||||
foreach ($journal->transactions()->get() as $t) {
|
||||
if ($t->amount > 0) {
|
||||
$journal->amount = $t->amount;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
return Response::json($set->toArray());
|
||||
} else {
|
||||
return Response::json((new Collection)->toArray());
|
||||
$journals = Auth::user()->transactionjournals()->whereIn('id', $unique)->get();
|
||||
}
|
||||
$parent = $journal;
|
||||
|
||||
return view('related.alreadyRelated', compact('parent', 'journals'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
|
||||
*
|
||||
* @param TransactionJournal $parentJournal
|
||||
* @param TransactionJournal $childJournal
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getRemoveRelation(TransactionJournal $parentJournal, TransactionJournal $childJournal)
|
||||
{
|
||||
$groups = $parentJournal->transactiongroups()->get();
|
||||
/** @var TransactionGroup $group */
|
||||
foreach ($groups as $group) {
|
||||
foreach ($group->transactionjournals()->get() as $loopJournal) {
|
||||
if ($loopJournal->id == $childJournal->id) {
|
||||
// remove from group:
|
||||
$group->transactionjournals()->detach($childJournal);
|
||||
}
|
||||
}
|
||||
if ($group->transactionjournals()->count() == 1) {
|
||||
$group->delete();
|
||||
}
|
||||
}
|
||||
|
||||
return Redirect::to(URL::previous());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,20 +153,12 @@ class RelatedController extends Controller
|
||||
{
|
||||
|
||||
$search = e(trim(Input::get('searchValue')));
|
||||
$parent = $journal;
|
||||
|
||||
$result = $repository->searchRelated($search, $journal);
|
||||
$result->each(
|
||||
function (TransactionJournal $journal) {
|
||||
/** @var Transaction $t */
|
||||
foreach ($journal->transactions()->get() as $t) {
|
||||
if ($t->amount > 0) {
|
||||
$journal->amount = $t->amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
$journals = $repository->searchRelated($search, $journal);
|
||||
|
||||
return view('related.searchResult', compact('journals', 'search', 'parent'));
|
||||
|
||||
return Response::json($result->toArray());
|
||||
}
|
||||
|
||||
}
|
||||
|
127
app/Http/Controllers/ReminderController.php
Normal file
127
app/Http/Controllers/ReminderController.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Reminders\ReminderHelperInterface;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use URL;
|
||||
|
||||
/**
|
||||
* Class ReminderController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class ReminderController extends Controller
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Reminder $reminder
|
||||
*/
|
||||
public function act(Reminder $reminder)
|
||||
{
|
||||
$data = [
|
||||
'description' => 'Money for piggy bank "' . $reminder->remindersable->name . '"',
|
||||
'amount' => round($reminder->metadata->perReminder, 2),
|
||||
'account_to_id' => $reminder->remindersable->account_id,
|
||||
'piggy_bank_id' => $reminder->remindersable_id,
|
||||
'reminder_id' => $reminder->id,
|
||||
];
|
||||
Session::flash('_old_input', $data);
|
||||
|
||||
return Redirect::route('transactions.create', 'transfer');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Reminder $reminder
|
||||
*/
|
||||
public function dismiss(Reminder $reminder)
|
||||
{
|
||||
$reminder->notnow = true;
|
||||
$reminder->save();
|
||||
|
||||
return Redirect::to(URL::previous());
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function index(ReminderHelperInterface $helper)
|
||||
{
|
||||
|
||||
$reminders = Auth::user()->reminders()->get();
|
||||
|
||||
$reminders->each(
|
||||
function (Reminder $reminder) use ($helper) {
|
||||
$reminder->description = $helper->getReminderText($reminder);
|
||||
}
|
||||
);
|
||||
|
||||
$today = new Carbon;
|
||||
// active reminders:
|
||||
$active = $reminders->filter(
|
||||
function (Reminder $reminder) use ($today) {
|
||||
if ($reminder->notnow === false && $reminder->active === true && $reminder->startdate <= $today && $reminder->enddate >= $today) {
|
||||
return $reminder;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// expired reminders:
|
||||
$expired = $reminders->filter(
|
||||
function (Reminder $reminder) use ($today) {
|
||||
if ($reminder->notnow === false && $reminder->active === true && $reminder->startdate > $today || $reminder->enddate < $today) {
|
||||
return $reminder;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// inactive reminders
|
||||
$inactive = $reminders->filter(
|
||||
function (Reminder $reminder) {
|
||||
if ($reminder->active === false) {
|
||||
return $reminder;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// dismissed reminders
|
||||
$dismissed = $reminders->filter(
|
||||
function (Reminder $reminder) {
|
||||
if ($reminder->notnow === true) {
|
||||
return $reminder;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$title = 'Reminders';
|
||||
$mainTitleIcon = 'fa-clock-o';
|
||||
|
||||
return view('reminders.index', compact('dismissed', 'expired', 'inactive', 'active', 'title', 'mainTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Reminder $reminder
|
||||
*/
|
||||
public function show(Reminder $reminder)
|
||||
{
|
||||
$title = 'Reminder';
|
||||
$mainTitleIcon = 'fa-clock-o';
|
||||
if ($reminder->notnow === true) {
|
||||
$subTitle = 'Dismissed reminder';
|
||||
} else {
|
||||
$subTitle = 'Reminder';
|
||||
}
|
||||
$subTitle .= ' for piggy bank "' . $reminder->remindersable->name . '"';
|
||||
|
||||
|
||||
return view('reminders.show', compact('reminder', 'title', 'subTitle', 'mainTitleIcon'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,199 +0,0 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Requests\PiggyBankFormRequest;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use Redirect;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class RepeatedExpenseController
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class RepeatedExpenseController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
View::share('title', 'Repeated expenses');
|
||||
View::share('mainTitleIcon', 'fa-rotate-left');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$periods = Config::get('firefly.piggy_bank_periods');
|
||||
$accounts = ExpandedForm::makeSelectList(Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']));
|
||||
|
||||
return view('repeatedExpense.create', compact('accounts', 'periods'))->with('subTitle', 'Create new repeated expense')->with(
|
||||
'subTitleIcon', 'fa-plus'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $repeatedExpense
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function delete(PiggyBank $repeatedExpense)
|
||||
{
|
||||
$subTitle = 'Delete "' . e($repeatedExpense->name) . '"';
|
||||
|
||||
return view('repeatedExpense.delete', compact('repeatedExpense', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $repeatedExpense
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy(PiggyBank $repeatedExpense)
|
||||
{
|
||||
|
||||
Session::flash('success', 'Repeated expense "' . e($repeatedExpense->name) . '" deleted.');
|
||||
|
||||
$repeatedExpense->delete();
|
||||
|
||||
return Redirect::route('repeated.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $repeatedExpense
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function edit(PiggyBank $repeatedExpense)
|
||||
{
|
||||
|
||||
$periods = Config::get('firefly.piggy_bank_periods');
|
||||
$accounts = ExpandedForm::makeSelectList(Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']));
|
||||
$subTitle = 'Edit repeated expense "' . e($repeatedExpense->name) . '"';
|
||||
$subTitleIcon = 'fa-pencil';
|
||||
|
||||
/*
|
||||
* Flash some data to fill the form.
|
||||
*/
|
||||
$preFilled = ['name' => $repeatedExpense->name,
|
||||
'account_id' => $repeatedExpense->account_id,
|
||||
'targetamount' => $repeatedExpense->targetamount,
|
||||
'reminder_skip' => $repeatedExpense->reminder_skip,
|
||||
'rep_every' => $repeatedExpense->rep_every,
|
||||
'rep_times' => $repeatedExpense->rep_times,
|
||||
'targetdate' => $repeatedExpense->targetdate->format('Y-m-d'),
|
||||
'reminder' => $repeatedExpense->reminder,
|
||||
'remind_me' => intval($repeatedExpense->remind_me) == 1 || !is_null($repeatedExpense->reminder) ? true : false
|
||||
];
|
||||
Session::flash('preFilled', $preFilled);
|
||||
|
||||
return view('repeatedExpense.edit', compact('subTitle', 'subTitleIcon', 'repeatedExpense', 'accounts', 'periods', 'preFilled'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
||||
$subTitle = 'Overview';
|
||||
|
||||
$expenses = Auth::user()->piggyBanks()->where('repeats', 1)->get();
|
||||
$expenses->each(
|
||||
function (PiggyBank $piggyBank) {
|
||||
$piggyBank->currentRelevantRep();
|
||||
}
|
||||
);
|
||||
|
||||
return view('repeatedExpense.index', compact('expenses', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $repeatedExpense
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function show(PiggyBank $repeatedExpense, PiggyBankRepositoryInterface $repository)
|
||||
{
|
||||
$subTitle = $repeatedExpense->name;
|
||||
$today = Carbon::now();
|
||||
$repetitions = $repeatedExpense->piggyBankRepetitions()->get();
|
||||
|
||||
$repetitions->each(
|
||||
function (PiggyBankRepetition $repetition) use ($repository) {
|
||||
$repetition->bars = $repository->calculateParts($repetition);
|
||||
}
|
||||
);
|
||||
|
||||
return view('repeatedExpense.show', compact('repetitions', 'repeatedExpense', 'today', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
|
||||
*/
|
||||
public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
|
||||
{
|
||||
|
||||
$piggyBankData = [
|
||||
'repeats' => true,
|
||||
'name' => $request->get('name'),
|
||||
'startdate' => new Carbon,
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => floatval($request->get('targetamount')),
|
||||
'targetdate' => new Carbon($request->get('targetdate')),
|
||||
'reminder' => $request->get('reminder'),
|
||||
'skip' => intval($request->get('skip')),
|
||||
'rep_every' => intval($request->get('rep_every')),
|
||||
'rep_times' => intval($request->get('rep_times')),
|
||||
];
|
||||
|
||||
$piggyBank = $repository->store($piggyBankData);
|
||||
|
||||
Session::flash('success', 'Stored repeated expense "' . e($piggyBank->name) . '".');
|
||||
|
||||
return Redirect::route('repeated.index');
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
|
||||
*
|
||||
* @param PiggyBank $repeatedExpense
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function update(PiggyBank $repeatedExpense, PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
|
||||
{
|
||||
$piggyBankData = [
|
||||
'repeats' => false,
|
||||
'name' => $request->get('name'),
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'targetamount' => floatval($request->get('targetamount')),
|
||||
'targetdate' => strlen($request->get('targetdate')) > 0 ? new Carbon($request->get('targetdate')) : null,
|
||||
'rep_length' => $request->get('rep_length'),
|
||||
'rep_every' => intval($request->get('rep_every')),
|
||||
'rep_times' => intval($request->get('rep_times')),
|
||||
'remind_me' => intval($request->get('remind_me')) == 1 ? true : false ,
|
||||
'reminder' => $request->get('reminder'),
|
||||
];
|
||||
|
||||
|
||||
$piggyBank = $repository->update($repeatedExpense, $piggyBankData);
|
||||
|
||||
Session::flash('success', 'Updated repeated expense "' . e($piggyBank->name) . '".');
|
||||
|
||||
return Redirect::route('repeated.index');
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,13 +1,14 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use FireflyIII\Helpers\Report\ReportHelperInterface;
|
||||
use FireflyIII\Helpers\Report\ReportQueryInterface;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Models\Account;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Preferences;
|
||||
use Session;
|
||||
use Steam;
|
||||
use View;
|
||||
|
||||
@@ -19,11 +20,20 @@ use View;
|
||||
class ReportController extends Controller
|
||||
{
|
||||
|
||||
/** @var ReportHelperInterface */
|
||||
protected $helper;
|
||||
/** @var ReportQueryInterface */
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ReportHelperInterface $helper
|
||||
* @param ReportQueryInterface $query
|
||||
*/
|
||||
public function __construct()
|
||||
public function __construct(ReportHelperInterface $helper, ReportQueryInterface $query)
|
||||
{
|
||||
$this->query = $query;
|
||||
$this->helper = $helper;
|
||||
|
||||
View::share('title', 'Reports');
|
||||
View::share('mainTitleIcon', 'fa-line-chart');
|
||||
|
||||
@@ -35,7 +45,7 @@ class ReportController extends Controller
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function budget($year = '2014', $month = '1', ReportQueryInterface $query)
|
||||
public function budget($year = '2014', $month = '1')
|
||||
{
|
||||
try {
|
||||
new Carbon($year . '-' . $month . '-01');
|
||||
@@ -49,62 +59,49 @@ class ReportController extends Controller
|
||||
$end->endOfMonth();
|
||||
$start->subDay();
|
||||
|
||||
/** @var Preference $pref */
|
||||
$pref = Preferences::get('showSharedReports', false);
|
||||
$showSharedReports = $pref->data;
|
||||
|
||||
|
||||
$dayEarly = clone $date;
|
||||
$subTitle = 'Budget report for ' . $date->format('F Y');
|
||||
$subTitleIcon = 'fa-calendar';
|
||||
$dayEarly = $dayEarly->subDay();
|
||||
$accounts = $query->getAllAccounts($start, $end);
|
||||
$accounts = $this->query->getAllAccounts($start, $end, $showSharedReports);
|
||||
$start->addDay();
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($start, $end, $query) {
|
||||
$budgets = $query->getBudgetSummary($account, $start, $end);
|
||||
$balancedAmount = $query->balancedTransactionsList($account, $start, $end);
|
||||
function (Account $account) use ($start, $end) {
|
||||
$budgets = $this->query->getBudgetSummary($account, $start, $end);
|
||||
$balancedAmount = $this->query->balancedTransactionsSum($account, $start, $end);
|
||||
$array = [];
|
||||
$hide = true;
|
||||
foreach ($budgets as $budget) {
|
||||
$id = intval($budget->id);
|
||||
$data = $budget->toArray();
|
||||
$array[$id] = $data;
|
||||
if (floatval($data['queryAmount']) != 0) {
|
||||
$hide = false;
|
||||
}
|
||||
}
|
||||
|
||||
$account->hide = $hide;
|
||||
$account->budgetInformation = $array;
|
||||
$account->balancedAmount = $balancedAmount;
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
$start = clone $date;
|
||||
$start->startOfMonth();
|
||||
|
||||
/**
|
||||
* Start getBudgetsForMonth DONE
|
||||
*/
|
||||
$set = Auth::user()->budgets()->orderBy('budgets.name', 'ASC')
|
||||
->leftJoin(
|
||||
'budget_limits', function (JoinClause $join) use ($date) {
|
||||
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
|
||||
}
|
||||
)
|
||||
->get(['budgets.*', 'budget_limits.amount as amount']);
|
||||
$budgets = Steam::makeArray($set);
|
||||
$amountSet = $query->journalsByBudget($start, $end);
|
||||
$amounts = Steam::makeArray($amountSet);
|
||||
$budgets = Steam::mergeArrays($budgets, $amounts);
|
||||
$budgets[0]['spent'] = isset($budgets[0]['spent']) ? $budgets[0]['spent'] : 0.0;
|
||||
$budgets[0]['amount'] = isset($budgets[0]['amount']) ? $budgets[0]['amount'] : 0.0;
|
||||
$budgets[0]['name'] = 'No budget';
|
||||
|
||||
// find transactions to shared expense accounts, which are without a budget by default:
|
||||
$transfers = $query->sharedExpenses($start, $end);
|
||||
foreach ($transfers as $transfer) {
|
||||
$budgets[0]['spent'] += floatval($transfer->amount) * -1;
|
||||
}
|
||||
$budgets = $this->helper->getBudgetsForMonth($date, $showSharedReports);
|
||||
|
||||
/**
|
||||
* End getBudgetsForMonth DONE
|
||||
*/
|
||||
|
||||
return view('reports.budget', compact('subTitle', 'subTitleIcon', 'date', 'accounts', 'budgets', 'dayEarly'));
|
||||
return view('reports.budget', compact('subTitle', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets', 'dayEarly'));
|
||||
|
||||
}
|
||||
|
||||
@@ -113,24 +110,105 @@ class ReportController extends Controller
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index(ReportHelperInterface $helper)
|
||||
public function index()
|
||||
{
|
||||
$start = $helper->firstDate();
|
||||
$months = $helper->listOfMonths($start);
|
||||
$years = $helper->listOfYears($start);
|
||||
$start = Session::get('first');
|
||||
$months = $this->helper->listOfMonths($start);
|
||||
$years = $this->helper->listOfYears($start);
|
||||
$title = 'Reports';
|
||||
$mainTitleIcon = 'fa-line-chart';
|
||||
|
||||
return view('reports.index', compact('years', 'months', 'title', 'mainTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param string $year
|
||||
* @param string $month
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function modalBalancedTransfers(Account $account, $year = '2014', $month = '1')
|
||||
{
|
||||
|
||||
try {
|
||||
new Carbon($year . '-' . $month . '-01');
|
||||
} catch (Exception $e) {
|
||||
return view('error')->with('message', 'Invalid date');
|
||||
}
|
||||
$start = new Carbon($year . '-' . $month . '-01');
|
||||
$end = clone $start;
|
||||
$end->endOfMonth();
|
||||
|
||||
$journals = $this->query->balancedTransactionsList($account, $start, $end);
|
||||
|
||||
return view('reports.modal-journal-list', compact('journals'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param string $year
|
||||
* @param string $month
|
||||
* @param ReportQueryInterface $query
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function modalLeftUnbalanced(Account $account, $year = '2014', $month = '1')
|
||||
{
|
||||
try {
|
||||
new Carbon($year . '-' . $month . '-01');
|
||||
} catch (Exception $e) {
|
||||
return view('error')->with('message', 'Invalid date');
|
||||
}
|
||||
$start = new Carbon($year . '-' . $month . '-01');
|
||||
$end = clone $start;
|
||||
$end->endOfMonth();
|
||||
$set = $this->query->getTransactionsWithoutBudget($account, $start, $end);
|
||||
|
||||
$journals = $set->filter(
|
||||
function (TransactionJournal $journal) {
|
||||
$count = $journal->transactiongroups()->where('relation', 'balance')->count();
|
||||
if ($count == 0) {
|
||||
return $journal;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return view('reports.modal-journal-list', compact('journals'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param string $year
|
||||
* @param string $month
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function modalNoBudget(Account $account, $year = '2014', $month = '1')
|
||||
{
|
||||
try {
|
||||
new Carbon($year . '-' . $month . '-01');
|
||||
} catch (Exception $e) {
|
||||
return view('error')->with('message', 'Invalid date');
|
||||
}
|
||||
$start = new Carbon($year . '-' . $month . '-01');
|
||||
$end = clone $start;
|
||||
$end->endOfMonth();
|
||||
$journals = $this->query->getTransactionsWithoutBudget($account, $start, $end);
|
||||
|
||||
return view('reports.modal-journal-list', compact('journals'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $year
|
||||
* @param string $month
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function month($year = '2014', $month = '1', ReportQueryInterface $query)
|
||||
public function month($year = '2014', $month = '1')
|
||||
{
|
||||
try {
|
||||
new Carbon($year . '-' . $month . '-01');
|
||||
@@ -141,6 +219,9 @@ class ReportController extends Controller
|
||||
$subTitle = 'Report for ' . $date->format('F Y');
|
||||
$subTitleIcon = 'fa-calendar';
|
||||
$displaySum = true; // to show sums in report.
|
||||
/** @var Preference $pref */
|
||||
$pref = Preferences::get('showSharedReports', false);
|
||||
$showSharedReports = $pref->data;
|
||||
|
||||
|
||||
/**
|
||||
@@ -157,14 +238,15 @@ class ReportController extends Controller
|
||||
/**
|
||||
* Start getIncomeForMonth DONE
|
||||
*/
|
||||
$income = $query->incomeByPeriod($start, $end);
|
||||
$income = $this->query->incomeByPeriod($start, $end, $showSharedReports);
|
||||
/**
|
||||
* End getIncomeForMonth DONE
|
||||
*/
|
||||
/**
|
||||
* Start getExpenseGroupedForMonth DONE
|
||||
*/
|
||||
$set = $query->journalsByExpenseAccount($start, $end);
|
||||
$set = $this->query->journalsByExpenseAccount($start, $end, $showSharedReports);
|
||||
|
||||
$expenses = Steam::makeArray($set);
|
||||
$expenses = Steam::sortArray($expenses);
|
||||
$expenses = Steam::limitArray($expenses, 10);
|
||||
@@ -174,26 +256,7 @@ class ReportController extends Controller
|
||||
/**
|
||||
* Start getBudgetsForMonth DONE
|
||||
*/
|
||||
$set = Auth::user()->budgets()
|
||||
->leftJoin(
|
||||
'budget_limits', function (JoinClause $join) use ($date) {
|
||||
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
|
||||
}
|
||||
)
|
||||
->get(['budgets.*', 'budget_limits.amount as amount']);
|
||||
$budgets = Steam::makeArray($set);
|
||||
$amountSet = $query->journalsByBudget($start, $end);
|
||||
$amounts = Steam::makeArray($amountSet);
|
||||
$budgets = Steam::mergeArrays($budgets, $amounts);
|
||||
$budgets[0]['spent'] = isset($budgets[0]['spent']) ? $budgets[0]['spent'] : 0.0;
|
||||
$budgets[0]['amount'] = isset($budgets[0]['amount']) ? $budgets[0]['amount'] : 0.0;
|
||||
$budgets[0]['name'] = 'No budget';
|
||||
|
||||
// find transactions to shared expense accounts, which are without a budget by default:
|
||||
$transfers = $query->sharedExpenses($start, $end);
|
||||
foreach ($transfers as $transfer) {
|
||||
$budgets[0]['spent'] += floatval($transfer->amount) * -1;
|
||||
}
|
||||
$budgets = $this->helper->getBudgetsForMonth($date, $showSharedReports);
|
||||
|
||||
/**
|
||||
* End getBudgetsForMonth DONE
|
||||
@@ -202,13 +265,19 @@ class ReportController extends Controller
|
||||
* Start getCategoriesForMonth DONE
|
||||
*/
|
||||
// all categories.
|
||||
$result = $query->journalsByCategory($start, $end);
|
||||
$result = $this->query->journalsByCategory($start, $end);
|
||||
$categories = Steam::makeArray($result);
|
||||
|
||||
|
||||
// all transfers
|
||||
$result = $query->sharedExpensesByCategory($start, $end);
|
||||
$transfers = Steam::makeArray($result);
|
||||
$merged = Steam::mergeArrays($categories, $transfers);
|
||||
if ($showSharedReports === false) {
|
||||
$result = $this->query->sharedExpensesByCategory($start, $end);
|
||||
$transfers = Steam::makeArray($result);
|
||||
$merged = Steam::mergeArrays($categories, $transfers);
|
||||
} else {
|
||||
$merged = $categories;
|
||||
}
|
||||
|
||||
|
||||
// sort.
|
||||
$sorted = Steam::sortNegativeArray($merged);
|
||||
@@ -221,7 +290,7 @@ class ReportController extends Controller
|
||||
/**
|
||||
* Start getAccountsForMonth
|
||||
*/
|
||||
$list = $query->accountList();
|
||||
$list = $this->query->accountList($showSharedReports);
|
||||
$accounts = [];
|
||||
/** @var Account $account */
|
||||
foreach ($list as $account) {
|
||||
@@ -255,25 +324,26 @@ class ReportController extends Controller
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function year($year, ReportHelperInterface $helper, ReportQueryInterface $query)
|
||||
public function year($year)
|
||||
{
|
||||
try {
|
||||
new Carbon('01-01-' . $year);
|
||||
} catch (Exception $e) {
|
||||
return view('error')->with('message', 'Invalid date.');
|
||||
}
|
||||
$date = new Carbon('01-01-' . $year);
|
||||
$end = clone $date;
|
||||
/** @var Preference $pref */
|
||||
$pref = Preferences::get('showSharedReports', false);
|
||||
$showSharedReports = $pref->data;
|
||||
$date = new Carbon('01-01-' . $year);
|
||||
$end = clone $date;
|
||||
$end->endOfYear();
|
||||
$title = 'Reports';
|
||||
$subTitle = $year;
|
||||
$subTitleIcon = 'fa-bar-chart';
|
||||
$mainTitleIcon = 'fa-line-chart';
|
||||
$balances = $helper->yearBalanceReport($date);
|
||||
$groupedIncomes = $query->journalsByRevenueAccount($date, $end);
|
||||
$groupedExpenses = $query->journalsByExpenseAccount($date, $end);
|
||||
|
||||
//$groupedExpenses = $helper-> expensesGroupedByAccount($date, $end, 15);
|
||||
$balances = $this->helper->yearBalanceReport($date, $showSharedReports);
|
||||
$groupedIncomes = $this->query->journalsByRevenueAccount($date, $end, $showSharedReports);
|
||||
$groupedExpenses = $this->query->journalsByExpenseAccount($date, $end, $showSharedReports);
|
||||
|
||||
return view(
|
||||
'reports.year', compact('date', 'groupedIncomes', 'groupedExpenses', 'year', 'balances', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon')
|
||||
|
@@ -1,10 +1,6 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
|
||||
use FireflyIII\Support\Search\SearchInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Input;
|
||||
|
||||
/**
|
||||
@@ -12,7 +8,8 @@ use Input;
|
||||
*
|
||||
* @package FireflyIII\Http\Controllers
|
||||
*/
|
||||
class SearchController extends Controller {
|
||||
class SearchController extends Controller
|
||||
{
|
||||
/**
|
||||
* Results always come in the form of an array [results, count, fullCount]
|
||||
*/
|
||||
|
@@ -1,21 +1,22 @@
|
||||
<?php namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Events\JournalCreated;
|
||||
use FireflyIII\Events\JournalSaved;
|
||||
use FireflyIII\Http\Requests;
|
||||
use FireflyIII\Http\Requests\JournalFormRequest;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Input;
|
||||
use Redirect;
|
||||
use Response;
|
||||
use Session;
|
||||
use URL;
|
||||
use View;
|
||||
|
||||
|
||||
/**
|
||||
* Class TransactionController
|
||||
*
|
||||
@@ -41,7 +42,9 @@ class TransactionController extends Controller
|
||||
public function create($what = 'deposit')
|
||||
{
|
||||
$accounts = ExpandedForm::makeSelectList(
|
||||
Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->where('active', 1)->orderBy('name', 'DESC')->get(['accounts.*'])
|
||||
Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->orderBy('name', 'ASC')->where(
|
||||
'active', 1
|
||||
)->orderBy('name', 'DESC')->get(['accounts.*'])
|
||||
);
|
||||
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
|
||||
$budgets[0] = '(no budget)';
|
||||
@@ -58,6 +61,12 @@ class TransactionController extends Controller
|
||||
}
|
||||
Session::put('preFilled', $preFilled);
|
||||
|
||||
// put previous url in session if not redirect from store (not "create another").
|
||||
if (Session::get('transactions.create.fromStore') !== true) {
|
||||
Session::put('transactions.create.url', URL::previous());
|
||||
}
|
||||
Session::forget('transactions.create.fromStore');
|
||||
|
||||
asort($piggies);
|
||||
|
||||
|
||||
@@ -76,7 +85,10 @@ class TransactionController extends Controller
|
||||
$type = strtolower($journal->transactionType->type);
|
||||
$subTitle = 'Delete ' . e($type) . ' "' . e($journal->description) . '"';
|
||||
|
||||
return View::make('transactions.delete', compact('journal', 'subTitle'));
|
||||
// put previous url in session
|
||||
Session::put('transactions.delete.url', URL::previous());
|
||||
|
||||
return view('transactions.delete', compact('journal', 'subTitle'));
|
||||
|
||||
|
||||
}
|
||||
@@ -88,23 +100,12 @@ class TransactionController extends Controller
|
||||
*/
|
||||
public function destroy(TransactionJournal $transactionJournal)
|
||||
{
|
||||
$type = $transactionJournal->transactionType->type;
|
||||
$return = 'withdrawal';
|
||||
|
||||
Session::flash('success', 'Transaction "' . e($transactionJournal->description) . '" destroyed.');
|
||||
|
||||
$transactionJournal->delete();
|
||||
|
||||
switch ($type) {
|
||||
case 'Deposit':
|
||||
$return = 'deposit';
|
||||
break;
|
||||
case 'Transfer':
|
||||
$return = 'transfers';
|
||||
break;
|
||||
}
|
||||
|
||||
return Redirect::route('transactions.index', $return);
|
||||
// redirect to previous URL:
|
||||
return Redirect::to(Session::get('transactions.delete.url'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +119,9 @@ class TransactionController extends Controller
|
||||
{
|
||||
$what = strtolower($journal->transactiontype->type);
|
||||
$accounts = ExpandedForm::makeSelectList(
|
||||
Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->where('active', 1)->orderBy('name', 'DESC')->get(['accounts.*'])
|
||||
Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->where('active', 1)->orderBy(
|
||||
'name', 'DESC'
|
||||
)->get(['accounts.*'])
|
||||
);
|
||||
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
|
||||
$budgets[0] = '(no budget)';
|
||||
@@ -143,22 +146,22 @@ class TransactionController extends Controller
|
||||
}
|
||||
|
||||
if ($journal->piggyBankEvents()->count() > 0) {
|
||||
$preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->first()->piggy_bank_id;
|
||||
$preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id;
|
||||
}
|
||||
|
||||
$preFilled['amount'] = 0;
|
||||
/** @var Transaction $t */
|
||||
foreach ($transactions as $t) {
|
||||
if (floatval($t->amount) > 0) {
|
||||
$preFilled['amount'] = floatval($t->amount);
|
||||
}
|
||||
}
|
||||
$preFilled['amount'] = $journal->amount;
|
||||
$preFilled['account_id'] = $repository->getAssetAccount($journal);
|
||||
$preFilled['expense_account'] = $transactions[0]->account->name;
|
||||
$preFilled['revenue_account'] = $transactions[1]->account->name;
|
||||
$preFilled['account_from_id'] = $transactions[1]->account->id;
|
||||
$preFilled['account_to_id'] = $transactions[0]->account->id;
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (Session::get('transactions.edit.fromUpdate') !== true) {
|
||||
Session::put('transactions.edit.url', URL::previous());
|
||||
}
|
||||
Session::forget('transactions.edit.fromUpdate');
|
||||
|
||||
|
||||
return View::make('transactions.edit', compact('journal', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled);
|
||||
}
|
||||
@@ -175,31 +178,32 @@ class TransactionController extends Controller
|
||||
case 'withdrawal':
|
||||
$subTitleIcon = 'fa-long-arrow-left';
|
||||
$subTitle = 'Expenses';
|
||||
//$journals = $this->_repository->getWithdrawalsPaginated(50);
|
||||
$types = ['Withdrawal'];
|
||||
$types = ['Withdrawal'];
|
||||
break;
|
||||
case 'revenue':
|
||||
case 'deposit':
|
||||
$subTitleIcon = 'fa-long-arrow-right';
|
||||
$subTitle = 'Revenue, income and deposits';
|
||||
// $journals = $this->_repository->getDepositsPaginated(50);
|
||||
$types = ['Deposit'];
|
||||
$types = ['Deposit'];
|
||||
break;
|
||||
case 'transfer':
|
||||
case 'transfers':
|
||||
$subTitleIcon = 'fa-arrows-h';
|
||||
$subTitleIcon = 'fa-exchange';
|
||||
$subTitle = 'Transfers';
|
||||
//$journals = $this->_repository->getTransfersPaginated(50);
|
||||
$types = ['Transfer'];
|
||||
$types = ['Transfer'];
|
||||
break;
|
||||
}
|
||||
|
||||
$page = intval(\Input::get('page'));
|
||||
$offset = $page > 0 ? ($page - 1) * 50 : 0;
|
||||
|
||||
$set = Auth::user()->transactionJournals()->transactionTypes($types)->withRelevantData()->take(50)->offset($offset)->orderBy('date', 'DESC')->get(
|
||||
['transaction_journals.*']
|
||||
);
|
||||
$set = Auth::user()->transactionJournals()->transactionTypes($types)->withRelevantData()->take(50)->offset($offset)
|
||||
->orderBy('date', 'DESC')
|
||||
->orderBy('order', 'ASC')
|
||||
->orderBy('id', 'DESC')
|
||||
->get(
|
||||
['transaction_journals.*']
|
||||
);
|
||||
$count = Auth::user()->transactionJournals()->transactionTypes($types)->count();
|
||||
$journals = new LengthAwarePaginator($set, $count, 50, $page);
|
||||
$journals->setPath('transactions/' . $what);
|
||||
@@ -208,6 +212,28 @@ class TransactionController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorder transactions (which all must have the same date)
|
||||
*/
|
||||
public function reorder()
|
||||
{
|
||||
$ids = Input::get('items');
|
||||
if (count($ids) > 0) {
|
||||
$order = 0;
|
||||
foreach ($ids as $id) {
|
||||
$journal = Auth::user()->transactionjournals()->where('id', $id)->where('date', Input::get('date'))->first();
|
||||
if ($journal) {
|
||||
$journal->order = $order;
|
||||
$order++;
|
||||
$journal->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Response::json(true);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
@@ -220,53 +246,56 @@ class TransactionController extends Controller
|
||||
$t->before = floatval(
|
||||
$t->account->transactions()->leftJoin(
|
||||
'transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id'
|
||||
)->where('transaction_journals.date', '<=', $journal->date->format('Y-m-d'))->where(
|
||||
'transaction_journals.created_at', '<=', $journal->created_at->format('Y-m-d H:i:s')
|
||||
)->where('transaction_journals.id', '!=', $journal->id)->sum('transactions.amount')
|
||||
)
|
||||
->where('transaction_journals.date', '<=', $journal->date->format('Y-m-d'))
|
||||
->where('transaction_journals.order', '>=', $journal->order)
|
||||
->where('transaction_journals.id', '!=', $journal->id)
|
||||
->sum('transactions.amount')
|
||||
);
|
||||
$t->after = $t->before + $t->amount;
|
||||
}
|
||||
);
|
||||
$members = new Collection;
|
||||
/** @var TransactionGroup $group */
|
||||
foreach ($journal->transactiongroups()->get() as $group) {
|
||||
/** @var TransactionJournal $loopJournal */
|
||||
foreach ($group->transactionjournals()->get() as $loopJournal) {
|
||||
if ($loopJournal->id != $journal->id) {
|
||||
$members->push($loopJournal);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return view('transactions.show', compact('journal', 'members'))->with(
|
||||
|
||||
return view('transactions.show', compact('journal'))->with(
|
||||
'subTitle', e($journal->transactiontype->type) . ' "' . e($journal->description) . '"'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param JournalFormRequest $request
|
||||
* @param JournalRepositoryInterface $repository
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(JournalFormRequest $request, JournalRepositoryInterface $repository)
|
||||
{
|
||||
|
||||
$journalData = [
|
||||
'what' => $request->get('what'),
|
||||
'description' => $request->get('description'),
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'account_from_id' => intval($request->get('account_from_id')),
|
||||
'account_to_id' => intval($request->get('account_to_id')),
|
||||
'expense_account' => $request->get('expense_account'),
|
||||
'revenue_account' => $request->get('revenue_account'),
|
||||
'amount' => floatval($request->get('amount')),
|
||||
'user' => Auth::user()->id,
|
||||
'amount_currency_id' => intval($request->get('amount_currency_id')),
|
||||
'date' => new Carbon($request->get('date')),
|
||||
'budget_id' => intval($request->get('budget_id')),
|
||||
'category' => $request->get('category'),
|
||||
];
|
||||
$journalData = $request->getJournalData();
|
||||
$journal = $repository->store($journalData);
|
||||
|
||||
$journal = $repository->store($journalData);
|
||||
// rescan journal, UpdateJournalConnection
|
||||
event(new JournalSaved($journal));
|
||||
// ConnectJournalToPiggyBank
|
||||
event(new JournalCreated($journal, intval($request->get('piggy_bank_id'))));
|
||||
|
||||
if (intval($request->get('reminder_id')) > 0) {
|
||||
$reminder = Auth::user()->reminders()->find($request->get('reminder_id'));
|
||||
$reminder->active = 0;
|
||||
$reminder->save();
|
||||
}
|
||||
|
||||
Session::flash('success', 'New transaction "' . $journal->description . '" stored!');
|
||||
|
||||
return Redirect::route('transactions.index', $request->input('what'));
|
||||
if (intval(Input::get('create_another')) === 1) {
|
||||
// set value so create routine will not overwrite URL:
|
||||
Session::put('transactions.create.fromStore', true);
|
||||
|
||||
return Redirect::route('transactions.create', $request->input('what'))->withInput();
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('transactions.create.url'));
|
||||
|
||||
}
|
||||
|
||||
@@ -276,31 +305,27 @@ class TransactionController extends Controller
|
||||
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
|
||||
*
|
||||
* @return $this
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function update(TransactionJournal $journal, JournalFormRequest $request, JournalRepositoryInterface $repository)
|
||||
{
|
||||
|
||||
$journalData = [
|
||||
'what' => $request->get('what'),
|
||||
'description' => $request->get('description'),
|
||||
'account_id' => intval($request->get('account_id')),
|
||||
'account_from_id' => intval($request->get('account_from_id')),
|
||||
'account_to_id' => intval($request->get('account_to_id')),
|
||||
'expense_account' => $request->get('expense_account'),
|
||||
'revenue_account' => $request->get('revenue_account'),
|
||||
'amount' => floatval($request->get('amount')),
|
||||
'user' => Auth::user()->id,
|
||||
'amount_currency_id' => intval($request->get('amount_currency_id')),
|
||||
'date' => new Carbon($request->get('date')),
|
||||
'budget_id' => intval($request->get('budget_id')),
|
||||
'category' => $request->get('category'),
|
||||
];
|
||||
|
||||
$journalData = $request->getJournalData();
|
||||
$repository->update($journal, $journalData);
|
||||
|
||||
event(new JournalSaved($journal));
|
||||
// update, get events by date and sort DESC
|
||||
|
||||
Session::flash('success', 'Transaction "' . e($journalData['description']) . '" updated.');
|
||||
|
||||
return Redirect::route('transactions.index', $journalData['what']);
|
||||
if (intval(Input::get('return_to_edit')) === 1) {
|
||||
// set value so edit routine will not overwrite URL:
|
||||
Session::put('transactions.edit.fromUpdate', true);
|
||||
|
||||
return Redirect::route('transactions.edit', $journal->id)->withInput(['return_to_edit' => 1]);
|
||||
}
|
||||
|
||||
// redirect to previous URL.
|
||||
return Redirect::to(Session::get('transactions.edit.url'));
|
||||
|
||||
}
|
||||
|
||||
|
@@ -22,6 +22,7 @@ class Kernel extends HttpKernel
|
||||
'Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse',
|
||||
'Illuminate\Session\Middleware\StartSession',
|
||||
'Illuminate\View\Middleware\ShareErrorsFromSession',
|
||||
'FireflyIII\Http\Middleware\ReplaceTestVars',
|
||||
'FireflyIII\Http\Middleware\VerifyCsrfToken',
|
||||
];
|
||||
|
||||
@@ -36,6 +37,9 @@ class Kernel extends HttpKernel
|
||||
'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
|
||||
'guest' => 'FireflyIII\Http\Middleware\RedirectIfAuthenticated',
|
||||
'range' => 'FireflyIII\Http\Middleware\Range',
|
||||
'reminders' => 'FireflyIII\Http\Middleware\Reminders',
|
||||
'piggybanks' => 'FireflyIII\Http\Middleware\PiggyBanks',
|
||||
|
||||
];
|
||||
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Class Authenticate
|
||||
@@ -37,7 +38,7 @@ class Authenticate
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ($this->auth->guest()) {
|
||||
if ($request->ajax()) {
|
||||
|
72
app/Http/Middleware/PiggyBanks.php
Normal file
72
app/Http/Middleware/PiggyBanks.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Http\Middleware;
|
||||
|
||||
|
||||
use App;
|
||||
use Closure;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class PiggyBanks
|
||||
*
|
||||
* @package FireflyIII\Http\Middleware
|
||||
*/
|
||||
class PiggyBanks
|
||||
{
|
||||
/**
|
||||
* The Guard implementation.
|
||||
*
|
||||
* @var Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new filter instance.
|
||||
*
|
||||
* @param Guard $auth
|
||||
*
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ($this->auth->check() && !$request->isXmlHttpRequest() && App::environment() != 'testing') {
|
||||
// get piggy banks without a repetition:
|
||||
/** @var Collection $set */
|
||||
$set = $this->auth->user()->piggybanks()
|
||||
->leftJoin('piggy_bank_repetitions', 'piggy_banks.id', '=', 'piggy_bank_repetitions.piggy_bank_id')
|
||||
->whereNull('piggy_bank_repetitions.id')
|
||||
->get(['piggy_banks.id', 'piggy_banks.startdate', 'piggy_banks.targetdate']);
|
||||
if ($set->count() > 0) {
|
||||
/** @var PiggyBank $partialPiggy */
|
||||
foreach ($set as $partialPiggy) {
|
||||
$repetition = new PiggyBankRepetition;
|
||||
$repetition->piggyBank()->associate($partialPiggy);
|
||||
$repetition->startdate = is_null($partialPiggy->startdate) ? null : $partialPiggy->startdate;
|
||||
$repetition->targetdate = is_null($partialPiggy->targetdate) ? null : $partialPiggy->targetdate;
|
||||
$repetition->currentamount = 0;
|
||||
$repetition->save();
|
||||
}
|
||||
}
|
||||
unset($partialPiggy, $set, $repetition);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
@@ -3,12 +3,15 @@
|
||||
|
||||
namespace FireflyIII\Http\Middleware;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\Request;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class SessionFilter
|
||||
@@ -43,28 +46,44 @@ class Range
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $theNext)
|
||||
public function handle(Request $request, Closure $theNext)
|
||||
{
|
||||
if ($this->auth->check()) {
|
||||
// user's view range comes from preferences, gets set in session:
|
||||
/** @var \FireflyIII\Models\Preference $viewRange */
|
||||
$viewRange = Preferences::get('viewRange', '1M');
|
||||
if ($this->auth->check() && App::environment() != 'testing') {
|
||||
|
||||
// ignore preference. set the range to be the current month:
|
||||
if (!Session::has('start') && !Session::has('end')) {
|
||||
|
||||
// the start and end date are checked and stored:
|
||||
$start = Session::has('start') ? Session::get('start') : new Carbon;
|
||||
$start = Navigation::updateStartDate($viewRange->data, $start);
|
||||
$end = Navigation::updateEndDate($viewRange->data, $start);
|
||||
$period = Navigation::periodName($viewRange->data, $start);
|
||||
$prev = Navigation::jumpToPrevious($viewRange->data, clone $start);
|
||||
$next = Navigation::jumpToNext($viewRange->data, clone $start);
|
||||
/** @var \FireflyIII\Models\Preference $viewRange */
|
||||
$viewRange = Preferences::get('viewRange', '1M');
|
||||
$start = new Carbon;
|
||||
$start = Navigation::updateStartDate($viewRange->data, $start);
|
||||
$end = Navigation::updateEndDate($viewRange->data, $start);
|
||||
|
||||
Session::put('start', $start);
|
||||
Session::put('end', $end);
|
||||
}
|
||||
if (!Session::has('first')) {
|
||||
/**
|
||||
* Get helper thing.
|
||||
*/
|
||||
/** @var \FireflyIII\Repositories\Journal\JournalRepositoryInterface $repository */
|
||||
$repository = App::make('FireflyIII\Repositories\Journal\JournalRepositoryInterface');
|
||||
$journal = $repository->first();
|
||||
if ($journal) {
|
||||
Session::put('first', $journal->date);
|
||||
} else {
|
||||
Session::put('first', Carbon::now()->startOfYear());
|
||||
}
|
||||
}
|
||||
|
||||
// set current / next / prev month.
|
||||
$current = Carbon::now()->format('F Y');
|
||||
$next = Carbon::now()->endOfMonth()->addDay()->format('F Y');
|
||||
$prev = Carbon::now()->startOfMonth()->subDay()->format('F Y');
|
||||
View::share('currentMonthName', $current);
|
||||
View::share('previousMonthName', $prev);
|
||||
View::share('nextMonthName', $next);
|
||||
|
||||
Session::put('range', $viewRange->data);
|
||||
Session::put('start', $start);
|
||||
Session::put('end', $end);
|
||||
Session::put('period', $period);
|
||||
Session::put('prev', Navigation::periodName($viewRange->data, $prev));
|
||||
Session::put('next', Navigation::periodName($viewRange->data, $next));
|
||||
|
||||
}
|
||||
|
||||
@@ -72,4 +91,4 @@ class Range
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* Class RedirectIfAuthenticated
|
||||
@@ -38,7 +39,7 @@ class RedirectIfAuthenticated
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle($request, Closure $next)
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ($this->auth->check()) {
|
||||
return new RedirectResponse(url('/'));
|
||||
|
91
app/Http/Middleware/Reminders.php
Normal file
91
app/Http/Middleware/Reminders.php
Normal file
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Http\Middleware;
|
||||
|
||||
use App;
|
||||
use Carbon\Carbon;
|
||||
use Closure;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use Illuminate\Contracts\Auth\Guard;
|
||||
use Illuminate\Http\Request;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class Reminders
|
||||
*
|
||||
* @package FireflyIII\Http\Middleware
|
||||
*/
|
||||
class Reminders
|
||||
{
|
||||
/**
|
||||
* The Guard implementation.
|
||||
*
|
||||
* @var Guard
|
||||
*/
|
||||
protected $auth;
|
||||
|
||||
/**
|
||||
* Create a new filter instance.
|
||||
*
|
||||
* @param Guard $auth
|
||||
*
|
||||
*/
|
||||
public function __construct(Guard $auth)
|
||||
{
|
||||
$this->auth = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ($this->auth->check() && !$request->isXmlHttpRequest() && App::environment() != 'testing') {
|
||||
// do reminders stuff.
|
||||
$piggyBanks = $this->auth->user()->piggyBanks()->where('remind_me', 1)->get();
|
||||
$today = new Carbon;
|
||||
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface $helper */
|
||||
$helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface');
|
||||
|
||||
/** @var PiggyBank $piggyBank */
|
||||
foreach ($piggyBanks as $piggyBank) {
|
||||
$ranges = $helper->getReminderRanges($piggyBank);
|
||||
|
||||
foreach ($ranges as $range) {
|
||||
if ($today < $range['end'] && $today > $range['start']) {
|
||||
// create a reminder here!
|
||||
$helper->createReminder($piggyBank, $range['start'], $range['end']);
|
||||
// stop looping, we're done.
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
// delete invalid reminders
|
||||
$set = $this->auth->user()->reminders()->leftJoin('piggy_banks', 'piggy_banks.id', '=', 'remindersable_id')->whereNull('piggy_banks.id')->get(
|
||||
['reminders.id']
|
||||
);
|
||||
foreach ($set as $reminder) {
|
||||
$reminder->delete();
|
||||
}
|
||||
|
||||
|
||||
// get and list active reminders:
|
||||
$reminders = $this->auth->user()->reminders()->today()->get();
|
||||
$reminders->each(
|
||||
function (Reminder $reminder) use ($helper) {
|
||||
$reminder->description = $helper->getReminderText($reminder);
|
||||
}
|
||||
);
|
||||
View::share('reminders', $reminders);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
56
app/Http/Middleware/ReplaceTestVars.php
Normal file
56
app/Http/Middleware/ReplaceTestVars.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class ReplaceTestVars
|
||||
*
|
||||
* @package FireflyIII\Http\Middleware
|
||||
*/
|
||||
class ReplaceTestVars
|
||||
{
|
||||
/**
|
||||
* The application implementation.
|
||||
*
|
||||
* @var Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* Create a new filter instance.
|
||||
*
|
||||
* @param Application $app
|
||||
*
|
||||
*/
|
||||
public function __construct(Application $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure $next
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if ('testing' === $this->app->environment() && $request->has('_token')) {
|
||||
$input = $request->all();
|
||||
$input['_token'] = $request->session()->token();
|
||||
// we need to update _token value to make sure we get the POST / PUT tests passed.
|
||||
Log::debug('Input token replaced (' . $input['_token'] . ').');
|
||||
$request->replace($input);
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
}
|
@@ -28,22 +28,29 @@ class AccountFormRequest extends Request
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$accountRoles = join(',', array_keys(Config::get('firefly.accountRoles')));
|
||||
$types = join(',', array_keys(Config::get('firefly.subTitlesByIdentifier')));
|
||||
$accountRoles = join(',', array_keys(Config::get('firefly.accountRoles')));
|
||||
$types = join(',', array_keys(Config::get('firefly.subTitlesByIdentifier')));
|
||||
$ccPaymentTypes = join(',', array_keys(Config::get('firefly.ccTypes')));
|
||||
|
||||
$nameRule = 'required|between:1,100|uniqueForUser:accounts,name';
|
||||
$nameRule = 'required|min:1|uniqueAccountForUser';
|
||||
$idRule = '';
|
||||
if (Account::find(Input::get('id'))) {
|
||||
$nameRule = 'required|between:1,100';
|
||||
$idRule = 'belongsToUser:accounts';
|
||||
$nameRule = 'required|min:1|uniqueAccountForUser:' . Input::get('id');
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $nameRule,
|
||||
'openingBalance' => 'numeric',
|
||||
'openingBalanceDate' => 'date',
|
||||
'accountRole' => 'in:' . $accountRoles,
|
||||
'active' => 'boolean',
|
||||
'balance_currency_id' => 'exists:transaction_currencies,id',
|
||||
'what' => 'in:' . $types
|
||||
'id' => $idRule,
|
||||
'name' => $nameRule,
|
||||
'openingBalance' => 'numeric',
|
||||
'virtualBalance' => 'numeric',
|
||||
'openingBalanceDate' => 'date',
|
||||
'accountRole' => 'in:' . $accountRoles,
|
||||
'active' => 'boolean',
|
||||
'ccType' => 'in:' . $ccPaymentTypes,
|
||||
'ccMonthlyPaymentDate' => 'date',
|
||||
'balance_currency_id' => 'exists:transaction_currencies,id',
|
||||
'what' => 'in:' . $types
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,14 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 25/02/15
|
||||
* Time: 12:29
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Input;
|
||||
|
||||
/**
|
||||
@@ -27,19 +22,41 @@ class BillFormRequest extends Request
|
||||
return Auth::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getBillData()
|
||||
{
|
||||
return [
|
||||
'name' => $this->get('name'),
|
||||
'match' => $this->get('match'),
|
||||
'amount_min' => floatval($this->get('amount_min')),
|
||||
'amount_currency_id' => floatval($this->get('amount_currency_id')),
|
||||
'amount_max' => floatval($this->get('amount_max')),
|
||||
'date' => new Carbon($this->get('date')),
|
||||
'user' => Auth::user()->id,
|
||||
'repeat_freq' => $this->get('repeat_freq'),
|
||||
'skip' => intval($this->get('skip')),
|
||||
'automatch' => intval($this->get('automatch')) === 1,
|
||||
'active' => intval($this->get('active')) === 1,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$nameRule = 'required|between:1,255|uniqueForUser:bills,name';
|
||||
if(intval(Input::get('id')) > 0) {
|
||||
$nameRule .= ','.intval(Input::get('id'));
|
||||
$nameRule = 'required|between:1,255|uniqueObjectForUser:bills,name,name_encrypted';
|
||||
$matchRule = 'required|between:1,255|uniqueObjectForUser:bills,match,match_encrypted';
|
||||
if (intval(Input::get('id')) > 0) {
|
||||
$nameRule .= ',' . intval(Input::get('id'));
|
||||
$matchRule .= ',' . intval(Input::get('id'));
|
||||
}
|
||||
|
||||
$rules = [
|
||||
'name' => $nameRule,
|
||||
'match' => 'required|between:1,255',
|
||||
'match' => $matchRule,
|
||||
'amount_min' => 'required|numeric|min:0.01',
|
||||
'amount_max' => 'required|numeric|min:0.01',
|
||||
'amount_currency_id' => 'required|exists:transaction_currencies,id',
|
||||
@@ -52,4 +69,4 @@ class BillFormRequest extends Request
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,13 +28,14 @@ class BudgetFormRequest extends Request
|
||||
public function rules()
|
||||
{
|
||||
|
||||
$nameRule = 'required|between:1,100|uniqueForUser:budgets,name';
|
||||
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,encrypted';
|
||||
if (Budget::find(Input::get('id'))) {
|
||||
$nameRule = 'required|between:1,100';
|
||||
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,encrypted,' . intval(Input::get('id'));
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $nameRule,
|
||||
'name' => $nameRule,
|
||||
'active' => 'numeric|between:0,1'
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -28,13 +28,13 @@ class CategoryFormRequest extends Request
|
||||
public function rules()
|
||||
{
|
||||
|
||||
$nameRule = 'required|between:1,100|uniqueForUser:categories,name';
|
||||
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,encrypted';
|
||||
if (Category::find(Input::get('id'))) {
|
||||
$nameRule = 'required|between:1,100';
|
||||
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,encrypted,' . intval(Input::get('id'));
|
||||
}
|
||||
|
||||
return [
|
||||
'name' => $nameRule,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 25/02/15
|
||||
* Time: 12:29
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
@@ -27,6 +21,18 @@ class CurrencyFormRequest extends Request
|
||||
return Auth::check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getCurrencyData()
|
||||
{
|
||||
return [
|
||||
'name' => $this->get('name'),
|
||||
'code' => $this->get('code'),
|
||||
'symbol' => $this->get('symbol'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
@@ -48,4 +54,4 @@ class CurrencyFormRequest extends Request
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,8 @@
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use Carbon\Carbon;
|
||||
use Exception;
|
||||
use Input;
|
||||
|
||||
/**
|
||||
@@ -25,6 +26,29 @@ class JournalFormRequest extends Request
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getJournalData()
|
||||
{
|
||||
return [
|
||||
'what' => $this->get('what'),
|
||||
'description' => $this->get('description'),
|
||||
'account_id' => intval($this->get('account_id')),
|
||||
'account_from_id' => intval($this->get('account_from_id')),
|
||||
'account_to_id' => intval($this->get('account_to_id')),
|
||||
'expense_account' => $this->get('expense_account'),
|
||||
'revenue_account' => $this->get('revenue_account'),
|
||||
'amount' => floatval($this->get('amount')),
|
||||
'user' => Auth::user()->id,
|
||||
'amount_currency_id' => intval($this->get('amount_currency_id')),
|
||||
'date' => new Carbon($this->get('date')),
|
||||
'budget_id' => intval($this->get('budget_id')),
|
||||
'category' => $this->get('category'),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
// can we switch on the "what"?
|
||||
@@ -35,6 +59,7 @@ class JournalFormRequest extends Request
|
||||
'what' => 'required|in:withdrawal,deposit,transfer|exists:transaction_types,type',
|
||||
'amount' => 'numeric|required|min:0.01',
|
||||
'date' => 'required|date',
|
||||
'reminder_id' => 'numeric|exists:reminders,id',
|
||||
'amount_currency_id' => 'required|exists:transaction_currencies,id',
|
||||
|
||||
];
|
||||
@@ -61,7 +86,7 @@ class JournalFormRequest extends Request
|
||||
$rules['category'] = 'between:1,255';
|
||||
break;
|
||||
default:
|
||||
die('Cannot handle ' . $what);
|
||||
throw new Exception('Cannot handle ' . $what);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -69,4 +94,4 @@ class JournalFormRequest extends Request
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use Input;
|
||||
|
||||
/**
|
||||
@@ -28,34 +27,27 @@ class PiggyBankFormRequest extends Request
|
||||
public function rules()
|
||||
{
|
||||
|
||||
$nameRule = 'required|between:1,255|uniqueForUser:piggy_banks,name';
|
||||
$nameRule = 'required|between:1,255|uniquePiggyBankForUser';
|
||||
$targetDateRule = 'date';
|
||||
if (intval(Input::get('id'))) {
|
||||
$nameRule = 'required|between:1,255';
|
||||
$nameRule = 'required|between:1,255|uniquePiggyBankForUser:' . intval(Input::get('id'));
|
||||
}
|
||||
|
||||
if (intval(Input::get('repeats')) == 1) {
|
||||
$targetDateRule = 'required|date|after:' . date('Y-m-d');
|
||||
}
|
||||
|
||||
$rules = [
|
||||
'repeats' => 'required|boolean',
|
||||
'name' => $nameRule,
|
||||
'account_id' => 'required|belongsToUser:accounts',
|
||||
'targetamount' => 'required|min:0.01',
|
||||
'amount_currency_id' => 'exists:transaction_currencies,id',
|
||||
'startdate' => 'date',
|
||||
'targetdate' => $targetDateRule,
|
||||
'rep_length' => 'in:day,week,quarter,month,year',
|
||||
'rep_every' => 'integer|min:0|max:31',
|
||||
'rep_times' => 'integer|min:0|max:99',
|
||||
'reminder' => 'in:day,week,quarter,month,year',
|
||||
'reminder_skip' => 'integer|min:0|max:99',
|
||||
'remind_me' => 'boolean',
|
||||
'remind_me' => 'boolean|piggyBankReminder',
|
||||
'order' => 'integer|min:1',
|
||||
|
||||
];
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
namespace FireflyIII\Http\Requests;
|
||||
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
|
||||
/**
|
||||
* Class ProfileFormRequest
|
||||
@@ -27,9 +26,9 @@ class ProfileFormRequest extends Request
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'current_password' => 'required',
|
||||
'current_password' => 'required',
|
||||
'new_password' => 'required|confirmed',
|
||||
'new_password_confirmation' => 'required',
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -3,12 +3,13 @@ use Carbon\Carbon;
|
||||
use DaveJamesMiller\Breadcrumbs\Generator;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
|
||||
/*
|
||||
* Back home.
|
||||
@@ -239,47 +240,22 @@ Breadcrumbs::register(
|
||||
|
||||
// reminders
|
||||
Breadcrumbs::register(
|
||||
'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) {
|
||||
'reminders.index', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push('Reminders', route('reminders.index'));
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
// reminders
|
||||
Breadcrumbs::register(
|
||||
'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) {
|
||||
$breadcrumbs->parent('reminders.index');
|
||||
$breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id));
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
// repeated expenses
|
||||
Breadcrumbs::register(
|
||||
'repeated.index', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('home');
|
||||
$breadcrumbs->push('Repeated expenses', route('repeated.index'));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'repeated.create', function (Generator $breadcrumbs) {
|
||||
$breadcrumbs->parent('repeated.index');
|
||||
$breadcrumbs->push('Create new repeated expense', route('repeated.create'));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'repeated.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
|
||||
$breadcrumbs->parent('repeated.show', $piggyBank);
|
||||
$breadcrumbs->push('Edit ' . e($piggyBank->name), route('repeated.edit', $piggyBank->id));
|
||||
}
|
||||
);
|
||||
Breadcrumbs::register(
|
||||
'repeated.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
|
||||
$breadcrumbs->parent('repeated.show', $piggyBank);
|
||||
$breadcrumbs->push('Delete ' . e($piggyBank->name), route('repeated.delete', $piggyBank->id));
|
||||
}
|
||||
);
|
||||
|
||||
Breadcrumbs::register(
|
||||
'repeated.show', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
|
||||
$breadcrumbs->parent('repeated.index');
|
||||
$breadcrumbs->push(e($piggyBank->name), route('repeated.show', $piggyBank->id));
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
// reports
|
||||
Breadcrumbs::register(
|
||||
|
@@ -4,9 +4,10 @@ use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Reminder;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
|
||||
|
||||
// models
|
||||
@@ -27,20 +28,6 @@ Route::bind(
|
||||
}
|
||||
);
|
||||
|
||||
Route::bind(
|
||||
'repeatedExpense', function ($value, $route) {
|
||||
if (Auth::check()) {
|
||||
return PiggyBank::
|
||||
where('piggy_banks.id', $value)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
|
||||
->where('accounts.user_id', Auth::user()->id)
|
||||
->where('repeats', 1)->first(['piggy_banks.*']);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
Route::bind(
|
||||
'tjSecond', function ($value, $route) {
|
||||
if (Auth::check()) {
|
||||
@@ -89,6 +76,16 @@ Route::bind(
|
||||
}
|
||||
);
|
||||
|
||||
Route::bind(
|
||||
'reminder', function ($value, $route) {
|
||||
if (Auth::check()) {
|
||||
return Reminder::where('id', $value)->where('user_id', Auth::user()->id)->first();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
);
|
||||
|
||||
Route::bind(
|
||||
'limitrepetition', function ($value, $route) {
|
||||
if (Auth::check()) {
|
||||
@@ -110,7 +107,7 @@ Route::bind(
|
||||
where('piggy_banks.id', $value)
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
|
||||
->where('accounts.user_id', Auth::user()->id)
|
||||
->where('repeats', 0)->first(['piggy_banks.*']);
|
||||
->first(['piggy_banks.*']);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -145,12 +142,10 @@ Route::controllers(
|
||||
* Home Controller
|
||||
*/
|
||||
Route::group(
|
||||
['middleware' => ['auth', 'range']], function () {
|
||||
['middleware' => ['auth', 'range', 'reminders', 'piggybanks']], function () {
|
||||
Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index']);
|
||||
Route::get('/home', ['uses' => 'HomeController@index', 'as' => 'home']);
|
||||
Route::get('/prev', ['uses' => 'HomeController@sessionPrev', 'as' => 'sessionPrev']);
|
||||
Route::get('/next', ['uses' => 'HomeController@sessionNext', 'as' => 'sessionNext']);
|
||||
Route::get('/jump/{range}', ['uses' => 'HomeController@rangeJump', 'as' => 'rangeJump']);
|
||||
Route::post('/daterange', ['uses' => 'HomeController@dateRange', 'as' => 'daterange']);
|
||||
Route::get('/flush', ['uses' => 'HomeController@flush', 'as' => 'flush']);
|
||||
/**
|
||||
* Account Controller
|
||||
@@ -172,9 +167,9 @@ Route::group(
|
||||
Route::get('/bills/rescan/{bill}', ['uses' => 'BillController@rescan', 'as' => 'bills.rescan']); # rescan for matching.
|
||||
Route::get('/bills/create', ['uses' => 'BillController@create', 'as' => 'bills.create']);
|
||||
Route::get('/bills/edit/{bill}', ['uses' => 'BillController@edit', 'as' => 'bills.edit']);
|
||||
Route::get('/bills/add/{bill}', ['uses' => 'BillController@add', 'as' => 'bills.add']);
|
||||
Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']);
|
||||
Route::get('/bills/show/{bill}', ['uses' => 'BillController@show', 'as' => 'bills.show']);
|
||||
|
||||
Route::post('/bills/store', ['uses' => 'BillController@store', 'as' => 'bills.store']);
|
||||
Route::post('/bills/update/{bill}', ['uses' => 'BillController@update', 'as' => 'bills.update']);
|
||||
Route::post('/bills/destroy/{bill}', ['uses' => 'BillController@destroy', 'as' => 'bills.destroy']);
|
||||
@@ -230,13 +225,14 @@ Route::group(
|
||||
Route::get('/chart/home/bills', ['uses' => 'GoogleChartController@billsOverview']);
|
||||
Route::get('/chart/account/{account}/{view?}', ['uses' => 'GoogleChartController@accountBalanceChart']);
|
||||
Route::get('/chart/budget/{budget}/spending/{year?}', ['uses' => 'GoogleChartController@budgetsAndSpending']);
|
||||
Route::get('/chart/budgets/spending/{year?}', ['uses' => 'GoogleChartController@allBudgetsAndSpending']);
|
||||
Route::get('/chart/budgets/spending/{year?}', ['uses' => 'GoogleChartController@allBudgetsAndSpending'])->where(['year' => '[0-9]+']);
|
||||
Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'GoogleChartController@budgetLimitSpending']);
|
||||
Route::get('/chart/category/{category}/spending/{year}', ['uses' => 'GoogleChartController@categoriesAndSpending']);
|
||||
Route::get('/chart/reports/income-expenses/{year}', ['uses' => 'GoogleChartController@yearInExp']);
|
||||
Route::get('/chart/reports/income-expenses-sum/{year}', ['uses' => 'GoogleChartController@yearInExpSum']);
|
||||
Route::get('/chart/bills/{bill}', ['uses' => 'GoogleChartController@billOverview']);
|
||||
Route::get('/chart/piggy-history/{piggyBank}', ['uses' => 'GoogleChartController@piggyBankHistory']);
|
||||
Route::get('/chart/category/{category}/period', ['uses' => 'GoogleChartController@categoryPeriodChart']);
|
||||
Route::get('/chart/category/{category}/overview', ['uses' => 'GoogleChartController@categoryOverviewChart']);
|
||||
|
||||
/**
|
||||
* Help Controller
|
||||
@@ -249,14 +245,21 @@ Route::group(
|
||||
Route::get('/json/expense-accounts', ['uses' => 'JsonController@expenseAccounts', 'as' => 'json.expense-accounts']);
|
||||
Route::get('/json/revenue-accounts', ['uses' => 'JsonController@revenueAccounts', 'as' => 'json.revenue-accounts']);
|
||||
Route::get('/json/categories', ['uses' => 'JsonController@categories', 'as' => 'json.categories']);
|
||||
Route::get('/json/box/in', ['uses' => 'JsonController@boxIn', 'as' => 'json.box.in']);
|
||||
Route::get('/json/box/out', ['uses' => 'JsonController@boxOut', 'as' => 'json.box.out']);
|
||||
Route::get('/json/box/bills-unpaid', ['uses' => 'JsonController@boxBillsUnpaid', 'as' => 'json.box.paid']);
|
||||
Route::get('/json/box/bills-paid', ['uses' => 'JsonController@boxBillsPaid', 'as' => 'json.box.unpaid']);
|
||||
Route::get('/json/show-shared-reports', 'JsonController@showSharedReports');
|
||||
Route::get('/json/transaction-journals/{what}', 'JsonController@transactionJournals');
|
||||
Route::get('/json/show-shared-reports/set', 'JsonController@setSharedReports');
|
||||
|
||||
|
||||
/**
|
||||
* Piggy Bank Controller
|
||||
*/
|
||||
Route::get('/piggy-banks', ['uses' => 'PiggyBankController@index', 'as' => 'piggy-banks.index']);
|
||||
Route::get('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@add']); # add money
|
||||
Route::get('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@remove']); #remove money
|
||||
Route::get('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@add', 'as' => 'piggy-banks.addMoney']); # add money
|
||||
Route::get('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@remove', 'as' => 'piggy-banks.removeMoney']); #remove money
|
||||
Route::get('/piggy-banks/create', ['uses' => 'PiggyBankController@create', 'as' => 'piggy-banks.create']);
|
||||
Route::get('/piggy-banks/edit/{piggyBank}', ['uses' => 'PiggyBankController@edit', 'as' => 'piggy-banks.edit']);
|
||||
Route::get('/piggy-banks/delete/{piggyBank}', ['uses' => 'PiggyBankController@delete', 'as' => 'piggy-banks.delete']);
|
||||
@@ -266,6 +269,7 @@ Route::group(
|
||||
Route::post('/piggy-banks/destroy/{piggyBank}', ['uses' => 'PiggyBankController@destroy', 'as' => 'piggy-banks.destroy']);
|
||||
Route::post('/piggy-banks/add/{piggyBank}', ['uses' => 'PiggyBankController@postAdd', 'as' => 'piggy-banks.add']); # add money
|
||||
Route::post('/piggy-banks/remove/{piggyBank}', ['uses' => 'PiggyBankController@postRemove', 'as' => 'piggy-banks.remove']); # remove money.
|
||||
Route::post('/piggy-banks/sort', ['uses' => 'PiggyBankController@order', 'as' => 'piggy-banks.order']);
|
||||
|
||||
/**
|
||||
* Preferences Controller
|
||||
@@ -278,7 +282,7 @@ Route::group(
|
||||
*/
|
||||
Route::get('/profile', ['uses' => 'ProfileController@index', 'as' => 'profile']);
|
||||
Route::get('/profile/change-password', ['uses' => 'ProfileController@changePassword', 'as' => 'change-password']);
|
||||
Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword','as' => 'change-password-post']);
|
||||
Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword', 'as' => 'change-password-post']);
|
||||
|
||||
/**
|
||||
* Related transactions controller
|
||||
@@ -286,20 +290,17 @@ Route::group(
|
||||
Route::get('/related/alreadyRelated/{tj}', ['uses' => 'RelatedController@alreadyRelated', 'as' => 'related.alreadyRelated']);
|
||||
Route::post('/related/relate/{tj}/{tjSecond}', ['uses' => 'RelatedController@relate', 'as' => 'related.relate']);
|
||||
Route::post('/related/removeRelation/{tj}/{tjSecond}', ['uses' => 'RelatedController@removeRelation', 'as' => 'related.removeRelation']);
|
||||
Route::get('/related/remove/{tj}/{tjSecond}', ['uses' => 'RelatedController@getRemoveRelation', 'as' => 'related.getRemoveRelation']);
|
||||
Route::get('/related/related/{tj}', ['uses' => 'RelatedController@related', 'as' => 'related.related']);
|
||||
Route::post('/related/search/{tj}', ['uses' => 'RelatedController@search', 'as' => 'related.search']);
|
||||
|
||||
/**
|
||||
* Repeated Expenses Controller
|
||||
* Reminder Controller
|
||||
*/
|
||||
Route::get('/repeated-expenses', ['uses' => 'RepeatedExpenseController@index', 'as' => 'repeated.index']);
|
||||
Route::get('/repeated-expenses/create', ['uses' => 'RepeatedExpenseController@create', 'as' => 'repeated.create']);
|
||||
Route::get('/repeated-expenses/edit/{repeatedExpense}', ['uses' => 'RepeatedExpenseController@edit', 'as' => 'repeated.edit']);
|
||||
Route::get('/repeated-expenses/delete/{repeatedExpense}', ['uses' => 'RepeatedExpenseController@delete', 'as' => 'repeated.delete']);
|
||||
Route::get('/repeated-expenses/show/{repeatedExpense}', ['uses' => 'RepeatedExpenseController@show', 'as' => 'repeated.show']);
|
||||
Route::post('/repeated-expense/store', ['uses' => 'RepeatedExpenseController@store', 'as' => 'repeated.store']);
|
||||
Route::post('/repeated-expense/update/{repeatedExpense}', ['uses' => 'RepeatedExpenseController@update', 'as' => 'repeated.update']);
|
||||
Route::post('/repeated-expense/destroy/{repeatedExpense}', ['uses' => 'RepeatedExpenseController@destroy', 'as' => 'repeated.destroy']);
|
||||
Route::get('/reminders', ['uses' => 'ReminderController@index', 'as' => 'reminders.index']);
|
||||
Route::get('/reminder/dismiss/{reminder}', ['uses' => 'ReminderController@dismiss', 'as' => 'reminders.dismiss']);
|
||||
Route::get('/reminder/act/{reminder}', ['uses' => 'ReminderController@act', 'as' => 'reminders.act']);
|
||||
Route::get('/reminder/{reminder}', ['uses' => 'ReminderController@show', 'as' => 'reminders.show']);
|
||||
|
||||
/**
|
||||
* Report Controller
|
||||
@@ -309,6 +310,16 @@ Route::group(
|
||||
Route::get('/reports/{year}/{month}', ['uses' => 'ReportController@month', 'as' => 'reports.month']);
|
||||
Route::get('/reports/budget/{year}/{month}', ['uses' => 'ReportController@budget', 'as' => 'reports.budget']);
|
||||
|
||||
// pop ups for budget report:
|
||||
Route::get('/reports/modal/{account}/{year}/{month}/no-budget', ['uses' => 'ReportController@modalNoBudget', 'as' => 'reports.no-budget']);
|
||||
Route::get(
|
||||
'/reports/modal/{account}/{year}/{month}/balanced-transfers',
|
||||
['uses' => 'ReportController@modalBalancedTransfers', 'as' => 'reports.balanced-transfers']
|
||||
);
|
||||
Route::get(
|
||||
'/reports/modal/{account}/{year}/{month}/left-unbalanced', ['uses' => 'ReportController@modalLeftUnbalanced', 'as' => 'reports.left-unbalanced']
|
||||
);
|
||||
|
||||
/**
|
||||
* Search Controller
|
||||
*/
|
||||
@@ -332,6 +343,7 @@ Route::group(
|
||||
);
|
||||
Route::post('/transaction/update/{tj}', ['uses' => 'TransactionController@update', 'as' => 'transactions.update']);
|
||||
Route::post('/transaction/destroy/{tj}', ['uses' => 'TransactionController@destroy', 'as' => 'transactions.destroy']);
|
||||
Route::post('/transaction/reorder', ['uses' => 'TransactionController@reorder', 'as' => 'transactions.reorder']);
|
||||
|
||||
/**
|
||||
* Auth\Auth Controller
|
||||
|
183
app/Models/Account.php
Normal file
183
app/Models/Account.php
Normal file
@@ -0,0 +1,183 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use App;
|
||||
use Crypt;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
* Class Account
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class Account extends Model
|
||||
{
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
protected $fillable = ['user_id', 'account_type_id', 'name', 'active', 'virtual_balance'];
|
||||
protected $rules
|
||||
= [
|
||||
'user_id' => 'required|exists:users,id',
|
||||
'account_type_id' => 'required|exists:account_types,id',
|
||||
'name' => 'required|between:1,1024|uniqueAccountForUser',
|
||||
'active' => 'required|boolean'
|
||||
];
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
*
|
||||
* @return Account|null
|
||||
*/
|
||||
public static function firstOrCreateEncrypted(array $fields)
|
||||
{
|
||||
// everything but the name:
|
||||
$query = Account::orderBy('id');
|
||||
foreach ($fields as $name => $value) {
|
||||
if ($name != 'name') {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
}
|
||||
$set = $query->get(['accounts.*']);
|
||||
/** @var Account $account */
|
||||
foreach ($set as $account) {
|
||||
if ($account->name == $fields['name']) {
|
||||
return $account;
|
||||
}
|
||||
}
|
||||
// create it!
|
||||
$account = Account::create($fields);
|
||||
if (is_null($account->id)) {
|
||||
// could not create account:
|
||||
App::abort(500, 'Could not create new account with data: ' . json_encode($fields).' because ' . json_encode($account->getErrors()));
|
||||
|
||||
|
||||
}
|
||||
|
||||
return $account;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function accountMeta()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\AccountMeta');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function accountType()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\AccountType');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'deleted_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $fieldName
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getMeta($fieldName)
|
||||
{
|
||||
foreach ($this->accountMeta as $meta) {
|
||||
if ($meta->name == $fieldName) {
|
||||
return $meta->data;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNameAttribute($value)
|
||||
{
|
||||
|
||||
if (intval($this->encrypted) == 1) {
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
return $value;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function piggyBanks()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\PiggyBank');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EloquentBuilder $query
|
||||
* @param array $types
|
||||
*/
|
||||
public function scopeAccountTypeIn(EloquentBuilder $query, array $types)
|
||||
{
|
||||
if (is_null($this->joinedAccountTypes)) {
|
||||
$query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id');
|
||||
$this->joinedAccountTypes = true;
|
||||
}
|
||||
$query->whereIn('account_types.type', $types);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EloquentBuilder $query
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*/
|
||||
public function scopeHasMetaValue(EloquentBuilder $query, $name, $value)
|
||||
{
|
||||
$joinName = str_replace('.', '_', $name);
|
||||
$query->leftJoin(
|
||||
'account_meta as ' . $joinName, function (JoinClause $join) use ($joinName, $name) {
|
||||
$join->on($joinName . '.account_id', '=', 'accounts.id')->where($joinName . '.name', '=', $name);
|
||||
}
|
||||
);
|
||||
$query->where($joinName . '.data', json_encode($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setNameAttribute($value)
|
||||
{
|
||||
$this->attributes['name'] = Crypt::encrypt($value);
|
||||
$this->attributes['encrypted'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function transactions()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\Transaction');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
}
|
@@ -14,12 +14,12 @@ class AccountMeta extends Model
|
||||
use ValidatingTrait;
|
||||
protected $fillable = ['account_id', 'name', 'data'];
|
||||
protected $rules
|
||||
= [
|
||||
= [
|
||||
'account_id' => 'required|exists:accounts,id',
|
||||
'name' => 'required|between:1,100',
|
||||
'data' => 'required'
|
||||
];
|
||||
protected $table = 'account_meta';
|
||||
protected $table = 'account_meta';
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
|
29
app/Models/AccountType.php
Normal file
29
app/Models/AccountType.php
Normal file
@@ -0,0 +1,29 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class AccountType
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class AccountType extends Model
|
||||
{
|
||||
|
||||
//
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function accounts()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\Account');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at'];
|
||||
}
|
||||
}
|
94
app/Models/Bill.php
Normal file
94
app/Models/Bill.php
Normal file
@@ -0,0 +1,94 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Crypt;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class Bill
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class Bill extends Model
|
||||
{
|
||||
|
||||
protected $fillable
|
||||
= ['name', 'match', 'amount_min', 'match_encrypted', 'name_encrypted', 'user_id', 'amount_max', 'date', 'repeat_freq', 'skip', 'automatch', 'active',];
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'date'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMatchAttribute($value)
|
||||
{
|
||||
|
||||
if (intval($this->match_encrypted) == 1) {
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
return $value;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNameAttribute($value)
|
||||
{
|
||||
|
||||
if (intval($this->name_encrypted) == 1) {
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
return $value;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setMatchAttribute($value)
|
||||
{
|
||||
$this->attributes['match'] = Crypt::encrypt($value);
|
||||
$this->attributes['match_encrypted'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setNameAttribute($value)
|
||||
{
|
||||
$this->attributes['name'] = Crypt::encrypt($value);
|
||||
$this->attributes['name_encrypted'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function transactionjournals()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
|
||||
}
|
86
app/Models/Budget.php
Normal file
86
app/Models/Budget.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Crypt;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* Class Budget
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class Budget extends Model
|
||||
{
|
||||
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = ['user_id', 'name'];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function budgetlimits()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\BudgetLimit');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'deleted_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNameAttribute($value)
|
||||
{
|
||||
|
||||
if (intval($this->encrypted) == 1) {
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
return $value;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
|
||||
*/
|
||||
public function limitrepetitions()
|
||||
{
|
||||
return $this->hasManyThrough('FireflyIII\Models\LimitRepetition', 'FireflyIII\Models\BudgetLimit', 'budget_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setNameAttribute($value)
|
||||
{
|
||||
$this->attributes['name'] = Crypt::encrypt($value);
|
||||
$this->attributes['encrypted'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function transactionjournals()
|
||||
{
|
||||
return $this->belongsToMany('FireflyIII\Models\TransactionJournal', 'budget_transaction_journal', 'budget_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
|
||||
}
|
37
app/Models/BudgetLimit.php
Normal file
37
app/Models/BudgetLimit.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class BudgetLimit
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class BudgetLimit extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function budget()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\Budget');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'startdate'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function limitrepetitions()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\LimitRepetition');
|
||||
}
|
||||
|
||||
}
|
101
app/Models/Category.php
Normal file
101
app/Models/Category.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Crypt;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use App;
|
||||
/**
|
||||
* Class Category
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class Category extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = ['user_id', 'name'];
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'deleted_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function transactionjournals()
|
||||
{
|
||||
return $this->belongsToMany('FireflyIII\Models\TransactionJournal', 'category_transaction_journal', 'category_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
*
|
||||
* @return Account|null
|
||||
*/
|
||||
public static function firstOrCreateEncrypted(array $fields)
|
||||
{
|
||||
// everything but the name:
|
||||
$query = Category::orderBy('id');
|
||||
foreach ($fields as $name => $value) {
|
||||
if ($name != 'name') {
|
||||
$query->where($name, $value);
|
||||
}
|
||||
}
|
||||
$set = $query->get(['categories.*']);
|
||||
/** @var Category $category */
|
||||
foreach ($set as $category) {
|
||||
if ($category->name == $fields['name']) {
|
||||
return $category;
|
||||
}
|
||||
}
|
||||
// create it!
|
||||
$category = Category::create($fields);
|
||||
if (is_null($category->id)) {
|
||||
// could not create account:
|
||||
App::abort(500, 'Could not create new category with data: ' . json_encode($fields));
|
||||
|
||||
}
|
||||
|
||||
return $category;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setNameAttribute($value)
|
||||
{
|
||||
$this->attributes['name'] = Crypt::encrypt($value);
|
||||
$this->attributes['encrypted'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNameAttribute($value)
|
||||
{
|
||||
|
||||
if (intval($this->encrypted) == 1) {
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
return $value;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
}
|
24
app/Models/Component.php
Normal file
24
app/Models/Component.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* Class Component
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class Component extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = ['user_id', 'name', 'class'];
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'deleted_at'];
|
||||
}
|
||||
}
|
52
app/Models/LimitRepetition.php
Normal file
52
app/Models/LimitRepetition.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Auth;
|
||||
use DB;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class LimitRepetition
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class LimitRepetition extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function budgetLimit()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\BudgetLimit');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'startdate', 'enddate'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function spentInRepetition()
|
||||
{
|
||||
$sum = DB::table('transactions')
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budget_transaction_journal.budget_id')
|
||||
->leftJoin('limit_repetitions', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
|
||||
->where('transaction_journals.date', '>=', $this->startdate->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $this->enddate->format('Y-m-d'))
|
||||
->where('transaction_journals.user_id', Auth::user()->id)
|
||||
->whereNull('transactions.deleted_at')
|
||||
->where('transactions.amount', '>', 0)
|
||||
->where('limit_repetitions.id', '=', $this->id)
|
||||
->sum('transactions.amount');
|
||||
|
||||
return floatval($sum);
|
||||
}
|
||||
|
||||
}
|
@@ -1,7 +1,6 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Crypt;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
@@ -14,7 +13,8 @@ class PiggyBank extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
protected $fillable = ['repeats', 'name', 'account_id','rep_every', 'rep_times', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder',];
|
||||
protected $fillable
|
||||
= ['name', 'account_id', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me'];
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
@@ -31,50 +31,14 @@ class PiggyBank extends Model
|
||||
*/
|
||||
public function currentRelevantRep()
|
||||
{
|
||||
if ($this->currentRep) {
|
||||
if (!is_null($this->currentRep)) {
|
||||
return $this->currentRep;
|
||||
}
|
||||
if ($this->repeats == 0) {
|
||||
$rep = $this->piggyBankRepetitions()->first(['piggy_bank_repetitions.*']);
|
||||
$this->currentRep = $rep;
|
||||
// repeating piggy banks are no longer supported.
|
||||
$rep = $this->piggyBankRepetitions()->first(['piggy_bank_repetitions.*']);
|
||||
$this->currentRep = $rep;
|
||||
|
||||
return $rep;
|
||||
} else {
|
||||
$query = $this->piggyBankRepetitions()->where(
|
||||
function (EloquentBuilder $q) {
|
||||
|
||||
$q->where(
|
||||
function (EloquentBuilder $q) {
|
||||
|
||||
$q->where(
|
||||
function (EloquentBuilder $q) {
|
||||
$today = new Carbon;
|
||||
$q->whereNull('startdate');
|
||||
$q->orWhere('startdate', '<=', $today->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
)->where(
|
||||
function (EloquentBuilder $q) {
|
||||
$today = new Carbon;
|
||||
$q->whereNull('targetdate');
|
||||
$q->orWhere('targetdate', '>=', $today->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
);
|
||||
}
|
||||
)->orWhere(
|
||||
function (EloquentBuilder $q) {
|
||||
$today = new Carbon;
|
||||
$q->where('startdate', '>=', $today->format('Y-m-d 00:00:00'));
|
||||
$q->where('targetdate', '>=', $today->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
)->orderBy('startdate', 'ASC');
|
||||
$result = $query->first(['piggy_bank_repetitions.*']);
|
||||
$this->currentRep = $result;
|
||||
|
||||
return $result;
|
||||
}
|
||||
return $rep;
|
||||
|
||||
|
||||
}
|
||||
@@ -95,6 +59,16 @@ class PiggyBank extends Model
|
||||
return ['created_at', 'updated_at', 'deleted_at', 'startdate', 'targetdate'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRemindMeAttribute($value)
|
||||
{
|
||||
return intval($value) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
@@ -110,4 +84,30 @@ class PiggyBank extends Model
|
||||
{
|
||||
return $this->morphMany('FireflyIII\Models\Reminder', 'remindersable');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setNameAttribute($value)
|
||||
{
|
||||
$this->attributes['name'] = Crypt::encrypt($value);
|
||||
$this->attributes['encrypted'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNameAttribute($value)
|
||||
{
|
||||
|
||||
if (intval($this->encrypted) == 1) {
|
||||
return Crypt::decrypt($value);
|
||||
}
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
return $value;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
|
39
app/Models/PiggyBankEvent.php
Normal file
39
app/Models/PiggyBankEvent.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class PiggyBankEvent
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class PiggyBankEvent extends Model
|
||||
{
|
||||
|
||||
protected $fillable = ['piggy_bank_id', 'transaction_journal_id', 'date', 'amount'];
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'date'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function piggyBank()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\PiggyBank');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function transactionJournal()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
|
||||
}
|
66
app/Models/PiggyBankRepetition.php
Normal file
66
app/Models/PiggyBankRepetition.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class PiggyBankRepetition
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class PiggyBankRepetition extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'startdate', 'targetdate'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function piggyBank()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\PiggyBank');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EloquentBuilder $query
|
||||
* @param Carbon $start
|
||||
* @param Carbon $target
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function scopeOnDates(EloquentBuilder $query, Carbon $start, Carbon $target)
|
||||
{
|
||||
return $query->where('startdate', $start->format('Y-m-d'))->where('targetdate', $target->format('Y-m-d'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EloquentBuilder $query
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function scopeRelevantOnDate(EloquentBuilder $query, Carbon $date)
|
||||
{
|
||||
return $query->where(
|
||||
function (EloquentBuilder $q) use ($date) {
|
||||
$q->where('startdate', '<=', $date->format('Y-m-d 00:00:00'));
|
||||
$q->orWhereNull('startdate');
|
||||
}
|
||||
)
|
||||
->where(
|
||||
function (EloquentBuilder $q) use ($date) {
|
||||
|
||||
$q->where('targetdate', '>=', $date->format('Y-m-d 00:00:00'));
|
||||
$q->orWhereNull('targetdate');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
106
app/Models/Reminder.php
Normal file
106
app/Models/Reminder.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Crypt;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class Reminder
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class Reminder extends Model
|
||||
{
|
||||
|
||||
|
||||
protected $fillable = ['user_id', 'startdate', 'metadata', 'enddate', 'active', 'notnow', 'remindersable_id', 'remindersable_type',];
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getActiveAttribute($value)
|
||||
{
|
||||
return intval($value) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'startdate', 'enddate'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMetadataAttribute($value)
|
||||
{
|
||||
if (intval($this->encrypted) == 1) {
|
||||
return json_decode(Crypt::decrypt($value));
|
||||
}
|
||||
|
||||
return json_decode($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getNotnowAttribute($value)
|
||||
{
|
||||
return intval($value) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
|
||||
*/
|
||||
public function remindersable()
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EloquentBuilder $query
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function scopeOnDates(EloquentBuilder $query, Carbon $start, Carbon $end)
|
||||
{
|
||||
return $query->where('reminders.startdate', '=', $start->format('Y-m-d 00:00:00'))->where('reminders.enddate', '=', $end->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
|
||||
public function scopeToday(EloquentBuilder $query)
|
||||
{
|
||||
$today = new Carbon;
|
||||
|
||||
return $query->where('startdate', '<=', $today->format('Y-m-d 00:00:00'))->where('enddate', '>=', $today->format('Y-m-d 00:00:00'))->where('active', 1)
|
||||
->where('notnow', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
*/
|
||||
public function setMetadataAttribute($value)
|
||||
{
|
||||
$this->attributes['encrypted'] = true;
|
||||
$this->attributes['metadata'] = Crypt::encrypt(json_encode($value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
}
|
72
app/Models/Transaction.php
Normal file
72
app/Models/Transaction.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
* Class Transaction
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class Transaction extends Model
|
||||
{
|
||||
|
||||
protected $fillable = ['account_id', 'transaction_journal_id', 'description', 'amount'];
|
||||
protected $rules
|
||||
= [
|
||||
'account_id' => 'required|exists:accounts,id',
|
||||
'transaction_journal_id' => 'required|exists:transaction_journals,id',
|
||||
'description' => 'between:1,255',
|
||||
'amount' => 'required|numeric'
|
||||
];
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function account()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\Account');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EloquentBuilder $query
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function scopeAfter(EloquentBuilder $query, Carbon $date)
|
||||
{
|
||||
return $query->where('transaction_journals.date', '>=', $date->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param EloquentBuilder $query
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function scopeBefore(EloquentBuilder $query, Carbon $date)
|
||||
{
|
||||
return $query->where('transaction_journals.date', '<=', $date->format('Y-m-d 00:00:00'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'deleted_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function transactionJournal()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
}
|
33
app/Models/TransactionCurrency.php
Normal file
33
app/Models/TransactionCurrency.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* Class TransactionCurrency
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class TransactionCurrency extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
|
||||
protected $fillable = ['name', 'code', 'symbol'];
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'deleted_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function transactionJournals()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
}
|
39
app/Models/TransactionGroup.php
Normal file
39
app/Models/TransactionGroup.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* Class TransactionGroup
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class TransactionGroup extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'deleted_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*/
|
||||
public function transactionjournals()
|
||||
{
|
||||
return $this->belongsToMany('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('FireflyIII\User');
|
||||
}
|
||||
|
||||
}
|
@@ -55,6 +55,19 @@ class TransactionJournal extends Model
|
||||
return $this->belongsToMany('FireflyIII\Models\Category');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function getAmountAttribute()
|
||||
{
|
||||
/** @var Transaction $t */
|
||||
foreach ($this->transactions as $t) {
|
||||
if ($t->amount > 0) {
|
||||
return floatval($t->amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
|
21
app/Models/TransactionRelation.php
Normal file
21
app/Models/TransactionRelation.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Class TransactionRelation
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class TransactionRelation extends Model
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at'];
|
||||
}
|
||||
|
||||
}
|
30
app/Models/TransactionType.php
Normal file
30
app/Models/TransactionType.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php namespace FireflyIII\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
|
||||
/**
|
||||
* Class TransactionType
|
||||
*
|
||||
* @package FireflyIII\Models
|
||||
*/
|
||||
class TransactionType extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDates()
|
||||
{
|
||||
return ['created_at', 'updated_at', 'deleted_at'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
*/
|
||||
public function transactionJournals()
|
||||
{
|
||||
return $this->hasMany('FireflyIII\Models\TransactionJournal');
|
||||
}
|
||||
}
|
@@ -1,17 +1,19 @@
|
||||
<?php namespace FireflyIII\Providers;
|
||||
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Support\Facades\Navigation;
|
||||
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
|
||||
use Illuminate\Database\QueryException;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
|
||||
use Log;
|
||||
use FireflyIII\Models\Reminder;
|
||||
|
||||
/**
|
||||
* Class EventServiceProvider
|
||||
@@ -28,12 +30,14 @@ class EventServiceProvider extends ServiceProvider
|
||||
*/
|
||||
protected $listen
|
||||
= [
|
||||
'event.name' => [
|
||||
'EventListener',
|
||||
],
|
||||
'App\Events\JournalDeleted' => [
|
||||
'App\Handlers\Events\JournalDeletedHandler@handle',
|
||||
'FireflyIII\Events\JournalSaved' => [
|
||||
'FireflyIII\Handlers\Events\RescanJournal',
|
||||
'FireflyIII\Handlers\Events\UpdateJournalConnection',
|
||||
|
||||
],
|
||||
'FireflyIII\Events\JournalCreated' => [
|
||||
'FireflyIII\Handlers\Events\ConnectJournalToPiggyBank',
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -57,6 +61,17 @@ class EventServiceProvider extends ServiceProvider
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
PiggyBank::deleting(
|
||||
function (PiggyBank $piggyBank) {
|
||||
$reminders = $piggyBank->reminders()->get();
|
||||
/** @var Reminder $reminder */
|
||||
foreach ($reminders as $reminder) {
|
||||
$reminder->delete();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Account::deleted(
|
||||
function (Account $account) {
|
||||
|
||||
@@ -68,14 +83,18 @@ class EventServiceProvider extends ServiceProvider
|
||||
}
|
||||
);
|
||||
|
||||
PiggyBank::created(function(PiggyBank $piggyBank) {
|
||||
// move this routine to a filter
|
||||
// in case of repeated piggy banks and/or other problems.
|
||||
PiggyBank::created(
|
||||
function (PiggyBank $piggyBank) {
|
||||
$repetition = new PiggyBankRepetition;
|
||||
$repetition->piggyBank()->associate($piggyBank);
|
||||
$repetition->startdate = $piggyBank->startdate;
|
||||
$repetition->targetdate = $piggyBank->targetdate;
|
||||
$repetition->startdate = is_null($piggyBank->startdate) ? null : $piggyBank->startdate;
|
||||
$repetition->targetdate = is_null($piggyBank->targetdate) ? null : $piggyBank->targetdate;
|
||||
$repetition->currentamount = 0;
|
||||
$repetition->save();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
BudgetLimit::saved(
|
||||
function (BudgetLimit $budgetLimit) {
|
||||
|
@@ -62,11 +62,15 @@ class FireflyServiceProvider extends ServiceProvider
|
||||
$this->app->bind('FireflyIII\Repositories\Journal\JournalRepositoryInterface', 'FireflyIII\Repositories\Journal\JournalRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\Bill\BillRepositoryInterface', 'FireflyIII\Repositories\Bill\BillRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface', 'FireflyIII\Repositories\PiggyBank\PiggyBankRepository');
|
||||
$this->app->bind('FireflyIII\Repositories\Currency\CurrencyRepositoryInterface', 'FireflyIII\Repositories\Currency\CurrencyRepository');
|
||||
$this->app->bind('FireflyIII\Support\Search\SearchInterface', 'FireflyIII\Support\Search\Search');
|
||||
|
||||
|
||||
$this->app->bind('FireflyIII\Helpers\Help\HelpInterface', 'FireflyIII\Helpers\Help\Help');
|
||||
$this->app->bind('FireflyIII\Helpers\Reminders\ReminderHelperInterface', 'FireflyIII\Helpers\Reminders\ReminderHelper');
|
||||
$this->app->bind('FireflyIII\Helpers\Report\ReportHelperInterface', 'FireflyIII\Helpers\Report\ReportHelper');
|
||||
$this->app->bind('FireflyIII\Helpers\Report\ReportQueryInterface', 'FireflyIII\Helpers\Report\ReportQuery');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<?php namespace FireflyIII\Providers;
|
||||
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Router;
|
||||
|
||||
/**
|
||||
@@ -32,22 +31,6 @@ class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
parent::boot($router);
|
||||
|
||||
$router->before(
|
||||
function (Request $request) {
|
||||
|
||||
// put IP in session if not already there.
|
||||
|
||||
$reminders = [];
|
||||
|
||||
if ($request->user()) {
|
||||
//Filter::setSessionDateRange();
|
||||
//Reminders::updateReminders();
|
||||
//Steam::removeEmptyBudgetLimits();
|
||||
//$reminders = Reminders::getReminders();
|
||||
}
|
||||
// View::share('reminders', $reminders);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -25,4 +25,4 @@ class TestingServiceProvider extends ServiceProvider
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -6,16 +6,21 @@ use App;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Session;
|
||||
use Steam;
|
||||
|
||||
/**
|
||||
* Class AccountRepository
|
||||
@@ -25,6 +30,16 @@ use Session;
|
||||
class AccountRepository implements AccountRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param array $types
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countAccounts(array $types)
|
||||
{
|
||||
return Auth::user()->accounts()->accountTypeIn($types)->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
@@ -38,34 +53,270 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $types
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAccounts(array $types)
|
||||
{
|
||||
$result = Auth::user()->accounts()->with(
|
||||
['accountmeta' => function (HasMany $query) {
|
||||
$query->where('name', 'accountRole');
|
||||
}]
|
||||
)->accountTypeIn($types)->orderBy('accounts.name', 'ASC')->get(['accounts.*'])->sortBy('name');
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCreditCards()
|
||||
{
|
||||
return Auth::user()->accounts()
|
||||
->hasMetaValue('accountRole', 'ccAsset')
|
||||
->hasMetaValue('ccType', 'monthlyFull')
|
||||
->get(
|
||||
[
|
||||
'accounts.*',
|
||||
'ccType.data as ccType',
|
||||
'accountRole.data as accountRole'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param Account $account
|
||||
*
|
||||
* @return Transaction
|
||||
*/
|
||||
public function getFirstTransaction(TransactionJournal $journal, Account $account)
|
||||
{
|
||||
|
||||
return $journal->transactions()->where('account_id', $account->id)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getFrontpageAccounts(Preference $preference)
|
||||
{
|
||||
if ($preference->data == []) {
|
||||
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
|
||||
} else {
|
||||
$accounts = Auth::user()->accounts()->whereIn('id', $preference->data)->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
|
||||
}
|
||||
|
||||
return $accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used on the front page where (in turn) its viewed journals-tiny.php which (in turn)
|
||||
* is almost the only place where formatJournal is used. Aka, we can use some custom querying to get some specific.
|
||||
* fields using left joins.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param int $page
|
||||
* @param string $range
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getJournals(Account $account, $page, $range = 'session')
|
||||
public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
$offset = $page * 50;
|
||||
return Auth::user()
|
||||
->transactionjournals()
|
||||
->with(['transactions'])
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $account->id)
|
||||
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transaction_journals.transaction_currency_id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->before($end)
|
||||
->after($start)
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->take(10)
|
||||
->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param int $page
|
||||
*
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function getJournals(Account $account, $page)
|
||||
{
|
||||
$offset = ($page - 1) * 50;
|
||||
$query = Auth::user()
|
||||
->transactionJournals()
|
||||
->withRelevantData()
|
||||
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transactions.account_id', $account->id)
|
||||
->orderBy('date', 'DESC');
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC');
|
||||
|
||||
if ($range == 'session') {
|
||||
$query->before(Session::get('end', Carbon::now()->startOfMonth()));
|
||||
$query->after(Session::get('start', Carbon::now()->startOfMonth()));
|
||||
}
|
||||
$query->before(Session::get('end', Carbon::now()->endOfMonth()));
|
||||
$query->after(Session::get('start', Carbon::now()->startOfMonth()));
|
||||
$count = $query->count();
|
||||
$set = $query->take(50)->offset($offset)->get(['transaction_journals.*']);
|
||||
$paginator = new LengthAwarePaginator($set, $count, 50, $page);
|
||||
|
||||
return $paginator;
|
||||
|
||||
//return Paginator::make($items, $count, 50);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public function getLastActivity(Account $account)
|
||||
{
|
||||
$lastTransaction = $account->transactions()->leftJoin(
|
||||
'transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)->orderBy('transaction_journals.date', 'DESC')->first(['transactions.*', 'transaction_journals.date']);
|
||||
if ($lastTransaction) {
|
||||
return $lastTransaction->transactionjournal->date;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the accounts of a user that have piggy banks connected to them.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getPiggyBankAccounts()
|
||||
{
|
||||
$ids = [];
|
||||
$start = clone Session::get('start', new Carbon);
|
||||
$end = clone Session::get('end', new Carbon);
|
||||
$accountIds = DB::table('piggy_banks')->distinct()->get(['piggy_banks.account_id']);
|
||||
$accounts = new Collection;
|
||||
|
||||
foreach ($accountIds as $id) {
|
||||
$ids[] = intval($id->account_id);
|
||||
}
|
||||
|
||||
$ids = array_unique($ids);
|
||||
if (count($ids) > 0) {
|
||||
$accounts = Auth::user()->accounts()->whereIn('id', $ids)->get();
|
||||
}
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($start, $end) {
|
||||
$account->startBalance = Steam::balance($account, $start, true);
|
||||
$account->endBalance = Steam::balance($account, $end, true);
|
||||
$account->piggyBalance = 0;
|
||||
/** @var PiggyBank $piggyBank */
|
||||
foreach ($account->piggyBanks as $piggyBank) {
|
||||
$account->piggyBalance += $piggyBank->currentRelevantRep()->currentamount;
|
||||
}
|
||||
// sum of piggy bank amounts on this account:
|
||||
// diff between endBalance and piggyBalance.
|
||||
// then, percentage.
|
||||
$difference = $account->endBalance - $account->piggyBalance;
|
||||
$account->difference = $difference;
|
||||
$account->percentage = $difference != 0 ? round((($difference / $account->endBalance) * 100)) : 100;
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
return $accounts;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get savings accounts and the balance difference in the period.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getSavingsAccounts()
|
||||
{
|
||||
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')
|
||||
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
|
||||
->where('account_meta.name', 'accountRole')
|
||||
->where('account_meta.data', '"savingAsset"')
|
||||
->get(['accounts.*']);
|
||||
$start = clone Session::get('start', new Carbon);
|
||||
$end = clone Session::get('end', new Carbon);
|
||||
|
||||
$accounts->each(
|
||||
function (Account $account) use ($start, $end) {
|
||||
$account->startBalance = Steam::balance($account, $start);
|
||||
$account->endBalance = Steam::balance($account, $end);
|
||||
|
||||
// diff (negative when lost, positive when gained)
|
||||
$diff = $account->endBalance - $account->startBalance;
|
||||
|
||||
if ($diff < 0 && $account->startBalance > 0) {
|
||||
// percentage lost compared to start.
|
||||
$pct = (($diff * -1) / $account->startBalance) * 100;
|
||||
} else {
|
||||
if ($diff >= 0 && $account->startBalance > 0) {
|
||||
$pct = ($diff / $account->startBalance) * 100;
|
||||
} else {
|
||||
$pct = 100;
|
||||
}
|
||||
}
|
||||
$pct = $pct > 100 ? 100 : $pct;
|
||||
$account->difference = $diff;
|
||||
$account->percentage = round($pct);
|
||||
}
|
||||
);
|
||||
|
||||
return $accounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all transfers TO this account in this range.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getTransfersInRange(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
return TransactionJournal::whereIn(
|
||||
'id', function ($q) use ($account, $start, $end) {
|
||||
$q->select('transaction_journals.id')
|
||||
->from('transactions')
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->where('transactions.account_id', $account->id)
|
||||
->where('transaction_journals.user_id', Auth::user()->id)
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
|
||||
->where('transactions.amount', '>', 0)
|
||||
->where('transaction_types.type', 'Transfer');
|
||||
|
||||
}
|
||||
)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function leftOnAccount(Account $account)
|
||||
{
|
||||
$balance = \Steam::balance($account, null, true);
|
||||
/** @var PiggyBank $p */
|
||||
foreach ($account->piggybanks()->get() as $p) {
|
||||
$balance -= $p->currentRelevantRep()->currentamount;
|
||||
}
|
||||
|
||||
return $balance;
|
||||
|
||||
}
|
||||
|
||||
@@ -89,21 +340,22 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*/
|
||||
public function store(array $data)
|
||||
{
|
||||
$newAccount = $this->_store($data);
|
||||
$this->_storeMetadata($newAccount, $data);
|
||||
$newAccount = $this->storeAccount($data);
|
||||
$this->storeMetadata($newAccount, $data);
|
||||
|
||||
|
||||
// continue with the opposing account:
|
||||
if ($data['openingBalance'] != 0) {
|
||||
$type = $data['openingBalance'] < 0 ? 'expense' : 'revenue';
|
||||
$opposingData = [
|
||||
'user' => $data['user'],
|
||||
'accountType' => $type,
|
||||
'name' => $data['name'] . ' initial balance',
|
||||
'active' => false,
|
||||
'user' => $data['user'],
|
||||
'accountType' => $type,
|
||||
'virtual_balance' => $data['virtualBalance'],
|
||||
'name' => $data['name'] . ' initial balance',
|
||||
'active' => false,
|
||||
];
|
||||
$opposing = $this->_store($opposingData);
|
||||
$this->_storeInitialBalance($newAccount, $opposing, $data);
|
||||
$opposing = $this->storeAccount($opposingData);
|
||||
$this->storeInitialBalance($newAccount, $opposing, $data);
|
||||
|
||||
}
|
||||
|
||||
@@ -111,6 +363,14 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function sumOfEverything()
|
||||
{
|
||||
return floatval(Auth::user()->transactions()->sum('amount'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
@@ -118,18 +378,13 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
public function update(Account $account, array $data)
|
||||
{
|
||||
// update the account:
|
||||
$account->name = $data['name'];
|
||||
$account->active = $data['active'] == '1' ? true : false;
|
||||
$account->name = $data['name'];
|
||||
$account->active = $data['active'] == '1' ? true : false;
|
||||
$account->virtual_balance = $data['virtualBalance'];
|
||||
$account->save();
|
||||
|
||||
// update meta data:
|
||||
/** @var AccountMeta $meta */
|
||||
foreach ($account->accountMeta()->get() as $meta) {
|
||||
if ($meta->name == 'accountRole') {
|
||||
$meta->data = $data['accountRole'];
|
||||
$meta->save();
|
||||
}
|
||||
}
|
||||
$this->updateMetadata($account, $data);
|
||||
|
||||
$openingBalance = $this->openingBalanceTransaction($account);
|
||||
|
||||
@@ -138,7 +393,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
// if opening balance, do an update:
|
||||
if ($openingBalance) {
|
||||
// update existing opening balance.
|
||||
$this->_updateInitialBalance($account, $openingBalance, $data);
|
||||
$this->updateInitialBalance($account, $openingBalance, $data);
|
||||
} else {
|
||||
// create new opening balance.
|
||||
$type = $data['openingBalance'] < 0 ? 'expense' : 'revenue';
|
||||
@@ -148,8 +403,8 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
'name' => $data['name'] . ' initial balance',
|
||||
'active' => false,
|
||||
];
|
||||
$opposing = $this->_store($opposingData);
|
||||
$this->_storeInitialBalance($account, $opposing, $data);
|
||||
$opposing = $this->storeAccount($opposingData);
|
||||
$this->storeInitialBalance($account, $opposing, $data);
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -168,7 +423,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*
|
||||
* @return Account
|
||||
*/
|
||||
protected function _store(array $data)
|
||||
protected function storeAccount(array $data)
|
||||
{
|
||||
$type = Config::get('firefly.accountTypeByIdentifier.' . $data['accountType']);
|
||||
$accountType = AccountType::whereType($type)->first();
|
||||
@@ -180,12 +435,14 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
'active' => $data['active'] === true ? true : false,
|
||||
]
|
||||
);
|
||||
|
||||
if (!$newAccount->isValid()) {
|
||||
// does the account already exist?
|
||||
$existingAccount = Account::where('user_id', $data['user'])->where('account_type_id', $accountType->id)->where('name', $data['name'])->first();
|
||||
if (!$existingAccount) {
|
||||
Log::error('Account create error: ' . $newAccount->getErrors()->toJson());
|
||||
var_dump($newAccount->getErrors()->toArray());
|
||||
App::abort(500);
|
||||
|
||||
}
|
||||
$newAccount = $existingAccount;
|
||||
}
|
||||
@@ -198,19 +455,23 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
protected function _storeMetadata(Account $account, array $data)
|
||||
protected function storeMetadata(Account $account, array $data)
|
||||
{
|
||||
$metaData = new AccountMeta(
|
||||
[
|
||||
'account_id' => $account->id,
|
||||
'name' => 'accountRole',
|
||||
'data' => $data['accountRole']
|
||||
]
|
||||
);
|
||||
if (!$metaData->isValid()) {
|
||||
App::abort(500);
|
||||
$validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType'];
|
||||
foreach ($validFields as $field) {
|
||||
if (isset($data[$field])) {
|
||||
$metaData = new AccountMeta(
|
||||
[
|
||||
'account_id' => $account->id,
|
||||
'name' => $field,
|
||||
'data' => $data[$field]
|
||||
]
|
||||
);
|
||||
$metaData->save();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
$metaData->save();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -220,7 +481,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
protected function _storeInitialBalance(Account $account, Account $opposing, array $data)
|
||||
protected function storeInitialBalance(Account $account, Account $opposing, array $data)
|
||||
{
|
||||
$type = $data['openingBalance'] < 0 ? 'Withdrawal' : 'Deposit';
|
||||
$transactionType = TransactionType::whereType($type)->first();
|
||||
@@ -285,6 +546,37 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param array $data
|
||||
*/
|
||||
protected function updateMetadata(Account $account, array $data)
|
||||
{
|
||||
$validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType'];
|
||||
|
||||
foreach ($validFields as $field) {
|
||||
$entry = $account->accountMeta()->where('name', $field)->first();
|
||||
|
||||
// update if new data is present:
|
||||
if ($entry && isset($data[$field])) {
|
||||
$entry->data = $data[$field];
|
||||
$entry->save();
|
||||
}
|
||||
// no entry but data present?
|
||||
if (!$entry && isset($data[$field])) {
|
||||
$metaData = new AccountMeta(
|
||||
[
|
||||
'account_id' => $account->id,
|
||||
'name' => $field,
|
||||
'data' => $data[$field]
|
||||
]
|
||||
);
|
||||
$metaData->save();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param TransactionJournal $journal
|
||||
@@ -292,7 +584,7 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
protected function _updateInitialBalance(Account $account, TransactionJournal $journal, array $data)
|
||||
protected function updateInitialBalance(Account $account, TransactionJournal $journal, array $data)
|
||||
{
|
||||
$journal->date = $data['openingBalanceDate'];
|
||||
|
||||
@@ -310,21 +602,4 @@ class AccountRepository implements AccountRepositoryInterface
|
||||
|
||||
return $journal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function leftOnAccount(Account $account)
|
||||
{
|
||||
$balance = \Steam::balance($account);
|
||||
/** @var PiggyBank $p */
|
||||
foreach ($account->piggybanks()->get() as $p) {
|
||||
$balance -= $p->currentRelevantRep()->currentamount;
|
||||
}
|
||||
|
||||
return $balance;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,13 @@
|
||||
|
||||
namespace FireflyIII\Repositories\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface AccountRepositoryInterface
|
||||
@@ -12,6 +17,13 @@ use FireflyIII\Models\TransactionJournal;
|
||||
*/
|
||||
interface AccountRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @param array $types
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countAccounts(array $types);
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
@@ -20,13 +32,93 @@ interface AccountRepositoryInterface
|
||||
public function destroy(Account $account);
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param int $page
|
||||
* @param string $range
|
||||
* @param array $types
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getJournals(Account $account, $page, $range = 'session');
|
||||
public function getAccounts(array $types);
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param Account $account
|
||||
*
|
||||
* @return Transaction
|
||||
*/
|
||||
public function getFirstTransaction(TransactionJournal $journal, Account $account);
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCreditCards();
|
||||
|
||||
/**
|
||||
* Get the accounts of a user that have piggy banks connected to them.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getPiggyBankAccounts();
|
||||
|
||||
|
||||
/**
|
||||
* Get all transfers TO this account in this range.
|
||||
*
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getTransfersInRange(Account $account, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getFrontpageAccounts(Preference $preference);
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
* @param string $range
|
||||
*
|
||||
* @return LengthAwarePaginator
|
||||
*/
|
||||
public function getJournals(Account $account, $page);
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public function getLastActivity(Account $account);
|
||||
|
||||
/**
|
||||
* @return float
|
||||
*/
|
||||
public function sumOfEverything();
|
||||
|
||||
/**
|
||||
* Get savings accounts and the balance difference in the period.
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getSavingsAccounts();
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function leftOnAccount(Account $account);
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
@@ -49,11 +141,4 @@ interface AccountRepositoryInterface
|
||||
* @return Account
|
||||
*/
|
||||
public function update(Account $account, array $data);
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function leftOnAccount(Account $account);
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 25/02/15
|
||||
* Time: 07:40
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Repositories\Bill;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Navigation;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
|
||||
/**
|
||||
* Class BillRepository
|
||||
@@ -21,6 +21,179 @@ use Log;
|
||||
*/
|
||||
class BillRepository implements BillRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Create a fake bill to help the chart controller.
|
||||
*
|
||||
* @param string $description
|
||||
* @param Carbon $date
|
||||
* @param float $amount
|
||||
*
|
||||
* @return Bill
|
||||
*/
|
||||
public function createFakeBill($description, Carbon $date, $amount)
|
||||
{
|
||||
$bill = new Bill;
|
||||
$bill->name = $description;
|
||||
$bill->match = $description;
|
||||
$bill->amount_min = $amount;
|
||||
$bill->amount_max = $amount;
|
||||
$bill->date = $date;
|
||||
$bill->repeat_freq = 'monthly';
|
||||
$bill->skip = 0;
|
||||
$bill->automatch = false;
|
||||
$bill->active = false;
|
||||
|
||||
return $bill;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function destroy(Bill $bill)
|
||||
{
|
||||
return $bill->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getActiveBills()
|
||||
{
|
||||
/** @var Collection $set */
|
||||
$set = Auth::user()->bills()->orderBy('name', 'ASC')->where('active', 1)->get()->sortBy('name');
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBills()
|
||||
{
|
||||
/** @var Collection $set */
|
||||
$set = Auth::user()->bills()->orderBy('name', 'ASC')->get()->sortBy('name');
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournals(Bill $bill)
|
||||
{
|
||||
return $bill->transactionjournals()->withRelevantData()
|
||||
->leftJoin(
|
||||
'transactions', function (JoinClause $join) {
|
||||
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transactions.amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->get(['transaction_journals.*', 'transactions.amount']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all journals that were recorded on this bill between these dates.
|
||||
*
|
||||
* @param Bill $bill
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournalsInRange(Bill $bill, Carbon $start, Carbon $end)
|
||||
{
|
||||
return $bill->transactionjournals()->before($end)->after($start)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getPossiblyRelatedJournals(Bill $bill)
|
||||
{
|
||||
$set = \DB::table('transactions')->where('amount', '>', 0)->where('amount', '>=', $bill->amount_min)->where('amount', '<=', $bill->amount_max)->get(
|
||||
['transaction_journal_id']
|
||||
);
|
||||
$ids = [];
|
||||
|
||||
/** @var Transaction $entry */
|
||||
foreach ($set as $entry) {
|
||||
$ids[] = intval($entry->transaction_journal_id);
|
||||
}
|
||||
$journals = new Collection;
|
||||
if (count($ids) > 0) {
|
||||
$journals = Auth::user()->transactionjournals()->whereIn('id', $ids)->get();
|
||||
}
|
||||
|
||||
return $journals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Every bill repeats itself weekly, monthly or yearly (or whatever). This method takes a date-range (usually the view-range of Firefly itself)
|
||||
* and returns date ranges that fall within the given range; those ranges are the bills expected. When a bill is due on the 14th of the month and
|
||||
* you give 1st and the 31st of that month as argument, you'll get one response, matching the range of your bill.
|
||||
*
|
||||
* @param Bill $bill
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRanges(Bill $bill, Carbon $start, Carbon $end)
|
||||
{
|
||||
$startOfBill = $bill->date;
|
||||
$startOfBill = Navigation::startOfPeriod($startOfBill, $bill->repeat_freq);
|
||||
|
||||
|
||||
// all periods of this bill up until the current period:
|
||||
$billStarts = [];
|
||||
while ($startOfBill < $end) {
|
||||
|
||||
$endOfBill = Navigation::endOfPeriod($startOfBill, $bill->repeat_freq);
|
||||
|
||||
$billStarts[] = [
|
||||
'start' => clone $startOfBill,
|
||||
'end' => clone $endOfBill,
|
||||
];
|
||||
// actually the next one:
|
||||
$startOfBill = Navigation::addPeriod($startOfBill, $bill->repeat_freq, $bill->skip);
|
||||
|
||||
}
|
||||
// for each
|
||||
$validRanges = [];
|
||||
foreach ($billStarts as $dateEntry) {
|
||||
if ($dateEntry['end'] > $start && $dateEntry['start'] < $end) {
|
||||
// count transactions for bill in this range (not relevant yet!):
|
||||
$validRanges[] = $dateEntry;
|
||||
}
|
||||
}
|
||||
|
||||
return $validRanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public function lastFoundMatch(Bill $bill)
|
||||
{
|
||||
$last = $bill->transactionjournals()->orderBy('date', 'DESC')->first();
|
||||
if ($last) {
|
||||
return $last->date;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
@@ -28,6 +201,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
*/
|
||||
public function nextExpectedMatch(Bill $bill)
|
||||
{
|
||||
|
||||
$finalDate = null;
|
||||
if ($bill->active == 0) {
|
||||
return $finalDate;
|
||||
@@ -113,7 +287,7 @@ class BillRepository implements BillRepositoryInterface
|
||||
$wordMatch = true;
|
||||
Log::debug('word match is true');
|
||||
} else {
|
||||
Log::debug('Count: ' . $count.', count(matches): ' . count($matches));
|
||||
Log::debug('Count: ' . $count . ', count(matches): ' . count($matches));
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +315,12 @@ class BillRepository implements BillRepositoryInterface
|
||||
Log::debug('TOTAL match is true!');
|
||||
$journal->bill()->associate($bill);
|
||||
$journal->save();
|
||||
} else {
|
||||
if ((!$wordMatch || !$amountMatch) && $bill->id == $journal->bill_id) {
|
||||
// if no match, but bill used to match, remove it:
|
||||
$journal->bill_id = null;
|
||||
$journal->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,22 +1,93 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: sander
|
||||
* Date: 25/02/15
|
||||
* Time: 07:40
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Repositories\Bill;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Bill;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface BillRepositoryInterface
|
||||
*
|
||||
* @package FireflyIII\Repositories\Bill
|
||||
*/
|
||||
interface BillRepositoryInterface {
|
||||
interface BillRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Create a fake bill to help the chart controller.
|
||||
*
|
||||
* @param string $description
|
||||
* @param Carbon $date
|
||||
* @param float $amount
|
||||
*
|
||||
* @return Bill
|
||||
*/
|
||||
public function createFakeBill($description, Carbon $date, $amount);
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function destroy(Bill $bill);
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getActiveBills();
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBills();
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournals(Bill $bill);
|
||||
|
||||
/**
|
||||
* Get all journals that were recorded on this bill between these dates.
|
||||
*
|
||||
* @param Bill $bill
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournalsInRange(Bill $bill, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getPossiblyRelatedJournals(Bill $bill);
|
||||
|
||||
/**
|
||||
* Every bill repeats itself weekly, monthly or yearly (or whatever). This method takes a date-range (usually the view-range of Firefly itself)
|
||||
* and returns date ranges that fall within the given range; those ranges are the bills expected. When a bill is due on the 14th of the month and
|
||||
* you give 1st and the 31st of that month as argument, you'll get one response, matching the range of your bill.
|
||||
*
|
||||
* @param Bill $bill
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getRanges(Bill $bill, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public function lastFoundMatch(Bill $bill);
|
||||
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
@@ -25,6 +96,14 @@ interface BillRepositoryInterface {
|
||||
*/
|
||||
public function nextExpectedMatch(Bill $bill);
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function scan(Bill $bill, TransactionJournal $journal);
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
@@ -40,12 +119,4 @@ interface BillRepositoryInterface {
|
||||
*/
|
||||
public function update(Bill $bill, array $data);
|
||||
|
||||
/**
|
||||
* @param Bill $bill
|
||||
* @param TransactionJournal $journal
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function scan(Bill $bill, TransactionJournal $journal);
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -2,11 +2,14 @@
|
||||
|
||||
namespace FireflyIII\Repositories\Budget;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class BudgetRepository
|
||||
@@ -16,6 +19,31 @@ use Illuminate\Pagination\LengthAwarePaginator;
|
||||
class BudgetRepository implements BudgetRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function cleanupBudgets()
|
||||
{
|
||||
$limits = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')->get(['budget_limits.*']);
|
||||
|
||||
// loop budget limits:
|
||||
$found = [];
|
||||
/** @var BudgetLimit $limit */
|
||||
foreach ($limits as $limit) {
|
||||
$key = $limit->budget_id . '-' . $limit->startdate;
|
||||
if (isset($found[$key])) {
|
||||
$limit->delete();
|
||||
} else {
|
||||
$found[$key] = true;
|
||||
}
|
||||
unset($key);
|
||||
}
|
||||
|
||||
// delete limits with amount 0:
|
||||
BudgetLimit::where('amount', 0)->delete();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
*
|
||||
@@ -28,6 +56,101 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function expensesOnDay(Budget $budget, Carbon $date)
|
||||
{
|
||||
return floatval($budget->transactionjournals()->lessThan(0)->transactionTypes(['Withdrawal'])->onDate($date)->sum('amount'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getActiveBudgets()
|
||||
{
|
||||
$budgets = Auth::user()->budgets()->where('active', 1)->get();
|
||||
$budgets->sortBy('name');
|
||||
|
||||
return $budgets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end)
|
||||
{
|
||||
/** @var Collection $repetitions */
|
||||
return LimitRepetition::
|
||||
leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
|
||||
->where('limit_repetitions.startdate', '<=', $end->format('Y-m-d 00:00:00'))
|
||||
->where('limit_repetitions.startdate', '>=', $start->format('Y-m-d 00:00:00'))
|
||||
->where('budget_limits.budget_id', $budget->id)
|
||||
->get(['limit_repetitions.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBudgetLimits(Budget $budget)
|
||||
{
|
||||
return $budget->budgetLimits()->orderBy('startdate', 'DESC')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBudgets()
|
||||
{
|
||||
$budgets = Auth::user()->budgets()->get();
|
||||
$budgets->sortBy('name');
|
||||
|
||||
return $budgets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return LimitRepetition|null
|
||||
*/
|
||||
public function getCurrentRepetition(Budget $budget, Carbon $date)
|
||||
{
|
||||
return $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getFirstBudgetLimitDate(Budget $budget)
|
||||
{
|
||||
$limit = $budget->budgetlimits()->orderBy('startdate', 'ASC')->first();
|
||||
if ($limit) {
|
||||
return $limit->startdate;
|
||||
}
|
||||
|
||||
return Carbon::now()->startOfYear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getInactiveBudgets()
|
||||
{
|
||||
return Auth::user()->budgets()->where('active', 0)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all the transaction journals for a limit, possibly limited by a limit repetition.
|
||||
*
|
||||
@@ -42,7 +165,10 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
$offset = intval(\Input::get('page')) > 0 ? intval(\Input::get('page')) * $take : 0;
|
||||
|
||||
|
||||
$setQuery = $budget->transactionJournals()->withRelevantData()->take($take)->offset($offset)->orderBy('date', 'DESC');
|
||||
$setQuery = $budget->transactionJournals()->withRelevantData()->take($take)->offset($offset)
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC');
|
||||
$countQuery = $budget->transactionJournals();
|
||||
|
||||
|
||||
@@ -54,9 +180,95 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
|
||||
$set = $setQuery->get(['transaction_journals.*']);
|
||||
$count = $countQuery->count();
|
||||
|
||||
return new LengthAwarePaginator($set, $count, $take, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getLastBudgetLimitDate(Budget $budget)
|
||||
{
|
||||
$limit = $budget->budgetlimits()->orderBy('startdate', 'DESC')->first();
|
||||
if ($limit) {
|
||||
return $limit->startdate;
|
||||
}
|
||||
|
||||
return Carbon::now()->startOfYear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return float|null
|
||||
*/
|
||||
public function getLimitAmountOnDate(Budget $budget, Carbon $date)
|
||||
{
|
||||
$repetition = LimitRepetition::leftJoin('budget_limits', 'limit_repetitions.budget_limit_id', '=', 'budget_limits.id')
|
||||
->where('limit_repetitions.startdate', $date->format('Y-m-d 00:00:00'))
|
||||
->where('budget_limits.budget_id', $budget->id)
|
||||
->first(['limit_repetitions.*']);
|
||||
|
||||
if ($repetition) {
|
||||
return floatval($repetition->amount);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getWithoutBudget(Carbon $start, Carbon $end)
|
||||
{
|
||||
return Auth::user()
|
||||
->transactionjournals()
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNull('budget_transaction_journal.id')
|
||||
->before($end)
|
||||
->after($start)
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->get(['transaction_journals.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getWithoutBudgetSum(Carbon $start, Carbon $end)
|
||||
{
|
||||
$noBudgetSet = Auth::user()
|
||||
->transactionjournals()
|
||||
->whereNotIn(
|
||||
'transaction_journals.id', function (QueryBuilder $query) use ($start, $end) {
|
||||
$query
|
||||
->select('transaction_journals.id')
|
||||
->from('transaction_journals')
|
||||
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00'))
|
||||
->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00'))
|
||||
->whereNotNull('budget_transaction_journal.budget_id');
|
||||
}
|
||||
)
|
||||
->before($end)
|
||||
->after($start)
|
||||
->lessThan(0)
|
||||
->transactionTypes(['Withdrawal'])
|
||||
->get();
|
||||
|
||||
return floatval($noBudgetSet->sum('amount')) * -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $date
|
||||
@@ -91,6 +303,18 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
return $newBudget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function sumBudgetExpensesInPeriod(Budget $budget, $start, $end)
|
||||
{
|
||||
return floatval($budget->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param array $data
|
||||
@@ -100,7 +324,8 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
public function update(Budget $budget, array $data)
|
||||
{
|
||||
// update the account:
|
||||
$budget->name = $data['name'];
|
||||
$budget->name = $data['name'];
|
||||
$budget->active = $data['active'];
|
||||
$budget->save();
|
||||
|
||||
return $budget;
|
||||
@@ -115,10 +340,12 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
*/
|
||||
public function updateLimitAmount(Budget $budget, Carbon $date, $amount)
|
||||
{
|
||||
// there should be a budget limit for this startdate:
|
||||
/** @var BudgetLimit $limit */
|
||||
$limit = $budget->limitrepetitions()->where('limit_repetitions.startdate', $date)->first(['limit_repetitions.*']);
|
||||
$limit = $budget->budgetlimits()->where('budget_limits.startdate', $date)->first(['budget_limits.*']);
|
||||
|
||||
if (!$limit) {
|
||||
// create one!
|
||||
// if not, create one!
|
||||
$limit = new BudgetLimit;
|
||||
$limit->budget()->associate($budget);
|
||||
$limit->startdate = $date;
|
||||
@@ -126,6 +353,10 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
$limit->repeat_freq = 'monthly';
|
||||
$limit->repeats = 0;
|
||||
$limit->save();
|
||||
|
||||
// likewise, there should be a limit repetition to match the end date
|
||||
// (which is always the end of the month) but that is caught by an event.
|
||||
|
||||
} else {
|
||||
if ($amount > 0) {
|
||||
$limit->amount = $amount;
|
||||
@@ -139,4 +370,4 @@ class BudgetRepository implements BudgetRepositoryInterface
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ namespace FireflyIII\Repositories\Budget;
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Budget;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface BudgetRepositoryInterface
|
||||
@@ -13,6 +14,11 @@ use FireflyIII\Models\LimitRepetition;
|
||||
*/
|
||||
interface BudgetRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function cleanupBudgets();
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
*
|
||||
@@ -26,31 +32,53 @@ interface BudgetRepositoryInterface
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function spentInMonth(Budget $budget, Carbon $date);
|
||||
public function expensesOnDay(Budget $budget, Carbon $date);
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getActiveBudgets();
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBudgetLimits(Budget $budget);
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getBudgets();
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $date
|
||||
* @param $amount
|
||||
*
|
||||
* @return mixed
|
||||
* @return LimitRepetition|null
|
||||
*/
|
||||
public function updateLimitAmount(Budget $budget, Carbon $date, $amount);
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function store(array $data);
|
||||
public function getCurrentRepetition(Budget $budget, Carbon $date);
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param array $data
|
||||
*
|
||||
* @return Budget
|
||||
* @return Carbon
|
||||
*/
|
||||
public function update(Budget $budget, array $data);
|
||||
public function getFirstBudgetLimitDate(Budget $budget);
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getInactiveBudgets();
|
||||
|
||||
/**
|
||||
* Returns all the transaction journals for a limit, possibly limited by a limit repetition.
|
||||
@@ -63,4 +91,76 @@ interface BudgetRepositoryInterface
|
||||
*/
|
||||
public function getJournals(Budget $budget, LimitRepetition $repetition = null, $take = 50);
|
||||
|
||||
}
|
||||
/**
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getLastBudgetLimitDate(Budget $budget);
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getLimitAmountOnDate(Budget $budget, Carbon $date);
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getWithoutBudget(Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getWithoutBudgetSum(Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function spentInMonth(Budget $budget, Carbon $date);
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function store(array $data);
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function sumBudgetExpensesInPeriod(Budget $budget, $start, $end);
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param array $data
|
||||
*
|
||||
* @return Budget
|
||||
*/
|
||||
public function update(Budget $budget, array $data);
|
||||
|
||||
/**
|
||||
* @param Budget $budget
|
||||
* @param Carbon $date
|
||||
* @param $amount
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function updateLimitAmount(Budget $budget, Carbon $date, $amount);
|
||||
|
||||
}
|
||||
|
@@ -2,7 +2,13 @@
|
||||
|
||||
namespace FireflyIII\Repositories\Category;
|
||||
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use FireflyIII\Models\Category;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Database\Query\JoinClause;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class CategoryRepository
|
||||
@@ -12,6 +18,17 @@ use FireflyIII\Models\Category;
|
||||
class CategoryRepository implements CategoryRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countJournals(Category $category)
|
||||
{
|
||||
return $category->transactionJournals()->count();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
@@ -24,6 +41,150 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCategories()
|
||||
{
|
||||
/** @var Collection $set */
|
||||
$set = Auth::user()->categories()->orderBy('name', 'ASC')->get();
|
||||
$set->sortBy(
|
||||
function (Category $category) {
|
||||
return $category->name;
|
||||
}
|
||||
);
|
||||
|
||||
return $set;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCategoriesAndExpenses($start, $end)
|
||||
{
|
||||
return TransactionJournal::
|
||||
where('transaction_journals.user_id', Auth::user()->id)
|
||||
->leftJoin(
|
||||
'transactions',
|
||||
function (JoinClause $join) {
|
||||
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0);
|
||||
}
|
||||
)
|
||||
->leftJoin(
|
||||
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
|
||||
)
|
||||
->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id')
|
||||
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
|
||||
->before($end)
|
||||
->where('categories.user_id', Auth::user()->id)
|
||||
->after($start)
|
||||
->where('transaction_types.type', 'Withdrawal')
|
||||
->groupBy('categories.id')
|
||||
->orderBy('sum', 'DESC')
|
||||
->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `sum`')]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getFirstActivityDate(Category $category)
|
||||
{
|
||||
/** @var TransactionJournal $first */
|
||||
$first = $category->transactionjournals()->orderBy('date', 'ASC')->first();
|
||||
if ($first) {
|
||||
return $first->date;
|
||||
}
|
||||
|
||||
return new Carbon;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param int $page
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournals(Category $category, $page)
|
||||
{
|
||||
$offset = $page > 0 ? $page * 50 : 0;
|
||||
|
||||
return $category->transactionJournals()->withRelevantData()->take(50)->offset($offset)
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->get(
|
||||
['transaction_journals.*']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public function getLatestActivity(Category $category)
|
||||
{
|
||||
$latest = $category->transactionjournals()
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->first();
|
||||
if ($latest) {
|
||||
return $latest->date;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getWithoutCategory(Carbon $start, Carbon $end)
|
||||
{
|
||||
return Auth::user()
|
||||
->transactionjournals()
|
||||
->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNull('category_transaction_journal.id')
|
||||
->before($end)
|
||||
->after($start)
|
||||
->orderBy('transaction_journals.date', 'DESC')
|
||||
->orderBy('transaction_journals.order', 'ASC')
|
||||
->orderBy('transaction_journals.id', 'DESC')
|
||||
->get(['transaction_journals.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function spentInPeriodSum(Category $category, Carbon $start, Carbon $end)
|
||||
{
|
||||
return floatval($category->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function spentOnDaySum(Category $category, Carbon $date)
|
||||
{
|
||||
return floatval($category->transactionjournals()->onDate($date)->lessThan(0)->sum('amount')) * -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
@@ -57,5 +218,4 @@ class CategoryRepository implements CategoryRepositoryInterface
|
||||
|
||||
return $category;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace FireflyIII\Repositories\Category;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\Category;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface CategoryRepositoryInterface
|
||||
@@ -11,6 +13,13 @@ use FireflyIII\Models\Category;
|
||||
*/
|
||||
interface CategoryRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countJournals(Category $category);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
@@ -18,6 +27,66 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
public function destroy(Category $category);
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCategories();
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getCategoriesAndExpenses($start, $end);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getFirstActivityDate(Category $category);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param int $page
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournals(Category $category, $page);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
*
|
||||
* @return Carbon|null
|
||||
*/
|
||||
public function getLatestActivity(Category $category);
|
||||
|
||||
/**
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getWithoutCategory(Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function spentInPeriodSum(Category $category, Carbon $start, Carbon $end);
|
||||
|
||||
/**
|
||||
* @param Category $category
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function spentOnDaySum(Category $category, Carbon $date);
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
@@ -33,4 +102,4 @@ interface CategoryRepositoryInterface
|
||||
*/
|
||||
public function update(Category $category, array $data);
|
||||
|
||||
}
|
||||
}
|
||||
|
84
app/Repositories/Currency/CurrencyRepository.php
Normal file
84
app/Repositories/Currency/CurrencyRepository.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Repositories\Currency;
|
||||
|
||||
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class CurrencyRepository
|
||||
*
|
||||
* @package FireflyIII\Repositories\Currency
|
||||
*/
|
||||
class CurrencyRepository implements CurrencyRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countJournals(TransactionCurrency $currency)
|
||||
{
|
||||
return $currency->transactionJournals()->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
return TransactionCurrency::get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function getCurrencyByPreference(Preference $preference)
|
||||
{
|
||||
$preferred = TransactionCurrency::whereCode($preference->data)->first();
|
||||
if (is_null($preferred)) {
|
||||
$preferred = TransactionCurrency::first();
|
||||
}
|
||||
|
||||
return $preferred;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function store(array $data)
|
||||
{
|
||||
$currency = TransactionCurrency::create(
|
||||
[
|
||||
'name' => $data['name'],
|
||||
'code' => $data['code'],
|
||||
'symbol' => $data['symbol'],
|
||||
]
|
||||
);
|
||||
|
||||
return $currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function update(TransactionCurrency $currency, array $data)
|
||||
{
|
||||
$currency->code = $data['code'];
|
||||
$currency->symbol = $data['symbol'];
|
||||
$currency->name = $data['name'];
|
||||
$currency->save();
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
52
app/Repositories/Currency/CurrencyRepositoryInterface.php
Normal file
52
app/Repositories/Currency/CurrencyRepositoryInterface.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace FireflyIII\Repositories\Currency;
|
||||
|
||||
|
||||
use FireflyIII\Models\Preference;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface CurrencyRepositoryInterface
|
||||
*
|
||||
* @package FireflyIII\Repositories\Currency
|
||||
*/
|
||||
interface CurrencyRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function countJournals(TransactionCurrency $currency);
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function get();
|
||||
|
||||
/**
|
||||
* @param Preference $preference
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function getCurrencyByPreference(Preference $preference);
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function store(array $data);
|
||||
|
||||
/**
|
||||
* @param TransactionCurrency $currency
|
||||
* @param array $data
|
||||
*
|
||||
* @return TransactionCurrency
|
||||
*/
|
||||
public function update(TransactionCurrency $currency, array $data);
|
||||
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace FireflyIII\Repositories\Journal;
|
||||
|
||||
use App;
|
||||
use Auth;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
@@ -11,6 +12,7 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class JournalRepository
|
||||
@@ -20,6 +22,16 @@ use Illuminate\Support\Collection;
|
||||
class JournalRepository implements JournalRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Get users first transaction journal
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
public function first()
|
||||
{
|
||||
return Auth::user()->transactionjournals()->orderBy('date', 'ASC')->first(['transaction_journals.*']);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the account_id, which is the asset account that paid for the transaction.
|
||||
@@ -50,6 +62,26 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
return $journal->transactions()->first()->account_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TransactionType $dbType
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournalsOfType(TransactionType $dbType)
|
||||
{
|
||||
return Auth::user()->transactionjournals()->where('transaction_type_id', $dbType->id)->orderBy('id', 'DESC')->take(50)->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
*
|
||||
* @return TransactionType
|
||||
*/
|
||||
public function getTransactionType($type)
|
||||
{
|
||||
return TransactionType::whereType($type)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $query
|
||||
* @param TransactionJournal $journal
|
||||
@@ -128,7 +160,7 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
|
||||
// store or get category
|
||||
if (strlen($data['category']) > 0) {
|
||||
$category = Category::firstOrCreate(['name' => $data['category'], 'user_id' => $data['user']]);
|
||||
$category = Category::firstOrCreateEncrypted(['name' => $data['category'], 'user_id' => $data['user']]);
|
||||
$journal->categories()->save($category);
|
||||
}
|
||||
|
||||
@@ -139,41 +171,7 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
}
|
||||
|
||||
// store accounts (depends on type)
|
||||
switch ($transactionType->type) {
|
||||
case 'Withdrawal':
|
||||
|
||||
$from = Account::find($data['account_id']);
|
||||
|
||||
if (strlen($data['expense_account']) > 0) {
|
||||
$toType = AccountType::where('type', 'Expense account')->first();
|
||||
$to = Account::firstOrCreate(
|
||||
['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => $data['expense_account'], 'active' => 1]
|
||||
);
|
||||
} else {
|
||||
$toType = AccountType::where('type', 'Cash account')->first();
|
||||
$to = Account::firstOrCreate(['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Deposit':
|
||||
$to = Account::find($data['account_id']);
|
||||
|
||||
if (strlen($data['revenue_account']) > 0) {
|
||||
$fromType = AccountType::where('type', 'Revenue account')->first();
|
||||
$from = Account::firstOrCreate(
|
||||
['user_id' => $data['user'], 'account_type_id' => $fromType->id, 'name' => $data['revenue_account'], 'active' => 1]
|
||||
);
|
||||
} else {
|
||||
$toType = AccountType::where('type', 'Cash account')->first();
|
||||
$from = Account::firstOrCreate(['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1]);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'Transfer':
|
||||
$from = Account::find($data['account_from_id']);
|
||||
$to = Account::find($data['account_to_id']);
|
||||
break;
|
||||
}
|
||||
list($from, $to) = $this->storeAccounts($transactionType, $data);
|
||||
|
||||
// store accompanying transactions.
|
||||
Transaction::create( // first transaction.
|
||||
@@ -198,7 +196,6 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param TransactionJournal $journal
|
||||
* @param array $data
|
||||
@@ -216,7 +213,7 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
// unlink all categories, recreate them:
|
||||
$journal->categories()->detach();
|
||||
if (strlen($data['category']) > 0) {
|
||||
$category = Category::firstOrCreate(['name' => $data['category'], 'user_id' => $data['user']]);
|
||||
$category = Category::firstOrCreateEncrypted(['name' => $data['category'], 'user_id' => $data['user']]);
|
||||
$journal->categories()->save($category);
|
||||
}
|
||||
|
||||
@@ -228,52 +225,20 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
}
|
||||
|
||||
// store accounts (depends on type)
|
||||
switch ($journal->transactionType->type) {
|
||||
case 'Withdrawal':
|
||||
|
||||
$from = Account::find($data['account_id']);
|
||||
|
||||
if (strlen($data['expense_account']) > 0) {
|
||||
$toType = AccountType::where('type', 'Expense account')->first();
|
||||
$to = Account::firstOrCreate(
|
||||
['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => $data['expense_account'], 'active' => 1]
|
||||
);
|
||||
} else {
|
||||
$toType = AccountType::where('type', 'Cash account')->first();
|
||||
$to = Account::firstOrCreate(['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Deposit':
|
||||
$to = Account::find($data['account_id']);
|
||||
|
||||
if (strlen($data['revenue_account']) > 0) {
|
||||
$fromType = AccountType::where('type', 'Revenue account')->first();
|
||||
$from = Account::firstOrCreate(
|
||||
['user_id' => $data['user'], 'account_type_id' => $fromType->id, 'name' => $data['revenue_account'], 'active' => 1]
|
||||
);
|
||||
} else {
|
||||
$toType = AccountType::where('type', 'Cash account')->first();
|
||||
$from = Account::firstOrCreate(['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1]);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'Transfer':
|
||||
$from = Account::find($data['account_from_id']);
|
||||
$to = Account::find($data['account_to_id']);
|
||||
break;
|
||||
}
|
||||
list($from, $to) = $this->storeAccounts($journal->transactionType, $data);
|
||||
|
||||
// update the from and to transaction.
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($journal->transactions()->get() as $transaction) {
|
||||
if ($transaction->account_id === $from->id) {
|
||||
if (floatval($transaction->amount) < 0) {
|
||||
// this is the from transaction, negative amount:
|
||||
$transaction->amount = $data['amount'] * -1;
|
||||
$transaction->amount = $data['amount'] * -1;
|
||||
$transaction->account_id = $from->id;
|
||||
$transaction->save();
|
||||
}
|
||||
if ($transaction->account_id === $to->id) {
|
||||
$transaction->amount = $data['amount'];
|
||||
if (floatval($transaction->amount) > 0) {
|
||||
$transaction->amount = $data['amount'];
|
||||
$transaction->account_id = $to->id;
|
||||
$transaction->save();
|
||||
}
|
||||
}
|
||||
@@ -284,4 +249,64 @@ class JournalRepository implements JournalRepositoryInterface
|
||||
return $journal;
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* @param TransactionType $type
|
||||
* @param array $data
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function storeAccounts(TransactionType $type, array $data)
|
||||
{
|
||||
$from = null;
|
||||
$to = null;
|
||||
switch ($type->type) {
|
||||
case 'Withdrawal':
|
||||
|
||||
$from = Account::find($data['account_id']);
|
||||
|
||||
if (strlen($data['expense_account']) > 0) {
|
||||
$toType = AccountType::where('type', 'Expense account')->first();
|
||||
$to = Account::firstOrCreateEncrypted(
|
||||
['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => $data['expense_account'], 'active' => 1]
|
||||
);
|
||||
} else {
|
||||
$toType = AccountType::where('type', 'Cash account')->first();
|
||||
$to = Account::firstOrCreateEncrypted(
|
||||
['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1]
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Deposit':
|
||||
$to = Account::find($data['account_id']);
|
||||
|
||||
if (strlen($data['revenue_account']) > 0) {
|
||||
$fromType = AccountType::where('type', 'Revenue account')->first();
|
||||
$from = Account::firstOrCreateEncrypted(
|
||||
['user_id' => $data['user'], 'account_type_id' => $fromType->id, 'name' => $data['revenue_account'], 'active' => 1]
|
||||
);
|
||||
} else {
|
||||
$toType = AccountType::where('type', 'Cash account')->first();
|
||||
$from = Account::firstOrCreateEncrypted(
|
||||
['user_id' => $data['user'], 'account_type_id' => $toType->id, 'name' => 'Cash account', 'active' => 1]
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
case 'Transfer':
|
||||
$from = Account::find($data['account_from_id']);
|
||||
$to = Account::find($data['account_to_id']);
|
||||
break;
|
||||
}
|
||||
if (is_null($to->id)) {
|
||||
Log::error('"to"-account is null, so we cannot continue!');
|
||||
App::abort(500, '"to"-account is null, so we cannot continue!');
|
||||
}
|
||||
if (is_null($from->id)) {
|
||||
Log::error('"from"-account is null, so we cannot continue!');
|
||||
App::abort(500, '"from"-account is null, so we cannot continue!');
|
||||
}
|
||||
|
||||
return [$from, $to];
|
||||
}
|
||||
}
|
||||
|
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace FireflyIII\Repositories\Journal;
|
||||
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
@@ -12,6 +14,13 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
interface JournalRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Get users first transaction journal
|
||||
*
|
||||
* @return TransactionJournal
|
||||
*/
|
||||
public function first();
|
||||
|
||||
/**
|
||||
*
|
||||
* Get the account_id, which is the asset account that paid for the transaction.
|
||||
@@ -22,6 +31,13 @@ interface JournalRepositoryInterface
|
||||
*/
|
||||
public function getAssetAccount(TransactionJournal $journal);
|
||||
|
||||
/**
|
||||
* @param TransactionType $dbType
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getJournalsOfType(TransactionType $dbType);
|
||||
|
||||
/**
|
||||
* @param string $query
|
||||
* @param TransactionJournal $journal
|
||||
@@ -30,6 +46,13 @@ interface JournalRepositoryInterface
|
||||
*/
|
||||
public function searchRelated($query, TransactionJournal $journal);
|
||||
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
*
|
||||
* @return TransactionType
|
||||
*/
|
||||
public function getTransactionType($type);
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
@@ -44,4 +67,4 @@ interface JournalRepositoryInterface
|
||||
* @return mixed
|
||||
*/
|
||||
public function update(TransactionJournal $journal, array $data);
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace FireflyIII\Repositories\PiggyBank;
|
||||
|
||||
use Auth;
|
||||
use DB;
|
||||
use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -15,48 +17,6 @@ use Navigation;
|
||||
class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public function store(array $data)
|
||||
{
|
||||
|
||||
$piggyBank = PiggyBank::create($data);
|
||||
|
||||
return $piggyBank;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public function update(PiggyBank $piggyBank, array $data)
|
||||
{
|
||||
/**
|
||||
'rep_length' => $request->get('rep_length'),
|
||||
'rep_every' => intval($request->get('rep_every')),
|
||||
'rep_times' => intval($request->get('rep_times')),
|
||||
'remind_me' => intval($request->get('remind_me')) == 1 ? true : false ,
|
||||
'reminder' => $request->get('reminder'),
|
||||
*/
|
||||
|
||||
$piggyBank->name = $data['name'];
|
||||
$piggyBank->account_id = intval($data['account_id']);
|
||||
$piggyBank->targetamount = floatval($data['targetamount']);
|
||||
$piggyBank->targetdate = $data['targetdate'];
|
||||
$piggyBank->reminder = $data['reminder'];
|
||||
$piggyBank->rep_length = isset($data['rep_length']) ? $data['rep_length'] : null;
|
||||
$piggyBank->rep_every =isset($data['rep_every']) ? $data['rep_every'] : null;
|
||||
$piggyBank->rep_times = isset($data['rep_times']) ? $data['rep_times'] : null;
|
||||
$piggyBank->remind_me = isset($data['remind_me']) ? $data['remind_me'] : null;
|
||||
|
||||
$piggyBank->save();
|
||||
return $piggyBank;
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
|
||||
@@ -126,4 +86,90 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
|
||||
|
||||
return $part;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getEventSummarySet(PiggyBank $piggyBank)
|
||||
{
|
||||
return DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set all piggy banks to order 0.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reset()
|
||||
{
|
||||
DB::table('piggy_banks')
|
||||
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.id')
|
||||
->where('accounts.user_id', Auth::user()->id)
|
||||
->update(['order' => 0, 'piggy_banks.updated_at' => DB::Raw('NOW()')]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* set id of piggy bank.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $order
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setOrder($id, $order)
|
||||
{
|
||||
$piggyBank = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')->where('accounts.user_id', Auth::user()->id)
|
||||
->where('piggy_banks.id', $id)->first(['piggy_banks.*']);
|
||||
if ($piggyBank) {
|
||||
$piggyBank->order = $order;
|
||||
$piggyBank->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public function store(array $data)
|
||||
{
|
||||
$data['remind_me'] = isset($data['remind_me']) && $data['remind_me'] == '1' ? true : false;
|
||||
$piggyBank = PiggyBank::create($data);
|
||||
|
||||
return $piggyBank;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public function update(PiggyBank $piggyBank, array $data)
|
||||
{
|
||||
/**
|
||||
* 'rep_length' => $request->get('rep_length'),
|
||||
* 'rep_every' => intval($request->get('rep_every')),
|
||||
* 'rep_times' => intval($request->get('rep_times')),
|
||||
* 'remind_me' => intval($request->get('remind_me')) == 1 ? true : false ,
|
||||
* 'reminder' => $request->get('reminder'),
|
||||
*/
|
||||
|
||||
$piggyBank->name = $data['name'];
|
||||
$piggyBank->account_id = intval($data['account_id']);
|
||||
$piggyBank->targetamount = floatval($data['targetamount']);
|
||||
$piggyBank->targetdate = $data['targetdate'];
|
||||
$piggyBank->reminder = $data['reminder'];
|
||||
$piggyBank->startdate = $data['startdate'];
|
||||
$piggyBank->remind_me = isset($data['remind_me']) && $data['remind_me'] == '1' ? 1 : 0;
|
||||
|
||||
$piggyBank->save();
|
||||
|
||||
return $piggyBank;
|
||||
}
|
||||
}
|
||||
|
@@ -11,23 +11,8 @@ use Illuminate\Support\Collection;
|
||||
*
|
||||
* @package FireflyIII\Repositories\PiggyBank
|
||||
*/
|
||||
interface PiggyBankRepositoryInterface {
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public function store(array $data);
|
||||
|
||||
/**
|
||||
* @param PiggyBank $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public function update(PiggyBank $piggyBank, array $data);
|
||||
interface PiggyBankRepositoryInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
|
||||
@@ -48,4 +33,45 @@ interface PiggyBankRepositoryInterface {
|
||||
* @return PiggyBankPart
|
||||
*/
|
||||
public function createPiggyBankPart(array $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PiggyBank $piggyBank
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
public function getEventSummarySet(PiggyBank $piggyBank);
|
||||
|
||||
/**
|
||||
* Set all piggy banks to order 0.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function reset();
|
||||
|
||||
/**
|
||||
*
|
||||
* set id of piggy bank.
|
||||
*
|
||||
* @param int $id
|
||||
* @param int $order
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setOrder($id, $order);
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public function store(array $data);
|
||||
|
||||
/**
|
||||
* @param PiggyBank $account
|
||||
* @param array $data
|
||||
*
|
||||
* @return PiggyBank
|
||||
*/
|
||||
public function update(PiggyBank $piggyBank, array $data);
|
||||
}
|
||||
|
@@ -2,10 +2,9 @@
|
||||
|
||||
namespace FireflyIII\Repositories\PiggyBank;
|
||||
|
||||
use FireflyIII\Models\Reminder;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Models\PiggyBankRepetition;
|
||||
use FireflyIII\Models\Reminder;
|
||||
|
||||
/**
|
||||
* Class PiggyBankPart
|
||||
|
@@ -5,6 +5,8 @@ namespace FireflyIII\Support;
|
||||
use Cache;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences as Prefs;
|
||||
|
||||
/**
|
||||
@@ -30,19 +32,27 @@ class Amount
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Transaction|\Transaction $transaction
|
||||
* @param bool $coloured
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function formatTransaction(Transaction $transaction, $coloured = true)
|
||||
public function getCurrencySymbol()
|
||||
{
|
||||
$symbol = $transaction->transactionJournal->transactionCurrency->symbol;
|
||||
$amount = floatval($transaction->amount);
|
||||
if (defined('FFCURRENCYSYMBOL')) {
|
||||
return FFCURRENCYSYMBOL;
|
||||
}
|
||||
if (\Cache::has('FFCURRENCYSYMBOL')) {
|
||||
define('FFCURRENCYSYMBOL', \Cache::get('FFCURRENCYSYMBOL'));
|
||||
|
||||
return $this->formatWithSymbol($symbol, $amount, $coloured);
|
||||
return FFCURRENCYSYMBOL;
|
||||
}
|
||||
|
||||
$currencyPreference = Prefs::get('currencyPreference', 'EUR');
|
||||
$currency = TransactionCurrency::whereCode($currencyPreference->data)->first();
|
||||
|
||||
\Cache::forever('FFCURRENCYSYMBOL', $currency->symbol);
|
||||
|
||||
define('FFCURRENCYSYMBOL', $currency->symbol);
|
||||
|
||||
return $currency->symbol;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,29 +83,64 @@ class Amount
|
||||
return $symbol . ' ' . $string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @param TransactionJournal $journal
|
||||
*/
|
||||
public function getCurrencySymbol()
|
||||
public function formatJournal(TransactionJournal $journal, $coloured = true)
|
||||
{
|
||||
if (defined('FFCURRENCYSYMBOL')) {
|
||||
return FFCURRENCYSYMBOL;
|
||||
$showPositive = true;
|
||||
if (is_null($journal->symbol)) {
|
||||
$symbol = $journal->transactionCurrency->symbol;
|
||||
} else {
|
||||
$symbol = $journal->symbol;
|
||||
}
|
||||
if (\Cache::has('FFCURRENCYSYMBOL')) {
|
||||
define('FFCURRENCYSYMBOL', \Cache::get('FFCURRENCYSYMBOL'));
|
||||
$amount = 0;
|
||||
|
||||
return FFCURRENCYSYMBOL;
|
||||
if (is_null($journal->type)) {
|
||||
$type = $journal->transactionType->type;
|
||||
} else {
|
||||
$type = $journal->type;
|
||||
}
|
||||
|
||||
$currencyPreference = Prefs::get('currencyPreference', 'EUR');
|
||||
$currency = TransactionCurrency::whereCode($currencyPreference->data)->first();
|
||||
if ($type == 'Withdrawal') {
|
||||
$showPositive = false;
|
||||
}
|
||||
|
||||
\Cache::forever('FFCURRENCYSYMBOL', $currency->symbol);
|
||||
foreach ($journal->transactions as $t) {
|
||||
if (floatval($t->amount) > 0 && $showPositive === true) {
|
||||
$amount = floatval($t->amount);
|
||||
break;
|
||||
}
|
||||
if (floatval($t->amount) < 0 && $showPositive === false) {
|
||||
$amount = floatval($t->amount);
|
||||
}
|
||||
}
|
||||
|
||||
define('FFCURRENCYSYMBOL', $currency->symbol);
|
||||
return $this->formatWithSymbol($symbol, $amount, $coloured);
|
||||
}
|
||||
|
||||
return $currency->symbol;
|
||||
/**
|
||||
* @param Transaction $transaction
|
||||
* @param bool $coloured
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function formatTransaction(Transaction $transaction, $coloured = true)
|
||||
{
|
||||
$symbol = $transaction->transactionJournal->transactionCurrency->symbol;
|
||||
$amount = floatval($transaction->amount);
|
||||
|
||||
return $this->formatWithSymbol($symbol, $amount, $coloured);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection
|
||||
*/
|
||||
public function getAllCurrencies()
|
||||
{
|
||||
return TransactionCurrency::orderBy('code', 'ASC')->get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,4 +175,4 @@ class Amount
|
||||
|
||||
return $currency;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace FireflyIII\Support;
|
||||
|
||||
use Amount as Amt;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\MessageBag;
|
||||
@@ -17,46 +18,6 @@ use View;
|
||||
class ExpandedForm
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function integer($name, $value = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = '1';
|
||||
$html = \View::make('form.integer', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function tags($name, $value = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['data-role'] = 'tagsinput';
|
||||
$html = \View::make('form.tags', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
@@ -72,8 +33,8 @@ class ExpandedForm
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = 'any';
|
||||
$options['min'] = '0.01';
|
||||
$defaultCurrency = isset($options['currency']) ? $options['currency'] : \Amount::getDefaultCurrency();
|
||||
$currencies = TransactionCurrency::orderBy('code', 'ASC')->get();
|
||||
$defaultCurrency = isset($options['currency']) ? $options['currency'] : Amt::getDefaultCurrency();
|
||||
$currencies = Amt::getAllCurrencies();
|
||||
$html = View::make('form.amount', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
@@ -91,9 +52,23 @@ class ExpandedForm
|
||||
if (isset($options['label'])) {
|
||||
return $options['label'];
|
||||
}
|
||||
$labels = ['amount_min' => 'Amount (min)', 'amount_max' => 'Amount (max)', 'match' => 'Matches on', 'repeat_freq' => 'Repetition',
|
||||
'account_from_id' => 'Account from', 'account_to_id' => 'Account to', 'account_id' => 'Asset account', 'budget_id' => 'Budget'
|
||||
, 'piggy_bank_id' => 'Piggy bank'];
|
||||
$labels = [
|
||||
'amount_min' => 'Amount (min)',
|
||||
'amount_max' => 'Amount (max)',
|
||||
'match' => 'Matches on',
|
||||
'repeat_freq' => 'Repetition',
|
||||
'account_from_id' => 'Account from',
|
||||
'account_to_id' => 'Account to',
|
||||
'account_id' => 'Asset account',
|
||||
'budget_id' => 'Budget',
|
||||
'openingBalance' => 'Opening balance',
|
||||
'virtualBalance' => 'Virtual balance',
|
||||
'targetamount' => 'Target amount',
|
||||
'accountRole' => 'Account role',
|
||||
'openingBalanceDate' => 'Opening balance date',
|
||||
'ccType' => 'Credit card payment plan',
|
||||
'ccMonthlyPaymentDate' => 'Credit card monthly payment date',
|
||||
'piggy_bank_id' => 'Piggy bank'];
|
||||
|
||||
|
||||
return isset($labels[$name]) ? $labels[$name] : str_replace('_', ' ', ucfirst($name));
|
||||
@@ -125,24 +100,14 @@ class ExpandedForm
|
||||
public function getHolderClasses($name)
|
||||
{
|
||||
/*
|
||||
* Get errors, warnings and successes from session:
|
||||
* Get errors from session:
|
||||
*/
|
||||
/** @var MessageBag $errors */
|
||||
$errors = Session::get('errors');
|
||||
$errors = Session::get('errors');
|
||||
$classes = 'form-group';
|
||||
|
||||
/** @var MessageBag $successes */
|
||||
$successes = Session::get('successes');
|
||||
|
||||
switch (true) {
|
||||
case (!is_null($errors) && $errors->has($name)):
|
||||
$classes = 'form-group has-error has-feedback';
|
||||
break;
|
||||
case (!is_null($successes) && $successes->has($name)):
|
||||
$classes = 'form-group has-success has-feedback';
|
||||
break;
|
||||
default:
|
||||
$classes = 'form-group';
|
||||
break;
|
||||
if (!is_null($errors) && $errors->has($name)) {
|
||||
$classes = 'form-group has-error has-feedback';
|
||||
}
|
||||
|
||||
return $classes;
|
||||
@@ -157,7 +122,7 @@ class ExpandedForm
|
||||
public function fillFieldValue($name, $value)
|
||||
{
|
||||
if (Session::has('preFilled')) {
|
||||
$preFilled = \Session::get('preFilled');
|
||||
$preFilled = Session::get('preFilled');
|
||||
$value = isset($preFilled[$name]) && is_null($value) ? $preFilled[$name] : $value;
|
||||
}
|
||||
if (!is_null(Input::old($name))) {
|
||||
@@ -181,8 +146,8 @@ class ExpandedForm
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = 'any';
|
||||
$defaultCurrency = isset($options['currency']) ? $options['currency'] : Amount::getDefaultCurrency();
|
||||
$currencies = TransactionCurrency::orderBy('code', 'ASC')->get();
|
||||
$defaultCurrency = isset($options['currency']) ? $options['currency'] : Amt::getDefaultCurrency();
|
||||
$currencies = Amt::getAllCurrencies();
|
||||
$html = View::make('form.balance', compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
@@ -229,6 +194,44 @@ class ExpandedForm
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function month($name, $value = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$html = View::make('form.month', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function integer($name, $value = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['step'] = '1';
|
||||
$html = View::make('form.integer', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
|
||||
*
|
||||
@@ -246,7 +249,7 @@ class ExpandedForm
|
||||
$selectList[0] = '(none)';
|
||||
}
|
||||
$fields = ['title', 'name', 'description'];
|
||||
/** @var \Eloquent $entry */
|
||||
/** @var Eloquent $entry */
|
||||
foreach ($set as $entry) {
|
||||
$id = intval($entry->id);
|
||||
$title = null;
|
||||
@@ -270,9 +273,9 @@ class ExpandedForm
|
||||
*/
|
||||
public function optionsList($type, $name)
|
||||
{
|
||||
$previousValue = \Input::old('post_submit_action');
|
||||
$previousValue = Input::old('post_submit_action');
|
||||
$previousValue = is_null($previousValue) ? 'store' : $previousValue;
|
||||
$html = \View::make('form.options', compact('type', 'name', 'previousValue'))->render();
|
||||
$html = View::make('form.options', compact('type', 'name', 'previousValue'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
@@ -291,7 +294,26 @@ class ExpandedForm
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$selected = $this->fillFieldValue($name, $selected);
|
||||
$html = \View::make('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
|
||||
$html = View::make('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $value
|
||||
* @param array $options
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function tags($name, $value = null, array $options = [])
|
||||
{
|
||||
$label = $this->label($name, $options);
|
||||
$options = $this->expandOptionArray($name, $label, $options);
|
||||
$classes = $this->getHolderClasses($name);
|
||||
$value = $this->fillFieldValue($name, $value);
|
||||
$options['data-role'] = 'tagsinput';
|
||||
$html = View::make('form.tags', compact('classes', 'name', 'label', 'value', 'options'))->render();
|
||||
|
||||
return $html;
|
||||
}
|
||||
@@ -314,4 +336,4 @@ class ExpandedForm
|
||||
return $html;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -21,4 +21,4 @@ class Amount extends Facade
|
||||
return 'amount';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -21,4 +21,4 @@ class ExpandedForm extends Facade
|
||||
return 'expandedform';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user