Compare commits

...

193 Commits

Author SHA1 Message Date
James Cole
8081eeb007 Merge branch 'release/3.4.0.1' 2015-05-05 12:35:22 +02:00
James Cole
56f91bd10d Increment version. 2015-05-05 12:35:11 +02:00
James Cole
8e20b78731 Cleanup. 2015-05-05 10:30:39 +02:00
James Cole
23a09b7081 Code cleanup. 2015-05-05 10:23:01 +02:00
James Cole
67fdd27499 Various code cleanup [skip ci] 2015-05-05 07:51:02 +02:00
James Cole
e1941daedd Updated phpdoc. [skip ci] 2015-05-05 07:48:34 +02:00
James Cole
f28bc568a4 Some cleanup [skip ci] 2015-05-05 07:43:16 +02:00
James Cole
f24cfe39aa Expanded some tests. 2015-05-05 07:41:30 +02:00
James Cole
59d2bf3f79 Covered transaction controller. 2015-05-05 07:28:04 +02:00
James Cole
3176e54614 Partial coverage of the transaction controller. 2015-05-04 23:46:14 +02:00
James Cole
eb090f7265 Better factory. 2015-05-04 22:33:52 +02:00
James Cole
6d3a9bfd18 Some cleaning up 2015-05-04 22:33:03 +02:00
James Cole
76f08b7acb Full coverage for chart controller. 2015-05-04 19:28:49 +02:00
James Cole
1ff99346aa Update chart [skip ci] 2015-05-04 18:51:51 +02:00
James Cole
369695ab32 Update chart [skip ci] 2015-05-04 18:51:38 +02:00
James Cole
7e23dd1d66 Update composer.lock [skip ci] 2015-05-04 18:45:32 +02:00
James Cole
0205d3fc5c Overspent transactions have a separate colour [skip ci] 2015-05-04 18:45:20 +02:00
James Cole
4660cf2ad5 Fixed a bug in the display of the current currency code. 2015-05-03 16:16:43 +02:00
James Cole
e26d08d674 Update git ignore. [skip ci] 2015-05-03 16:14:15 +02:00
James Cole
0932bf2797 Don't need these files [skip ci] 2015-05-03 16:13:38 +02:00
James Cole
f560fc6d76 Covered search controller. 2015-05-03 15:55:19 +02:00
James Cole
aa6209af00 Covered tag controller. 2015-05-03 15:00:39 +02:00
James Cole
4a51176193 General cleanup. 2015-05-03 12:58:55 +02:00
James Cole
bb84f7a434 Fixed parameter order [skip ci] 2015-05-03 12:54:39 +02:00
James Cole
48168b1ef0 Covered report controller. 2015-05-03 11:02:34 +02:00
James Cole
8281c7c83e Don't escape currency symbol [skip ci] 2015-05-03 10:11:16 +02:00
James Cole
a07c1e3c71 See code. [skip ci] 2015-05-03 10:07:18 +02:00
James Cole
0766bb31fe Better amount formatting [skip ci] 2015-05-03 10:03:50 +02:00
James Cole
ff4472c1a5 FormatAmountPlain is HTML safe [skip ci] 2015-05-03 10:01:38 +02:00
James Cole
17424740e5 Show plain amount instead of coloured amounts. [skip ci] 2015-05-03 10:00:47 +02:00
James Cole
dad0b2fcd3 Show plain amount instead of coloured amounts. [skip ci] 2015-05-03 10:00:03 +02:00
James Cole
c48dbf030f Covered the reminder controller. 2015-05-03 09:55:22 +02:00
James Cole
617808d603 Covered profile controller with tests. 2015-05-03 09:19:14 +02:00
James Cole
845149deee Boxes are empty, so even when it's zero, place the amount. 2015-05-03 08:56:44 +02:00
James Cole
1a9e009327 Merge branch 'release/3.4' into develop 2015-05-02 23:51:45 +02:00
James Cole
ae90815708 Merge branch 'release/3.4' 2015-05-02 23:51:44 +02:00
James Cole
1c460343b7 New version! 2015-05-02 23:51:34 +02:00
James Cole
26079622f9 Fixed JSON controller tests. 2015-05-02 23:39:39 +02:00
James Cole
06c6d6096f Fixed coverage. 2015-05-02 23:28:04 +02:00
James Cole
c8183aea51 Format amount [skip ci] 2015-05-02 22:50:40 +02:00
James Cole
7531134ad2 Some tag related fine tuning. 2015-05-02 22:41:32 +02:00
James Cole
cd0c6439c2 Delete tags now possible. 2015-05-02 22:30:59 +02:00
James Cole
c918c93f51 Forget me own head next. [skip ci] 2015-05-02 22:13:37 +02:00
James Cole
97d3bd68ed Show balance act tags. 2015-05-02 22:12:26 +02:00
James Cole
75f1e034ae Fixed menu. [skip ci] 2015-05-02 22:09:21 +02:00
James Cole
8e72f218f1 Show HTML 2015-05-02 22:05:57 +02:00
James Cole
d643e05c5a Basic amount format fix. 2015-05-02 22:05:18 +02:00
James Cole
fea44834d0 Fixed test to match fixed controller. 2015-05-02 21:22:27 +02:00
James Cole
195a2d7523 Removed all the old views. 2015-05-02 21:18:04 +02:00
James Cole
b2fd346ef8 Merge branch 'feature/twig' into develop 2015-05-02 21:16:21 +02:00
James Cole
1ff8b62cb7 And now with actual coverage. 2015-05-02 19:44:31 +02:00
James Cole
c7ae15a41a This should fix all twig tests. Let's find out! 2015-05-02 19:44:12 +02:00
James Cole
efe6f59f79 Last templates. Should cover everything. [skip ci] 2015-05-02 19:19:47 +02:00
James Cole
8e31d0491d Fixed search [skip ci] 2015-05-02 18:30:59 +02:00
James Cole
73d4a10351 Fixed reports [skip ci] 2015-05-02 18:26:55 +02:00
James Cole
81d9d4dbc7 Various files updated to twig [skip ci] 2015-05-02 13:20:49 +02:00
James Cole
184ec13f99 Fixed bills [skip ci] 2015-05-02 12:51:02 +02:00
James Cole
dee0422eff Fix preferences [skip ci] 2015-05-02 12:22:19 +02:00
James Cole
81a2975f1a Show piggy banks [skip ci] 2015-05-02 11:32:45 +02:00
James Cole
5cd2ef4a5e Some generic templates and the first piggy bank ones [skip ci] 2015-05-02 10:53:54 +02:00
James Cole
466c2a68c2 Add delete form [skip ci] 2015-05-02 10:42:41 +02:00
James Cole
0fb9fba531 New currency routes 2015-05-02 10:40:20 +02:00
James Cole
356dd2c6cd Creat / edit / index [skip ci] 2015-05-02 10:37:16 +02:00
James Cole
32c4661233 Fixed no budget / no category bread crumb [skip ci] 2015-05-02 09:49:37 +02:00
James Cole
a245b504ec Fixed bread crumbs. 2015-05-02 09:31:57 +02:00
James Cole
a2f5fbdfd3 Working on two more views [skip ci] 2015-05-02 09:29:34 +02:00
James Cole
04be26adc5 Fixed title [skip ci] 2015-05-02 09:26:20 +02:00
James Cole
be0adb7cf2 Create / edit category 2015-05-02 09:25:45 +02:00
James Cole
84fd92bf5a Categories [skip ci] 2015-05-02 09:21:42 +02:00
James Cole
ee4e061739 Removed code from budget index [skip ci] 2015-05-02 09:21:32 +02:00
James Cole
4a2b01cd9a Menu fixes [skip ci] 2015-05-02 09:16:17 +02:00
James Cole
efdd6460fb Fixed injection. 2015-05-02 09:08:41 +02:00
James Cole
803827e05c Fixed more views. [skip ci] 2015-05-02 09:06:07 +02:00
James Cole
a41d5e9ab3 New budget [skip ci] 2015-05-02 08:32:20 +02:00
James Cole
e94333f877 Can view budgets [skip ci] 2015-05-02 08:28:24 +02:00
James Cole
6dbb80d687 Optimisations [skip ci] 2015-05-02 08:09:54 +02:00
James Cole
31a1031624 And delete is fixed. 2015-05-01 23:39:45 +02:00
James Cole
f8e9ce0d52 Can edit as well. 2015-05-01 23:35:35 +02:00
James Cole
11baa968cd Can create accounts. 2015-05-01 23:17:17 +02:00
James Cole
3e5e5b376f Made it almost to the accounts. 2015-05-01 22:44:35 +02:00
James Cole
bda18f296d Optimised Twig extensions. 2015-05-01 20:17:06 +02:00
James Cole
287d110c84 Small bug fix in budget chart. 2015-05-01 18:45:42 +02:00
James Cole
c98275e73a More templates converted to twig. 2015-05-01 18:44:49 +02:00
James Cole
aa573cc951 Fix redirect 2015-05-01 14:32:31 +02:00
James Cole
883d3d86e3 Update a test. 2015-05-01 14:32:26 +02:00
James Cole
fb047bd5f4 Fix migration. 2015-05-01 08:34:53 +02:00
James Cole
66a04d8365 Slightly different chart on index. 2015-05-01 08:34:44 +02:00
James Cole
a0e501f9fd First attempt at implementing Twig. 2015-05-01 08:29:41 +02:00
James Cole
8b40d3346d An attempt at showing tag info. 2015-05-01 06:47:24 +02:00
James Cole
eddf5cd250 Fix button, close #74 2015-05-01 06:38:48 +02:00
James Cole
ee5c534ca3 Took the time to fix the tests. 2015-04-30 17:32:00 +02:00
James Cole
fd4e77ae0f Catch empty tags. 2015-04-28 21:01:54 +02:00
James Cole
b747c50aa3 Fix method to return object, not key. 2015-04-28 21:00:26 +02:00
James Cole
deebdd86a6 And another small JS fix [skip ci] 2015-04-28 20:20:16 +02:00
James Cole
b2db79cc10 Fixed some small CSS / JS problems. 2015-04-28 20:17:31 +02:00
James Cole
bbab370b1e Some new code. 2015-04-28 17:10:52 +02:00
James Cole
db4adf399d Cleaning up. 2015-04-28 15:26:30 +02:00
James Cole
0683c87e52 Small check in tags. 2015-04-28 14:08:58 +02:00
James Cole
3f62b647fc Removed code related to "related transactions". 2015-04-28 13:50:53 +02:00
James Cole
2562a5b30d Don't save all tags unconditionally. 2015-04-28 13:47:13 +02:00
James Cole
e232f2e223 Delete tags 2015-04-28 11:04:46 +02:00
James Cole
21644ff4dd Routes will throw 404's 2015-04-28 11:04:38 +02:00
James Cole
be96a4fce5 Show tags in transaction. 2015-04-28 10:51:56 +02:00
James Cole
a1cabcbed3 Show tag icons. 2015-04-28 10:50:43 +02:00
James Cole
ce933b1f06 Edit and update tags. 2015-04-28 10:36:13 +02:00
James Cole
51ae130922 Fixed the build by adding new migrations for each step. 2015-04-28 09:54:22 +02:00
James Cole
da1bc18a47 Better list for piggy banks. 2015-04-28 09:15:31 +02:00
James Cole
e7165a526b First attempt at basic tag functionality. 2015-04-28 08:58:01 +02:00
James Cole
6081cc399f Small bug fixes and cleaning up. 2015-04-28 08:12:12 +02:00
James Cole
7c5c24e15d Moved edit buttons. 2015-04-26 07:42:55 +02:00
James Cole
e3e55b4347 Moved all create-buttons lower. 2015-04-26 07:39:49 +02:00
James Cole
40d8e7d1ad Fixed a bug where transfers away from a piggy bank's account would not properly reflect the piggy bank. 2015-04-24 12:06:13 +02:00
James Cole
59e23b89f2 Removed unnecessary sort. 2015-04-24 11:54:23 +02:00
James Cole
cc33af8193 Could not set order. 2015-04-24 10:00:56 +02:00
James Cole
0e1e7eb2a9 Merge branch 'release/3.3.9' 2015-04-22 08:08:14 +02:00
James Cole
52a28a7758 Merge branch 'release/3.3.9' into develop 2015-04-22 08:08:14 +02:00
James Cole
3f752d6832 New read me. 2015-04-22 08:08:05 +02:00
James Cole
fe714e9989 Built a routine that will allow you to completely delete an account. 2015-04-22 07:54:56 +02:00
James Cole
0d3213a379 Covered the preferences controller. 2015-04-21 17:19:14 +02:00
James Cole
44056629e8 Use local db instead of constant migrating. 2015-04-20 22:08:24 +02:00
James Cole
54125c05d3 New tests and prep for future runs. 2015-04-20 21:57:20 +02:00
James Cole
7d32e50f25 Mentioned wrong amount. 2015-04-20 20:56:28 +02:00
James Cole
4af9ff49a0 Fixed a bug in the report controller that grouped transactions wrong. 2015-04-20 20:54:55 +02:00
James Cole
23faef845c Merge branch 'release/3.3.8' 2015-04-20 18:07:02 +02:00
James Cole
41dad4091a Merge branch 'release/3.3.8' into develop 2015-04-20 18:07:02 +02:00
James Cole
daf859b977 Updated read me. 2015-04-20 18:06:37 +02:00
James Cole
f47ba6c977 Update example file. 2015-04-20 18:06:21 +02:00
James Cole
4b9b207d92 Removed development references. 2015-04-20 17:59:04 +02:00
James Cole
875cbf66af 1 should be 0 2015-04-19 19:10:53 +02:00
James Cole
412d6d4fd7 Small CSS fix for piggy banks [skip ci] 2015-04-19 17:43:04 +02:00
James Cole
91c6deeb1f Renamed another field. 2015-04-19 14:28:17 +02:00
James Cole
6d1978fd9a Showed the wrong value. 2015-04-19 14:27:08 +02:00
James Cole
52d23b6ef5 Referred to an id which turned out to be a index. 2015-04-19 14:19:25 +02:00
James Cole
0656ccbdd9 Fixed a bug where the query would include deleted transactions. 2015-04-19 13:57:43 +02:00
James Cole
e774ebd0a3 Possible bug in account create thing. [skip ci] 2015-04-18 16:04:21 +02:00
James Cole
edbda32a84 Fix balance. 2015-04-13 21:13:05 +02:00
James Cole
721fa04e3c Added home screen information about piggy banks. 2015-04-13 20:43:58 +02:00
James Cole
9fd8d8915d amount > queryAmount 2015-04-12 10:53:53 +02:00
James Cole
7a9f5ebdd1 Added "what" variable. 2015-04-12 10:22:15 +02:00
James Cole
a3423f0321 Add the correct path to category overview. 2015-04-12 10:19:37 +02:00
James Cole
c37e9a4467 Covered the JSON controller. 2015-04-11 19:59:41 +02:00
James Cole
6157d82a0b time format 2015-04-11 18:52:03 +02:00
James Cole
38b27fec92 Without moment.js 2015-04-11 18:49:57 +02:00
James Cole
c43439bb68 Test for date. 2015-04-11 18:47:37 +02:00
James Cole
8d9561d7a5 Removed data-value. 2015-04-11 18:45:01 +02:00
James Cole
2a72cce3b7 Included date format. 2015-04-11 15:11:45 +02:00
James Cole
d3bbb6fb1f Removed date value. 2015-04-11 15:11:19 +02:00
James Cole
7b6723e9a2 Update date format. 2015-04-11 15:10:29 +02:00
James Cole
1ee741460d Updated empty entries as well. 2015-04-11 15:09:48 +02:00
James Cole
967b0b493b Switched dates around. 2015-04-11 15:07:42 +02:00
James Cole
b53aaf7dde Fixed sort format. 2015-04-11 15:06:10 +02:00
James Cole
714c13bdbf Include moment.js 2015-04-11 15:04:16 +02:00
James Cole
651a4fd3cc Sortable accounts. 2015-04-11 15:01:42 +02:00
James Cole
505aee22bb Sortable categories. 2015-04-11 14:53:22 +02:00
James Cole
ca3d59dc33 Another fix. 2015-04-11 12:51:58 +02:00
James Cole
13890e32a1 Fixed a view and a botched include. 2015-04-11 12:50:56 +02:00
James Cole
df8976eabe Journals that no longer match a bill will be removed. 2015-04-11 12:40:47 +02:00
James Cole
3e01daa172 Query & loop optimizations. 2015-04-11 12:36:17 +02:00
James Cole
f6999f355b Some foreach loop cleaning up. 2015-04-11 12:27:56 +02:00
James Cole
5c06b45eb1 Code cleanup. 2015-04-11 07:32:11 +02:00
James Cole
1802bb967a Moved JSON money boxes to individual functions. 2015-04-11 07:24:07 +02:00
James Cole
d8d92f147f Removed logging, found bug. 2015-04-10 07:29:36 +02:00
James Cole
4a95bdd8ba Added temporary debug to google chart. 2015-04-10 07:25:24 +02:00
James Cole
db5d94d956 Added temporary debug entries. 2015-04-10 07:19:45 +02:00
James Cole
06f2e34bb5 Renamed the amount variable so it stops interfering with another variable 2015-04-10 06:57:39 +02:00
James Cole
2ef7a01945 Fixed a bug where the bill chart and boxes would inaccurately reflect the amount of bills yet to pay. 2015-04-10 06:52:36 +02:00
James Cole
d3f642551d Fixed a small bug in the bill-chart and simplified yet another Json box. 2015-04-09 21:36:58 +02:00
James Cole
490997157e Switched two queries around. 2015-04-09 21:30:35 +02:00
James Cole
2432af7883 Simplified the in and out-box. 2015-04-09 21:29:58 +02:00
James Cole
7abeece3f0 Simplified the "out"-box. 2015-04-09 21:27:35 +02:00
James Cole
3851652821 Renamed various fields from 'amount' to 'queryAmount' to prevent interfering with the getAmountAttribute property. 2015-04-09 21:18:18 +02:00
James Cole
1d67d2250a Renamed various fields from 'amount' to 'queryAmount' to prevent interfering with the getAmountAttribute property. 2015-04-09 21:16:35 +02:00
James Cole
37f40d8637 Renamed various fields from 'amount' to 'queryAmount' to prevent interfering with the getAmountAttribute property. 2015-04-09 21:14:15 +02:00
James Cole
0224d1d59b Accidentally commented out date limits in query. 2015-04-09 21:01:08 +02:00
James Cole
587b94153d Removed some foreach() routines that are no longer necessary now that getAmountAttribute() exists. 2015-04-09 20:58:57 +02:00
James Cole
5124ce0302 Fixed a bug where getAmountAttribute would interfere with queries that contained a "amount"-field. 2015-04-09 20:52:47 +02:00
James Cole
950c4045b0 Fix total savings to accurately reflect end of current period. 2015-04-09 19:10:24 +02:00
James Cole
9c8ba66873 Order categories by name. 2015-04-09 17:54:24 +02:00
James Cole
25d1d1be1b Merge pull request #72 from vbali/feature/savings-total
Add savings total for savings widget on dashboard
2015-04-09 17:47:24 +02:00
James Cole
339c352505 Fixed a bug where categories would be created even though they already existed. 2015-04-09 17:46:47 +02:00
Balazs Varkonyi
c587081fe4 Add savings total for savings widget on dashboard 2015-04-09 11:52:35 +02:00
James Cole
8f9b1b866b Included full home controller tests. 2015-04-07 20:54:43 +02:00
James Cole
ff5ecf6182 More tests. 2015-04-07 19:58:49 +02:00
James Cole
05670cf393 Optimize test code. 2015-04-07 18:52:15 +02:00
James Cole
f10f5d30bf Mock previously unmocked calls. 2015-04-07 18:48:34 +02:00
James Cole
0d336727e8 Automated code cleanup. 2015-04-07 18:26:14 +02:00
James Cole
bf354275b3 Some general cleaning up. 2015-04-07 18:25:21 +02:00
James Cole
1932bf277a More tests 2015-04-07 17:51:22 +02:00
James Cole
192db4bb6e Accidentally included JS twice. 2015-04-07 10:14:20 +02:00
James Cole
701efb943d Lots of new tests. 2015-04-07 10:14:10 +02:00
James Cole
b2674971f1 Updated composer.lock. 2015-04-06 09:20:45 +02:00
James Cole
c907cb4cf1 General cleanup and new (incomplete) tests. 2015-04-06 09:15:59 +02:00
James Cole
1035f0e139 Merge branch 'release/3.3.7' into develop 2015-04-05 21:15:01 +02:00
275 changed files with 11253 additions and 5400 deletions

View File

@@ -1,5 +1,5 @@
APP_ENV=local
APP_DEBUG=true
APP_ENV=production
APP_DEBUG=false
APP_KEY=SomeRandomString
DB_CONNECTION=mysql

3
.gitignore vendored
View File

@@ -28,3 +28,6 @@ tests/_output/*
clover.xml
node_modules/
addNewLines.php
.phpstorm.meta.php
.env.backup
.env.local

View File

@@ -1,4 +1,4 @@
Firefly III (v3.3.7)
Firefly III (v3.4.0.1)
===========
[![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=develop)](https://travis-ci.org/JC5/firefly-iii)
@@ -6,7 +6,7 @@ Firefly III (v3.3.7)
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102/mini.png)](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102)
[![Code Climate](https://codeclimate.com/github/JC5/firefly-iii/badges/gpa.svg)](https://codeclimate.com/github/JC5/firefly-iii)
[![Coverage Status](https://coveralls.io/repos/JC5/firefly-iii/badge.svg?branch=master)](https://coveralls.io/r/JC5/firefly-iii?branch=master)
[![Coverage Status](https://coveralls.io/repos/JC5/firefly-iii/badge.svg?branch=master)](https://coveralls.io/r/JC5/firefly-iii?branch=develop)
[![Coverage Status](https://coveralls.io/repos/JC5/firefly-iii/badge.svg?branch=develop)](https://coveralls.io/r/JC5/firefly-iii?branch=develop)
[![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
[![Total Downloads](https://poser.pugx.org/grumpydictator/firefly-iii/downloads.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
@@ -22,7 +22,9 @@ 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)**
[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)**.
If you want to try out Firefly III, you can do so on [this dedicated website](https://geld.nder.be/). This site always runs the latest version of Firefly III. If you want to use it, please read the [privacy considerations](https://github.com/JC5/firefly-iii/wiki/Privacy-on-demo-site) for this demo-site.
## Current features

View File

@@ -19,7 +19,8 @@ class JournalCreated extends Event
/**
* Create a new event instance.
*
* @return void
* @param TransactionJournal $journal
* @param $piggyBankId
*/
public function __construct(TransactionJournal $journal, $piggyBankId)
{

View File

@@ -2,6 +2,11 @@
use Illuminate\Queue\SerializesModels;
/**
* Class JournalDeleted
*
* @package FireflyIII\Events
*/
class JournalDeleted extends Event
{
@@ -10,7 +15,6 @@ class JournalDeleted extends Event
/**
* Create a new event instance.
*
* @return void
*/
public function __construct()
{

View File

@@ -3,6 +3,11 @@
use FireflyIII\Models\TransactionJournal;
use Illuminate\Queue\SerializesModels;
/**
* Class JournalSaved
*
* @package FireflyIII\Events
*/
class JournalSaved extends Event
{
@@ -13,7 +18,7 @@ class JournalSaved extends Event
/**
* Create a new event instance.
*
* @return void
* @param TransactionJournal $journal
*/
public function __construct(TransactionJournal $journal)
{

View File

@@ -49,8 +49,7 @@ class Handler extends ExceptionHandler
*/
public function report(Exception $e)
{
/** @noinspection PhpInconsistentReturnPointsInspection */
return parent::report($e);
parent::report($e);
}
}

View File

@@ -19,7 +19,6 @@ class ConnectJournalToPiggyBank
/**
* Create the event handler.
*
* @return void
*/
public function __construct()
{
@@ -51,14 +50,7 @@ class ConnectJournalToPiggyBank
return;
}
Log::debug('Found a piggy bank');
$amount = 0;
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
if ($transaction->account_id === $piggyBank->account_id) {
// this transaction is the relevant one.
$amount = floatval($transaction->amount);
}
}
$amount = $journal->amount;
Log::debug('Amount: ' . $amount);
if ($amount == 0) {
return;
@@ -72,6 +64,22 @@ class ConnectJournalToPiggyBank
}
Log::debug('Found rep! ' . $repetition->id);
/*
* Add amount when
*/
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
if ($transaction->account_id == $piggyBank->account_id) {
if ($transaction->amount < 0) {
$amount = $amount * -1;
Log::debug('Transaction is away from piggy, so amount becomes ' . $amount);
} else {
Log::debug('Transaction is to from piggy, so amount stays ' . $amount);
}
}
}
$repetition->currentamount += $amount;
$repetition->save();

View File

@@ -15,7 +15,6 @@ class RescanJournal
/**
* Create the event handler.
*
* @return void
*/
public function __construct()
{
@@ -41,7 +40,7 @@ class RescanJournal
Log::debug('Found ' . $list->count() . ' bills to check.');
/** @var Bill $bill */
/** @var \FireflyIII\Models\Bill $bill */
foreach ($list as $bill) {
Log::debug('Now calling bill #' . $bill->id . ' (' . $bill->name . ')');
$repository->scan($bill, $journal);

View File

@@ -15,7 +15,6 @@ class UpdateJournalConnection
/**
* Create the event handler.
*
* @return void
*/
public function __construct()
{
@@ -45,17 +44,8 @@ class UpdateJournalConnection
if (is_null($repetition)) {
return;
}
$amount = 0;
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
if ($transaction->account_id === $piggyBank->account_id) {
// this transaction is the relevant one.
$amount = floatval($transaction->amount);
}
}
// update current repetition:
$diff = $amount - $event->amount;
$amount = $journal->amount;
$diff = $amount - $event->amount;// update current repetition
$repetition->currentamount += $diff;
$repetition->save();

87
app/Helpers/Help/Help.php Normal file
View File

@@ -0,0 +1,87 @@
<?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;
}
/**
* @param $route
*
* @return bool
*/
public function hasRoute($route)
{
return Route::has($route);
}
/**
* @param $route
* @param array $content
*
* @internal param $title
*/
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');
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace FireflyIII\Helpers\Help;
/**
* Interface HelpInterface
*
* @package FireflyIII\Helpers\Help
*/
interface HelpInterface
{
/**
* @param $key
*
* @return string
*/
public function getFromCache($key);
/**
* @param $route
*
* @return array
*/
public function getFromGithub($route);
/**
* @param $route
*
* @return bool
*/
public function hasRoute($route);
/**
* @param $route
*
* @return bool
*/
public function inCache($route);
/**
* @param $route
* @param array $content
*
* @return void
*/
public function putInCache($route, array $content);
}

View File

@@ -60,23 +60,21 @@ class ReportHelper implements ReportHelperInterface
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
}
)
->get(['budgets.*', 'budget_limits.amount as amount']);
->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]['amount'] = isset($budgets[0]['amount']) ? $budgets[0]['amount'] : 0.0;
$budgets[0]['name'] = 'No budget';
$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';
// 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);
foreach ($transfers as $transfer) {
$budgets[0]['spent'] += floatval($transfer->amount) * -1;
}
$transfers = $query->sharedExpenses($start, $end)->sum('queryAmount');
$budgets[0]['spent'] += floatval($transfers) * -1;
}
return $budgets;
@@ -93,11 +91,11 @@ class ReportHelper implements ReportHelperInterface
$end = Carbon::now();
$months = [];
while ($start <= $end) {
$year = $start->format('Y');
$year = $start->year;
$months[$year][] = [
'formatted' => $start->format('F Y'),
'month' => intval($start->format('m')),
'year' => intval($start->format('Y')),
'month' => $start->month,
'year' => $year,
];
$start->addMonth();
}
@@ -116,10 +114,10 @@ class ReportHelper implements ReportHelperInterface
$end = Carbon::now();
$years = [];
while ($start <= $end) {
$years[] = $start->format('Y');
$years[] = $start->year;
$start->addYear();
}
$years[] = Carbon::now()->format('Y');
$years[] = Carbon::now()->year;
// force the current year.
$years = array_unique($years);

