Compare commits

...

191 Commits

Author SHA1 Message Date
James Cole
50cf7f6a3b Merge branch 'release/3.4.0.8' 2015-05-22 18:55:13 +02:00
James Cole
eecb4db34c Built chart tests. 2015-05-22 18:31:57 +02:00
James Cole
1f865d3ea4 Improved coverage. 2015-05-22 15:05:32 +02:00
James Cole
623bb4b350 New tests. 2015-05-22 10:17:20 +02:00
James Cole
dc8ad673a6 New test to cover some reminder stuff. 2015-05-22 08:52:30 +02:00
James Cole
4914ad821e Fixed coverage for transaction controller. 2015-05-22 08:03:34 +02:00
James Cole
f099cbadc3 Version increment. 2015-05-22 07:16:36 +02:00
James Cole
42cda384c8 Fix help routes 2015-05-22 07:15:40 +02:00
James Cole
23c91b9990 Some translations, playing around with popups. [skip ci] 2015-05-21 23:05:31 +02:00
James Cole
ff0379182e Sort chart [skip ci] 2015-05-21 18:57:14 +02:00
James Cole
e08a23948f Fixed chart. [skip ci] 2015-05-21 18:50:23 +02:00
James Cole
bd56de6d36 Fix other translations [skip ci] 2015-05-21 17:47:10 +02:00
James Cole
42970aea80 Fix some translations. 2015-05-21 17:45:01 +02:00
James Cole
003a05ee8d Fixed the category chart. 2015-05-21 17:27:48 +02:00
James Cole
ffb11b01a6 Some new translations. 2015-05-21 07:44:44 +02:00
James Cole
e426f5d5da Some new translations. 2015-05-21 07:30:38 +02:00
James Cole
6989f61e1b Extra translations [skip ci] 2015-05-20 20:10:01 +02:00
James Cole
0e6677ccb3 Remove cash accounts from list [skip ci] 2015-05-20 20:04:27 +02:00
James Cole
8f104d555a Added newlines to files. 2015-05-20 19:56:14 +02:00
James Cole
b1d3158db1 Code cleanup. 2015-05-20 19:55:53 +02:00
James Cole
7645005d5a Return of account id. 2015-05-20 18:18:05 +02:00
James Cole
411f77fd29 Fixed some other displays of money 2015-05-20 18:09:44 +02:00
James Cole
568ab26db1 Spell check [skip ci] 2015-05-20 17:06:47 +02:00
James Cole
29652108f0 Fixed tests. 2015-05-20 17:04:53 +02:00
James Cole
f07e4dc711 Fix sort. [skip ci] 2015-05-20 07:21:40 +02:00
James Cole
8a2ac457c2 Name fix [skip ci] 2015-05-20 07:21:01 +02:00
James Cole
9e54eecfaa Fixed some views. 2015-05-20 07:20:02 +02:00
James Cole
95ef691077 Fixed some more reports and charts. [skip ci] 2015-05-20 07:07:46 +02:00
James Cole
7a0ad5a587 Fixed a chart [skip ci] 2015-05-20 06:50:24 +02:00
James Cole
42b49d0e4b Added some correcting methods. [skip ci] 2015-05-20 06:50:15 +02:00
James Cole
9217c2f003 Corrected some charts [skip ci] 2015-05-20 06:49:51 +02:00
James Cole
fbdf66998d Added a forgotten chart, corrected some others. [skip ci] 2015-05-20 06:49:22 +02:00
James Cole
deda9d3c54 Add corrected expense routes [skip ci] 2015-05-20 06:49:03 +02:00
James Cole
a5d78f20ae Add corrected income and expense methods [skip ci] 2015-05-20 06:48:52 +02:00
James Cole
5ed09e3f38 Call the corrected spent function [skip ci] 2015-05-20 06:47:53 +02:00
James Cole
3e9774cd66 Merge branch 'release/3.4.0.7' 2015-05-18 18:23:07 +02:00
James Cole
54387c8fdf Merge branch 'release/3.4.0.7' into develop 2015-05-18 18:23:07 +02:00
James Cole
7eec949a13 Push new release. 2015-05-18 18:23:01 +02:00
James Cole
4113c4ff40 Fixed the tests. 2015-05-18 17:57:44 +02:00
James Cole
1bf0968bfe Show correct icon. [skip ci] 2015-05-18 17:05:22 +02:00
James Cole
374b90fb00 Show correct amount [skip ci] 2015-05-18 17:04:10 +02:00
James Cole
064e60e9d5 Show tag amount better [skip ci] 2015-05-18 17:02:18 +02:00
James Cole
b637455970 New translations [skip ci] 2015-05-18 16:59:01 +02:00
James Cole
68158937d1 Fixed translation [skip ci] 2015-05-18 06:56:59 +02:00
James Cole
adb1356b7a Small bug fix in display of income vs. expenses [skip ci] 2015-05-18 06:55:36 +02:00
James Cole
d880ccb8e0 Small bug fix in display of income vs. expenses [skip ci] 2015-05-18 06:54:46 +02:00
James Cole
050fb1d1ef Some translations [skip ci] 2015-05-17 18:06:00 +02:00
James Cole
6580752bde Now includes chart! [skip ci] 2015-05-17 18:03:16 +02:00
James Cole
c9df265c9b Included bills in month report. [skip ci] 2015-05-17 17:54:13 +02:00
James Cole
098e5bc162 Small translation fix [skip ci] 2015-05-17 17:27:56 +02:00
James Cole
4b2dcc74d4 Expanded the amount thing. 2015-05-17 16:12:00 +02:00
James Cole
a9254c5c9a Some new translations, better tag view [skip ci] 2015-05-17 15:55:24 +02:00
James Cole
7ce57e6ccb Fix a view, fix tag format. 2015-05-17 15:24:30 +02:00
James Cole
0fcb32a66f Fix update error. 2015-05-17 15:17:06 +02:00
James Cole
9946535f01 Some new bread crumbs [skip ci] 2015-05-17 15:12:45 +02:00
James Cole
2b17396d6b Fix some translations. 2015-05-17 13:44:58 +02:00
James Cole
b01d5bc237 Translation fixes [skip ci] 2015-05-17 12:53:32 +02:00
James Cole
b123860304 More stuff. 2015-05-17 12:49:09 +02:00
James Cole
033f5b67db Code cleanup 2015-05-17 11:28:58 +02:00
James Cole
6280448dfb Fixed more tests. 2015-05-17 10:47:12 +02:00
James Cole
01cd3333e4 Fixing tests. 2015-05-17 10:36:11 +02:00
James Cole
63050907b9 Code cleanup. 2015-05-17 10:30:18 +02:00
James Cole
beedf7d780 Cleaning up 2015-05-17 10:10:58 +02:00
James Cole
6b8194261f Clean up and simplify code. 2015-05-17 10:01:47 +02:00
James Cole
dbb1c4d534 Fixed some reports. 2015-05-17 09:35:49 +02:00
James Cole
e6263f9ff5 Some cleaning up 2015-05-17 09:18:44 +02:00
James Cole
6ca119c4db Minor changes [skip ci] 2015-05-17 09:04:55 +02:00
James Cole
c483a1ab3a Ignore simple classes. 2015-05-16 19:08:54 +02:00
James Cole
2e7edd033c Some expanded things. 2015-05-16 16:47:52 +02:00
James Cole
c576902501 Fixed tests. 2015-05-16 16:04:51 +02:00
James Cole
66c2951594 Cleanup 2015-05-16 15:52:09 +02:00
James Cole
b812881cdb More hip report stuff. 2015-05-16 15:43:58 +02:00
James Cole
cdeac2c6db Should simplify reports. 2015-05-16 14:51:23 +02:00
James Cole
bca2ddd529 Budget report thing. 2015-05-16 14:14:22 +02:00
James Cole
e7285c6499 Some overhauls. 2015-05-16 13:53:08 +02:00
James Cole
bdff275672 Simplified report code. 2015-05-16 13:06:38 +02:00
James Cole
bec58a1ee6 Experimental test coverage. 2015-05-16 10:34:38 +02:00
James Cole
f64616748c Expenses only [skip ci] 2015-05-16 10:18:32 +02:00
James Cole
512ce15973 Small tweaks in charts. 2015-05-16 10:13:41 +02:00
James Cole
ed8b301574 Routes and JS cleanup. 2015-05-16 10:05:22 +02:00
James Cole
d22a6c019c Fixed lots of chart references. 2015-05-16 09:57:31 +02:00
James Cole
a0cb1b9d9e Clean up and split chart controllers 2015-05-16 09:41:14 +02:00
James Cole
a5294c62ea Renamed a method. 2015-05-16 09:26:54 +02:00
James Cole
e155d3311c Fixed tests 2015-05-16 09:25:14 +02:00
James Cole
0a372b0daf Cleanup tests 2015-05-16 09:16:32 +02:00
James Cole
69143399d1 Moved some stuff around. 2015-05-16 09:09:52 +02:00
James Cole
3270d3bf96 Cleanup. 2015-05-16 08:14:26 +02:00
James Cole
3896a66122 Fixed tests. 2015-05-16 08:09:15 +02:00
James Cole
b94781aef1 Some optimisations. 2015-05-16 08:05:04 +02:00
James Cole
bed1adc367 Fixed budget. 2015-05-16 07:56:15 +02:00
James Cole
ae54497efa Differ between shared and normal transactions (not build yet). 2015-05-16 07:49:02 +02:00
James Cole
06b747c221 Some cleanup and translations. 2015-05-16 07:28:58 +02:00
James Cole
f159beee0d Fixed preferences tests. 2015-05-15 23:24:55 +02:00
James Cole
49d7dea086 Fixed some coverage. 2015-05-15 23:02:42 +02:00
James Cole
3e65733dc5 Small fix in report view [skip ci] 2015-05-15 22:12:31 +02:00
James Cole
cc375d58bb Fixed tests. 2015-05-15 22:06:52 +02:00
James Cole
911c7c662a Expanded reports. 2015-05-15 22:00:00 +02:00
James Cole
aae003be33 Some more cleaning up and fixing 2015-05-15 21:01:24 +02:00
James Cole
aede03d8b2 Some more layout changes. 2015-05-15 20:43:50 +02:00
James Cole
f0f5ada7de More changes to reports. 2015-05-15 20:38:39 +02:00
James Cole
58365121a3 Fixed tests. 2015-05-15 20:15:58 +02:00
James Cole
d5a154d2e6 Cleaned up reports and associated views. 2015-05-15 20:07:51 +02:00
James Cole
b20f369aef Some new tests. 2015-05-15 18:39:59 +02:00
James Cole
abb8aa0b29 Merge branch 'feature/translations' into develop 2015-05-15 18:38:26 +02:00
James Cole
5368a0f1d7 Some new translations. 2015-05-14 19:44:20 +02:00
James Cole
d3897eece7 This should fix the tests on the translations branch. 2015-05-14 18:15:31 +02:00
James Cole
a82b829da9 More translations. 2015-05-14 18:00:56 +02:00
James Cole
9f5058e81a Some new translations. 2015-05-14 17:52:50 +02:00
James Cole
5b19263720 Some more [skip ci] 2015-05-14 16:43:12 +02:00
James Cole
9d5a0db0d9 [skip ci] 2015-05-14 16:36:08 +02:00
James Cole
4bd8a7014f Count things [skip ci] 2015-05-14 16:35:41 +02:00
James Cole
353e96d951 Better (and translated) delete forms. [skip ci] 2015-05-14 16:32:35 +02:00
James Cole
149a6f92b0 Translations [skip ci] 2015-05-14 15:56:23 +02:00
James Cole
d66426c137 Nieuw vertalingen [skip ci] 2015-05-14 15:53:56 +02:00
James Cole
4fc9966392 Chart translations [skip ci] 2015-05-14 13:43:58 +02:00
James Cole
417766f0db Various date localisation. [skip ci] 2015-05-14 13:41:21 +02:00
James Cole
de9ac97887 Also english. [skip ci] 2015-05-14 13:19:26 +02:00
James Cole
6be42f112a Charts and titles in Dutch. [skip ci] 2015-05-14 13:17:53 +02:00
James Cole
3895ae63c7 Some translations for lists [skip ci] 2015-05-14 13:00:43 +02:00
James Cole
607d416d54 Better translation for 'balance' [skip ci] 2015-05-14 12:11:56 +02:00
James Cole
038693dc86 More index translations [skip ci] 2015-05-14 12:10:42 +02:00
James Cole
cc9be13544 Added a bread crumb [skip ci] 2015-05-14 11:50:48 +02:00
James Cole
9c1474087f Forgot one [skip ci] 2015-05-14 11:50:04 +02:00
James Cole
831de2bcf4 New menu translations [skip ci] 2015-05-14 11:48:59 +02:00
James Cole
eb687333bb Small edits to buttons and others. [skip ci] 2015-05-14 11:31:54 +02:00
James Cole
5cc7966d54 Some new form things. [skip ci] 2015-05-14 11:25:43 +02:00
James Cole
d1a34e7a6f Breadcrumbs translated to English. [skip ci] 2015-05-14 11:22:20 +02:00
James Cole
d63d791717 Translated all bread crumbs to Dutch. [skip ci] 2015-05-14 11:17:56 +02:00
James Cole
015570c741 Small translations as a basic start [skip ci] 2015-05-14 10:26:15 +02:00
James Cole
8400ebc9c6 Added a language test, added Dutch basic file. [skip ci] 2015-05-14 10:03:57 +02:00
James Cole
9f99e7c0af Edit and set language [skip ci] 2015-05-14 09:59:30 +02:00
James Cole
392c1fc399 Add language selector to preferences [skip ci] 2015-05-14 09:56:41 +02:00
James Cole
d3cea7a89c Add new supported languages [skip ci] 2015-05-14 09:52:58 +02:00
James Cole
1dcf7407e6 Cleanup [skip ci] 2015-05-14 09:51:54 +02:00
James Cole
d543c033a3 Small fixes to translations. 2015-05-14 09:50:07 +02:00
James Cole
aaa186be5e Merge branch 'release/3.4.0.6' 2015-05-14 09:21:23 +02:00
James Cole
2054b5b3dd Merge branch 'release/3.4.0.6' into develop 2015-05-14 09:21:23 +02:00
James Cole
98ae5b0ca0 New read me. 2015-05-14 09:21:12 +02:00
James Cole
36c8171d0f Clean up and tests. 2015-05-14 09:01:10 +02:00
James Cole
3603eb94cc Different budget query [skip ci] 2015-05-14 08:08:25 +02:00
James Cole
0e068d4ccf Fixed some tests. 2015-05-13 21:37:11 +02:00
James Cole
199f348ff4 Smaller mobile pages. 2015-05-13 21:32:33 +02:00
James Cole
b22655fb7c Fix helper 2015-05-13 21:32:27 +02:00
James Cole
06cc9618ba Some new tests 2015-05-13 21:32:21 +02:00
James Cole
b9019c8c7f Smaller screens update [skip ci] 2015-05-13 06:34:17 +02:00
James Cole
77e133e67c Some cleaning up for mobile screens [skip ci] 2015-05-13 06:31:32 +02:00
James Cole
571e7df807 Some tiny optimisations. 2015-05-12 20:51:03 +02:00
James Cole
22f4d2979a Added some more ignores, edited some middleware. 2015-05-11 22:12:53 +02:00
James Cole
e46e366694 Added some tests to cover an event. 2015-05-11 21:45:31 +02:00
James Cole
7b4bc23815 Merge branch 'release/3.4.0.5' 2015-05-10 19:18:57 +02:00
James Cole
9ca79f767c Merge branch 'release/3.4.0.5' into develop 2015-05-10 19:18:57 +02:00
James Cole
274dba7408 Update read me. 2015-05-10 19:18:49 +02:00
James Cole
31708ca29e Ignore some code. 2015-05-10 19:18:43 +02:00
James Cole
671b025588 More ignore stuff. 2015-05-10 13:40:29 +02:00
James Cole
a7956e4856 Adding lots of ignore statements because testing the models is pointless. 2015-05-10 13:22:00 +02:00
James Cole
355862025a Auth and password controller. 2015-05-10 13:06:02 +02:00
James Cole
a2a39ee0f8 Ignore piggy bank part. 2015-05-10 09:35:42 +02:00
James Cole
ec8e39c16f Fixed currency tests. 2015-05-10 09:26:44 +02:00
James Cole
88f714999e Add test to get full coverage. 2015-05-10 08:53:49 +02:00
James Cole
c0c2aa3be0 Fixed one test. 2015-05-10 08:49:15 +02:00
James Cole
822044820e Ignored more files. 2015-05-10 08:26:42 +02:00
James Cole
6ffc182142 Ignore lots of code in test coverage. 2015-05-10 08:08:07 +02:00
James Cole
3d54a78573 Tag repository tests 2015-05-10 07:48:33 +02:00
James Cole
8ddf7d953a Ignore constructor. 2015-05-10 07:09:21 +02:00
James Cole
8b9e9ad103 Tests for reminder repository. 2015-05-10 07:07:17 +02:00
James Cole
5737224c40 Simplified translations [skip ci] 2015-05-09 22:42:45 +02:00
James Cole
ec9aacbcae More new tests. 2015-05-09 22:30:16 +02:00
James Cole
9395454997 Small optimalizations [skip ci] 2015-05-09 19:27:25 +02:00
James Cole
66198a8d98 Expanded bread crumb [skip ci] 2015-05-09 19:23:37 +02:00
James Cole
96ed9a4256 Finished journal repository. 2015-05-09 18:30:58 +02:00
James Cole
10e54b2263 Tested part of the journal repository. 2015-05-09 18:11:48 +02:00
James Cole
cf00922ad2 Merge branch 'release/3.4.0.4' 2015-05-09 15:13:20 +02:00
James Cole
84e8e007a5 Merge branch 'release/3.4.0.4' into develop 2015-05-09 15:13:20 +02:00
James Cole
d07b2e773b Update read me 2015-05-09 15:13:14 +02:00
James Cole
506ef7b0b9 Covered currency repository. 2015-05-09 15:11:12 +02:00
James Cole
2cd5dae8e2 New read me [skip ci] 2015-05-09 15:08:56 +02:00
James Cole
a1cd49c111 First attempt at translations. 2015-05-09 13:56:03 +02:00
James Cole
aca2973aef Experimental chart [skip ci] 2015-05-09 13:55:07 +02:00
James Cole
0a7a691c95 Experimental chart [skip ci] 2015-05-09 13:53:58 +02:00
James Cole
72906a7afd Experimental chart [skip ci] 2015-05-09 13:52:33 +02:00
James Cole
d1a4a83570 Covered category repository. 2015-05-09 13:14:02 +02:00
James Cole
e0396b29e8 Add GA beacon [skip ci] 2015-05-09 10:43:37 +02:00
James Cole
536833cfe0 Fixed tests. 2015-05-09 10:25:52 +02:00
James Cole
317b02d1b9 Finished budget repository tests. 2015-05-09 10:23:13 +02:00
James Cole
75e279ea0d Update read me [skip ci] 2015-05-09 09:17:09 +02:00
James Cole
dc2ad21f4c Updated read me [skip ci] 2015-05-09 09:15:39 +02:00
James Cole
484d49aae1 Fixed tests 2015-05-09 09:15:27 +02:00
James Cole
ca39438ad4 Small update to the read me. [skip ci] 2015-05-09 09:11:54 +02:00
James Cole
49a65ebff4 New budget repository tests. 2015-05-09 09:05:37 +02:00
James Cole
befdc05084 Rewrote read me. [skip ci] 2015-05-08 19:34:03 +02:00
James Cole
1fbffe761b Merge branch 'release/3.4.0.3' into develop 2015-05-08 17:35:03 +02:00
258 changed files with 9094 additions and 4532 deletions

View File

@@ -16,3 +16,4 @@ EMAIL_DRIVER=smtp
EMAIL_USERNAME=
EMAIL_PASSWORD=
ANALYTICS_ID=
EMAIL_PRETEND=false

View File

@@ -15,3 +15,4 @@ EMAIL_SMTP=
EMAIL_USERNAME=
EMAIL_PASSWORD=
ANALYTICS_ID=ABC
EMAIL_PRETEND=true

View File

