mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 10:47:00 +00:00 
			
		
		
		
	Merge branch 'release/4.7.6'
This commit is contained in:
		
							
								
								
									
										11
									
								
								.deploy/docker/cronjob.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.deploy/docker/cronjob.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| [program:cron] | ||||
| command=/usr/sbin/cron -f -L 15 | ||||
| user=root | ||||
| autostart=true | ||||
| autorestart=true | ||||
| stdout_events_enabled=true | ||||
| stderr_events_enabled=true | ||||
| stdout_logfile=/dev/stdout | ||||
| stdout_logfile_maxbytes=0 | ||||
| startsecs=10 | ||||
| startretries=3 | ||||
| @@ -22,8 +22,8 @@ chmod -R 775 $FIREFLY_PATH/storage | ||||
| # remove any lingering files that may break upgrades: | ||||
| rm -f $FIREFLY_PATH/storage/logs/laravel.log | ||||
|  | ||||
| cat .env.docker | envsubst > .env && cat .env | ||||
| cat .env.docker | envsubst > .env | ||||
| composer dump-autoload | ||||
| php artisan package:discover | ||||
| php artisan firefly:instructions install | ||||
| exec apache2-foreground | ||||
| exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf --nodaemon | ||||
							
								
								
									
										6
									
								
								.deploy/docker/firefly-iii.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.deploy/docker/firefly-iii.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| [program:apache2] | ||||
| command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND" | ||||
| stdout_events_enabled=true | ||||
| stderr_events_enabled=true | ||||
| stdout_logfile=/dev/stdout | ||||
| stdout_logfile_maxbytes=0 | ||||
							
								
								
									
										30
									
								
								.deploy/docker/supervisord.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								.deploy/docker/supervisord.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| # supervisor config file | ||||