View File

@@ -96,7 +96,7 @@ class ReportQuery implements ReportQueryInterface
->get(
[
'transaction_journals.*',
'transactions.amount'
'transactions.amount as queryAmount'
]
);
@@ -111,17 +111,11 @@ class ReportQuery implements ReportQueryInterface
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
* @return float
*/
public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end)
{
$set = $this->balancedTransactionsList($account, $start, $end);
$sum = 0;
foreach ($set as $entry) {
$sum += floatval($entry->amount);
}
return $sum;
return floatval($this->balancedTransactionsList($account, $start, $end)->sum('queryAmount'));
}
/**
@@ -156,8 +150,16 @@ class ReportQuery implements ReportQueryInterface
$set = $query->get(['accounts.*']);
$set->each(
function (Account $account) use ($start, $end) {
/**
* The balance for today always incorporates transactions
* made on today. So to get todays "start" balance, we sub one
* day.
*/
$yesterday = clone $start;
$yesterday->subDay();
/** @noinspection PhpParamsInspection */
$account->startBalance = Steam::balance($account, $start);
$account->startBalance = Steam::balance($account, $yesterday);
$account->endBalance = Steam::balance($account, $end);
}
);
@@ -178,7 +180,7 @@ class ReportQuery implements ReportQueryInterface
{
$query = $this->queryJournalsNoBudget($account, $start, $end);
return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `amount`')]);
return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `queryAmount`')]);
}
@@ -196,7 +198,7 @@ class ReportQuery implements ReportQueryInterface
{
$query = $this->queryJournalsNoBudget($account, $start, $end);
return $query->get(['budgets.name', 'transactions.amount', 'transaction_journals.*']);
return $query->get(['budgets.name', 'transactions.amount as queryAmount', 'transaction_journals.*']);
}
/**
@@ -236,7 +238,7 @@ class ReportQuery implements ReportQueryInterface
// any deposit is fine.
$query->where('transaction_types.type', 'Deposit');
}
$query->groupBy('t_from.account_id')->orderBy('transaction_journals.date');
$query->groupBy('transaction_journals.id')->orderBy('transaction_journals.date');
// get everything, decrypt and return
$data = $query->get(
@@ -244,7 +246,7 @@ class ReportQuery implements ReportQueryInterface
'transaction_journals.description',
'transaction_journals.encrypted',
'transaction_types.type',
DB::Raw('SUM(`t_to`.`amount`) as `amount`'),
DB::Raw('SUM(`t_to`.`amount`) as `queryAmount`'),
'transaction_journals.date',
't_from.account_id as account_id',
'ac_from.name as name',
@@ -254,7 +256,6 @@ class ReportQuery implements ReportQueryInterface
$data->each(
function (Model $object) {
// $object->description = intval($object->encrypted);
$object->name = intval($object->account_encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
}
);
@@ -335,9 +336,9 @@ class ReportQuery implements ReportQueryInterface
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->where('transaction_types.type', 'Withdrawal')
->groupBy('categories.id')
->orderBy('amount');
->orderBy('queryAmount');
$data = $query->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `amount`')]);
$data = $query->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `queryAmount`')]);
// decrypt data:
$data->each(
function (Model $object) {
@@ -390,9 +391,9 @@ class ReportQuery implements ReportQueryInterface
$query->before($end)->after($start)
->where('transaction_journals.user_id', Auth::user()->id)
->groupBy('t_to.account_id')
->orderBy('amount', 'DESC');
->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 `amount`')]);
$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(
@@ -441,10 +442,10 @@ class ReportQuery implements ReportQueryInterface
$query->where('transaction_types.type', 'Deposit');
}
$query->groupBy('t_from.account_id')->orderBy('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 `amount`')]
['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(
@@ -489,7 +490,7 @@ class ReportQuery implements ReportQueryInterface
->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']
);
}
@@ -534,7 +535,7 @@ 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`')
]
);
}

View File

@@ -43,7 +43,7 @@ interface ReportQueryInterface
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
* @return float
*/
public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end);

View File

@@ -1,6 +1,5 @@
<?php namespace FireflyIII\Http\Controllers;
use Amount;
use Auth;
use Carbon\Carbon;
use Config;
@@ -8,11 +7,11 @@ use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\AccountFormRequest;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Illuminate\Pagination\LengthAwarePaginator;
use Input;
use Redirect;
use Session;
use Steam;
use URL;
use View;
/**
@@ -27,6 +26,7 @@ class AccountController extends Controller
*/
public function __construct()
{
parent::__construct();
View::share('mainTitleIcon', 'fa-credit-card');
View::share('title', 'Accounts');
}
@@ -41,6 +41,12 @@ class AccountController extends Controller
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$subTitle = 'Create a new ' . e($what) . ' account';
// put previous url in session if not redirect from store (not "create another").
if (Session::get('accounts.create.fromStore') !== true) {
Session::put('accounts.create.url', URL::previous());
}
Session::forget('accounts.create.fromStore');
return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle'));
}
@@ -54,15 +60,19 @@ class AccountController extends Controller
{
$subTitle = 'Delete ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
// put previous url in session
Session::put('accounts.delete.url', URL::previous());
return view('accounts.delete', compact('account', 'subTitle'));
}
/**
* @param Account $account
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Account $account, AccountRepositoryInterface $repository)
public function destroy(AccountRepositoryInterface $repository, Account $account)
{
$type = $account->accountType->type;
@@ -73,16 +83,16 @@ class AccountController extends Controller
Session::flash('success', 'The ' . e($typeName) . ' account "' . e($name) . '" was deleted.');
return Redirect::route('accounts.index', $typeName);
return Redirect::to(Session::get('accounts.delete.url'));
}
/**
* @param Account $account
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @return View
*/
public function edit(Account $account, AccountRepositoryInterface $repository)
public function edit(AccountRepositoryInterface $repository, Account $account)
{
$what = Config::get('firefly.shortNamesByFullName')[$account->accountType->type];
@@ -90,6 +100,12 @@ class AccountController extends Controller
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$openingBalance = $repository->openingBalanceTransaction($account);
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('accounts.edit.fromUpdate') !== true) {
Session::put('accounts.edit.url', URL::previous());
}
Session::forget('accounts.edit.fromUpdate');
// pre fill some useful values.
// the opening balance is tricky:
@@ -114,28 +130,24 @@ class AccountController extends Controller
}
/**
* @param $what
* @param AccountRepositoryInterface $repository
* @param $what
*
* @return View
*/
public function index($what, AccountRepositoryInterface $repository)
public function index(AccountRepositoryInterface $repository, $what)
{
$subTitle = Config::get('firefly.subTitlesByIdentifier.' . $what);
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$types = Config::get('firefly.accountTypesByIdentifier.' . $what);
$size = 50;
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
$set = $repository->getAccounts($types, $page);
$total = $repository->countAccounts($types);
$accounts = $repository->getAccounts($types);
// last activity:
/**
* HERE WE ARE
*/
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$start->subDay();
$set->each(
$accounts->each(
function (Account $account) use ($start, $repository) {
$account->lastActivityDate = $repository->getLastActivity($account);
$account->startBalance = Steam::balance($account, $start);
@@ -143,20 +155,16 @@ class AccountController extends Controller
}
);
$accounts = new LengthAwarePaginator($set, $total, $size, $page);
$accounts->setPath(route('accounts.index', $what));
return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts'));
}
/**
* @param Account $account
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @return View
*/
public function show(Account $account, AccountRepositoryInterface $repository)
public function show(AccountRepositoryInterface $repository, Account $account)
{
$page = intval(Input::get('page')) == 0 ? 1 : intval(Input::get('page'));
$subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type);
@@ -166,7 +174,6 @@ class AccountController extends Controller
$journals->setPath('accounts/show/' . $account->id);
return view('accounts.show', compact('account', 'what', 'subTitleIcon', 'journals', 'subTitle'));
}
@@ -192,26 +199,31 @@ class AccountController extends Controller
];
$account = $repository->store($accountData);
Session::flash('success', 'New account "' . $account->name . '" stored!');
Session::flash('success', 'New account "' . $account->name . '" stored!');
if (intval(Input::get('create_another')) === 1) {
return Redirect::route('accounts.create', $request->input('what'))->withInput();
// set value so create routine will not overwrite URL:
Session::put('accounts.create.fromStore', true);
return Redirect::route('accounts.create')->withInput();
}
return Redirect::route('accounts.index', $request->input('what'));
// redirect to previous URL.
return Redirect::to(Session::get('accounts.create.url'));
}
/**
* @param Account $account
* @param AccountFormRequest $request
* @param AccountRepositoryInterface $repository
* @param Account $account
*
* @return \Illuminate\Http\RedirectResponse
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function update(Account $account, AccountFormRequest $request, AccountRepositoryInterface $repository)
public function update(AccountFormRequest $request, AccountRepositoryInterface $repository, Account $account)
{
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$accountData = [
'name' => $request->input('name'),
'active' => $request->input('active'),
@@ -230,10 +242,14 @@ class AccountController extends Controller
Session::flash('success', 'Account "' . $account->name . '" updated.');
if (intval(Input::get('return_to_edit')) === 1) {
return Redirect::route('accounts.edit', $account->id);
// set value so edit routine will not overwrite URL:
Session::put('accounts.edit.fromUpdate', true);
return Redirect::route('accounts.edit', $account->id)->withInput(['return_to_edit' => 1]);
}
return Redirect::route('accounts.index', $what);
// redirect to previous URL.
return Redirect::to(Session::get('accounts.edit.url'));
}

View File

@@ -8,6 +8,7 @@ use Illuminate\Http\Request;
use Illuminate\Mail\Message;
use Mail;
use Session;
use Twig;
/**
* Class AuthController
@@ -47,6 +48,16 @@ class AuthController extends Controller
$this->middleware('guest', ['except' => 'getLogout']);
}
/**
* Show the application login form.
*
* @return \Illuminate\Http\Response
*/
public function getLogin()
{
return Twig::render('auth.login');
}
/**
* Handle a registration request for the application.
*

View File

@@ -29,23 +29,25 @@ class BillController extends Controller
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Bills');
View::share('mainTitleIcon', 'fa-calendar-o');
}
/**
* @param Bill $bill
* @param AccountRepositoryInterface $repository
* @param Bill $bill
*
* @return \Illuminate\Http\RedirectResponse
*/
public function add(Bill $bill, AccountRepositoryInterface $repository)
public function add(AccountRepositoryInterface $repository, Bill $bill)
{
$matches = explode(',', $bill->match);
$description = [];
$expense = null;
// get users expense accounts:
$accounts = $repository->getAccounts(Config::get('firefly.accountTypesByIdentifier.expense'), -1);
$accounts = $repository->getAccounts(Config::get('firefly.accountTypesByIdentifier.expense'));
foreach ($matches as $match) {
$match = strtolower($match);
@@ -83,7 +85,14 @@ class BillController extends Controller
{
$periods = Config::get('firefly.periods_to_text');
return view('bills.create')->with('periods', $periods)->with('subTitle', 'Create new');
// put previous url in session if not redirect from store (not "create another").
if (Session::get('bills.create.fromStore') !== true) {
Session::put('bills.create.url', URL::previous());
}
Session::forget('bills.create.fromStore');
$subTitle = 'Create new bill';
return view('bills.create', compact('periods', 'subTitle'));
}
/**
@@ -93,21 +102,26 @@ class BillController extends Controller
*/
public function delete(Bill $bill)
{
return view('bills.delete')->with('bill', $bill)->with('subTitle', 'Delete "' . e($bill->name) . '"');
// put previous url in session
Session::put('bills.delete.url', URL::previous());
$subTitle = 'Delete "' . e($bill->name) . '"';
return view('bills.delete', compact('bill', 'subTitle'));
}
/**
* @param Bill $bill
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Bill $bill, BillRepositoryInterface $repository)
public function destroy(BillRepositoryInterface $repository, Bill $bill)
{
$repository->destroy($bill);
Session::flash('success', 'The bill was deleted.');
return Redirect::route('bills.index');
return Redirect::to(Session::get('bills.delete.url'));
}
@@ -118,9 +132,16 @@ class BillController extends Controller
*/
public function edit(Bill $bill)
{
$periods = Config::get('firefly.periods_to_text');
$periods = Config::get('firefly.periods_to_text');
$subTitle = 'Edit "' . e($bill->name) . '"';
return view('bills.edit')->with('periods', $periods)->with('bill', $bill)->with('subTitle', 'Edit "' . e($bill->name) . '"');
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('bills.edit.fromUpdate') !== true) {
Session::put('bills.edit.url', URL::previous());
}
Session::forget('bills.edit.fromUpdate');
return view('bills.edit', compact('subTitle', 'periods', 'bill'));
}
/**
@@ -142,11 +163,12 @@ class BillController extends Controller
}
/**
* @param Bill $bill
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return mixed
* @return \Illuminate\Http\RedirectResponse
*/
public function rescan(Bill $bill, BillRepositoryInterface $repository)
public function rescan(BillRepositoryInterface $repository, Bill $bill)
{
if (intval($bill->active) == 0) {
Session::flash('warning', 'Inactive bills cannot be scanned.');
@@ -167,21 +189,26 @@ class BillController extends Controller
}
/**
* @param Bill $bill
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return mixed
*/
public function show(Bill $bill, BillRepositoryInterface $repository)
public function show(BillRepositoryInterface $repository, Bill $bill)
{
$journals = $repository->getJournals($bill);
$journals = $repository->getJournals($bill);
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill);
$hideBill = true;
$subTitle = e($bill->name);
return view('bills.show', compact('journals', 'hideBill', 'bill'))->with('subTitle', e($bill->name));
return view('bills.show', compact('journals', 'hideBill', 'bill', 'subTitle'));
}
/**
* @return $this
* @param BillFormRequest $request
* @param BillRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function store(BillFormRequest $request, BillRepositoryInterface $repository)
{
@@ -190,30 +217,40 @@ class BillController extends Controller
Session::flash('success', 'Bill "' . e($bill->name) . '" stored.');
if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('bills.create.fromStore', true);
return Redirect::route('bills.create')->withInput();
}
return Redirect::route('bills.index');
// redirect to previous URL.
return Redirect::to(Session::get('bills.create.url'));
}
/**
* @param Bill $bill
* @param BillFormRequest $request
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return $this
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function update(Bill $bill, BillFormRequest $request, BillRepositoryInterface $repository)
public function update(BillFormRequest $request, BillRepositoryInterface $repository, Bill $bill)
{
$billData = $request->getBillData();
$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');
if (intval(Input::get('return_to_edit')) === 1) {
// set value so edit routine will not overwrite URL:
Session::put('bills.edit.fromUpdate', true);
return Redirect::route('bills.edit', $bill->id)->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.
return Redirect::to(Session::get('bills.edit.url'));
}

View File

@@ -29,16 +29,19 @@ class BudgetController extends Controller
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Budgets');
View::share('mainTitleIcon', 'fa-tasks');
View::share('hideBudgets', true);
}
/**
* @param Budget $budget
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
*
* @return \Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function amount(Budget $budget, BudgetRepositoryInterface $repository)
public function amount(BudgetRepositoryInterface $repository, Budget $budget)
{
$amount = intval(Input::get('amount'));
$date = Session::get('start', Carbon::now()->startOfMonth());
@@ -58,8 +61,9 @@ class BudgetController extends Controller
Session::put('budgets.create.url', URL::previous());
}
Session::forget('budgets.create.fromStore');
$subTitle = 'Create a new budget';
return view('budgets.create')->with('subTitle', 'Create a new budget');
return view('budgets.create', compact('subTitle'));
}
/**
@@ -78,7 +82,8 @@ class BudgetController extends Controller
}
/**
* @param Budget $budget
* @param Budget $budget
* @param BudgetRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse
*/
@@ -114,7 +119,9 @@ class BudgetController extends Controller
}
/**
* @return mixed
* @param BudgetRepositoryInterface $repository
*
* @return View
*/
public function index(BudgetRepositoryInterface $repository)
{
@@ -148,7 +155,9 @@ class BudgetController extends Controller
}
/**
* @return \Illuminate\View\View
* @param BudgetRepositoryInterface $repository
*
* @return View
*/
public function noBudget(BudgetRepositoryInterface $repository)
{
@@ -161,7 +170,7 @@ class BudgetController extends Controller
}
/**
* @return mixed
* @return \Illuminate\Http\RedirectResponse
*/
public function postUpdateIncome()
{
@@ -173,24 +182,26 @@ class BudgetController extends Controller
}
/**
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return \Illuminate\View\View
* @return View
*/
public function show(Budget $budget, LimitRepetition $repetition = null, BudgetRepositoryInterface $repository)
public function show(BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition = null)
{
if (!is_null($repetition->id) && $repetition->budgetLimit->budget->id != $budget->id) {
return view('error')->with('message', 'Invalid selection.');
$message = 'Invalid selection.';
return view('error', compact('message'));
}
$hideBudget = true; // used in transaction list.
$journals = $repository->getJournals($budget, $repetition);
$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);
$journals = $repository->getJournals($budget, $repetition);
$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);
$journals->setPath('/budgets/show/' . $budget->id);
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle', 'hideBudget'));
return view('budgets.show', compact('limits', 'budget', 'repetition', 'journals', 'subTitle'));
}
/**
@@ -222,13 +233,13 @@ class BudgetController extends Controller
}
/**
* @param Budget $budget
* @param BudgetFormRequest $request
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
*
* @return \Illuminate\Http\RedirectResponse
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function update(Budget $budget, BudgetFormRequest $request, BudgetRepositoryInterface $repository)
public function update(BudgetFormRequest $request, BudgetRepositoryInterface $repository, Budget $budget)
{
$budgetData = [
'name' => $request->input('name'),
@@ -252,14 +263,14 @@ class BudgetController extends Controller
}
/**
* @return $this
* @return View
*/
public function updateIncome()
{
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
$budgetAmount = Preferences::get('budgetIncomeTotal' . $date, 1000);
$date = Session::get('start', Carbon::now()->startOfMonth())->format('FY');
$amount = Preferences::get('budgetIncomeTotal' . $date, 1000);
return view('budgets.income')->with('amount', $budgetAmount);
return view('budgets.income', compact('amount'));
}
}

View File