@@ -1,73 +1,68 @@
Firefly III (v3.4.0.3)
===========
# Firefly III
#### v3.4.0.8
[![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=develop)](https://travis-ci.org/JC5/firefly-iii)
[![Project Status](http://stillmaintained.com/JC5/firefly-iii.png?a=b)](http://stillmaintained.com/JC5/firefly-iii)
[![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=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)
[![Latest Unstable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/unstable.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
[![License](https://poser.pugx.org/grumpydictator/firefly-iii/license.svg)](https://packagist.org/packages/grumpydictator/firefly-iii)
![GA](https://ga-beacon.appspot.com/UA-58172398-6/firefly-iii/readme)
## About
Firefly III is a tool to help you manage your finances. Please read the full description [in the wiki](https://github.com/JC5/firefly-iii/wiki/full-description).
"Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared
household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money.
Firefly Mark III is a new version of Firefly built upon best practices and lessons learned
from building [Firefly](https://github.com/JC5/Firefly). It's Mark III since the original Firefly never made it outside of my
laptop and [Firefly II](https://github.com/JC5/Firefly) is live.
_Firefly is a system you'll have install yourself on webhosting of your choosing._
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).
Personal financial management is pretty difficult, and everybody has their own approach to it. Some people
make budgets, other people limit their cashflow by throwing away their credit cards, others try to increase
their current cashflow. There are tons of ways to save and earn money.
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)**.
Firefly works on the principle that if you know where you're money is going, you can stop it from going there.
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.
To get to know Firefly, and to see if it fits you, check out these resources:
- The screenshots below on this very page.
- The featurelist below, also on this very page.
- The [full description](https://github.com/JC5/firefly-iii/wiki/full-description), which will tell you how Firefly works,
and the philosophy behind it.
#### About the name (if you care)
It's III, or 3, because [version 2](https://github.com/JC5/Firefly) and version 1 (not online) preceded it. It has been growing steadily ever since.
## Current features
- [A double-entry bookkeeping system](https://en.wikipedia.org/wiki/Double-entry_bookkeeping_system);
- You can store, edit and remove withdrawals, deposits and transfers. This allows you full financial management;
- You can manage different types of accounts
- Asset accounts
- Shared asset accounts (household accounts)
- You can store, edit and remove [withdrawals, deposits and transfers](https://en.wikipedia.org/wiki/Financial_transaction). This allows you full financial management;
- You can manage different types of accounts;
- [Asset](https://en.wikipedia.org/wiki/Asset) accounts
- Shared [asset accounts](https://en.wikipedia.org/wiki/Asset) ([household accounts](https://en.wikipedia.org/wiki/Household))
- Saving accounts
- Credit cards
- It's possible to create, change and manage money using _[budgets](https://en.wikipedia.org/wiki/Envelope_system)_;
- Organize transactions using categories;
- Save towards a goal using piggy banks;
- Predict and anticipate bills;
- View income / expense reports;
- Lots of help text in case you don't get it;
- Save towards a goal using [piggy banks](https://en.wikipedia.org/wiki/Piggy_bank);
- Predict and anticipate [bills](https://en.wikipedia.org/wiki/Invoice);
- View income / expense [reports](https://en.wikipedia.org/wiki/Financial_statement);
- Organize expenses using tags;
- Lots of help text in case you don't get it.
Everything is organised:
- Clear views that should show you how you're doing;
- Easy navigation through your records;
- Browse back and forth to see previous months or even years;
- Lots of charts because we all love them.
- Financial reporting showing you how well you are doing;
## Changes
Firefly III will feature, but does not feature yet:
- More control over other resources outside of personal finance
- Debts
- More test-coverage;
- Firefly will be able to split transactions; a single purchase can be split in multiple entries, for more fine-grained control.
- Firefly will be able to join transactions.
- Any other features I might not have thought of.
Some stuff has been removed:
- The nesting of budgets, categories and beneficiaries is removed because it was pretty pointless.
- Lots of charts because we all love them;
- Financial reporting showing you how well you are doing.
## Screenshots
_Please note that everything in these screenshots is fictional and may not be realistic._
![Index](https://i.nder.be/c09vfw90)
![Accounts](https://i.nder.be/hkn0vhcg)
@@ -82,7 +77,21 @@ Some stuff has been removed:
![Piggy banks](https://i.nder.be/hkud0h53)
## Current state
I have the basics up and running. Test coverage is currently coming, slowly.
## Running and installing
Questions, ideas or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)!
If you're still interested 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)**.
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 state
Firefly III is pretty much all grown up. Full test coverage (nerd alert!) is coming. One of the things on the todo-list
is adding translations.
Questions, ideas, bugs or other things to contribute? [Let me know](https://github.com/JC5/firefly-iii/issues/new)!
If you like this tool, feel free to [donate me some beer money](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=2ZMV952UUSCLU&lc=NL&item_name=Development%20of%20Firefly&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_SM%2egif%3aNonHosted).

View File

@@ -2,6 +2,7 @@
/**
* Class Command
*
* @codeCoverageIgnore
* @package FireflyIII\Commands
*/
abstract class Command

View File

@@ -6,6 +6,7 @@ use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
/**
* Class Kernel
*
* @codeCoverageIgnore
* @package FireflyIII\Console
*/
class Kernel extends ConsoleKernel
@@ -25,6 +26,8 @@ class Kernel extends ConsoleKernel
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*
* @return void
*/
protected function schedule(Schedule $schedule)

View File

@@ -3,6 +3,7 @@
/**
* Class Event
*
* @codeCoverageIgnore
* @package FireflyIII\Events
*/
abstract class Event

View File

@@ -6,6 +6,7 @@ use Illuminate\Queue\SerializesModels;
/**
* Class JournalCreated
*
* @codeCoverageIgnore
* @package FireflyIII\Events
*/
class JournalCreated extends Event

View File

@@ -5,6 +5,7 @@ use Illuminate\Queue\SerializesModels;
/**
* Class JournalDeleted
*
* @codeCoverageIgnore
* @package FireflyIII\Events
*/
class JournalDeleted extends Event

View File

@@ -6,6 +6,7 @@ use Illuminate\Queue\SerializesModels;
/**
* Class JournalSaved
*
* @codeCoverageIgnore
* @package FireflyIII\Events
*/
class JournalSaved extends Event

View File

@@ -6,6 +6,7 @@ namespace FireflyIII\Exceptions;
/**
* Class FireflyException
*
* @codeCoverageIgnore
* @package FireflyIII\Exceptions
*/
class FireflyException extends \Exception

View File

@@ -6,6 +6,7 @@ use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
/**
* Class Handler
*
* @codeCoverageIgnore
* @package FireflyIII\Exceptions
*/
class Handler extends ExceptionHandler
@@ -26,6 +27,7 @@ class Handler extends ExceptionHandler
*
* @param \Illuminate\Http\Request $request
* @param \Exception $e
* @SuppressWarnings(PHPMD.ShortVariable)
*
* @return \Illuminate\Http\Response
*/
@@ -42,6 +44,7 @@ class Handler extends ExceptionHandler
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
* @SuppressWarnings(PHPMD.ShortVariable)
*
* @param \Exception $e
*

View File

@@ -5,6 +5,7 @@ namespace FireflyIII\Exceptions;
/**
* Class NotImplementedException
*
* @codeCoverageIgnore
* @package FireflyIII\Exceptions
*/
class NotImplementedException extends \Exception

View File

@@ -4,6 +4,7 @@ namespace FireflyIII\Exceptions;
/**
* Class ValidationExceptions
*
* @codeCoverageIgnore
* @package FireflyIII\Exception
*/
class ValidationException extends \Exception

View File

@@ -6,7 +6,6 @@ use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use Log;
/**
* Class ConnectJournalToPiggyBank
@@ -28,54 +27,36 @@ class ConnectJournalToPiggyBank
/**
* Handle the event when journal is saved.
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @param JournalCreated $event
*
* @return void
* @return boolean
*/
public function handle(JournalCreated $event)
{
/** @var TransactionJournal $journal */
$journal = $event->journal;
$piggyBankId = $event->piggyBankId;
if (intval($piggyBankId) < 1) {
return;
}
Log::debug('JournalCreated event: ' . $journal->id . ', ' . $piggyBankId);
/** @var PiggyBank $piggyBank */
$piggyBank = Auth::user()->piggybanks()->where('piggy_banks.id', $piggyBankId)->first(['piggy_banks.*']);
if (is_null($piggyBank) || $journal->transactionType->type != 'Transfer') {
return;
}
Log::debug('Found a piggy bank');
$amount = $journal->amount;
Log::debug('Amount: ' . $amount);
if ($amount == 0) {
return;
if (is_null($piggyBank)) {
return false;
}
// update piggy bank rep for date of transaction journal.
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
if (is_null($repetition)) {
Log::debug('Found no repetition for piggy bank for date ' . $journal->date->format('Y M d'));
return;
return false;
}
Log::debug('Found rep! ' . $repetition->id);
/*
* Add amount when
*/
$amount = $journal->amount;
/** @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);
$amount = $transaction->amount * -1;
}
}
}
@@ -83,14 +64,9 @@ class ConnectJournalToPiggyBank
$repetition->currentamount += $amount;
$repetition->save();
PiggyBankEvent::create(
[
'piggy_bank_id' => $piggyBank->id,
'transaction_journal_id' => $journal->id,
'date' => $journal->date,
'amount' => $amount
]
);
PiggyBankEvent::create(['piggy_bank_id' => $piggyBank->id, 'transaction_journal_id' => $journal->id, 'date' => $journal->date, 'amount' => $amount]);
return true;
}

View File

@@ -1,35 +0,0 @@
<?php namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\JournalDeleted;
/**
* Class JournalDeletedHandler
*
* @package FireflyIII\Handlers\Events
*/
class JournalDeletedHandler
{
/**
* Create the event handler.
*
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param JournalDeleted $event
*
* @return void
*/
public function handle(JournalDeleted $event)
{
//
}
}

View File

@@ -7,6 +7,7 @@ use Log;
/**
* Class RescanJournal
*
* @codeCoverageIgnore
* @package FireflyIII\Handlers\Events
*/
class RescanJournal

View File

@@ -2,10 +2,12 @@
use FireflyIII\Events\JournalSaved;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\PiggyBankRepetition;
/**
* Class UpdateJournalConnection
*
* @codeCoverageIgnore
* @package FireflyIII\Handlers\Events
*/
class UpdateJournalConnection
@@ -38,7 +40,11 @@ class UpdateJournalConnection
return;
}
$piggyBank = $event->piggyBank()->first();
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
$repetition = null;
if ($piggyBank) {
/** @var PiggyBankRepetition $repetition */
$repetition = $piggyBank->piggyBankRepetitions()->relevantOnDate($journal->date)->first();
}
if (is_null($repetition)) {
return;

View File

@@ -0,0 +1,90 @@
<?php
namespace FireflyIII\Helpers\Collection;
use Illuminate\Support\Collection;
/**
* @codeCoverageIgnore
* Class Account
*
* @package FireflyIII\Helpers\Collection
*/
class Account
{
/** @var Collection */
protected $accounts;
/** @var float */
protected $difference;
/** @var float */
protected $end;
/** @var float */
protected $start;
/**
* @return \Illuminate\Support\Collection
*/
public function getAccounts()
{
return $this->accounts;
}
/**
* @param \Illuminate\Support\Collection $accounts
*/
public function setAccounts($accounts)
{
$this->accounts = $accounts;
}
/**
* @return float
*/
public function getDifference()
{
return $this->difference;
}
/**
* @param float $difference
*/
public function setDifference($difference)
{
$this->difference = $difference;
}
/**
* @return float
*/
public function getEnd()
{
return $this->end;
}
/**
* @param float $end
*/
public function setEnd($end)
{
$this->end = $end;
}
/**
* @return float
*/
public function getStart()
{
return $this->start;
}
/**
* @param float $start
*/
public function setStart($start)
{
$this->start = $start;
}
}

View File

@@ -0,0 +1,64 @@
<?php
namespace FireflyIII\Helpers\Collection;
use Illuminate\Support\Collection;
/**
* @codeCoverageIgnore
*
* Class Balance
*
* @package FireflyIII\Helpers\Collection
*/
class Balance
{
/** @var BalanceHeader */
protected $balanceHeader;
/** @var Collection */
protected $balanceLines;
/**
*
*/
public function __construct()
{
$this->balanceLines = new Collection;
}
/**
* @param BalanceLine $line
*/
public function addBalanceLine(BalanceLine $line)
{
$this->balanceLines->push($line);
}
/**
* @return BalanceHeader
*/
public function getBalanceHeader()
{
return $this->balanceHeader;
}
/**
* @param BalanceHeader $balanceHeader
*/
public function setBalanceHeader($balanceHeader)
{
$this->balanceHeader = $balanceHeader;
}
/**
* @return \Illuminate\Support\Collection
*/
public function getBalanceLines()
{
return $this->balanceLines;
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\Account as AccountModel;
/**
* @codeCoverageIgnore
*
* Class BalanceEntry
*
* @package FireflyIII\Helpers\Collection
*/
class BalanceEntry
{
/** @var AccountModel */
protected $account;
/** @var float */
protected $left = 0.0;
/** @var float */
protected $spent = 0.0;
/**
* @return AccountModel
*/
public function getAccount()
{
return $this->account;
}
/**
* @param AccountModel $account
*/
public function setAccount($account)
{
$this->account = $account;
}
/**
* @return float
*/
public function getLeft()
{
return $this->left;
}
/**
* @param float $left
*/
public function setLeft($left)
{
$this->left = $left;
}
/**
* @return float
*/
public function getSpent()
{
return $this->spent;
}
/**
* @param float $spent
*/
public function setSpent($spent)
{
$this->spent = $spent;
}
}

View File

@@ -0,0 +1,46 @@
<?php
namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\Account as AccountModel;
use Illuminate\Support\Collection;
/**
* @codeCoverageIgnore
*
* Class BalanceHeader
*
* @package FireflyIII\Helpers\Collection
*/
class BalanceHeader
{
/** @var Collection */
protected $accounts;
/**
*
*/
public function __construct()
{
$this->accounts = new Collection;
}
/**
* @param AccountModel $account
*/
public function addAccount(AccountModel $account)
{
$this->accounts->push($account);
}
/**
* @return Collection
*/
public function getAccounts()
{
return $this->accounts;
}
}

View File

@@ -0,0 +1,170 @@
<?php
namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\Budget as BudgetModel;
use FireflyIII\Models\LimitRepetition;
use Illuminate\Support\Collection;
/**
* @codeCoverageIgnore
*
* Class BalanceLine
*
* @package FireflyIII\Helpers\Collection
*/
class BalanceLine
{
const ROLE_DEFAULTROLE = 1;
const ROLE_TAGROLE = 2;
const ROLE_DIFFROLE = 3;
/** @var Collection */
protected $balanceEntries;
/** @var BudgetModel */
protected $budget;
/** @var LimitRepetition */
protected $repetition;
protected $role = self::ROLE_DEFAULTROLE;
/**
*
*/
public function __construct()
{
$this->balanceEntries = new Collection;
}
/**
* @param BalanceEntry $balanceEntry
*/
public function addBalanceEntry(BalanceEntry $balanceEntry)
{
$this->balanceEntries->push($balanceEntry);
}
/**
* @return string
*/
public function getTitle()
{
if ($this->getBudget() instanceof BudgetModel) {
return $this->getBudget()->name;
}
if ($this->getRole() == self::ROLE_DEFAULTROLE) {
return trans('firefly.noBudget');
}
if ($this->getRole() == self::ROLE_TAGROLE) {
return trans('firefly.coveredWithTags');
}
if ($this->getRole() == self::ROLE_DIFFROLE) {
return trans('firefly.leftUnbalanced');
}
}
/**
* @return BudgetModel
*/
public function getBudget()
{
return $this->budget;
}
/**
* @param BudgetModel $budget
*/
public function setBudget($budget)
{
$this->budget = $budget;
}
/**
* @return int
*/
public function getRole()
{
return $this->role;
}
/**
* @param int $role
*/
public function setRole($role)
{
$this->role = $role;
}
/**
* If a BalanceLine has a budget/repetition, each BalanceEntry in this BalanceLine
* should have a "spent" value, which is the amount of money that has been spent
* on the given budget/repetition. If you subtract all those amounts from the budget/repetition's
* total amount, this is returned:
*
* @return float
*/
public function leftOfRepetition()
{
$start = $this->getRepetition() ? $this->getRepetition()->amount : 0;
/** @var BalanceEntry $balanceEntry */
foreach ($this->getBalanceEntries() as $balanceEntry) {
$start += $balanceEntry->getSpent();
}
return $start;
}
/**
* @return LimitRepetition
*/
public function getRepetition()
{
return $this->repetition;
}
/**
* @param LimitRepetition $repetition
*/
public function setRepetition($repetition)
{
$this->repetition = $repetition;
}
/**
* @return Collection
*/
public function getBalanceEntries()
{
return $this->balanceEntries;
}
/**
* @param Collection $balanceEntries
*/
public function setBalanceEntries($balanceEntries)
{
$this->balanceEntries = $balanceEntries;
}
/**
* If the BalanceEntries for a BalanceLine have a "left" value, the amount
* of money left in the entire BalanceLine is returned here:
*
* @return float
*/
public function sumOfLeft()
{
$sum = 0.0;
/** @var BalanceEntry $balanceEntry */
foreach ($this->getBalanceEntries() as $balanceEntry) {
$sum += $balanceEntry->getLeft();
}
return $sum;
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\Bill as BillModel;
use Illuminate\Support\Collection;
/**
* @codeCoverageIgnore
* Class Bill
*
* @package FireflyIII\Helpers\Collection
*/
class Bill
{
/**
* @var Collection
*/
protected $bills;
/**
*
*/
public function __construct()
{
$this->bills = new Collection;
}
/**
* @param BillLine $bill
*/
public function addBill(BillLine $bill)
{
$this->bills->push($bill);
}
/**
* @return Collection
*/
public function getBills()
{
$this->bills->sortBy(
function (BillLine $bill) {
$active = intval($bill->getBill()->active) == 0 ? 1 : 0;
$name = $bill->getBill()->name;
return $active . $name;
}
);
return $this->bills;
}
}

View File

@@ -0,0 +1,127 @@
<?php
namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\Bill as BillModel;
/**
* @codeCoverageIgnore
*
* Class BillLine
*
* @package FireflyIII\Helpers\Collection
*/
class BillLine
{
/** @var bool */
protected $active;
/** @var float */
protected $amount;
/** @var BillModel */
protected $bill;
/** @var bool */
protected $hit;
/** @var float */
protected $max;
/** @var float */
protected $min;
/**
* @return float
*/
public function getAmount()
{
return $this->amount;
}
/**
* @param float $amount
*/
public function setAmount($amount)
{
$this->amount = $amount;
}
/**
* @return BillModel
*/
public function getBill()
{
return $this->bill;
}
/**
* @param BillModel $bill
*/
public function setBill($bill)
{
$this->bill = $bill;
}
/**
* @return float
*/
public function getMax()
{
return $this->max;
}
/**
* @param float $max
*/
public function setMax($max)
{
$this->max = $max;
}
/**
* @return float
*/
public function getMin()
{
return $this->min;
}
/**
* @param float $min
*/
public function setMin($min)
{
$this->min = $min;
}
/**
* @return boolean
*/
public function isActive()
{
return $this->active;
}
/**
* @param boolean $active
*/
public function setActive($active)
{
$this->active = $active;
}
/**
* @return boolean
*/
public function isHit()
{
return $this->hit;
}
/**
* @param boolean $hit
*/
public function setHit($hit)
{
$this->hit = $hit;
}
}

View File

@@ -0,0 +1,148 @@
<?php
namespace FireflyIII\Helpers\Collection;
use Illuminate\Support\Collection;
/**
* @codeCoverageIgnore
*
* Class Budget
*
* @package FireflyIII\Helpers\Collection
*/
class Budget
{
/** @var Collection */
protected $budgetLines;
/** @var float */
protected $budgeted = 0;
/** @var float */
protected $left = 0;
/** @var float */
protected $overspent = 0;
/** @var float */
protected $spent = 0;
/**
*
*/
public function __construct()
{
$this->budgetLines = new Collection;
}
/**
* @param BudgetLine $budgetLine
*/
public function addBudgetLine(BudgetLine $budgetLine)
{
$this->budgetLines->push($budgetLine);
}
/**
* @param float $add
*/
public function addBudgeted($add)
{
$this->budgeted += floatval($add);
}
/**
* @param float $add
*/
public function addLeft($add)
{
$this->left += floatval($add);
}
/**
* @param float $add
*/
public function addOverspent($add)
{
$this->overspent += floatval($add);
}
/**
* @param float $add
*/
public function addSpent($add)
{
$this->spent += floatval($add);
}
/**
* @return \Illuminate\Support\Collection
*/
public function getBudgetLines()
{
return $this->budgetLines;
}
/**
* @return float
*/
public function getBudgeted()
{
return $this->budgeted;
}
/**
* @param float $budgeted
*/
public function setBudgeted($budgeted)
{
$this->budgeted = $budgeted;
}
/**
* @return float
*/
public function getLeft()
{
return $this->left;
}
/**
* @param float $left
*/
public function setLeft($left)
{
$this->left = $left;
}
/**
* @return float
*/
public function getOverspent()
{
return $this->overspent;
}
/**
* @param float $overspent
*/
public function setOverspent($overspent)
{
$this->overspent = $overspent;
}
/**
* @return float
*/
public function getSpent()
{
return $this->spent;
}
/**
* @param float $spent
*/
public function setSpent($spent)
{
$this->spent = $spent;
}
}

View File

@@ -0,0 +1,130 @@
<?php
namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\Budget as BudgetModel;
use FireflyIII\Models\LimitRepetition;
/**
* @codeCoverageIgnore
*
* Class BudgetLine
*
* @package FireflyIII\Helpers\Collection
*/
class BudgetLine
{
/** @var BudgetModel */
protected $budget;
/** @var LimitRepetition */
protected $repetition;
/** @var float */
protected $budgeted = 0;
/** @var float */
protected $left = 0;
/** @var float */
protected $overspent = 0;
/** @var float */
protected $spent = 0;
/**
* @return BudgetModel
*/
public function getBudget()
{
return $this->budget;
}
/**
* @param BudgetModel $budget
*/
public function setBudget($budget)
{
$this->budget = $budget;
}
/**
* @return float
*/
public function getBudgeted()
{
return $this->budgeted;
}
/**
* @param float $budgeted
*/
public function setBudgeted($budgeted)
{
$this->budgeted = $budgeted;
}
/**
* @return float
*/
public function getLeft()
{
return $this->left;
}
/**
* @param float $left
*/
public function setLeft($left)
{
$this->left = $left;
}
/**
* @return float
*/
public function getOverspent()
{
return $this->overspent;
}
/**
* @param float $overspent
*/
public function setOverspent($overspent)
{
$this->overspent = $overspent;
}
/**
* @return float
*/
public function getSpent()
{
return $this->spent;
}
/**
* @param float $spent
*/
public function setSpent($spent)
{
$this->spent = $spent;
}
/**
* @return LimitRepetition
*/
public function getRepetition()
{
return $this->repetition;
}
/**
* @param LimitRepetition $repetition
*/
public function setRepetition($repetition)
{
$this->repetition = $repetition;
}
}

View File

@@ -0,0 +1,80 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 16/05/15
* Time: 13:09
*/
namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\Category as CategoryModel;
use Illuminate\Support\Collection;
/**
* @codeCoverageIgnore
*
* Class Category
*
* @package FireflyIII\Helpers\Collection
*/
class Category
{
/** @var Collection */
protected $categories;
/** @var float */
protected $total = 0;
/**
*
*/
public function __construct()
{
$this->categories = new Collection;
}
/**
* @param CategoryModel $category
*/
public function addCategory(CategoryModel $category)
{
if ($category->spent > 0) {
$this->categories->push($category);
}
}
/**
* @param float $add
*/
public function addTotal($add)
{
$this->total += floatval($add);
}
/**
* @return Collection
*/
public function getCategories()
{
$this->categories->sortByDesc(
function (CategoryModel $category) {
return $category->spent;
}
);
return $this->categories;
}
/**
* @return float
*/
public function getTotal()
{
return $this->total;
}
}

View File

@@ -0,0 +1,82 @@
<?php
namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
use stdClass;
/**
* @codeCoverageIgnore
*
* Class Expense
*
* @package FireflyIII\Helpers\Collection
*/
class Expense
{
/** @var Collection */
protected $expenses;
/** @var float */
protected $total;
/**
*
*/
public function __construct()
{
$this->expenses = new Collection;
}
/**
* @param TransactionJournal $entry
*/
public function addOrCreateExpense(TransactionJournal $entry)
{
$accountId = $entry->account_id;
if (!$this->expenses->has($accountId)) {
$newObject = new stdClass;
$newObject->amount = floatval($entry->amount);
$newObject->name = $entry->name;
$newObject->count = 1;
$newObject->id = $accountId;
$this->expenses->put($accountId, $newObject);
} else {
$existing = $this->expenses->get($accountId);
$existing->amount += floatval($entry->amount);
$existing->count++;
$this->expenses->put($accountId, $existing);
}
}
/**
* @param $add
*/
public function addToTotal($add)
{
$this->total += floatval($add);
}
/**
* @return Collection
*/
public function getExpenses()
{
$this->expenses->sortByDesc(
function (stdClass $object) {
return $object->amount;
}
);
return $this->expenses;
}
/**
* @return float
*/
public function getTotal()
{
return $this->total;
}
}

View File

@@ -0,0 +1,85 @@
<?php
namespace FireflyIII\Helpers\Collection;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Support\Collection;
use stdClass;
/**
* @codeCoverageIgnore
*
* Class Income
*
* @package FireflyIII\Helpers\Collection
*/
class Income
{
/** @var Collection */
protected $incomes;
/** @var float */
protected $total;
/**
*
*/
public function __construct()
{
$this->incomes = new Collection;
}
/**
* @param TransactionJournal $entry
*/
public function addOrCreateIncome(TransactionJournal $entry)
{
$accountId = $entry->account_id;
if (!$this->incomes->has($accountId)) {
$newObject = new stdClass;
$newObject->amount = floatval($entry->amount);
$newObject->name = $entry->name;
$newObject->count = 1;
$newObject->id = $accountId;
$this->incomes->put($accountId, $newObject);
} else {
$existing = $this->incomes->get($accountId);
$existing->amount += floatval($entry->amount);
$existing->count++;
$this->incomes->put($accountId, $existing);
}
}
/**
* @param $add
*/
public function addToTotal($add)
{
$this->total += floatval($add);
}
/**
* @return Collection
*/
public function getIncomes()
{
$this->incomes->sortByDesc(
function (stdClass $object) {
return $object->amount;
}
);
return $this->incomes;
}
/**
* @return float
*/
public function getTotal()
{
return $this->total;
}
}

View File

@@ -17,6 +17,8 @@ class Help implements HelpInterface
{
/**
* @codeCoverageIgnore
*
* @param $key
*
* @return string
@@ -27,13 +29,15 @@ class Help implements HelpInterface
}
/**
* @codeCoverageIgnore
*
* @param $route
*
* @return array
*/
public function getFromGithub($route)
{
$uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/' . e($route) . '.md';
$uri = 'https://raw.githubusercontent.com/JC5/firefly-iii-help/master/en/' . e($route) . '.md';
$content = [
'text' => '<p>There is no help for this route!</p>',
'title' => $route,
@@ -54,6 +58,8 @@ class Help implements HelpInterface
}
/**
* @codeCoverageIgnore
*
* @param $route
*
* @return bool
@@ -64,6 +70,8 @@ class Help implements HelpInterface
}
/**
* @codeCoverageIgnore
*
* @param $route
* @param array $content
*
@@ -76,6 +84,8 @@ class Help implements HelpInterface
}
/**
* @codeCoverageIgnore
*
* @param $route
*
* @return bool

View File

@@ -33,7 +33,7 @@ class ReminderHelper implements ReminderHelperInterface
$ranges = $this->getReminderRanges($piggyBank, $start);
$currentRep = $piggyBank->currentRelevantRep();
$left = $piggyBank->targetamount - $currentRep->currentamount;
$perReminder = $left / count($ranges);
$perReminder = count($ranges) == 0 ? $left : $left / count($ranges);
} else {
$perReminder = null;
$ranges = [];
@@ -46,8 +46,6 @@ class ReminderHelper implements ReminderHelperInterface
'leftToSave' => $left,
];
// create one:
$reminder = new Reminder;
$reminder->user()->associate(Auth::user());
$reminder->startdate = $start;
@@ -65,6 +63,30 @@ class ReminderHelper implements ReminderHelperInterface
}
}
/**
* Create all reminders for a piggy bank for a given date.
*
* @param PiggyBank $piggyBank
*
* @param Carbon $date
*
* @return mixed
*/
public function createReminders(PiggyBank $piggyBank, Carbon $date)
{
$ranges = $this->getReminderRanges($piggyBank);
foreach ($ranges as $range) {
if ($date < $range['end'] && $date > $range['start']) {
// create a reminder here!
$this->createReminder($piggyBank, $range['start'], $range['end']);
// stop looping, we're done.
break;
}
}
}
/**
* This routine will return an array consisting of two dates which indicate the start
* and end date for each reminder that this piggy bank will have, if the piggy bank has

View File

@@ -4,6 +4,7 @@ namespace FireflyIII\Helpers\Reminders;
use Carbon\Carbon;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition;
use FireflyIII\Models\Reminder;
/**
@@ -49,4 +50,15 @@ interface ReminderHelperInterface
* @return Reminder
*/
public function createReminder(PiggyBank $piggyBank, Carbon $start, Carbon $end);
/**
* Create all reminders for a piggy bank for a given date.
*
* @param PiggyBank $piggyBank
*
* @param Carbon $date
*
* @return mixed
*/
public function createReminders(PiggyBank $piggyBank, Carbon $date);
}

View File

@@ -3,12 +3,23 @@
namespace FireflyIII\Helpers\Report;
use App;
use Auth;
use Carbon\Carbon;
use FireflyIII\Helpers\Collection\Account as AccountCollection;
use FireflyIII\Helpers\Collection\Balance;
use FireflyIII\Helpers\Collection\BalanceEntry;
use FireflyIII\Helpers\Collection\BalanceHeader;
use FireflyIII\Helpers\Collection\BalanceLine;
use FireflyIII\Helpers\Collection\Bill as BillCollection;
use FireflyIII\Helpers\Collection\BillLine;
use FireflyIII\Helpers\Collection\Budget as BudgetCollection;
use FireflyIII\Helpers\Collection\BudgetLine;
use FireflyIII\Helpers\Collection\Category as CategoryCollection;
use FireflyIII\Helpers\Collection\Expense;
use FireflyIII\Helpers\Collection\Income;
use FireflyIII\Models\Account;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Steam;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget as BudgetModel;
use FireflyIII\Models\LimitRepetition;
/**
* Class ReportHelper
@@ -18,66 +29,345 @@ use Steam;
class ReportHelper implements ReportHelperInterface
{
/**
* This methods fails to take in account transfers FROM shared accounts.
*
* @param Carbon $start
* @param Carbon $end
* @param int $limit
*
* @return Collection
*/
public function expensesGroupedByAccount(Carbon $start, Carbon $end, $limit = 15)
{
$result = $this->_queries->journalsByExpenseAccount($start, $end);
$array = $this->_helper->makeArray($result);
$limited = $this->_helper->limitArray($array, $limit);
/** @var ReportQueryInterface */
protected $query;
return $limited;
/**
* @codeCoverageIgnore
* @param ReportQueryInterface $query
*
*/
public function __construct(ReportQueryInterface $query)
{
$this->query = $query;
}
/**
* This method generates a full report for the given period on all
* the users asset and cash accounts.
*
* @param Carbon $date
* @param Carbon $end
* @param $shared
*
* @return Account
*/
public function getAccountReport(Carbon $date, Carbon $end, $shared)
{
$accounts = $this->query->getAllAccounts($date, $end, $shared);
$start = 0;
$end = 0;
$diff = 0;
// remove cash account, if any:
$accounts =$accounts->filter(function(Account $account) {
if($account->accountType->type != 'Cash account') {
return $account;
}
});
// summarize:
foreach ($accounts as $account) {
$start += $account->startBalance;
$end += $account->endBalance;
$diff += ($account->endBalance - $account->startBalance);
}
$object = new AccountCollection;
$object->setStart($start);
$object->setEnd($end);
$object->setDifference($diff);
$object->setAccounts($accounts);
return $object;
}
/**
*
* The balance report contains a Balance object which in turn contains:
*
* A BalanceHeader object which contains all relevant user asset accounts for the report.
*
* A number of BalanceLine objects, which hold:
* - A budget
* - A number of BalanceEntry objects.
*
* The BalanceEntry object holds:
* - The same budget (again)
* - A user asset account as mentioned in the BalanceHeader
* - The amount of money spent on the budget by the user asset account
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Balance
*/
public function getBalanceReport(Carbon $start, Carbon $end, $shared)
{
$repository = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
$tagRepository = App::make('FireflyIII\Repositories\Tag\TagRepositoryInterface');
$balance = new Balance;
// build a balance header:
$header = new BalanceHeader;
$accounts = $this->query->getAllAccounts($start, $end, $shared);
$budgets = $repository->getBudgets();
foreach ($accounts as $account) {
$header->addAccount($account);
}
/** @var BudgetModel $budget */
foreach ($budgets as $budget) {
$line = new BalanceLine;
$line->setBudget($budget);
// get budget amount for current period:
$rep = $repository->getCurrentRepetition($budget, $start);
$line->setRepetition($rep);
// loop accounts:
foreach ($accounts as $account) {
$balanceEntry = new BalanceEntry;
$balanceEntry->setAccount($account);
// get spent:
$spent = $this->query->spentInBudgetCorrected($account, $budget, $start, $end); // I think shared is irrelevant.
$balanceEntry->setSpent($spent);
$line->addBalanceEntry($balanceEntry);
}
// add line to balance:
$balance->addBalanceLine($line);
}
// then a new line for without budget.
// and one for the tags:
$empty = new BalanceLine;
$tags = new BalanceLine;
$diffLine = new BalanceLine;
$tags->setRole(BalanceLine::ROLE_TAGROLE);
$diffLine->setRole(BalanceLine::ROLE_DIFFROLE);
foreach ($accounts as $account) {
$spent = $this->query->spentNoBudget($account, $start, $end);
$left = $tagRepository->coveredByBalancingActs($account, $start, $end);
$diff = $spent + $left;
// budget
$budgetEntry = new BalanceEntry;
$budgetEntry->setAccount($account);
$budgetEntry->setSpent($spent);
$empty->addBalanceEntry($budgetEntry);
// balanced by tags
$tagEntry = new BalanceEntry;
$tagEntry->setAccount($account);
$tagEntry->setLeft($left);
$tags->addBalanceEntry($tagEntry);
// difference:
$diffEntry = new BalanceEntry;
$diffEntry->setAccount($account);
$diffEntry->setSpent($diff);
$diffLine->addBalanceEntry($diffEntry);
}
$balance->addBalanceLine($empty);
$balance->addBalanceLine($tags);
$balance->addBalanceLine($diffLine);
$balance->setBalanceHeader($header);
return $balance;
}
/**
* This method generates a full report for the given period on all
* the users bills and their payments.
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return BillCollection
*/
public function getBillReport(Carbon $start, Carbon $end, $shared)
{
/** @var \FireflyIII\Repositories\Bill\BillRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Bill\BillRepositoryInterface');
$bills = $repository->getBills();
$collection = new BillCollection;
/** @var Bill $bill */
foreach ($bills as $bill) {
$billLine = new BillLine;
$billLine->setBill($bill);
$billLine->setActive(intval($bill->active) == 1);
$billLine->setMin(floatval($bill->amount_min));
$billLine->setMax(floatval($bill->amount_max));
// is hit in period?
$set = $repository->getJournalsInRange($bill, $start, $end);
if ($set->count() == 0) {
$billLine->setHit(false);
} else {
$billLine->setHit(true);
$amount = 0;
foreach ($set as $entry) {
$amount += $entry->amount;
}
$billLine->setAmount($amount);
}
$collection->addBill($billLine);
}
return $collection;
}
/**
* This method gets some kind of list for a monthly overview.
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @param Carbon $date
* @param bool $showSharedReports
*
* @return Collection
* @return BudgetCollection
*/
public function getBudgetsForMonth(Carbon $date, $showSharedReports = false)
public function getBudgetReport(Carbon $start, Carbon $end, $shared)
{
/** @var \FireflyIII\Helpers\Report\ReportQueryInterface $query */
$query = App::make('FireflyIII\Helpers\Report\ReportQueryInterface');
$object = new BudgetCollection;
/** @var \FireflyIII\Repositories\Budget\BudgetRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
$set = $repository->getBudgets();
$start = clone $date;
$start->startOfMonth();
$end = clone $date;
$end->endOfMonth();
$set = Auth::user()->budgets()->orderBy('budgets.name', 'ASC')
->leftJoin(
'budget_limits', function (JoinClause $join) use ($date) {
$join->on('budget_limits.budget_id', '=', 'budgets.id')->where('budget_limits.startdate', '=', $date->format('Y-m-d'));
}
)
->get(['budgets.*', 'budget_limits.amount as queryAmount']);
foreach ($set as $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';
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
// no repetition(s) for this budget:
if ($repetitions->count() == 0) {
$spent = $repository->spentInPeriodCorrected($budget, $start, $end, $shared);
$budgetLine = new BudgetLine;
$budgetLine->setBudget($budget);
$budgetLine->setOverspent($spent);
$object->addOverspent($spent);
$object->addBudgetLine($budgetLine);
continue;
}
// one or more repetitions for budget:
/** @var LimitRepetition $repetition */
foreach ($repetitions as $repetition) {
$budgetLine = new BudgetLine;
$budgetLine->setBudget($budget);
$budgetLine->setRepetition($repetition);
$expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, $shared);
$left = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0;
$spent = $expenses > floatval($repetition->amount) ? 0 : $expenses;
$overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0;
$budgetLine->setLeft($left);
$budgetLine->setSpent($spent);
$budgetLine->setOverspent($overspent);
$budgetLine->setBudgeted($repetition->amount);
$object->addBudgeted($repetition->amount);
$object->addSpent($spent);
$object->addLeft($left);
$object->addOverspent($overspent);
$object->addBudgetLine($budgetLine);
}
// find transactions to shared asset accounts, which are without a budget by default:
// which is only relevant when shared asset accounts are hidden.
if ($showSharedReports === false) {
$transfers = $query->sharedExpenses($start, $end)->sum('queryAmount');
$budgets[0]['spent'] += floatval($transfers) * -1;
}
return $budgets;
// stuff outside of budgets:
$noBudget = $repository->getWithoutBudgetSum($start, $end);
$budgetLine = new BudgetLine;
$budgetLine->setOverspent($noBudget);
$object->addOverspent($noBudget);
$object->addBudgetLine($budgetLine);
return $object;
}
/**
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return CategoryCollection
*/
public function getCategoryReport(Carbon $start, Carbon $end, $shared)
{
$object = new CategoryCollection;
/**
* GET CATEGORIES:
*/
/** @var \FireflyIII\Repositories\Category\CategoryRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Category\CategoryRepositoryInterface');
$set = $repository->getCategories();
foreach ($set as $category) {
$spent = $repository->spentInPeriodCorrected($category, $start, $end, $shared);
$category->spent = $spent;
$object->addCategory($category);
$object->addTotal($spent);
}
return $object;
}
/**
* Get a full report on the users expenses during the period.
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Expense
*/
public function getExpenseReport($start, $end, $shared)
{
$object = new Expense;
$set = $this->query->expenseInPeriodCorrected($start, $end, $shared);
foreach ($set as $entry) {
$object->addToTotal($entry->amount);
$object->addOrCreateExpense($entry);
}
return $object;
}
/**
* Get a full report on the users incomes during the period.
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Income
*/
public function getIncomeReport($start, $end, $shared)
{
$object = new Income;
$set = $this->query->incomeInPeriodCorrected($start, $end, $shared);
foreach ($set as $entry) {
$object->addToTotal($entry->amount);
$object->addOrCreateIncome($entry);
}
return $object;
}
/**
@@ -87,13 +377,14 @@ class ReportHelper implements ReportHelperInterface
*/
public function listOfMonths(Carbon $date)
{
$start = clone $date;
$end = Carbon::now();
$months = [];
while ($start <= $end) {
$year = $start->year;
$months[$year][] = [
'formatted' => $start->format('F Y'),
'formatted' => $start->formatLocalized('%B %Y'),
'month' => $start->month,
'year' => $year,
];
@@ -102,77 +393,4 @@ class ReportHelper implements ReportHelperInterface
return $months;
}
/**
* @param Carbon $date
*
* @return array
*/
public function listOfYears(Carbon $date)
{
$start = clone $date;
$end = Carbon::now();
$years = [];
while ($start <= $end) {
$years[] = $start->year;
$start->addYear();
}
$years[] = Carbon::now()->year;
// force the current year.
$years = array_unique($years);
return $years;
}
/**
* @param Carbon $date
* @param bool $showSharedReports
*
* @return array
*/
public function yearBalanceReport(Carbon $date, $showSharedReports = false)
{
$start = clone $date;
$end = clone $date;
$sharedAccounts = [];
if ($showSharedReports === false) {
$sharedCollection = Auth::user()->accounts()
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
->where('account_meta.name', '=', 'accountRole')
->where('account_meta.data', '=', json_encode('sharedAsset'))
->get(['accounts.id']);
foreach ($sharedCollection as $account) {
$sharedAccounts[] = $account->id;
}
}
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')->get(['accounts.*'])
->filter(
function (Account $account) use ($sharedAccounts) {
if (!in_array($account->id, $sharedAccounts)) {
return $account;
}
return null;
}
);
$report = [];
$start->startOfYear()->subDay();
$end->endOfYear();
foreach ($accounts as $account) {
$startBalance = Steam::balance($account, $start);
$endBalance = Steam::balance($account, $end);
$report[] = [
'start' => $startBalance,
'end' => $endBalance,
'hide' => ($startBalance == 0 && $endBalance == 0),
'account' => $account,
'shared' => $account->accountRole == 'sharedAsset'
];
}
return $report;
}
}

View File

@@ -3,7 +3,12 @@
namespace FireflyIII\Helpers\Report;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use FireflyIII\Helpers\Collection\Account;
use FireflyIII\Helpers\Collection\Balance;
use FireflyIII\Helpers\Collection\Budget as BudgetCollection;
use FireflyIII\Helpers\Collection\Category as CategoryCollection;
use FireflyIII\Helpers\Collection\Expense;
use FireflyIII\Helpers\Collection\Income;
/**
* Interface ReportHelperInterface
@@ -13,26 +18,78 @@ use Illuminate\Support\Collection;
interface ReportHelperInterface
{
/**
* This method generates a full report for the given period on all
* the users asset and cash accounts.
*
* @param Carbon $date
* @param Carbon $end
* @param boolean $shared
*
* @return Account
*/
public function getAccountReport(Carbon $date, Carbon $end, $shared);
/**
* This methods fails to take in account transfers FROM shared accounts.
* This method generates a full report for the given period on all
* the users bills and their payments.
*
* @param Carbon $start
* @param Carbon $end
* @param int $limit
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Collection
* @return Account
*/
public function expensesGroupedByAccount(Carbon $start, Carbon $end, $limit = 15);
public function getBillReport(Carbon $start, Carbon $end, $shared);
/**
* This method gets some kind of list for a monthly overview.
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @param Carbon $date
*
* @return Collection
* @return Balance
*/
public function getBudgetsForMonth(Carbon $date);
public function getBalanceReport(Carbon $start, Carbon $end, $shared);
/**
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return BudgetCollection
*/
public function getBudgetReport(Carbon $start, Carbon $end, $shared);
/**
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return CategoryCollection
*/
public function getCategoryReport(Carbon $start, Carbon $end, $shared);
/**
* Get a full report on the users expenses during the period.
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Expense
*/
public function getExpenseReport($start, $end, $shared);
/**
* Get a full report on the users incomes during the period.
*
* @param Carbon $start
* @param Carbon $end
* @param boolean $shared
*
* @return Income
*/
public function getIncomeReport($start, $end, $shared);
/**
* @param Carbon $date
@@ -41,18 +98,4 @@ interface ReportHelperInterface
*/
public function listOfMonths(Carbon $date);
/**
* @param Carbon $date
*
* @return array
*/
public function listOfYears(Carbon $date);
/**
* @param Carbon $date
* @param bool $showSharedReports
*
* @return array
*/
public function yearBalanceReport(Carbon $date, $showSharedReports = false);
}

View File

@@ -7,6 +7,7 @@ use Carbon\Carbon;
use Crypt;
use DB;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
@@ -21,101 +22,62 @@ use Steam;
*/
class ReportQuery implements ReportQueryInterface
{
/**
* This query retrieves a list of accounts that are active and not shared.
* See ReportQueryInterface::incomeInPeriodCorrected
*
* @param bool $showSharedReports
* @param Carbon $start
* @param Carbon $end
* @param bool $includeShared
*
* @return Collection
*
*/
public function accountList($showSharedReports = false)
public function expenseInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false)
{
$query = Auth::user()->accounts();
if ($showSharedReports === false) {
$query->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', "accountRole");
}
)->where(
$query = $this->queryJournalsWithTransactions($start, $end);
if ($includeShared === false) {
$query->where(
function (Builder $query) {
$query->where('account_meta.data', '!=', '"sharedAsset"');
$query->orWhereNull('account_meta.data');
$query->where(
function (Builder $q) { // only get withdrawals not from a shared account
$q->where('transaction_types.type', 'Withdrawal');
$q->where('acm_from.data', '!=', '"sharedAsset"');
}
);
$query->orWhere(
function (Builder $q) { // and transfers from a shared account.
$q->where('transaction_types.type', 'Transfer');
$q->where('acm_to.data', '=', '"sharedAsset"');
}
);
}
);
} else {
$query->where('transaction_types.type', 'Withdrawal'); // any withdrawal is fine.
}
$query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->whereIn('account_types.type', ['Default account', 'Cash account', 'Asset account'])
->where('active', 1)
->orderBy('accounts.name', 'ASC');
$query->orderBy('transaction_journals.date');
return $query->get(['accounts.*']);
}
// get everything
$data = $query->get(
['transaction_journals.*', 'transaction_types.type', 'ac_to.name as name', 'ac_to.id as account_id', 'ac_to.encrypted as account_encrypted']
);
/**
* This method will get a list of all expenses in a certain time period that have no budget
* and are balanced by a transfer to make up for it.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end)
{
$data->each(
function (TransactionJournal $journal) {
if (intval($journal->account_encrypted) == 1) {
$journal->name = Crypt::decrypt($journal->name);
}
}
);
$data = $data->filter(
function (TransactionJournal $journal) {
if ($journal->amount != 0) {
return $journal;
}
}
);
$set = TransactionJournal::
leftJoin('transaction_group_transaction_journal', 'transaction_group_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin(
'transaction_group_transaction_journal as otherFromGroup', function (JoinClause $join) {
$join->on('otherFromGroup.transaction_group_id', '=', 'transaction_group_transaction_journal.transaction_group_id')
->on('otherFromGroup.transaction_journal_id', '!=', 'transaction_journals.id');
}
)
->leftJoin('transaction_journals as otherJournals', 'otherJournals.id', '=', 'otherFromGroup.transaction_journal_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'otherJournals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('amount', '>', 0);
}
)
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'otherJournals.id')
->before($end)->after($start)
->where('transaction_types.type', 'Withdrawal')
->where('transaction_journals.user_id', Auth::user()->id)
->whereNull('budget_transaction_journal.budget_id')->whereNull('transaction_journals.deleted_at')
->whereNull('otherJournals.deleted_at')
->where('transactions.account_id', $account->id)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->whereNotNull('transaction_group_transaction_journal.transaction_group_id')
->get(
[
'transaction_journals.*',
'transactions.amount as queryAmount'
]
);
return $set;
}
/**
* This method will get the sum of all expenses in a certain time period that have no budget
* and are balanced by a transfer to make up for it.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return float
*/
public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end)
{
return floatval($this->balancedTransactionsList($account, $start, $end)->sum('queryAmount'));
return $data;
}
/**
@@ -123,15 +85,15 @@ class ReportQuery implements ReportQueryInterface
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
* @param bool $includeShared
*
* @return Collection
*/
public function getAllAccounts(Carbon $start, Carbon $end, $showSharedReports = false)
public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = false)
{
$query = Auth::user()->accounts()->orderBy('accounts.name', 'ASC')
->accountTypeIn(['Default account', 'Asset account', 'Cash account']);
if ($showSharedReports === false) {
if ($includeShared === false) {
$query->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
@@ -167,55 +129,27 @@ class ReportQuery implements ReportQueryInterface
return $set;
}
/**
* Grabs a summary of all expenses grouped by budget, related to the account.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
*/
public function getBudgetSummary(Account $account, Carbon $start, Carbon $end)
{
$query = $this->queryJournalsNoBudget($account, $start, $end);
return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) as `queryAmount`')]);
}
/**
* Get a list of transaction journals that have no budget, filtered for the specified account
* and the specified date range.
* This method works the same way as ReportQueryInterface::incomeInPeriod does, but instead of returning results
* will simply list the transaction journals only. This should allow any follow up counting to be accurate with
* regards to tags.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function getTransactionsWithoutBudget(Account $account, Carbon $start, Carbon $end)
{
$query = $this->queryJournalsNoBudget($account, $start, $end);
return $query->get(['budgets.name', 'transactions.amount as queryAmount', 'transaction_journals.*']);
}
/**
* This method returns all "income" journals in a certain period, which are both transfers from a shared account
* and "ordinary" deposits. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does
* not group and returns different fields.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
* @param bool $includeShared
*
* @return Collection
*/
public function incomeByPeriod(Carbon $start, Carbon $end, $showSharedReports = false)
public function incomeInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false)
{
$query = $this->queryJournalsWithTransactions($start, $end);
if ($showSharedReports === false) {
if ($includeShared === false) {
// only get deposits not to a shared account
// and transfers to a shared account.
$query->where(
@@ -238,219 +172,25 @@ class ReportQuery implements ReportQueryInterface
// any deposit is fine.
$query->where('transaction_types.type', 'Deposit');
}
$query->groupBy('transaction_journals.id')->orderBy('transaction_journals.date');
$query->orderBy('transaction_journals.date');
// get everything, decrypt and return
// get everything
$data = $query->get(
['transaction_journals.id',
'transaction_journals.description',
'transaction_journals.encrypted',
'transaction_types.type',
DB::Raw('SUM(`t_to`.`amount`) as `queryAmount`'),
'transaction_journals.date',
't_from.account_id as account_id',
'ac_from.name as name',
'ac_from.encrypted as account_encrypted'
]
['transaction_journals.*', 'transaction_types.type', 'ac_from.name as name', 'ac_from.id as account_id', 'ac_from.encrypted as account_encrypted']
);
$data->each(
function (Model $object) {
$object->name = intval($object->account_encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
}
);
return $data;
}
/**
* Gets a list of expenses grouped by the budget they were filed under.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByBudget(Carbon $start, Carbon $end, $showSharedReports = false)
{
$query = Auth::user()->transactionjournals()
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id');
if ($showSharedReports === false) {
$query->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)->where('account_meta.data', '!=', '"sharedAsset"');
}
$query->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->where('transaction_types.type', 'Withdrawal')
->groupBy('budgets.id')
->orderBy('budgets.name', 'ASC');
return $query->get(['budgets.id', 'budgets.name', DB::Raw('SUM(`transactions`.`amount`) AS `spent`')]);
}
/**
* Gets a list of categories and the expenses therein, grouped by the relevant category.
* This result excludes transfers to shared accounts which are expenses, technically.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByCategory(Carbon $start, Carbon $end, $showSharedReports = false)
{
$query = Auth::user()->transactionjournals()
->leftJoin(
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
)
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id');
if ($showSharedReports === false) {
$query->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)->where('account_meta.data', '!=', '"sharedAsset"');
}
$query->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->where('transaction_types.type', 'Withdrawal')
->groupBy('categories.id')
->orderBy('queryAmount');
$data = $query->get(['categories.id', 'categories.encrypted', 'categories.name', DB::Raw('SUM(`transactions`.`amount`) AS `queryAmount`')]);
// decrypt data:
$data->each(
function (Model $object) {
$object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
}
);
return $data;
}
/**
* Gets a list of expense accounts and the expenses therein, grouped by that expense account.
* This result excludes transfers to shared accounts which are expenses, technically.
*
* So now it will include them!
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByExpenseAccount(Carbon $start, Carbon $end, $showSharedReports = false)
{
$query = $this->queryJournalsWithTransactions($start, $end);
if ($showSharedReports === false) {
// get all withdrawals not from a shared accounts
// and all transfers to a shared account
$query->where(
function (Builder $query) {
$query->where(
function (Builder $q) {
$q->where('transaction_types.type', 'Withdrawal');
$q->where('acm_from.data', '!=', '"sharedAsset"');
}
);
$query->orWhere(
function (Builder $q) {
$q->where('transaction_types.type', 'Transfer');
$q->where('acm_to.data', '=', '"sharedAsset"');
}
);
function (TransactionJournal $journal) {
if (intval($journal->account_encrypted) == 1) {
$journal->name = Crypt::decrypt($journal->name);
}
);
} else {
// any withdrawal goes:
$query->where('transaction_types.type', 'Withdrawal');
}
$query->before($end)->after($start)
->where('transaction_journals.user_id', Auth::user()->id)
->groupBy('t_to.account_id')
->orderBy('queryAmount', 'DESC');
$data = $query->get(['t_to.account_id as id', 'ac_to.name as name', 'ac_to.encrypted', DB::Raw('SUM(t_to.amount) as `queryAmount`')]);
// decrypt
$data->each(
function (Model $object) {
$object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
}
);
return $data;
}
/**
* This method returns all deposits into asset accounts, grouped by the revenue account,
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByRevenueAccount(Carbon $start, Carbon $end, $showSharedReports = false)
{
$query = $this->queryJournalsWithTransactions($start, $end);
if ($showSharedReports === false) {
// show queries where transfer type is deposit, and its not to a shared account
// or where its a transfer and its from a shared account (both count as incomes)
$query->where(
function (Builder $query) {
$query->where(
function (Builder $q) {
$q->where('transaction_types.type', 'Deposit');
$q->where('acm_to.data', '!=', '"sharedAsset"');
}
);
$query->orWhere(
function (Builder $q) {
$q->where('transaction_types.type', 'Transfer');
$q->where('acm_from.data', '=', '"sharedAsset"');
}
);
$data = $data->filter(
function (TransactionJournal $journal) {
if ($journal->amount != 0) {
return $journal;
}
);
} else {
// any deposit goes:
$query->where('transaction_types.type', 'Deposit');
}
$query->groupBy('t_from.account_id')->orderBy('queryAmount');
$data = $query->get(
['t_from.account_id as account_id', 'ac_from.name as name', 'ac_from.encrypted as encrypted', DB::Raw('SUM(t_from.amount) as `queryAmount`')]
);
// decrypt
$data->each(
function (Model $object) {
$object->name = intval($object->encrypted) == 1 ? Crypt::decrypt($object->name) : $object->name;
}
);
@@ -458,119 +198,53 @@ class ReportQuery implements ReportQueryInterface
}
/**
* With an equally misleading name, this query returns are transfers to shared accounts. These are considered
* expenses.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function sharedExpenses(Carbon $start, Carbon $end)
{
return TransactionJournal::
leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where(
'transactions.amount', '>', 0
);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)
->where('account_meta.data', '"sharedAsset"')
->after($start)
->before($end)
->where('transaction_types.type', 'Transfer')
->where('transaction_journals.user_id', Auth::user()->id)
->get(
['transaction_journals.id', 'transaction_journals.description', 'transactions.account_id', 'accounts.name',
'transactions.amount as queryAmount']
);
}
/**
* With a slightly misleading name, this query returns all transfers to shared accounts
* which are technically expenses, since it won't be just your money that gets spend.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function sharedExpensesByCategory(Carbon $start, Carbon $end)
{
return TransactionJournal::
leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where(
'transactions.amount', '>', 0
);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin(
'account_meta', function (JoinClause $join) {
$join->on('account_meta.account_id', '=', 'accounts.id')->where('account_meta.name', '=', 'accountRole');
}
)
->leftJoin(
'category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'
)
->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id')
->where('account_meta.data', '"sharedAsset"')
->after($start)
->before($end)
->where('transaction_types.type', 'Transfer')
->where('transaction_journals.user_id', Auth::user()->id)
->groupBy('categories.name')
->get(
[
'categories.id',
'categories.name as name',
DB::Raw('SUM(`transactions`.`amount`) * -1 AS `queryAmount`')
]
);
}
/**
*
* This query will get all transaction journals and budget information for a specified account
* in a certain date range, where the transaction journal does not have a budget.
* There is no get() specified, this is up to the method itself.
* Covers tags
*
* @param Account $account
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return Builder
* @return float
*/
protected function queryJournalsNoBudget(Account $account, Carbon $start, Carbon $end)
public function spentInBudgetCorrected(Account $account, Budget $budget, Carbon $start, Carbon $end)
{
return TransactionJournal::
leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '<', 0);
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->before($end)
->after($start)
->where('accounts.id', $account->id)
->where('transaction_journals.user_id', Auth::user()->id)
->where('transaction_types.type', 'Withdrawal')
->groupBy('budgets.id')
->orderBy('budgets.name', 'ASC');
return floatval(
Auth::user()->transactionjournals()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->transactionTypes(['Withdrawal'])
->where('transactions.account_id', $account->id)
->before($end)
->after($start)
->where('budget_transaction_journal.budget_id', $budget->id)
->get(['transaction_journals.*'])->sum('amount')
) * -1;
}
/**
* @param Account $account
* @param Carbon $start
* @param Carbon $end
* @param bool $shared
*
* @return float
*/
public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false)
{
return floatval(
Auth::user()->transactionjournals()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.amount', '<', 0)
->transactionTypes(['Withdrawal'])
->where('transactions.account_id', $account->id)
->before($end)
->after($start)
->whereNull('budget_transaction_journal.budget_id')
->sum('transactions.amount')
);
}
/**
@@ -609,5 +283,4 @@ class ReportQuery implements ReportQueryInterface
return $query;
}
}

View File

@@ -4,6 +4,7 @@ namespace FireflyIII\Helpers\Report;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use Illuminate\Support\Collection;
/**
@@ -15,152 +16,66 @@ interface ReportQueryInterface
{
/**
* This query retrieves a list of accounts that are active and not shared.
* See ReportQueryInterface::incomeInPeriodCorrected
*
* @param bool $showSharedReports
* This method returns all "expense" journals in a certain period, which are both transfers to a shared account
* and "ordinary" withdrawals. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does
* not group and returns different fields.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $includeShared
*
* @return Collection
*
*/
public function accountList($showSharedReports = false);
/**
* This method will get a list of all expenses in a certain time period that have no budget
* and are balanced by a transfer to make up for it.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function balancedTransactionsList(Account $account, Carbon $start, Carbon $end);
/**
* This method will get the sum of all expenses in a certain time period that have no budget
* and are balanced by a transfer to make up for it.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
*
* @return float
*/
public function balancedTransactionsSum(Account $account, Carbon $start, Carbon $end);
public function expenseInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false);
/**
* Get a users accounts combined with various meta-data related to the start and end date.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
* @param bool $includeShared
*
* @return Collection
*/
public function getAllAccounts(Carbon $start, Carbon $end, $showSharedReports = false);
public function getAllAccounts(Carbon $start, Carbon $end, $includeShared = false);
/**
* Grabs a summary of all expenses grouped by budget, related to the account.
* This method works the same way as ReportQueryInterface::incomeInPeriod does, but instead of returning results
* will simply list the transaction journals only. This should allow any follow up counting to be accurate with
* regards to tags.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $includeShared
*
* @return Collection
*/
public function incomeInPeriodCorrected(Carbon $start, Carbon $end, $includeShared = false);
/**
* Covers tags as well.
*
* @param Account $account
* @param Budget $budget
* @param Carbon $start
* @param Carbon $end
*
* @return mixed
* @return float
*/
public function getBudgetSummary(Account $account, Carbon $start, Carbon $end);
public function spentInBudgetCorrected(Account $account, Budget $budget, Carbon $start, Carbon $end);
/**
* Get a list of transaction journals that have no budget, filtered for the specified account
* and the specified date range.
*
* @param Account $account
* @param Carbon $start
* @param Carbon $end
* @param bool $shared
*
* @return Collection
* @return float
*/
public function getTransactionsWithoutBudget(Account $account, Carbon $start, Carbon $end);
public function spentNoBudget(Account $account, Carbon $start, Carbon $end, $shared = false);
/**
* This method returns all "income" journals in a certain period, which are both transfers from a shared account
* and "ordinary" deposits. The query used is almost equal to ReportQueryInterface::journalsByRevenueAccount but it does
* not group and returns different fields.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function incomeByPeriod(Carbon $start, Carbon $end, $showSharedReports = false);
/**
* Gets a list of expenses grouped by the budget they were filed under.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByBudget(Carbon $start, Carbon $end, $showSharedReports = false);
/**
* Gets a list of categories and the expenses therein, grouped by the relevant category.
* This result excludes transfers to shared accounts which are expenses, technically.
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByCategory(Carbon $start, Carbon $end, $showSharedReports = false);
/**
* Gets a list of expense accounts and the expenses therein, grouped by that expense account.
* This result excludes transfers to shared accounts which are expenses, technically.
*
* So now it will include them!
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByExpenseAccount(Carbon $start, Carbon $end, $showSharedReports = false);
/**
* This method returns all deposits into asset accounts, grouped by the revenue account,
*
* @param Carbon $start
* @param Carbon $end
* @param bool $showSharedReports
*
* @return Collection
*/
public function journalsByRevenueAccount(Carbon $start, Carbon $end, $showSharedReports = false);
/**
* With an equally misleading name, this query returns are transfers to shared accounts. These are considered
* expenses.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function sharedExpenses(Carbon $start, Carbon $end);
/**
* With a slightly misleading name, this query returns all transfers to shared accounts
* which are technically expenses, since it won't be just your money that gets spend.
*
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
public function sharedExpensesByCategory(Carbon $start, Carbon $end);
}

View File

@@ -28,7 +28,7 @@ class AccountController extends Controller
{
parent::__construct();
View::share('mainTitleIcon', 'fa-credit-card');
View::share('title', 'Accounts');
View::share('title', trans('firefly.accounts'));
}
/**
@@ -96,7 +96,7 @@ class AccountController extends Controller
{
$what = Config::get('firefly.shortNamesByFullName')[$account->accountType->type];
$subTitle = 'Edit ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
$subTitle = trans('firefly.edit_' . $what . '_account', ['name' => $account->name]);
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$openingBalance = $repository->openingBalanceTransaction($account);
@@ -137,7 +137,7 @@ class AccountController extends Controller
*/
public function index(AccountRepositoryInterface $repository, $what)
{
$subTitle = Config::get('firefly.subTitlesByIdentifier.' . $what);
$subTitle = trans('firefly.' . $what . '_accounts');
$subTitleIcon = Config::get('firefly.subIconsByIdentifier.' . $what);
$types = Config::get('firefly.accountTypesByIdentifier.' . $what);
$accounts = $repository->getAccounts($types);
@@ -170,7 +170,7 @@ class AccountController extends Controller
$subTitleIcon = Config::get('firefly.subTitlesByIdentifier.' . $account->accountType->type);
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$journals = $repository->getJournals($account, $page);
$subTitle = 'Details for ' . strtolower(e($account->accountType->type)) . ' "' . e($account->name) . '"';
$subTitle = trans('firefly.details_for_' . $what, ['name' => $account->name]);
$journals->setPath('accounts/show/' . $account->id);

View File

@@ -39,6 +39,8 @@ class AuthController extends Controller
* @param \Illuminate\Contracts\Auth\Guard $auth
* @param \Illuminate\Contracts\Auth\Registrar $registrar
*
* @codeCoverageIgnore
*
*/
public function __construct(Guard $auth, Registrar $registrar)
{
@@ -51,7 +53,9 @@ class AuthController extends Controller
/**
* Show the application login form.
*
* @codeCoverageIgnore
* @return \Illuminate\Http\Response
*
*/
public function getLogin()
{
@@ -73,7 +77,9 @@ class AuthController extends Controller
$this->throwValidationException(
$request, $validator
);
// @codeCoverageIgnoreStart
}
// @codeCoverageIgnoreEnd
$data = $request->all();
$data['password'] = bcrypt($data['password']);

View File

@@ -8,6 +8,7 @@ use Illuminate\Foundation\Auth\ResetsPasswords;
/**
* Class PasswordController
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Controllers\Auth
*/
class PasswordController extends Controller

View File

@@ -7,7 +7,6 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use Input;
use Redirect;
@@ -29,54 +28,10 @@ class BillController extends Controller
public function __construct()
{
parent::__construct();
View::share('title', 'Bills');
View::share('title', trans('firefly.bills'));
View::share('mainTitleIcon', 'fa-calendar-o');
}
/**
* @param AccountRepositoryInterface $repository
* @param Bill $bill
*
* @return \Illuminate\Http\RedirectResponse
*/
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'));
foreach ($matches as $match) {
$match = strtolower($match);
// find expense account for each word if not found already:
if (is_null($expense)) {
/** @var Account $account */
foreach ($accounts as $account) {
$name = strtolower($account->name);
if (!(strpos($name, $match) === false)) {
$expense = $account;
break;
}
}
}
if (is_null($expense)) {
$description[] = $match;
}
}
$parameters = [
'description' => ucfirst(join(' ', $description)),
'expense_account' => is_null($expense) ? '' : $expense->name,
'amount' => round(($bill->amount_min + $bill->amount_max), 2),
];
Session::put('preFilled', $parameters);
return Redirect::to(route('transactions.create', 'withdrawal'));
}
/**
* @return $this
*/

View File

@@ -29,7 +29,7 @@ class BudgetController extends Controller
public function __construct()
{
parent::__construct();
View::share('title', 'Budgets');
View::share('title', trans('firefly.budgets'));
View::share('mainTitleIcon', 'fa-tasks');
View::share('hideBudgets', true);
}
@@ -60,7 +60,7 @@ class BudgetController extends Controller
Session::put('budgets.create.url', URL::previous());
}
Session::forget('budgets.create.fromStore');
$subTitle = 'Create a new budget';
$subTitle = trans('firefly.create_new_budget');
return view('budgets.create', compact('subTitle'));
}
@@ -137,7 +137,8 @@ class BudgetController extends Controller
$budgets->each(
function (Budget $budget) use ($repository) {
$date = Session::get('start', Carbon::now()->startOfMonth());
$budget->spent = $repository->spentInMonth($budget, $date);
$end = Session::get('end', Carbon::now()->endOfMonth());
$budget->spent = $repository->spentInPeriodCorrected($budget, $date, $end);
$budget->currentRep = $repository->getCurrentRepetition($budget, $date);
}
);

View File

@@ -26,7 +26,7 @@ class CategoryController extends Controller
public function __construct()
{
parent::__construct();
View::share('title', 'Categories');
View::share('title', trans('firefly.categories'));
View::share('mainTitleIcon', 'fa-bar-chart');
}

View File

@@ -0,0 +1,150 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Preferences;
use Response;
use Session;
use Steam;
/**
* Class AccountController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class AccountController extends Controller
{
/**
* Shows the balances for all the user's accounts.
*
* @param GChart $chart
* @param AccountRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function all(GChart $chart, AccountRepositoryInterface $repository, $year, $month, $shared = false)
{
$start = new Carbon($year . '-' . $month . '-01');
$end = clone $start;
$end->endOfMonth();
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
/** @var Collection $accounts */
$accounts = $repository->getAccounts(['Default account', 'Asset account']);
if ($shared === false) {
// remove the shared accounts from the collection:
/** @var Account $account */
foreach ($accounts as $index => $account) {
if ($account->getMeta('accountRole') == 'sharedAsset') {
$accounts->forget($index);
}
}
}
$index = 1;
/** @var Account $account */
foreach ($accounts as $account) {
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
$chart->addCertainty($index);
$index++;
}
$current = clone $start;
$current->subDay();
$today = Carbon::now();
while ($end >= $current) {
$row = [clone $current];
$certain = $current < $today;
foreach ($accounts as $account) {
$row[] = Steam::balance($account, $current);
$row[] = $certain;
}
$chart->addRowArray($row);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Shows the balances for all the user's frontpage accounts.
*
* @param GChart $chart
* @param AccountRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(GChart $chart, AccountRepositoryInterface $repository)
{
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
$frontPage = Preferences::get('frontPageAccounts', []);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$accounts = $repository->getFrontpageAccounts($frontPage);
$index = 1;
/** @var Account $account */
foreach ($accounts as $account) {
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
$chart->addCertainty($index);
$index++;
}
$current = clone $start;
$current->subDay();
$today = Carbon::now();
while ($end >= $current) {
$row = [clone $current];
$certain = $current < $today;
foreach ($accounts as $account) {
$row[] = Steam::balance($account, $current);
$row[] = $certain;
}
$chart->addRowArray($row);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Shows an account's balance for a single month.
*
* @param GChart $chart
* @param Account $account
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function single(GChart $chart, Account $account)
{
$chart->addColumn(trans('firefly.dayOfMonth'), 'date');
$chart->addColumn(trans('firefly.balanceFor', ['name' => $account->name]), 'number');
$chart->addCertainty(1);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$current = clone $start;
$today = new Carbon;
while ($end >= $current) {
$certain = $current < $today;
$chart->addRow(clone $current, Steam::balance($account, $current), $certain);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -0,0 +1,141 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Response;
use Session;
use Steam;
/**
* Class BillController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class BillController extends Controller
{
/**
* Shows the overview for a bill. The min/max amount and matched journals.
*
* @param GChart $chart
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function single(GChart $chart, BillRepositoryInterface $repository, Bill $bill)
{
$chart->addColumn(trans('firefly.date'), 'date');
$chart->addColumn(trans('firefly.maxAmount'), 'number');
$chart->addColumn(trans('firefly.minAmount'), 'number');
$chart->addColumn(trans('firefly.billEntry'), 'number');
// get first transaction or today for start:
$results = $repository->getJournals($bill);
/** @var TransactionJournal $result */
foreach ($results as $result) {
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Shows all bills and whether or not theyve been paid this month (pie chart).
*
* @param GChart $chart
*
* @param BillRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
{
$chart->addColumn(trans('firefly.name'), 'string');
$chart->addColumn(trans('firefly.amount'), 'number');
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$bills = $repository->getActiveBills();
$paid = new Collection; // journals.
$unpaid = new Collection; // bills
// loop paid and create single entry:
$paidDescriptions = [];
$paidAmount = 0;
$unpaidDescriptions = [];
$unpaidAmount = 0;
/** @var Bill $bill */
foreach ($bills as $bill) {
$ranges = $repository->getRanges($bill, $start, $end);
foreach ($ranges as $range) {
// paid a bill in this range?
$journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']);
if ($journals->count() == 0) {
$unpaid->push([$bill, $range['start']]);
} else {
$paid = $paid->merge($journals);
}
}
}
$creditCards = $accounts->getCreditCards();
foreach ($creditCards as $creditCard) {
$balance = Steam::balance($creditCard, $end, true);
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
if ($balance < 0) {
// unpaid! create a fake bill that matches the amount.
$description = $creditCard->name;
$amount = $balance * -1;
$fakeBill = $repository->createFakeBill($description, $date, $amount);
unset($description, $amount);
$unpaid->push([$fakeBill, $date]);
}
if ($balance == 0) {
// find transfer(s) TO the credit card which should account for
// anything paid. If not, the CC is not yet used.
$journals = $accounts->getTransfersInRange($creditCard, $start, $end);
$paid = $paid->merge($journals);
}
}
/** @var TransactionJournal $entry */
foreach ($paid as $entry) {
$paidDescriptions[] = $entry->description;
$paidAmount += floatval($entry->amount);
}
// loop unpaid:
/** @var Bill $entry */
foreach ($unpaid as $entry) {
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
$unpaidDescriptions[] = $description;
$unpaidAmount += $amount;
unset($amount, $description);
}
$chart->addRow(trans('firefly.unpaid') . ': ' . join(', ', $unpaidDescriptions), $unpaidAmount);
$chart->addRow(trans('firefly.paid') . ': ' . join(', ', $paidDescriptions), $paidAmount);
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -0,0 +1,195 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Navigation;
use Preferences;
use Response;
use Session;
/**
* Class BudgetController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class BudgetController extends Controller
{
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
*/
public function budget(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget)
{
$chart->addColumn(trans('firefly.period'), 'date');
$chart->addColumn(trans('firefly.spent'), 'number');
$first = $repository->getFirstBudgetLimitDate($budget);
$range = $viewRange = Preferences::get('viewRange', '1M')->data;
$last = Session::get('end', new Carbon);
$final = clone $last;
$final->addYears(2);
$last = Navigation::endOfX($last, $range, $final);
while ($first < $last) {
$end = Navigation::addPeriod($first, $range, 0);
$spent = $repository->spentInPeriodCorrected($budget, $first, $end);
$chart->addRow($end, $spent);
$first = Navigation::addPeriod($first, $range, 0);
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Shows the amount left in a specific budget limit.
*
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function budgetLimit(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
{
$start = clone $repetition->startdate;
$end = $repetition->enddate;
$chart->addColumn(trans('firefly.day'), 'date');
$chart->addColumn(trans('firefly.left'), 'number');
$amount = $repetition->amount;
while ($start <= $end) {
/*
* Sum of expenses on this day:
*/
$sum = $repository->expensesOnDayCorrected($budget, $start);
$amount += $sum;
$chart->addRow(clone $start, $amount);
$start->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Shows a budget list with spent/left/overspent.
*
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(GChart $chart, BudgetRepositoryInterface $repository)
{
$chart->addColumn(trans('firefly.budget'), 'string');
$chart->addColumn(trans('firefly.left'), 'number');
$chart->addColumn(trans('firefly.spent'), 'number');
$chart->addColumn(trans('firefly.overspent'), 'number');
$budgets = $repository->getBudgets();
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$allEntries = new Collection;
foreach ($budgets as $budget) {
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
if ($repetitions->count() == 0) {
$expenses = $repository->spentInPeriodCorrected($budget, $start, $end, true);
$allEntries->push([$budget->name, 0, 0, $expenses]);
continue;
}
/** @var LimitRepetition $repetition */
foreach ($repetitions as $repetition) {
$expenses = $repository->spentInPeriodCorrected($budget, $repetition->startdate, $repetition->enddate, true);
$left = $expenses < floatval($repetition->amount) ? floatval($repetition->amount) - $expenses : 0;
$spent = $expenses > floatval($repetition->amount) ? floatval($repetition->amount) : $expenses;
$overspent = $expenses > floatval($repetition->amount) ? $expenses - floatval($repetition->amount) : 0;
$allEntries->push(
[$budget->name . ' (' . $repetition->startdate->formatLocalized($this->monthAndDayFormat) . ')',
$left,
$spent,
$overspent
]
);
}
}
$noBudgetExpenses = $repository->getWithoutBudgetSum($start, $end);
$allEntries->push([trans('firefly.noBudget'), 0, 0, $noBudgetExpenses]);
foreach ($allEntries as $entry) {
if ($entry[1] != 0 || $entry[2] != 0 || $entry[3] != 0) {
$chart->addRow($entry[0], $entry[1], $entry[2], $entry[3]);
}
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Show a yearly overview for a budget.
*
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function year(GChart $chart, BudgetRepositoryInterface $repository, $year, $shared = false)
{
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false;
$budgets = $repository->getBudgets();
// add columns:
$chart->addColumn(trans('firefly.month'), 'date');
foreach ($budgets as $budget) {
$chart->addColumn($budget->name, 'number');
}
while ($start < $end) {
// month is the current end of the period:
$month = clone $start;
$month->endOfMonth();
// make a row:
$row = [clone $start];
// each budget, fill the row:
foreach ($budgets as $budget) {
$spent = $repository->spentInPeriodCorrected($budget, $start, $month, $shared);
$row[] = $spent;
}
$chart->addRowArray($row);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -0,0 +1,180 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\Preference;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Navigation;
use Preferences;
use Response;
use Session;
/**
* Class CategoryController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class CategoryController extends Controller
{
/**
* Show an overview for a category for all time, per month/week/year.
*
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function all(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{
// oldest transaction in category:
$start = $repository->getFirstActivityDate($category);
$range = Preferences::get('viewRange', '1M')->data;
// jump to start of week / month / year / etc
$start = Navigation::startOfPeriod($start, $range);
$chart->addColumn(trans('firefly.period'), 'date');
$chart->addColumn(trans('firefly.spent'), 'number');
$end = new Carbon;
while ($start <= $end) {
$currentEnd = Navigation::endOfPeriod($start, $range);
$spent = $repository->spentInPeriodCorrected($category, $start, $currentEnd);
$chart->addRow(clone $start, $spent);
$start = Navigation::addPeriod($start, $range, 0);
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Show this month's category overview.
*
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function frontpage(GChart $chart, CategoryRepositoryInterface $repository)
{
$chart->addColumn(trans('firefly.category'), 'string');
$chart->addColumn(trans('firefly.spent'), 'number');
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$set = $repository->getCategoriesAndExpensesCorrected($start, $end);
// sort by callback:
uasort(
$set,
function ($left, $right) {
if ($left['sum'] == $right['sum']) {
return 0;
}
return ($left['sum'] < $right['sum']) ? 1 : -1;
}
);
foreach ($set as $entry) {
$sum = floatval($entry['sum']);
if ($sum != 0) {
$chart->addRow($entry['name'], $sum);
}
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function month(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$chart->addColumn(trans('firefly.period'), 'date');
$chart->addColumn(trans('firefly.spent'), 'number');
while ($start <= $end) {
$spent = $repository->spentOnDaySumCorrected($category, $start);
$chart->addRow(clone $start, $spent);
$start->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* This chart will only show expenses.
*
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function year(GChart $chart, CategoryRepositoryInterface $repository, $year, $shared = false)
{
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false;
$categories = $repository->getCategories();
// add columns:
$chart->addColumn(trans('firefly.month'), 'date');
foreach ($categories as $category) {
$chart->addColumn($category->name, 'number');
}
while ($start < $end) {
// month is the current end of the period:
$month = clone $start;
$month->endOfMonth();
// make a row:
$row = [clone $start];
// each budget, fill the row:
foreach ($categories as $category) {
$spent = $repository->spentInPeriodCorrected($category, $start, $month, $shared);
$row[] = $spent;
}
$chart->addRowArray($row);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* Created by PhpStorm.
* User: sander
* Date: 16/05/15
* Time: 09:36
*/
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Response;
/**
* Class PiggyBankController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class PiggyBankController extends Controller
{
/**
* Shows the piggy bank history.
*
* @param GChart $chart
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function history(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
$chart->addColumn(trans('firefly.date'), 'date');
$chart->addColumn(trans('firefly.balance'), 'number');
/** @var Collection $set */
$set = $repository->getEventSummarySet($piggyBank);
$sum = 0;
foreach ($set as $entry) {
$sum += floatval($entry->sum);
$chart->addRow(new Carbon($entry->date), $sum);
}
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace FireflyIII\Http\Controllers\Chart;
use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Http\Controllers\Controller;
use Grumpydictator\Gchart\GChart;
use Response;
/**
* Class ReportController
*
* @package FireflyIII\Http\Controllers\Chart
*/
class ReportController extends Controller
{
/**
* Summarizes all income and expenses, per month, for a given year.
*
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInOut(GChart $chart, ReportQueryInterface $query, $year, $shared = false)
{
// get start and end of year
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false;
$chart->addColumn(trans('firefly.month'), 'date');
$chart->addColumn(trans('firefly.income'), 'number');
$chart->addColumn(trans('firefly.expenses'), 'number');
while ($start < $end) {
$month = clone $start;
$month->endOfMonth();
// total income and total expenses:
$incomeSum = floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'));
$expenseSum = floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'));
$chart->addRow(clone $start, $incomeSum, $expenseSum);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* Summarizes all income and expenses for a given year. Gives a total and an average.
*
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
* @param bool $shared
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInOutSummarized(GChart $chart, ReportQueryInterface $query, $year, $shared = false)
{
$start = new Carbon($year . '-01-01');
$end = new Carbon($year . '-12-31');
$shared = $shared == 'shared' ? true : false;
$income = 0;
$expense = 0;
$count = 0;
$chart->addColumn(trans('firefly.summary'), 'string');
$chart->addColumn(trans('firefly.income'), 'number');
$chart->addColumn(trans('firefly.expenses'), 'number');
while ($start < $end) {
$month = clone $start;
$month->endOfMonth();
// total income and total expenses:
$income += floatval($query->incomeInPeriodCorrected($start, $month, $shared)->sum('amount'));
$expense += floatval($query->expenseInPeriodCorrected($start, $month, $shared)->sum('amount'));
$count++;
$start->addMonth();
}
// add total + average:
$chart->addRow(trans('firefly.sum'), $income, $expense);
$count = $count > 0 ? $count : 1;
$chart->addRow(trans('firefly.average'), ($income / $count), ($expense / $count));
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -1,8 +1,11 @@
<?php namespace FireflyIII\Http\Controllers;
use Auth;
use Config;
use Illuminate\Foundation\Bus\DispatchesCommands;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Preferences;
use View;
/**
@@ -15,6 +18,11 @@ abstract class Controller extends BaseController
use DispatchesCommands, ValidatesRequests;
/** @var string */
protected $monthAndDayFormat;
/** @var string */
protected $monthFormat;
/**
*
*/
@@ -24,5 +32,16 @@ abstract class Controller extends BaseController
View::share('hideCategories', false);
View::share('hideBills', false);
View::share('hideTags', false);
if (Auth::check()) {
$pref = Preferences::get('language', 'en');
$lang = $pref->data;
$this->monthFormat = Config::get('firefly.month.' . $lang);
$this->monthAndDayFormat = Config::get('firefly.monthAndDay.' . $lang);
View::share('monthFormat', $this->monthFormat);
View::share('monthAndDayFormat', $this->monthAndDayFormat);
View::share('language', $lang);
}
}
}

View File

@@ -28,7 +28,7 @@ class CurrencyController extends Controller
public function __construct()
{
parent::__construct();
View::share('title', 'Currencies');
View::share('title', trans('firefly.currencies'));
View::share('mainTitleIcon', 'fa-usd');
}

View File

@@ -1,588 +0,0 @@
<?php namespace FireflyIII\Http\Controllers;
use Carbon\Carbon;
use Crypt;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Budget;
use FireflyIII\Models\Category;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\Preference;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Grumpydictator\Gchart\GChart;
use Illuminate\Support\Collection;
use Navigation;
use Preferences;
use Response;
use Session;
use Steam;
/**
* Class GoogleChartController
*
* @package FireflyIII\Http\Controllers
*/
class GoogleChartController extends Controller
{
/**
* @param GChart $chart
* @param Account $account
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function accountBalanceChart(GChart $chart, Account $account)
{
$chart->addColumn('Day of month', 'date');
$chart->addColumn('Balance for ' . $account->name, 'number');
$chart->addCertainty(1);
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$current = clone $start;
$today = new Carbon;
while ($end >= $current) {
$certain = $current < $today;
$chart->addRow(clone $current, Steam::balance($account, $current), $certain);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param AccountRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
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);
$index = 1;
/** @var Account $account */
foreach ($accounts as $account) {
$chart->addColumn('Balance for ' . $account->name, 'number');
$chart->addCertainty($index);
$index++;
}
$current = clone $start;
$current->subDay();
$today = Carbon::now();
while ($end >= $current) {
$row = [clone $current];
$certain = $current < $today;
foreach ($accounts as $account) {
$row[] = Steam::balance($account, $current);
$row[] = $certain;
}
$chart->addRowArray($row);
$current->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param $year
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allBudgetsAndSpending(GChart $chart, BudgetRepositoryInterface $repository, $year)
{
$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) {
$spent = $repository->spentInMonth($budget, $start);
$row[] = $spent;
}
$chart->addRowArray($row);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allBudgetsHomeChart(GChart $chart, BudgetRepositoryInterface $repository)
{
$chart->addColumn('Budget', 'string');
$chart->addColumn('Left', 'number');
$chart->addColumn('Overspent', 'number');
$budgets = $repository->getBudgets();
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$allEntries = new Collection;
foreach ($budgets as $budget) {
$repetitions = $repository->getBudgetLimitRepetitions($budget, $start, $end);
if ($repetitions->count() == 0) {
$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);
}
}
}
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function allCategoriesHomeChart(GChart $chart, CategoryRepositoryInterface $repository)
{
$chart->addColumn('Category', 'string');
$chart->addColumn('Spent', 'number');
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$set = $repository->getCategoriesAndExpenses($start, $end);
foreach ($set as $entry) {
$isEncrypted = intval($entry->encrypted) == 1 ? true : false;
$name = strlen($entry->name) == 0 ? '(no category)' : $entry->name;
$name = $isEncrypted ? Crypt::decrypt($name) : $name;
$chart->addRow($name, floatval($entry->sum));
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param BillRepositoryInterface $repository
* @param Bill $bill
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function billOverview(GChart $chart, BillRepositoryInterface $repository, Bill $bill)
{
$chart->addColumn('Date', 'date');
$chart->addColumn('Max amount', 'number');
$chart->addColumn('Min amount', 'number');
$chart->addColumn('Recorded bill entry', 'number');
// get first transaction or today for start:
$results = $repository->getJournals($bill);
/** @var TransactionJournal $result */
foreach ($results as $result) {
$chart->addRow(clone $result->date, floatval($bill->amount_max), floatval($bill->amount_min), floatval($result->amount));
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
*
* @param BillRepositoryInterface $repository
* @param AccountRepositoryInterface $accounts
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function billsOverview(GChart $chart, BillRepositoryInterface $repository, AccountRepositoryInterface $accounts)
{
$chart->addColumn('Name', 'string');
$chart->addColumn('Amount', 'number');
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$bills = $repository->getActiveBills();
$paid = new Collection; // journals.
$unpaid = new Collection; // bills
// loop paid and create single entry:
$paidDescriptions = [];
$paidAmount = 0;
$unpaidDescriptions = [];
$unpaidAmount = 0;
/** @var Bill $bill */
foreach ($bills as $bill) {
$ranges = $repository->getRanges($bill, $start, $end);
foreach ($ranges as $range) {
// paid a bill in this range?
$journals = $repository->getJournalsInRange($bill, $range['start'], $range['end']);
if ($journals->count() == 0) {
$unpaid->push([$bill, $range['start']]);
} else {
$paid = $paid->merge($journals);
}
}
}
$creditCards = $accounts->getCreditCards();
foreach ($creditCards as $creditCard) {
$balance = Steam::balance($creditCard, null, true);
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
if ($balance < 0) {
// unpaid! create a fake bill that matches the amount.
$description = $creditCard->name;
$amount = $balance * -1;
$fakeBill = $repository->createFakeBill($description, $date, $amount);
unset($description, $amount);
$unpaid->push([$fakeBill, $date]);
}
if ($balance == 0) {
// find transfer(s) TO the credit card which should account for
// anything paid. If not, the CC is not yet used.
$journals = $accounts->getTransfersInRange($creditCard, $start, $end);
$paid = $paid->merge($journals);
}
}
/** @var TransactionJournal $entry */
foreach ($paid as $entry) {
$paidDescriptions[] = $entry->description;
$paidAmount += floatval($entry->amount);
}
// loop unpaid:
/** @var Bill $entry */
foreach ($unpaid as $entry) {
$description = $entry[0]->name . ' (' . $entry[1]->format('jS M Y') . ')';
$amount = ($entry[0]->amount_max + $entry[0]->amount_min) / 2;
$unpaidDescriptions[] = $description;
$unpaidAmount += $amount;
unset($amount, $description);
}
$chart->addRow('Unpaid: ' . join(', ', $unpaidDescriptions), $unpaidAmount);
$chart->addRow('Paid: ' . join(', ', $paidDescriptions), $paidAmount);
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param LimitRepetition $repetition
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function budgetLimitSpending(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, LimitRepetition $repetition)
{
$start = clone $repetition->startdate;
$end = $repetition->enddate;
$chart->addColumn('Day', 'date');
$chart->addColumn('Left', 'number');
$amount = $repetition->amount;
while ($start <= $end) {
/*
* Sum of expenses on this day:
*/
$sum = $repository->expensesOnDay($budget, $start);
$amount += $sum;
$chart->addRow(clone $start, $amount);
$start->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param BudgetRepositoryInterface $repository
* @param Budget $budget
* @param int $year
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function budgetsAndSpending(GChart $chart, BudgetRepositoryInterface $repository, Budget $budget, $year = 0)
{
$chart->addColumn('Month', 'date');
$chart->addColumn('Budgeted', 'number');
$chart->addColumn('Spent', 'number');
if ($year == 0) {
$start = $repository->getFirstBudgetLimitDate($budget);
$end = $repository->getLastBudgetLimitDate($budget);
} else {
$start = Carbon::createFromDate(intval($year), 1, 1);
$end = clone $start;
$end->endOfYear();
}
while ($start <= $end) {
$spent = $repository->spentInMonth($budget, $start);
$budgeted = $repository->getLimitAmountOnDate($budget, $start);
$chart->addRow(clone $start, $budgeted, $spent);
$start->addMonth();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function categoryOverviewChart(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{
// oldest transaction in category:
$start = $repository->getFirstActivityDate($category);
/** @var Preference $range */
$range = Preferences::get('viewRange', '1M');
// jump to start of week / month / year / etc (TODO).
$start = Navigation::startOfPeriod($start, $range->data);
$chart->addColumn('Period', 'date');
$chart->addColumn('Spent', 'number');
$end = new Carbon;
while ($start <= $end) {
$currentEnd = Navigation::endOfPeriod($start, $range->data);
$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());
}
/**
* @param GChart $chart
* @param CategoryRepositoryInterface $repository
* @param Category $category
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function categoryPeriodChart(GChart $chart, CategoryRepositoryInterface $repository, Category $category)
{
$start = clone Session::get('start', Carbon::now()->startOfMonth());
$chart->addColumn('Period', 'date');
$chart->addColumn('Spent', 'number');
$end = Session::get('end', Carbon::now()->endOfMonth());
while ($start <= $end) {
$spent = $repository->spentOnDaySum($category, $start);
$chart->addRow(clone $start, $spent);
$start->addDay();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param PiggyBankRepositoryInterface $repository
* @param PiggyBank $piggyBank
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function piggyBankHistory(GChart $chart, PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
$chart->addColumn('Date', 'date');
$chart->addColumn('Balance', 'number');
/** @var Collection $set */
$set = $repository->getEventSummarySet($piggyBank);
$sum = 0;
foreach ($set as $entry) {
$sum += floatval($entry->sum);
$chart->addRow(new Carbon($entry->date), $sum);
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInExp(GChart $chart, ReportQueryInterface $query, $year)
{
$start = new Carbon('01-01-' . $year);
$chart->addColumn('Month', 'date');
$chart->addColumn('Income', 'number');
$chart->addColumn('Expenses', 'number');
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
// get report query interface.
$end = clone $start;
$end->endOfYear();
while ($start < $end) {
$currentEnd = clone $start;
$currentEnd->endOfMonth();
// 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();
}
$chart->generate();
return Response::json($chart->getData());
}
/**
* @param GChart $chart
* @param ReportQueryInterface $query
* @param $year
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function yearInExpSum(GChart $chart, ReportQueryInterface $query, $year)
{
$start = new Carbon('01-01-' . $year);
$chart->addColumn('Summary', 'string');
$chart->addColumn('Income', 'number');
$chart->addColumn('Expenses', 'number');
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
$income = 0;
$expense = 0;
$count = 0;
$end = clone $start;
$end->endOfYear();
while ($start < $end) {
$currentEnd = clone $start;
$currentEnd->endOfMonth();
// total income:
$incomeSum = floatval($query->incomeByPeriod($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
// total expenses:
$expenseSum = floatval($query->journalsByExpenseAccount($start, $currentEnd, $showSharedReports)->sum('queryAmount'));
$income += $incomeSum;
$expense += $expenseSum;
$count++;
$start->addMonth();
}
$chart->addRow('Sum', $income, $expense);
$count = $count > 0 ? $count : 1;
$chart->addRow('Average', ($income / $count), ($expense / $count));
$chart->generate();
return Response::json($chart->getData());
}
}

View File

@@ -53,7 +53,7 @@ class HomeController extends Controller
$types = Config::get('firefly.accountTypesByIdentifier.asset');
$count = $repository->countAccounts($types);
$title = 'Firefly';
$subTitle = 'What\'s playing?';
$subTitle = trans('firefly.welcomeBack');
$mainTitleIcon = 'fa-fire';
$transactions = [];
$frontPage = Preferences::get('frontPageAccounts', []);
@@ -63,13 +63,11 @@ class HomeController extends Controller
$savings = $repository->getSavingsAccounts();
$piggyBankAccounts = $repository->getPiggyBankAccounts();
$savingsTotal = 0;
foreach ($savings as $savingAccount) {
$savingsTotal += Steam::balance($savingAccount, $end);
}
// check if all books are correct.
$sum = $repository->sumOfEverything();
if ($sum != 0) {
Session::flash(

View File

@@ -12,7 +12,6 @@ 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;
use Steam;
@@ -39,19 +38,14 @@ class JsonController extends Controller
$end = Session::get('end', Carbon::now()->endOfMonth());
$amount = 0;
// these two functions are the same as the chart TODO
// these two functions are the same as the chart
$bills = $repository->getActiveBills();
/** @var Bill $bill */
foreach ($bills as $bill) {
$ranges = $repository->getRanges($bill, $start, $end);
foreach ($ranges as $range) {
// paid a bill in this range?
$amount += $repository->getJournalsInRange($bill, $range['start'], $range['end'])->sum('amount');
}
$amount += $repository->billPaymentsInRange($bill, $start, $end);
}
unset($ranges, $bill, $range, $bills);
unset($bill, $bills);
/**
* Find credit card accounts and possibly unpaid credit card bills.
@@ -60,7 +54,7 @@ class JsonController extends Controller
// 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);
$balance = Steam::balance($creditCard, $end, 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.
@@ -100,7 +94,7 @@ class JsonController extends Controller
$creditCards = $accountRepository->getCreditCards();
foreach ($creditCards as $creditCard) {
$balance = Steam::balance($creditCard, null, true);
$balance = Steam::balance($creditCard, $end, true);
$date = new Carbon($creditCard->getMeta('ccMonthlyPaymentDate'));
if ($balance < 0) {
// unpaid! create a fake bill that matches the amount.
@@ -128,7 +122,12 @@ class JsonController extends Controller
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$amount = $reportQuery->incomeByPeriod($start, $end, true)->sum('queryAmount');
$amount = $reportQuery->incomeInPeriodCorrected($start, $end, true)->sum('amount');
// $amount = 0;
// foreach($set as $entry) {
// //echo $entry->description.' ('.$entry->tags->count().'): ' . $entry->amount."\n";
// $amount += $entry->amount;
// }
return Response::json(['box' => 'in', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]);
}
@@ -142,7 +141,7 @@ class JsonController extends Controller
{
$start = Session::get('start', Carbon::now()->startOfMonth());
$end = Session::get('end', Carbon::now()->endOfMonth());
$amount = $reportQuery->journalsByExpenseAccount($start, $end, true)->sum('queryAmount');
$amount = $reportQuery->expenseInPeriodCorrected($start, $end, true)->sum('amount');
return Response::json(['box' => 'out', 'amount' => Amount::format($amount, false), 'amount_raw' => $amount]);
}
@@ -202,30 +201,6 @@ class JsonController extends Controller
}
/**
* @return \Symfony\Component\HttpFoundation\Response
*/
public function setSharedReports()
{
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$new = !$pref->data;
Preferences::set('showSharedReports', $new);
return Response::json(['value' => $new]);
}
/**
* @return \Symfony\Component\HttpFoundation\Response
*/
public function showSharedReports()
{
$pref = Preferences::get('showSharedReports', false);
return Response::json(['value' => $pref->data]);
}
/**
* Returns a JSON list of all beneficiaries.
*

View File

@@ -31,7 +31,7 @@ class PiggyBankController extends Controller
public function __construct()
{
parent::__construct();
View::share('title', 'Piggy banks');
View::share('title', trans('firefly.piggyBanks'));
View::share('mainTitleIcon', 'fa-sort-amount-asc');
}
@@ -45,7 +45,8 @@ class PiggyBankController extends Controller
*/
public function add(AccountRepositoryInterface $repository, PiggyBank $piggyBank)
{
$leftOnAccount = $repository->leftOnAccount($piggyBank->account);
$date = Session::get('end', Carbon::now()->endOfMonth());
$leftOnAccount = $repository->leftOnAccount($piggyBank->account, $date);
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
$leftToSave = $piggyBank->targetamount - $savedSoFar;
$maxAmount = min($leftOnAccount, $leftToSave);
@@ -157,6 +158,7 @@ class PiggyBankController extends Controller
{
/** @var Collection $piggyBanks */
$piggyBanks = $piggyRepository->getPiggyBanks();
$end = Session::get('end', Carbon::now()->endOfMonth());
$accounts = [];
/** @var PiggyBank $piggyBank */
@@ -172,8 +174,8 @@ class PiggyBankController extends Controller
if (!isset($accounts[$account->id])) {
$accounts[$account->id] = [
'name' => $account->name,
'balance' => Steam::balance($account, null, true),
'leftForPiggyBanks' => $repository->leftOnAccount($account),
'balance' => Steam::balance($account, $end, true),
'leftForPiggyBanks' => $repository->leftOnAccount($account, $end),
'sumOfSaved' => $piggyBank->savedSoFar,
'sumOfTargets' => floatval($piggyBank->targetamount),
'leftToSave' => $piggyBank->leftToSave
@@ -215,7 +217,8 @@ class PiggyBankController extends Controller
public function postAdd(PiggyBankRepositoryInterface $repository, AccountRepositoryInterface $accounts, PiggyBank $piggyBank)
{
$amount = round(floatval(Input::get('amount')), 2);
$leftOnAccount = $accounts->leftOnAccount($piggyBank->account);
$date = Session::get('end', Carbon::now()->endOfMonth());
$leftOnAccount = $accounts->leftOnAccount($piggyBank->account, $date);
$savedSoFar = $piggyBank->currentRelevantRep()->currentamount;
$leftToSave = $piggyBank->targetamount - $savedSoFar;
$maxAmount = round(min($leftOnAccount, $leftToSave), 2);

View File

@@ -1,5 +1,6 @@
<?php namespace FireflyIII\Http\Controllers;
use Config;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Input;
use Preferences;
@@ -21,7 +22,7 @@ class PreferencesController extends Controller
public function __construct()
{
parent::__construct();
View::share('title', 'Preferences');
View::share('title', trans('firefly.preferences'));
View::share('mainTitleIcon', 'fa-gear');
}
@@ -37,9 +38,11 @@ class PreferencesController extends Controller
$viewRange = $viewRangePref->data;
$frontPageAccounts = Preferences::get('frontPageAccounts', []);
$budgetMax = Preferences::get('budgetMaximum', 1000);
$languagePref = Preferences::get('language', 'en');
$language = $languagePref->data;
$budgetMaximum = $budgetMax->data;
return view('preferences.index', compact('budgetMaximum', 'accounts', 'frontPageAccounts', 'viewRange'));
return view('preferences.index', compact('budgetMaximum', 'language', 'accounts', 'frontPageAccounts', 'viewRange'));
}
/**
@@ -49,10 +52,12 @@ class PreferencesController extends Controller
{
// front page accounts
$frontPageAccounts = [];
foreach (Input::get('frontPageAccounts') as $id) {
$frontPageAccounts[] = intval($id);
if (is_array(Input::get('frontPageAccounts'))) {
foreach (Input::get('frontPageAccounts') as $id) {
$frontPageAccounts[] = intval($id);
}
Preferences::set('frontPageAccounts', $frontPageAccounts);
}
Preferences::set('frontPageAccounts', $frontPageAccounts);
// view range:
Preferences::set('viewRange', Input::get('viewRange'));
@@ -65,6 +70,12 @@ class PreferencesController extends Controller
$budgetMaximum = intval(Input::get('budgetMaximum'));
Preferences::set('budgetMaximum', $budgetMaximum);
// language:
$lang = Input::get('language');
if (in_array($lang, array_keys(Config::get('firefly.lang')))) {
Preferences::set('language', $lang);
}
Session::flash('success', 'Preferences saved!');

View File

@@ -2,13 +2,13 @@
use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Helpers\Report\ReportQueryInterface;
use FireflyIII\Models\Account;
use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\Preference;
use FireflyIII\Models\TransactionJournal;
use Preferences;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use Session;
use Steam;
use View;
/**
@@ -21,311 +21,132 @@ class ReportController extends Controller
/** @var ReportHelperInterface */
protected $helper;
/** @var ReportQueryInterface */
protected $query;
/**
* @param ReportHelperInterface $helper
* @param ReportQueryInterface $query
*/
public function __construct(ReportHelperInterface $helper, ReportQueryInterface $query)
public function __construct(ReportHelperInterface $helper)
{
$this->query = $query;
parent::__construct();
$this->helper = $helper;
View::share('title', 'Reports');
View::share('title', trans('firefly.reports'));
View::share('mainTitleIcon', 'fa-line-chart');
}
/**
* @param string $year
* @param string $month
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\View\View
*/
public function budget($year = '2014', $month = '1')
{
$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();
// 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) {
$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) ^^
// 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;
}
$accountAmounts[$account->id] += $data['queryAmount'];
}
$account->hide = $hide;
$account->budgetInformation = $array;
$account->balancedAmount = $balancedAmount;
}
/**
* Start getBudgetsForMonth DONE
*/
$budgets = $this->helper->getBudgetsForMonth($date, $showSharedReports);
/**
* End getBudgetsForMonth DONE
*/
return view('reports.budget', compact('subTitle', 'accountAmounts', 'year', 'month', 'subTitleIcon', 'date', 'accounts', 'budgets'));
}
/**
* @return View
* @internal param ReportHelperInterface $helper
*
*/
public function index()
public function index(AccountRepositoryInterface $repository)
{
$start = Session::get('first');
$months = $this->helper->listOfMonths($start);
$years = $this->helper->listOfYears($start);
$title = 'Reports';
$mainTitleIcon = 'fa-line-chart';
$start = Session::get('first');
$months = $this->helper->listOfMonths($start);
return view('reports.index', compact('years', 'months', 'title', 'mainTitleIcon'));
}
// does the user have shared accounts?
$accounts = $repository->getAccounts(['Default account', 'Asset account']);
$hasShared = false;
/**
* @param Account $account
* @param string $year
* @param string $month
*
* @return \Illuminate\View\View
*/
public function modalBalancedTransfers(Account $account, $year = '2014', $month = '1')
{
$start = new Carbon($year . '-' . $month . '-01');
$end = clone $start;
$end->endOfMonth();
$journals = $this->query->balancedTransactionsList($account, $start, $end);
return view('reports.modal-journal-list', compact('journals'));
}
/**
* @param Account $account
* @param string $year
* @param string $month
*
* @return View
* @internal param ReportQueryInterface $query
*
*/
public function modalLeftUnbalanced(Account $account, $year = '2014', $month = '1')
{
$start = new Carbon($year . '-' . $month . '-01');
$end = clone $start;
$end->endOfMonth();
$set = $this->query->getTransactionsWithoutBudget($account, $start, $end);
$journals = $set->filter(
function (TransactionJournal $journal) {
$count = $journal->transactiongroups()->where('relation', 'balance')->count();
if ($count == 0) {
return $journal;
}
return null;
/** @var Account $account */
foreach ($accounts as $account) {
if ($account->getMeta('accountRole') == 'sharedAsset') {
$hasShared = true;
}
);
}
return view('reports.modal-journal-list', compact('journals'));
}
/**
* @param Account $account
* @param string $year
* @param string $month
*
* @return \Illuminate\View\View
*/
public function modalNoBudget(Account $account, $year = '2014', $month = '1')
{
$start = new Carbon($year . '-' . $month . '-01');
$end = clone $start;
$end->endOfMonth();
$journals = $this->query->getTransactionsWithoutBudget($account, $start, $end);
return view('reports.modal-journal-list', compact('journals'));
return view('reports.index', compact('months', 'hasShared'));
}
/**
* @param string $year
* @param string $month
*
* @param bool $shared
*
* @return \Illuminate\View\View
*/
public function month($year = '2014', $month = '1')
public function month($year = '2014', $month = '1', $shared = false)
{
$date = new Carbon($year . '-' . $month . '-01');
$subTitle = 'Report for ' . $date->format('F Y');
$subTitleIcon = 'fa-calendar';
$displaySum = true; // to show sums in report.
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
$start = new Carbon($year . '-' . $month . '-01');
$subTitle = trans('firefly.reportForMonth', ['date' => $start->formatLocalized($this->monthFormat)]);
$subTitleIcon = 'fa-calendar';
$end = clone $start;
$incomeTopLength = 8;
$expenseTopLength = 8;
if ($shared == 'shared') {
$shared = true;
$subTitle = trans('firefly.reportForMonthShared', ['date' => $start->formatLocalized($this->monthFormat)]);
}
/**
*
* get income for month (date)
*
*/
$start = clone $date;
$start->startOfMonth();
$end = clone $date;
$end->endOfMonth();
/**
* Start getIncomeForMonth DONE
*/
$income = $this->query->incomeByPeriod($start, $end, $showSharedReports);
/**
* End getIncomeForMonth DONE
*/
/**
* Start getExpenseGroupedForMonth DONE
*/
$set = $this->query->journalsByExpenseAccount($start, $end, $showSharedReports);
$expenses = Steam::makeArray($set);
$expenses = Steam::sortArray($expenses);
$expenses = Steam::limitArray($expenses, 10);
/**
* End getExpenseGroupedForMonth DONE
*/
/**
* Start getBudgetsForMonth DONE
*/
$budgets = $this->helper->getBudgetsForMonth($date, $showSharedReports);
/**
* End getBudgetsForMonth DONE
*/
/**
* Start getCategoriesForMonth DONE
*/
// all categories.
$result = $this->query->journalsByCategory($start, $end);
$categories = Steam::makeArray($result);
// all transfers
if ($showSharedReports === false) {
$result = $this->query->sharedExpensesByCategory($start, $end);
$transfers = Steam::makeArray($result);
$merged = Steam::mergeArrays($categories, $transfers);
} else {
$merged = $categories;
}
// sort.
$sorted = Steam::sortNegativeArray($merged);
// limit to $limit:
$categories = Steam::limitArray($sorted, 10);
/**
* End getCategoriesForMonth DONE
*/
/**
* Start getAccountsForMonth
*/
$list = $this->query->accountList($showSharedReports);
$accounts = [];
/** @var Account $account */
foreach ($list as $account) {
$id = intval($account->id);
/** @noinspection PhpParamsInspection */
$accounts[$id] = [
'name' => $account->name,
'startBalance' => Steam::balance($account, $start),
'endBalance' => Steam::balance($account, $end)
];
$accounts[$id]['difference'] = $accounts[$id]['endBalance'] - $accounts[$id]['startBalance'];
}
/**
* End getAccountsForMonth
*/
$accounts = $this->helper->getAccountReport($start, $end, $shared);
$incomes = $this->helper->getIncomeReport($start, $end, $shared);
$expenses = $this->helper->getExpenseReport($start, $end, $shared);
$budgets = $this->helper->getBudgetReport($start, $end, $shared);
$categories = $this->helper->getCategoryReport($start, $end, $shared);
$balance = $this->helper->getBalanceReport($start, $end, $shared);
$bills = $this->helper->getBillReport($start, $end, $shared);
return view(
'reports.month',
compact(
'income', 'expenses', 'budgets', 'accounts', 'categories',
'date', 'subTitle', 'displaySum', 'subTitleIcon'
'start', 'shared',
'subTitle', 'subTitleIcon',
'accounts',
'incomes', 'incomeTopLength',
'expenses', 'expenseTopLength',
'budgets', 'balance',
'categories',
'bills'
)
);
}
/**
* @param $year
* @param $year
*
* @param bool $shared
*
* @return $this
*/
public function year($year)
public function year($year, $shared = false)
{
/** @var Preference $pref */
$pref = Preferences::get('showSharedReports', false);
$showSharedReports = $pref->data;
$date = new Carbon('01-01-' . $year);
$end = clone $date;
$start = new Carbon('01-01-' . $year);
$end = clone $start;
$subTitle = trans('firefly.reportForYear', ['year' => $year]);
$subTitleIcon = 'fa-bar-chart';
$incomeTopLength = 8;
$expenseTopLength = 8;
if ($shared == 'shared') {
$shared = true;
$subTitle = trans('firefly.reportForYearShared', ['year' => $year]);
}
$end->endOfYear();
$title = 'Reports';
$subTitle = $year;
$subTitleIcon = 'fa-bar-chart';
$mainTitleIcon = 'fa-line-chart';
$balances = $this->helper->yearBalanceReport($date, $showSharedReports);
$groupedIncomes = $this->query->journalsByRevenueAccount($date, $end, $showSharedReports);
$groupedExpenses = $this->query->journalsByExpenseAccount($date, $end, $showSharedReports);
$accounts = $this->helper->getAccountReport($start, $end, $shared);
$incomes = $this->helper->getIncomeReport($start, $end, $shared);
$expenses = $this->helper->getExpenseReport($start, $end, $shared);
return view(
'reports.year', compact('date', 'groupedIncomes', 'groupedExpenses', 'year', 'balances', 'title', 'subTitle', 'subTitleIcon', 'mainTitleIcon')
'reports.year',
compact(
'start', // the date for this report.
'shared', // is a shared report?
'accounts', // all accounts
'incomes', 'expenses', // expenses and incomes.
'subTitle', 'subTitleIcon', // subtitle and subtitle icon.
'incomeTopLength', // length of income top X
'expenseTopLength' // length of expense top X.
)
);
}

View File

@@ -133,7 +133,7 @@ class TagController extends Controller
* changes to an advancePayment.
*/
if ($tag->tagMode == 'balancingAct') {
if ($tag->tagMode == 'balancingAct' || $tag->tagMode == 'nothing') {
foreach ($tag->transactionjournals as $journal) {
if ($journal->transactionType->type == 'Transfer') {
$allowToAdvancePayment = false;
@@ -289,9 +289,9 @@ class TagController extends Controller
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;
$latitude = $request->get('latitude');
$longitude = $request->get('longitude');
$zoomLevel = $request->get('zoomLevel');
} else {
$latitude = null;
$longitude = null;

View File

@@ -30,7 +30,7 @@ class TransactionController extends Controller
public function __construct()
{
parent::__construct();
View::share('title', 'Transactions');
View::share('title', trans('firefly.transactions'));
View::share('mainTitleIcon', 'fa-repeat');
}
@@ -44,17 +44,15 @@ class TransactionController extends Controller
{
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = '(no budget)';
$budgets[0] = trans('form.noBudget');
$piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
$piggies[0] = '(no piggy bank)';
$piggies[0] = trans('form.noPiggybank');
$preFilled = Session::has('preFilled') ? Session::get('preFilled') : [];
$respondTo = ['account_id', 'account_from_id'];
$subTitle = 'Add a new ' . e($what);
$subTitle = trans('form.add_new_' . $what);
foreach ($respondTo as $r) {
if (!is_null(Input::get($r))) {
$preFilled[$r] = Input::get($r);
}
$preFilled[$r] = Input::get($r);
}
Session::put('preFilled', $preFilled);
@@ -119,10 +117,11 @@ class TransactionController extends Controller
$what = strtolower($journal->transactiontype->type);
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = '(no budget)';
$budgets[0] = trans('form.noBudget');
$transactions = $journal->transactions()->orderBy('amount', 'DESC')->get();
$piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
$piggies[0] = '(no piggy bank)';
$piggies[0] = trans('form.noPiggybank');
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
$preFilled = [
'date' => $journal->date->format('Y-m-d'),
'category' => '',
@@ -150,7 +149,7 @@ class TransactionController extends Controller
$preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id;
}
$preFilled['amount'] = $journal->amount;
$preFilled['amount'] = $journal->actualAmount;
$preFilled['account_id'] = $journal->assetAccount->id;
$preFilled['expense_account'] = $transactions[0]->account->name;
$preFilled['revenue_account'] = $transactions[1]->account->name;
@@ -182,19 +181,19 @@ class TransactionController extends Controller
case 'expenses':
case 'withdrawal':
$subTitleIcon = 'fa-long-arrow-left';
$subTitle = 'Expenses';
$subTitle = trans('firefly.expenses');
$types = ['Withdrawal'];
break;
case 'revenue':
case 'deposit':
$subTitleIcon = 'fa-long-arrow-right';
$subTitle = 'Revenue, income and deposits';
$subTitle = trans('firefly.income');
$types = ['Deposit'];
break;
case 'transfer':
case 'transfers':
$subTitleIcon = 'fa-exchange';
$subTitle = 'Transfers';
$subTitle = trans('firefly.transfers');
$types = ['Transfer'];
break;
}
@@ -249,7 +248,7 @@ class TransactionController extends Controller
$t->after = $t->before + $t->amount;
}
);
$subTitle = e($journal->transactiontype->type) . ' "' . e($journal->description) . '"';
$subTitle = trans('firefly.' . $journal->transactiontype->type) . ' "' . e($journal->description) . '"';
return view('transactions.show', compact('journal', 'subTitle'));
}
@@ -269,7 +268,9 @@ class TransactionController extends Controller
// rescan journal, UpdateJournalConnection
event(new JournalSaved($journal));
// ConnectJournalToPiggyBank
event(new JournalCreated($journal, intval($request->get('piggy_bank_id'))));
if ($journal->transactionType->type == 'Transfer' && intval($request->get('piggy_bank_id')) > 0) {
event(new JournalCreated($journal, intval($request->get('piggy_bank_id'))));
}
$repository->deactivateReminder($request->get('reminder_id'));

View File

@@ -1,12 +1,17 @@
<?php namespace FireflyIII\Http\Middleware;
use App;
use Closure;
use Config;
use FireflyIII\Models\Preference;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Http\Request;
use Preferences;
/**
* Class Authenticate
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Middleware
*/
class Authenticate
@@ -47,6 +52,11 @@ class Authenticate
return redirect()->guest('auth/login');
}
}
// if logged in, set user language:
$pref = Preferences::get('language', 'en');
App::setLocale($pref->data);
setlocale(LC_TIME, Config::get('firefly.locales.' . $pref->data));
return $next($request);
}

View File

@@ -3,7 +3,6 @@
namespace FireflyIII\Http\Middleware;
use App;
use Closure;
use FireflyIII\Models\PiggyBank;
use FireflyIII\Models\PiggyBankRepetition;
@@ -46,23 +45,22 @@ class PiggyBanks
*/
public function handle(Request $request, Closure $next)
{
if ($this->auth->check() && !$request->isXmlHttpRequest() && App::environment() != 'testing') {
if ($this->auth->check() && !$request->isXmlHttpRequest()) {
// get piggy banks without a repetition:
/** @var Collection $set */
$set = $this->auth->user()->piggybanks()
->leftJoin('piggy_bank_repetitions', 'piggy_banks.id', '=', 'piggy_bank_repetitions.piggy_bank_id')
->whereNull('piggy_bank_repetitions.id')
->get(['piggy_banks.id', 'piggy_banks.startdate', 'piggy_banks.targetdate']);
if ($set->count() > 0) {
/** @var PiggyBank $partialPiggy */
foreach ($set as $partialPiggy) {
$repetition = new PiggyBankRepetition;
$repetition->piggyBank()->associate($partialPiggy);
$repetition->startdate = is_null($partialPiggy->startdate) ? null : $partialPiggy->startdate;
$repetition->targetdate = is_null($partialPiggy->targetdate) ? null : $partialPiggy->targetdate;
$repetition->currentamount = 0;
$repetition->save();
}
/** @var PiggyBank $partialPiggy */
foreach ($set as $partialPiggy) {
$repetition = new PiggyBankRepetition;
$repetition->piggyBank()->associate($partialPiggy);
$repetition->startdate = $partialPiggy->startdate;
$repetition->targetdate = $partialPiggy->targetdate;
$repetition->currentamount = 0;
$repetition->save();
}
unset($partialPiggy, $set, $repetition);
}

View File

@@ -43,29 +43,27 @@ class Range
*
* @param \Illuminate\Http\Request $request
* @param \Closure $theNext
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @return mixed
*/
public function handle(Request $request, Closure $theNext)
{
if ($this->auth->check() && App::environment() != 'testing') {
if ($this->auth->check()) {
// ignore preference. set the range to be the current month:
if (!Session::has('start') && !Session::has('end')) {
/** @var \FireflyIII\Models\Preference $viewRange */
$viewRange = Preferences::get('viewRange', '1M');
$viewRange = Preferences::get('viewRange', '1M')->data;
$start = new Carbon;
$start = Navigation::updateStartDate($viewRange->data, $start);
$end = Navigation::updateEndDate($viewRange->data, $start);
$start = Navigation::updateStartDate($viewRange, $start);
$end = Navigation::updateEndDate($viewRange, $start);
Session::put('start', $start);
Session::put('end', $end);
}
if (!Session::has('first')) {
/**
* Get helper thing.
*/
/** @var \FireflyIII\Repositories\Journal\JournalRepositoryInterface $repository */
$repository = App::make('FireflyIII\Repositories\Journal\JournalRepositoryInterface');
$journal = $repository->first();
@@ -75,16 +73,12 @@ class Range
Session::put('first', Carbon::now()->startOfYear());
}
}
// set current / next / prev month.
$current = Carbon::now()->format('F Y');
$next = Carbon::now()->endOfMonth()->addDay()->format('F Y');
$prev = Carbon::now()->startOfMonth()->subDay()->format('F Y');
$current = Carbon::now()->formatLocalized('%B %Y');
$next = Carbon::now()->endOfMonth()->addDay()->formatLocalized('%B %Y');
$prev = Carbon::now()->startOfMonth()->subDay()->formatLocalized('%B %Y');
View::share('currentMonthName', $current);
View::share('previousMonthName', $prev);
View::share('nextMonthName', $next);
}
return $theNext($request);

View File

@@ -8,6 +8,7 @@ use Illuminate\Http\Request;
/**
* Class RedirectIfAuthenticated
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Middleware
*/
class RedirectIfAuthenticated

View File

@@ -46,36 +46,25 @@ class Reminders
*/
public function handle(Request $request, Closure $next)
{
if ($this->auth->check() && !$request->isXmlHttpRequest() && App::environment() != 'testing') {
if ($this->auth->check() && !$request->isXmlHttpRequest()) {
// do reminders stuff.
$piggyBanks = $this->auth->user()->piggyBanks()->where('remind_me', 1)->get();
$today = new Carbon;
/** @var \FireflyIII\Helpers\Reminders\ReminderHelperInterface $helper */
$helper = App::make('FireflyIII\Helpers\Reminders\ReminderHelperInterface');
/** @var PiggyBank $piggyBank */
foreach ($piggyBanks as $piggyBank) {
$ranges = $helper->getReminderRanges($piggyBank);
foreach ($ranges as $range) {
if ($today < $range['end'] && $today > $range['start']) {
// create a reminder here!
$helper->createReminder($piggyBank, $range['start'], $range['end']);
// stop looping, we're done.
break;
}
}
$helper->createReminders($piggyBank, new Carbon);
}
// delete invalid reminders
$set = $this->auth->user()->reminders()->leftJoin('piggy_banks', 'piggy_banks.id', '=', 'remindersable_id')->whereNull('piggy_banks.id')->get(
['reminders.id']
);
foreach ($set as $reminder) {
$reminder->delete();
// this is a construction SQLITE cannot handle :(
if (env('DB_CONNECTION') != 'sqlite') {
Reminder::whereUserId($this->auth->user()->id)
->leftJoin('piggy_banks', 'piggy_banks.id', '=', 'remindersable_id')
->whereNull('piggy_banks.id')
->delete();
}
// get and list active reminders:
$reminders = $this->auth->user()->reminders()->today()->get();
$reminders->each(

View File

@@ -10,6 +10,7 @@ use Log;
/**
* Class ReplaceTestVars
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Middleware
*/
class ReplaceTestVars

View File

@@ -6,6 +6,7 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
/**
* Class VerifyCsrfToken
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Middleware
*/
class VerifyCsrfToken extends BaseVerifier

View File

@@ -10,6 +10,7 @@ use Input;
/**
* Class AccountFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class AccountFormRequest extends Request

View File

@@ -9,6 +9,7 @@ use Input;
/**
* Class BillFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class BillFormRequest extends Request

View File

@@ -9,6 +9,7 @@ use Input;
/**
* Class BudgetFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class BudgetFormRequest extends Request

View File

@@ -9,6 +9,7 @@ use Input;
/**
* Class CategoryFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class CategoryFormRequest extends Request

View File

@@ -8,6 +8,7 @@ use Input;
/**
* Class BillFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class CurrencyFormRequest extends Request

View File

@@ -7,6 +7,7 @@ use Auth;
/**
* Class DeleteAccountFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class DeleteAccountFormRequest extends Request

View File

@@ -10,6 +10,7 @@ use Input;
/**
* Class JournalFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class JournalFormRequest extends Request
@@ -49,12 +50,11 @@ class JournalFormRequest extends Request
/**
* @return array
* @throws Exception
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function rules()
{
// can we switch on the "what"?
$what = Input::get('what');
$what = Input::get('what');
$rules = [
'description' => 'required|min:1,max:255',
'what' => 'required|in:withdrawal,deposit,transfer',
@@ -73,8 +73,6 @@ class JournalFormRequest extends Request
if (intval(Input::get('budget_id')) != 0) {
$rules['budget_id'] = 'exists:budgets,id|belongsToUser:budgets';
}
break;
case 'deposit':
$rules['category'] = 'between:1,255';
@@ -92,7 +90,5 @@ class JournalFormRequest extends Request
}
return $rules;
}
}

View File

@@ -8,6 +8,7 @@ use Input;
/**
* Class PiggyBankFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class PiggyBankFormRequest extends Request

View File

@@ -7,6 +7,7 @@ use Auth;
/**
* Class ProfileFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class ProfileFormRequest extends Request

View File

@@ -5,6 +5,7 @@ use Illuminate\Foundation\Http\FormRequest;
/**
* Class Request
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
abstract class Request extends FormRequest

View File

@@ -15,6 +15,7 @@ use Input;
/**
* Class TagFormRequest
*
* @codeCoverageIgnore
* @package FireflyIII\Http\Requests
*/
class TagFormRequest extends Request
@@ -47,6 +48,7 @@ class TagFormRequest extends Request
'date' => 'date',
'latitude' => 'numeric|min:-90|max:90',
'longitude' => 'numeric|min:-90|max:90',
'zoomLevel' => 'numeric|min:0|max:80',
'tagMode' => 'required|in:nothing,balancingAct,advancePayment'
];
}

View File

@@ -20,7 +20,7 @@ Breadcrumbs::register(
'home',
function (Generator $breadcrumbs) {
$breadcrumbs->push('Home', route('index'));
$breadcrumbs->push(trans('breadcrumbs.home'), route('index'));
}
);
@@ -28,38 +28,32 @@ Breadcrumbs::register(
'index',
function (Generator $breadcrumbs) {
$breadcrumbs->push('Home', route('index'));
$breadcrumbs->push(trans('breadcrumbs.home'), route('index'));
}
);
//trans('breadcrumbs.')
// accounts
Breadcrumbs::register(
'accounts.index', function (Generator $breadcrumbs, $what) {
$breadcrumbs->parent('home');
$breadcrumbs->push(ucfirst(e($what)) . ' accounts', route('accounts.index', $what));
$breadcrumbs->push(trans('breadcrumbs.' . strtolower(e($what)) . '_accounts'), route('accounts.index', $what));
}
);
Breadcrumbs::register(
'accounts.create', function (Generator $breadcrumbs, $what) {
$breadcrumbs->parent('accounts.index', $what);
$breadcrumbs->push(trans('breadcrumbs.new_' . strtolower(e($what)) . '_account'), route('accounts.create', $what));
}
);
Breadcrumbs::register(
'accounts.show', function (Generator $breadcrumbs, Account $account) {
switch ($account->accountType->type) {
default:
throw new FireflyException('Cannot handle account type "' . e($account->accountType->type) . '"');
break;
case 'Default account':
case 'Asset account':
$what = 'asset';
break;
case 'Cash account':
$what = 'cash';
break;
case 'Expense account':
case 'Beneficiary account':
$what = 'expense';
break;
case 'Revenue account':
$what = 'revenue';
break;
}
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$breadcrumbs->parent('accounts.index', $what);
$breadcrumbs->push(e($account->name), route('accounts.show', $account->id));
}
@@ -67,14 +61,17 @@ Breadcrumbs::register(
Breadcrumbs::register(
'accounts.delete', function (Generator $breadcrumbs, Account $account) {
$breadcrumbs->parent('accounts.show', $account);
$breadcrumbs->push('Delete ' . e($account->name), route('accounts.delete', $account->id));
$breadcrumbs->push(trans('breadcrumbs.delete_account', ['name' => e($account->name)]), route('accounts.delete', $account->id));
}
);
Breadcrumbs::register(
'accounts.edit', function (Generator $breadcrumbs, Account $account) {
$breadcrumbs->parent('accounts.show', $account);
$breadcrumbs->push('Edit ' . e($account->name), route('accounts.edit', $account->id));
$what = Config::get('firefly.shortNamesByFullName.' . $account->accountType->type);
$breadcrumbs->push(trans('breadcrumbs.edit_'.$what.'_account', ['name' => e($account->name)]), route('accounts.edit', $account->id));
}
);
@@ -82,26 +79,26 @@ Breadcrumbs::register(
Breadcrumbs::register(
'budgets.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Budgets', route('budgets.index'));
$breadcrumbs->push(trans('breadcrumbs.budgets'), route('budgets.index'));
}
);
Breadcrumbs::register(
'budgets.create', function (Generator $breadcrumbs) {
$breadcrumbs->parent('budgets.index');
$breadcrumbs->push('Create new budget', route('budgets.create'));
$breadcrumbs->push(trans('breadcrumbs.newBudget'), route('budgets.create'));
}
);
Breadcrumbs::register(
'budgets.edit', function (Generator $breadcrumbs, Budget $budget) {
$breadcrumbs->parent('budgets.show', $budget);
$breadcrumbs->push('Edit ' . e($budget->name), route('budgets.edit', $budget->id));
$breadcrumbs->push(trans('breadcrumbs.edit_budget', ['name' => e($budget->name)]), route('budgets.edit', $budget->id));
}
);
Breadcrumbs::register(
'budgets.delete', function (Generator $breadcrumbs, Budget $budget) {
$breadcrumbs->parent('budgets.show', $budget);
$breadcrumbs->push('Delete ' . e($budget->name), route('budgets.delete', $budget->id));
$breadcrumbs->push(trans('breadcrumbs.delete_budget', ['name' => e($budget->name)]), route('budgets.delete', $budget->id));
}
);
@@ -128,26 +125,26 @@ Breadcrumbs::register(
Breadcrumbs::register(
'categories.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Categories', route('categories.index'));
$breadcrumbs->push(trans('breadcrumbs.categories'), route('categories.index'));
}
);
Breadcrumbs::register(
'categories.create', function (Generator $breadcrumbs) {
$breadcrumbs->parent('categories.index');
$breadcrumbs->push('Create new category', route('categories.create'));
$breadcrumbs->push(trans('breadcrumbs.newCategory'), route('categories.create'));
}
);
Breadcrumbs::register(
'categories.edit', function (Generator $breadcrumbs, Category $category) {
$breadcrumbs->parent('categories.show', $category);
$breadcrumbs->push('Edit ' . e($category->name), route('categories.edit', $category->id));
$breadcrumbs->push(trans('breadcrumbs.edit_category', ['name' => e($category->name)]), route('categories.edit', $category->id));
}
);
Breadcrumbs::register(
'categories.delete', function (Generator $breadcrumbs, Category $category) {
$breadcrumbs->parent('categories.show', $category);
$breadcrumbs->push('Delete ' . e($category->name), route('categories.delete', $category->id));
$breadcrumbs->push(trans('breadcrumbs.delete_category', ['name' => e($category->name)]), route('categories.delete', $category->id));
}
);
@@ -170,20 +167,20 @@ Breadcrumbs::register(
Breadcrumbs::register(
'currency.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Currencies', route('currency.index'));
$breadcrumbs->push(trans('breadcrumbs.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->push(trans('breadcrumbs.edit_currency', ['name' => e($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));
$breadcrumbs->push(trans('breadcrumbs.delete_currency', ['name' => e($currency->name)]), route('currency.delete', $currency->id));
}
);
@@ -192,26 +189,26 @@ Breadcrumbs::register(
Breadcrumbs::register(
'piggy-banks.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Piggy banks', route('piggy-banks.index'));
$breadcrumbs->push(trans('breadcrumbs.piggyBanks'), route('piggy-banks.index'));
}
);
Breadcrumbs::register(
'piggy-banks.create', function (Generator $breadcrumbs) {
$breadcrumbs->parent('piggy-banks.index');
$breadcrumbs->push('Create new piggy bank', route('piggy-banks.create'));
$breadcrumbs->push(trans('breadcrumbs.newPiggyBank'), route('piggy-banks.create'));
}
);
Breadcrumbs::register(
'piggy-banks.edit', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
$breadcrumbs->parent('piggy-banks.show', $piggyBank);
$breadcrumbs->push('Edit ' . e($piggyBank->name), route('piggy-banks.edit', $piggyBank->id));
$breadcrumbs->push(trans('breadcrumbs.edit_piggyBank', ['name' => e($piggyBank->name)]), route('piggy-banks.edit', $piggyBank->id));
}
);
Breadcrumbs::register(
'piggy-banks.delete', function (Generator $breadcrumbs, PiggyBank $piggyBank) {
$breadcrumbs->parent('piggy-banks.show', $piggyBank);
$breadcrumbs->push('Delete ' . e($piggyBank->name), route('piggy-banks.delete', $piggyBank->id));
$breadcrumbs->push(trans('breadcrumbs.delete_piggyBank', ['name' => e($piggyBank->name)]), route('piggy-banks.delete', $piggyBank->id));
}
);
@@ -227,7 +224,7 @@ Breadcrumbs::register(
Breadcrumbs::register(
'preferences', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Preferences', route('preferences'));
$breadcrumbs->push(trans('breadcrumbs.preferences'), route('preferences'));
}
);
@@ -236,14 +233,14 @@ Breadcrumbs::register(
Breadcrumbs::register(
'profile', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Profile', route('profile'));
$breadcrumbs->push(trans('breadcrumbs.profile'), route('profile'));
}
);
Breadcrumbs::register(
'change-password', function (Generator $breadcrumbs) {
$breadcrumbs->parent('profile');
$breadcrumbs->push('Change your password', route('change-password'));
$breadcrumbs->push(trans('breadcrumbs.changePassword'), route('change-password'));
}
);
@@ -252,26 +249,26 @@ Breadcrumbs::register(
Breadcrumbs::register(
'bills.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Bills', route('bills.index'));
$breadcrumbs->push(trans('breadcrumbs.bills'), route('bills.index'));
}
);
Breadcrumbs::register(
'bills.create', function (Generator $breadcrumbs) {
$breadcrumbs->parent('bills.index');
$breadcrumbs->push('Create new bill', route('bills.create'));
$breadcrumbs->push(trans('breadcrumbs.newBill'), route('bills.create'));
}
);
Breadcrumbs::register(
'bills.edit', function (Generator $breadcrumbs, Bill $bill) {
$breadcrumbs->parent('bills.show', $bill);
$breadcrumbs->push('Edit ' . e($bill->name), route('bills.edit', $bill->id));
$breadcrumbs->push(trans('breadcrumbs.edit_bill', ['name' => e($bill->name)]), route('bills.edit', $bill->id));
}
);
Breadcrumbs::register(
'bills.delete', function (Generator $breadcrumbs, Bill $bill) {
$breadcrumbs->parent('bills.show', $bill);
$breadcrumbs->push('Delete ' . e($bill->name), route('bills.delete', $bill->id));
$breadcrumbs->push(trans('breadcrumbs.delete_bill', ['name' => e($bill->name)]), route('bills.delete', $bill->id));
}
);
@@ -287,7 +284,7 @@ Breadcrumbs::register(
Breadcrumbs::register(
'reminders.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Reminders', route('reminders.index'));
$breadcrumbs->push(trans('breadcrumbs.reminders'), route('reminders.index'));
}
);
@@ -296,7 +293,7 @@ Breadcrumbs::register(
Breadcrumbs::register(
'reminders.show', function (Generator $breadcrumbs, Reminder $reminder) {
$breadcrumbs->parent('reminders.index');
$breadcrumbs->push('Reminder #' . $reminder->id, route('reminders.show', $reminder->id));
$breadcrumbs->push(trans('breadcrumbs.reminder', ['id' => e($reminder->id)]), route('reminders.show', $reminder->id));
}
);
@@ -306,28 +303,33 @@ Breadcrumbs::register(
Breadcrumbs::register(
'reports.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Reports', route('reports.index'));
$breadcrumbs->push(trans('breadcrumbs.reports'), route('reports.index'));
}
);
Breadcrumbs::register(
'reports.year', function (Generator $breadcrumbs, Carbon $date) {
'reports.year', function (Generator $breadcrumbs, Carbon $date, $shared) {
$breadcrumbs->parent('reports.index');
$breadcrumbs->push($date->year, route('reports.year', $date->year));
if ($shared) {
$title = trans('breadcrumbs.yearly_report_shared', ['date' => $date->year]);
} else {
$title = trans('breadcrumbs.yearly_report', ['date' => $date->year]);
}
$breadcrumbs->push($title, 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->year, $date->month]));
}
);
'reports.month', function (Generator $breadcrumbs, Carbon $date, $shared) {
$breadcrumbs->parent('reports.year', $date, $shared);
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->year, $date->month]));
if ($shared) {
$title = trans('breadcrumbs.monthly_report_shared', ['date' => $date->year]);
} else {
$title = trans('breadcrumbs.monthly_report', ['date' => $date->year]);
}
$breadcrumbs->push($title, route('reports.month', [$date->year, $date->month]));
}
);
@@ -335,7 +337,7 @@ Breadcrumbs::register(
Breadcrumbs::register(
'search', function (Generator $breadcrumbs, $query) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Search for "' . e($query) . '"', route('search'));
$breadcrumbs->push(trans('breadcrumbs.searchResult', ['query' => e($query)]), route('search'));
}
);
@@ -343,47 +345,26 @@ Breadcrumbs::register(
Breadcrumbs::register(
'transactions.index', function (Generator $breadcrumbs, $what) {
$breadcrumbs->parent('home');
switch ($what) {
case 'expenses':
case 'withdrawal':
$subTitle = 'Expenses';
break;
case 'revenue':
case 'deposit':
$subTitle = 'Revenue, income and deposits';
break;
case 'transfer':
case 'transfers':
$subTitle = 'Transfers';
break;
case 'opening balance':
$subTitle = 'Opening balances';
break;
default:
throw new FireflyException('Cannot handle $what "' . e($what) . '" in bread crumbs');
}
$breadcrumbs->push($subTitle, route('transactions.index', $what));
$breadcrumbs->push(trans('breadcrumbs.' . $what . '_list'), route('transactions.index', $what));
}
);
Breadcrumbs::register(
'transactions.create', function (Generator $breadcrumbs, $what) {
$breadcrumbs->parent('transactions.index', $what);
$breadcrumbs->push('Create new ' . e($what), route('transactions.create', $what));
$breadcrumbs->push(trans('breadcrumbs.create_' . e($what)), route('transactions.create', $what));
}
);
Breadcrumbs::register(
'transactions.edit', function (Generator $breadcrumbs, TransactionJournal $journal) {
$breadcrumbs->parent('transactions.show', $journal);
$breadcrumbs->push('Edit ' . e($journal->description), route('transactions.edit', $journal->id));
$breadcrumbs->push(trans('breadcrumbs.edit_journal', ['description' => $journal->description]), route('transactions.edit', $journal->id));
}
);
Breadcrumbs::register(
'transactions.delete', function (Generator $breadcrumbs, TransactionJournal $journal) {
$breadcrumbs->parent('transactions.show', $journal);
$breadcrumbs->push('Delete ' . e($journal->description), route('transactions.delete', $journal->id));
$breadcrumbs->push(trans('breadcrumbs.delete_journal', ['description' => e($journal->description)]), route('transactions.delete', $journal->id));
}
);
@@ -391,7 +372,7 @@ Breadcrumbs::register(
'transactions.show', function (Generator $breadcrumbs, TransactionJournal $journal) {
$breadcrumbs->parent('transactions.index', strtolower($journal->transactionType->type));
$breadcrumbs->push(e($journal->description), route('transactions.show', $journal->id));
$breadcrumbs->push($journal->description, route('transactions.show', $journal->id));
}
);
@@ -400,16 +381,32 @@ Breadcrumbs::register(
Breadcrumbs::register(
'tags.index', function (Generator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push('Tags', route('tags.index'));
$breadcrumbs->push(trans('breadcrumbs.tags'), route('tags.index'));
}
);
Breadcrumbs::register(
'tags.create', function (Generator $breadcrumbs) {
$breadcrumbs->parent('tags.index');
$breadcrumbs->push('Create tag', route('tags.create'));
$breadcrumbs->push(trans('breadcrumbs.createTag'), route('tags.create'));
}
);
Breadcrumbs::register(
'tags.edit', function (Generator $breadcrumbs, Tag $tag) {
$breadcrumbs->parent('tags.show', $tag);
$breadcrumbs->push(trans('breadcrumbs.edit_tag', ['tag' => e($tag->tag)]), route('tags.edit', $tag->id));
}
);
Breadcrumbs::register(
'tags.delete', function (Generator $breadcrumbs, Tag $tag) {
$breadcrumbs->parent('tags.show', $tag);
$breadcrumbs->push(trans('breadcrumbs.delete_tag', ['tag' => e($tag->tag)]), route('tags.delete', $tag->id));
}
);
Breadcrumbs::register(
'tags.show', function (Generator $breadcrumbs, Tag $tag) {
$breadcrumbs->parent('tags.index');

View File

@@ -223,7 +223,6 @@ Route::group(
Route::get('/bills/rescan/{bill}', ['uses' => 'BillController@rescan', 'as' => 'bills.rescan']); # rescan for matching.
Route::get('/bills/create', ['uses' => 'BillController@create', 'as' => 'bills.create']);
Route::get('/bills/edit/{bill}', ['uses' => 'BillController@edit', 'as' => 'bills.edit']);
Route::get('/bills/add/{bill}', ['uses' => 'BillController@add', 'as' => 'bills.add']);
Route::get('/bills/delete/{bill}', ['uses' => 'BillController@delete', 'as' => 'bills.delete']);
Route::get('/bills/show/{bill}', ['uses' => 'BillController@show', 'as' => 'bills.show']);
Route::post('/bills/store', ['uses' => 'BillController@store', 'as' => 'bills.store']);
@@ -273,22 +272,41 @@ Route::group(
/**
* Google Chart Controller
* ALL CHART Controllers
*/
Route::get('/chart/home/account', ['uses' => 'GoogleChartController@allAccountsBalanceChart']);
Route::get('/chart/home/budgets', ['uses' => 'GoogleChartController@allBudgetsHomeChart']);
Route::get('/chart/home/categories', ['uses' => 'GoogleChartController@allCategoriesHomeChart']);
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'])->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']);
Route::get('/chart/bills/{bill}', ['uses' => 'GoogleChartController@billOverview']);
Route::get('/chart/piggy-history/{piggyBank}', ['uses' => 'GoogleChartController@piggyBankHistory']);
Route::get('/chart/category/{category}/period', ['uses' => 'GoogleChartController@categoryPeriodChart']);
Route::get('/chart/category/{category}/overview', ['uses' => 'GoogleChartController@categoryOverviewChart']);
// accounts:
Route::get('/chart/account/frontpage', ['uses' => 'Chart\AccountController@frontpage']);
Route::get('/chart/account/month/{year}/{month}/{shared?}', ['uses' => 'Chart\AccountController@all'])->where(
['year' => '[0-9]{4}', 'month' => '[0-9]{1,2}', 'shared' => 'shared']
);
Route::get('/chart/account/{account}', ['uses' => 'Chart\AccountController@single']);
// bills:
Route::get('/chart/bill/frontpage', ['uses' => 'Chart\BillController@frontpage']);
Route::get('/chart/bill/{bill}', ['uses' => 'Chart\BillController@single']);
// budgets:
Route::get('/chart/budget/frontpage', ['uses' => 'Chart\BudgetController@frontpage']);
Route::get('/chart/budget/year/{year}/{shared?}', ['uses' => 'Chart\BudgetController@year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
Route::get('/chart/budget/{budget}/{limitrepetition}', ['uses' => 'Chart\BudgetController@budgetLimit']);
Route::get('/chart/budget/{budget}', ['uses' => 'Chart\BudgetController@budget']);
// categories:
Route::get('/chart/category/frontpage', ['uses' => 'Chart\CategoryController@frontpage']);
Route::get('/chart/category/year/{year}/{shared?}', ['uses' => 'Chart\CategoryController@year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
Route::get('/chart/category/{category}/month', ['uses' => 'Chart\CategoryController@month']); // should be period.
Route::get('/chart/category/{category}/all', ['uses' => 'Chart\CategoryController@all']);
// piggy banks:
Route::get('/chart/piggyBank/{piggyBank}', ['uses' => 'Chart\PiggyBankController@history']);
// reports:
Route::get('/chart/report/in-out/{year}/{shared?}', ['uses' => 'Chart\ReportController@yearInOut'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
Route::get('/chart/report/in-out-sum/{year}/{shared?}', ['uses' => 'Chart\ReportController@yearInOutSummarized'])->where(
['year' => '[0-9]{4}', 'shared' => 'shared']
);
/**
* Help Controller
@@ -306,10 +324,7 @@ Route::group(
Route::get('/json/box/out', ['uses' => 'JsonController@boxOut', 'as' => 'json.box.out']);
Route::get('/json/box/bills-unpaid', ['uses' => 'JsonController@boxBillsUnpaid', 'as' => 'json.box.paid']);
Route::get('/json/box/bills-paid', ['uses' => 'JsonController@boxBillsPaid', 'as' => 'json.box.unpaid']);
Route::get('/json/show-shared-reports', 'JsonController@showSharedReports');
Route::get('/json/transaction-journals/{what}', 'JsonController@transactionJournals');
Route::get('/json/show-shared-reports/set', 'JsonController@setSharedReports');
/**
* Piggy Bank Controller
@@ -355,19 +370,13 @@ Route::group(
* Report Controller
*/
Route::get('/reports', ['uses' => 'ReportController@index', 'as' => 'reports.index']);
Route::get('/reports/{year}', ['uses' => 'ReportController@year', 'as' => 'reports.year']);
Route::get('/reports/{year}/{month}', ['uses' => 'ReportController@month', 'as' => 'reports.month']);
Route::get('/reports/budget/{year}/{month}', ['uses' => 'ReportController@budget', 'as' => 'reports.budget']);
//Route::get('/reports/{year}', ['uses' => 'ReportController@year', 'as' => 'reports.year'])->where(['year' => '[0-9]{4}']);
Route::get('/reports/{year}/{shared?}', ['uses' => 'ReportController@year', 'as' => 'reports.year'])->where(['year' => '[0-9]{4}', 'shared' => 'shared']);
Route::get('/reports/{year}/{month}/{shared?}', ['uses' => 'ReportController@month', 'as' => 'reports.month'])->where(
['year' => '[0-9]{4}', 'month' => '[0-9]{1,2}', 'shared' => 'shared']
);
// pop ups for budget report:
Route::get('/reports/modal/{account}/{year}/{month}/no-budget', ['uses' => 'ReportController@modalNoBudget', 'as' => 'reports.no-budget']);
Route::get(
'/reports/modal/{account}/{year}/{month}/balanced-transfers',
['uses' => 'ReportController@modalBalancedTransfers', 'as' => 'reports.balanced-transfers']
);
Route::get(
'/reports/modal/{account}/{year}/{month}/left-unbalanced', ['uses' => 'ReportController@modalLeftUnbalanced', 'as' => 'reports.left-unbalanced']
);
/**
* Search Controller

View File

@@ -28,6 +28,7 @@ class Account extends Model
/**
* @param array $fields
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @return Account|null
*/
@@ -86,6 +87,7 @@ class Account extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function accountMeta()
@@ -94,6 +96,7 @@ class Account extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function accountType()
@@ -102,6 +105,7 @@ class Account extends Model
}
/**
* @codeCoverageIgnore
* @return array
*/
public function getDates()
@@ -110,6 +114,7 @@ class Account extends Model
}
/**
*
* @param $fieldName
*
* @return string|null
@@ -127,6 +132,8 @@ class Account extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string
@@ -144,6 +151,7 @@ class Account extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function piggyBanks()
@@ -152,6 +160,8 @@ class Account extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param array $types
*/
@@ -165,6 +175,8 @@ class Account extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param string $name
* @param string $value
@@ -181,6 +193,8 @@ class Account extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setNameAttribute($value)
@@ -190,6 +204,7 @@ class Account extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function transactions()
@@ -198,6 +213,7 @@ class Account extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()

View File

@@ -6,6 +6,7 @@ use Watson\Validating\ValidatingTrait;
/**
* Class AccountMeta
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class AccountMeta extends Model
@@ -22,6 +23,7 @@ class AccountMeta extends Model
protected $table = 'account_meta';
/**
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function account()

View File

@@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class AccountType
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class AccountType extends Model

View File

@@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class Budget
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class Budget extends Model
@@ -17,6 +18,7 @@ class Budget extends Model
protected $fillable = ['user_id', 'name'];
/**
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function budgetlimits()

View File

@@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class BudgetLimit
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class BudgetLimit extends Model

View File

@@ -8,6 +8,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class Category
*
*
* @package FireflyIII\Models
*/
class Category extends Model
@@ -17,6 +18,7 @@ class Category extends Model
protected $fillable = ['user_id', 'name'];
/**
* @codeCoverageIgnore
* @return array
*/
public function getDates()
@@ -25,6 +27,7 @@ class Category extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function transactionjournals()
@@ -34,6 +37,7 @@ class Category extends Model
/**
* @param array $fields
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @return Account|null
*/
@@ -66,6 +70,7 @@ class Category extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
@@ -74,6 +79,8 @@ class Category extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setNameAttribute($value)
@@ -83,6 +90,8 @@ class Category extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string
@@ -94,9 +103,7 @@ class Category extends Model
return Crypt::decrypt($value);
}
// @codeCoverageIgnoreStart
return $value;
// @codeCoverageIgnoreEnd
}
}

View File

@@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class Component
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class Component extends Model

View File

@@ -13,6 +13,7 @@ class LimitRepetition extends Model
{
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function budgetLimit()
@@ -21,6 +22,7 @@ class LimitRepetition extends Model
}
/**
* @codeCoverageIgnore
* @return array
*/
public function getDates()

View File

@@ -17,6 +17,7 @@ class PiggyBank extends Model
= ['name', 'account_id', 'order', 'reminder_skip', 'targetamount', 'startdate', 'targetdate', 'reminder', 'remind_me'];
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function account()
@@ -44,6 +45,7 @@ class PiggyBank extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function piggyBankRepetitions()
@@ -52,6 +54,7 @@ class PiggyBank extends Model
}
/**
* @codeCoverageIgnore
* @return array
*/
public function getDates()
@@ -60,6 +63,8 @@ class PiggyBank extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return int
@@ -70,6 +75,7 @@ class PiggyBank extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function piggyBankEvents()
@@ -78,6 +84,7 @@ class PiggyBank extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function reminders()
@@ -86,6 +93,8 @@ class PiggyBank extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setNameAttribute($value)
@@ -95,6 +104,8 @@ class PiggyBank extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string

View File

@@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class PiggyBankEvent
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class PiggyBankEvent extends Model

View File

@@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class PiggyBankRepetition
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class PiggyBankRepetition extends Model

View File

@@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class Preference
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class Preference extends Model

View File

@@ -17,6 +17,8 @@ class Reminder extends Model
protected $fillable = ['user_id', 'startdate', 'metadata', 'enddate', 'active', 'notnow', 'remindersable_id', 'remindersable_type',];
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return int
@@ -27,6 +29,7 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
* @return array
*/
public function getDates()
@@ -35,6 +38,8 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return mixed
@@ -49,6 +54,8 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return bool
@@ -59,6 +66,7 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function remindersable()
@@ -67,6 +75,8 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Carbon $start
* @param Carbon $end
@@ -79,6 +89,8 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
*
* @return $this
@@ -92,6 +104,8 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setMetadataAttribute($value)
@@ -101,6 +115,7 @@ class Reminder extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()

View File

@@ -29,6 +29,8 @@ class Tag extends Model
/**
* @param array $fields
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*
* @return Tag|null
*/
@@ -67,6 +69,7 @@ class Tag extends Model
}
/**
* @codeCoverageIgnore
* @return array
*/
public function getDates()
@@ -75,6 +78,8 @@ class Tag extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string
@@ -85,6 +90,8 @@ class Tag extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string
@@ -95,6 +102,8 @@ class Tag extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setDescriptionAttribute($value)
@@ -103,6 +112,8 @@ class Tag extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setTagAttribute($value)
@@ -111,6 +122,7 @@ class Tag extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function transactionjournals()
@@ -119,6 +131,7 @@ class Tag extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()

View File

@@ -9,6 +9,7 @@ use Watson\Validating\ValidatingTrait;
/**
* Class Transaction
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class Transaction extends Model

View File

@@ -4,8 +4,10 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
*
* Class TransactionCurrency
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class TransactionCurrency extends Model

View File

@@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class TransactionGroup
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class TransactionGroup extends Model

View File

@@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Query\JoinClause;
use Watson\Validating\ValidatingTrait;
/**
@@ -32,6 +33,7 @@ class TransactionJournal extends Model
];
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function bill()
@@ -40,6 +42,7 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function budgets()
@@ -48,6 +51,7 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function categories()
@@ -58,20 +62,90 @@ class TransactionJournal extends Model
/**
* @return float
*/
public function getAmountAttribute()
public function getActualAmountAttribute()
{
$amount = 0;
/** @var Transaction $t */
foreach ($this->transactions as $t) {
if ($t->amount > 0) {
return floatval($t->amount);
$amount = floatval($t->amount);
}
}
return 0;
return $amount;
}
/**
* @return Account|mixed
* @return float
*/
public function getAmountAttribute()
{
$amount = 0;
/** @var Transaction $t */
foreach ($this->transactions as $t) {
if ($t->amount > 0) {
$amount = floatval($t->amount);
}
}
/*
* If the journal has tags, it gets complicated.
*/
if ($this->tags->count() == 0) {
return $amount;
}
// if journal is part of advancePayment AND journal is a withdrawal,
// then journal is being repaid by other journals, so the actual amount will lower:
/** @var Tag $advancePayment */
$advancePayment = $this->tags()->where('tagMode', 'advancePayment')->first();
if ($advancePayment && $this->transactionType->type == 'Withdrawal') {
// loop other deposits, remove from our amount.
$others = $advancePayment->transactionJournals()->transactionTypes(['Deposit'])->get();
foreach ($others as $other) {
$amount -= $other->actualAmount;
}
return $amount;
}
// if this journal is part of an advancePayment AND the journal is a deposit,
// then the journal amount is correcting a withdrawal, and the amount is zero:
if ($advancePayment && $this->transactionType->type == 'Deposit') {
return 0;
}
// is balancing act?
$balancingAct = $this->tags()->where('tagMode', 'balancingAct')->first();
if ($balancingAct) {
// this is the transfer
// this is the expense:
if ($this->transactionType->type == 'Withdrawal') {
$transfer = $balancingAct->transactionJournals()->transactionTypes(['Transfer'])->first();
if ($transfer) {
$amount -= $transfer->actualAmount;
return $amount;
}
}
}
return $amount;
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags()
{
return $this->belongsToMany('FireflyIII\Models\Tag');
}
/**
* @return Account
*/
public function getAssetAccountAttribute()
{
@@ -90,10 +164,11 @@ class TransactionJournal extends Model
}
return $this->transactions()->first();
return $this->transactions()->first()->account;
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function transactions()
@@ -102,6 +177,29 @@ class TransactionJournal extends Model
}
/**
* @return float
*/
public function getCorrectedActualAmountAttribute()
{
$amount = 0;
$type = $this->transactionType->type;
/** @var Transaction $t */
foreach ($this->transactions as $t) {
if ($t->amount > 0 && $type != 'Withdrawal') {
$amount = floatval($t->amount);
break;
}
if ($t->amount < 0 && $type == 'Withdrawal') {
$amount = floatval($t->amount);
break;
}
}
return $amount;
}
/**
* @codeCoverageIgnore
* @return array
*/
public function getDates()
@@ -110,6 +208,8 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*
* @return string
@@ -120,12 +220,11 @@ class TransactionJournal extends Model
return Crypt::decrypt($value);
}
// @codeCoverageIgnoreStart
return $value;
// @codeCoverageIgnoreEnd
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function piggyBankEvents()
@@ -134,6 +233,8 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Account $account
*/
@@ -147,6 +248,8 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Carbon $date
*
@@ -158,6 +261,8 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Carbon $date
*
@@ -169,6 +274,8 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param $amount
*/
@@ -185,6 +292,8 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Carbon $date
*
@@ -196,6 +305,26 @@ class TransactionJournal extends Model
}
/**
* Returns the account to which the money was moved.
*
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param Account $account
*/
public function scopeToAccountIs(EloquentBuilder $query, Account $account)
{
$query->leftJoin(
'transactions', function (JoinClause $join) {
$join->on('transactions.transaction_journal_id', '=', 'transaction_journals.id')->where('transactions.amount', '>', 0);
}
);
$query->where('transactions.account_id', $account->id);
}
/**
* @codeCoverageIgnore
*
* @param EloquentBuilder $query
* @param array $types
*/
@@ -211,6 +340,7 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
* Automatically includes the 'with' parameters to get relevant related
* objects.
*
@@ -226,6 +356,8 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
*
* @param $value
*/
public function setDescriptionAttribute($value)
@@ -235,14 +367,7 @@ class TransactionJournal extends Model
}
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function tags()
{
return $this->belongsToMany('FireflyIII\Models\Tag');
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function transactionCurrency()
@@ -251,6 +376,7 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function transactionType()
@@ -259,6 +385,7 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function transactiongroups()
@@ -267,6 +394,7 @@ class TransactionJournal extends Model
}
/**
* @codeCoverageIgnore
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()

View File

@@ -5,6 +5,7 @@ use Illuminate\Database\Eloquent\Model;
/**
* Class TransactionRelation
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class TransactionRelation extends Model

View File

@@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class TransactionType
*
* @codeCoverageIgnore
* @package FireflyIII\Models
*/
class TransactionType extends Model

View File

@@ -17,6 +17,8 @@ class ConfigServiceProvider extends ServiceProvider
* to overwrite any "vendor" or package configuration that you may want to
* modify before the application handles the incoming request / command.
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*
* @return void
*/
public function register()
@@ -163,6 +165,7 @@ class ConfigServiceProvider extends ServiceProvider
'Session',
'Route',
'Auth',
'Lang',
'URL',
'Config',
'ExpandedForm' => [

View File

@@ -49,7 +49,47 @@ class EventServiceProvider extends ServiceProvider
public function boot(DispatcherContract $events)
{
parent::boot($events);
$this->registerDeleteEvents();
$this->registerCreateEvents();
BudgetLimit::saved(
function (BudgetLimit $budgetLimit) {
$end = Navigation::addPeriod(clone $budgetLimit->startdate, $budgetLimit->repeat_freq, 0);
$end->subDay();
$set = $budgetLimit->limitrepetitions()->where('startdate', $budgetLimit->startdate->format('Y-m-d'))->where('enddate', $end->format('Y-m-d'))
->get();
if ($set->count() == 0) {
$repetition = new LimitRepetition;
$repetition->startdate = $budgetLimit->startdate;
$repetition->enddate = $end;
$repetition->amount = $budgetLimit->amount;
$repetition->budgetLimit()->associate($budgetLimit);
try {
$repetition->save();
} catch (QueryException $e) {
Log::error('Trying to save new LimitRepetition failed!');
Log::error($e->getMessage());
}
} else {
if ($set->count() == 1) {
$repetition = $set->first();
$repetition->amount = $budgetLimit->amount;
$repetition->save();
}
}
}
);
}
/**
*
*/
protected function registerDeleteEvents()
{
TransactionJournal::deleted(
function (TransactionJournal $journal) {
@@ -59,8 +99,6 @@ class EventServiceProvider extends ServiceProvider
}
}
);
PiggyBank::deleting(
function (PiggyBank $piggyBank) {
$reminders = $piggyBank->reminders()->get();
@@ -82,6 +120,14 @@ class EventServiceProvider extends ServiceProvider
}
);
}
/**
*
*/
protected function registerCreateEvents()
{
// move this routine to a filter
// in case of repeated piggy banks and/or other problems.
PiggyBank::created(
@@ -94,47 +140,6 @@ class EventServiceProvider extends ServiceProvider
$repetition->save();
}
);
BudgetLimit::saved(
function (BudgetLimit $budgetLimit) {
$end = Navigation::addPeriod(clone $budgetLimit->startdate, $budgetLimit->repeat_freq, 0);
$end->subDay();
$set = $budgetLimit->limitrepetitions()->where('startdate', $budgetLimit->startdate->format('Y-m-d'))->where('enddate', $end->format('Y-m-d'))
->get();
/*
* Create new LimitRepetition:
*/
if ($set->count() == 0) {
$repetition = new LimitRepetition;
$repetition->startdate = $budgetLimit->startdate;
$repetition->enddate = $end;
$repetition->amount = $budgetLimit->amount;
$repetition->budgetLimit()->associate($budgetLimit);
try {
$repetition->save();
} catch (QueryException $e) {
Log::error('Trying to save new LimitRepetition failed!');
Log::error($e->getMessage());
}
} else {
if ($set->count() == 1) {
/*
* Update existing one.
*/
$repetition = $set->first();
$repetition->amount = $budgetLimit->amount;
$repetition->save();
}
}
}
);
}
}

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