| # Adapted from the config file distributed with the supervisor package on Debian | ||||
| # Jessie | ||||
|  | ||||
| # Enable supervisord in non-daemon mode. Disable the logfile as we receive | ||||
| # log messages via stdout/err. Set up the child process log directory in case | ||||
| # the user doesn't set logging to stdout/err. | ||||
| [supervisord] | ||||
| nodaemon = true | ||||
| logfile = NONE | ||||
| pidfile = /var/run/supervisord.pid | ||||
| childlogdir = /var/log/supervisor | ||||
| loglevel=debug | ||||
|  | ||||
| # Enable supervisorctl via RPC interface over Unix socket | ||||
| [unix_http_server] | ||||
| file = /var/run/supervisor.sock | ||||
| chmod = 0700 | ||||
|  | ||||
| [rpcinterface:supervisor] | ||||
| supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface | ||||
|  | ||||
| [supervisorctl] | ||||
| serverurl = unix:///var/run/supervisor.sock | ||||
|  | ||||
|  | ||||
| # Include conf files for child processes | ||||
| # Debian/Ubuntu packages use /etc/supervisor/conf.d | ||||
| [include] | ||||
| files = /etc/supervisor/conf.d/*.conf | ||||
							
								
								
									
										26
									
								
								.deploy/docker/vhost.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.deploy/docker/vhost.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| server { | ||||
|     listen 80 default_server; | ||||
|  | ||||
|     server_name  _ *.vm docker; | ||||
|  | ||||
|     root "/app/public"; | ||||
|     index index.php; | ||||
|  | ||||
|     include /opt/docker/etc/nginx/vhost.common.d/*.conf; | ||||
| } | ||||
|  | ||||
| ############## | ||||
| # SSL | ||||
| ############## | ||||
|  | ||||
| server { | ||||
|     listen 443 default_server; | ||||
|  | ||||
|     server_name  _ *.vm docker; | ||||
|  | ||||
|     root "/app/public"; | ||||
|     index index.php; | ||||
|  | ||||
|     include /opt/docker/etc/nginx/vhost.common.d/*.conf; | ||||
|     include /opt/docker/etc/nginx/vhost.ssl.conf; | ||||
| } | ||||
							
								
								
									
										36
									
								
								.env.docker
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								.env.docker
									
									
									
									
									
								
							| @@ -13,15 +13,31 @@ SITE_OWNER=${SITE_OWNER} | ||||
| # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it | ||||
| APP_KEY=${FF_APP_KEY} | ||||
|  | ||||
| # APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy. | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=UTC | ||||
|  | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=${APP_URL} | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES=${TRUSTED_PROXIES} | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| LOG_CHANNEL=${LOG_CHANNEL} | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=stdout | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=${APP_LOG_LEVEL} | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # If you use SQLite, set connection to `sqlite` and remove the database, username and password settings. | ||||
| # For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html | ||||
| DB_CONNECTION=${FF_DB_CONNECTION} | ||||
| DB_HOST=${FF_DB_HOST} | ||||
| DB_PORT=${FF_DB_PORT} | ||||
| @@ -29,17 +45,6 @@ DB_DATABASE=${FF_DB_NAME} | ||||
| DB_USERNAME=${FF_DB_USER} | ||||
| DB_PASSWORD=${FF_DB_PASSWORD} | ||||
|  | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog' and 'errorlog' which will log to the system itself. | ||||
| APP_LOG=syslog | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=info | ||||
|  | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| @@ -103,4 +108,5 @@ IS_DOCKER=true | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| TZ=${TZ} | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|   | ||||
							
								
								
									
										29
									
								
								.env.example
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								.env.example
									
									
									
									
									
								
							| @@ -15,15 +15,27 @@ APP_KEY=SomeRandomStringOf32CharsExactly | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=UTC | ||||
| TZ=${TZ} | ||||
|  | ||||
| # APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy. | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=daily | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=notice | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html | ||||
| DB_CONNECTION=mysql | ||||
| @@ -33,17 +45,6 @@ DB_DATABASE=homestead | ||||
| DB_USERNAME=homestead | ||||
| DB_PASSWORD=secret | ||||
|  | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog' and 'errorlog' which will log to the system itself. | ||||
| APP_LOG=daily | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=notice | ||||
|  | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| @@ -105,7 +106,7 @@ DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|   | ||||
							
								
								
									
										31
									
								
								.env.heroku
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								.env.heroku
									
									
									
									
									
								
							| @@ -17,12 +17,24 @@ APP_KEY=7ahyYVPVsmxjdhsweWCauGeJfwc92NP2 | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=UTC | ||||
|  | ||||
| # APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy. | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES=** | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| LOG_CHANNEL=syslog | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=stdout | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=debug | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # If you use SQLite, set connection to `sqlite` and remove the database, username and password settings. | ||||
| @@ -33,17 +45,6 @@ DB_CONNECTION=pgsql | ||||
|  | ||||
|  | ||||
|  | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog' and 'errorlog' which will log to the system itself. | ||||
| APP_LOG=errorlog | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=debug | ||||
|  | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| @@ -105,7 +106,7 @@ DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| IS_HEROKU=true | ||||
| BUNQ_USE_SANDBOX=false | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|   | ||||
| @@ -17,12 +17,24 @@ APP_KEY=SomeRandomStringOf32CharsExactly | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=UTC | ||||
|  | ||||
| # APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy. | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| LOG_CHANNEL=syslog | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=stdout | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=debug | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # If you use SQLite, set connection to `sqlite` and remove the database, username and password settings. | ||||
| @@ -33,17 +45,6 @@ DB_DATABASE=firefly | ||||
| DB_USERNAME=firefly | ||||
| DB_PASSWORD=firefly | ||||
|  | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog' and 'errorlog' which will log to the system itself. | ||||
| APP_LOG=syslog | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=info | ||||
|  | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| @@ -105,7 +106,7 @@ DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=true | ||||
| BUNQ_USE_SANDBOX=false | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|   | ||||
							
								
								
									
										29
									
								
								.env.testing
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								.env.testing
									
									
									
									
									
								
							| @@ -17,21 +17,18 @@ APP_KEY=TestTestTestTestTestTestTestTest | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=Europe/Amsterdam | ||||
|  | ||||
| # APP_URL and TRUSTED_PROXIES are useful when using Docker and/or a reverse proxy. | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| LOG_CHANNEL=dailytest | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html | ||||
| DB_CONNECTION=sqlite | ||||
|  | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog' and 'errorlog' which will log to the system itself. | ||||
| APP_LOG=daily | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=dailytest | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| @@ -39,6 +36,15 @@ APP_LOG=daily | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=debug | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html | ||||
| DB_CONNECTION=sqlite | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| @@ -64,6 +70,9 @@ MAILGUN_SECRET= | ||||
| MANDRILL_SECRET= | ||||
| SPARKPOST_SECRET= | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=false | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| MAPBOX_API_KEY= | ||||
| @@ -97,7 +106,7 @@ DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=false | ||||
| BUNQ_USE_SANDBOX=true | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=true | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|   | ||||
| @@ -1,3 +1,46 @@ | ||||
| # 4.7.6 | ||||
| - [Issue 145](https://github.com/firefly-iii/firefly-iii/issues/145) You can now download transactions from YNAB. | ||||
| - [Issue 306](https://github.com/firefly-iii/firefly-iii/issues/306) You can now add liabilities to Firefly III. | ||||
| - [Issue 740](https://github.com/firefly-iii/firefly-iii/issues/740) Various charts are now currency aware. | ||||
| - [Issue 833](https://github.com/firefly-iii/firefly-iii/issues/833) Bills can use non-default currencies. | ||||
| - [Issue 1578](https://github.com/firefly-iii/firefly-iii/issues/1578) Firefly III will notify you if the cron job hasn't fired. | ||||
| - [Issue 1623](https://github.com/firefly-iii/firefly-iii/issues/1623) New transactions will link back from the success message. | ||||
| - [Issue 1624](https://github.com/firefly-iii/firefly-iii/issues/1624) transactions will link to the object. | ||||
| - You can call the cron job over the web now (see docs). | ||||
| - You don't need to call the cron job every minute any more. | ||||
| - Various charts are now red/green to signify income and expenses. | ||||
| - Option to add or remove accounts from the net worth calculations. | ||||
| - This will be the last release on PHP 7.1. Future versions will require PHP 7.2. | ||||
| - [Issue 1460](https://github.com/firefly-iii/firefly-iii/issues/1460) Downloading transactions from bunq should go more smoothly. | ||||
| - [Issue 1464](https://github.com/firefly-iii/firefly-iii/issues/1464) Fixed the docker file to work on Raspberry Pi's. | ||||
| - [Issue 1540](https://github.com/firefly-iii/firefly-iii/issues/1540) The Docker file now has a working cron job for recurring transactions. | ||||
| - [Issue 1564](https://github.com/firefly-iii/firefly-iii/issues/1564) Fix double transfers when importing from bunq. | ||||
| - [Issue 1575](https://github.com/firefly-iii/firefly-iii/issues/1575) Some views would give a XSRF token warning | ||||
| - [Issue 1576](https://github.com/firefly-iii/firefly-iii/issues/1576) Fix assigning budgets | ||||
| - [Issue 1580](https://github.com/firefly-iii/firefly-iii/issues/1580) Missing string for translation | ||||
| - [Issue 1581](https://github.com/firefly-iii/firefly-iii/issues/1581) Expand help text | ||||
| - [Issue 1584](https://github.com/firefly-iii/firefly-iii/issues/1584) Link to administration is back. | ||||
| - [Issue 1586](https://github.com/firefly-iii/firefly-iii/issues/1586) Date fields in import were mislabeled. | ||||
| - [Issue 1593](https://github.com/firefly-iii/firefly-iii/issues/1593) Link types are translatable. | ||||
| - [Issue 1594](https://github.com/firefly-iii/firefly-iii/issues/1594) Very long breadcrumbs are weird. | ||||
| - [Issue 1598](https://github.com/firefly-iii/firefly-iii/issues/1598) Fix budget calculations. | ||||
| - [Issue 1597](https://github.com/firefly-iii/firefly-iii/issues/1597) Piggy banks are always inactive. | ||||
| - [Issue 1605](https://github.com/firefly-iii/firefly-iii/issues/1605) System will ignore foreign currency setting if user doesn't indicate the amount. | ||||
| - [Issue 1607](https://github.com/firefly-iii/firefly-iii/issues/1607) Firefly III trusts the Heroku load balancer, fixing deployment on Heroku. | ||||
| - [Issue 1608](https://github.com/firefly-iii/firefly-iii/issues/1608) Spelling error in command line import. | ||||
| - [Issue 1609](https://github.com/firefly-iii/firefly-iii/issues/1609) Link to budgets page was absolute. | ||||
| - [Issue 1615](https://github.com/firefly-iii/firefly-iii/issues/1615) Fix currency bug in transactions. | ||||
| - [Issue 1616](https://github.com/firefly-iii/firefly-iii/issues/1616) Fix null pointer exception in pie charts. | ||||
| - [Issue 1617](https://github.com/firefly-iii/firefly-iii/issues/1617) Fix for complex tag names in URL's. | ||||
| - [Issue 1620](https://github.com/firefly-iii/firefly-iii/issues/1620) Fixed index reference in API. | ||||
| - [Issue 1642](https://github.com/firefly-iii/firefly-iii/issues/1642) Fix issue with split journals. | ||||
| - [Issue 1643](https://github.com/firefly-iii/firefly-iii/issues/1643) Fix reconciliation issue. | ||||
| - Users can no longer give expenses a budget. | ||||
| - Fix bug in Spectre import. | ||||
| - Heroku would not make you owner. | ||||
| - Add `.htaccess` files to all public directories. | ||||
| - New secure headers will make Firefly III slightly more secure. | ||||
|  | ||||
| # 4.7.5.3 | ||||
| - [Issue 1527](https://github.com/firefly-iii/firefly-iii/issues/1527), fixed views for transactions without a budget. | ||||
| - [Issue 1553](https://github.com/firefly-iii/firefly-iii/issues/1553), report could not handle transactions before the first one in the system. | ||||
|   | ||||
| @@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = ( | ||||
|  | ||||
|   manifest = ( | ||||
|     appTitle = (defaultText = "Firefly III"), | ||||
|     appVersion = 15, | ||||
|     appMarketingVersion = (defaultText = "4.7.5.3"), | ||||
|     appVersion = 16, | ||||
|     appMarketingVersion = (defaultText = "4.7.6"), | ||||
|  | ||||
|     actions = [ | ||||
|       # Define your "new document" handlers here. | ||||
|   | ||||
							
								
								
									
										61
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										61
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,12 +1,16 @@ | ||||
| # use PHP 7.1 and Apache as a base. | ||||
| FROM php:7.1-apache | ||||
|  | ||||
| # set working dir | ||||
| ENV FIREFLY_PATH /var/www/firefly-iii | ||||
| # If building on a RPi, use --build-arg cores=3 to use all cores when compiling | ||||
| # to speed up the image build | ||||
| ARG CORES | ||||
| ENV CORES ${CORES:-1} | ||||
|  | ||||
| ENV FIREFLY_PATH /var/www/firefly-iii/ | ||||
| ENV CURL_VERSION 7.60.0 | ||||
| ENV OPENSSL_VERSION 1.1.1-pre6 | ||||
| WORKDIR $FIREFLY_PATH | ||||
| ADD . $FIREFLY_PATH | ||||
|  | ||||
| LABEL version="1.0" maintainer="thegrumpydictator@gmail.com" | ||||
|  | ||||
|  | ||||
| # install packages | ||||
| RUN apt-get update -y && \ | ||||
| @@ -19,48 +23,62 @@ RUN apt-get update -y && \ | ||||
|                                                libedit-dev \ | ||||
|                                                libtidy-dev \ | ||||
|                                                libxml2-dev \ | ||||
|                                                unzip \ | ||||
|                                                libsqlite3-dev \ | ||||
|                                                nano \ | ||||
|                                                libpq-dev \ | ||||
|                                                libbz2-dev \ | ||||
|                                                gettext-base \ | ||||
|                                                cron \ | ||||
|                                                rsyslog \ | ||||
|                                                supervisor \ | ||||
|                                                locales && \ | ||||
|                                                apt-get clean && \ | ||||
|                                                rm -rf /var/lib/apt/lists/* | ||||
|  | ||||
| # Setup the Composer installer | ||||
| RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer | ||||
|  | ||||
| # Install latest curl | ||||
| RUN cd /tmp && \ | ||||
|     wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz && \ | ||||
|     tar -xvf openssl-${OPENSSL_VERSION}.tar.gz && \ | ||||
|     cd openssl-${OPENSSL_VERSION} && \ | ||||
|     ./config && \ | ||||
|     make && \ | ||||
|     make -j${CORES} && \ | ||||
|     make install | ||||
|  | ||||
| RUN cd /tmp && \ | ||||
|     wget https://curl.haxx.se/download/curl-${CURL_VERSION}.tar.gz && \ | ||||
|     tar -xvf curl-${CURL_VERSION}.tar.gz && \ | ||||
|     cd curl-${CURL_VERSION} && \ | ||||
|     ./configure --with-ssl && \ | ||||
|     make && \ | ||||
|     ./configure --with-ssl --host=$(gcc -dumpmachine) && \ | ||||
|     make -j${CORES} && \ | ||||
|     make install | ||||
|  | ||||
| # Make sure that libcurl is using the newer curl libaries | ||||
| RUN echo "/usr/local/lib" >> /etc/ld.so.conf.d/00-curl.conf && ldconfig | ||||
|  | ||||
| # Create the log file to be able to run tail | ||||
| RUN touch /var/log/cron.log | ||||
| # Mimic the Debian/Ubuntu config file structure for supervisor | ||||
| COPY .deploy/docker/supervisord.conf /etc/supervisor/supervisord.conf | ||||
| RUN mkdir -p /etc/supervisor/conf.d /var/log/supervisor | ||||
|  | ||||
| # Setup cron job | ||||
| RUN (crontab -l ; echo "* * * * * root $FIREFLY_PATH/artisan schedule:run >> /var/log/cron.log") | crontab | ||||
| # copy Firefly III supervisor conf file. | ||||
| COPY ./.deploy/docker/firefly-iii.conf /etc/supervisor/conf.d/firefly-iii.conf | ||||
|  | ||||
| # copy cron job supervisor conf file. | ||||
| COPY ./.deploy/docker/cronjob.conf /etc/supervisor/conf.d/cronjob.conf | ||||
|  | ||||
| # test crons added via crontab | ||||
| RUN echo "0 3 * * * /usr/local/bin/php /var/www/firefly-iii/artisan firefly:cron" | crontab - | ||||
| #RUN (crontab -l ; echo "*/1 * * * * free >> /var/www/firefly-iii/public/cron.html") 2>&1 | crontab - | ||||
| # Install PHP exentions. | ||||
| RUN docker-php-ext-install -j$(nproc) curl gd intl json readline tidy zip bcmath xml mbstring pdo_sqlite pdo_mysql bz2 pdo_pgsql | ||||
| RUN docker-php-ext-install -j$(nproc) gd intl tidy zip bcmath pdo_mysql bz2 pdo_pgsql | ||||
|  | ||||
| # Install composer | ||||
| RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer | ||||
|  | ||||
| # Generate locales supported by Firefly III | ||||
| RUN echo "en_US.UTF-8 UTF-8\nde_DE.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nit_IT.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8\nru_RU.UTF-8 UTF-8\ntr_TR.UTF-8 UTF-8\n\n" > /etc/locale.gen && locale-gen | ||||
|  | ||||
|  | ||||
| # copy Apache config to correct spot. | ||||
| COPY ./.deploy/docker/apache2.conf /etc/apache2/apache2.conf | ||||
|  | ||||
| @@ -70,7 +88,7 @@ RUN a2enmod rewrite | ||||
| # Enable apache mod ssl.. | ||||
| RUN a2enmod ssl | ||||
|  | ||||
| # Create volumes for several directories: | ||||
| # Create volumes | ||||
| VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload | ||||
|  | ||||
| # Enable default site (Firefly III) | ||||
| @@ -79,15 +97,16 @@ COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-defau | ||||
| # Make sure we own Firefly III directory | ||||
| RUN chown -R www-data:www-data /var/www && chmod -R 775 $FIREFLY_PATH/storage | ||||
|  | ||||
| # Copy in Firefly Source | ||||
| WORKDIR $FIREFLY_PATH | ||||
| ADD . $FIREFLY_PATH | ||||
|  | ||||
| # Run composer | ||||
| ENV COMPOSER_ALLOW_SUPERUSER 1 | ||||
| RUN composer install --prefer-dist --no-dev --no-scripts --no-suggest | ||||
|  | ||||
| # Expose port 80 | ||||
| EXPOSE 80 | ||||
|  | ||||
| # Run the command on container startup | ||||
| CMD cron | ||||
|  | ||||
| # Run entrypoint thing | ||||
| ENTRYPOINT [".deploy/docker/entrypoint.sh"] | ||||
|  | ||||
|   | ||||
| @@ -221,6 +221,11 @@ class AccountController extends Controller | ||||
|             'special'                    => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION, | ||||
|                                              AccountType::LOAN,], | ||||
|             'hidden'                     => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION, AccountType::LOAN,], | ||||
|             'liability'                  => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD], | ||||
|             'liabilities'                => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD], | ||||
|             'cc'                         => [AccountType::CREDITCARD], | ||||
|             'creditcard'                 => [AccountType::CREDITCARD], | ||||
|             'credit_card'                => [AccountType::CREDITCARD], | ||||
|             AccountType::DEFAULT         => [AccountType::DEFAULT], | ||||
|             AccountType::CASH            => [AccountType::CASH], | ||||
|             AccountType::ASSET           => [AccountType::ASSET], | ||||
| @@ -231,6 +236,10 @@ class AccountController extends Controller | ||||
|             AccountType::IMPORT          => [AccountType::IMPORT], | ||||
|             AccountType::RECONCILIATION  => [AccountType::RECONCILIATION], | ||||
|             AccountType::LOAN            => [AccountType::LOAN], | ||||
|             AccountType::MORTGAGE        => [AccountType::MORTGAGE], | ||||
|             AccountType::DEBT            => [AccountType::DEBT], | ||||
|             AccountType::CREDITCARD      => [AccountType::CREDITCARD], | ||||
|  | ||||
|         ]; | ||||
|         $return = $types['all']; | ||||
|         if (isset($types[$type])) { | ||||
|   | ||||
| @@ -152,7 +152,10 @@ class AvailableBudgetController extends Controller | ||||
|     public function store(AvailableBudgetRequest $request): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getAll(); | ||||
|         $currency = $this->currencyRepository->findNull($data['transaction_currency_id']); | ||||
|         $currency = $this->currencyRepository->findNull($data['currency_id']); | ||||
|         if (null === $currency) { | ||||
|             $currency = $this->currencyRepository->findByCodeNull($data['currency_code']); | ||||
|         } | ||||
|         if (null === $currency) { | ||||
|             throw new FireflyException('Could not find the indicated currency.'); | ||||
|         } | ||||
| @@ -166,6 +169,8 @@ class AvailableBudgetController extends Controller | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|   | ||||
| @@ -34,7 +34,6 @@ use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
|  | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
|   | ||||
| @@ -54,6 +54,7 @@ class ConfigurationController extends Controller | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 if (!$this->repository->hasRole($admin, 'owner')) { | ||||
|                     /** @noinspection ExceptionsAnnotatingAndHandlingInspection */ | ||||
|                     throw new FireflyException('No access to method.'); // @codeCoverageIgnore | ||||
|                 } | ||||
|  | ||||
|   | ||||
| @@ -175,8 +175,7 @@ class JournalLinkController extends Controller | ||||
|         $data['direction'] = 'inward'; | ||||
|  | ||||
|         $journalLink = $this->repository->storeLink($data, $inward, $outward); | ||||
|  | ||||
|         $resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links'); | ||||
|         $resource    = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|   | ||||
| @@ -161,7 +161,7 @@ class PiggyBankController extends Controller | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new piggy bank.'); // @codeCoverageIgnore | ||||
|         throw new FireflyException('Could not store new piggy bank.'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -101,7 +101,7 @@ class RuleController extends Controller | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.piggy_banks.index') . $this->buildParams()); | ||||
|         $paginator->setPath(route('api.v1.rules.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|   | ||||
| @@ -95,7 +95,7 @@ class RuleGroupController extends Controller | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         // get list of rule groups. Count it and split it. | ||||
|         $collection = $this->ruleGroupRepository->get(); | ||||
|         $count      = $collection->count(); | ||||
|         $ruleGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|   | ||||
| @@ -26,7 +26,7 @@ namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\TransactionRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\JournalCollectorInterface; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Helpers\Filter\NegativeAmountFilter; | ||||
| use FireflyIII\Helpers\Filter\PositiveAmountFilter; | ||||
| @@ -108,8 +108,8 @@ class TransactionController extends Controller | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var JournalCollectorInterface $collector */ | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
| @@ -123,7 +123,7 @@ class TransactionController extends Controller | ||||
|         } | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedJournals(); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
| @@ -155,7 +155,7 @@ class TransactionController extends Controller | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         // collect transactions using the journal collector | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser(auth()->user()); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         // filter on specific journals. | ||||
| @@ -170,7 +170,7 @@ class TransactionController extends Controller | ||||
|             $collector->addFilter(NegativeAmountFilter::class); | ||||
|         } | ||||
|  | ||||
|         $transactions = $collector->getJournals(); | ||||
|         $transactions = $collector->getTransactions(); | ||||
|         $resource     = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
| @@ -201,7 +201,7 @@ class TransactionController extends Controller | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         // collect transactions using the journal collector | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser(auth()->user()); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         // filter on specific journals. | ||||
| @@ -216,7 +216,7 @@ class TransactionController extends Controller | ||||
|             $collector->addFilter(NegativeAmountFilter::class); | ||||
|         } | ||||
|  | ||||
|         $transactions = $collector->getJournals(); | ||||
|         $transactions = $collector->getTransactions(); | ||||
|         $resource     = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
| @@ -247,7 +247,7 @@ class TransactionController extends Controller | ||||
|  | ||||
|         // needs a lot of extra data to match the journal collector. Or just expand that one. | ||||
|         // collect transactions using the journal collector | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser(auth()->user()); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         // filter on specific journals. | ||||
| @@ -262,7 +262,7 @@ class TransactionController extends Controller | ||||
|             $collector->addFilter(NegativeAmountFilter::class); | ||||
|         } | ||||
|  | ||||
|         $transactions = $collector->getJournals(); | ||||
|         $transactions = $collector->getTransactions(); | ||||
|         $resource     = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|   | ||||
| @@ -50,6 +50,7 @@ class AccountRequest extends Request | ||||
|         $data = [ | ||||
|             'name'                 => $this->string('name'), | ||||
|             'active'               => $this->boolean('active'), | ||||
|             'include_net_worth'    => $this->boolean('include_net_worth'), | ||||
|             'accountType'          => $this->string('type'), | ||||
|             'account_type_id'      => null, | ||||
|             'currency_id'          => $this->integer('currency_id'), | ||||
| @@ -64,7 +65,21 @@ class AccountRequest extends Request | ||||
|             'ccType'               => $this->string('cc_type'), | ||||
|             'ccMonthlyPaymentDate' => $this->string('cc_monthly_payment_date'), | ||||
|             'notes'                => $this->string('notes'), | ||||
|             'interest'             => $this->string('interest'), | ||||
|             'interest_period'      => $this->string('interest_period'), | ||||
|         ]; | ||||
|         // new fields for liabilities | ||||
|         //            'liability_type'       => $this->string('liability_type'), | ||||
|         //            'liability_start_date' => $this->date('liability_start_date'), | ||||
|  | ||||
|  | ||||
|         //]; | ||||
|         if ('liability' === $data['accountType']) { | ||||
|             $data['openingBalance']     = bcmul($this->string('liability_amount'), '-1'); | ||||
|             $data['openingBalanceDate'] = $this->date('liability_start_date'); | ||||
|             $data['accountType']        = $this->string('liability_type'); | ||||
|             $data['account_type_id']    = null; | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| @@ -91,10 +106,18 @@ class AccountRequest extends Request | ||||
|             'account_number'          => 'between:1,255|nullable|uniqueAccountNumberForUser', | ||||
|             'account_role'            => 'in:' . $accountRoles . '|required_if:type,asset', | ||||
|             'active'                  => 'required|boolean', | ||||
|             'include_net_worth'       => 'required|boolean', | ||||
|             'cc_type'                 => 'in:' . $ccPaymentTypes . '|required_if:account_role,ccAsset', | ||||
|             'cc_monthly_payment_date' => 'date' . '|required_if:account_role,ccAsset|required_if:cc_type,monthlyFull', | ||||
|             'type'                    => 'required|in:' . $types, | ||||
|             'notes'                   => 'min:0|max:65536', | ||||
|             // required fields for liabilities: | ||||
|             'liability_type'          => 'required_if:type,liability|in:loan,debt,mortgage,credit card', | ||||
|             'liability_amount'        => 'required_if:type,liability|min:0|numeric', | ||||
|             'liability_start_date'    => 'required_if:type,liability|date', | ||||
|             'interest'                => 'required_if:type,liability|between:0,100|numeric', | ||||
|             'interest_period'         => 'required_if:type,liability|in:daily,monthly,yearly', | ||||
|  | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|   | ||||
| @@ -47,10 +47,11 @@ class AvailableBudgetRequest extends Request | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'transaction_currency_id' => $this->integer('transaction_currency_id'), | ||||
|             'amount'                  => $this->string('amount'), | ||||
|             'start_date'              => $this->date('start_date'), | ||||
|             'end_date'                => $this->date('end_date'), | ||||
|             'currency_id'   => $this->integer('currency_id'), | ||||
|             'currency_code' => $this->string('currency_code'), | ||||
|             'amount'        => $this->string('amount'), | ||||
|             'start_date'    => $this->date('start_date'), | ||||
|             'end_date'      => $this->date('end_date'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| @@ -62,10 +63,11 @@ class AvailableBudgetRequest extends Request | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'transaction_currency_id' => 'required|numeric|exists:transaction_currencies,id', | ||||
|             'amount'                  => 'required|numeric|more:0', | ||||
|             'start_date'              => 'required|date|before:end_date', | ||||
|             'end_date'                => 'required|date|after:start_date', | ||||
|             'currency_id'   => 'numeric|exists:transaction_currencies,id|required_without:currency_code', | ||||
|             'currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id', | ||||
|             'amount'        => 'required|numeric|more:0', | ||||
|             'start_date'    => 'required|date|before:end_date', | ||||
|             'end_date'      => 'required|date|after:start_date', | ||||
|         ]; | ||||
|  | ||||
|         return $rules; | ||||
|   | ||||
| @@ -23,6 +23,9 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
|  * | ||||
| @@ -49,10 +52,11 @@ class JournalLinkRequest extends Request | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'link_type_id' => $this->integer('link_type_id'), | ||||
|             'inward_id'    => $this->integer('inward_id'), | ||||
|             'outward_id'   => $this->integer('outward_id'), | ||||
|             'notes'        => $this->string('notes'), | ||||
|             'link_type_id'   => $this->integer('link_type_id'), | ||||
|             'link_type_name' => $this->string('link_type_name'), | ||||
|             'inward_id'      => $this->integer('inward_id'), | ||||
|             'outward_id'     => $this->integer('outward_id'), | ||||
|             'notes'          => $this->string('notes'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| @@ -65,11 +69,63 @@ class JournalLinkRequest extends Request | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'link_type_id' => 'required|exists:link_types,id', | ||||
|             'inward_id'    => 'required|belongsToUser:transaction_journals,id', | ||||
|             'outward_id'   => 'required|belongsToUser:transaction_journals,id', | ||||
|             'notes'        => 'between:0,65000', | ||||
|             'link_type_id'   => 'exists:link_types,id|required_without:link_type_name', | ||||
|             'link_type_name' => 'exists:link_types,name|required_without:link_type_id', | ||||
|             'inward_id'      => 'required|belongsToUser:transaction_journals,id', | ||||
|             'outward_id'     => 'required|belongsToUser:transaction_journals,id', | ||||
|             'notes'          => 'between:0,65000', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $this->validateExistingLink($validator); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Validator $validator | ||||
|      */ | ||||
|     private function validateExistingLink(Validator $validator): void | ||||
|     { | ||||
|         /** @var LinkTypeRepositoryInterface $repository */ | ||||
|         $repository = app(LinkTypeRepositoryInterface::class); | ||||
|         $repository->setUser(auth()->user()); | ||||
|  | ||||
|         /** @var JournalRepositoryInterface $journalRepos */ | ||||
|         $journalRepos = app(JournalRepositoryInterface::class); | ||||
|         $journalRepos->setUser(auth()->user()); | ||||
|  | ||||
|         $data      = $validator->getData(); | ||||
|         $inwardId  = (int)($data['inward_id'] ?? 0); | ||||
|         $outwardId = (int)($data['outward_id'] ?? 0); | ||||
|         $inward    = $journalRepos->findNull($inwardId); | ||||
|         $outward   = $journalRepos->findNull($outwardId); | ||||
|  | ||||
|         if (null === $inward) { | ||||
|             $validator->errors()->add('inward_id', 'Invalid inward ID.'); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|         if (null === $outward) { | ||||
|             $validator->errors()->add('outward_id', 'Invalid outward ID.'); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if ($repository->findLink($inward, $outward)) { | ||||
|             $validator->errors()->add('outward_id', 'Already have a link between inward and outward.'); | ||||
|             $validator->errors()->add('inward_id', 'Already have a link between inward and outward.'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -57,7 +57,7 @@ class PiggyBankRequest extends Request | ||||
|             'current_amount' => $this->string('current_amount'), | ||||
|             'start_date'     => $this->date('start_date'), | ||||
|             'target_date'    => $this->date('target_date'), | ||||
|             'note'           => $this->string('notes'), | ||||
|             'notes'           => $this->string('notes'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -84,7 +84,7 @@ class RecurrenceRequest extends Request | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $today = Carbon::create()->addDay(); | ||||
|         $today = Carbon::now()->addDay(); | ||||
|  | ||||
|         return [ | ||||
|             'type'                                 => 'required|in:withdrawal,transfer,deposit', | ||||
|   | ||||
| @@ -56,27 +56,12 @@ class RuleRequest extends Request | ||||
|             'rule_group_title' => $this->string('rule_group_title'), | ||||
|             'trigger'          => $this->string('trigger'), | ||||
|             'strict'           => $this->boolean('strict'), | ||||
|             'stop-processing'  => $this->boolean('stop_processing'), | ||||
|             'stop_processing'  => $this->boolean('stop_processing'), | ||||
|             'active'           => $this->boolean('active'), | ||||
|             'rule-triggers'    => [], | ||||
|             'rule-actions'     => [], | ||||
|             'rule_triggers'    => $this->getRuleTriggers(), | ||||
|             'rule_actions'     => $this->getRuleActions(), | ||||
|         ]; | ||||
|  | ||||
|         foreach ($this->get('rule-triggers') as $trigger) { | ||||
|             $data['rule-triggers'][] = [ | ||||
|                 'name'            => $trigger['name'], | ||||
|                 'value'           => $trigger['value'], | ||||
|                 'stop-processing' => 1 === (int)($trigger['stop-processing'] ?? 0), | ||||
|             ]; | ||||
|         } | ||||
|         foreach ($this->get('rule-actions') as $action) { | ||||
|             $data['rule-actions'][] = [ | ||||
|                 'name'            => $action['name'], | ||||
|                 'value'           => $action['value'], | ||||
|                 'stop-processing' => 1 === (int)($action['stop-processing'] ?? 0), | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
| @@ -99,12 +84,12 @@ class RuleRequest extends Request | ||||
|             'rule_group_id'                   => 'required|belongsToUser:rule_groups|required_without:rule_group_title', | ||||
|             'rule_group_title'                => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title', | ||||
|             'trigger'                         => 'required|in:store-journal,update-journal', | ||||
|             'rule-triggers.*.name'            => 'required|in:' . implode(',', $validTriggers), | ||||
|             'rule-triggers.*.stop-processing' => 'boolean', | ||||
|             'rule-triggers.*.value'           => 'required|min:1|ruleTriggerValue', // | ||||
|             'rule-actions.*.name'             => 'required|in:' . implode(',', $validActions), | ||||
|             'rule-actions.*.value'            => 'required_if:rule-action.*.type,' . $contextActions . '|ruleActionValue', | ||||
|             'rule-actions.*.stop-processing'  => 'boolean', | ||||
|             'rule_triggers.*.name'            => 'required|in:' . implode(',', $validTriggers), | ||||
|             'rule_triggers.*.stop_processing' => 'boolean', | ||||
|             'rule_triggers.*.value'           => 'required|min:1|ruleTriggerValue', | ||||
|             'rule_actions.*.name'             => 'required|in:' . implode(',', $validActions), | ||||
|             'rule_actions.*.value'            => 'required_if:rule_actions.*.type,' . $contextActions . '|ruleActionValue', | ||||
|             'rule_actions.*.stop_processing'  => 'boolean', | ||||
|             'strict'                          => 'required|boolean', | ||||
|             'stop_processing'                 => 'required|boolean', | ||||
|             'active'                          => 'required|boolean', | ||||
| @@ -138,7 +123,7 @@ class RuleRequest extends Request | ||||
|     protected function atLeastOneAction(Validator $validator): void | ||||
|     { | ||||
|         $data        = $validator->getData(); | ||||
|         $repetitions = $data['rule-actions'] ?? []; | ||||
|         $repetitions = $data['rule_actions'] ?? []; | ||||
|         // need at least one transaction | ||||
|         if (0 === \count($repetitions)) { | ||||
|             $validator->errors()->add('title', (string)trans('validation.at_least_one_action')); | ||||
| @@ -153,10 +138,50 @@ class RuleRequest extends Request | ||||
|     protected function atLeastOneTrigger(Validator $validator): void | ||||
|     { | ||||
|         $data        = $validator->getData(); | ||||
|         $repetitions = $data['rule-triggers'] ?? []; | ||||
|         $repetitions = $data['rule_triggers'] ?? []; | ||||
|         // need at least one transaction | ||||
|         if (0 === \count($repetitions)) { | ||||
|             $validator->errors()->add('title', (string)trans('validation.at_least_one_trigger')); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getRuleActions(): array | ||||
|     { | ||||
|         $actions = $this->get('rule_actions'); | ||||
|         $return  = []; | ||||
|         if (\is_array($actions)) { | ||||
|             foreach ($actions as $action) { | ||||
|                 $return[] = [ | ||||
|                     'name'            => $action['name'], | ||||
|                     'value'           => $action['value'], | ||||
|                     'stop_processing' => 1 === (int)($action['stop-processing'] ?? '0'), | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getRuleTriggers(): array | ||||
|     { | ||||
|         $triggers = $this->get('rule_triggers'); | ||||
|         $return   = []; | ||||
|         if (\is_array($triggers)) { | ||||
|             foreach ($triggers as $trigger) { | ||||
|                 $return[] = [ | ||||
|                     'name'            => $trigger['name'], | ||||
|                     'value'           => $trigger['value'], | ||||
|                     'stop_processing' => 1 === (int)($trigger['stop-processing'] ?? '0'), | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -39,6 +39,8 @@ use Storage; | ||||
|  * Class CreateExport. | ||||
|  * | ||||
|  * Generates export from the command line. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class CreateExport extends Command | ||||
| { | ||||
|   | ||||
| @@ -37,6 +37,8 @@ use Log; | ||||
|  | ||||
| /** | ||||
|  * Class CreateImport. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class CreateImport extends Command | ||||
| { | ||||
| @@ -150,7 +152,7 @@ class CreateImport extends Command | ||||
|  | ||||
|  | ||||
|         if (true === $this->option('start')) { | ||||
|             $this->infoLine('The has started. The process is not visible. Please wait.'); | ||||
|             $this->infoLine('The import routine has started. The process is not visible. Please wait.'); | ||||
|             Log::debug('Go for import!'); | ||||
|  | ||||
|             // run it! | ||||
|   | ||||
							
								
								
									
										67
									
								
								app/Console/Commands/Cron.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								app/Console/Commands/Cron.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
|  | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Support\Cronjobs\RecurringCronjob; | ||||
| use Illuminate\Console\Command; | ||||
|  | ||||
| /** | ||||
|  * Class Cron | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class Cron extends Command | ||||
| { | ||||
|     /** | ||||
|      * The console command description. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $description = 'Runs all Firefly III cron-job related commands. Configure a cron job according to the official Firefly III documentation.'; | ||||
|     /** | ||||
|      * The name and signature of the console command. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $signature = 'firefly:cron'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle(): int | ||||
|     { | ||||
|         $recurring = new RecurringCronjob; | ||||
|         try { | ||||
|             $result = $recurring->fire(); | ||||
|         } catch (FireflyException $e) { | ||||
|             $this->error($e->getMessage()); | ||||
|  | ||||
|             return 0; | ||||
|         } | ||||
|         if (false === $result) { | ||||
|             $this->line('The recurring transaction cron job did not fire.'); | ||||
|         } | ||||
|         if (true === $result) { | ||||
|             $this->line('The recurring transaction cron job fired successfully.'); | ||||
|         } | ||||
|  | ||||
|         $this->info('More feedback on the cron jobs can be found in the log files.'); | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -31,6 +31,8 @@ use Log; | ||||
|  | ||||
| /** | ||||
|  * Class DecryptAttachment. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class DecryptAttachment extends Command | ||||
| { | ||||
|   | ||||
| @@ -29,6 +29,8 @@ use Illuminate\Console\Command; | ||||
|  | ||||
| /** | ||||
|  * Class EncryptFile. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class EncryptFile extends Command | ||||
| { | ||||
|   | ||||
| @@ -35,6 +35,8 @@ use Log; | ||||
|  | ||||
| /** | ||||
|  * Class Import. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class Import extends Command | ||||
| { | ||||
| @@ -64,7 +66,7 @@ class Import extends Command | ||||
|         Log::debug('Start start-import command'); | ||||
|         $jobKey = (string)$this->argument('key'); | ||||
|         /** @var ImportJob $job */ | ||||
|         $job    = ImportJob::where('key', $jobKey)->first(); | ||||
|         $job = ImportJob::where('key', $jobKey)->first(); | ||||
|         if (null === $job) { | ||||
|             $this->errorLine(sprintf('No job found with key "%s"', $jobKey)); | ||||
|  | ||||
|   | ||||
| @@ -34,6 +34,8 @@ use Storage; | ||||
|  | ||||
| /** | ||||
|  * Class ScanAttachments. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class ScanAttachments extends Command | ||||
| { | ||||
| @@ -82,6 +84,7 @@ class ScanAttachments extends Command | ||||
|             $attachment->save(); | ||||
|             $this->line(sprintf('Fixed attachment #%d', $attachment->id)); | ||||
|         } | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -63,6 +63,7 @@ use UnexpectedValueException; | ||||
|  * Upgrade user database. | ||||
|  * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class UpgradeDatabase extends Command | ||||
| { | ||||
|   | ||||
| @@ -27,6 +27,8 @@ use Illuminate\Console\Command; | ||||
|  | ||||
| /** | ||||
|  * Class UpgradeFireflyInstructions. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class UpgradeFireflyInstructions extends Command | ||||
| { | ||||
| @@ -54,6 +56,7 @@ class UpgradeFireflyInstructions extends Command | ||||
|         if ('install' === (string)$this->argument('task')) { | ||||
|             $this->installInstructions(); | ||||
|         } | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -28,6 +28,7 @@ use Illuminate\Support\Str; | ||||
|  | ||||
| /** | ||||
|  * Class UseEncryption. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class UseEncryption extends Command | ||||
| { | ||||
| @@ -62,6 +63,7 @@ class UseEncryption extends Command | ||||
|         $this->handleObjects('Category', 'name', 'encrypted'); | ||||
|         $this->handleObjects('PiggyBank', 'name', 'encrypted'); | ||||
|         $this->handleObjects('TransactionJournal', 'description', 'encrypted'); | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use Log; | ||||
|  * Trait VerifiesAccessToken. | ||||
|  * | ||||
|  * Verifies user access token for sensitive commands. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| trait VerifiesAccessToken | ||||
| { | ||||
|   | ||||
| @@ -50,6 +50,7 @@ use stdClass; | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class VerifyDatabase extends Command | ||||
| { | ||||
|   | ||||
| @@ -24,13 +24,13 @@ declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Jobs\CreateRecurringTransactions; | ||||
| use Illuminate\Console\Scheduling\Schedule; | ||||
| use Illuminate\Foundation\Console\Kernel as ConsoleKernel; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * File to make sure commands work. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class Kernel extends ConsoleKernel | ||||
| { | ||||
| @@ -52,6 +52,21 @@ class Kernel extends ConsoleKernel | ||||
|      */ | ||||
|     protected function schedule(Schedule $schedule): void | ||||
|     { | ||||
|         $schedule->job(new CreateRecurringTransactions(new Carbon))->daily(); | ||||
|         $schedule->call( | ||||
|             function () { | ||||
|                 Log::error('Firefly III no longer users the Laravel scheduler to do cron jobs! Please read the instructions at https://firefly-iii.readthedocs.io/en/latest/'); | ||||
|                 echo "\n"; | ||||
|                 echo '------------'; | ||||
|                 echo "\n"; | ||||
|                 echo wordwrap('Firefly III no longer users the Laravel scheduler to do cron jobs! Please read the instructions here:'); | ||||
|                 echo "\n"; | ||||
|                 echo 'https://firefly-iii.readthedocs.io/en/latest/'; | ||||
|                 echo "\n\n"; | ||||
|                 echo 'Disable this cron job!'; | ||||
|                 echo "\n"; | ||||
|                 echo '------------'; | ||||
|                 echo "\n"; | ||||
|             } | ||||
|         )->everyMinute(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -30,6 +30,7 @@ use Log; | ||||
|  | ||||
| /** | ||||
|  * Class AdminRequestedTestMessage. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class AdminRequestedTestMessage extends Event | ||||
| { | ||||
|   | ||||
| @@ -26,6 +26,7 @@ namespace FireflyIII\Events; | ||||
|  | ||||
| /** | ||||
|  * Class Event. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| abstract class Event | ||||
| { | ||||
|   | ||||
| @@ -29,6 +29,7 @@ use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| /** | ||||
|  * Class RegisteredUser. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class RegisteredUser extends Event | ||||
| { | ||||
|   | ||||
| @@ -29,6 +29,7 @@ use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| /** | ||||
|  * Class RequestedNewPassword. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class RequestedNewPassword extends Event | ||||
| { | ||||
| @@ -36,10 +37,10 @@ class RequestedNewPassword extends Event | ||||
|  | ||||
|     /** @var string The users IP address */ | ||||
|     public $ipAddress; | ||||
|     /** @var User The user */ | ||||
|     public $user; | ||||
|     /** @var string The token */ | ||||
|     public $token; | ||||
|     /** @var User The user */ | ||||
|     public $user; | ||||
|  | ||||
|     /** | ||||
|      * Create a new event instance. This event is triggered when a users tries to reset his or her password. | ||||
|   | ||||
| @@ -31,6 +31,8 @@ use Log; | ||||
|  | ||||
| /** | ||||
|  * Class RequestedReportOnJournals | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class RequestedReportOnJournals | ||||
| { | ||||
|   | ||||
| @@ -30,6 +30,8 @@ use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| /** | ||||
|  * Class RequestedVersionCheckStatus | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class RequestedVersionCheckStatus extends Event | ||||
| { | ||||
|   | ||||
| @@ -29,6 +29,8 @@ use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| /** | ||||
|  * Class UserChangedEmail. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class UserChangedEmail extends Event | ||||
| { | ||||
|   | ||||
| @@ -38,6 +38,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; | ||||
|  | ||||
| /** | ||||
|  * Class Handler | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class Handler extends ExceptionHandler | ||||
| { | ||||
|   | ||||
| @@ -28,13 +28,15 @@ use Crypt; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| use Illuminate\Contracts\Encryption\DecryptException; | ||||
| use Illuminate\Contracts\Filesystem\FileNotFoundException; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Storage; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentCollector. | ||||
|  * | ||||
|  * @deprecated | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class AttachmentCollector extends BasicCollector implements CollectorInterface | ||||
| { | ||||
| @@ -108,7 +110,7 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface | ||||
|         if ($this->uploadDisk->exists($file)) { | ||||
|             try { | ||||
|                 $decrypted = Crypt::decrypt($this->uploadDisk->get($file)); | ||||
|             } catch (FileNotFoundException|DecryptException $e) { | ||||
|             } catch (DecryptException $e) { | ||||
|                 Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage()); | ||||
|  | ||||
|                 return false; | ||||
|   | ||||
| @@ -30,6 +30,9 @@ use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class BasicCollector. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @deprecated | ||||
|  */ | ||||
| class BasicCollector | ||||
| { | ||||
|   | ||||
| @@ -29,6 +29,9 @@ use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface CollectorInterface. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @deprecated | ||||
|  */ | ||||
| interface CollectorInterface | ||||
| { | ||||
|   | ||||
| @@ -31,6 +31,9 @@ use Storage; | ||||
|  | ||||
| /** | ||||
|  * Class UploadCollector. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @deprecated | ||||
|  */ | ||||
| class UploadCollector extends BasicCollector implements CollectorInterface | ||||
| { | ||||
|   | ||||
| @@ -43,6 +43,9 @@ use FireflyIII\Models\Transaction; | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.LongVariable) | ||||
|  * @SuppressWarnings(PHPMD.TooManyFields) | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @deprecated | ||||
|  */ | ||||
| final class Entry | ||||
| { | ||||
|   | ||||
| @@ -32,7 +32,7 @@ use FireflyIII\Export\Collector\AttachmentCollector; | ||||
| use FireflyIII\Export\Collector\UploadCollector; | ||||
| use FireflyIII\Export\Entry\Entry; | ||||
| use FireflyIII\Export\Exporter\ExporterInterface; | ||||
| use FireflyIII\Helpers\Collector\JournalCollectorInterface; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Models\AccountMeta; | ||||
| use FireflyIII\Models\ExportJob; | ||||
| @@ -49,12 +49,15 @@ use ZipArchive; | ||||
|  * Class ExpandedProcessor. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) // its doing a lot. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @deprecated | ||||
|  */ | ||||
| class ExpandedProcessor implements ProcessorInterface | ||||
| { | ||||
|     /** @var Collection All accounts */ | ||||
|     public $accounts; | ||||
|     /** @var string The export format*/ | ||||
|     /** @var string The export format */ | ||||
|     public $exportFormat; | ||||
|     /** @var bool Should include attachments */ | ||||
|     public $includeAttachments; | ||||
| @@ -62,7 +65,7 @@ class ExpandedProcessor implements ProcessorInterface | ||||
|     public $includeOldUploads; | ||||
|     /** @var ExportJob The export job itself */ | ||||
|     public $job; | ||||
|     /** @var array The settings*/ | ||||
|     /** @var array The settings */ | ||||
|     public $settings; | ||||
|     /** @var Collection The entries to export. */ | ||||
|     private $exportEntries; | ||||
| @@ -107,13 +110,13 @@ class ExpandedProcessor implements ProcessorInterface | ||||
|     public function collectJournals(): bool | ||||
|     { | ||||
|         // use journal collector thing. | ||||
|         /** @var JournalCollectorInterface $collector */ | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($this->job->user); | ||||
|         $collector->setAccounts($this->accounts)->setRange($this->settings['startDate'], $this->settings['endDate']) | ||||
|                   ->withOpposingAccount()->withBudgetInformation()->withCategoryInformation() | ||||
|                   ->removeFilter(InternalTransferFilter::class); | ||||
|         $transactions = $collector->getJournals(); | ||||
|         $transactions = $collector->getTransactions(); | ||||
|         // get some more meta data for each entry: | ||||
|         $ids         = $transactions->pluck('journal_id')->toArray(); | ||||
|         $assetIds    = $transactions->pluck('account_id')->toArray(); | ||||
| @@ -222,7 +225,7 @@ class ExpandedProcessor implements ProcessorInterface | ||||
|     { | ||||
|         $exporterClass = config('firefly.export_formats.' . $this->exportFormat); | ||||
|         /** @var ExporterInterface $exporter */ | ||||
|         $exporter      = app($exporterClass); | ||||
|         $exporter = app($exporterClass); | ||||
|         $exporter->setJob($this->job); | ||||
|         $exporter->setEntries($this->exportEntries); | ||||
|         $exporter->run(); | ||||
| @@ -260,7 +263,7 @@ class ExpandedProcessor implements ProcessorInterface | ||||
|     /** | ||||
|      * Delete files. | ||||
|      */ | ||||
|     private function deleteFiles():void | ||||
|     private function deleteFiles(): void | ||||
|     { | ||||
|         $disk = Storage::disk('export'); | ||||
|         foreach ($this->getFiles() as $file) { | ||||
|   | ||||
| @@ -29,6 +29,9 @@ use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class BasicExporter. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @deprecated | ||||
|  */ | ||||
| class BasicExporter | ||||
| { | ||||
|   | ||||
| @@ -30,6 +30,9 @@ use Storage; | ||||
|  | ||||
| /** | ||||
|  * Class CsvExporter. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @deprecated | ||||
|  */ | ||||
| class CsvExporter extends BasicExporter implements ExporterInterface | ||||
| { | ||||
|   | ||||
| @@ -29,6 +29,9 @@ use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface ExporterInterface. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @deprecated | ||||
|  */ | ||||
| interface ExporterInterface | ||||
| { | ||||
|   | ||||
| @@ -28,6 +28,9 @@ use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Interface ProcessorInterface. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @deprecated | ||||
|  */ | ||||
| interface ProcessorInterface | ||||
| { | ||||
|   | ||||
| @@ -32,6 +32,7 @@ use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Services\Internal\Support\AccountServiceTrait; | ||||
| use FireflyIII\User; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Factory to create or return accounts. | ||||
| @@ -80,8 +81,9 @@ class AccountFactory | ||||
|                 'iban'            => $data['iban'], | ||||
|             ]; | ||||
|  | ||||
|             // remove virtual balance when not an asset account: | ||||
|             if ($type->type !== AccountType::ASSET) { | ||||
|             // remove virtual balance when not an asset account or a liability | ||||
|             $canHaveVirtual = [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD]; | ||||
|             if (!\in_array($type->type, $canHaveVirtual, true)) { | ||||
|                 $databaseData['virtual_balance'] = '0'; | ||||
|             } | ||||
|  | ||||
| @@ -93,7 +95,7 @@ class AccountFactory | ||||
|             $return = Account::create($databaseData); | ||||
|             $this->updateMetaData($return, $data); | ||||
|  | ||||
|             if ($type->type === AccountType::ASSET) { | ||||
|             if (\in_array($type->type, $canHaveVirtual, true)) { | ||||
|                 if ($this->validIBData($data)) { | ||||
|                     $this->updateIB($return, $data); | ||||
|                 } | ||||
| @@ -130,6 +132,7 @@ class AccountFactory | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * @param string $accountName | ||||
|      * @param string $accountType | ||||
|      * | ||||
| @@ -188,9 +191,13 @@ class AccountFactory | ||||
|             $result = AccountType::find($accountTypeId); | ||||
|         } | ||||
|         if (null === $result) { | ||||
|             /** @var string $type */ | ||||
|             $type   = (string)config('firefly.accountTypeByIdentifier.' . $accountType); | ||||
|             $result = AccountType::whereType($type)->first(); | ||||
|             Log::debug(sprintf('No account type found by ID, continue search for "%s".', $accountType)); | ||||
|             /** @var array $types */ | ||||
|             $types = config('firefly.accountTypeByIdentifier.' . $accountType) ?? []; | ||||
|             if (\count($types) > 0) { | ||||
|                 Log::debug(sprintf('%d accounts in list from config', \count($types)), $types); | ||||
|                 $result = AccountType::whereIn('type', $types)->first(); | ||||
|             } | ||||
|             if (null === $result && null !== $accountType) { | ||||
|                 // try as full name: | ||||
|                 $result = AccountType::whereType($accountType)->first(); | ||||
|   | ||||
| @@ -65,7 +65,7 @@ class AccountMetaFactory | ||||
|             // if $data has field and $entry is null, create new one: | ||||
|             if (null === $entry) { | ||||
|                 Log::debug(sprintf('Created meta-field "%s":"%s" for account #%d ("%s") ', $field, $value, $account->id, $account->name)); | ||||
|                 $this->create(['account_id' => $account->id, 'name' => $field, 'data' => $value]); | ||||
|                 return $this->create(['account_id' => $account->id, 'name' => $field, 'data' => $value]); | ||||
|             } | ||||
|  | ||||
|             // if $data has field and $entry is not null, update $entry: | ||||
| @@ -75,12 +75,13 @@ class AccountMetaFactory | ||||
|                 Log::debug(sprintf('Updated meta-field "%s":"%s" for #%d ("%s") ', $field, $value, $account->id, $account->name)); | ||||
|             } | ||||
|         } | ||||
|         if ('' === $value && null !== $entry && isset($data[$field])) { | ||||
|         if ('' === $value && null !== $entry) { | ||||
|             try { | ||||
|                 $entry->delete(); | ||||
|             } catch (Exception $e) { | ||||
|                 Log::debug(sprintf('Could not delete entry: %s', $e->getMessage())); | ||||
|             } catch (Exception $e) { // @codeCoverageIgnore | ||||
|                 Log::debug(sprintf('Could not delete entry: %s', $e->getMessage())); // @codeCoverageIgnore | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         return $entry; | ||||
|   | ||||
| @@ -25,6 +25,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Factory; | ||||
|  | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Services\Internal\Support\BillServiceTrait; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Support\Collection; | ||||
| @@ -46,6 +47,10 @@ class BillFactory | ||||
|      */ | ||||
|     public function create(array $data): ?Bill | ||||
|     { | ||||
|         /** @var TransactionCurrencyFactory $factory */ | ||||
|         $factory = app(TransactionCurrencyFactory::class); | ||||
|         /** @var TransactionCurrency $currency */ | ||||
|         $currency = $factory->find((int)$data['currency_id'], (string)$data['currency_code']); | ||||
|         /** @var Bill $bill */ | ||||
|         $bill = Bill::create( | ||||
|             [ | ||||
| @@ -53,7 +58,7 @@ class BillFactory | ||||
|                 'match'                   => 'MIGRATED_TO_RULES', | ||||
|                 'amount_min'              => $data['amount_min'], | ||||
|                 'user_id'                 => $this->user->id, | ||||
|                 'transaction_currency_id' => $data['transaction_currency_id'], | ||||
|                 'transaction_currency_id' => $currency->id, | ||||
|                 'amount_max'              => $data['amount_max'], | ||||
|                 'date'                    => $data['date'], | ||||
|                 'repeat_freq'             => $data['repeat_freq'], | ||||
|   | ||||
| @@ -59,10 +59,10 @@ class TransactionFactory | ||||
|         $currencyId = isset($data['currency']) ? $data['currency']->id : $currencyId; | ||||
|         if ('' === $data['amount']) { | ||||
|             Log::error('Empty string in data.', $data); | ||||
|             throw new FireflyException('Amount is an empty string, which Firefly III cannot handle. Apologies.'); // @codeCoverageIgnore | ||||
|             throw new FireflyException('Amount is an empty string, which Firefly III cannot handle. Apologies.'); | ||||
|         } | ||||
|         if (null === $currencyId) { | ||||
|             throw new FireflyException('Cannot store transaction without currency information.'); // @codeCoverageIgnore | ||||
|             throw new FireflyException('Cannot store transaction without currency information.'); | ||||
|         } | ||||
|         $data['foreign_amount'] = '' === (string)$data['foreign_amount'] ? null : $data['foreign_amount']; | ||||
|         Log::debug(sprintf('Create transaction for account #%d ("%s") with amount %s', $data['account']->id, $data['account']->name, $data['amount'])); | ||||
| @@ -121,13 +121,9 @@ class TransactionFactory | ||||
|         } | ||||
|  | ||||
|         Log::debug(sprintf('Source type is "%s", destination type is "%s"', $sourceAccount->accountType->type, $destinationAccount->accountType->type)); | ||||
|         // throw big fat error when source type === dest type and it's not a transfer or reconciliation. | ||||
|         if ($sourceAccount->accountType->type === $destinationAccount->accountType->type && $journal->transactionType->type !== TransactionType::TRANSFER) { | ||||
|             throw new FireflyException(sprintf('Source and destination account cannot be both of the type "%s"', $destinationAccount->accountType->type)); | ||||
|         } | ||||
|         if ($sourceAccount->accountType->type !== AccountType::ASSET && $destinationAccount->accountType->type !== AccountType::ASSET) { | ||||
|             throw new FireflyException('At least one of the accounts must be an asset account.'); | ||||
|         } | ||||
|  | ||||
|         // based on the source type, destination type and transaction type, the system can start throwing FireflyExceptions. | ||||
|         $this->validateTransaction($sourceAccount->accountType->type, $destinationAccount->accountType->type, $journal->transactionType->type); | ||||
|  | ||||
|         $source = $this->create( | ||||
|             [ | ||||
| @@ -154,7 +150,7 @@ class TransactionFactory | ||||
|             ] | ||||
|         ); | ||||
|         if (null === $source || null === $dest) { | ||||
|             throw new FireflyException('Could not create transactions.'); | ||||
|             throw new FireflyException('Could not create transactions.'); // @codeCoverageIgnore | ||||
|         } | ||||
|  | ||||
|         // set foreign currency | ||||
| @@ -194,5 +190,29 @@ class TransactionFactory | ||||
|         $this->user = $user; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $sourceType | ||||
|      * @param string $destinationType | ||||
|      * @param string $transactionType | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     private function validateTransaction(string $sourceType, string $destinationType, string $transactionType): void | ||||
|     { | ||||
|         // throw big fat error when source type === dest type and it's not a transfer or reconciliation. | ||||
|         if ($sourceType === $destinationType && $transactionType !== TransactionType::TRANSFER) { | ||||
|             throw new FireflyException(sprintf('Source and destination account cannot be both of the type "%s"', $destinationType)); | ||||
|         } | ||||
|         // source must be in this list AND dest must be in this list: | ||||
|         $list = [AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH, AccountType::DEBT, AccountType::MORTGAGE, AccountType::LOAN, AccountType::MORTGAGE]; | ||||
|         if ( | ||||
|             !\in_array($sourceType, $list, true) && | ||||
|             !\in_array($destinationType, $list, true)) { | ||||
|             throw new FireflyException(sprintf('At least one of the accounts must be an asset account (%s, %s).', $sourceType, $destinationType)); | ||||
|         } | ||||
|         // either of these must be asset or default account. | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -104,7 +104,7 @@ class TransactionJournalFactory | ||||
|         // store date meta fields (if present): | ||||
|         $fields = ['sepa-cc', 'sepa-ct-op', 'sepa-ct-id', 'sepa-db', 'sepa-country', 'sepa-ep', 'sepa-ci', 'interest_date', 'book_date', 'process_date', | ||||
|                    'due_date', 'recurrence_id', 'payment_date', 'invoice_date', 'internal_reference', 'bunq_payment_id', 'importHash', 'importHashV2', | ||||
|                    'external_id','sepa-batch-id']; | ||||
|                    'external_id', 'sepa-batch-id']; | ||||
|  | ||||
|         foreach ($fields as $field) { | ||||
|             $this->storeMeta($journal, $data, $field); | ||||
|   | ||||
| @@ -28,7 +28,6 @@ namespace FireflyIII\Factory; | ||||
| use FireflyIII\Models\TransactionType; | ||||
|  | ||||
| /** | ||||
|  * @codeCoverageIgnore | ||||
|  * Class TransactionTypeFactory | ||||
|  */ | ||||
| class TransactionTypeFactory | ||||
|   | ||||
| @@ -39,6 +39,8 @@ class ChartJsGenerator implements GeneratorInterface | ||||
|      *    'type' => bar or line, optional | ||||
|      *    'yAxisID' => ID of yAxis, optional, will not be included when unused. | ||||
|      *    'fill' => if to fill a line? optional, will not be included when unused. | ||||
|      *    'currency_symbol' => 'x', | ||||
|      *    'backgroundColor' => 'x', | ||||
|      *    'entries' => | ||||
|      *        [ | ||||
|      *         'label-of-entry' => 'value' | ||||
| @@ -120,7 +122,7 @@ class ChartJsGenerator implements GeneratorInterface | ||||
|         // different sort when values are positive and when they're negative. | ||||
|         asort($data); | ||||
|         $next = next($data); | ||||
|         if (!\is_bool($next) && 1 === bccomp($next, '0')) { | ||||
|         if (!\is_bool($next) && 1 === bccomp((string)$next, '0')) { | ||||
|             // next is positive, sort other way around. | ||||
|             arsort($data); | ||||
|         } | ||||
| @@ -129,7 +131,7 @@ class ChartJsGenerator implements GeneratorInterface | ||||
|         $index = 0; | ||||
|         foreach ($data as $key => $value) { | ||||
|             // make larger than 0 | ||||
|             $chartData['datasets'][0]['data'][]            = (float)app('steam')->positive($value); | ||||
|             $chartData['datasets'][0]['data'][]            = (float)app('steam')->positive((string)$value); | ||||
|             $chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index); | ||||
|             $chartData['labels'][]                         = $key; | ||||
|             ++$index; | ||||
| @@ -138,6 +140,46 @@ class ChartJsGenerator implements GeneratorInterface | ||||
|         return $chartData; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Expects data as:. | ||||
|      * | ||||
|      * key => [value => x, 'currency_symbol' => 'x'] | ||||
|      * | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiCurrencyPieChart(array $data): array | ||||
|     { | ||||
|         $chartData = [ | ||||
|             'datasets' => [ | ||||
|                 0 => [], | ||||
|             ], | ||||
|             'labels'   => [], | ||||
|         ]; | ||||
|  | ||||
|         $amounts = array_column($data, 'amount'); | ||||
|         $next = next($amounts); | ||||
|         $sortFlag = SORT_ASC; | ||||
|         if (!\is_bool($next) && 1 === bccomp((string)$next, '0')) { | ||||
|             $sortFlag = SORT_DESC; | ||||
|         } | ||||
|         array_multisort($amounts, $sortFlag, $data); | ||||
|         unset($next, $sortFlag, $amounts); | ||||
|  | ||||
|         $index = 0; | ||||
|         foreach ($data as $key => $valueArray) { | ||||
|             // make larger than 0 | ||||
|             $chartData['datasets'][0]['data'][]            = (float)app('steam')->positive((string)$valueArray['amount']); | ||||
|             $chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index); | ||||
|             $chartData['datasets'][0]['currency_symbol'][] = $valueArray['currency_symbol']; | ||||
|             $chartData['labels'][]                         = $key; | ||||
|             ++$index; | ||||
|         } | ||||
|  | ||||
|         return $chartData; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Will generate a (ChartJS) compatible array from the given input. Expects this format:. | ||||
|      * | ||||
|   | ||||
| @@ -27,6 +27,13 @@ namespace FireflyIII\Generator\Chart\Basic; | ||||
|  */ | ||||
| interface GeneratorInterface | ||||
| { | ||||
|     /** | ||||
|      * @param array $data | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function multiCurrencyPieChart(array $data): array; | ||||
|  | ||||
|     /** | ||||
|      * Will generate a Chart JS compatible array from the given input. Expects this format. | ||||
|      * | ||||
|   | ||||
| @@ -25,9 +25,13 @@ namespace FireflyIII\Generator\Report\Account; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Generator\Report\ReportGeneratorInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Throwable; | ||||
|  | ||||
| /** | ||||
|  * Class MonthReportGenerator. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MonthReportGenerator implements ReportGeneratorInterface | ||||
| { | ||||
| @@ -44,7 +48,6 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|      * Generate the report. | ||||
|      * | ||||
|      * @return string | ||||
|      * @throws \Throwable | ||||
|      */ | ||||
|     public function generate(): string | ||||
|     { | ||||
| @@ -52,11 +55,17 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|         $expenseIds      = implode(',', $this->expense->pluck('id')->toArray()); | ||||
|         $reportType      = 'account'; | ||||
|         $preferredPeriod = $this->preferredPeriod(); | ||||
|         try { | ||||
|             $result = view( | ||||
|                 'reports.account.report', | ||||
|                 compact('accountIds', 'reportType', 'expenseIds', 'preferredPeriod') | ||||
|             )->with('start', $this->start)->with('end', $this->end)->render(); | ||||
|         } catch (Throwable $e) { | ||||
|             Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); | ||||
|             $result = 'Could not render report view.'; | ||||
|         } | ||||
|  | ||||
|         return view( | ||||
|             'reports.account.report', | ||||
|             compact('accountIds', 'reportType', 'expenseIds', 'preferredPeriod') | ||||
|         )->with('start', $this->start)->with('end', $this->end)->render(); | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -24,6 +24,8 @@ namespace FireflyIII\Generator\Report\Account; | ||||
|  | ||||
| /** | ||||
|  * Class MultiYearReportGenerator. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MultiYearReportGenerator extends MonthReportGenerator | ||||
| { | ||||
|   | ||||
| @@ -24,6 +24,8 @@ namespace FireflyIII\Generator\Report\Account; | ||||
|  | ||||
| /** | ||||
|  * Class YearReportGenerator. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class YearReportGenerator extends MonthReportGenerator | ||||
| { | ||||
|   | ||||
| @@ -28,12 +28,14 @@ namespace FireflyIII\Generator\Report\Audit; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Generator\Report\ReportGeneratorInterface; | ||||
| use FireflyIII\Helpers\Collector\JournalCollectorInterface; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Throwable; | ||||
|  | ||||
| /** | ||||
|  * Class MonthReportGenerator. | ||||
| @@ -52,7 +54,7 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|      * | ||||
|      * @return string | ||||
|      * @throws FireflyException | ||||
|      * @throws \Throwable | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function generate(): string | ||||
|     { | ||||
| @@ -78,100 +80,16 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|                         'internal_reference', 'notes', | ||||
|                         'create_date', 'update_date', | ||||
|         ]; | ||||
|         try { | ||||
|             $result = view('reports.audit.report', compact('reportType', 'accountIds', 'auditData', 'hideable', 'defaultShow')) | ||||
|                 ->with('start', $this->start)->with('end', $this->end)->with('accounts', $this->accounts) | ||||
|                 ->render(); | ||||
|         } catch (Throwable $e) { | ||||
|             Log::error(sprintf('Cannot render reports.audit.report: %s', $e->getMessage())); | ||||
|             $result = 'Could not render report view.'; | ||||
|         } | ||||
|  | ||||
|         return view('reports.audit.report', compact('reportType', 'accountIds', 'auditData', 'hideable', 'defaultShow')) | ||||
|             ->with('start', $this->start)->with('end', $this->end)->with('accounts', $this->accounts) | ||||
|             ->render(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Account collection setter. | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      */ | ||||
|     public function setAccounts(Collection $accounts): ReportGeneratorInterface | ||||
|     { | ||||
|         $this->accounts = $accounts; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Budget collection setter. | ||||
|      * | ||||
|      * @param Collection $budgets | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      */ | ||||
|     public function setBudgets(Collection $budgets): ReportGeneratorInterface | ||||
|     { | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Category collection setter. | ||||
|      * | ||||
|      * @param Collection $categories | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      */ | ||||
|     public function setCategories(Collection $categories): ReportGeneratorInterface | ||||
|     { | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * End date setter. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      */ | ||||
|     public function setEndDate(Carbon $date): ReportGeneratorInterface | ||||
|     { | ||||
|         $this->end = $date; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Expenses collection setter. | ||||
|      * | ||||
|      * @param Collection $expense | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      */ | ||||
|     public function setExpense(Collection $expense): ReportGeneratorInterface | ||||
|     { | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Start date collection setter. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      */ | ||||
|     public function setStartDate(Carbon $date): ReportGeneratorInterface | ||||
|     { | ||||
|         $this->start = $date; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Tags collection setter. | ||||
|      * | ||||
|      * @param Collection $tags | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      */ | ||||
|     public function setTags(Collection $tags): ReportGeneratorInterface | ||||
|     { | ||||
|         return $this; | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -185,7 +103,7 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) // not that long | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     private function getAuditReport(Account $account, Carbon $date): array | ||||
|     public function getAuditReport(Account $account, Carbon $date): array | ||||
|     { | ||||
|         /** @var CurrencyRepositoryInterface $currencyRepos */ | ||||
|         $currencyRepos = app(CurrencyRepositoryInterface::class); | ||||
| @@ -194,10 +112,10 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|         $accountRepository = app(AccountRepositoryInterface::class); | ||||
|         $accountRepository->setUser($account->user); | ||||
|  | ||||
|         /** @var JournalCollectorInterface $collector */ | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setAccounts(new Collection([$account]))->setRange($this->start, $this->end); | ||||
|         $journals         = $collector->getJournals(); | ||||
|         $journals         = $collector->getTransactions(); | ||||
|         $journals         = $journals->reverse(); | ||||
|         $dayBeforeBalance = app('steam')->balance($account, $date); | ||||
|         $startBalance     = $dayBeforeBalance; | ||||
| @@ -232,4 +150,101 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Account collection setter. | ||||
|      * | ||||
|      * @param Collection $accounts | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function setAccounts(Collection $accounts): ReportGeneratorInterface | ||||
|     { | ||||
|         $this->accounts = $accounts; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Budget collection setter. | ||||
|      * | ||||
|      * @param Collection $budgets | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function setBudgets(Collection $budgets): ReportGeneratorInterface | ||||
|     { | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Category collection setter. | ||||
|      * | ||||
|      * @param Collection $categories | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function setCategories(Collection $categories): ReportGeneratorInterface | ||||
|     { | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * End date setter. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function setEndDate(Carbon $date): ReportGeneratorInterface | ||||
|     { | ||||
|         $this->end = $date; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Expenses collection setter. | ||||
|      * | ||||
|      * @param Collection $expense | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function setExpense(Collection $expense): ReportGeneratorInterface | ||||
|     { | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Start date collection setter. | ||||
|      * | ||||
|      * @param Carbon $date | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function setStartDate(Carbon $date): ReportGeneratorInterface | ||||
|     { | ||||
|         $this->start = $date; | ||||
|  | ||||
|         return $this; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Tags collection setter. | ||||
|      * | ||||
|      * @param Collection $tags | ||||
|      * | ||||
|      * @return ReportGeneratorInterface | ||||
|      * @codeCoverageIgnore | ||||
|      */ | ||||
|     public function setTags(Collection $tags): ReportGeneratorInterface | ||||
|     { | ||||
|         return $this; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -24,6 +24,7 @@ namespace FireflyIII\Generator\Report\Audit; | ||||
|  | ||||
| /** | ||||
|  * Class MultiYearReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MultiYearReportGenerator extends MonthReportGenerator | ||||
| { | ||||
|   | ||||
| @@ -24,6 +24,7 @@ namespace FireflyIII\Generator\Report\Audit; | ||||
|  | ||||
| /** | ||||
|  * Class YearReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class YearReportGenerator extends MonthReportGenerator | ||||
| { | ||||
|   | ||||
| @@ -27,7 +27,7 @@ namespace FireflyIII\Generator\Report\Budget; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Generator\Report\ReportGeneratorInterface; | ||||
| use FireflyIII\Generator\Report\Support; | ||||
| use FireflyIII\Helpers\Collector\JournalCollectorInterface; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\OpposingAccountFilter; | ||||
| use FireflyIII\Helpers\Filter\PositiveAmountFilter; | ||||
| use FireflyIII\Helpers\Filter\TransferFilter; | ||||
| @@ -35,9 +35,12 @@ use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Throwable; | ||||
|  | ||||
| /** | ||||
|  * Class MonthReportGenerator. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
| { | ||||
| @@ -64,7 +67,6 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|      * Generates the report. | ||||
|      * | ||||
|      * @return string | ||||
|      * @throws \Throwable | ||||
|      */ | ||||
|     public function generate(): string | ||||
|     { | ||||
| @@ -77,11 +79,18 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|         $topExpenses     = $this->getTopExpenses(); | ||||
|  | ||||
|         // render! | ||||
|         return view('reports.budget.month', compact('accountIds', 'budgetIds', 'accountSummary', 'budgetSummary', 'averageExpenses', 'topExpenses')) | ||||
|             ->with('start', $this->start)->with('end', $this->end) | ||||
|             ->with('budgets', $this->budgets) | ||||
|             ->with('accounts', $this->accounts) | ||||
|             ->render(); | ||||
|         try { | ||||
|             $result = view('reports.budget.month', compact('accountIds', 'budgetIds', 'accountSummary', 'budgetSummary', 'averageExpenses', 'topExpenses')) | ||||
|                 ->with('start', $this->start)->with('end', $this->end) | ||||
|                 ->with('budgets', $this->budgets) | ||||
|                 ->with('accounts', $this->accounts) | ||||
|                 ->render(); | ||||
|         } catch (Throwable $e) { | ||||
|             Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); | ||||
|             $result = 'Could not render report view.'; | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -189,8 +198,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|             return $this->expenses; | ||||
|         } | ||||
|  | ||||
|         /** @var JournalCollectorInterface $collector */ | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setAccounts($this->accounts)->setRange($this->start, $this->end) | ||||
|                   ->setTypes([TransactionType::WITHDRAWAL]) | ||||
|                   ->setBudgets($this->budgets)->withOpposingAccount(); | ||||
| @@ -199,7 +208,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|         $collector->addFilter(OpposingAccountFilter::class); | ||||
|         $collector->addFilter(PositiveAmountFilter::class); | ||||
|  | ||||
|         $transactions   = $collector->getJournals(); | ||||
|         $transactions   = $collector->getTransactions(); | ||||
|         $this->expenses = $transactions; | ||||
|  | ||||
|         return $transactions; | ||||
|   | ||||
| @@ -24,6 +24,7 @@ namespace FireflyIII\Generator\Report\Budget; | ||||
|  | ||||
| /** | ||||
|  * Class MultiYearReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MultiYearReportGenerator extends MonthReportGenerator | ||||
| { | ||||
|   | ||||
| @@ -24,6 +24,7 @@ namespace FireflyIII\Generator\Report\Budget; | ||||
|  | ||||
| /** | ||||
|  * Class YearReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class YearReportGenerator extends MonthReportGenerator | ||||
| { | ||||
|   | ||||
| @@ -27,7 +27,7 @@ namespace FireflyIII\Generator\Report\Category; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Generator\Report\ReportGeneratorInterface; | ||||
| use FireflyIII\Generator\Report\Support; | ||||
| use FireflyIII\Helpers\Collector\JournalCollectorInterface; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\NegativeAmountFilter; | ||||
| use FireflyIII\Helpers\Filter\OpposingAccountFilter; | ||||
| use FireflyIII\Helpers\Filter\PositiveAmountFilter; | ||||
| @@ -36,9 +36,11 @@ use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Throwable; | ||||
|  | ||||
| /** | ||||
|  * Class MonthReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
| { | ||||
| @@ -68,7 +70,6 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|      * Generates the report. | ||||
|      * | ||||
|      * @return string | ||||
|      * @throws \Throwable | ||||
|      */ | ||||
|     public function generate(): string | ||||
|     { | ||||
| @@ -85,24 +86,23 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|         $topIncome       = $this->getTopIncome(); | ||||
|  | ||||
|         // render! | ||||
|         return view( | ||||
|             'reports.category.month', | ||||
|             compact( | ||||
|                 'accountIds', | ||||
|                 'categoryIds', | ||||
|                 'topIncome', | ||||
|                 'reportType', | ||||
|                 'accountSummary', | ||||
|                 'categorySummary', | ||||
|                 'averageExpenses', | ||||
|                 'averageIncome', | ||||
|                 'topExpenses' | ||||
|         try { | ||||
|             return view( | ||||
|                 'reports.category.month', compact( | ||||
|                                             'accountIds', 'categoryIds', 'topIncome', 'reportType', 'accountSummary', 'categorySummary', 'averageExpenses', | ||||
|                                             'averageIncome', 'topExpenses' | ||||
|                                         ) | ||||
|             ) | ||||
|         ) | ||||
|             ->with('start', $this->start)->with('end', $this->end) | ||||
|             ->with('categories', $this->categories) | ||||
|             ->with('accounts', $this->accounts) | ||||
|             ->render(); | ||||
|                 ->with('start', $this->start)->with('end', $this->end) | ||||
|                 ->with('categories', $this->categories) | ||||
|                 ->with('accounts', $this->accounts) | ||||
|                 ->render(); | ||||
|         } catch (Throwable $e) { | ||||
|             Log::error(sprintf('Cannot render reports.category.month: %s', $e->getMessage())); | ||||
|             $result = 'Could not render report view.'; | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -210,8 +210,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|             return $this->expenses; | ||||
|         } | ||||
|  | ||||
|         /** @var JournalCollectorInterface $collector */ | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setAccounts($this->accounts)->setRange($this->start, $this->end) | ||||
|                   ->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]) | ||||
|                   ->setCategories($this->categories)->withOpposingAccount(); | ||||
| @@ -220,7 +220,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|         $collector->addFilter(OpposingAccountFilter::class); | ||||
|         $collector->addFilter(PositiveAmountFilter::class); | ||||
|  | ||||
|         $transactions   = $collector->getJournals(); | ||||
|         $transactions   = $collector->getTransactions(); | ||||
|         $this->expenses = $transactions; | ||||
|  | ||||
|         return $transactions; | ||||
| @@ -237,8 +237,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|             return $this->income; | ||||
|         } | ||||
|  | ||||
|         /** @var JournalCollectorInterface $collector */ | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setAccounts($this->accounts)->setRange($this->start, $this->end) | ||||
|                   ->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER]) | ||||
|                   ->setCategories($this->categories)->withOpposingAccount(); | ||||
| @@ -246,7 +246,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|         $collector->addFilter(OpposingAccountFilter::class); | ||||
|         $collector->addFilter(NegativeAmountFilter::class); | ||||
|  | ||||
|         $transactions = $collector->getJournals(); | ||||
|         $transactions = $collector->getTransactions(); | ||||
|         $this->income = $transactions; | ||||
|  | ||||
|         return $transactions; | ||||
|   | ||||
| @@ -24,6 +24,7 @@ namespace FireflyIII\Generator\Report\Category; | ||||
|  | ||||
| /** | ||||
|  * Class MultiYearReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MultiYearReportGenerator extends MonthReportGenerator | ||||
| { | ||||
|   | ||||
| @@ -24,6 +24,7 @@ namespace FireflyIII\Generator\Report\Category; | ||||
|  | ||||
| /** | ||||
|  * Class YearReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class YearReportGenerator extends MonthReportGenerator | ||||
| { | ||||
|   | ||||
| @@ -27,6 +27,7 @@ use FireflyIII\Exceptions\FireflyException; | ||||
|  | ||||
| /** | ||||
|  * Class ReportGeneratorFactory. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class ReportGeneratorFactory | ||||
| { | ||||
|   | ||||
| @@ -26,9 +26,12 @@ use Carbon\Carbon; | ||||
| use FireflyIII\Generator\Report\ReportGeneratorInterface; | ||||
| use FireflyIII\Helpers\Report\ReportHelperInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Throwable; | ||||
|  | ||||
| /** | ||||
|  * Class MonthReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MonthReportGenerator implements ReportGeneratorInterface | ||||
| { | ||||
| @@ -43,7 +46,6 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|      * Generates the report. | ||||
|      * | ||||
|      * @return string | ||||
|      * @throws \Throwable | ||||
|      */ | ||||
|     public function generate(): string | ||||
|     { | ||||
| @@ -53,11 +55,17 @@ class MonthReportGenerator implements ReportGeneratorInterface | ||||
|         $accountIds = implode(',', $this->accounts->pluck('id')->toArray()); | ||||
|         $reportType = 'default'; | ||||
|  | ||||
|         // continue! | ||||
|         return view( | ||||
|             'reports.default.month', | ||||
|             compact('bills', 'accountIds', 'reportType') | ||||
|         )->with('start', $this->start)->with('end', $this->end)->render(); | ||||
|         try { | ||||
|             return view( | ||||
|                 'reports.default.month', | ||||
|                 compact('bills', 'accountIds', 'reportType') | ||||
|             )->with('start', $this->start)->with('end', $this->end)->render(); | ||||
|         } catch (Throwable $e) { | ||||
|             Log::error(sprintf('Cannot render reports.default.month: %s', $e->getMessage())); | ||||
|             $result = 'Could not render report view.'; | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -25,9 +25,12 @@ namespace FireflyIII\Generator\Report\Standard; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Generator\Report\ReportGeneratorInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Throwable; | ||||
|  | ||||
| /** | ||||
|  * Class MonthReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MultiYearReportGenerator implements ReportGeneratorInterface | ||||
| { | ||||
| @@ -42,7 +45,6 @@ class MultiYearReportGenerator implements ReportGeneratorInterface | ||||
|      * Generates the report. | ||||
|      * | ||||
|      * @return string | ||||
|      * @throws \Throwable | ||||
|      */ | ||||
|     public function generate(): string | ||||
|     { | ||||
| @@ -50,11 +52,17 @@ class MultiYearReportGenerator implements ReportGeneratorInterface | ||||
|         $accountIds = implode(',', $this->accounts->pluck('id')->toArray()); | ||||
|         $reportType = 'default'; | ||||
|  | ||||
|         // continue! | ||||
|         return view( | ||||
|             'reports.default.multi-year', | ||||
|             compact('accountIds', 'reportType') | ||||
|         )->with('start', $this->start)->with('end', $this->end)->render(); | ||||
|         try { | ||||
|             return view( | ||||
|                 'reports.default.multi-year', | ||||
|                 compact('accountIds', 'reportType') | ||||
|             )->with('start', $this->start)->with('end', $this->end)->render(); | ||||
|         } catch (Throwable $e) { | ||||
|             Log::error(sprintf('Cannot render reports.default.multi-year: %s', $e->getMessage())); | ||||
|             $result = 'Could not render report view.'; | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -25,9 +25,12 @@ namespace FireflyIII\Generator\Report\Standard; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Generator\Report\ReportGeneratorInterface; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Throwable; | ||||
|  | ||||
| /** | ||||
|  * Class MonthReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class YearReportGenerator implements ReportGeneratorInterface | ||||
| { | ||||
| @@ -42,7 +45,6 @@ class YearReportGenerator implements ReportGeneratorInterface | ||||
|      * Generates the report. | ||||
|      * | ||||
|      * @return string | ||||
|      * @throws \Throwable | ||||
|      */ | ||||
|     public function generate(): string | ||||
|     { | ||||
| @@ -50,13 +52,20 @@ class YearReportGenerator implements ReportGeneratorInterface | ||||
|         $accountIds = implode(',', $this->accounts->pluck('id')->toArray()); | ||||
|         $reportType = 'default'; | ||||
|  | ||||
|         // continue! | ||||
|         return view( | ||||
|             'reports.default.year', | ||||
|             compact('accountIds', 'reportType') | ||||
|         )->with('start', $this->start)->with('end', $this->end)->render(); | ||||
|         try { | ||||
|             $result = view( | ||||
|                 'reports.default.year', | ||||
|                 compact('accountIds', 'reportType') | ||||
|             )->with('start', $this->start)->with('end', $this->end)->render(); | ||||
|         } catch (Throwable $e) { | ||||
|             Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); | ||||
|             $result = 'Could not render report view.'; | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Set the accounts. | ||||
|      * | ||||
|   | ||||
| @@ -31,6 +31,7 @@ use Illuminate\Support\Collection; | ||||
|  * Class Support. | ||||
|  * @method Collection getExpenses() | ||||
|  * @method Collection getIncome() | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class Support | ||||
| { | ||||
|   | ||||
| @@ -28,7 +28,7 @@ namespace FireflyIII\Generator\Report\Tag; | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Generator\Report\ReportGeneratorInterface; | ||||
| use FireflyIII\Generator\Report\Support; | ||||
| use FireflyIII\Helpers\Collector\JournalCollectorInterface; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\NegativeAmountFilter; | ||||
| use FireflyIII\Helpers\Filter\OpposingAccountFilter; | ||||
| use FireflyIII\Helpers\Filter\PositiveAmountFilter; | ||||
| @@ -38,9 +38,11 @@ use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Throwable; | ||||
|  | ||||
| /** | ||||
|  * Class MonthReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
| { | ||||
| @@ -70,7 +72,6 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|      * Generate the report. | ||||
|      * | ||||
|      * @return string | ||||
|      * @throws \Throwable | ||||
|      */ | ||||
|     public function generate(): string | ||||
|     { | ||||
| @@ -87,20 +88,19 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|         $topIncome       = $this->getTopIncome(); | ||||
|  | ||||
|         // render! | ||||
|         return view( | ||||
|             'reports.tag.month', | ||||
|             compact( | ||||
|                 'accountIds', | ||||
|                 'tagTags', | ||||
|                 'reportType', | ||||
|                 'accountSummary', | ||||
|                 'tagSummary', | ||||
|                 'averageExpenses', | ||||
|                 'averageIncome', | ||||
|                 'topIncome', | ||||
|                 'topExpenses' | ||||
|             ) | ||||
|         )->with('start', $this->start)->with('end', $this->end)->with('tags', $this->tags)->with('accounts', $this->accounts)->render(); | ||||
|         try { | ||||
|             $result = view( | ||||
|                 'reports.tag.month', compact( | ||||
|                                        'accountIds', 'tagTags', 'reportType', 'accountSummary', 'tagSummary', 'averageExpenses', 'averageIncome', 'topIncome', | ||||
|                                        'topExpenses' | ||||
|                                    ) | ||||
|             )->with('start', $this->start)->with('end', $this->end)->with('tags', $this->tags)->with('accounts', $this->accounts)->render(); | ||||
|         } catch (Throwable $e) { | ||||
|             Log::error(sprintf('Cannot render reports.tag.month: %s', $e->getMessage())); | ||||
|             $result = 'Could not render report view.'; | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -208,8 +208,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|             return $this->expenses; | ||||
|         } | ||||
|  | ||||
|         /** @var JournalCollectorInterface $collector */ | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setAccounts($this->accounts)->setRange($this->start, $this->end) | ||||
|                   ->setTypes([TransactionType::WITHDRAWAL, TransactionType::TRANSFER]) | ||||
|                   ->setTags($this->tags)->withOpposingAccount(); | ||||
| @@ -218,7 +218,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|         $collector->addFilter(OpposingAccountFilter::class); | ||||
|         $collector->addFilter(PositiveAmountFilter::class); | ||||
|  | ||||
|         $transactions = $collector->getJournals(); | ||||
|         $transactions = $collector->getTransactions(); | ||||
|  | ||||
|         $this->expenses = $transactions; | ||||
|  | ||||
| @@ -236,8 +236,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|             return $this->income; | ||||
|         } | ||||
|  | ||||
|         /** @var JournalCollectorInterface $collector */ | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setAccounts($this->accounts)->setRange($this->start, $this->end) | ||||
|                   ->setTypes([TransactionType::DEPOSIT, TransactionType::TRANSFER]) | ||||
|                   ->setTags($this->tags)->withOpposingAccount(); | ||||
| @@ -245,7 +245,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface | ||||
|         $collector->addFilter(OpposingAccountFilter::class); | ||||
|         $collector->addFilter(NegativeAmountFilter::class); | ||||
|  | ||||
|         $transactions = $collector->getJournals(); | ||||
|         $transactions = $collector->getTransactions(); | ||||
|         $this->income = $transactions; | ||||
|  | ||||
|         return $transactions; | ||||
|   | ||||
| @@ -24,6 +24,7 @@ namespace FireflyIII\Generator\Report\Tag; | ||||
|  | ||||
| /** | ||||
|  * Class MultiYearReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class MultiYearReportGenerator extends MonthReportGenerator | ||||
| { | ||||
|   | ||||
| @@ -24,6 +24,7 @@ namespace FireflyIII\Generator\Report\Tag; | ||||
|  | ||||
| /** | ||||
|  * Class YearReportGenerator. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class YearReportGenerator extends MonthReportGenerator | ||||
| { | ||||
|   | ||||
| @@ -65,10 +65,10 @@ class APIEventHandler | ||||
|                 Log::error($e->getTraceAsString()); | ||||
|                 Session::flash('error', 'Possible email error: ' . $e->getMessage()); | ||||
|             } | ||||
|             // @codeCoverageIgnoreEnd | ||||
|             Log::debug('If no error above this line, message was sent.'); | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreEnd | ||||
|         return true; | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -57,16 +57,17 @@ class AdminEventHandler | ||||
|                 Log::debug('Trying to send message...'); | ||||
|                 Mail::to($email)->send(new AdminTestMail($email, $ipAddress)); | ||||
|                 // @codeCoverageIgnoreStart | ||||
|                 // Laravel cannot pretend this process failed during testing. | ||||
|             } catch (Exception $e) { | ||||
|                 Log::debug('Send message failed! :('); | ||||
|                 Log::error($e->getMessage()); | ||||
|                 Log::error($e->getTraceAsString()); | ||||
|                 Session::flash('error', 'Possible email error: ' . $e->getMessage()); | ||||
|             } | ||||
|             // @codeCoverageIgnoreEnd | ||||
|             Log::debug('If no error above this line, message was sent.'); | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreEnd | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -55,12 +55,14 @@ class AutomationHandler | ||||
|                 Mail::to($user->email)->send(new ReportNewJournalsMail($user->email, '127.0.0.1', $event->journals)); | ||||
|                 // @codeCoverageIgnoreStart | ||||
|             } catch (Exception $e) { | ||||
|                 Log::debug('Send message failed! :('); | ||||
|                 Log::error($e->getMessage()); | ||||
|                 Log::error($e->getTraceAsString()); | ||||
|             } | ||||
|             // @codeCoverageIgnoreEnd | ||||
|             Log::debug('Done!'); | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreEnd | ||||
|         return true; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -25,8 +25,6 @@ namespace FireflyIII\Handlers\Events; | ||||
| use FireflyIII\Events\StoredTransactionJournal; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; | ||||
| use FireflyIII\TransactionRules\Processor; | ||||
|  | ||||
| @@ -35,28 +33,6 @@ use FireflyIII\TransactionRules\Processor; | ||||
|  */ | ||||
| class StoredJournalEventHandler | ||||
| { | ||||
|     /** @var JournalRepositoryInterface The journal repository. */ | ||||
|     public $journalRepository; | ||||
|     /** @var PiggyBankRepositoryInterface The Piggy bank repository */ | ||||
|     public $repository; | ||||
|     /** @var RuleGroupRepositoryInterface The rule group repository */ | ||||
|     public $ruleGroupRepository; | ||||
|  | ||||
|     /** | ||||
|      * StoredJournalEventHandler constructor. | ||||
|      * | ||||
|      * @param PiggyBankRepositoryInterface $repository | ||||
|      * @param JournalRepositoryInterface   $journalRepository | ||||
|      * @param RuleGroupRepositoryInterface $ruleGroupRepository | ||||
|      */ | ||||
|     public function __construct( | ||||
|         PiggyBankRepositoryInterface $repository, JournalRepositoryInterface $journalRepository, RuleGroupRepositoryInterface $ruleGroupRepository | ||||
|     ) { | ||||
|         $this->repository          = $repository; | ||||
|         $this->journalRepository   = $journalRepository; | ||||
|         $this->ruleGroupRepository = $ruleGroupRepository; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method grabs all the users rules and processes them. | ||||
|      * | ||||
| @@ -67,16 +43,22 @@ class StoredJournalEventHandler | ||||
|      */ | ||||
|     public function processRules(StoredTransactionJournal $storedJournalEvent): bool | ||||
|     { | ||||
|         // get all the user's rule groups, with the rules, order by 'order'. | ||||
|         $journal = $storedJournalEvent->journal; | ||||
|         $groups  = $this->ruleGroupRepository->getActiveGroups($journal->user); | ||||
|  | ||||
|         // create objects: | ||||
|         /** @var RuleGroupRepositoryInterface $ruleGroupRepos */ | ||||
|         $ruleGroupRepos = app(RuleGroupRepositoryInterface::class); | ||||
|         $ruleGroupRepos->setUser($journal->user); | ||||
|         $groups         = $ruleGroupRepos->getActiveGroups($journal->user); | ||||
|  | ||||
|         /** @var RuleGroup $group */ | ||||
|         foreach ($groups as $group) { | ||||
|             $rules = $this->ruleGroupRepository->getActiveStoreRules($group); | ||||
|             $rules = $ruleGroupRepos->getActiveStoreRules($group); | ||||
|             /** @var Rule $rule */ | ||||
|             foreach ($rules as $rule) { | ||||
|                 $processor = Processor::make($rule); | ||||
|                 /** @var Processor $processor */ | ||||
|                 $processor = app(Processor::class); | ||||
|                 $processor->make($rule); | ||||
|                 $processor->handleTransactionJournal($journal); | ||||
|  | ||||
|                 if ($rule->stop_processing) { | ||||
|   | ||||
| @@ -33,19 +33,6 @@ use FireflyIII\TransactionRules\Processor; | ||||
|  */ | ||||
| class UpdatedJournalEventHandler | ||||
| { | ||||
|     /** @var RuleGroupRepositoryInterface The rule group repository */ | ||||
|     public $repository; | ||||
|  | ||||
|     /** | ||||
|      * StoredJournalEventHandler constructor. | ||||
|      * | ||||
|      * @param RuleGroupRepositoryInterface $ruleGroupRepository | ||||
|      */ | ||||
|     public function __construct(RuleGroupRepositoryInterface $ruleGroupRepository) | ||||
|     { | ||||
|         $this->repository = $ruleGroupRepository; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This method will check all the rules when a journal is updated. | ||||
|      * | ||||
| @@ -58,14 +45,21 @@ class UpdatedJournalEventHandler | ||||
|     { | ||||
|         // get all the user's rule groups, with the rules, order by 'order'. | ||||
|         $journal = $updatedJournalEvent->journal; | ||||
|         $groups  = $this->repository->getActiveGroups($journal->user); | ||||
|  | ||||
|         /** @var RuleGroupRepositoryInterface $ruleGroupRepos */ | ||||
|         $ruleGroupRepos = app(RuleGroupRepositoryInterface::class); | ||||
|         $ruleGroupRepos->setUser($journal->user); | ||||
|  | ||||
|         $groups  = $ruleGroupRepos->getActiveGroups($journal->user); | ||||
|  | ||||
|         /** @var RuleGroup $group */ | ||||
|         foreach ($groups as $group) { | ||||
|             $rules = $this->repository->getActiveUpdateRules($group); | ||||
|             $rules = $ruleGroupRepos->getActiveUpdateRules($group); | ||||
|             /** @var Rule $rule */ | ||||
|             foreach ($rules as $rule) { | ||||
|                 $processor = Processor::make($rule); | ||||
|                 /** @var Processor $processor */ | ||||
|                 $processor = app(Processor::class); | ||||
|                 $processor->make($rule); | ||||
|                 $processor->handleTransactionJournal($journal); | ||||
|  | ||||
|                 if ($rule->stop_processing) { | ||||
|   | ||||
| @@ -61,6 +61,7 @@ class UserEventHandler | ||||
|  | ||||
|         // first user ever? | ||||
|         if (1 === $repository->count()) { | ||||
|             Log::debug('User count is one, attach role.'); | ||||
|             $repository->attachRole($event->user, 'owner'); | ||||
|         } | ||||
|  | ||||
| @@ -145,8 +146,8 @@ class UserEventHandler | ||||
|         } catch (Exception $e) { | ||||
|             Log::error($e->getMessage()); | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreEnd | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @@ -171,8 +172,8 @@ class UserEventHandler | ||||
|         } catch (Exception $e) { | ||||
|             Log::error($e->getMessage()); | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreEnd | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
| @@ -198,7 +199,6 @@ class UserEventHandler | ||||
|         } catch (Exception $e) { | ||||
|             Log::error($e->getMessage()); | ||||
|         } | ||||
|  | ||||
|         // @codeCoverageIgnoreEnd | ||||
|  | ||||
|         return true; | ||||
|   | ||||
| @@ -27,14 +27,13 @@ namespace FireflyIII\Handlers\Events; | ||||
|  | ||||
| use FireflyConfig; | ||||
| use FireflyIII\Events\RequestedVersionCheckStatus; | ||||
|  | ||||
| use FireflyIII\Helpers\Update\UpdateTrait; | ||||
| use FireflyIII\Models\Configuration; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
|  | ||||
|  | ||||
| use FireflyIII\User; | ||||
| use Log; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class VersionCheckEventHandler | ||||
|  */ | ||||
| @@ -52,10 +51,13 @@ class VersionCheckEventHandler | ||||
|      */ | ||||
|     public function checkForUpdates(RequestedVersionCheckStatus $event): void | ||||
|     { | ||||
|         Log::debug('Now in checkForUpdates()'); | ||||
|         // in Sandstorm, cannot check for updates: | ||||
|         $sandstorm = 1 === (int)getenv('SANDSTORM'); | ||||
|         if (true === $sandstorm) { | ||||
|             return; // @codeCoverageIgnore | ||||
|             Log::debug('This is Sandstorm instance, done.'); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         /** @var UserRepositoryInterface $repository */ | ||||
| @@ -63,25 +65,27 @@ class VersionCheckEventHandler | ||||
|         /** @var User $user */ | ||||
|         $user = $event->user; | ||||
|         if (!$repository->hasRole($user, 'owner')) { | ||||
|             Log::debug('User is not admin, done.'); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         /** @var Configuration $lastCheckTime */ | ||||
|         $lastCheckTime = FireflyConfig::get('last_update_check', time()); | ||||
|         $now           = time(); | ||||
|         $diff          = $now - $lastCheckTime->data; | ||||
|         Log::debug(sprintf('Difference is %d seconds.', $diff)); | ||||
|         Log::debug(sprintf('Last check time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff)); | ||||
|         if ($diff < 604800) { | ||||
|             Log::debug(sprintf('Checked for updates less than a week ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data))); | ||||
|  | ||||
|             //return; | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|         // last check time was more than a week ago. | ||||
|         Log::debug('Have not checked for a new version in a week!'); | ||||
|  | ||||
|         $latestRelease = $this->getLatestRelease(); | ||||
|         $versionCheck  = $this->versionCheck($latestRelease); | ||||
|         $resultString = $this->parseResult($versionCheck, $latestRelease); | ||||
|         $resultString  = $this->parseResult($versionCheck, $latestRelease); | ||||
|         if (0 !== $versionCheck && '' !== $resultString) { | ||||
|             // flash info | ||||
|             session()->flash('info', $resultString); | ||||
|   | ||||
| @@ -25,7 +25,6 @@ namespace FireflyIII\Helpers\Attachments; | ||||
| use Crypt; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use Illuminate\Contracts\Encryption\DecryptException; | ||||
| use Illuminate\Contracts\Filesystem\FileNotFoundException; | ||||
| use Illuminate\Database\Eloquent\Model; | ||||
| use Illuminate\Support\Collection; | ||||
| use Illuminate\Support\MessageBag; | ||||
| @@ -80,7 +79,7 @@ class AttachmentHelper implements AttachmentHelperInterface | ||||
|  | ||||
|         try { | ||||
|             $content = Crypt::decrypt($this->uploadDisk->get(sprintf('at-%d.data', $attachment->id))); | ||||
|         } catch (DecryptException|FileNotFoundException $e) { | ||||
|         } catch (DecryptException $e) { | ||||
|             Log::error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage())); | ||||
|             $content = ''; | ||||
|         } | ||||
| @@ -145,9 +144,11 @@ class AttachmentHelper implements AttachmentHelperInterface | ||||
|     { | ||||
|         $resource = tmpfile(); | ||||
|         if (false === $resource) { | ||||
|             // @codeCoverageIgnoreStart | ||||
|             Log::error('Cannot create temp-file for file upload.'); | ||||
|  | ||||
|             return false; | ||||
|             // @codeCoverageIgnoreEnd | ||||
|         } | ||||
|         $path = stream_get_meta_data($resource)['uri']; | ||||
|         fwrite($resource, $content); | ||||
| @@ -342,9 +343,12 @@ class AttachmentHelper implements AttachmentHelperInterface | ||||
|         if (!$this->validMime($file)) { | ||||
|             $result = false; | ||||
|         } | ||||
|         // @codeCoverageIgnoreStart | ||||
|         // can't seem to reach this point. | ||||
|         if (true === $result && !$this->validSize($file)) { | ||||
|             $result = false; | ||||
|         } | ||||
|         // @codeCoverageIgnoreEnd | ||||
|         if (true === $result && $this->hasFile($file, $model)) { | ||||
|             $result = false; | ||||
|         } | ||||
|   | ||||
| @@ -24,7 +24,7 @@ declare(strict_types=1); | ||||
| namespace FireflyIII\Helpers\Chart; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Helpers\Collector\JournalCollectorInterface; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\NegativeAmountFilter; | ||||
| use FireflyIII\Helpers\Filter\OpposingAccountFilter; | ||||
| use FireflyIII\Helpers\Filter\PositiveAmountFilter; | ||||
| @@ -108,12 +108,12 @@ class MetaPieChart implements MetaPieChartInterface | ||||
|  | ||||
|         // also collect all other transactions | ||||
|         if ($this->collectOtherObjects && 'expense' === $direction) { | ||||
|             /** @var JournalCollectorInterface $collector */ | ||||
|             $collector = app(JournalCollectorInterface::class); | ||||
|             /** @var TransactionCollectorInterface $collector */ | ||||
|             $collector = app(TransactionCollectorInterface::class); | ||||
|             $collector->setUser($this->user); | ||||
|             $collector->setAccounts($this->accounts)->setRange($this->start, $this->end)->setTypes([TransactionType::WITHDRAWAL]); | ||||
|  | ||||
|             $journals        = $collector->getJournals(); | ||||
|             $journals        = $collector->getTransactions(); | ||||
|             $sum             = (string)$journals->sum('transaction_amount'); | ||||
|             $sum             = bcmul($sum, '-1'); | ||||
|             $sum             = bcsub($sum, $this->total); | ||||
| @@ -121,11 +121,11 @@ class MetaPieChart implements MetaPieChartInterface | ||||
|         } | ||||
|  | ||||
|         if ($this->collectOtherObjects && 'income' === $direction) { | ||||
|             /** @var JournalCollectorInterface $collector */ | ||||
|             $collector = app(JournalCollectorInterface::class); | ||||
|             /** @var TransactionCollectorInterface $collector */ | ||||
|             $collector = app(TransactionCollectorInterface::class); | ||||
|             $collector->setUser($this->user); | ||||
|             $collector->setAccounts($this->accounts)->setRange($this->start, $this->end)->setTypes([TransactionType::DEPOSIT]); | ||||
|             $journals        = $collector->getJournals(); | ||||
|             $journals        = $collector->getTransactions(); | ||||
|             $sum             = (string)$journals->sum('transaction_amount'); | ||||
|             $sum             = bcsub($sum, $this->total); | ||||
|             $chartData[$key] = $sum; | ||||
| @@ -271,8 +271,8 @@ class MetaPieChart implements MetaPieChartInterface | ||||
|      */ | ||||
|     protected function getTransactions(string $direction): Collection | ||||
|     { | ||||
|         /** @var JournalCollectorInterface $collector */ | ||||
|         $collector = app(JournalCollectorInterface::class); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $types     = [TransactionType::DEPOSIT, TransactionType::TRANSFER]; | ||||
|         $collector->addFilter(NegativeAmountFilter::class); | ||||
|         if ('expense' === $direction) { | ||||
| @@ -304,7 +304,7 @@ class MetaPieChart implements MetaPieChartInterface | ||||
|  | ||||
|         // @codeCoverageIgnoreEnd | ||||
|  | ||||
|         return $collector->getJournals(); | ||||
|         return $collector->getTransactions(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -360,7 +360,8 @@ class MetaPieChart implements MetaPieChartInterface | ||||
|         foreach ($array as $objectId => $amount) { | ||||
|             if (!isset($names[$objectId])) { | ||||
|                 $object           = $repository->findNull((int)$objectId); | ||||
|                 $names[$objectId] = $object->name ?? $object->tag; | ||||
|                 $name             = null === $object ? '(no name)' : $object->name; | ||||
|                 $names[$objectId] = $name ?? $object->tag; | ||||
|             } | ||||
|             $amount                       = app('steam')->positive($amount); | ||||
|             $this->total                  = bcadd($this->total, $amount); | ||||
|   | ||||
| @@ -26,6 +26,8 @@ use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class Balance. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class Balance | ||||
| { | ||||
|   | ||||
| @@ -26,6 +26,8 @@ use FireflyIII\Models\Account as AccountModel; | ||||
|  | ||||
| /** | ||||
|  * Class BalanceEntry. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class BalanceEntry | ||||
| { | ||||
|   | ||||
| @@ -27,6 +27,8 @@ use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class BalanceHeader. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class BalanceHeader | ||||
| { | ||||
|   | ||||
| @@ -29,6 +29,8 @@ use Illuminate\Support\Collection; | ||||
|  | ||||
| /** | ||||
|  * Class BalanceLine. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class BalanceLine | ||||
| { | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user