@@ -2,7 +2,6 @@
use Auth;
use Carbon\Carbon;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\CategoryFormRequest;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
@@ -26,6 +25,7 @@ class CategoryController extends Controller
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Categories');
View::share('mainTitleIcon', 'fa-bar-chart');
}
@@ -40,8 +40,9 @@ class CategoryController extends Controller
Session::put('categories.create.url', URL::previous());
}
Session::forget('categories.create.fromStore');
$subTitle = 'Create a new category';
return view('categories.create')->with('subTitle', 'Create a new category');
return view('categories.create', compact('subTitle'));
}
/**
@@ -51,7 +52,7 @@ class CategoryController extends Controller
*/
public function delete(Category $category)
{
$subTitle = 'Delete category' . e($category->name) . '"';
$subTitle = 'Delete category "' . e($category->name) . '"';
// put previous url in session
Session::put('categories.delete.url', URL::previous());
@@ -60,11 +61,12 @@ class CategoryController extends Controller
}
/**
* @param Category $category
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(Category $category, CategoryRepositoryInterface $repository)
public function destroy(CategoryRepositoryInterface $repository, Category $category)
{
$name = $category->name;
@@ -95,8 +97,9 @@ class CategoryController extends Controller
}
/**
* @return $this
* @param CategoryRepositoryInterface $repository
*
* @return $this
*/
public function index(CategoryRepositoryInterface $repository)
{
@@ -112,6 +115,8 @@ class CategoryController extends Controller
}
/**
* @param CategoryRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function noCategory(CategoryRepositoryInterface $repository)
@@ -125,17 +130,19 @@ class CategoryController extends Controller
}
/**
* @param Category $category
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return $this
* @return View
*/
public function show(Category $category, CategoryRepositoryInterface $repository)
public function show(CategoryRepositoryInterface $repository, Category $category)
{
$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'));
}
@@ -167,13 +174,13 @@ class CategoryController extends Controller
/**
* @param Category $category
* @param CategoryFormRequest $request
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Illuminate\Http\RedirectResponse
*/
public function update(Category $category, CategoryFormRequest $request, CategoryRepositoryInterface $repository)
public function update(CategoryFormRequest $request, CategoryRepositoryInterface $repository, Category $category)
{
$categoryData = [
'name' => $request->input('name'),

View File

@@ -3,6 +3,7 @@
use Illuminate\Foundation\Bus\DispatchesCommands;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use View;
/**
* Class Controller
@@ -14,4 +15,14 @@ abstract class Controller extends BaseController
use DispatchesCommands, ValidatesRequests;
/**
*
*/
public function __construct()
{
View::share('hideBudgets', false);
View::share('hideCategories', false);
View::share('hideBills', false);
View::share('hideTags', false);
}
}

View File

@@ -27,7 +27,7 @@ class CurrencyController extends Controller
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Currencies');
View::share('mainTitleIcon', 'fa-usd');
}
@@ -68,11 +68,12 @@ class CurrencyController extends Controller
}
/**
* @param TransactionCurrency $currency
* @param CurrencyRepositoryInterface $repository
* @param TransactionCurrency $currency
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
* @return \Illuminate\Http\RedirectResponse|View
*/
public function delete(TransactionCurrency $currency, CurrencyRepositoryInterface $repository)
public function delete(CurrencyRepositoryInterface $repository, TransactionCurrency $currency)
{
if ($repository->countJournals($currency) > 0) {
@@ -89,11 +90,13 @@ class CurrencyController extends Controller
}
/**
* @param TransactionCurrency $currency
* @param CurrencyRepositoryInterface $repository
* @param TransactionCurrency $currency
*
* @return \Illuminate\Http\RedirectResponse
* @throws \Exception
*/
public function destroy(TransactionCurrency $currency, CurrencyRepositoryInterface $repository)
public function destroy(CurrencyRepositoryInterface $repository, TransactionCurrency $currency)
{
if ($repository->countJournals($currency) > 0) {
Session::flash('error', 'Cannot destroy ' . e($currency->name) . ' because there are still transactions attached to it.');
@@ -130,6 +133,8 @@ class CurrencyController extends Controller
}
/**
* @param CurrencyRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function index(CurrencyRepositoryInterface $repository)
@@ -141,7 +146,9 @@ class CurrencyController extends Controller
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* @param CurrencyFormRequest $request
* @param CurrencyRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse
*/
@@ -166,11 +173,13 @@ class CurrencyController extends Controller
}
/**
* @param TransactionCurrency $currency
* @param CurrencyFormRequest $request
* @param CurrencyRepositoryInterface $repository
* @param TransactionCurrency $currency
*
* @return $this|\Illuminate\Http\RedirectResponse
* @return \Illuminate\Http\RedirectResponse
*/
public function update(TransactionCurrency $currency, CurrencyFormRequest $request, CurrencyRepositoryInterface $repository)
public function update(CurrencyFormRequest $request, CurrencyRepositoryInterface $repository, TransactionCurrency $currency)
{
$data = $request->getCurrencyData();
$currency = $repository->update($currency, $data);

View File

@@ -1,12 +1,7 @@
<?php namespace FireflyIII\Http\Controllers;
use Amount;
use App;
use Auth;
use Carbon\Carbon;
use Crypt;
use DB;
use Exception;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
@@ -17,11 +12,12 @@ 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;
@@ -39,16 +35,15 @@ class GoogleChartController extends Controller
/**
* @param GChart $chart
* @param Account $account
* @param string $view
*
* @return \Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function accountBalanceChart(Account $account, GChart $chart)
public function accountBalanceChart(GChart $chart, Account $account)
{
$accountName = iconv('UTF-8', 'ASCII//TRANSLIT', $account->name);
$chart->addColumn('Day of month', 'date');
$chart->addColumn('Balance for ' . $accountName, 'number');
$chart->addColumn('Balance for ' . $account->name, 'number');
$chart->addCertainty(1);
$start = Session::get('start', Carbon::now()->startOfMonth());
@@ -69,28 +64,24 @@ class GoogleChartController extends Controller
}
/**
* @param GChart $chart
* @param GChart $chart
* @param AccountRepositoryInterface $repository
*
* @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()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*']);
} else {
$accounts = Auth::user()->accounts()->whereIn('id', $frontPage->data)->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
}
$index = 1;
/** @var Account $account */
foreach ($accounts as $account) {
$accountName = $account->name;
$chart->addColumn('Balance for ' . $accountName, 'number');
$chart->addColumn('Balance for ' . $account->name, 'number');
$chart->addCertainty($index);
$index++;
}
@@ -108,34 +99,30 @@ class GoogleChartController extends Controller
$current->addDay();
}
$chart->generate();
//header('Content-Type: application/json; charset=utf-8');
return Response::json($chart->getData());
}
/**
* @param int $year
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param $year
*
* @return $this|\Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allBudgetsAndSpending($year, GChart $chart, BudgetRepositoryInterface $repository)
public function allBudgetsAndSpending(GChart $chart, BudgetRepositoryInterface $repository, $year)
{
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) {
@@ -146,7 +133,6 @@ class GoogleChartController extends Controller
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
@@ -154,112 +140,73 @@ class GoogleChartController extends Controller
}
/**
* @param GChart $chart
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
*
* @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');
$chart->addColumn('Left', 'number');
$chart->addColumn('Overspent', '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 Collection $repetitions */
$repetitions = 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.*']);
// no results? search entire range for expenses and list those.
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
if ($repetitions->count() == 0) {
$expenses = floatval($budget->transactionjournals()->before($end)->after($start)->lessThan(0)->sum('amount')) * -1;
if ($expenses > 0) {
$chart->addRow($budget->name, 0, $expenses);
}
} else {
// add with foreach:
/** @var LimitRepetition $repetition */
foreach ($repetitions as $repetition) {
$expenses
=
floatval($budget->transactionjournals()->before($repetition->enddate)->after($repetition->startdate)->lessThan(0)->sum('amount')) * -1;
if ($expenses > 0) {
$chart->addRow($budget->name . ' (' . $repetition->startdate->format('j M Y') . ')', floatval($repetition->amount), $expenses);
}
}
$expenses = $repository->sumBudgetExpensesInPeriod($budget, $start, $end);
$allEntries->push([$budget->name, 0, $expenses]);
continue;
}
/** @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) {
$left = $entry[1] - $entry[2];
if ($left > 0) {
$chart->addRow($entry[0], $left, null);
} else {
if ($left < 0) {
$chart->addRow($entry[0], null, $left);
}
}
}
}
$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();
$sum = $noBudgetSet->sum('amount') * -1;
$chart->addRow('No budget', 0, $sum);
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
*
* @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::
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`')]);
$set = $repository->getCategoriesAndExpenses($start, $end);
foreach ($set as $entry) {
$isEncrypted = intval($entry->encrypted) == 1 ? true : false;
@@ -275,11 +222,13 @@ class GoogleChartController extends Controller
}
/**
* @param Bill $bill
* @param GChart $chart
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return \Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function billOverview(Bill $bill, GChart $chart)
public function billOverview(GChart $chart, BillRepositoryInterface $repository, Bill $bill)
{
$chart->addColumn('Date', 'date');
@@ -288,24 +237,10 @@ class GoogleChartController extends Controller
$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;
}
$results = $bill->transactionjournals()->after($start)->get();
$results = $repository->getJournals($bill);
/** @var TransactionJournal $result */
foreach ($results as $result) {
$amount = 0;
/** @var Transaction $tr */
foreach ($result->transactions()->get() as $tr) {
if (floatval($tr->amount) > 0) {
$amount = floatval($tr->amount);
}
}
$chart->addRow(clone $result->date, $bill->amount_max, $bill->amount_min, $amount);
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
}
$chart->generate();
@@ -315,22 +250,28 @@ class GoogleChartController extends Controller
}
/**
* @param GChart $chart
* @param GChart $chart
*
* @param BillRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function billsOverview(GChart $chart, BillRepositoryInterface $repository)
public function billsOverview(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
{
$chart->addColumn('Name', 'string');
$chart->addColumn('Amount', 'number');
$paid = ['items' => [], 'amount' => 0];
$unpaid = ['items' => [], 'amount' => 0];
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$bills = Auth::user()->bills()->where('active', 1)->get();
$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) {
@@ -338,84 +279,70 @@ class GoogleChartController extends Controller
foreach ($ranges as $range) {
// paid a bill in this range?
$count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count();
if ($count == 0) {
$unpaid['items'][] = $bill->name . ' (' . $range['start']->format('jS M Y') . ')';
$unpaid['amount'] += ($bill->amount_max + $bill->amount_min / 2);
$journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']);
if ($journals->count() == 0) {
$unpaid->push([$bill, $range['start']]);
} else {
$journal = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first();
$paid['items'][] = $journal->description;
$amount = 0;
foreach ($journal->transactions as $t) {
if (floatval($t->amount) > 0) {
$amount = floatval($t->amount);
}
}
$paid['amount'] += $amount;
$paid = $paid->merge($journals);
}
}
}
/**
* Find credit card accounts and possibly unpaid credit card bills.
*/
$creditCards = Auth::user()->accounts()
->hasMetaValue('accountRole', 'ccAsset')
->hasMetaValue('ccType', 'monthlyFull')
->get(
[
'accounts.*',
'ccType.data as ccType',
'accountRole.data as accountRole'
]
);
// if the balance is not zero, the monthly payment is still underway.
/** @var Account $creditCard */
$creditCards = $accounts->getCreditCards();
foreach ($creditCards as $creditCard) {
$balance = Steam::balance($creditCard, null, true);
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
if ($balance < 0) {
// unpaid!
$unpaid['amount'] += $balance * -1;
$unpaid['items'][] = $creditCard->name . ' (expected ' . Amount::format(($balance * -1), false) . ') on the ' . $date->format('jS') . ')';
// 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 a transfer TO the credit card which should account for
// find transfer(s) TO the credit card which should account for
// anything paid. If not, the CC is not yet used.
$transactions = $creditCard->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->before($end)->after($start)->get();
if ($transactions->count() > 0) {
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
$journal = $transaction->transactionJournal;
if ($journal->transactionType->type == 'Transfer') {
$paid['amount'] += floatval($transaction->amount);
$paid['items'][] = $creditCard->name .
' (paid ' . Amount::format((floatval($transaction->amount)), false) .
' on the ' . $journal->date->format('jS') . ')';
}
}
}
$journals = $accounts->getTransfersInRange($creditCard, $start, $end);
$paid = $paid->merge($journals);
}
}
$chart->addRow('Unpaid: ' . join(', ', $unpaid['items']), $unpaid['amount']);
$chart->addRow('Paid: ' . join(', ', $paid['items']), $paid['amount']);
/** @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());
}
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return \Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function budgetLimitSpending(Budget $budget, LimitRepetition $repetition, GChart $chart)
public function budgetLimitSpending(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
{
$start = clone $repetition->startdate;
$end = $repetition->enddate;
@@ -430,7 +357,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();
@@ -442,37 +369,22 @@ class GoogleChartController extends Controller
}
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param int $year
*
* @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(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, $year = 0)
{
$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;
@@ -480,19 +392,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();
}
@@ -505,17 +406,17 @@ class GoogleChartController extends Controller
}
/**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @param Category $category
*
* @return \Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function categoryOverviewChart(Category $category, GChart $chart)
public function categoryOverviewChart(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{
// oldest transaction in category:
/** @var TransactionJournal $first */
$first = $category->transactionjournals()->orderBy('date', 'ASC')->first();
$start = $first->date;
$start = $repository->getFirstActivityDate($category);
/** @var Preference $range */
$range = Preferences::get('viewRange', '1M');
// jump to start of week / month / year / etc (TODO).
@@ -528,13 +429,12 @@ class GoogleChartController extends Controller
while ($start <= $end) {
$currentEnd = Navigation::endOfPeriod($start, $range->data);
$spent = floatval($category->transactionjournals()->before($currentEnd)->after($start)->lessThan(0)->sum('amount')) * -1;
$spent = $repository->spentInPeriodSum($category, $start, $currentEnd);
$chart->addRow(clone $start, $spent);
$start = Navigation::addPeriod($start, $range->data, 0);
}
$chart->generate();
return Response::json($chart->getData());
@@ -543,22 +443,21 @@ class GoogleChartController extends Controller
}
/**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @param Category $category
*
* @return \Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function categoryPeriodChart(Category $category, GChart $chart)
public function categoryPeriodChart(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{
// oldest transaction in category:
/** @var TransactionJournal $first */
$start = clone Session::get('start');
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$chart->addColumn('Period', 'date');
$chart->addColumn('Spent', 'number');
$end = Session::get('end');
$end = Session::get('end', Carbon::now()->endOfMonth());
while ($start <= $end) {
$spent = floatval($category->transactionjournals()->onDate($start)->lessThan(0)->sum('amount')) * -1;
$spent = $repository->spentOnDaySum($category, $start);
$chart->addRow(clone $start, $spent);
$start->addDay();
}
@@ -572,17 +471,19 @@ class GoogleChartController extends Controller
/**
* @param PiggyBank $piggyBank
* @param GChart $chart
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return \Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function piggyBankHistory(PiggyBank $piggyBank, GChart $chart)
public function piggyBankHistory(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
$chart->addColumn('Date', 'date');
$chart->addColumn('Balance', 'number');
/** @var Collection $set */
$set = DB::table('piggy_bank_events')->where('piggy_bank_id', $piggyBank->id)->groupBy('date')->get(['date', DB::Raw('SUM(`amount`) AS `sum`')]);
$set = $repository->getEventSummarySet($piggyBank);
$sum = 0;
foreach ($set as $entry) {
@@ -597,18 +498,15 @@ class GoogleChartController extends Controller
}
/**
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
*
* @param $year
*
* @return \Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInExp($year, GChart $chart, ReportQueryInterface $query)
public function yearInExp(GChart $chart, ReportQueryInterface $query, $year)
{
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');
@@ -623,19 +521,9 @@ class GoogleChartController extends Controller
while ($start < $end) {
$currentEnd = clone $start;
$currentEnd->endOfMonth();
// total income:
$income = $query->incomeByPeriod($start, $currentEnd, $showSharedReports);
$incomeSum = 0;
foreach ($income as $entry) {
$incomeSum += floatval($entry->amount);
}
// total expenses:
$expense = $query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports);
$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();
@@ -649,18 +537,15 @@ class GoogleChartController extends Controller
}
/**
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
*
* @param $year
*
* @return \Illuminate\Http\JsonResponse
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInExpSum($year, GChart $chart, ReportQueryInterface $query)
public function yearInExpSum(GChart $chart, ReportQueryInterface $query, $year)
{
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');
@@ -678,18 +563,9 @@ class GoogleChartController extends Controller
$currentEnd = clone $start;
$currentEnd->endOfMonth();
// total income:
$incomeResult = $query->incomeByPeriod($start, $currentEnd, $showSharedReports);
$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, $showSharedReports);
$expenseSum = 0;
foreach ($expenseResult as $entry) {
$expenseSum += floatval($entry->amount);
}
$expenseSum = floatval($query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
$income += $incomeSum;
$expense += $expenseSum;

View File

@@ -1,10 +1,8 @@
<?php namespace FireflyIII\Http\Controllers;
use Cache;
use ErrorException;
use League\CommonMark\CommonMarkConverter;
use FireflyIII\Helpers\Help\HelpInterface;
use Log;
use Response;
use Route;
/**
* Class HelpController
@@ -15,77 +13,39 @@ class HelpController extends Controller
{
/**
* @param $route
* @param HelpInterface $help
* @param $route
*
* @return \Illuminate\Http\JsonResponse
*/
public function show($route)
public function show(HelpInterface $help, $route)
{
$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;
}
}

View File

@@ -1,13 +1,14 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use Config;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Input;
use Preferences;
use Session;
use Redirect;
use Config;
use Session;
use Steam;
/**
* Class HomeController
*
@@ -31,31 +32,45 @@ class HomeController extends Controller
Session::put('end', $end);
}
public function flush() {
/**
* @return \Illuminate\Http\RedirectResponse
*/
public function flush()
{
Session::clear();
return Redirect::route('index');
}
/**
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function index(AccountRepositoryInterface $repository)
{
$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();
$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 = floatval(Auth::user()->transactions()->sum('amount'));
$sum = $repository->sumOfEverything();
if ($sum != 0) {
Session::flash(
'error', 'Your transactions are unbalanced. This means a'
@@ -71,7 +86,7 @@ class HomeController extends Controller
}
}
return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions'));
return view('index', compact('count', 'title', 'savings', 'subTitle', 'mainTitleIcon', 'transactions', 'savingsTotal', 'piggyBankAccounts'));
}

View File

@@ -1,15 +1,19 @@
<?php namespace FireflyIII\Http\Controllers;
use Amount;
use Auth;
use Carbon\Carbon;
use DB;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use Input;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Support\Collection;
use Preferences;
use Response;
use Session;
@@ -23,163 +27,143 @@ use Steam;
class JsonController extends Controller
{
/**
* @param BillRepositoryInterface $repository
*
* @param AccountRepositoryInterface $accountRepository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function box(BillRepositoryInterface $repository)
public function boxBillsPaid(BillRepositoryInterface $repository, AccountRepositoryInterface $accountRepository)
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$amount = 0;
$start = Session::get('start');
$end = Session::get('end');
$box = 'empty';
switch (Input::get('box')) {
case 'in':
$box = Input::get('box');
$in = Auth::user()->transactionjournals()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->before($end)
->after($start)
->transactionTypes(['Deposit'])
->where('transactions.amount', '>', 0)
->first([DB::Raw('SUM(transactions.amount) as `amount`')]);
if (!is_null($in)) {
$amount = floatval($in->amount);
}
break;
case 'out':
$box = Input::get('box');
$in = Auth::user()->transactionjournals()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->before($end)
->after($start)
->transactionTypes(['Withdrawal'])
->where('transactions.amount', '>', 0)
->first([DB::Raw('SUM(transactions.amount) as `amount`')]);
if (!is_null($in)) {
$amount = floatval($in->amount);
}
// these two functions are the same as the chart TODO
$bills = $repository->getActiveBills();
break;
case 'bills-unpaid':
$box = 'bills-unpaid';
$bills = Auth::user()->bills()->where('active', 1)->get();
/** @var Bill $bill */
foreach ($bills as $bill) {
$ranges = $repository->getRanges($bill, $start, $end);
/** @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);
foreach ($ranges as $range) {
// paid a bill in this range?
$count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count();
if ($count == 0) {
$amount += floatval($bill->amount_max + $bill->amount_min / 2);
}
}
}
/**
* Find credit card accounts and possibly unpaid credit card bills.
*/
$creditCards = Auth::user()->accounts()
->hasMetaValue('accountRole', 'ccAsset')
->hasMetaValue('ccType', 'monthlyFull')
->get(
[
'accounts.*',
'ccType.data as ccType',
'accountRole.data as accountRole'
]
);
// 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) {
// unpaid!
$amount += $balance * -1;
}
}
break;
case 'bills-paid':
$box = 'bills-paid';
// these two functions are the same as the chart TODO
$bills = Auth::user()->bills()->where('active', 1)->get();
/** @var Bill $bill */
foreach ($bills as $bill) {
$ranges = $repository->getRanges($bill, $start, $end);
foreach ($ranges as $range) {
// paid a bill in this range?
$count = $bill->transactionjournals()->before($range['end'])->after($range['start'])->count();
if ($count != 0) {
$journal = $bill->transactionjournals()->with('transactions')->before($range['end'])->after($range['start'])->first();
$currentAmount = 0;
foreach ($journal->transactions as $t) {
if (floatval($t->amount) > 0) {
$currentAmount = floatval($t->amount);
}
}
$amount += $currentAmount;
}
}
}
/**
* Find credit card accounts and possibly unpaid credit card bills.
*/
$creditCards = Auth::user()->accounts()
->hasMetaValue('accountRole', 'ccAsset')
->hasMetaValue('ccType', 'monthlyFull')
->get(
[
'accounts.*',
'ccType.data as ccType',
'accountRole.data as accountRole'
]
);
// 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.
$transactions = $creditCard->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->before($end)->after($start)->get();
if ($transactions->count() > 0) {
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
$journal = $transaction->transactionJournal;
if ($journal->transactionType->type == 'Transfer') {
$amount += floatval($transaction->amount);
}
}
}
}
}
/**
* 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' => $box, 'amount' => Amount::format($amount, false), 'amount_raw' => $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.
*
* @param CategoryRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*/
public function categories()
public function categories(CategoryRepositoryInterface $repository)
{
$list = Auth::user()->categories()->orderBy('name', 'ASC')->get();
$list = $repository->getCategories();
$return = [];
foreach ($list as $entry) {
$return[] = $entry->name;
}
sort($return);
return Response::json($return);
}
@@ -187,11 +171,13 @@ class JsonController extends Controller
/**
* Returns a JSON list of all beneficiaries.
*
* @param AccountRepositoryInterface $accountRepository
*
* @return \Illuminate\Http\JsonResponse
*/
public function expenseAccounts()
public function expenseAccounts(AccountRepositoryInterface $accountRepository)
{
$list = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Expense account', 'Beneficiary account'])->get();
$list = $accountRepository->getAccounts(['Expense account', 'Beneficiary account']);
$return = [];
foreach ($list as $entry) {
$return[] = $entry->name;
@@ -202,11 +188,32 @@ class JsonController extends Controller
}
/**
* Returns a JSON list of all beneficiaries.
*
* @param TagRepositoryInterface $tagRepository
*
* @return \Illuminate\Http\JsonResponse
*/
public function revenueAccounts()
public function tags(TagRepositoryInterface $tagRepository)
{
$list = Auth::user()->accounts()->accountTypeIn(['Revenue account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*']);
$list = $tagRepository->get();
$return = [];
foreach ($list as $entry) {
$return[] = $entry->tag;
}
return Response::json($return);
}
/**
* @param AccountRepositoryInterface $accountRepository
*
* @return \Illuminate\Http\JsonResponse
*/
public function revenueAccounts(AccountRepositoryInterface $accountRepository)
{
$list = $accountRepository->getAccounts(['Revenue account']);
$return = [];
foreach ($list as $entry) {
$return[] = $entry->name;
@@ -221,6 +228,7 @@ class JsonController extends Controller
*/
public function setSharedReports()
{
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$new = !$pref->data;
Preferences::set('showSharedReports', $new);
@@ -239,13 +247,18 @@ class JsonController extends Controller
return Response::json(['value' => $pref->data]);
}
public function transactionJournals($what)
/**
* @param JournalRepositoryInterface $repository
* @param $what
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function transactionJournals(JournalRepositoryInterface $repository, $what)
{
$descriptions = [];
$dbType = TransactionType::whereType($what)->first();
$journals = Auth::user()->transactionjournals()->where('transaction_type_id', $dbType->id)
->orderBy('id', 'DESC')->take(50)
->get();
$dbType = $repository->getTransactionType($what);
$journals = $repository->getJournalsOfType($dbType);
foreach ($journals as $j) {
$descriptions[] = $j->description;
}

View File

@@ -1,12 +1,12 @@
<?php namespace FireflyIII\Http\Controllers;
use Amount;
use Auth;
use Carbon\Carbon;
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;
@@ -16,8 +16,8 @@ use Input;
use Redirect;
use Session;
use Steam;
use View;
use URL;
use View;
/**
* Class PiggyBankController
@@ -32,6 +32,7 @@ class PiggyBankController extends Controller
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Piggy banks');
View::share('mainTitleIcon', 'fa-sort-amount-asc');
}
@@ -39,11 +40,12 @@ class PiggyBankController extends Controller
/**
* Add money to piggy bank
*
* @param PiggyBank $piggyBank
* @param AccountRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return $this
*/
public function add(PiggyBank $piggyBank, AccountRepositoryInterface $repository)
public function add(AccountRepositoryInterface $repository, PiggyBank $piggyBank)
{
$leftOnAccount = $repository->leftOnAccount($piggyBank->account);
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
@@ -54,15 +56,15 @@ class PiggyBankController extends Controller
}
/**
* @param AccountRepositoryInterface $repository
*
* @return mixed
*/
public function create()
public function create(AccountRepositoryInterface $repository)
{
$periods = Config::get('firefly.piggy_bank_periods');
$accounts = ExpandedForm::makeSelectList(
Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*'])
);
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$subTitle = 'Create new piggy bank';
$subTitleIcon = 'fa-plus';
@@ -91,33 +93,32 @@ class PiggyBankController extends Controller
}
/**
* @param PiggyBank $piggyBank
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(PiggyBank $piggyBank)
public function destroy(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.');
$piggyBank->delete();
$repository->destroy($piggyBank);
return Redirect::to(Session::get('piggy-banks.delete.url'));
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
* @param AccountRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @param PiggyBank $piggyBank
*
* @return $this
* @return View
*/
public function edit(PiggyBank $piggyBank)
public function edit(AccountRepositoryInterface $repository, PiggyBank $piggyBank)
{
$periods = Config::get('firefly.piggy_bank_periods');
$accounts = ExpandedForm::makeSelectList(
Auth::user()->accounts()->orderBy('accounts.name', 'ASC')->accountTypeIn(['Default account', 'Asset account'])->get(['accounts.*'])
);
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$subTitle = 'Edit piggy bank "' . e($piggyBank->name) . '"';
$subTitleIcon = 'fa-pencil';
@@ -149,18 +150,21 @@ class PiggyBankController extends Controller
}
/**
* @return $this
* @param AccountRepositoryInterface $repository
* @param PiggyBankRepositoryInterface $piggyRepository
*
* @return View
*/
public function index(AccountRepositoryInterface $repository)
public function index(AccountRepositoryInterface $repository, PiggyBankRepositoryInterface $piggyRepository)
{
/** @var Collection $piggyBanks */
$piggyBanks = Auth::user()->piggyBanks()->orderBy('order', 'ASC')->get();
$piggyBanks = $piggyRepository->getPiggyBanks();
$accounts = [];
/** @var PiggyBank $piggyBank */
foreach ($piggyBanks as $piggyBank) {
$piggyBank->savedSoFar = floatval($piggyBank->currentRelevantRep()->currentamount);
$piggyBank->percentage = intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100);
$piggyBank->percentage = $piggyBank->savedSoFar != 0 ? intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100) : 0;
$piggyBank->leftToSave = $piggyBank->targetamount - $piggyBank->savedSoFar;
/*
@@ -170,7 +174,7 @@ class PiggyBankController extends Controller
if (!isset($accounts[$account->id])) {
$accounts[$account->id] = [
'name' => $account->name,
'balance' => Steam::balance($account,null,true),
'balance' => Steam::balance($account, null, true),
'leftForPiggyBanks' => $repository->leftOnAccount($account),
'sumOfSaved' => $piggyBank->savedSoFar,
'sumOfTargets' => floatval($piggyBank->targetamount),
@@ -187,7 +191,7 @@ class PiggyBankController extends Controller
}
/**
* Allow user to order piggy banks.
* @param PiggyBankRepositoryInterface $repository
*/
public function order(PiggyBankRepositoryInterface $repository)
{
@@ -204,13 +208,13 @@ class PiggyBankController extends Controller
}
/**
* POST add money to piggy bank
*
* @param PiggyBank $piggyBank
* @param PiggyBankRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts
* @param PiggyBank $piggyBank
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postAdd(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts)
public function postAdd(PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts, PiggyBank $piggyBank)
{
$amount = round(floatval(Input::get('amount')), 2);
$leftOnAccount = $accounts->leftOnAccount($piggyBank->account);
@@ -223,8 +227,8 @@ 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
$repository->createEvent($piggyBank, $amount);
/*
* Create event!
@@ -240,11 +244,12 @@ class PiggyBankController extends Controller
}
/**
* @param PiggyBank $piggyBank
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return \Illuminate\Http\RedirectResponse
*/
public function postRemove(PiggyBank $piggyBank)
public function postRemove(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
$amount = floatval(Input::get('amount'));
@@ -255,12 +260,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!
*/
//Event::fire('piggy_bank.removeMoney', [$piggyBank, $amount]); // new and used.
// create event
$repository->createEvent($piggyBank, $amount * -1);
Session::flash('success', 'Removed ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".');
} else {
@@ -273,7 +274,6 @@ class PiggyBankController extends Controller
/**
* @param PiggyBank $piggyBank
*
* @SuppressWarnings("Unused")
*
* @return \Illuminate\View\View
*/
@@ -283,14 +283,14 @@ class PiggyBankController extends Controller
}
/**
* @param PiggyBank $piggyBank
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return $this
* @return View
*/
public function show(PiggyBank $piggyBank)
public function show(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
$events = $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
$events = $repository->getEvents($piggyBank);
/*
* Number of reminders:
@@ -310,6 +310,7 @@ class PiggyBankController extends Controller
*/
public function store(PiggyBankFormRequest $request, PiggyBankRepositoryInterface $repository)
{
$piggyBankData = [
'name' => $request->get('name'),
'startdate' => new Carbon,
@@ -326,6 +327,7 @@ class PiggyBankController extends Controller
if (intval(Input::get('create_another')) === 1) {
Session::put('piggy-banks.create.fromStore', true);
return Redirect::route('piggy-banks.create')->withInput();
}
@@ -335,13 +337,13 @@ class PiggyBankController extends Controller
}
/**
* @param PiggyBank $piggyBank
*
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBankFormRequest $request
* @param PiggyBank $piggyBank
*
* @return $this
*/
public function update(PiggyBank $piggyBank, PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request)
public function update(PiggyBankRepositoryInterface $repository, PiggyBankFormRequest $request, PiggyBank $piggyBank)
{
$piggyBankData = [
'name' => $request->get('name'),
@@ -353,13 +355,13 @@ class PiggyBankController extends Controller
'remind_me' => $request->get('remind_me')
];
$piggyBank = $repository->update($piggyBank, $piggyBankData);
Session::flash('success', 'Updated piggy bank "' . e($piggyBank->name) . '".');
if (intval(Input::get('return_to_edit')) === 1) {
Session::put('piggy-banks.edit.fromUpdate', true);
return Redirect::route('piggy-banks.edit', $piggyBank->id);
}

View File

@@ -1,6 +1,6 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Input;
use Preferences;
use Redirect;
@@ -20,26 +20,26 @@ class PreferencesController extends Controller
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Preferences');
View::share('mainTitleIcon', 'fa-gear');
}
/**
* @param AccountRepositoryInterface $repository
*
* @return $this|\Illuminate\View\View
*/
public function index()
public function index(AccountRepositoryInterface $repository)
{
$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', []);
$budgetMax = Preferences::get('budgetMaximum', 1000);
$budgetMaximum = $budgetMax->data;
$accounts = $repository->getAccounts(['Default account', 'Asset account']);
$viewRangePref = Preferences::get('viewRange', '1M');
$viewRange = $viewRangePref->data;
$frontPageAccounts = Preferences::get('frontPageAccounts', []);
$budgetMax = Preferences::get('budgetMaximum', 1000);
$budgetMaximum = $budgetMax->data;
return view('preferences.index', compact('budgetMaximum'))->with('accounts', $accounts)->with('frontPageAccounts', $frontPage)->with(
'viewRange', $viewRangeValue
);
return view('preferences.index', compact('budgetMaximum', 'accounts', 'frontPageAccounts', 'viewRange'));
}
/**

View File

@@ -2,6 +2,7 @@
use Auth;
use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\DeleteAccountFormRequest;
use FireflyIII\Http\Requests\ProfileFormRequest;
use Hash;
use Redirect;
@@ -25,6 +26,16 @@ class ProfileController extends Controller
);
}
/**
* @return \Illuminate\View\View
*/
public function deleteAccount()
{
return view('profile.delete-account')->with('title', Auth::user()->email)->with('subTitle', 'Delete account')->with(
'mainTitleIcon', 'fa-user'
);
}
/**
* @return \Illuminate\View\View
*
@@ -35,6 +46,8 @@ class ProfileController extends Controller
}
/**
* @param ProfileFormRequest $request
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
*/
public function postChangePassword(ProfileFormRequest $request)
@@ -45,7 +58,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'));
if (!($result === true)) {
Session::flash('error', $result);
@@ -62,29 +75,43 @@ class ProfileController extends Controller
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* @param string $old
* @param string $new1
* @param string $new2
*
* @return string|bool
*/
protected function validatePassword($old, $new1, $new2)
protected function validatePassword($old, $new1)
{
if (strlen($new1) == 0 || strlen($new2) == 0) {
return 'Do fill in a password!';
}
if ($new1 == $old) {
return 'The idea is to change your password.';
}
if ($new1 !== $new2) {
return 'New passwords do not match!';
}
return true;
}
/**
* @param DeleteAccountFormRequest $request
*
* @return \Illuminate\Http\RedirectResponse
* @throws \Exception
*/
public function postDeleteAccount(DeleteAccountFormRequest $request)
{
// old, new1, new2
if (!Hash::check($request->get('password'), Auth::user()->password)) {
Session::flash('error', 'Invalid password!');
return Redirect::route('delete-account');
}
// DELETE!
Auth::user()->delete();
Session::flush();
return Redirect::route('index');
}
}

View File

@@ -1,176 +0,0 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Support\Collection;
use Input;
use Redirect;
use Response;
use URL;
/**
* Class RelatedController
*
* @package FireflyIII\Http\Controllers
*/
class RelatedController extends Controller
{
/**
*
* @param TransactionJournal $journal
*
* @return \Illuminate\Http\JsonResponse
*/
public function alreadyRelated(TransactionJournal $journal)
{
$ids = [];
/** @var TransactionGroup $group */
foreach ($journal->transactiongroups()->get() as $group) {
/** @var TransactionJournal $loopJournal */
foreach ($group->transactionjournals()->get() as $loopJournal) {
if ($loopJournal->id != $journal->id) {
$ids[] = $loopJournal->id;
}
}
}
$unique = array_unique($ids);
$journals = new Collection;
if (count($unique) > 0) {
$journals = Auth::user()->transactionjournals()->whereIn('id', $unique)->get();
$journals->each(
function (TransactionJournal $journal) {
/** @var Transaction $t */
foreach ($journal->transactions()->get() as $t) {
if ($t->amount > 0) {
$journal->amount = $t->amount;
}
}
}
);
}
$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());
}
/**
* @param TransactionJournal $parentJournal
* @param TransactionJournal $childJournal
*
* @return \Illuminate\Http\JsonResponse
*/
public function relate(TransactionJournal $parentJournal, TransactionJournal $childJournal)
{
$group = new TransactionGroup;
$group->relation = 'balance';
$group->user_id = Auth::user()->id;
$group->save();
$group->transactionjournals()->save($parentJournal);
$group->transactionjournals()->save($childJournal);
return Response::json(true);
}
/**
* @param TransactionJournal $journal
*
* @return \Illuminate\View\View
*/
public function related(TransactionJournal $journal)
{
$groups = $journal->transactiongroups()->get();
$members = new Collection;
/** @var TransactionGroup $group */
foreach ($groups as $group) {
/** @var TransactionJournal $loopJournal */
foreach ($group->transactionjournals()->get() as $loopJournal) {
if ($loopJournal->id != $journal->id) {
$members->push($loopJournal);
}
}
}
return view('related.relate', compact('journal', 'members'));
}
/**
* @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 removeRelation(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 Response::json(true);
}
/**
* @param TransactionJournal $journal
*
* @return \Illuminate\Http\JsonResponse
*/
public function search(TransactionJournal $journal, JournalRepositoryInterface $repository)
{
$search = e(trim(Input::get('searchValue')));
$parent = $journal;
$journals = $repository->searchRelated($search, $journal);
return view('related.searchResult', compact('journals', 'search', 'parent'));
}
}

View File

@@ -1,9 +1,7 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use FireflyIII\Helpers\Reminders\ReminderHelperInterface;
use FireflyIII\Models\Reminder;
use FireflyIII\Repositories\Reminder\ReminderRepositoryInterface;
use Redirect;
use Session;
use URL;
@@ -19,6 +17,8 @@ class ReminderController extends Controller
/**
* @param Reminder $reminder
*
* @return \Illuminate\Http\RedirectResponse
*/
public function act(Reminder $reminder)
{
@@ -36,6 +36,8 @@ class ReminderController extends Controller
/**
* @param Reminder $reminder
*
* @return \Illuminate\Http\RedirectResponse
*/
public function dismiss(Reminder $reminder)
{
@@ -48,55 +50,18 @@ class ReminderController extends Controller
}
/**
* @param ReminderRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function index(ReminderHelperInterface $helper)
public function index(ReminderRepositoryInterface $repository)
{
$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;
}
}
);
$active = $repository->getActiveReminders();
$expired = $repository->getExpiredReminders();
$inactive = $repository->getInactiveReminders();
$dismissed = $repository->getDismissedReminders();
$title = 'Reminders';
$mainTitleIcon = 'fa-clock-o';
@@ -106,6 +71,8 @@ class ReminderController extends Controller
/**
* @param Reminder $reminder
*
* @return \Illuminate\View\View
*/
public function show(Reminder $reminder)
{

View File

@@ -1,7 +1,6 @@
<?php namespace FireflyIII\Http\Controllers;
use Carbon\Carbon;
use Exception;
use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account;
@@ -11,7 +10,6 @@ use Preferences;
use Session;
use Steam;
use View;
use Crypt;
/**
* Class ReportController
@@ -48,50 +46,52 @@ class ReportController extends Controller
*/
public function budget($year = '2014', $month = '1')
{
try {
new Carbon($year . '-' . $month . '-01');
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date');
}
$date = new Carbon($year . '-' . $month . '-01');
$start = clone $date;
$date = new Carbon($year . '-' . $month . '-01');
$subTitle = 'Budget report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar';
$start = clone $date;
$start->startOfMonth();
$end = clone $date;
$end->endOfMonth();
$start->subDay();
// should show shared reports?
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
$accountAmounts = []; // array with sums of spent amounts on each account.
$accounts = $this->query->getAllAccounts($start, $end, $showSharedReports); // all accounts and some data.
foreach ($accounts as $account) {
$dayEarly = clone $date;
$subTitle = 'Budget report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar';
$dayEarly = $dayEarly->subDay();
$accounts = $this->query->getAllAccounts($start, $end, $showSharedReports);
$start->addDay();
$budgets = $this->query->getBudgetSummary($account, $start, $end);// get budget summary for this account:
$balancedAmount = $this->query->balancedTransactionsSum($account, $start, $end);
$accountAmounts[$account->id] = $balancedAmount;
// balance out the transactions (see transaction groups & tags) ^^
$accounts->each(
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['amount']) != 0) {
$hide = false;
}
// array with budget information for each account:
$array = [];
// should always hide account
$hide = true;
// loop all budgets
/** @var \FireflyIII\Models\Budget $budget */
foreach ($budgets as $budget) {
$id = intval($budget->id);
$data = $budget->toArray();
$array[$id] = $data;
// no longer hide account if any budget has money in it.
if (floatval($data['queryAmount']) != 0) {
$hide = false;
}
$account->hide = $hide;
$account->budgetInformation = $array;
$account->balancedAmount = $balancedAmount;
$accountAmounts[$account->id] += $data['queryAmount'];
}
);
$account->hide = $hide;
$account->budgetInformation = $array;
$account->balancedAmount = $balancedAmount;
}
/**
* Start getBudgetsForMonth DONE
@@ -102,14 +102,14 @@ class ReportController extends Controller
* End getBudgetsForMonth DONE
*/
return view('reports.budget', compact('subTitle', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets', 'dayEarly'));
return view('reports.budget', compact('subTitle', 'accountAmounts', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets'));
}
/**
* @param ReportHelperInterface $helper
*
* @return View
* @internal param ReportHelperInterface $helper
*
*/
public function index()
{
@@ -132,11 +132,6 @@ class ReportController extends Controller
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();
@@ -149,20 +144,16 @@ class ReportController extends Controller
}
/**
* @param Account $account
* @param string $year
* @param string $month
* @param ReportQueryInterface $query
* @param Account $account
* @param string $year
* @param string $month
*
* @return View
* @internal param ReportQueryInterface $query
*
*/
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();
@@ -174,6 +165,8 @@ class ReportController extends Controller
if ($count == 0) {
return $journal;
}
return null;
}
);
@@ -189,11 +182,6 @@ class ReportController extends Controller
*/
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();
@@ -211,11 +199,6 @@ class ReportController extends Controller
*/
public function month($year = '2014', $month = '1')
{
try {
new Carbon($year . '-' . $month . '-01');
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date.');
}
$date = new Carbon($year . '-' . $month . '-01');
$subTitle = 'Report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar';
@@ -246,7 +229,7 @@ class ReportController extends Controller
/**
* Start getExpenseGroupedForMonth DONE
*/
$set = $this->query->journalsByExpenseAccount($start, $end, $showSharedReports);
$set = $this->query->journalsByExpenseAccount($start, $end, $showSharedReports);
$expenses = Steam::makeArray($set);
$expenses = Steam::sortArray($expenses);
@@ -327,11 +310,6 @@ class ReportController extends Controller
*/
public function year($year)
{
try {
new Carbon('01-01-' . $year);
} catch (Exception $e) {
return view('error')->with('message', 'Invalid date.');
}
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;

View File

@@ -12,6 +12,10 @@ class SearchController extends Controller
{
/**
* Results always come in the form of an array [results, count, fullCount]
*
* @param SearchInterface $searcher
*
* @return $this
*/
public function index(SearchInterface $searcher)
{

View File

@@ -0,0 +1,325 @@
<?php
namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use FireflyIII\Http\Requests\TagFormRequest;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Tag;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Input;
use Preferences;
use Redirect;
use Response;
use Session;
use URL;
use View;
/**
* Class TagController
*
* Remember: a balancingAct takes at most one expense and one transfer.
* an advancePayment takes at most one expense, infinite deposits and NO transfers.
*
* TODO transaction can only have one advancePayment OR balancingAct.
* TODO Other attempts to put in such a tag are blocked.
* TODO also show an error when editing a tag and it becomes either
* TODO of these two types. Or rather, block editing of the tag.
*
* @package FireflyIII\Http\Controllers
*/
class TagController extends Controller
{
/**
*
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Tags');
View::share('mainTitleIcon', 'fa-tags');
View::share('hideTags', true);
$tagOptions = [
'nothing' => 'Just a regular tag.',
'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
];
View::share('tagOptions', $tagOptions);
}
/**
* @return \Illuminate\View\View
*/
public function create()
{
$subTitle = 'New tag';
$subTitleIcon = 'fa-tag';
$preFilled = [
'tagMode' => 'nothing'
];
if (!Input::old('tagMode')) {
Session::flash('preFilled', $preFilled);
}
// put previous url in session if not redirect from store (not "create another").
if (Session::get('tags.create.fromStore') !== true) {
Session::put('tags.create.url', URL::previous());
}
Session::forget('tags.create.fromStore');
return view('tags.create', compact('subTitle', 'subTitleIcon'));
}
/**
* @param Tag $tag
*
* @return \Illuminate\View\View
*/
public function delete(Tag $tag)
{
$subTitle = 'Delete "' . e($tag->tag) . '"';
// put previous url in session
Session::put('tags.delete.url', URL::previous());
return view('tags.delete', compact('tag', 'subTitle'));
}
/**
* @param TagRepositoryInterface $repository
* @param Tag $tag
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(TagRepositoryInterface $repository, Tag $tag)
{
$tagName = $tag->tag;
$repository->destroy($tag);
Session::flash('success', 'Tag "' . e($tagName) . '" was deleted.');
return Redirect::to(route('tags.index'));
}
/**
* @param Tag $tag
*
* @return View
*/
public function edit(Tag $tag)
{
$subTitle = 'Edit tag "' . e($tag->tag) . '"';
$subTitleIcon = 'fa-tag';
/*
* Default tag options (again)
*/
$tagOptions = [
'nothing' => 'Just a regular tag.',
'balancingAct' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
'advancePayment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
];
/*
* Can this tag become another type?
*/
$allowToAdvancePayment = true;
$allowToBalancingAct = true;
/*
* If this tag is a balancing act, and it contains transfers, it cannot be
* changes to an advancePayment.
*/
if ($tag->tagMode == 'balancingAct') {
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Transfer') {
$allowToAdvancePayment = false;
}
}
}
/*
* If this tag contains more than one expenses, it cannot become an advance payment.
*/
$count = 0;
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Withdrawal') {
$count++;
}
}
if ($count > 1) {
$allowToAdvancePayment = false;
}
/*
* If has more than two transactions already, cannot become a balancing act:
*/
if ($tag->transactionjournals->count() > 2) {
$allowToBalancingAct = false;
}
/*
* If any transaction is a deposit, cannot become a balancing act.
*/
$count = 0;
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Deposit') {
$count++;
}
}
if ($count > 0) {
$allowToBalancingAct = false;
}
// edit tag options:
if ($allowToAdvancePayment === false) {
unset($tagOptions['advancePayment']);
}
if ($allowToBalancingAct === false) {
unset($tagOptions['balancingAct']);
}
// put previous url in session if not redirect from store (not "return_to_edit").
if (Session::get('tags.edit.fromUpdate') !== true) {
Session::put('tags.edit.url', URL::previous());
}
Session::forget('tags.edit.fromUpdate');
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'tagOptions'));
}
/**
* @param $state
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function hideTagHelp($state)
{
$state = $state == 'true' ? true : false;
Preferences::set('hideTagHelp', $state);
return Response::json(true);
}
/**
*
*/
public function index()
{
/** @var Preference $helpHiddenPref */
$helpHiddenPref = Preferences::get('hideTagHelp', false);
$title = 'Tags';
$mainTitleIcon = 'fa-tags';
$helpHidden = $helpHiddenPref->data;
$tags = Auth::user()->tags()->get();
return view('tags.index', compact('title', 'mainTitleIcon', 'helpHidden', 'tags'));
}
/**
* @param Tag $tag
*
* @return \Illuminate\View\View
*/
public function show(Tag $tag)
{
$subTitle = $tag->tag;
$subTitleIcon = 'fa-tag';
return view('tags.show', compact('tag', 'subTitle', 'subTitleIcon'));
}
/**
* @param TagFormRequest $request
*
* @param TagRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function store(TagFormRequest $request, TagRepositoryInterface $repository)
{
if (Input::get('setTag') == 'true') {
$latitude = strlen($request->get('latitude')) > 0 ? $request->get('latitude') : null;
$longitude = strlen($request->get('longitude')) > 0 ? $request->get('longitude') : null;
$zoomLevel = strlen($request->get('zoomLevel')) > 0 ? $request->get('zoomLevel') : null;
} else {
$latitude = null;
$longitude = null;
$zoomLevel = null;
}
$data = [
'tag' => $request->get('tag'),
'date' => strlen($request->get('date')) > 0 ? new Carbon($request->get('date')) : null,
'description' => strlen($request->get('description')) > 0 ? $request->get('description') : '',
'latitude' => $latitude,
'longitude' => $longitude,
'zoomLevel' => $zoomLevel,
'tagMode' => $request->get('tagMode'),
];
$repository->store($data);
Session::flash('success', 'The tag has been created!');
if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('tags.create.fromStore', true);
return Redirect::route('tags.create')->withInput();
}
// redirect to previous URL.
return Redirect::to(Session::get('tags.create.url'));
}
/**
* @param TagFormRequest $request
* @param TagRepositoryInterface $repository
* @param Tag $tag
*
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function update(TagFormRequest $request, TagRepositoryInterface $repository, Tag $tag)
{
if (Input::get('setTag') == 'true') {
$latitude = strlen($request->get('latitude')) > 0 ? $request->get('latitude') : null;
$longitude = strlen($request->get('longitude')) > 0 ? $request->get('longitude') : null;
$zoomLevel = strlen($request->get('zoomLevel')) > 0 ? $request->get('zoomLevel') : null;
} else {
$latitude = null;
$longitude = null;
$zoomLevel = null;
}
$data = [
'tag' => $request->get('tag'),
'date' => strlen($request->get('date')) > 0 ? new Carbon($request->get('date')) : null,
'description' => strlen($request->get('description')) > 0 ? $request->get('description') : '',
'latitude' => $latitude,
'longitude' => $longitude,
'zoomLevel' => $zoomLevel,
'tagMode' => $request->get('tagMode'),
];
$repository->update($tag, $data);
Session::flash('success', 'Tag "' . e($data['tag']) . '" updated.');
if (intval(Input::get('return_to_edit')) === 1) {
// set value so edit routine will not overwrite URL:
Session::put('tags.edit.fromUpdate', true);
return Redirect::route('tags.edit', $tag->id)->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.
return Redirect::to(Session::get('tags.edit.url'));
}
}

View File

@@ -1,6 +1,7 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Carbon\Carbon;
use ExpandedForm;
use FireflyIII\Events\JournalCreated;
use FireflyIII\Events\JournalSaved;
@@ -8,8 +9,8 @@ use FireflyIII\Http\Requests;
use FireflyIII\Http\Requests\JournalFormRequest;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use Illuminate\Pagination\LengthAwarePaginator;
use Input;
use Redirect;
use Response;
@@ -28,24 +29,20 @@ class TransactionController extends Controller
*/
public function __construct()
{
parent::__construct();
View::share('title', 'Transactions');
View::share('mainTitleIcon', 'fa-repeat');
}
/**
* Shows the view helping the user to create a new transaction journal.
* @param AccountRepositoryInterface $repository
* @param string $what
*
* @param string $what
*
* @return \Illuminate\View\View
* @return View
*/
public function create($what = 'deposit')
public function create(AccountRepositoryInterface $repository, $what = 'deposit')
{
$accounts = ExpandedForm::makeSelectList(
Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->orderBy('name', 'ASC')->where(
'active', 1
)->orderBy('name', 'DESC')->get(['accounts.*'])
);
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = '(no budget)';
$piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
@@ -94,15 +91,16 @@ class TransactionController extends Controller
}
/**
* @param TransactionJournal $transactionJournal
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $transactionJournal
*
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy(TransactionJournal $transactionJournal)
public function destroy(JournalRepositoryInterface $repository, TransactionJournal $transactionJournal)
{
Session::flash('success', 'Transaction "' . e($transactionJournal->description) . '" destroyed.');
$transactionJournal->delete();
$repository->delete($transactionJournal);
// redirect to previous URL:
return Redirect::to(Session::get('transactions.delete.url'));
@@ -111,18 +109,15 @@ class TransactionController extends Controller
/**
* Shows the view to edit a transaction.
*
* @param TransactionJournal $journal
* @param AccountRepositoryInterface $repository
* @param TransactionJournal $journal
*
* @return $this
*/
public function edit(TransactionJournal $journal, JournalRepositoryInterface $repository)
public function edit(AccountRepositoryInterface $repository, TransactionJournal $journal)
{
$what = strtolower($journal->transactiontype->type);
$accounts = ExpandedForm::makeSelectList(
Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->where('active', 1)->orderBy(
'name', 'DESC'
)->get(['accounts.*'])
);
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = '(no budget)';
$transactions = $journal->transactions()->orderBy('amount', 'DESC')->get();
@@ -134,6 +129,12 @@ class TransactionController extends Controller
'budget_id' => 0,
'piggy_bank_id' => 0
];
// get tags:
$tags = [];
foreach ($journal->tags as $tag) {
$tags[] = $tag->tag;
}
$preFilled['tags'] = join(',', $tags);
$category = $journal->categories()->first();
if (!is_null($category)) {
@@ -149,19 +150,15 @@ class TransactionController extends Controller
$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['account_id'] = $repository->getAssetAccount($journal);
$preFilled['amount'] = $journal->amount;
$preFilled['account_id'] = $journal->assetAccount->id;
$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;
Session::flash('preFilled', $preFilled);
// 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());
@@ -173,12 +170,14 @@ class TransactionController extends Controller
}
/**
* @param $what
* @param JournalRepositoryInterface $repository
* @param $what
*
* @return $this
* @return View
*/
public function index($what)
public function index(JournalRepositoryInterface $repository, $what)
{
$types = [];
switch ($what) {
case 'expenses':
case 'withdrawal':
@@ -200,18 +199,10 @@ class TransactionController extends Controller
break;
}
$page = intval(\Input::get('page'));
$offset = $page > 0 ? ($page - 1) * 50 : 0;
$page = intval(Input::get('page'));
$offset = $page > 0 ? ($page - 1) * 50 : 0;
$journals = $repository->getJournalsOfTypes($types, $offset, $page);
$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);
return view('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals'));
@@ -219,15 +210,19 @@ class TransactionController extends Controller
}
/**
* Reorder transactions (which all must have the same date)
* @param JournalRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function reorder()
public function reorder(JournalRepositoryInterface $repository)
{
$ids = Input::get('items');
$ids = Input::get('items');
$date = new Carbon(Input::get('date'));
if (count($ids) > 0) {
$order = 0;
foreach ($ids as $id) {
$journal = Auth::user()->transactionjournals()->where('id', $id)->where('date', Input::get('date'))->first();
$journal = $repository->getWithDate($id, $date);
if ($journal) {
$journal->order = $order;
$order++;
@@ -241,31 +236,22 @@ class TransactionController extends Controller
}
/**
* @param TransactionJournal $journal
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $journal
*
* @return $this
*/
public function show(TransactionJournal $journal)
public function show(JournalRepositoryInterface $repository, TransactionJournal $journal)
{
$journal->transactions->each(
function (Transaction $t) use ($journal) {
$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.order', '>=', $journal->order)
->where('transaction_journals.id', '!=', $journal->id)
->sum('transactions.amount')
);
function (Transaction $t) use ($journal, $repository) {
$t->before = $repository->getAmountBefore($journal, $t);
$t->after = $t->before + $t->amount;
}
);
$subTitle = e($journal->transactiontype->type) . ' "' . e($journal->description) . '"';
return view('transactions.show', compact('journal'))->with(
'subTitle', e($journal->transactiontype->type) . ' "' . e($journal->description) . '"'
);
return view('transactions.show', compact('journal', 'subTitle'));
}
/**
@@ -285,11 +271,7 @@ class TransactionController extends Controller
// 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();
}
$repository->deactivateReminder($request->get('reminder_id'));
Session::flash('success', 'New transaction "' . $journal->description . '" stored!');
@@ -305,14 +287,15 @@ class TransactionController extends Controller
}
/**
* @param TransactionJournal $journal
* @param JournalFormRequest $request
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $journal
*
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* @return $this
* @return $this|\Illuminate\Http\RedirectResponse
*/
public function update(TransactionJournal $journal, JournalFormRequest $request, JournalRepositoryInterface $repository)
public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, TransactionJournal $journal)
{
$journalData = $request->getJournalData();

View File

@@ -3,17 +3,13 @@
namespace FireflyIII\Http\Middleware;
use Carbon\Carbon;
use App;
use Closure;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Navigation;
use Session;
use App;
/**
* Class PiggyBanks

View File

@@ -30,7 +30,7 @@ class BudgetFormRequest extends Request
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,encrypted';
if (Budget::find(Input::get('id'))) {
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,encrypted,'.intval(Input::get('id'));
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,encrypted,' . intval(Input::get('id'));
}
return [

View File

@@ -30,7 +30,7 @@ class CategoryFormRequest extends Request
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,encrypted';
if (Category::find(Input::get('id'))) {
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,encrypted,'.intval(Input::get('id'));
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,encrypted,' . intval(Input::get('id'));
}
return [

View File

@@ -0,0 +1,32 @@
<?php
namespace FireflyIII\Http\Requests;
use Auth;
/**
* Class DeleteAccountFormRequest
*
* @package FireflyIII\Http\Requests
*/
class DeleteAccountFormRequest extends Request
{
/**
* @return bool
*/
public function authorize()
{
// Only allow logged in users
return Auth::check();
}
/**
* @return array
*/
public function rules()
{
return [
'password' => 'required',
];
}
}

View File

@@ -42,6 +42,7 @@ class JournalFormRequest extends Request
'date' => new Carbon($this->get('date')),
'budget_id' => intval($this->get('budget_id')),
'category' => $this->get('category'),
'tags' => explode(',', $this->get('tags')),
];
}
@@ -56,7 +57,7 @@ class JournalFormRequest extends Request
$rules = [
'description' => 'required|min:1,max:255',
'what' => 'required|in:withdrawal,deposit,transfer|exists:transaction_types,type',
'what' => 'required|in:withdrawal,deposit,transfer',
'amount' => 'numeric|required|min:0.01',
'date' => 'required|date',
'reminder_id' => 'numeric|exists:reminders,id',

View File

@@ -3,9 +3,7 @@
namespace FireflyIII\Http\Requests;
use Auth;
use Carbon\Carbon;
use Input;
use Navigation;
/**
* Class PiggyBankFormRequest
@@ -32,7 +30,7 @@ class PiggyBankFormRequest extends Request
$nameRule = 'required|between:1,255|uniquePiggyBankForUser';
$targetDateRule = 'date';
if (intval(Input::get('id'))) {
$nameRule = 'required|between:1,255|uniquePiggyBankForUser:'.intval(Input::get('id'));
$nameRule = 'required|between:1,255|uniquePiggyBankForUser:' . intval(Input::get('id'));
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 27/04/15
* Time: 12:50
*/
namespace FireflyIII\Http\Requests;
use Auth;
use FireflyIII\Models\Tag;
use Input;
/**
* Class TagFormRequest
*
* @package FireflyIII\Http\Requests
*/
class TagFormRequest extends Request
{
/**
* @return bool
*/
public function authorize()
{
// Only allow logged in users
return Auth::check();
}
/**
* @return array
*/
public function rules()
{
$idRule = '';
$tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,TRUE';
if (Tag::find(Input::get('id'))) {
$idRule = 'belongsToUser:tags';
$tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,TRUE,' . Input::get('id');
}
return [
'tag' => $tagRule,
'id' => $idRule,
'description' => 'min:1',
'date' => 'date',
'latitude' => 'numeric|min:-90|max:90',
'longitude' => 'numeric|min:-90|max:90',
'tagMode' => 'required|in:nothing,balancingAct,advancePayment'
];
}
}

View File

@@ -9,6 +9,8 @@ use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
/*
@@ -22,6 +24,14 @@ Breadcrumbs::register(
}
);
Breadcrumbs::register(
'index',
function (Generator $breadcrumbs) {
$breadcrumbs->push('Home', route('index'));
}
);
// accounts
Breadcrumbs::register(
'accounts.index', function (Generator $breadcrumbs, $what) {
@@ -95,6 +105,13 @@ Breadcrumbs::register(
}
);
Breadcrumbs::register(
'budgets.noBudget', function (Generator $breadcrumbs, $subTitle) {
$breadcrumbs->parent('budgets.index');
$breadcrumbs->push($subTitle, route('budgets.noBudget'));
}
);
Breadcrumbs::register(
'budgets.show', function (Generator $breadcrumbs, Budget $budget, LimitRepetition $repetition = null) {
$breadcrumbs->parent('budgets.index');
@@ -142,6 +159,34 @@ Breadcrumbs::register(
}
);
Breadcrumbs::register(
'categories.noCategory', function (Generator $breadcrumbs, $subTitle) {
$breadcrumbs->parent('categories.index');
$breadcrumbs->push($subTitle, route('categories.noCategory'));
}
);
// currencies.
Breadcrumbs::register(
'currency.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Currencies', route('currency.index'));
}
);
Breadcrumbs::register(
'currency.edit', function (Generator $breadcrumbs, TransactionCurrency $currency) {
$breadcrumbs->parent('currency.index');
$breadcrumbs->push('Edit ' . $currency->name, route('currency.edit', $currency->id));
}
);
Breadcrumbs::register(
'currency.delete', function (Generator $breadcrumbs, TransactionCurrency $currency) {
$breadcrumbs->parent('currency.index');
$breadcrumbs->push('Delete ' . $currency->name, route('currency.delete', $currency->id));
}
);
// piggy banks
Breadcrumbs::register(
@@ -268,21 +313,21 @@ Breadcrumbs::register(
Breadcrumbs::register(
'reports.year', function (Generator $breadcrumbs, Carbon $date) {
$breadcrumbs->parent('reports.index');
$breadcrumbs->push($date->format('Y'), route('reports.year', $date->format('Y')));
$breadcrumbs->push($date->year, route('reports.year', $date->year));
}
);
Breadcrumbs::register(
'reports.month', function (Generator $breadcrumbs, Carbon $date) {
$breadcrumbs->parent('reports.index');
$breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', $date));
$breadcrumbs->push('Monthly report for ' . $date->format('F Y'), route('reports.month', [$date->year, $date->month]));
}
);
Breadcrumbs::register(
'reports.budget', function (Generator $breadcrumbs, Carbon $date) {
$breadcrumbs->parent('reports.index');
$breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', $date));
$breadcrumbs->push('Budget report for ' . $date->format('F Y'), route('reports.budget', [$date->year, $date->month]));
}
);
@@ -350,3 +395,24 @@ Breadcrumbs::register(
}
);
// tags
Breadcrumbs::register(
'tags.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Tags', route('tags.index'));
}
);
Breadcrumbs::register(
'tags.create', function (Generator $breadcrumbs) {
$breadcrumbs->parent('tags.index');
$breadcrumbs->push('Create tag', route('tags.create'));
}
);
Breadcrumbs::register(
'tags.show', function (Generator $breadcrumbs, Tag $tag) {
$breadcrumbs->parent('tags.index');
$breadcrumbs->push(e($tag->tag), route('tags.show', $tag->id));
}
);

View File

@@ -6,121 +6,177 @@ use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Reminder;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
// models
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'account',
function ($value, $route) {
if (Auth::check()) {
$account = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.editable', 1)
->where('accounts.id', $value)
->where('user_id', Auth::user()->id)
->first(['accounts.*']);
if ($account) {
return $account;
$object = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->where('account_types.editable', 1)
->where('accounts.id', $value)
->where('user_id', Auth::user()->id)
->first(['accounts.*']);
if ($object) {
return $object;
}
}
App::abort(404);
throw new NotFoundHttpException;
}
);
Route::bind(
'tjSecond', function ($value, $route) {
if (Auth::check()) {
return TransactionJournal::
where('id', $value)->where('user_id', Auth::user()->id)->first();
}
return null;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'tj', function ($value, $route) {
if (Auth::check()) {
return TransactionJournal::
where('id', $value)->where('user_id', Auth::user()->id)->first();
$object = TransactionJournal::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
}
return null;
throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'currency', function ($value, $route) {
return TransactionCurrency::find($value);
if (Auth::check()) {
$object = TransactionCurrency::find($value);
if ($object) {
return $object;
}
}
throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'bill', function ($value, $route) {
if (Auth::check()) {
return Bill::where('id', $value)->where('user_id', Auth::user()->id)->first();
$object = Bill::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
}
return null;
throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'budget', function ($value, $route) {
if (Auth::check()) {
return Budget::where('id', $value)->where('user_id', Auth::user()->id)->first();
$object = Budget::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
}
return null;
throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'reminder', function ($value, $route) {
if (Auth::check()) {
return Reminder::where('id', $value)->where('user_id', Auth::user()->id)->first();
$object = Reminder::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
}
return null;
throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'limitrepetition', function ($value, $route) {
if (Auth::check()) {
return LimitRepetition::where('limit_repetitions.id', $value)
->leftjoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->where('budgets.user_id', Auth::user()->id)
->first(['limit_repetitions.*']);
$object = LimitRepetition::where('limit_repetitions.id', $value)
->leftjoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->where('budgets.user_id', Auth::user()->id)
->first(['limit_repetitions.*']);
if ($object) {
return $object;
}
}
return null;
throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'piggyBank', 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)
->first(['piggy_banks.*']);
$object = PiggyBank::where('piggy_banks.id', $value)
->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')
->where('accounts.user_id', Auth::user()->id)
->first(['piggy_banks.*']);
if ($object) {
return $object;
}
}
return null;
throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'category', function ($value, $route) {
if (Auth::check()) {
return Category::where('id', $value)->where('user_id', Auth::user()->id)->first();
$object = Category::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
}
return null;
throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'reminder', function ($value, $route) {
if (Auth::check()) {
/** @var \FireflyIII\Models\Reminder $object */
$object = Reminder::find($value);
if ($object) {
if ($object->remindersable->account->user_id == Auth::user()->id) {
return $object;
}
}
}
throw new NotFoundHttpException;
}
);
/** @noinspection PhpUnusedParameterInspection */
Route::bind(
'tag', function ($value, $route) {
if (Auth::check()) {
$object = Tag::where('id', $value)->where('user_id', Auth::user()->id)->first();
if ($object) {
return $object;
}
}
throw new NotFoundHttpException;
}
);
@@ -170,7 +226,6 @@ Route::group(
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']);
@@ -226,7 +281,7 @@ 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/reports/income-expenses/{year}', ['uses' => 'GoogleChartController@yearInExp']);
Route::get('/chart/reports/income-expenses-sum/{year}', ['uses' => 'GoogleChartController@yearInExpSum']);
@@ -246,7 +301,11 @@ 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', ['uses' => 'JsonController@box', 'as' => 'json.box']);
Route::get('/json/tags', ['uses' => 'JsonController@tags', 'as' => 'json.tags']);
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');
@@ -280,18 +339,10 @@ Route::group(
*/
Route::get('/profile', ['uses' => 'ProfileController@index', 'as' => 'profile']);
Route::get('/profile/change-password', ['uses' => 'ProfileController@changePassword', 'as' => 'change-password']);
Route::get('/profile/delete-account', ['uses' => 'ProfileController@deleteAccount', 'as' => 'delete-account']);
Route::post('/profile/delete-account', ['uses' => 'ProfileController@postDeleteAccount', 'as' => 'delete-account-post']);
Route::post('/profile/change-password', ['uses' => 'ProfileController@postChangePassword', 'as' => 'change-password-post']);
/**
* Related transactions controller
*/
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']);
/**
* Reminder Controller
*/
@@ -323,6 +374,22 @@ Route::group(
*/
Route::get('/search', ['uses' => 'SearchController@index', 'as' => 'search']);
/**
* Tag Controller
*/
Route::get('/tags', ['uses' => 'TagController@index', 'as' => 'tags.index']);
Route::get('/tags/create', ['uses' => 'TagController@create', 'as' => 'tags.create']);
Route::get('/tags/show/{tag}', ['uses' => 'TagController@show', 'as' => 'tags.show']);
Route::get('/tags/edit/{tag}', ['uses' => 'TagController@edit', 'as' => 'tags.edit']);
Route::get('/tags/delete/{tag}', ['uses' => 'TagController@delete', 'as' => 'tags.delete']);
Route::post('/tags/store', ['uses' => 'TagController@store', 'as' => 'tags.store']);
Route::post('/tags/update/{tag}', ['uses' => 'TagController@update', 'as' => 'tags.update']);
Route::post('/tags/destroy/{tag}', ['uses' => 'TagController@destroy', 'as' => 'tags.destroy']);
Route::post('/tags/hideTagHelp/{state}', ['uses' => 'TagController@hideTagHelp', 'as' => 'tags.hideTagHelp']);
/**
* Transaction Controller
*/

View File

@@ -51,9 +51,11 @@ class Account extends Model
$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));
App::abort(500, 'Could not create new account with data: ' . json_encode($fields) . ' because ' . json_encode($account->getErrors()));
}
return $account;
}

View File

@@ -1,8 +1,10 @@
<?php namespace FireflyIII\Models;
use App;
use Crypt;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Crypt;
/**
* Class Category
*
@@ -30,6 +32,39 @@ class Category extends Model
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
*/
@@ -46,6 +81,7 @@ class Category extends Model
$this->attributes['name'] = Crypt::encrypt($value);
$this->attributes['encrypted'] = true;
}
/**
* @param $value
*

View File

@@ -1,5 +1,7 @@
<?php namespace FireflyIII\Models;
use Auth;
use DB;
use Illuminate\Database\Eloquent\Model;
/**
@@ -26,18 +28,23 @@ class LimitRepetition extends Model
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('transactions.amount', '>', 0)
->where('limit_repetitions.id', '=', $this->id)
->sum('transactions.amount');
$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);
}

View File

@@ -1,8 +1,9 @@
<?php namespace FireflyIII\Models;
use Crypt;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Crypt;
/**
* Class PiggyBank
*
@@ -13,7 +14,7 @@ class PiggyBank extends Model
use SoftDeletes;
protected $fillable
= ['name', 'account_id', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me'];
= ['name', 'account_id', 'order', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
@@ -92,6 +93,7 @@ class PiggyBank extends Model
$this->attributes['name'] = Crypt::encrypt($value);
$this->attributes['encrypted'] = true;
}
/**
* @param $value
*

View File

@@ -1,9 +1,10 @@
<?php namespace FireflyIII\Models;
use Carbon\Carbon;
use Crypt;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model;
use Crypt;
/**
* Class Reminder
*
@@ -43,6 +44,7 @@ class Reminder extends Model
if (intval($this->encrypted) == 1) {
return json_decode(Crypt::decrypt($value));
}
return json_decode($value);
}
@@ -76,6 +78,11 @@ class Reminder extends Model
return $query->where('reminders.startdate', '=', $start->format('Y-m-d 00:00:00'))->where('reminders.enddate', '=', $end->format('Y-m-d 00:00:00'));
}
/**
* @param EloquentBuilder $query
*
* @return $this
*/
public function scopeToday(EloquentBuilder $query)
{
$today = new Carbon;
@@ -90,7 +97,7 @@ class Reminder extends Model
public function setMetadataAttribute($value)
{
$this->attributes['encrypted'] = true;
$this->attributes['metadata'] = Crypt::encrypt(json_encode($value));
$this->attributes['metadata'] = Crypt::encrypt(json_encode($value));
}
/**

128
app/Models/Tag.php Normal file
View File

@@ -0,0 +1,128 @@
<?php
namespace FireflyIII\Models;
use App;
use Crypt;
use Illuminate\Database\Eloquent\Model;
use Watson\Validating\ValidatingTrait;
/**
* Class Tag
*
* @package FireflyIII\Models
*/
class Tag extends Model
{
use ValidatingTrait;
protected $fillable = ['user_id', 'tag', 'date', 'description', 'longitude', 'latitude', 'zoomLevel', 'tagMode'];
protected $rules
= [
'tag' => 'required|min:1|uniqueObjectForUser:tags,tag,TRUE',
'description' => 'min:1',
'date' => 'date',
'latitude' => 'numeric|min:-90|max:90',
'longitude' => 'numeric|min:-90|max:90',
'tagMode' => 'required|in:nothing,balancingAct,advancePayment'
];
/**
* @param array $fields
*
* @return Tag|null
*/
public static function firstOrCreateEncrypted(array $fields)
{
// everything but the tag:
if (isset($fields['tagMode'])) {
unset($fields['tagMode']);
}
$query = Tag::orderBy('id');
foreach ($fields as $name => $value) {
if ($name != 'tag') {
$query->where($name, $value);
}
}
$set = $query->get(['tags.*']);
/** @var Tag $tag */
foreach ($set as $tag) {
if ($tag->tag == $fields['tag']) {
return $tag;
}
}
// create it!
$fields['tagMode'] = 'nothing';
$fields['description'] = isset($fields['description']) && !is_null($fields['description']) ? $fields['description'] : '';
$tag = Tag::create($fields);
if (is_null($tag->id)) {
// could not create account:
App::abort(500, 'Could not create new tag with data: ' . json_encode($fields) . ' because ' . json_encode($tag->getErrors()));
}
return $tag;
}
/**
* @return array
*/
public function getDates()
{
return ['created_at', 'updated_at', 'date'];
}
/**
* @param $value
*
* @return string
*/
public function getDescriptionAttribute($value)
{
return Crypt::decrypt($value);
}
/**
* @param $value
*
* @return string
*/
public function getTagAttribute($value)
{
return Crypt::decrypt($value);
}
/**
* @param $value
*/
public function setDescriptionAttribute($value)
{
$this->attributes['description'] = Crypt::encrypt($value);
}
/**
* @param $value
*/
public function setTagAttribute($value)
{
$this->attributes['tag'] = Crypt::encrypt($value);
}
/**
* @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');
}
}

View File

@@ -1,10 +1,11 @@
<?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;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Carbon\Carbon;
/**
* Class Transaction
*

View File

@@ -55,6 +55,52 @@ 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 0;
}
/**
* @return Account|mixed
*/
public function getAssetAccountAttribute()
{
$positive = true; // the asset account is in the transaction with the positive amount.
if ($this->transactionType->type === 'Withdrawal') {
$positive = false;
}
/** @var Transaction $transaction */
foreach ($this->transactions()->get() as $transaction) {
if (floatval($transaction->amount) > 0 && $positive === true) {
return $transaction->account;
}
if (floatval($transaction->amount) < 0 && $positive === false) {
return $transaction->account;
}
}
return $this->transactions()->first();
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function transactions()
{
return $this->hasMany('FireflyIII\Models\Transaction');
}
/**
* @return array
*/
@@ -188,6 +234,14 @@ class TransactionJournal extends Model
$this->attributes['encrypted'] = true;
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags()
{
return $this->belongsToMany('FireflyIII\Models\Tag');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
@@ -212,14 +266,6 @@ class TransactionJournal extends Model
return $this->belongsToMany('FireflyIII\Models\TransactionGroup');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function transactions()
{
return $this->hasMany('FireflyIII\Models\Transaction');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/

View File

@@ -35,6 +35,7 @@ class AppServiceProvider extends ServiceProvider
'Illuminate\Contracts\Auth\Registrar',
'FireflyIII\Services\Registrar'
);
}
}

View File

@@ -23,7 +23,227 @@ class ConfigServiceProvider extends ServiceProvider
{
config(
[
//
'twigbridge' => [
'twig' => [
/*
|--------------------------------------------------------------------------
| Extension
|--------------------------------------------------------------------------
|
| File extension for Twig view files.
|
*/
'extension' => 'twig',
/*
|--------------------------------------------------------------------------
| Accepts all Twig environment configuration options
|--------------------------------------------------------------------------
|
| http://twig.sensiolabs.org/doc/api.html#environment-options
|
*/
'environment' => [
// When set to true, the generated templates have a __toString() method
// that you can use to display the generated nodes.
// default: false
'debug' => config('app.debug', false),
// The charset used by the templates.
// default: utf-8
'charset' => 'utf-8',
// The base template class to use for generated templates.
// default: TwigBridge\Twig\Template
'base_template_class' => 'TwigBridge\Twig\Template',
// An absolute path where to store the compiled templates, or false to disable caching. If null
// then the cache file path is used.
// default: cache file storage path
'cache' => null,
// When developing with Twig, it's useful to recompile the template
// whenever the source code changes. If you don't provide a value
// for the auto_reload option, it will be determined automatically based on the debug value.
'auto_reload' => true,
// If set to false, Twig will silently ignore invalid variables
// (variables and or attributes/methods that do not exist) and
// replace them with a null value. When set to true, Twig throws an exception instead.
// default: false
'strict_variables' => false,
// If set to true, auto-escaping will be enabled by default for all templates.
// default: true
'autoescape' => true,
// A flag that indicates which optimizations to apply
// (default to -1 -- all optimizations are enabled; set it to 0 to disable)
'optimizations' => -1,
],
/*
|--------------------------------------------------------------------------
| Global variables
|--------------------------------------------------------------------------
|
| These will always be passed in and can be accessed as Twig variables.
| NOTE: these will be overwritten if you pass data into the view with the same key.
|
*/
'globals' => [],
],
'extensions' => [
/*
|--------------------------------------------------------------------------
| Extensions
|--------------------------------------------------------------------------
|
| Enabled extensions.
|
| `Twig_Extension_Debug` is enabled automatically if twig.debug is TRUE.
|
*/
'enabled' => [
'TwigBridge\Extension\Loader\Facades',
'TwigBridge\Extension\Loader\Filters',
'TwigBridge\Extension\Loader\Functions',
'TwigBridge\Extension\Laravel\Auth',
'TwigBridge\Extension\Laravel\Config',
'TwigBridge\Extension\Laravel\Dump',
'TwigBridge\Extension\Laravel\Input',
'TwigBridge\Extension\Laravel\Session',
'TwigBridge\Extension\Laravel\String',
'TwigBridge\Extension\Laravel\Translator',
'TwigBridge\Extension\Laravel\Url',
// 'TwigBridge\Extension\Laravel\Form',
// 'TwigBridge\Extension\Laravel\Html',
// 'TwigBridge\Extension\Laravel\Legacy\Facades',
],
/*
|--------------------------------------------------------------------------
| Facades
|--------------------------------------------------------------------------
|
| Available facades. Access like `{{ Config.get('foo.bar') }}`.
|
| Each facade can take an optional array of options. To mark the whole facade
| as safe you can set the option `'is_safe' => true`. Setting the facade as
| safe means that any HTML returned will not be escaped.
|
| It is advisable to not set the whole facade as safe and instead mark the
| each appropriate method as safe for security reasons. You can do that with
| the following syntax:
|
| <code>
| 'Form' => [
| 'is_safe' => [
| 'open'
| ]
| ]
| </code>
|
| The values of the `is_safe` array must match the called method on the facade
| in order to be marked as safe.
|
*/
'facades' => [
'Breadcrumbs' => [
'is_safe' => [
'renderIfExists'
]
],
'Session',
'Route',
'Auth',
'URL',
'Config',
'ExpandedForm' => [
'is_safe' => [
'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location',
'multiRadio'
]
],
'Form' => [
'is_safe' => [
'input', 'select', 'checkbox', 'model', 'open', 'radio', 'textarea'
]
],
],
/*
|--------------------------------------------------------------------------
| Functions
|--------------------------------------------------------------------------
|
| Available functions. Access like `{{ secure_url(...) }}`.
|
| Each function can take an optional array of options. These options are
| passed directly to `Twig_SimpleFunction`.
|
| So for example, to mark a function as safe you can do the following:
|
| <code>
| 'link_to' => [
| 'is_safe' => ['html']
| ]
| </code>
|
| The options array also takes a `callback` that allows you to name the
| function differently in your Twig templates than what it's actually called.
|
| <code>
| 'link' => [
| 'callback' => 'link_to'
| ]
| </code>
|
*/
'functions' => [
'elixir',
'head',
'last',
'old'
],
/*
|--------------------------------------------------------------------------
| Filters
|--------------------------------------------------------------------------
|
| Available filters. Access like `{{ variable|filter }}`.
|
| Each filter can take an optional array of options. These options are
| passed directly to `Twig_SimpleFilter`.
|
| So for example, to mark a filter as safe you can do the following:
|
| <code>
| 'studly_case' => [
| 'is_safe' => ['html']
| ]
| </code>
|
| The options array also takes a `callback` that allows you to name the
| filter differently in your Twig templates than what is actually called.
|
| <code>
| 'snake' => [
| 'callback' => 'snake_case'
| ]
| </code>
|
*/
'filters' => [],
],
]
]
);
}

View File

@@ -1,10 +1,12 @@
<?php namespace FireflyIII\Providers;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\Reminder;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Support\Facades\Navigation;
@@ -12,7 +14,7 @@ use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Log;
use Reminder;
/**
* Class EventServiceProvider
*
@@ -60,14 +62,15 @@ class EventServiceProvider extends ServiceProvider
);
PiggyBank::deleting(function(PiggyBank $piggyBank) {
$reminders = $piggyBank->reminders()->get();
/** @var Reminder $reminder */
foreach($reminders as $reminder) {
$reminder->delete();
PiggyBank::deleting(
function (PiggyBank $piggyBank) {
$reminders = $piggyBank->reminders()->get();
/** @var Reminder $reminder */
foreach ($reminders as $reminder) {
$reminder->delete();
}
}
});
);
Account::deleted(
function (Account $account) {

View File

@@ -2,13 +2,21 @@
namespace FireflyIII\Providers;
use App;
use FireflyIII\Models\Account;
use FireflyIII\Support\Amount;
use FireflyIII\Support\ExpandedForm;
use FireflyIII\Support\Navigation;
use FireflyIII\Support\Preferences;
use FireflyIII\Support\Steam;
use FireflyIII\Support\Twig\Budget;
use FireflyIII\Support\Twig\General;
use FireflyIII\Support\Twig\Journal;
use FireflyIII\Support\Twig\PiggyBank;
use FireflyIII\Validation\FireflyValidator;
use Illuminate\Support\ServiceProvider;
use Twig;
use TwigBridge\Extension\Loader\Functions;
use Validator;
/**
@@ -25,10 +33,22 @@ class FireflyServiceProvider extends ServiceProvider
return new FireflyValidator($translator, $data, $rules, $messages);
}
);
/*
* Default Twig configuration:
*/
$config = App::make('config');
Twig::addExtension(new Functions($config));
Twig::addExtension(new PiggyBank);
Twig::addExtension(new General);
Twig::addExtension(new Journal);
Twig::addExtension(new Budget);
}
public function register()
{
$this->app->bind(
'preferences', function () {
return new Preferences;
@@ -63,13 +83,17 @@ class FireflyServiceProvider extends ServiceProvider
$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\Repositories\Tag\TagRepositoryInterface', 'FireflyIII\Repositories\Tag\TagRepository');
$this->app->bind('FireflyIII\Repositories\Reminder\ReminderRepositoryInterface', 'FireflyIII\Repositories\Reminder\ReminderRepository');
$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');
}
}

View File

@@ -6,6 +6,7 @@ use App;
use Auth;
use Carbon\Carbon;
use Config;
use DB;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\AccountType;
@@ -53,26 +54,36 @@ class AccountRepository implements AccountRepositoryInterface
/**
* @param array $types
* @param int $page
*
* @return Collection
*/
public function getAccounts(array $types, $page)
public function getAccounts(array $types)
{
$query = Auth::user()->accounts()->with(
$result = Auth::user()->accounts()->with(
['accountmeta' => function (HasMany $query) {
$query->where('name', 'accountRole');
}]
)->accountTypeIn($types)->orderBy('accounts.name', 'ASC');
)->accountTypeIn($types)->orderBy('accounts.name', 'ASC')->get(['accounts.*'])->sortBy('name');
if ($page == -1) {
return $query->get(['accounts.*']);
} else {
$size = 50;
$offset = ($page - 1) * $size;
return $result;
}
return $query->take($size)->offset($offset)->get(['accounts.*']);
}
/**
* @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'
]
);
}
/**
@@ -135,7 +146,7 @@ class AccountRepository implements AccountRepositoryInterface
* @param Account $account
* @param int $page
*
* @return mixed
* @return LengthAwarePaginator
*/
public function getJournals(Account $account, $page)
{
@@ -177,6 +188,51 @@ class AccountRepository implements AccountRepositoryInterface
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.
*
@@ -219,6 +275,34 @@ class AccountRepository implements AccountRepositoryInterface
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
*
@@ -279,9 +363,19 @@ class AccountRepository implements AccountRepositoryInterface
}
/**
* @return float
*/
public function sumOfEverything()
{
return floatval(Auth::user()->transactions()->sum('amount'));
}
/**
* @param Account $account
* @param array $data
*
* @return Account
*/
public function update(Account $account, array $data)
{
@@ -461,7 +555,6 @@ class AccountRepository implements AccountRepositoryInterface
protected function updateMetadata(Account $account, array $data)
{
$validFields = ['accountRole', 'ccMonthlyPaymentDate', 'ccType'];
$updated = false;
foreach ($validFields as $field) {
$entry = $account->accountMeta()->where('name', $field)->first();

View File

@@ -7,6 +7,7 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
/**
@@ -32,11 +33,10 @@ interface AccountRepositoryInterface
/**
* @param array $types
* @param int $page
*
* @return mixed
*/
public function getAccounts(array $types, $page);
public function getAccounts(array $types);
/**
* @param TransactionJournal $journal
@@ -46,6 +46,30 @@ interface AccountRepositoryInterface
*/
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
*
@@ -64,9 +88,9 @@ interface AccountRepositoryInterface
/**
* @param Account $account
* @param string $range
* @param $page
*
* @return mixed
* @return LengthAwarePaginator
*/
public function getJournals(Account $account, $page);
@@ -77,6 +101,11 @@ interface AccountRepositoryInterface
*/
public function getLastActivity(Account $account);
/**
* @return float
*/
public function sumOfEverything();
/**
* Get savings accounts and the balance difference in the period.
*

View File

@@ -4,9 +4,12 @@ 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 Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Log;
use Navigation;
@@ -18,6 +21,31 @@ use Navigation;
*/
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
*
@@ -28,12 +56,26 @@ class BillRepository implements BillRepositoryInterface
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()
{
return Auth::user()->bills()->orderBy('name', 'ASC')->get();
/** @var Collection $set */
$set = Auth::user()->bills()->orderBy('name', 'ASC')->get()->sortBy('name');
return $set;
}
/**
@@ -44,10 +86,30 @@ class BillRepository implements BillRepositoryInterface
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();
->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();
}
/**
@@ -149,10 +211,12 @@ class BillRepository implements BillRepositoryInterface
* $today is the start of the next period, to make sure FF3 won't miss anything
* when the current period has a transaction journal.
*/
$today = Navigation::addPeriod(new Carbon, $bill->repeat_freq, 0);
/** @var \Carbon\Carbon $obj */
$obj = new Carbon;
$today = Navigation::addPeriod($obj, $bill->repeat_freq, 0);
$skip = $bill->skip + 1;
$start = Navigation::startOfPeriod(new Carbon, $bill->repeat_freq);
$start = Navigation::startOfPeriod($obj, $bill->repeat_freq);
/*
* go back exactly one month/week/etc because FF3 does not care about 'next'
* bills if they're too far into the past.
@@ -253,6 +317,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();
}
}
}

View File

@@ -15,6 +15,17 @@ use Illuminate\Support\Collection;
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
*
@@ -22,6 +33,11 @@ interface BillRepositoryInterface
*/
public function destroy(Bill $bill);
/**
* @return Collection
*/
public function getActiveBills();
/**
* @return Collection
*/
@@ -32,14 +48,25 @@ interface BillRepositoryInterface
*
* @return Collection
*/
public function getPossiblyRelatedJournals(Bill $bill);
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 getJournals(Bill $bill);
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)
@@ -61,6 +88,7 @@ interface BillRepositoryInterface
*/
public function lastFoundMatch(Bill $bill);
/**
* @param Bill $bill
*

View File

@@ -7,6 +7,7 @@ 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;
@@ -55,12 +56,65 @@ 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()
{
return Auth::user()->budgets()->where('active', 1)->get();
$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;
}
/**
@@ -74,12 +128,27 @@ class BudgetRepository implements BudgetRepositoryInterface
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', 1)->get();
return Auth::user()->budgets()->where('active', 0)->get();
}
/**
@@ -115,6 +184,41 @@ class BudgetRepository implements BudgetRepositoryInterface
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
@@ -135,6 +239,36 @@ class BudgetRepository implements BudgetRepositoryInterface
->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
@@ -169,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
@@ -224,14 +370,4 @@ class BudgetRepository implements BudgetRepositoryInterface
}
/**
* @param Budget $budget
*
* @return Collection
*/
public function getBudgetLimits(Budget $budget)
{
return $budget->budgetLimits()->orderBy('startdate', 'DESC')->get();
}
}

View File

@@ -14,6 +14,11 @@ use Illuminate\Support\Collection;
*/
interface BudgetRepositoryInterface
{
/**
* @return void
*/
public function cleanupBudgets();
/**
* @param Budget $budget
*
@@ -21,36 +26,27 @@ interface BudgetRepositoryInterface
*/
public function destroy(Budget $budget);
/**
* @return Collection
*/
public function getActiveBudgets();
/**
* @return Collection
*/
public function getInactiveBudgets();
/**
* @return void
*/
public function cleanupBudgets();
/**
* @param Budget $budget
* @param Carbon $date
*
* @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 getWithoutBudget(Carbon $start, Carbon $end);
public function getBudgetLimitRepetitions(Budget $budget, Carbon $start, Carbon $end);
/**
* @param Budget $budget
@@ -59,6 +55,11 @@ interface BudgetRepositoryInterface
*/
public function getBudgetLimits(Budget $budget);
/**
* @return Collection
*/
public function getBudgets();
/**
* @param Budget $budget
* @param Carbon $date
@@ -69,27 +70,15 @@ interface BudgetRepositoryInterface
/**
* @param Budget $budget
* @param Carbon $date
* @param $amount
*
* @return mixed
* @return Carbon
*/
public function updateLimitAmount(Budget $budget, Carbon $date, $amount);
public function getFirstBudgetLimitDate(Budget $budget);
/**
* @param array $data
*
* @return Budget
* @return Collection
*/
public function store(array $data);
/**
* @param Budget $budget
* @param array $data
*
* @return Budget
*/
public function update(Budget $budget, array $data);
public function getInactiveBudgets();
/**
* Returns all the transaction journals for a limit, possibly limited by a limit repetition.
@@ -102,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);
}

View File

@@ -4,7 +4,10 @@ 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;
/**
@@ -43,7 +46,62 @@ class CategoryRepository implements CategoryRepositoryInterface
*/
public function getCategories()
{
return Auth::user()->categories()->orderBy('name', 'ASC')->get();
/** @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;
}
/**
@@ -105,6 +163,29 @@ class CategoryRepository implements CategoryRepositoryInterface
->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
*

View File

@@ -32,6 +32,21 @@ interface CategoryRepositoryInterface
*/
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
@@ -55,6 +70,23 @@ interface CategoryRepositoryInterface
*/
public function getWithoutCategory(Carbon $start, Carbon $end);
/**
* @param Category $category
* @param \Carbon\Carbon $start
* @param \Carbon\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
*

View File

@@ -81,4 +81,4 @@ class CurrencyRepository implements CurrencyRepositoryInterface
return $currency;
}
}
}

View File

@@ -49,4 +49,4 @@ interface CurrencyRepositoryInterface
*/
public function update(TransactionCurrency $currency, array $data);
}
}

View File

@@ -4,13 +4,17 @@ namespace FireflyIII\Repositories\Journal;
use App;
use Auth;
use Carbon\Carbon;
use DB;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Log;
@@ -22,6 +26,38 @@ use Log;
class JournalRepository implements JournalRepositoryInterface
{
/**
* @param int $reminderId
*
* @return bool
*/
public function deactivateReminder($reminderId)
{
$reminder = Auth::user()->reminders()->find($reminderId);
if ($reminder) {
$reminder->active = 0;
$reminder->save();
}
}
/**
* @param TransactionJournal $journal
*
* @return bool
*/
public function delete(TransactionJournal $journal)
{
// delete transactions first:
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
$transaction->delete();
}
$journal->delete();
return true;
}
/**
* Get users first transaction journal
*
@@ -33,85 +69,98 @@ class JournalRepository implements JournalRepositoryInterface
}
/**
*
* Get the account_id, which is the asset account that paid for the transaction.
*
* @param TransactionJournal $journal
* @param Transaction $transaction
*
* @return mixed
* @return float
*/
public function getAssetAccount(TransactionJournal $journal)
public function getAmountBefore(TransactionJournal $journal, Transaction $transaction)
{
$positive = true; // the asset account is in the transaction with the positive amount.
switch ($journal->transactionType->type) {
case 'Withdrawal':
$positive = false;
break;
}
/** @var Transaction $transaction */
foreach ($journal->transactions()->get() as $transaction) {
if (floatval($transaction->amount) > 0 && $positive === true) {
return $transaction->account_id;
}
if (floatval($transaction->amount) < 0 && $positive === false) {
return $transaction->account_id;
}
}
return $journal->transactions()->first()->account_id;
return floatval(
$transaction->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.order', '>=', $journal->order)
->where('transaction_journals.id', '!=', $journal->id)
->sum('transactions.amount')
);
}
/**
* @param string $query
* @param TransactionJournal $journal
* @param TransactionType $dbType
*
* @return Collection
*/
public function searchRelated($query, TransactionJournal $journal)
public function getJournalsOfType(TransactionType $dbType)
{
$start = clone $journal->date;
$end = clone $journal->date;
$start->startOfMonth();
$end->endOfMonth();
return Auth::user()->transactionjournals()->where('transaction_type_id', $dbType->id)->orderBy('id', 'DESC')->take(50)->get();
}
// get already related transactions:
$exclude = [$journal->id];
foreach ($journal->transactiongroups()->get() as $group) {
foreach ($group->transactionjournals()->get() as $current) {
$exclude[] = $current->id;
/**
* @param array $types
* @param int $offset
* @param int $page
*
* @return LengthAwarePaginator
*/
public function getJournalsOfTypes(array $types, $offset, $page)
{
$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);
return $journals;
}
/**
* @param $type
*
* @return TransactionType
*/
public function getTransactionType($type)
{
return TransactionType::whereType($type)->first();
}
/**
* @param $id
* @param Carbon $date
*
* @return TransactionJournal
*/
public function getWithDate($id, Carbon $date)
{
return Auth::user()->transactionjournals()->where('id', $id)->where('date', $date->format('Y-m-d'))->first();
}
/**
*
* * Remember: a balancingAct takes at most one expense and one transfer.
* an advancePayment takes at most one expense, infinite deposits and NO transfers.
*
* @param TransactionJournal $journal
* @param array $array
*
* @return void
*/
public function saveTags(TransactionJournal $journal, array $array)
{
/** @var \FireflyIII\Repositories\Tag\TagRepositoryInterface $tagRepository */
$tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface');
foreach ($array as $name) {
if (strlen(trim($name)) > 0) {
$tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]);
$tagRepository->connect($journal, $tag);
}
}
$exclude = array_unique($exclude);
/** @var Collection $collection */
$collection = Auth::user()->transactionjournals()
->withRelevantData()
->before($end)->after($start)->where('encrypted', 0)
->whereNotIn('id', $exclude)
->where('description', 'LIKE', '%' . $query . '%')
->get();
// manually search encrypted entries:
/** @var Collection $encryptedCollection */
$encryptedCollection = Auth::user()->transactionjournals()
->withRelevantData()
->before($end)->after($start)
->where('encrypted', 1)
->whereNotIn('id', $exclude)
->get();
$encrypted = $encryptedCollection->filter(
function (TransactionJournal $journal) use ($query) {
$strPos = strpos(strtolower($journal->description), strtolower($query));
if ($strPos !== false) {
return $journal;
}
return null;
}
);
return $collection->merge($encrypted);
}
/**
@@ -140,12 +189,13 @@ 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);
}
// store or get budget
if (intval($data['budget_id']) > 0) {
/** @var \FireflyIII\Models\Budget $budget */
$budget = Budget::find($data['budget_id']);
$journal->budgets()->save($budget);
}
@@ -171,6 +221,11 @@ class JournalRepository implements JournalRepositoryInterface
$journal->completed = 1;
$journal->save();
// store tags
if (isset($data['tags']) && is_array($data['tags'])) {
$this->saveTags($journal, $data['tags']);
}
return $journal;
@@ -193,13 +248,14 @@ 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);
}
// unlink all budgets and recreate them:
$journal->budgets()->detach();
if (intval($data['budget_id']) > 0) {
/** @var \FireflyIII\Models\Budget $budget */
$budget = Budget::find($data['budget_id']);
$journal->budgets()->save($budget);
}
@@ -226,9 +282,54 @@ class JournalRepository implements JournalRepositoryInterface
$journal->save();
// update tags:
if (isset($data['tags']) && is_array($data['tags'])) {
$this->updateTags($journal, $data['tags']);
}
return $journal;
}
/**
* @param TransactionJournal $journal
* @param array $array
*
* @return void
*/
public function updateTags(TransactionJournal $journal, array $array)
{
// create tag repository
/** @var \FireflyIII\Repositories\Tag\TagRepositoryInterface $tagRepository */
$tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface');
// find or create all tags:
$tags = [];
$ids = [];
foreach ($array as $name) {
if (strlen(trim($name)) > 0) {
$tag = Tag::firstOrCreateEncrypted(['tag' => $name, 'user_id' => $journal->user_id]);
$tags[] = $tag;
$ids[] = $tag->id;
}
}
// delete all tags connected to journal not in this array:
if (count($ids) > 0) {
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->whereNotIn('tag_id', $ids)->delete();
}
// if count is zero, delete them all:
if (count($ids) == 0) {
DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal->id)->delete();
}
// connect each tag to journal (if not yet connected):
/** @var Tag $tag */
foreach ($tags as $tag) {
$tagRepository->connect($journal, $tag);
}
}
/**
* @param TransactionType $type
* @param array $data
@@ -289,5 +390,4 @@ class JournalRepository implements JournalRepositoryInterface
return [$from, $to];
}
}

View File

@@ -2,8 +2,11 @@
namespace FireflyIII\Repositories\Journal;
use FireflyIII\Models\TransactionJournal;
use Carbon\Carbon;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
/**
@@ -14,22 +17,79 @@ use Illuminate\Support\Collection;
interface JournalRepositoryInterface
{
/**
* @param int $reminderId
*
* Get the account_id, which is the asset account that paid for the transaction.
*
* @param TransactionJournal $journal
*
* @return int
* @return bool
*/
public function getAssetAccount(TransactionJournal $journal);
public function deactivateReminder($reminderId);
/**
* @param string $query
* @param TransactionJournal $journal
*
* @return bool
*/
public function delete(TransactionJournal $journal);
/**
* Get users first transaction journal
*
* @return TransactionJournal
*/
public function first();
/**
* @param TransactionJournal $journal
* @param Transaction $transaction
*
* @return float
*/
public function getAmountBefore(TransactionJournal $journal, Transaction $transaction);
/**
* @param TransactionType $dbType
*
* @return Collection
*/
public function searchRelated($query, TransactionJournal $journal);
public function getJournalsOfType(TransactionType $dbType);
/**
* @param array $types
* @param int $offset
* @param int $page
*
* @return LengthAwarePaginator
*/
public function getJournalsOfTypes(array $types, $offset, $page);
/**
* @param $type
*
* @return TransactionType
*/
public function getTransactionType($type);
/**
* @param $id
* @param Carbon $date
*
* @return TransactionJournal
*/
public function getWithDate($id, Carbon $date);
/**
* @param TransactionJournal $journal
* @param array $array
*
* @return void
/**
*
* @param TransactionJournal $journal
* @param array $array
*
* @return void
*/
public function saveTags(TransactionJournal $journal, array $array);
/**
* @param array $data
@@ -47,8 +107,10 @@ interface JournalRepositoryInterface
public function update(TransactionJournal $journal, array $data);
/**
* Get users first transaction journal
* @return TransactionJournal
* @param TransactionJournal $journal
* @param array $array
*
* @return mixed
*/
public function first();
public function updateTags(TransactionJournal $journal, array $array);
}

View File

@@ -3,8 +3,10 @@
namespace FireflyIII\Repositories\PiggyBank;
use Auth;
use Carbon\Carbon;
use DB;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\PiggyBankRepetition;
use Illuminate\Support\Collection;
use Navigation;
@@ -17,8 +19,8 @@ use Navigation;
class PiggyBankRepository implements PiggyBankRepositoryInterface
{
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* Based on the piggy bank, the reminder-setting and
* other variables this method tries to divide the piggy bank into equal parts. Each is
@@ -68,6 +70,19 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
return $bars;
}
/**
* @param PiggyBank $piggyBank
* @param $amount
*
* @return bool
*/
public function createEvent(PiggyBank $piggyBank, $amount)
{
PiggyBankEvent::create(['date' => Carbon::now(), 'amount' => $amount, 'piggy_bank_id' => $piggyBank->id]);
return true;
}
/**
* @param array $data
*
@@ -86,6 +101,47 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
return $part;
}
/**
* @param PiggyBank $piggyBank
*
* @return bool
*/
public function destroy(PiggyBank $piggyBank)
{
return $piggyBank->delete();
}
/**
* @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`')]);
}
/**
* @param PiggyBank $piggyBank
*
* @return Collection
*/
public function getEvents(PiggyBank $piggyBank)
{
return $piggyBank->piggyBankEvents()->orderBy('date', 'DESC')->orderBy('id', 'DESC')->get();
}
/**
* @return Collection
*/
public function getPiggyBanks()
{
/** @var Collection $set */
$set = Auth::user()->piggyBanks()->orderBy('order', 'ASC')->get();
return $set;
}
/**
* Set all piggy banks to order 0.
*
@@ -132,10 +188,11 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
}
/**
* @param PiggyBank $account
* @param PiggyBank $piggyBank
* @param array $data
*
* @return PiggyBank
* @internal param PiggyBank $account
*/
public function update(PiggyBank $piggyBank, array $data)
{

View File

@@ -14,9 +14,7 @@ use Illuminate\Support\Collection;
interface PiggyBankRepositoryInterface
{
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
*
* Based on the piggy bank, the reminder-setting and
* other variables this method tries to divide the piggy bank into equal parts. Each is
@@ -28,6 +26,18 @@ interface PiggyBankRepositoryInterface
*/
public function calculateParts(PiggyBankRepetition $repetition);
/**
* @return Collection
*/
public function getPiggyBanks();
/**
* @param PiggyBank $piggyBank
*
* @return Collection
*/
public function getEvents(PiggyBank $piggyBank);
/**
* @param array $data
*
@@ -35,6 +45,28 @@ interface PiggyBankRepositoryInterface
*/
public function createPiggyBankPart(array $data);
/**
* @param PiggyBank $piggyBank
* @param $amount
*
* @return bool
*/
public function createEvent(PiggyBank $piggyBank, $amount);
/**
* @param PiggyBank $piggyBank
*
* @return Collection
*/
public function getEventSummarySet(PiggyBank $piggyBank);
/**
* @param PiggyBank $piggyBank
*
* @return bool
*/
public function destroy(PiggyBank $piggyBank);
/**
* Set all piggy banks to order 0.
*
@@ -62,7 +94,7 @@ interface PiggyBankRepositoryInterface
public function store(array $data);
/**
* @param PiggyBank $account
* @param PiggyBank $piggyBank
* @param array $data
*
* @return PiggyBank

View File

@@ -0,0 +1,116 @@
<?php
namespace FireflyIII\Repositories\Reminder;
use App;
use Auth;
use Carbon\Carbon;
use FireflyIII\Models\Reminder;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
/**
* Class ReminderRepository
*
* @package FireflyIII\Repositories\Reminder
*/
class ReminderRepository implements ReminderRepositoryInterface
{
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface */
protected $helper;
/**
*
*/
public function __construct()
{
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface helper */
$this->helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface');
}
/**
* @return Collection
*/
public function getActiveReminders()
{
$today = new Carbon;
// active reminders:
$active = Auth::user()->reminders()
->where('notnow', 0)
->where('active', 1)
->where('startdate', '<=', $today->format('Y-m-d 00:00:00'))
->where('enddate', '>=', $today->format('Y-m-d 00:00:00'))
->get();
$active->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $active;
}
/**
* @return Collection
*/
public function getDismissedReminders()
{
$dismissed = Auth::user()->reminders()
->where('notnow', 1)
->get();
$dismissed->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $dismissed;
}
/**
* @return Collection
*/
public function getExpiredReminders()
{
$expired = Auth::user()->reminders()
->where('notnow', 0)
->where('active', 1)
->where(
function (Builder $q) {
$today = new Carbon;
$q->where('startdate', '>', $today->format('Y-m-d 00:00:00'));
$q->orWhere('enddate', '<', $today->format('Y-m-d 00:00:00'));
}
)->get();
$expired->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $expired;
}
/**
* @return Collection
*/
public function getInactiveReminders()
{
$inactive = Auth::user()->reminders()
->where('active', 0)
->get();
$inactive->each(
function (Reminder $reminder) {
$reminder->description = $this->helper->getReminderText($reminder);
}
);
return $inactive;
}
}

View File

@@ -0,0 +1,35 @@
<?php
namespace FireflyIII\Repositories\Reminder;
use Illuminate\Support\Collection;
/**
* Interface ReminderRepositoryInterface
*
* @package FireflyIII\Repositories\Reminder
*/
interface ReminderRepositoryInterface
{
/**
* @return Collection
*/
public function getActiveReminders();
/**
* @return Collection
*/
public function getDismissedReminders();
/**
* @return Collection
*/
public function getExpiredReminders();
/**
* @return Collection
*/
public function getInactiveReminders();
}

View File

@@ -0,0 +1,180 @@
<?php
namespace FireflyIII\Repositories\Tag;
use Auth;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use Illuminate\Support\Collection;
/**
* Class TagRepository
*
* @package FireflyIII\Repositories\Tag
*/
class TagRepository implements TagRepositoryInterface
{
/**
* @param TransactionJournal $journal
* @param Tag $tag
*
* @return boolean
*/
public function connect(TransactionJournal $journal, Tag $tag)
{
/*
* Already connected:
*/
if ($journal->tags()->find($tag->id)) {
return false;
}
if ($tag->tagMode == 'nothing') {
// save it, no problem:
$journal->tags()->save($tag);
return true;
}
/*
* get some withdrawal types:
*/
/** @var TransactionType $withdrawal */
$withdrawal = TransactionType::whereType('Withdrawal')->first();
/** @var TransactionType $deposit */
$deposit = TransactionType::whereType('Deposit')->first();
/** @var TransactionType $transfer */
$transfer = TransactionType::whereType('Transfer')->first();
$withdrawals = $tag->transactionjournals()->where('transaction_type_id', $withdrawal->id)->count();
$transfers = $tag->transactionjournals()->where('transaction_type_id', $transfer->id)->count();
if ($tag->tagMode == 'balancingAct') {
// only if this is the only withdrawal.
if ($journal->transaction_type_id == $withdrawal->id && $withdrawals < 1) {
$journal->tags()->save($tag);
return true;
}
// and only if this is the only transfer
if ($journal->transaction_type_id == $transfer->id && $transfers < 1) {
$journal->tags()->save($tag);
return true;
}
// ignore expense
return false;
}
if ($tag->tagMode == 'advancePayment') {
// only if this is the only withdrawal
if ($journal->transaction_type_id == $withdrawal->id && $withdrawals < 1) {
$journal->tags()->save($tag);
return true;
}
// only if this is a deposit.
if ($journal->transaction_type_id == $deposit->id) {
// if this is a deposit, account must match the current only journal
// (if already present):
$currentWithdrawal = $tag->transactionjournals()->where('transaction_type_id', $withdrawal->id)->first();
if ($currentWithdrawal && $currentWithdrawal->assetAccount->id == $journal->assetAccount->id) {
$journal->tags()->save($tag);
return true;
} else {
if (is_null($currentWithdrawal)) {
$journal->tags()->save($tag);
return true;
}
}
}
return false;
}
return false;
}
/**
* @param Tag $tag
*
* @return boolean
*/
public function destroy(Tag $tag)
{
$tag->delete();
return true;
}
/**
* @return Collection
*/
public function get()
{
/** @var Collection $tags */
$tags = Auth::user()->tags()->get();
$tags->sortBy(
function (Tag $tag) {
return $tag->tag;
}
);
return $tags;
}
/**
* @param array $data
*
* @return Tag
*/
public function store(array $data)
{
$tag = new Tag;
$tag->tag = $data['tag'];
$tag->date = $data['date'];
$tag->description = $data['description'];
$tag->latitude = $data['latitude'];
$tag->longitude = $data['longitude'];
$tag->zoomLevel = $data['zoomLevel'];
$tag->tagMode = $data['tagMode'];
$tag->user()->associate(Auth::user());
$tag->save();
return $tag;
}
/**
* @param Tag $tag
* @param array $data
*
* @return Tag
*/
public function update(Tag $tag, array $data)
{
$tag->tag = $data['tag'];
$tag->date = $data['date'];
$tag->description = $data['description'];
$tag->latitude = $data['latitude'];
$tag->longitude = $data['longitude'];
$tag->zoomLevel = $data['zoomLevel'];
$tag->tagMode = $data['tagMode'];
$tag->save();
return $tag;
}
}

View File

@@ -0,0 +1,52 @@
<?php
namespace FireflyIII\Repositories\Tag;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
/**
* Interface TagRepositoryInterface
*
* @package FireflyIII\Repositories\Tag
*/
interface TagRepositoryInterface
{
/**
* @param array $data
*
* @return Tag
*/
public function store(array $data);
/**
* @return Collection
*/
public function get();
/**
* @param Tag $tag
* @param array $data
*
* @return Tag
*/
public function update(Tag $tag, array $data);
/**
* @param Tag $tag
*
* @return boolean
*/
public function destroy(Tag $tag);
/**
* @param TransactionJournal $journal
* @param Tag $tag
*
* @return boolean
*/
public function connect(TransactionJournal $journal, Tag $tag);
}

View File

@@ -84,9 +84,11 @@ class Amount
}
/**
* @return string
*
* @param TransactionJournal $journal
* @param bool $coloured
*
* @return string
*/
public function formatJournal(TransactionJournal $journal, $coloured = true)
{
@@ -151,23 +153,25 @@ class Amount
if (defined('FFCURRENCYCODE')) {
return FFCURRENCYCODE;
}
if (Cache::has('FFCURRENCYCODE')) {
define('FFCURRENCYCODE', Cache::get('FFCURRENCYCODE'));
return FFCURRENCYCODE;
}
$currencyPreference = Prefs::get('currencyPreference', 'EUR');
$currency = TransactionCurrency::whereCode($currencyPreference->data)->first();
\Cache::forever('FFCURRENCYCODE', $currency->code);
$currency = TransactionCurrency::whereCode($currencyPreference->data)->first();
if ($currency) {
define('FFCURRENCYCODE', $currency->code);
Cache::forever('FFCURRENCYCODE', $currency->code);
define('FFCURRENCYCODE', $currency->code);
return $currency->code;
return $currency->code;
}
return 'EUR';
}
/**
* @return mixed|static
*/
public function getDefaultCurrency()
{
$currencyPreference = Prefs::get('currencyPreference', 'EUR');

View File

@@ -62,7 +62,10 @@ class ExpandedForm
'account_id' => 'Asset account',
'budget_id' => 'Budget',
'openingBalance' => 'Opening balance',
'tagMode' => 'Tag mode',
'tagPosition' => 'Tag location',
'virtualBalance' => 'Virtual balance',
'longitude_latitude' => 'Location',
'targetamount' => 'Target amount',
'accountRole' => 'Account role',
'openingBalanceDate' => 'Opening balance date',
@@ -194,24 +197,6 @@ 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
@@ -233,12 +218,30 @@ class ExpandedForm
}
/**
* @SuppressWarnings("CyclomaticComplexity") // It's exactly 5. So I don't mind.
* @param $name
* @param null $value
* @param array $options
*
* @return string
*/
public function location($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.location', compact('classes', 'name', 'label', 'value', 'options'))->render();
return $html;
}
/**
*
* Takes any collection and tries to make a sensible select list compatible array of it.
*
* @param Collection $set
* @param bool $addEmpty
* @param \Illuminate\Support\Collection $set
* @param bool $addEmpty
*
* @return mixed
*/
@@ -265,6 +268,46 @@ class ExpandedForm
return $selectList;
}
/**
* @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 array $list
* @param null $selected
* @param array $options
*
* @return string
* @internal param null $value
*/
public function multiRadio($name, array $list = [], $selected = null, array $options = [])
{
$label = $this->label($name, $options);
$options = $this->expandOptionArray($name, $label, $options);
$classes = $this->getHolderClasses($name);
$selected = $this->fillFieldValue($name, $selected);
unset($options['class']);
$html = View::make('form.multiRadio', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render();
return $html;
}
/**
* @param $type
* @param $name
@@ -336,4 +379,24 @@ class ExpandedForm
return $html;
}
/**
* @param $name
* @param null $value
* @param array $options
*
* @return string
*/
public function textarea($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['rows'] = 4;
$html = View::make('form.textarea', compact('classes', 'name', 'label', 'value', 'options'))->render();
return $html;
}
}

View File

@@ -15,7 +15,7 @@ class Navigation
/**
* @param Carbon $theDate
* @param \Carbon\Carbon $theDate
* @param $repeatFreq
* @param $skip
*
@@ -64,10 +64,10 @@ class Navigation
}
/**
* @param Carbon $theCurrentEnd
* @param \Carbon\Carbon $theCurrentEnd
* @param $repeatFreq
*
* @return Carbon
* @return \Carbon\Carbon
* @throws FireflyException
*/
public function endOfPeriod(Carbon $theCurrentEnd, $repeatFreq)
@@ -148,9 +148,8 @@ class Navigation
}
if (isset($specials[$repeatFreq])) {
$month = intval($theCurrentEnd->format('m'));
$currentEnd->endOfYear();
if ($month <= 6) {
if ($theCurrentEnd->month <= 6) {
$currentEnd->subMonths(6);
}
}
@@ -184,7 +183,7 @@ class Navigation
$date->lastOfQuarter()->addDay();
break;
case '6M':
if (intval($date->format('m')) >= 7) {
if ($date->month >= 7) {
$date->startOfYear()->addYear();
} else {
$date->startOfYear()->addMonths(6);
@@ -230,9 +229,8 @@ class Navigation
return $date;
}
if ($range == '6M') {
$month = intval($date->format('m'));
$date->startOfYear();
if ($month <= 6) {
if ($date->month <= 6) {
$date->subMonths(6);
}
@@ -260,16 +258,15 @@ class Navigation
return $date->format($formatMap[$range]);
}
if ($range == '3M') {
$month = intval($date->format('m'));
return 'Q' . ceil(($month / 12) * 4) . ' ' . $date->format('Y');
return 'Q' . ceil(($date->month / 12) * 4) . ' ' . $date->year;
}
if ($range == '6M') {
$month = intval($date->format('m'));
$half = ceil(($month / 12) * 2);
$half = ceil(($date->month / 12) * 2);
$halfName = $half == 1 ? 'first' : 'second';
return $halfName . ' half of ' . $date->format('Y');
return $halfName . ' half of ' . $date->year;
}
throw new FireflyException('No _periodName() for range "' . $range . '"');
}
@@ -301,10 +298,10 @@ class Navigation
}
/**
* @param Carbon $theDate
* @param \Carbon\Carbon $theDate
* @param $repeatFreq
*
* @return Carbon
* @return \Carbon\Carbon
* @throws FireflyException
*/
public function startOfPeriod(Carbon $theDate, $repeatFreq)
@@ -333,7 +330,7 @@ class Navigation
return $date;
}
if ($repeatFreq == 'half-year' || $repeatFreq == '6M') {
$month = intval($date->format('m'));
$month = $date->month;
$date->startOfYear();
if ($month >= 7) {
$date->addMonths(6);
@@ -388,9 +385,9 @@ class Navigation
/**
* @param $range
* @param Carbon $start
* @param \Carbon\Carbon $start
*
* @return Carbon
* @return \Carbon\Carbon
* @throws FireflyException
*/
public function updateEndDate($range, Carbon $start)
@@ -411,7 +408,7 @@ class Navigation
return $end;
}
if ($range == '6M') {
if (intval($start->format('m')) >= 7) {
if ($start->month >= 7) {
$end->endOfYear();
} else {
$end->startOfYear()->addMonths(6);
@@ -423,10 +420,10 @@ class Navigation
}
/**
* @param $range
* @param Carbon $start
* @param $range
* @param \Carbon\Carbon $start
*
* @return Carbon
* @return \Carbon\Carbon
* @throws FireflyException
*/
public function updateStartDate($range, Carbon $start)
@@ -445,7 +442,7 @@ class Navigation
return $start;
}
if ($range == '6M') {
if (intval($start->format('m')) >= 7) {
if ($start->month >= 7) {
$start->startOfYear()->addMonths(6);
} else {
$start->startOfYear();

View File

@@ -16,7 +16,7 @@ class Preferences
* @param $name
* @param null $default
*
* @return null|Preference
* @return null|\FireflyIII\Models\Preference
*/
public function get($name, $default = null)
{

View File

@@ -84,7 +84,6 @@ class Search implements SearchInterface
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @param array $words
*
@@ -122,6 +121,7 @@ class Search implements SearchInterface
return $journal;
}
}
return null;
}
);

View File

@@ -17,8 +17,8 @@ class Steam
{
/**
*
* @param Account $account
* @param Carbon $date
* @param \FireflyIII\Models\Account $account
* @param \Carbon\Carbon $date
* @param bool $ignoreVirtualBalance
*
* @return float
@@ -67,8 +67,8 @@ class Steam
public function limitArray(array $array, $limit = 10)
{
$others = [
'name' => 'Others',
'amount' => 0
'name' => 'Others',
'queryAmount' => 0
];
$return = [];
$count = 0;
@@ -76,7 +76,7 @@ class Steam
if ($count < ($limit - 1)) {
$return[$id] = $entry;
} else {
$others['amount'] += $entry['amount'];
$others['queryAmount'] += $entry['queryAmount'];
}
$count++;
@@ -91,7 +91,7 @@ class Steam
* Turns a collection into an array. Needs the field 'id' for the key,
* and saves only 'name' and 'amount' as a sub array.
*
* @param Collection $collection
* @param \Illuminate\Support\Collection $collection
*
* @return array
*/
@@ -103,14 +103,16 @@ class Steam
$id = intval($entry->id);
if (isset($array[$id])) {
$array[$id]['amount'] += floatval($entry->amount);
$array[$id]['queryAmount'] += floatval($entry->queryAmount);
$array[$id]['spent'] += floatval($entry->spent);
$array[$id]['encrypted'] = intval($entry->encrypted);
} else {
$array[$id] = [
'amount' => floatval($entry->amount),
'spent' => floatval($entry->spent),
'encrypted' => intval($entry->encrypted),
'name' => $entry->name
'amount' => floatval($entry->amount),
'queryAmount' => floatval($entry->queryAmount),
'spent' => floatval($entry->spent),
'encrypted' => intval($entry->encrypted),
'name' => $entry->name
];
}
}
@@ -131,7 +133,7 @@ class Steam
foreach ($two as $id => $value) {
// $otherId also exists in $one:
if (isset($one[$id])) {
$one[$id]['amount'] += $value['amount'];
$one[$id]['queryAmount'] += $value['queryAmount'];
$one[$id]['spent'] += $value['spent'];
} else {
$one[$id] = $value;
@@ -170,11 +172,11 @@ class Steam
{
uasort(
$array, function ($left, $right) {
if ($left['amount'] == $right['amount']) {
if ($left['queryAmount'] == $right['queryAmount']) {
return 0;
}
return ($left['amount'] < $right['amount']) ? 1 : -1;
return ($left['queryAmount'] < $right['queryAmount']) ? 1 : -1;
}
);
@@ -193,11 +195,11 @@ class Steam
{
uasort(
$array, function ($left, $right) {
if ($left['amount'] == $right['amount']) {
if ($left['queryAmount'] == $right['queryAmount']) {
return 0;
}
return ($left['amount'] < $right['amount']) ? -1 : 1;
return ($left['queryAmount'] < $right['queryAmount']) ? -1 : 1;
}
);

View File

@@ -0,0 +1,53 @@
<?php
namespace FireflyIII\Support\Twig;
use Auth;
use DB;
use FireflyIII\Models\LimitRepetition;
use Twig_Extension;
use Twig_SimpleFunction;
/**
* Class Budget
*
* @package FireflyIII\Support\Twig
*/
class Budget extends Twig_Extension
{
/**
* {@inheritDoc}
*/
public function getFunctions()
{
$functions[] = new Twig_SimpleFunction(
'spentInRepetition', function (LimitRepetition $repetition) {
$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', '>=', $repetition->startdate->format('Y-m-d'))
->where('transaction_journals.date', '<=', $repetition->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', '=', $repetition->id)
->sum('transactions.amount');
return floatval($sum);
}
);
return $functions;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'FireflyIII\Support\Twig\Budget';
}
}

View File

@@ -0,0 +1,146 @@
<?php
namespace FireflyIII\Support\Twig;
use App;
use Config;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use Route;
use Twig_Extension;
use Twig_SimpleFilter;
use Twig_SimpleFunction;
/**
* Class TwigSupport
*
* @package FireflyIII\Support
*/
class General extends Twig_Extension
{
/**
* @return array
*/
public function getFilters()
{
$filters = [];
$filters[] = new Twig_SimpleFilter(
'formatAmount', function ($string) {
return App::make('amount')->format($string);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'formatTransaction', function (Transaction $transaction) {
return App::make('amount')->formatTransaction($transaction);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'formatAmountPlain', function ($string) {
return App::make('amount')->format($string, false);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'formatJournal', function ($journal) {
return App::make('amount')->formatJournal($journal);
}, ['is_safe' => ['html']]
);
$filters[] = new Twig_SimpleFilter(
'balance', function (Account $account = null) {
if (is_null($account)) {
return 'NULL';
}
return App::make('steam')->balance($account);
}
);
// should be a function but OK
$filters[] = new Twig_SimpleFilter(
'getAccountRole', function ($name) {
return Config::get('firefly.accountRoles.' . $name);
}
);
return $filters;
}
/**
* {@inheritDoc}
*/
public function getFunctions()
{
$functions = [];
$functions[] = new Twig_SimpleFunction(
'getCurrencyCode', function () {
return App::make('amount')->getCurrencyCode();
}
);
$functions[] = new Twig_SimpleFunction(
'getCurrencySymbol', function () {
return App::make('amount')->getCurrencySymbol();
}
);
$functions[] = new Twig_SimpleFunction(
'phpdate', function ($str) {
return date($str);
}
);
$functions[] = new Twig_SimpleFunction(
'env', function ($name, $default) {
return env($name, $default);
}
);
$functions[] = new Twig_SimpleFunction(
'activeRoute', function ($context) {
$args = func_get_args();
$route = $args[1];
$what = isset($args[2]) ? $args[2] : false;
$strict = isset($args[3]) ? $args[3] : false;
$activeWhat = isset($context['what']) ? $context['what'] : false;
// activeRoute
if (!($what === false)) {
if ($what == $activeWhat && Route::getCurrentRoute()->getName() == $route) {
return 'active because-active-what';
}
} else {
if (!$strict && !(strpos(Route::getCurrentRoute()->getName(), $route) === false)) {
return 'active because-route-matches-non-strict';
} else {
if ($strict && Route::getCurrentRoute()->getName() == $route) {
return 'active because-route-matches-strict';
}
}
}
return 'not-xxx-at-all';
}, ['needs_context' => true]
);
return $functions;
}
/**
* {@inheritDoc}
*/
public function getName()
{
return 'FireflyIII\Support\Twig\General';
}
}

View File

@@ -0,0 +1,99 @@
<?php
namespace FireflyIII\Support\Twig;
use App;
use FireflyIII\Models\TransactionJournal;
use Twig_Extension;
use Twig_SimpleFilter;
use Twig_SimpleFunction;
/**
* Class Journal
*
* @package FireflyIII\Support\Twig
*/
class Journal extends Twig_Extension
{
/**
* @return array
*/
public function getFilters()
{
$filters = [];
$filters[] = new Twig_SimpleFilter(
'typeIcon', function (TransactionJournal $journal) {
$type = $journal->transactionType->type;
if ($type == 'Withdrawal') {
return '<span class="glyphicon glyphicon-arrow-left" title="Withdrawal"></span>';
}
if ($type == 'Deposit') {
return '<span class="glyphicon glyphicon-arrow-right" title="Deposit"></span>';
}
if ($type == 'Transfer') {
return '<i class="fa fa-fw fa-exchange" title="Transfer"></i>';
}
if ($type == 'Opening balance') {
return '<span class="glyphicon glyphicon-ban-circle" title="Opening balance"></span>';
}
return '';
}, ['is_safe' => ['html']]
);
return $filters;
}
/**
* @return array
*/
public function getFunctions()
{
$functions = [];
$functions[] = new Twig_SimpleFunction(
'invalidJournal', function (TransactionJournal $journal) {
if (!isset($journal->transactions[1]) || !isset($journal->transactions[0])) {
return true;
}
return false;
}
);
$functions[] = new Twig_SimpleFunction(
'relevantTags', function (TransactionJournal $journal) {
if ($journal->tags->count() == 0) {
return App::make('amount')->formatJournal($journal);
}
foreach ($journal->tags as $tag) {
if ($tag->tagMode == 'balancingAct') {
// return tag formatted for a "balancing act".
$amount = App::make('amount')->formatJournal($journal, false);
return '<a href="' . route('tags.show', $tag->id) . '" class="label label-success" title="' . $amount
. '"><i class="fa fa-fw fa-refresh"></i> ' . $tag->tag . '</span>';
}
}
return 'TODO: ' . $journal->amount;
}
);
return $functions;
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'FireflyIII\Support\Twig\Journals';
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace FireflyIII\Support\Twig;
use FireflyIII\Models\PiggyBank as PB;
use Twig_Extension;
use Twig_SimpleFunction;
/**
* Class PiggyBank
*
* @package FireflyIII\Support\Twig
*/
class PiggyBank extends Twig_Extension
{
/**
*
*/
public function getFunctions()
{
$functions = [];
$functions[] = new Twig_SimpleFunction(
'currentRelevantRepAmount', function (PB $piggyBank) {
return $piggyBank->currentRelevantRep()->currentamount;
}
);
return $functions;
}
/**
* Returns the name of the extension.
*
* @return string The extension name
*/
public function getName()
{
return 'FireflyIII\Support\Twig\PiggyBank';
}
}

View File

@@ -43,6 +43,14 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return $this->hasMany('FireflyIII\Models\Account');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function tags()
{
return $this->hasMany('FireflyIII\Models\Tag');
}
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/

View File

@@ -13,6 +13,7 @@ use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Validation\Validator;
use Log;
use Navigation;
use Symfony\Component\Translation\TranslatorInterface;
/**
* Class FireflyValidator
@@ -22,6 +23,18 @@ use Navigation;
class FireflyValidator extends Validator
{
/**
* @param TranslatorInterface $translator
* @param array $data
* @param array $rules
* @param array $messages
* @param array $customAttributes
*/
public function __construct(TranslatorInterface $translator, array $data, array $rules, array $messages = [], array $customAttributes = [])
{
parent::__construct($translator, $data, $rules, $messages);
}
/**
* @param $attribute
* @param $value
@@ -181,12 +194,22 @@ class FireflyValidator extends Validator
*/
public function validateUniqueObjectForUser($attribute, $value, $parameters)
{
$table = $parameters[0];
$field = $parameters[1];
$encrypted = isset($parameters[2]) ? $parameters[2] : 'encrypted';
$exclude = isset($parameters[3]) ? $parameters[3] : null;
$table = $parameters[0];
$field = $parameters[1];
$encrypted = isset($parameters[2]) ? $parameters[2] : 'encrypted';
$exclude = isset($parameters[3]) ? $parameters[3] : null;
$alwaysEncrypted = false;
if ($encrypted == 'TRUE') {
$alwaysEncrypted = true;
}
if (is_null(Auth::user())) {
// user is not logged in.. weird.
return true;
} else {
$query = DB::table($table)->where('user_id', Auth::user()->id);
}
$query = DB::table($table)->where('user_id', Auth::user()->id);
if (!is_null($exclude)) {
$query->where('id', '!=', $exclude);
@@ -195,8 +218,12 @@ class FireflyValidator extends Validator
$set = $query->get();
foreach ($set as $entry) {
$isEncrypted = intval($entry->$encrypted) == 1 ? true : false;
$checkValue = $isEncrypted ? Crypt::decrypt($entry->$field) : $entry->$field;
if (!$alwaysEncrypted) {
$isEncrypted = intval($entry->$encrypted) == 1 ? true : false;
} else {
$isEncrypted = true;
}
$checkValue = $isEncrypted ? Crypt::decrypt($entry->$field) : $entry->$field;
if ($checkValue == $value) {
return false;
}
@@ -223,10 +250,10 @@ class FireflyValidator extends Validator
}
$set = $query->get(['piggy_banks.*']);
foreach($set as $entry) {
foreach ($set as $entry) {
$isEncrypted = intval($entry->encrypted) == 1 ? true : false;
$checkValue = $isEncrypted ? Crypt::decrypt($entry->name) : $entry->name;
if($checkValue == $value) {
$checkValue = $isEncrypted ? Crypt::decrypt($entry->name) : $entry->name;
if ($checkValue == $value) {
return false;
}
}

View File

@@ -11,6 +11,7 @@
|
*/
$app = new Illuminate\Foundation\Application(
realpath(__DIR__ . '/../')
);
@@ -26,6 +27,8 @@ $app = new Illuminate\Foundation\Application(
|
*/
$app->singleton(
'Illuminate\Contracts\Http\Kernel',
'FireflyIII\Http\Kernel'
@@ -41,6 +44,9 @@ $app->singleton(
'FireflyIII\Exceptions\Handler'
);
/*
|--------------------------------------------------------------------------
| Return The Application

View File

@@ -26,7 +26,9 @@
"watson/validating": "~1.0",
"doctrine/dbal": "~2.5",
"illuminate/html": "~5.0",
"league/commonmark": "0.7.*"
"league/commonmark": "0.7.*",
"rcrowe/twigbridge": "0.7.x@dev",
"twig/extensions": "~1.2"
},
"require-dev": {
"barryvdh/laravel-debugbar": "@stable",

412
composer.lock generated
View File

@@ -4,24 +4,24 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "0d43c4c85607c5cdc901cde2d18b75d5",
"hash": "e3e90dd365b74f4878cf3b5b4a1c4007",
"packages": [
{
"name": "classpreloader/classpreloader",
"version": "1.2.0",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/ClassPreloader/ClassPreloader.git",
"reference": "f0bfbf71fb3335c9473f695d4d966ba2fb879a9f"
"reference": "0544616ba33fb2a6b792b3a7822650810c6d65d9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/f0bfbf71fb3335c9473f695d4d966ba2fb879a9f",
"reference": "f0bfbf71fb3335c9473f695d4d966ba2fb879a9f",
"url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/0544616ba33fb2a6b792b3a7822650810c6d65d9",
"reference": "0544616ba33fb2a6b792b3a7822650810c6d65d9",
"shasum": ""
},
"require": {
"nikic/php-parser": "~1.0",
"nikic/php-parser": "^1.2.2",
"php": ">=5.3.3",
"symfony/console": "~2.1",
"symfony/filesystem": "~2.1",
@@ -36,7 +36,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
"dev-master": "1.3-dev"
}
},
"autoload": {
@@ -64,7 +64,7 @@
"class",
"preload"
],
"time": "2015-01-26 22:06:19"
"time": "2015-04-15 21:59:30"
},
{
"name": "danielstjules/stringy",
@@ -206,16 +206,16 @@
},
{
"name": "doctrine/annotations",
"version": "v1.2.3",
"version": "v1.2.4",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
"reference": "eeda578cbe24a170331a1cfdf78be723412df7a4"
"reference": "b5202eb9e83f8db52e0e58867e0a46e63be8332e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/eeda578cbe24a170331a1cfdf78be723412df7a4",
"reference": "eeda578cbe24a170331a1cfdf78be723412df7a4",
"url": "https://api.github.com/repos/doctrine/annotations/zipball/b5202eb9e83f8db52e0e58867e0a46e63be8332e",
"reference": "b5202eb9e83f8db52e0e58867e0a46e63be8332e",
"shasum": ""
},
"require": {
@@ -270,20 +270,20 @@
"docblock",
"parser"
],
"time": "2014-12-20 20:49:38"
"time": "2014-12-23 22:40:37"
},
{
"name": "doctrine/cache",
"version": "v1.4.0",
"version": "v1.4.1",
"source": {
"type": "git",
"url": "https://github.com/doctrine/cache.git",
"reference": "2346085d2b027b233ae1d5de59b07440b9f288c8"
"reference": "c9eadeb743ac6199f7eec423cb9426bc518b7b03"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/2346085d2b027b233ae1d5de59b07440b9f288c8",
"reference": "2346085d2b027b233ae1d5de59b07440b9f288c8",
"url": "https://api.github.com/repos/doctrine/cache/zipball/c9eadeb743ac6199f7eec423cb9426bc518b7b03",
"reference": "c9eadeb743ac6199f7eec423cb9426bc518b7b03",
"shasum": ""
},
"require": {
@@ -294,13 +294,13 @@
},
"require-dev": {
"phpunit/phpunit": ">=3.7",
"predis/predis": "~0.8",
"predis/predis": "~1.0",
"satooshi/php-coveralls": "~0.6"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
"dev-master": "1.5.x-dev"
}
},
"autoload": {
@@ -340,25 +340,28 @@
"cache",
"caching"
],
"time": "2015-01-15 20:38:55"
"time": "2015-04-15 00:11:59"
},
{
"name": "doctrine/collections",
"version": "v1.2",
"version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/collections.git",
"reference": "b99c5c46c87126201899afe88ec490a25eedd6a2"
"reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/collections/zipball/b99c5c46c87126201899afe88ec490a25eedd6a2",
"reference": "b99c5c46c87126201899afe88ec490a25eedd6a2",
"url": "https://api.github.com/repos/doctrine/collections/zipball/6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
"reference": "6c1e4eef75f310ea1b3e30945e9f06e652128b8a",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
@@ -375,17 +378,6 @@
"MIT"
],
"authors": [
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com",
"homepage": "http://www.jwage.com/",
"role": "Creator"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com",
"homepage": "http://www.instaclick.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
@@ -394,11 +386,17 @@
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com",
"homepage": "https://github.com/schmittjoh",
"role": "Developer of wrapped JMSSerializerBundle"
"email": "schmittjoh@gmail.com"
}
],
"description": "Collections Abstraction library",
@@ -408,7 +406,7 @@
"collections",
"iterator"
],
"time": "2014-02-03 23:07:43"
"time": "2015-04-14 22:21:58"
},
{
"name": "doctrine/common",
@@ -677,16 +675,16 @@
},
{
"name": "grumpydictator/gchart",
"version": "1.0.8",
"version": "1.0.9",
"source": {
"type": "git",
"url": "https://github.com/JC5/gchart.git",
"reference": "24d06101cfda7ff336ecb10f7f0cb0d6004cb83c"
"reference": "920a0494a0697472bf81c0111b6825c516099e59"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/JC5/gchart/zipball/24d06101cfda7ff336ecb10f7f0cb0d6004cb83c",
"reference": "24d06101cfda7ff336ecb10f7f0cb0d6004cb83c",
"url": "https://api.github.com/repos/JC5/gchart/zipball/920a0494a0697472bf81c0111b6825c516099e59",
"reference": "920a0494a0697472bf81c0111b6825c516099e59",
"shasum": ""
},
"require": {
@@ -709,7 +707,7 @@
}
],
"description": "GChart is a small package that allows you to easily generate data for the Google Charts API.",
"time": "2015-02-20 20:07:26"
"time": "2015-04-05 19:17:17"
},
{
"name": "illuminate/html",
@@ -945,16 +943,16 @@
},
{
"name": "laravel/framework",
"version": "v5.0.26",
"version": "v5.0.28",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "8e53c33e144f94032cc6ecbfee0be2a96ed63be0"
"reference": "06a09429322cf53e5bd4587db1060f02a291562e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/8e53c33e144f94032cc6ecbfee0be2a96ed63be0",
"reference": "8e53c33e144f94032cc6ecbfee0be2a96ed63be0",
"url": "https://api.github.com/repos/laravel/framework/zipball/06a09429322cf53e5bd4587db1060f02a291562e",
"reference": "06a09429322cf53e5bd4587db1060f02a291562e",
"shasum": ""
},
"require": {
@@ -1024,7 +1022,7 @@
"predis/predis": "~1.0"
},
"suggest": {
"aws/aws-sdk-php": "Required to use the SQS queue driver (~2.4).",
"aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~2.4).",
"doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).",
"guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers (~5.0).",
"iron-io/iron_mq": "Required to use the iron queue driver (~1.5).",
@@ -1067,7 +1065,7 @@
"framework",
"laravel"
],
"time": "2015-04-03 02:58:05"
"time": "2015-04-21 01:44:32"
},
{
"name": "league/commonmark",
@@ -1377,16 +1375,16 @@
},
{
"name": "nikic/php-parser",
"version": "v1.2.1",
"version": "v1.3.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "dba7524b3724f25b947cd26a580787c55c8a6f9b"
"reference": "dff239267fd1befa1cd40430c9ed12591aa720ca"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dba7524b3724f25b947cd26a580787c55c8a6f9b",
"reference": "dba7524b3724f25b947cd26a580787c55c8a6f9b",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dff239267fd1befa1cd40430c9ed12591aa720ca",
"reference": "dff239267fd1befa1cd40430c9ed12591aa720ca",
"shasum": ""
},
"require": {
@@ -1396,7 +1394,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
"dev-master": "1.3-dev"
}
},
"autoload": {
@@ -1418,7 +1416,7 @@
"parser",
"php"
],
"time": "2015-03-24 19:10:28"
"time": "2015-05-02 15:40:40"
},
{
"name": "psr/log",
@@ -1529,6 +1527,70 @@
],
"time": "2015-03-26 18:43:54"
},
{
"name": "rcrowe/twigbridge",
"version": "0.7.x-dev",
"source": {
"type": "git",
"url": "https://github.com/rcrowe/TwigBridge.git",
"reference": "ac0bfb5bcdb4fcd0cd01ab8425620ff07f6af026"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/rcrowe/TwigBridge/zipball/ac0bfb5bcdb4fcd0cd01ab8425620ff07f6af026",
"reference": "ac0bfb5bcdb4fcd0cd01ab8425620ff07f6af026",
"shasum": ""
},
"require": {
"illuminate/support": "5.0.*",
"illuminate/view": "5.0.*",
"php": ">=5.4.0",
"twig/twig": "~1.15"
},
"require-dev": {
"laravel/framework": "5.0.*",
"mockery/mockery": "0.9.*",
"phpunit/phpunit": "~4.0",
"satooshi/php-coveralls": "~0.6",
"squizlabs/php_codesniffer": "~1.5"
},
"suggest": {
"laravelcollective/html": "For bringing back html/form in Laravel 5.x",
"twig/extensions": "~1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "0.7-dev"
}
},
"autoload": {
"psr-4": {
"TwigBridge\\": "src",
"TwigBridge\\Tests\\": "tests"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
},
{
"name": "Rob Crowe",
"email": "hello@vivalacrowe.com"
}
],
"description": "Adds the power of Twig to Laravel",
"keywords": [
"laravel",
"twig"
],
"time": "2015-04-22 09:19:03"
},
{
"name": "swiftmailer/swiftmailer",
"version": "v5.4.0",
@@ -2293,6 +2355,115 @@
],
"time": "2015-03-31 08:12:29"
},
{
"name": "twig/extensions",
"version": "v1.2.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig-extensions.git",
"reference": "8cf4b9fe04077bd54fc73f4fde83347040c3b8cd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig-extensions/zipball/8cf4b9fe04077bd54fc73f4fde83347040c3b8cd",
"reference": "8cf4b9fe04077bd54fc73f4fde83347040c3b8cd",
"shasum": ""
},
"require": {
"twig/twig": "~1.12"
},
"require-dev": {
"symfony/translation": "~2.3"
},
"suggest": {
"symfony/translation": "Allow the time_diff output to be translated"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
}
},
"autoload": {
"psr-0": {
"Twig_Extensions_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
}
],
"description": "Common additional features for Twig that do not directly belong in core",
"homepage": "http://twig.sensiolabs.org/doc/extensions/index.html",
"keywords": [
"i18n",
"text"
],
"time": "2014-10-30 14:30:03"
},
{
"name": "twig/twig",
"version": "v1.18.1",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
"reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/9f70492f44398e276d1b81c1b43adfe6751c7b7f",
"reference": "9f70492f44398e276d1b81c1b43adfe6751c7b7f",
"shasum": ""
},
"require": {
"php": ">=5.2.7"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.18-dev"
}
},
"autoload": {
"psr-0": {
"Twig_": "lib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com",
"homepage": "http://fabien.potencier.org",
"role": "Lead Developer"
},
{
"name": "Armin Ronacher",
"email": "armin.ronacher@active-4.com",
"role": "Project Founder"
},
{
"name": "Twig Team",
"homepage": "http://twig.sensiolabs.org/contributors",
"role": "Contributors"
}
],
"description": "Twig, the flexible, fast, and secure template language for PHP",
"homepage": "http://twig.sensiolabs.org",
"keywords": [
"templating"
],
"time": "2015-04-19 08:30:27"
},
{
"name": "vlucas/phpdotenv",
"version": "v1.1.0",
@@ -3027,23 +3198,23 @@
},
{
"name": "phpspec/phpspec",
"version": "2.1.1",
"version": "2.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpspec/phpspec.git",
"reference": "66a1df93099282b1514e9e001fcf6e9393f7783d"
"reference": "9727d75919a00455433e867565bc022f0b985a39"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/phpspec/zipball/66a1df93099282b1514e9e001fcf6e9393f7783d",
"reference": "66a1df93099282b1514e9e001fcf6e9393f7783d",
"url": "https://api.github.com/repos/phpspec/phpspec/zipball/9727d75919a00455433e867565bc022f0b985a39",
"reference": "9727d75919a00455433e867565bc022f0b985a39",
"shasum": ""
},
"require": {
"doctrine/instantiator": "~1.0,>=1.0.1",
"doctrine/instantiator": "^1.0.1",
"php": ">=5.3.3",
"phpspec/php-diff": "~1.0.0",
"phpspec/prophecy": "~1.1",
"phpspec/prophecy": "~1.4",
"sebastian/exporter": "~1.0",
"symfony/console": "~2.3",
"symfony/event-dispatcher": "~2.1",
@@ -3052,9 +3223,11 @@
"symfony/yaml": "~2.1"
},
"require-dev": {
"behat/behat": "~3.0,>=3.0.11",
"behat/behat": "^3.0.11",
"bossa/phpspec2-expect": "~1.0",
"symfony/filesystem": "~2.1"
"phpunit/phpunit": "~4.4",
"symfony/filesystem": "~2.1",
"symfony/process": "~2.1"
},
"suggest": {
"phpspec/nyan-formatters": "~1.0 Adds Nyan formatters"
@@ -3065,7 +3238,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1.x-dev"
"dev-master": "2.2.x-dev"
}
},
"autoload": {
@@ -3099,20 +3272,20 @@
"testing",
"tests"
],
"time": "2015-01-09 13:21:45"
"time": "2015-04-18 16:22:51"
},
{
"name": "phpspec/prophecy",
"version": "1.4.0",
"version": "v1.4.1",
"source": {
"type": "git",
"url": "https://github.com/phpspec/prophecy.git",
"reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5"
"reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5",
"reference": "8724cd239f8ef4c046f55a3b18b4d91cc7f3e4c5",
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373",
"reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373",
"shasum": ""
},
"require": {
@@ -3159,20 +3332,20 @@
"spy",
"stub"
],
"time": "2015-03-27 19:31:25"
"time": "2015-04-27 22:15:08"
},
{
"name": "phpunit/php-code-coverage",
"version": "2.0.15",
"version": "2.0.16",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "34cc484af1ca149188d0d9e91412191e398e0b67"
"reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/34cc484af1ca149188d0d9e91412191e398e0b67",
"reference": "34cc484af1ca149188d0d9e91412191e398e0b67",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/934fd03eb6840508231a7f73eb8940cf32c3b66c",
"reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c",
"shasum": ""
},
"require": {
@@ -3221,35 +3394,37 @@
"testing",
"xunit"
],
"time": "2015-01-24 10:06:35"
"time": "2015-04-11 04:35:00"
},
{
"name": "phpunit/php-file-iterator",
"version": "1.3.4",
"version": "1.4.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
"reference": "acd690379117b042d1c8af1fafd61bde001bf6bb"
"reference": "a923bb15680d0089e2316f7a4af8f437046e96bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb",
"reference": "acd690379117b042d1c8af1fafd61bde001bf6bb",
"url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb",
"reference": "a923bb15680d0089e2316f7a4af8f437046e96bb",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4.x-dev"
}
},
"autoload": {
"classmap": [
"File/"
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"BSD-3-Clause"
],
@@ -3266,7 +3441,7 @@
"filesystem",
"iterator"
],
"time": "2013-10-10 15:34:57"
"time": "2015-04-02 05:19:05"
},
{
"name": "phpunit/php-text-template",
@@ -3358,16 +3533,16 @@
},
{
"name": "phpunit/php-token-stream",
"version": "1.4.0",
"version": "1.4.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
"reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74"
"reference": "eab81d02569310739373308137284e0158424330"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/db32c18eba00b121c145575fcbcd4d4d24e6db74",
"reference": "db32c18eba00b121c145575fcbcd4d4d24e6db74",
"url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330",
"reference": "eab81d02569310739373308137284e0158424330",
"shasum": ""
},
"require": {
@@ -3403,20 +3578,20 @@
"keywords": [
"tokenizer"
],
"time": "2015-01-17 09:51:32"
"time": "2015-04-08 04:46:07"
},
{
"name": "phpunit/phpunit",
"version": "4.5.1",
"version": "4.6.6",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4"
"reference": "3afe303d873a4d64c62ef84de491b97b006fbdac"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d6429b0995b24a2d9dfe5587ee3a7071c1161af4",
"reference": "d6429b0995b24a2d9dfe5587ee3a7071c1161af4",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3afe303d873a4d64c62ef84de491b97b006fbdac",
"reference": "3afe303d873a4d64c62ef84de491b97b006fbdac",
"shasum": ""
},
"require": {
@@ -3428,17 +3603,17 @@
"php": ">=5.3.3",
"phpspec/prophecy": "~1.3,>=1.3.1",
"phpunit/php-code-coverage": "~2.0,>=2.0.11",
"phpunit/php-file-iterator": "~1.3.2",
"phpunit/php-file-iterator": "~1.4",
"phpunit/php-text-template": "~1.2",
"phpunit/php-timer": "~1.0.2",
"phpunit/php-timer": "~1.0",
"phpunit/phpunit-mock-objects": "~2.3",
"sebastian/comparator": "~1.1",
"sebastian/diff": "~1.1",
"sebastian/diff": "~1.2",
"sebastian/environment": "~1.2",
"sebastian/exporter": "~1.2",
"sebastian/global-state": "~1.0",
"sebastian/version": "~1.0",
"symfony/yaml": "~2.0"
"symfony/yaml": "~2.1|~3.0"
},
"suggest": {
"phpunit/php-invoker": "~1.1"
@@ -3449,7 +3624,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "4.5.x-dev"
"dev-master": "4.6.x-dev"
}
},
"autoload": {
@@ -3475,7 +3650,7 @@
"testing",
"xunit"
],
"time": "2015-03-29 09:24:05"
"time": "2015-04-29 15:18:52"
},
{
"name": "phpunit/phpunit-mock-objects",
@@ -3666,16 +3841,16 @@
},
{
"name": "sebastian/diff",
"version": "1.2.0",
"version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
"reference": "5843509fed39dee4b356a306401e9dd1a931fec7"
"reference": "863df9687835c62aa423a22412d26fa2ebde3fd3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/5843509fed39dee4b356a306401e9dd1a931fec7",
"reference": "5843509fed39dee4b356a306401e9dd1a931fec7",
"url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3",
"reference": "863df9687835c62aa423a22412d26fa2ebde3fd3",
"shasum": ""
},
"require": {
@@ -3687,7 +3862,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2-dev"
"dev-master": "1.3-dev"
}
},
"autoload": {
@@ -3714,32 +3889,32 @@
"keywords": [
"diff"
],
"time": "2014-08-15 10:29:00"
"time": "2015-02-22 15:13:53"
},
{
"name": "sebastian/environment",
"version": "1.2.1",
"version": "1.2.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
"reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7"
"reference": "5a8c7d31914337b69923db26c4221b81ff5a196e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e6c71d918088c251b181ba8b3088af4ac336dd7",
"reference": "6e6c71d918088c251b181ba8b3088af4ac336dd7",
"url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e",
"reference": "5a8c7d31914337b69923db26c4221b81ff5a196e",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"require-dev": {
"phpunit/phpunit": "~4.3"
"phpunit/phpunit": "~4.4"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.2.x-dev"
"dev-master": "1.3.x-dev"
}
},
"autoload": {
@@ -3764,7 +3939,7 @@
"environment",
"hhvm"
],
"time": "2014-10-25 08:00:45"
"time": "2015-01-01 10:01:08"
},
{
"name": "sebastian/exporter",
@@ -3938,16 +4113,16 @@
},
{
"name": "sebastian/version",
"version": "1.0.4",
"version": "1.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
"reference": "a77d9123f8e809db3fbdea15038c27a95da4058b"
"reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/a77d9123f8e809db3fbdea15038c27a95da4058b",
"reference": "a77d9123f8e809db3fbdea15038c27a95da4058b",
"url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4",
"reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4",
"shasum": ""
},
"type": "library",
@@ -3969,7 +4144,7 @@
],
"description": "Library that helps with managing the version number of Git-hosted PHP projects",
"homepage": "https://github.com/sebastianbergmann/version",
"time": "2014-12-15 14:25:24"
"time": "2015-02-24 06:35:25"
},
{
"name": "symfony/class-loader",
@@ -4177,6 +4352,7 @@
"aliases": [],
"minimum-stability": "stable",
"stability-flags": {
"rcrowe/twigbridge": 20,
"barryvdh/laravel-debugbar": 0
},
"prefer-stable": false,

View File

@@ -136,9 +136,11 @@ return [
'Illuminate\Validation\ValidationServiceProvider',
'Illuminate\View\ViewServiceProvider',
'Illuminate\Html\HtmlServiceProvider',
'TwigBridge\ServiceProvider',
'DaveJamesMiller\Breadcrumbs\ServiceProvider',
'Barryvdh\Debugbar\ServiceProvider',
'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider',
'DaveJamesMiller\Breadcrumbs\ServiceProvider',
/*
* Application Service Providers...
@@ -151,6 +153,7 @@ return [
'FireflyIII\Providers\FireflyServiceProvider',
'FireflyIII\Providers\TestingServiceProvider',
],
/*
@@ -200,13 +203,14 @@ return [
'View' => 'Illuminate\Support\Facades\View',
'Form' => 'Illuminate\Html\FormFacade',
'Html' => 'Illuminate\Html\HtmlFacade',
'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade',
'Breadcrumbs' => 'DaveJamesMiller\Breadcrumbs\Facade',
'Preferences' => 'FireflyIII\Support\Facades\Preferences',
'Navigation' => 'FireflyIII\Support\Facades\Navigation',
'Amount' => 'FireflyIII\Support\Facades\Amount',
'Steam' => 'FireflyIII\Support\Facades\Steam',
'ExpandedForm' => 'FireflyIII\Support\Facades\ExpandedForm',
'Twig' => 'TwigBridge\Facade\Twig',
],

View File

@@ -48,7 +48,7 @@ return [
'sqlite' => [
'driver' => 'sqlite',
'database' => ':memory:',
'database' => __DIR__.'/../storage/database/testing.db',
'prefix' => '',
],

View File

@@ -14,7 +14,7 @@ return [
*/
'paths' => [
realpath(base_path('resources/views'))
realpath(base_path('resources/twig'))
],
/*

View File

@@ -4,6 +4,8 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
*
* Class CreatePasswordResetsTable
*/
class CreatePasswordResetsTable extends Migration

View File

@@ -41,6 +41,9 @@ class CreateAccountMetaTable extends Migration
$table->unique(['account_id', 'name']);
// link to account!
$table->foreign('account_id')->references('id')->on('accounts')->onDelete('cascade');
}
);

View File

@@ -7,6 +7,7 @@ use FireflyIII\Models\Component;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
/**
* @SuppressWarnings(PHPMD.ShortMethodName) // method names are mandated by laravel.
* @SuppressWarnings("TooManyMethods") // I'm fine with this
@@ -426,7 +427,6 @@ class ChangesForV321 extends Migration
public function moveComponentIdToBudgetId()
{
//Log::debug('Now in moveComponentIdToBudgetId()');
BudgetLimit::get()->each(
function (BudgetLimit $bl) {
Log::debug('Now at budgetLimit #' . $bl->id . ' with component_id: ' . $bl->component_id);
@@ -447,7 +447,6 @@ class ChangesForV321 extends Migration
}
}
);
//Log::debug('Done with moveComponentIdToBudgetId()');
}

View File

@@ -5,7 +5,7 @@ use Illuminate\Database\Schema\Blueprint;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
* @SuppressWarnings("MethodLength") // I don't mind this in case of migrations.
* @SuppressWarnings("PHPMD.ExcessiveMethodLength")
*
* Class ChangesForV322
*/

View File

@@ -5,7 +5,7 @@ use Illuminate\Database\Schema\Blueprint;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
* @SuppressWarnings("MethodLength") // I don't mind this in case of migrations.
* @SuppressWarnings("PHPMD.ExcessiveMethodLength")
*
* Class ChangesForV325
*/

View File

@@ -4,6 +4,8 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
*
* Class ChangesForV332
*/
class ChangesForV332 extends Migration

View File

@@ -3,6 +3,11 @@
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
*
* Class ChangesForV333
*/
class ChangesForV333 extends Migration
{

View File

@@ -4,6 +4,9 @@ use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
* @SuppressWarnings("PHPMD.ExcessiveMethodLength")
*
* Class ChangesForV336
*/
class ChangesForV336 extends Migration
@@ -134,7 +137,7 @@ class ChangesForV336 extends Migration
// reinstate a long forgotten index:
Schema::table(
'budget_limits', function (Blueprint $table) {
$table->unique(['budget_id', 'startdate'],'unique_limit');
$table->unique(['budget_id', 'startdate'], 'unique_limit');
}
);

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