Compare commits

..

156 Commits
4.2.2 ... 4.3.0

Author SHA1 Message Date
James Cole
ad1e9c27e9 Merge branch 'release/4.3.0' 2016-12-26 10:46:22 +01:00
James Cole
ab761696bf New version indicator. 2016-12-26 10:45:45 +01:00
James Cole
0713273a99 New composer file. 2016-12-26 10:45:19 +01:00
James Cole
5668a3271b Updated change log. 2016-12-26 10:40:28 +01:00
James Cole
1eca105a91 Merge pull request #494 from JC5/l10n_develop
New Crowdin translations
2016-12-26 10:34:00 +01:00
James Cole
3883b99c24 New translations 2016-12-26 10:31:51 +01:00
James Cole
d6adbc697a New translations 2016-12-26 10:31:49 +01:00
James Cole
a5789b1085 New translations 2016-12-26 10:31:48 +01:00
James Cole
a6ccbcb795 New translations 2016-12-26 10:31:47 +01:00
James Cole
1a6067f7ae New translations 2016-12-26 10:31:46 +01:00
James Cole
cb735b18a9 New translations 2016-12-26 10:31:45 +01:00
James Cole
909bd11147 New translations 2016-12-26 10:31:42 +01:00
James Cole
1a76c606ed New translations 2016-12-26 10:31:41 +01:00
James Cole
8c9b6796a1 Approved. Step name: Proofread 2016-12-26 10:31:38 +01:00
James Cole
844ab608d4 More demo text [skip ci] 2016-12-26 10:23:47 +01:00
James Cole
dc39094975 New translations 2016-12-26 10:12:11 +01:00
James Cole
b32184d525 New translations 2016-12-26 10:12:09 +01:00
James Cole
d95ae53ce2 New translations 2016-12-26 10:12:07 +01:00
James Cole
5e3147ddeb New translations 2016-12-26 10:12:06 +01:00
James Cole
9e594c6075 New translations 2016-12-26 10:12:04 +01:00
James Cole
c0058c51ea New translations 2016-12-26 10:12:03 +01:00
James Cole
b0b68d4243 New translations 2016-12-26 10:12:00 +01:00
James Cole
22eb90212d New translations 2016-12-26 10:11:59 +01:00
James Cole
94e264b6ce Expand demo text [skip ci] 2016-12-26 10:00:40 +01:00
James Cole
7ea15761a6 Fix tests. 2016-12-26 09:50:37 +01:00
James Cole
1ced4a089d Update read me [skip ci] 2016-12-26 09:50:28 +01:00
James Cole
648e63628c Extra code for demo site. 2016-12-26 09:33:52 +01:00
James Cole
2847e2aff5 Code for the demo features. 2016-12-26 09:18:45 +01:00
James Cole
9dfaabb5d0 New translations 2016-12-26 09:12:28 +01:00
James Cole
6a21f98ea4 New translations 2016-12-26 09:12:22 +01:00
James Cole
4d5f4cc1c0 New translations 2016-12-26 09:12:14 +01:00
James Cole
970ce6cb0d New translations 2016-12-26 09:12:10 +01:00
James Cole
31cad5de00 New translations 2016-12-26 09:12:05 +01:00
James Cole
e06db9e620 New translations 2016-12-26 09:11:59 +01:00
James Cole
f57ac64dc2 New translations 2016-12-26 09:11:54 +01:00
James Cole
57d7c1623f New translations 2016-12-26 09:11:36 +01:00
James Cole
c86aa9cb3f Can no longer reset the demo user’s password. 2016-12-26 09:08:59 +01:00
James Cole
48209d0d22 Demo user cannot enable two factor auth. 2016-12-26 08:57:07 +01:00
James Cole
8f6a271cc0 Add the ability to prefix cache differently. 2016-12-25 13:38:30 +01:00
James Cole
a9b610f367 New translations 2016-12-25 13:12:12 +01:00
James Cole
1046930f29 New translations 2016-12-25 13:12:00 +01:00
James Cole
1b16e5e216 New translations 2016-12-25 13:11:56 +01:00
James Cole
e16ba9ac70 New translations 2016-12-25 13:11:53 +01:00
James Cole
71ac676b83 New translations 2016-12-25 13:11:47 +01:00
James Cole
1b6c0d5d86 New translations 2016-12-25 13:11:43 +01:00
James Cole
14db016e98 New translations 2016-12-25 13:11:27 +01:00
James Cole
7e2e1626ac Approved. Step name: Proofread 2016-12-25 13:11:15 +01:00
James Cole
bce4e7e2bf Add restrictions for demo accounts. 2016-12-25 13:09:29 +01:00
James Cole
ede327f3d3 Merge pull request #493 from JC5/l10n_develop
New Crowdin translations
2016-12-25 12:59:27 +01:00
James Cole
82718a74dc Fix tests 2016-12-25 12:55:22 +01:00
James Cole
eefd6141a1 Translated 2016-12-25 12:31:05 +01:00
James Cole
7894f1871e Make sure the attachment tests work. 2016-12-25 12:23:36 +01:00
James Cole
0ef9b5b462 Make sure database is present in tests. 2016-12-25 12:06:17 +01:00
James Cole
9ca75d134e This is the test database required to run the tests. 2016-12-25 12:03:21 +01:00
James Cole
b78776e1f7 This generates a lot of logging, let’s remove it. 2016-12-25 11:52:01 +01:00
James Cole
f2f9f8fbab Various bug fixes and extensions to test routine. 2016-12-25 11:50:42 +01:00
James Cole
5b5acba816 Clean up lots of models. 2016-12-24 17:36:51 +01:00
James Cole
9f2729d0ff Removed Firefly’s ability to generate test data. 2016-12-24 14:48:14 +01:00
James Cole
afe98cda9f Various code cleanup things and preparation for a new demo user. 2016-12-24 14:43:42 +01:00
James Cole
9c4d2e8791 Mention $other in chart cache. [skip ci] 2016-12-23 18:48:21 +01:00
James Cole
cea170359f Budget chart. 2016-12-23 18:34:58 +01:00
James Cole
70bb8fbc89 New translations 2016-12-23 17:53:16 +01:00
James Cole
82cd0adca6 New translations 2016-12-23 17:52:57 +01:00
James Cole
e821f5b2b6 New translations 2016-12-23 17:52:51 +01:00
James Cole
4cade467c6 New translations 2016-12-23 17:52:46 +01:00
James Cole
b6c9639948 New translations 2016-12-23 17:52:39 +01:00
James Cole
ca9319db34 New translations 2016-12-23 17:52:33 +01:00
James Cole
beaec9a4c1 New translations 2016-12-23 17:52:11 +01:00
James Cole
cbc44e8200 Approved. Step name: Proofread 2016-12-23 17:51:54 +01:00
James Cole
017b1a481a Committed bad code. 2016-12-23 17:51:33 +01:00
James Cole
e15932fe4a Make budget report actually more useful. 2016-12-23 17:50:26 +01:00
James Cole
08c044fe52 Merge pull request #491 from JC5/l10n_develop
New Crowdin translations
2016-12-23 15:52:34 +01:00
James Cole
0e11245cb4 Fix tests. 2016-12-23 15:52:12 +01:00
James Cole
cde494d3ef Fixed missing chart data. 2016-12-23 15:52:05 +01:00
James Cole
9a15decdff Translated 2016-12-23 15:02:25 +01:00
James Cole
186b986e02 New translations 2016-12-23 07:32:48 +01:00
James Cole
cdbf5653ac New translations 2016-12-23 07:32:34 +01:00
James Cole
c403dd7490 New translations 2016-12-23 07:32:28 +01:00
James Cole
d15d9fdf2a New translations 2016-12-23 07:32:24 +01:00
James Cole
0b618de44c New translations 2016-12-23 07:32:16 +01:00
James Cole
875f19f728 New translations 2016-12-23 07:32:11 +01:00
James Cole
7bb549732c New translations 2016-12-23 07:31:50 +01:00
James Cole
b9baa93ae4 Approved. Step name: Proofread 2016-12-23 07:31:36 +01:00
James Cole
315479fcd3 New translations [skip ci] 2016-12-23 07:24:38 +01:00
James Cole
1f1334a1fc Update chart to show sum 2016-12-23 07:20:47 +01:00
James Cole
bf0744e03a Updated some copyright notices [skip ci] 2016-12-23 07:02:45 +01:00
James Cole
8fb9577660 Add some debug, fix balance report bug. 2016-12-22 21:45:04 +01:00
James Cole
90d58c5c39 Update test scripts [skip ci] 2016-12-22 19:51:49 +01:00
James Cole
b6aa79bb38 Various code cleanup. Removed executable flags, added newlines. 2016-12-22 19:42:45 +01:00
James Cole
14a0de6b6a This should fix account-number. 2016-12-22 19:18:35 +01:00
James Cole
13e56b7249 Can handle account number, but do nothing with it. 2016-12-22 19:17:33 +01:00
James Cole
3753901e38 Expand flush routine because of issues. [skip ci] 2016-12-22 18:26:16 +01:00
James Cole
e76075e29f Various small fixes. 2016-12-22 18:19:50 +01:00
James Cole
284db7f90b Fixed some small display issues. 2016-12-22 17:04:41 +01:00
James Cole
cabdf4e380 This might fix the missing stack trace. [skip ci] 2016-12-22 16:55:27 +01:00
James Cole
9859052c4d Code for issue #489 2016-12-22 16:36:56 +01:00
James Cole
0feeac9160 Removed some unused imports [skip ci] 2016-12-22 15:24:16 +01:00
James Cole
54b33a0b69 Removed views no longer used. 2016-12-22 07:13:49 +01:00
James Cole
e08e7b2c9b Speed up some tests. 2016-12-22 07:13:37 +01:00
James Cole
782e2add88 Fix sort URI, smaller view [skip ci] 2016-12-21 20:34:47 +01:00
James Cole
f18a5a6f1b This fixes the broken tests. 2016-12-21 20:32:02 +01:00
James Cole
6fc971c4cb This is a fix for #487 2016-12-21 20:31:44 +01:00
James Cole
3250c4830d New seeds plus the preparation for some extended testing. 2016-12-21 19:56:06 +01:00
James Cole
9e1a69217d This fixes #484. 2016-12-21 17:50:00 +01:00
James Cole
46c26a64d8 Update import storage routine for issue #483, as suggested by @zjean 2016-12-21 17:21:36 +01:00
James Cole
2f12a70647 Add support for Spanish. [skip ci] 2016-12-20 17:21:16 +01:00
James Cole
be190d1fa0 Update favicon information. 2016-12-20 17:19:16 +01:00
James Cole
1e4888209b Fixed #479 2016-12-20 17:14:43 +01:00
James Cole
8aa2961c19 This should fix #482 2016-12-20 17:10:30 +01:00
James Cole
304cdabc96 Merge pull request #481 from JC5/l10n_develop
New Crowdin translations
2016-12-20 14:16:39 +01:00
James Cole
c60e272eb3 New translations 2016-12-20 10:42:06 +01:00
James Cole
c074f55cb2 New translations 2016-12-20 10:42:05 +01:00
James Cole
e6af29646e New translations 2016-12-20 10:42:03 +01:00
James Cole
b4213328fe New translations 2016-12-20 10:42:02 +01:00
James Cole
8a7628c9dc New translations 2016-12-20 10:42:00 +01:00
James Cole
d52c146e12 New translations 2016-12-20 10:41:58 +01:00
James Cole
1910a4bd4b New translations 2016-12-20 10:41:57 +01:00
James Cole
bd0c552f54 New translations 2016-12-20 10:41:55 +01:00
James Cole
b29ea98de4 New translations 2016-12-20 10:41:53 +01:00
James Cole
dd1db87806 New translations 2016-12-20 10:41:50 +01:00
James Cole
6f9e446577 New translations 2016-12-20 10:41:45 +01:00
James Cole
664230dca8 This fixes #478, again 2016-12-20 10:25:11 +01:00
James Cole
1a24e7e0aa Merge pull request #476 from JC5/l10n_develop
New Crowdin translations
2016-12-19 21:10:53 +01:00
James Cole
9239815ce6 Tiny view update. 2016-12-19 21:07:38 +01:00
James Cole
116e19ec06 These routines fix #477 2016-12-19 21:07:22 +01:00
James Cole
fc0ad622eb Clarify chart details [skip ci] 2016-12-19 20:47:26 +01:00
James Cole
2c5cdb8780 Clarify chart details [skip ci] 2016-12-19 20:46:24 +01:00
James Cole
9a309f32fa This fixes #478 2016-12-19 20:36:28 +01:00
James Cole
e2e54d342a This completes all controller acceptance tests 2016-12-19 20:21:14 +01:00
James Cole
42f7529495 Approved. Step name: Proofread 2016-12-19 20:01:50 +01:00
James Cole
f172151252 Expand read me [skip ci] 2016-12-19 17:31:23 +01:00
James Cole
e2ad38d3e0 Expand read me [skip ci] 2016-12-19 17:24:15 +01:00
James Cole
40cc32fc5a Updated favicon. 2016-12-19 17:15:31 +01:00
James Cole
436c034fdd New translations 2016-12-19 11:51:37 +01:00
James Cole
286b1848d9 New translations 2016-12-19 10:31:15 +01:00
James Cole
7fffebf6df New translations 2016-12-19 10:21:22 +01:00
James Cole
b1764478ec Translated 2016-12-19 10:11:53 +01:00
James Cole
6b6a799206 Translated 2016-12-18 21:41:01 +01:00
James Cole
0a82ed901e New translations 2016-12-18 21:12:00 +01:00
James Cole
d733c9ed14 New translations 2016-12-18 21:11:57 +01:00
James Cole
a752ea489c New translations 2016-12-18 21:11:51 +01:00
James Cole
876a24586f New translations 2016-12-18 21:11:47 +01:00
James Cole
ea2779cf9a New translations 2016-12-18 21:11:41 +01:00
James Cole
77aa36163d New translations 2016-12-18 21:11:38 +01:00
James Cole
b581d8ecb7 New translations 2016-12-18 21:11:18 +01:00
James Cole
83b404d01e More tests. 2016-12-18 21:04:53 +01:00
James Cole
8deb92c3e5 More tests. 2016-12-18 19:34:03 +01:00
James Cole
20a6e0170c New translations 2016-12-18 18:22:10 +01:00
James Cole
944a78807c New translations 2016-12-18 18:22:05 +01:00
James Cole
0b02d294f4 New translations 2016-12-18 18:22:00 +01:00
James Cole
a5d86536c3 New translations 2016-12-18 18:21:52 +01:00
James Cole
71c08cfe0c New translations 2016-12-18 18:21:48 +01:00
James Cole
8ab0d5fc48 New translations 2016-12-18 18:21:40 +01:00
James Cole
57f81ee4c8 Approved. Step name: Proofread 2016-12-18 18:21:29 +01:00
James Cole
5c28adf266 New tests. [skip ci] 2016-12-18 18:16:41 +01:00
James Cole
5a57398f81 New tests. 2016-12-18 17:54:11 +01:00
345 changed files with 4750 additions and 5695 deletions

View File

@@ -38,9 +38,14 @@ SEND_REGISTRATION_MAIL=true
SEND_ERROR_MESSAGE=true
SHOW_INCOMPLETE_TRANSLATIONS=false
CACHE_PREFIX=firefly
ANALYTICS_ID=
SITE_OWNER=mail@example.com
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_APP_ID=
DEMO_USERNAME=
DEMO_PASSWORD=

View File

@@ -5,14 +5,13 @@ php:
install:
- phpenv config-rm xdebug.ini
- composer selfupdate
- rm composer.lock
- composer update --no-scripts
- php artisan clear-compiled
- php artisan optimize
- php artisan env
- ./test.sh -r
- php artisan env
- cp .env.testing .env
- mv storage/database/databasecopy.sqlite storage/database/database.sqlite
script:
- phpunit

View File

@@ -2,6 +2,28 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [4.3.0] - 2015-12-26
### Added
- New method of keeping track of available budget, see issue #489
- Support for Spanish
- Firefly III now has an extended demo mode. Will expand further in the future.
### Changed
- New favicon
- Import routine no longer gives transactions a description #483
### Removed
- All test data generation code.
### Fixed
- Removed import accounts from search results #478
- Redirect after delete will no longer go back to deleted item #477
- Cannot math #482
- Fixed bug in virtual balance field #479
## [4.2.2] - 2016-12-18
### Added
- New budget report (still a bit of a beta)

View File

@@ -1,8 +1,8 @@
# Firefly III [![Requires PHP7](https://img.shields.io/badge/php-7.0-red.svg)](https://secure.php.net/downloads.php#v7.0.4) [![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable)](https://packagist.org/packages/grumpydictator/firefly-iii) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
# Firefly III: A personal finances manager
[![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=master)](https://travis-ci.org/JC5/firefly-iii)
[![Requires PHP7](https://img.shields.io/badge/php-7.0-red.svg)](https://secure.php.net/downloads.php#v7.0.4) [![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable)](https://packagist.org/packages/grumpydictator/firefly-iii) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master)
## A personal finances manager
[![Build Status](https://travis-ci.org/JC5/firefly-iii.svg?branch=master)](https://travis-ci.org/JC5/firefly-iii) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA)
[![The index of Firefly III](https://i.nder.be/hurdhgyg/400)](https://i.nder.be/h2b37243) [![The account overview of Firefly III](https://i.nder.be/hnkfkdpr/400)](https://i.nder.be/hv70pbwc)
@@ -12,6 +12,10 @@ _(You can click on the images for a better view)_
"Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money.
## Try it out!
Try out Firefly III on the [demo site](https://firefly-iii.nder.be/).
## Installation
To install Firefly III, you'll need a web server (preferrably on Linux) and access to the command line. Then, please read the [installation guide](https://firefly-iii.github.io/installation-guide/).
@@ -31,4 +35,6 @@ Firefly works on the principle that if you know where you're money is going, you
Firefly is pretty awesome. [You can read more about Firefly III, and its features, on the Github Pages](https://firefly-iii.github.io/).
If you like Firefly and if it helps you save lots of money, why not send me [a dime for every dollar saved](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA) (this is a joke, although the Paypal form works just fine, try it!)
If you want to contact me, please open an issue or [email me](mailto:thegrumpydictator@gmail.com).

View File

@@ -50,11 +50,10 @@ class CreateImport extends Command
}
/**
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped
*/
public function handle()
{
// find the file
/** @var UserRepositoryInterface $userRepository */
$userRepository = app(UserRepositoryInterface::class);
$file = $this->argument('file');
@@ -67,7 +66,6 @@ class CreateImport extends Command
return;
}
// try to parse configuration data:
$configurationData = json_decode(file_get_contents($configuration));
if (is_null($configurationData)) {
$this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
@@ -82,21 +80,17 @@ class CreateImport extends Command
/** @var ImportJobRepositoryInterface $jobRepository */
$jobRepository = app(ImportJobRepositoryInterface::class, [$user]);
$job = $jobRepository->create($type);
$job = $jobRepository->create($type);
$this->line(sprintf('Created job "%s"...', $job->key));
// put the file in the proper place:
Artisan::call('firefly:encrypt', ['file' => $file, 'key' => $job->key]);
$this->line('Stored import data...');
// store the configuration in the job:
$job->configuration = $configurationData;
$job->status = 'settings_complete';
$job->save();
$this->line('Stored configuration...');
// if user wants to run it, do!
if ($this->option('start') === true) {
$this->line('The import will start in a moment. This process is not visible...');
Log::debug('Go for import!');
@@ -109,10 +103,10 @@ class CreateImport extends Command
/**
* @return bool
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly.
*/
private function validArguments(): bool
{
// find the file
/** @var UserRepositoryInterface $userRepository */
$userRepository = app(UserRepositoryInterface::class);
$file = $this->argument('file');

View File

@@ -18,6 +18,7 @@ use FireflyIII\Import\Logging\CommandHandler;
use FireflyIII\Models\ImportJob;
use FireflyIII\Models\TransactionJournal;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Log;
/**
@@ -69,32 +70,15 @@ class Import extends Command
$monolog = Log::getMonolog();
$handler = new CommandHandler($this);
$monolog->pushHandler($handler);
$importProcedure = new ImportProcedure;
$result = $importProcedure->runImport($job);
$result = ImportProcedure::runImport($job);
/**
* @var int $index
* @var TransactionJournal $journal
*/
foreach ($result as $index => $journal) {
if (!is_null($journal->id)) {
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $journal->id));
continue;
}
$this->error(sprintf('Could not store line #%d', $index));
}
// display result to user:
$this->presentResults($result);
$this->line('The import has completed.');
// get any errors from the importer:
$extendedStatus = $job->extended_status;
if (isset($extendedStatus['errors']) && count($extendedStatus['errors']) > 0) {
$this->line(sprintf('The following %d error(s) occured during the import:', count($extendedStatus['errors'])));
foreach ($extendedStatus['errors'] as $error) {
$this->error($error);
}
}
$this->presentErrors($job);
return;
}
@@ -120,4 +104,36 @@ class Import extends Command
return true;
}
/**
* @param ImportJob $job
*/
private function presentErrors(ImportJob $job)
{
$extendedStatus = $job->extended_status;
if (isset($extendedStatus['errors']) && count($extendedStatus['errors']) > 0) {
$this->line(sprintf('The following %d error(s) occured during the import:', count($extendedStatus['errors'])));
foreach ($extendedStatus['errors'] as $error) {
$this->error($error);
}
}
}
/**
* @param Collection $result
*/
private function presentResults(Collection $result)
{
/**
* @var int $index
* @var TransactionJournal $journal
*/
foreach ($result as $index => $journal) {
if (!is_null($journal->id)) {
$this->line(sprintf('Line #%d has been imported as transaction #%d.', $index, $journal->id));
continue;
}
$this->error(sprintf('Could not store line #%d', $index));
}
}
}

View File

@@ -60,42 +60,26 @@ class ScanAttachments extends Command
/** @var Attachment $attachment */
foreach ($attachments as $attachment) {
$fileName = $attachment->fileName();
// try to grab file content:
try {
$content = $disk->get($fileName);
} catch (FileNotFoundException $e) {
$this->error(sprintf('Could not find data for attachment #%d', $attachment->id));
continue;
}
// try to decrypt content.
try {
$decrypted = Crypt::decrypt($content);
} catch (DecryptException $e) {
$this->error(sprintf('Could not decrypt data of attachment #%d', $attachment->id));
continue;
}
// make temp file:
$tmpfname = tempnam(sys_get_temp_dir(), 'FireflyIII');
// store content in temp file:
file_put_contents($tmpfname, $decrypted);
// get md5 and mime
$md5 = md5_file($tmpfname);
$mime = mime_content_type($tmpfname);
// update attachment:
$md5 = md5_file($tmpfname);
$mime = mime_content_type($tmpfname);
$attachment->md5 = $md5;
$attachment->mime = $mime;
$attachment->save();
$this->line(sprintf('Fixed attachment #%d', $attachment->id));
// find file:
}
}
}

View File

@@ -124,16 +124,16 @@ class VerifyDatabase extends Command
{
$set = Budget::leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id')
->leftJoin('users', 'budgets.user_id', '=', 'users.id')
->groupBy(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email'])
->groupBy(['budgets.id', 'budgets.name', 'budgets.encrypted', 'budgets.user_id', 'users.email'])
->whereNull('budget_limits.id')
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email']);
->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'budgets.encrypted', 'users.email']);
/** @var stdClass $entry */
/** @var Budget $entry */
foreach ($set as $entry) {
$name = $entry->encrypted ? Crypt::decrypt($entry->name) : $entry->name;
$line = sprintf(
'Notice: User #%d (%s) has budget #%d ("%s") which has no budget limits.',
$entry->user_id, $entry->email, $entry->id, Crypt::decrypt($entry->name)
$entry->user_id, $entry->email, $entry->id, $name
);
$this->line($line);
}

0
app/Console/Kernel.php Executable file → Normal file
View File

View File

@@ -35,4 +35,4 @@ class DeletedUser extends Event
{
$this->email = $email;
}
}
}

View File

@@ -43,4 +43,4 @@ class RequestedNewPassword extends Event
$this->ipAddress = $ipAddress;
}
}
}

0
app/Exceptions/Handler.php Executable file → Normal file
View File

View File

@@ -64,4 +64,4 @@ interface ProcessorInterface
* @return Collection
*/
public function getFiles(): Collection;
}
}

View File

@@ -31,6 +31,8 @@ class ChartJsGenerator implements GeneratorInterface
* 0: [
* 'label' => 'label of set',
* '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.
* 'entries' =>
* [
* 'label-of-entry' => 'value'
@@ -39,6 +41,8 @@ class ChartJsGenerator implements GeneratorInterface
* 1: [
* 'label' => 'label of another set',
* '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.
* 'entries' =>
* [
* 'label-of-entry' => 'value'
@@ -64,11 +68,19 @@ class ChartJsGenerator implements GeneratorInterface
unset($first, $labels);
foreach ($data as $set) {
$chartData['datasets'][] = [
$currentSet = [
'label' => $set['label'],
'type' => $set['type'] ?? 'line',
'data' => array_values($set['entries']),
];
if (isset($set['yAxisID'])) {
$currentSet['yAxisID'] = $set['yAxisID'];
}
if (isset($set['fill'])) {
$currentSet['fill'] = $set['fill'];
}
$chartData['datasets'][] = $currentSet;
}
return $chartData;
@@ -134,4 +146,4 @@ class ChartJsGenerator implements GeneratorInterface
return $chartData;
}
}
}

View File

@@ -70,4 +70,4 @@ interface GeneratorInterface
*/
public function singleSet(string $setLabel, array $data): array;
}
}

View File

@@ -153,4 +153,4 @@ class MonthReportGenerator implements ReportGeneratorInterface
return $this;
}
}
}

View File

@@ -24,4 +24,4 @@ class MultiYearReportGenerator extends MonthReportGenerator
/**
* Doesn't do anything different.
*/
}
}

View File

@@ -25,4 +25,4 @@ class YearReportGenerator extends MonthReportGenerator
/**
* Doesn't do anything different.
*/
}
}

View File

@@ -244,4 +244,4 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
return $result;
}
}
}

View File

@@ -24,4 +24,4 @@ class MultiYearReportGenerator extends MonthReportGenerator
/**
* Doesn't do anything different.
*/
}
}

View File

@@ -25,4 +25,4 @@ class YearReportGenerator extends MonthReportGenerator
/**
* Doesn't do anything different.
*/
}
}

View File

@@ -325,4 +325,4 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
return $result;
}
}
}

View File

@@ -24,4 +24,4 @@ class MultiYearReportGenerator extends MonthReportGenerator
/**
* Doesn't do anything different.
*/
}
}

View File

@@ -25,4 +25,4 @@ class YearReportGenerator extends MonthReportGenerator
/**
* Doesn't do anything different.
*/
}
}

View File

@@ -57,4 +57,4 @@ class ReportGeneratorFactory
}
throw new FireflyException(sprintf('Cannot generate report. There is no "%s"-report for period "%s".', $type, $period));
}
}
}

View File

@@ -64,4 +64,4 @@ interface ReportGeneratorInterface
*/
public function setStartDate(Carbon $date): ReportGeneratorInterface;
}
}

View File

@@ -106,4 +106,4 @@ class MonthReportGenerator implements ReportGeneratorInterface
return $this;
}
}
}

View File

@@ -103,4 +103,4 @@ class MultiYearReportGenerator implements ReportGeneratorInterface
return $this;
}
}
}

View File

@@ -103,4 +103,4 @@ class YearReportGenerator implements ReportGeneratorInterface
return $this;
}
}
}

View File

@@ -88,4 +88,4 @@ class Support
return $result;
}
}
}

View File

@@ -60,6 +60,7 @@ class JournalCollector implements JournalCollectorInterface
'transaction_types.type as transaction_type_type',
'transaction_journals.bill_id',
'bills.name as bill_name',
'bills.name_encrypted as bill_name_encrypted',
'transactions.id as id',
'transactions.amount as transaction_amount',
'transactions.description as transaction_description',
@@ -180,10 +181,12 @@ class JournalCollector implements JournalCollectorInterface
$set->each(
function (Transaction $transaction) {
$transaction->date = new Carbon($transaction->date);
$transaction->description = intval($transaction->encrypted) === 1 ? Crypt::decrypt($transaction->description) : $transaction->description;
$transaction->bill_name = !is_null($transaction->bill_name) ? Crypt::decrypt($transaction->bill_name) : '';
$transaction->description = $transaction->encrypted ? Crypt::decrypt($transaction->description) : $transaction->description;
if (!is_null($transaction->bill_name)) {
$transaction->bill_name = $transaction->bill_name_encrypted ? Crypt::decrypt($transaction->bill_name) : $transaction->bill_name;
}
// optionally decrypted:
try {
$transaction->opposing_account_name = Crypt::decrypt($transaction->opposing_account_name);
} catch (DecryptException $e) {
@@ -726,4 +729,4 @@ class JournalCollector implements JournalCollectorInterface
return $query;
}
}
}

View File

@@ -173,4 +173,4 @@ interface JournalCollectorInterface
* @return JournalCollectorInterface
*/
public function withoutCategory(): JournalCollectorInterface;
}
}

View File

@@ -26,6 +26,7 @@ use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Log;
/**
* Class BalanceReportHelper
@@ -59,19 +60,23 @@ class BalanceReportHelper implements BalanceReportHelperInterface
*/
public function getBalanceReport(Collection $accounts, Carbon $start, Carbon $end): Balance
{
Log::debug('Start of balance report');
$balance = new Balance;
$header = new BalanceHeader;
$limitRepetitions = $this->budgetRepository->getAllBudgetLimitRepetitions($start, $end);
foreach ($accounts as $account) {
Log::debug(sprintf('Add account %s to headers.', $account->name));
$header->addAccount($account);
}
/** @var LimitRepetition $repetition */
foreach ($limitRepetitions as $repetition) {
$budget = $this->budgetRepository->find($repetition->budget_id);
$line = $this->createBalanceLine($budget, $repetition, $accounts);
Log::debug(sprintf('Create balance line for budget #%d ("%s") and repetition #%d', $budget->id, $budget->name, $repetition->id));
$line = $this->createBalanceLine($budget, $repetition, $accounts);
$balance->addBalanceLine($line);
}
Log::debug('Create rest of the things.');
$noBudgetLine = $this->createNoBudgetLine($accounts, $start, $end);
$coveredByTagLine = $this->createTagsBalanceLine($accounts, $start, $end);
$leftUnbalancedLine = $this->createLeftUnbalancedLine($noBudgetLine, $coveredByTagLine);
@@ -81,9 +86,12 @@ class BalanceReportHelper implements BalanceReportHelperInterface
$balance->addBalanceLine($leftUnbalancedLine);
$balance->setBalanceHeader($header);
Log::debug('Clear unused budgets.');
// remove budgets without expenses from balance lines:
$balance = $this->removeUnusedBudgets($balance);
Log::debug('Return report.');
return $balance;
}

View File

@@ -124,17 +124,24 @@ class AccountController extends Controller
*/
public function destroy(ARI $repository, Account $account)
{
$type = $account->accountType->type;
$typeName = config('firefly.shortNamesByFullName.' . $type);
$name = $account->name;
$moveTo = $repository->find(intval(Input::get('move_account_before_delete')));
$type = $account->accountType->type;
$typeName = config('firefly.shortNamesByFullName.' . $type);
$name = $account->name;
$accountId = $account->id;
$moveTo = $repository->find(intval(Input::get('move_account_before_delete')));
$repository->destroy($account, $moveTo);
Session::flash('success', strval(trans('firefly.' . $typeName . '_deleted', ['name' => $name])));
Preferences::mark();
return redirect(session('accounts.delete.url'));
$uri = session('accounts.delete.url');
if (!(strpos($uri, sprintf('accounts/show/%s', $accountId)) === false)) {
// uri would point back to account
$uri = route('accounts.index', [$typeName]);
}
return redirect($uri);
}
/**
@@ -192,8 +199,7 @@ class AccountController extends Controller
*/
public function index(ARI $repository, string $what)
{
$what = $what ?? 'asset';
$what = $what ?? 'asset';
$subTitle = trans('firefly.' . $what . '_accounts');
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
$types = config('firefly.accountTypesByIdentifier.' . $what);
@@ -214,6 +220,7 @@ class AccountController extends Controller
$account->lastActivityDate = $this->isInArray($activities, $account->id);
$account->startBalance = $this->isInArray($startBalances, $account->id);
$account->endBalance = $this->isInArray($endBalances, $account->id);
$account->difference = bcsub($account->endBalance, $account->startBalance);
}
);
@@ -235,12 +242,12 @@ class AccountController extends Controller
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
$subTitle = $account->name;
$range = Preferences::get('viewRange', '1M')->data;
$start = session('start', Navigation::startOfPeriod(new Carbon, $range));
$end = session('end', Navigation::endOfPeriod(new Carbon, $range));
$page = intval(Input::get('page')) === 0 ? 1 : intval(Input::get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$chartUri = route('chart.account.single', [$account->id]);
// grab those journals:
$collector->setAccounts(new Collection([$account]))->setRange($start, $end)->setLimit($pageSize)->setPage($page);
$journals = $collector->getPaginatedJournals();
@@ -379,7 +386,7 @@ class AccountController extends Controller
return $array[$entryId];
}
return '';
return '0';
}
/**

View File

@@ -95,16 +95,12 @@ class AttachmentController extends Controller
* @throws FireflyException
*
*/
public function download(Attachment $attachment)
public function download(AttachmentRepositoryInterface $repository, Attachment $attachment)
{
// create a disk.
$disk = Storage::disk('upload');
$file = $attachment->fileName();
if ($disk->exists($file)) {
if ($repository->exists($attachment)) {
$content = $repository->getContent($attachment);
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));
$content = Crypt::decrypt($disk->get($file));
Log::debug('Send file to user', ['file' => $quoted, 'size' => strlen($content)]);
@@ -118,8 +114,8 @@ class AttachmentController extends Controller
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
->header('Pragma', 'public')
->header('Content-Length', strlen($content));
}
throw new FireflyException('Could not find the indicated attachment. The file is no longer there.');
}

37
app/Http/Controllers/Auth/ForgotPasswordController.php Executable file → Normal file
View File

@@ -13,7 +13,9 @@ declare(strict_types = 1);
namespace FireflyIII\Http\Controllers\Auth;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\User;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request;
/**
* Class ForgotPasswordController
@@ -33,4 +35,39 @@ class ForgotPasswordController extends Controller
parent::__construct();
$this->middleware('guest');
}
/**
* Send a reset link to the given user.
*
* @param Request $request
*
* @return \Illuminate\Http\RedirectResponse
*/
public function sendResetLinkEmail(Request $request)
{
$this->validate($request, ['email' => 'required|email']);
// verify if the user is not a demo user. If so, we give him back an error.
$user = User::where('email', $request->get('email'))->first();
if (!is_null($user) && $user->hasRole('demo')) {
return back()->withErrors(
['email' => trans('firefly.cannot_reset_demo_user')]
);
}
$response = $this->broker()->sendResetLink(
$request->only('email')
);
if ($response === Password::RESET_LINK_SENT) {
return back()->with('status', trans($response));
}
// If an error was returned by the password broker, we will get this message
// translated so we can notify a user of the problem. We'll redirect back
// to where the users came from so they can attempt this process again.
return back()->withErrors(
['email' => trans($response)]
);
}
}

4
app/Http/Controllers/Auth/LoginController.php Executable file → Normal file
View File

@@ -53,9 +53,9 @@ class LoginController extends Controller
/**
* Handle a login request to the application.
*
* @param \Illuminate\Http\Request $request
* @param Request $request
*
* @return \Illuminate\Http\Response
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
*/
public function login(Request $request)
{

View File

@@ -26,8 +26,8 @@ use Illuminate\Support\Facades\Password;
*
* @package FireflyIII\Http\Controllers\Auth
* @method getEmailSubject()
* @method getSendResetLinkEmailSuccessResponse()
* @method getSendResetLinkEmailFailureResponse()
* @method getSendResetLinkEmailSuccessResponse(string $response)
* @method getSendResetLinkEmailFailureResponse(string $response)
*/
class PasswordController extends Controller
{

3
app/Http/Controllers/Auth/RegisterController.php Executable file → Normal file
View File

@@ -22,11 +22,8 @@ use FireflyIII\Http\Controllers\Controller;
use FireflyIII\User;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
use Illuminate\Mail\Message;
use Log;
use Mail;
use Session;
use Swift_TransportException;
use Validator;
/**

0
app/Http/Controllers/Auth/ResetPasswordController.php Executable file → Normal file
View File

View File

@@ -99,13 +99,20 @@ class BillController extends Controller
*/
public function destroy(BillRepositoryInterface $repository, Bill $bill)
{
$name = $bill->name;
$name = $bill->name;
$billId = $bill->id;
$repository->destroy($bill);
Session::flash('success', strval(trans('firefly.deleted_bill', ['name' => $name])));
Preferences::mark();
return redirect(session('bills.delete.url'));
$uri = session('bills.delete.url');
if (!(strpos($uri, sprintf('bills/show/%s', $billId)) === false)) {
// uri would point back to bill
$uri = route('bills.index');
}
return redirect($uri);
}
/**

View File

@@ -15,10 +15,10 @@ namespace FireflyIII\Http\Controllers;
use Amount;
use Carbon\Carbon;
use Config;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Http\Requests\BudgetFormRequest;
use FireflyIII\Http\Requests\BudgetIncomeRequest;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition;
@@ -26,8 +26,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Support\Collection;
use Input;
use Log;
use Navigation;
use Preferences;
use Response;
use Session;
@@ -42,6 +40,9 @@ use View;
class BudgetController extends Controller
{
/** @var BudgetRepositoryInterface */
private $repository;
/**
*
*/
@@ -55,6 +56,7 @@ class BudgetController extends Controller
function ($request, $next) {
View::share('title', trans('firefly.budgets'));
View::share('mainTitleIcon', 'fa-tasks');
$this->repository = app(BudgetRepositoryInterface::class);
return $next($request);
}
@@ -73,21 +75,15 @@ class BudgetController extends Controller
/** @var Carbon $start */
$start = session('start', Carbon::now()->startOfMonth());
/** @var Carbon $end */
$end = session('end', Carbon::now()->endOfMonth());
$viewRange = Preferences::get('viewRange', '1M')->data;
// is custom view range?
if (session('is_custom_range') === true) {
$viewRange = 'custom';
}
$end = session('end', Carbon::now()->endOfMonth());
$viewRange = Preferences::get('viewRange', '1M')->data;
$limitRepetition = $repository->updateLimitAmount($budget, $start, $end, $viewRange, $amount);
if ($amount == 0) {
$limitRepetition = null;
}
Preferences::mark();
return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0]);
return Response::json(['name' => $budget->name, 'repetition' => $limitRepetition ? $limitRepetition->id : 0, 'amount' => $amount]);
}
@@ -134,15 +130,21 @@ class BudgetController extends Controller
public function destroy(Budget $budget, BudgetRepositoryInterface $repository)
{
$name = $budget->name;
$name = $budget->name;
$budgetId = $budget->id;
$repository->destroy($budget);
Session::flash('success', strval(trans('firefly.deleted_budget', ['name' => e($name)])));
Preferences::mark();
$uri = session('budgets.delete.url');
if (!(strpos($uri, sprintf('budgets/show/%s', $budgetId)) === false)) {
// uri would point back to budget
$uri = route('budgets.index');
}
return redirect(session('budgets.delete.url'));
return redirect($uri);
}
/**
@@ -167,82 +169,27 @@ class BudgetController extends Controller
}
/**
* @param BudgetRepositoryInterface $repository
* @param AccountRepositoryInterface $accountRepository
*
* @return View
*
*/
public function index(BudgetRepositoryInterface $repository, AccountRepositoryInterface $accountRepository)
public function index()
{
$repository->cleanupBudgets();
$this->repository->cleanupBudgets();
$budgets = $repository->getActiveBudgets();
$inactive = $repository->getInactiveBudgets();
$spent = '0';
$budgeted = '0';
$range = Preferences::get('viewRange', '1M')->data;
$repeatFreq = Config::get('firefly.range_to_repeat_freq.' . $range);
if (session('is_custom_range') === true) {
$repeatFreq = 'custom';
}
/** @var Carbon $start */
$start = session('start', new Carbon);
/** @var Carbon $end */
$budgets = $this->repository->getActiveBudgets();
$inactive = $this->repository->getInactiveBudgets();
$start = session('start', new Carbon);
$end = session('end', new Carbon);
$key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd');
$budgetIncomeTotal = Preferences::get($key, 1000)->data;
$period = Navigation::periodShow($start, $range);
$periodStart = $start->formatLocalized($this->monthAndDayFormat);
$periodEnd = $end->formatLocalized($this->monthAndDayFormat);
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
$startAsString = $start->format('Y-m-d');
$endAsString = $end->format('Y-m-d');
Log::debug('Now at /budgets');
// loop the budgets:
/** @var Budget $budget */
foreach ($budgets as $budget) {
Log::debug(sprintf('Now at budget #%d ("%s")', $budget->id, $budget->name));
$budget->spent = $repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end);
$allRepetitions = $repository->getAllBudgetLimitRepetitions($start, $end);
$otherRepetitions = new Collection;
/** @var LimitRepetition $repetition */
foreach ($allRepetitions as $repetition) {
if ($repetition->budget_id == $budget->id) {
if ($repetition->budgetLimit->repeat_freq == $repeatFreq
&& $repetition->startdate->format('Y-m-d') == $startAsString
&& $repetition->enddate->format('Y-m-d') == $endAsString
) {
// do something
$budget->currentRep = $repetition;
continue;
}
$otherRepetitions->push($repetition);
}
}
$budget->otherRepetitions = $otherRepetitions;
if (!is_null($budget->currentRep) && !is_null($budget->currentRep->id)) {
$budgeted = bcadd($budgeted, $budget->currentRep->amount);
}
$spent = bcadd($spent, $budget->spent);
}
$defaultCurrency = Amount::getDefaultCurrency();
$budgetInformation = $this->collectBudgetInformation($budgets, $start, $end);
$defaultCurrency = Amount::getDefaultCurrency();
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
$spent = array_sum(array_column($budgetInformation, 'spent'));
$budgeted = array_sum(array_column($budgetInformation, 'budgeted'));
return view(
'budgets.index', compact(
'periodStart', 'periodEnd',
'period', 'range', 'budgetIncomeTotal',
'defaultCurrency', 'inactive', 'budgets',
'spent', 'budgeted'
)
'budgets.index',
compact('available', 'periodStart', 'periodEnd', 'budgetInformation', 'defaultCurrency', 'inactive', 'budgets', 'spent', 'budgeted')
);
}
@@ -274,16 +221,14 @@ class BudgetController extends Controller
/**
* @return \Illuminate\Http\RedirectResponse
*/
public function postUpdateIncome()
public function postUpdateIncome(BudgetIncomeRequest $request)
{
$range = Preferences::get('viewRange', '1M')->data;
/** @var Carbon $date */
$date = session('start', new Carbon);
$start = Navigation::startOfPeriod($date, $range);
$end = Navigation::endOfPeriod($start, $range);
$key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd');
$start = session('start', new Carbon);
$end = session('end', new Carbon);
$defaultCurrency = Amount::getDefaultCurrency();
$amount = $request->get('amount');
Preferences::set($key, intval(Input::get('amount')));
$this->repository->setAvailableBudget($defaultCurrency, $start, $end, $amount);
Preferences::mark();
return redirect(route('budgets.index'));
@@ -424,19 +369,57 @@ class BudgetController extends Controller
*/
public function updateIncome()
{
$range = Preferences::get('viewRange', '1M')->data;
$format = strval(trans('config.month_and_day'));
$start = session('start', new Carbon);
$end = session('end', new Carbon);
$defaultCurrency = Amount::getDefaultCurrency();
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
/** @var Carbon $date */
$date = session('start', new Carbon);
$start = Navigation::startOfPeriod($date, $range);
$end = Navigation::endOfPeriod($start, $range);
$key = 'budgetIncomeTotal' . $start->format('Ymd') . $end->format('Ymd');
$amount = Preferences::get($key, 1000);
$displayStart = $start->formatLocalized($format);
$displayEnd = $end->formatLocalized($format);
return view('budgets.income', compact('amount', 'displayStart', 'displayEnd'));
return view('budgets.income', compact('available', 'start', 'end'));
}
/**
* @param Collection $budgets
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
private function collectBudgetInformation(Collection $budgets, Carbon $start, Carbon $end): array
{
// get account information
$accountRepository = app(AccountRepositoryInterface::class);
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
$return = [];
/** @var Budget $budget */
foreach ($budgets as $budget) {
$budgetId = $budget->id;
$return[$budgetId] = [
'spent' => $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end),
'budgeted' => '0',
'currentRep' => false,
];
$allRepetitions = $this->repository->getAllBudgetLimitRepetitions($start, $end);
$otherRepetitions = new Collection;
// get all the limit repetitions relevant between start and end and examine them:
/** @var LimitRepetition $repetition */
foreach ($allRepetitions as $repetition) {
if ($repetition->budget_id == $budget->id) {
if ($repetition->startdate->isSameDay($start) && $repetition->enddate->isSameDay($end)
) {
$return[$budgetId]['currentRep'] = $repetition;
$return[$budgetId]['budgeted'] = $repetition->amount;
continue;
}
// otherwise it's just one of the many relevant repetitions:
$otherRepetitions->push($repetition);
}
}
$return[$budgetId]['otherRepetitions'] = $otherRepetitions;
}
return $return;
}
}

View File

@@ -98,13 +98,20 @@ class CategoryController extends Controller
public function destroy(CRI $repository, Category $category)
{
$name = $category->name;
$name = $category->name;
$categoryId = $category->id;
$repository->destroy($category);
Session::flash('success', strval(trans('firefly.deleted_category', ['name' => e($name)])));
Preferences::mark();
return redirect(session('categories.delete.url'));
$uri = session('categories.delete.url');
if (!(strpos($uri, sprintf('categories/show/%s', $categoryId)) === false)) {
// uri would point back to category
$uri = route('categories.index');
}
return redirect($uri);
}
/**
@@ -262,7 +269,6 @@ class CategoryController extends Controller
$journals = $collector->getPaginatedJournals();
$journals->setPath('categories/show/' . $category->id . '/' . $date);
return view('categories.show-by-date', compact('category', 'journals', 'hideCategory', 'subTitle', 'carbon'));
}

View File

@@ -204,7 +204,7 @@ class BudgetController extends Controller
}
// for no budget:
$row = $this->spentInPeriodWithout($start, $end);
if (bccomp($row['spent'], '0') !== 0 || bccomp($row['repetition_left'], '0') !== 0) {
if (bccomp($row['repetition_overspent'], '0') !== 0) {
$chartData[0]['entries'][$row['name']] = bcmul($row['spent'], '-1');
$chartData[1]['entries'][$row['name']] = $row['repetition_left'];
$chartData[2]['entries'][$row['name']] = bcmul($row['repetition_overspent'], '-1');
@@ -284,8 +284,8 @@ class BudgetController extends Controller
foreach (array_keys($periods) as $period) {
$label = $periods[$period];
$spent = isset($entries[$budget->id]['entries'][$period]) ? $entries[$budget->id]['entries'][$period] : '0';
$limit = isset($entries[$period]) ? $budgeted[$period] : 0;
$chartData[0]['entries'][$label] = bcmul($spent, '-1');
$limit = isset($budgeted[$period]) ? $budgeted[$period] : 0;
$chartData[0]['entries'][$label] = round(bcmul($spent, '-1'), 2);
$chartData[1]['entries'][$label] = $limit;
}
@@ -386,7 +386,7 @@ class BudgetController extends Controller
}
$amount = $repetition->amount;
$left = bccomp(bcadd($amount, $expenses), '0') < 1 ? '0' : bcadd($amount, $expenses);
$spent = bccomp(bcadd($amount, $expenses), '0') < 1 ? bcmul($amount, '-1') : $expenses;
$spent = $expenses;
$overspent = bccomp(bcadd($amount, $expenses), '0') < 1 ? bcadd($amount, $expenses) : '0';
$return[] = [
'name' => $name,
@@ -454,8 +454,8 @@ class BudgetController extends Controller
$array = [
'name' => strval(trans('firefly.no_budget')),
'repetition_left' => '0',
'repetition_overspent' => '0',
'spent' => $sum,
'repetition_overspent' => $sum,
'spent' => '0',
];
return $array;

View File

@@ -20,16 +20,17 @@ use FireflyIII\Generator\Report\Category\MonthReportGenerator;
use FireflyIII\Helpers\Collector\JournalCollector;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Budget;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Log;
use Navigation;
use Response;
/**
* Separate controller because many helper functions are shared.
*
@@ -83,6 +84,7 @@ class BudgetReportController extends Controller
$cache->addProperty($budgets);
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty($others);
if ($cache->has()) {
return Response::json($cache->get());
}
@@ -139,6 +141,7 @@ class BudgetReportController extends Controller
$cache->addProperty($budgets);
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty($others);
if ($cache->has()) {
return Response::json($cache->get());
}
@@ -195,21 +198,39 @@ class BudgetReportController extends Controller
if ($cache->has()) {
return Response::json($cache->get());
}
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class);
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
$function = Navigation::preferredEndOfPeriod($start, $end);
$chartData = [];
$currentStart = clone $start;
$limits = $repository->getAllBudgetLimitRepetitions($start, $end); // also for ALL budgets.
// prep chart data:
foreach ($budgets as $budget) {
$chartData[$budget->id] = [
'label' => $budget->name,
$chartData[$budget->id] = [
'label' => strval(trans('firefly.spent_in_specific_budget', ['budget' => $budget->name])),
'type' => 'bar',
'yAxisID' => 'y-axis-0',
'entries' => [],
];
$chartData[$budget->id . '-sum'] = [
'label' => strval(trans('firefly.sum_of_expenses_in_budget', ['budget' => $budget->name])),
'type' => 'line',
'fill' => false,
'yAxisID' => 'y-axis-1',
'entries' => [],
];
$chartData[$budget->id . '-left'] = [
'label' => strval(trans('firefly.left_in_budget_limit', ['budget' => $budget->name])),
'type' => 'bar',
'fill' => false,
'yAxisID' => 'y-axis-0',
'entries' => [],
];
}
$sumOfExpenses = [];
$leftOfLimits = [];
while ($currentStart < $end) {
$currentEnd = clone $currentStart;
$currentEnd = $currentEnd->$function();
@@ -218,7 +239,20 @@ class BudgetReportController extends Controller
/** @var Budget $budget */
foreach ($budgets as $budget) {
$chartData[$budget->id]['entries'][$label] = $expenses[$budget->id] ?? '0';
$currentExpenses = $expenses[$budget->id] ?? '0';
$sumOfExpenses[$budget->id] = $sumOfExpenses[$budget->id] ?? '0';
$sumOfExpenses[$budget->id] = bcadd($currentExpenses, $sumOfExpenses[$budget->id]);
$chartData[$budget->id]['entries'][$label] = round(bcmul($currentExpenses, '-1'), 2);
$chartData[$budget->id . '-sum']['entries'][$label] = round(bcmul($sumOfExpenses[$budget->id], '-1'), 2);
$limit = $this->filterLimits($limits, $budget, $currentStart);
if (!is_null($limit->id)) {
$leftOfLimits[$limit->id] = $leftOfLimits[$limit->id] ?? strval($limit->amount);
$leftOfLimits[$limit->id] = bcadd($leftOfLimits[$limit->id], $currentExpenses);
$chartData[$budget->id . '-left']['entries'][$label] = round($leftOfLimits[$limit->id], 2);
}
}
$currentStart = clone $currentEnd;
$currentStart->addDay();
@@ -230,6 +264,44 @@ class BudgetReportController extends Controller
return Response::json($data);
}
/**
* @param $limits
* @param $budget
* @param $currentStart
*
* @return LimitRepetition
*/
private function filterLimits(Collection $limits, Budget $budget, Carbon $date): LimitRepetition
{
Log::debug(sprintf('Start of filterLimits with %d limits.', $limits->count()));
$filtered = $limits->filter(
function (LimitRepetition $limit) use ($budget, $date) {
if ($limit->budget_id !== $budget->id) {
Log::debug(sprintf('LimitRepetition has budget #%d but expecting #%d', $limit->budget_id, $budget->id));
return false;
}
if ($date < $limit->startdate || $date > $limit->enddate) {
Log::debug(
sprintf(
'Date %s is not between %s and %s',
$date->format('Y-m-d'), $limit->startdate->format('Y-m-d'), $limit->enddate->format('Y-m-d')
)
);
return false;
}
return $limit;
}
);
if ($filtered->count() === 1) {
return $filtered->first();
}
return new LimitRepetition;
}
/**
* @param Collection $accounts
@@ -289,4 +361,4 @@ class BudgetReportController extends Controller
return $grouped;
}
}
}

View File

@@ -83,6 +83,7 @@ class CategoryReportController extends Controller
$cache->addProperty($categories);
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty($others);
if ($cache->has()) {
return Response::json($cache->get());
}
@@ -138,6 +139,7 @@ class CategoryReportController extends Controller
$cache->addProperty($accounts);
$cache->addProperty($categories);
$cache->addProperty($start);
$cache->addProperty($others);
$cache->addProperty($end);
if ($cache->has()) {
return Response::json($cache->get());
@@ -194,6 +196,7 @@ class CategoryReportController extends Controller
$cache->addProperty($categories);
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty($others);
if ($cache->has()) {
return Response::json($cache->get());
}
@@ -250,6 +253,7 @@ class CategoryReportController extends Controller
$cache->addProperty($categories);
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty($others);
if ($cache->has()) {
return Response::json($cache->get());
}
@@ -314,14 +318,33 @@ class CategoryReportController extends Controller
$chartData[$category->id . '-in'] = [
'label' => $category->name . ' (' . strtolower(strval(trans('firefly.income'))) . ')',
'type' => 'bar',
'yAxisID' => 'y-axis-0',
'entries' => [],
];
$chartData[$category->id . '-out'] = [
'label' => $category->name . ' (' . strtolower(strval(trans('firefly.expenses'))) . ')',
'type' => 'bar',
'yAxisID' => 'y-axis-0',
'entries' => [],
];
// total in, total out:
$chartData[$category->id . '-total-in'] = [
'label' => $category->name . ' (' . strtolower(strval(trans('firefly.sum_of_income'))) . ')',
'type' => 'line',
'fill' => false,
'yAxisID' => 'y-axis-1',
'entries' => [],
];
$chartData[$category->id . '-total-out'] = [
'label' => $category->name . ' (' . strtolower(strval(trans('firefly.sum_of_expenses'))) . ')',
'type' => 'line',
'fill' => false,
'yAxisID' => 'y-axis-1',
'entries' => [],
];
}
$sumOfIncome = [];
$sumOfExpense = [];
while ($currentStart < $end) {
$currentEnd = clone $currentStart;
@@ -332,17 +355,40 @@ class CategoryReportController extends Controller
/** @var Category $category */
foreach ($categories as $category) {
$labelIn = $category->id . '-in';
$labelOut = $category->id . '-out';
// get sum, and get label:
$chartData[$labelIn]['entries'][$label] = $income[$category->id] ?? '0';
$chartData[$labelOut]['entries'][$label] = $expenses[$category->id] ?? '0';
$labelIn = $category->id . '-in';
$labelOut = $category->id . '-out';
$labelSumIn = $category->id . '-total-in';
$labelSumOut = $category->id . '-total-out';
$currentIncome = $income[$category->id] ?? '0';
$currentExpense = $expenses[$category->id] ?? '0';
// add to sum:
$sumOfIncome[$category->id] = $sumOfIncome[$category->id] ?? '0';
$sumOfExpense[$category->id] = $sumOfExpense[$category->id] ?? '0';
$sumOfIncome[$category->id] = bcadd($sumOfIncome[$category->id], $currentIncome);
$sumOfExpense[$category->id] = bcadd($sumOfExpense[$category->id], $currentExpense);
// add to chart:
$chartData[$labelIn]['entries'][$label] = $currentIncome;
$chartData[$labelOut]['entries'][$label] = $currentExpense;
$chartData[$labelSumIn]['entries'][$label] = $sumOfIncome[$category->id];
$chartData[$labelSumOut]['entries'][$label] = $sumOfExpense[$category->id];
}
$currentStart = clone $currentEnd;
$currentStart->addDay();
}
$data = $this->generator->multiSet($chartData);
// remove all empty entries to prevent cluttering:
$newSet = [];
foreach ($chartData as $key => $entry) {
if (!array_sum($entry['entries']) == 0) {
$newSet[$key] = $chartData[$key];
}
}
if (count($newSet) === 0) {
$newSet = $chartData;
}
$data = $this->generator->multiSet($newSet);
$cache->store($data);
return Response::json($data);
@@ -427,4 +473,4 @@ class CategoryReportController extends Controller
return $grouped;
}
}
}

6
app/Http/Controllers/Controller.php Executable file → Normal file
View File

@@ -23,6 +23,7 @@ use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Session;
use View;
use FireflyConfig;
/**
* Class Controller
@@ -49,7 +50,10 @@ class Controller extends BaseController
View::share('hideCategories', false);
View::share('hideBills', false);
View::share('hideTags', false);
$isDemoSite = FireflyConfig::get('is_demo_site', config('firefly.configuration.is_demo_site'))->data;
View::share('IS_DEMO_SITE', $isDemoSite);
View::share('DEMO_USERNAME', env('DEMO_USERNAME',''));
View::share('DEMO_PASSWORD', env('DEMO_PASSWORD',''));
// translations:

View File

@@ -22,6 +22,7 @@ use FireflyIII\Http\Requests\ExportFormRequest;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\ExportJob;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface;
use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface as EJRI;
use Preferences;
use Response;
@@ -59,21 +60,22 @@ class ExportController extends Controller
* @return \Symfony\Component\HttpFoundation\Response|\Illuminate\Contracts\Routing\ResponseFactory
* @throws FireflyException
*/
public function download(ExportJob $job)
public function download(ExportJobRepositoryInterface $repository, ExportJob $job)
{
$disk = Storage::disk('export');
$file = $job->key . '.zip';
$date = date('Y-m-d \a\t H-i-s');
$name = 'Export job on ' . $date . '.zip';
$quoted = sprintf('"%s"', addcslashes($name, '"\\'));
if (!$disk->exists($file)) {
if (!$repository->exists($job)) {
throw new FireflyException('Against all expectations, zip file "' . $file . '" does not exist.');
}
$content = $repository->getContent($job);
$job->change('export_downloaded');
return response($disk->get($file), 200)
return response($content, 200)
->header('Content-Description', 'File Transfer')
->header('Content-Type', 'application/octet-stream')
->header('Content-Disposition', 'attachment; filename=' . $quoted)
@@ -82,7 +84,7 @@ class ExportController extends Controller
->header('Expires', '0')
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
->header('Pragma', 'public')
->header('Content-Length', $disk->size($file));
->header('Content-Length', strlen($content));
}

View File

@@ -63,6 +63,7 @@ class HomeController extends Controller
// a possible problem with the budgets.
if ($label === strval(trans('firefly.everything')) || $label === strval(trans('firefly.customRange'))) {
$isCustomRange = true;
//Preferences::set('viewRange', 'custom');
Log::debug('Range is now marked as "custom".');
}
@@ -107,7 +108,7 @@ class HomeController extends Controller
$journal->save();
}
}
Session::forget(['start', 'end', 'viewRange', 'range', 'is_custom_range']);
Session::clear();
Artisan::call('cache:clear');

View File

@@ -15,7 +15,7 @@ namespace FireflyIII\Http\Controllers;
use Crypt;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Requests\ImportUploadRequest;
use FireflyIII\Import\ImportProcedure;
use FireflyIII\Import\ImportProcedureInterface;
use FireflyIII\Import\Setup\SetupInterface;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
@@ -315,13 +315,13 @@ class ImportController extends Controller
}
/**
* @param ImportJob $job
* @param ImportProcedureInterface $importProcedure
* @param ImportJob $job
*/
public function start(ImportJob $job)
public function start(ImportProcedureInterface $importProcedure, ImportJob $job)
{
set_time_limit(0);
if ($job->status == 'settings_complete') {
$importProcedure = new ImportProcedure;
$importProcedure->runImport($job);
}
}
@@ -334,7 +334,7 @@ class ImportController extends Controller
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
*/
public function status(ImportJob $job)
{
{ //
Log::debug('Now in status()', ['job' => $job->key]);
if (!$this->jobInCorrectStep($job, 'status')) {
return $this->redirectToCorrectStep($job);

View File

@@ -24,6 +24,7 @@ use Illuminate\Support\Collection;
use Input;
use Log;
use Preferences;
use Response;
use Session;
use Steam;
use URL;
@@ -149,13 +150,18 @@ class PiggyBankController extends Controller
*/
public function destroy(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank)
{
Session::flash('success', strval(trans('firefly.deleted_piggy_bank', ['name' => e($piggyBank->name)])));
Preferences::mark();
$piggyBankId = $piggyBank->id;
$repository->destroy($piggyBank);
return redirect(session('piggy-banks.delete.url'));
$uri = session('piggy-banks.delete.url');
if (!(strpos($uri, sprintf('piggy-banks/show/%s', $piggyBankId)) === false)) {
// uri would point back to piggy bank
$uri = route('piggy-banks.index');
}
return redirect($uri);
}
/**
@@ -243,6 +249,8 @@ class PiggyBankController extends Controller
/**
* @param PiggyBankRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*/
public function order(PiggyBankRepositoryInterface $repository)
{
@@ -257,6 +265,8 @@ class PiggyBankController extends Controller
$repository->setOrder(intval($id), ($order + 1));
}
}
return Response::json(['result' => 'ok']);
}
/**

View File

@@ -133,8 +133,8 @@ class ReportController extends Controller
$budget->name = strval(trans('firefly.leftUnbalanced'));
$journals = $journals->filter(
function (TransactionJournal $journal) {
$tags = $journal->tags()->where('tagMode', 'balancingAct')->count();
function (Transaction $transaction) {
$tags = $transaction->transactionJournal->tags()->where('tagMode', 'balancingAct')->count();
if ($tags === 0) {
return true;
}

View File

@@ -150,7 +150,7 @@ class PreferencesController extends Controller
// custom fiscal year
$customFiscalYear = intval($request->get('customFiscalYear')) === 1;
$fiscalYearStart = date('m-d', strtotime($request->get('fiscalYearStart')));
$fiscalYearStart = date('m-d', strtotime(strval($request->get('fiscalYearStart'))));
Preferences::set('customFiscalYear', $customFiscalYear);
Preferences::set('fiscalYearStart', $fiscalYearStart);
@@ -166,13 +166,17 @@ class PreferencesController extends Controller
Preferences::set('transactionPageSize', 50);
}
// two factor auth
$twoFactorAuthEnabled = intval($request->get('twoFactorAuthEnabled'));
$hasTwoFactorAuthSecret = !is_null(Preferences::get('twoFactorAuthSecret'));
$twoFactorAuthEnabled = false;
$hasTwoFactorAuthSecret = false;
if (!auth()->user()->hasRole('demo')) {
// two factor auth
$twoFactorAuthEnabled = intval($request->get('twoFactorAuthEnabled'));
$hasTwoFactorAuthSecret = !is_null(Preferences::get('twoFactorAuthSecret'));
// If we already have a secret, just set the two factor auth enabled to 1, and let the user continue with the existing secret.
if ($hasTwoFactorAuthSecret) {
Preferences::set('twoFactorAuthEnabled', $twoFactorAuthEnabled);
// If we already have a secret, just set the two factor auth enabled to 1, and let the user continue with the existing secret.
if ($hasTwoFactorAuthSecret) {
Preferences::set('twoFactorAuthEnabled', $twoFactorAuthEnabled);
}
}
// language:

View File

@@ -51,6 +51,12 @@ class ProfileController extends Controller
*/
public function changePassword()
{
if (auth()->user()->hasRole('demo')) {
Session::flash('info', strval(trans('firefly.cannot_change_demo')));
return redirect(route('profile.index'));
}
$title = auth()->user()->email;
$subTitle = strval(trans('firefly.change_your_password'));
$subTitleIcon = 'fa-key';
@@ -63,6 +69,12 @@ class ProfileController extends Controller
*/
public function deleteAccount()
{
if (auth()->user()->hasRole('demo')) {
Session::flash('info', strval(trans('firefly.cannot_delete_demo')));
return redirect(route('profile.index'));
}
$title = auth()->user()->email;
$subTitle = strval(trans('firefly.delete_account'));
$subTitleIcon = 'fa-trash';
@@ -83,12 +95,19 @@ class ProfileController extends Controller
}
/**
* @param ProfileFormRequest $request
* @param ProfileFormRequest $request
* @param UserRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function postChangePassword(ProfileFormRequest $request)
public function postChangePassword(ProfileFormRequest $request, UserRepositoryInterface $repository)
{
if (auth()->user()->hasRole('demo')) {
Session::flash('info', strval(trans('firefly.cannot_change_demo')));
return redirect(route('profile.index'));
}
// old, new1, new2
if (!Hash::check($request->get('current_password'), auth()->user()->password)) {
Session::flash('error', strval(trans('firefly.invalid_current_password')));
@@ -103,9 +122,7 @@ class ProfileController extends Controller
}
// update the user with the new password.
auth()->user()->password = bcrypt($request->get('new_password'));
auth()->user()->save();
$repository->changePassword(auth()->user(), $request->get('new_password'));
Session::flash('success', strval(trans('firefly.password_changed')));
return redirect(route('profile.index'));
@@ -119,6 +136,12 @@ class ProfileController extends Controller
*/
public function postDeleteAccount(UserRepositoryInterface $repository, DeleteAccountFormRequest $request)
{
if (auth()->user()->hasRole('demo')) {
Session::flash('info', strval(trans('firefly.cannot_delete_demo')));
return redirect(route('profile.index'));
}
// old, new1, new2
if (!Hash::check($request->get('password'), auth()->user()->password)) {
Session::flash('error', strval(trans('firefly.invalid_password')));

View File

@@ -57,4 +57,4 @@ class BalanceController extends Controller
return $result;
}
}
}

View File

@@ -120,4 +120,4 @@ class BudgetController extends Controller
return $data;
}
}
}

View File

@@ -15,7 +15,6 @@ namespace FireflyIII\Http\Controllers\Report;
use Carbon\Carbon;
use FireflyIII\Helpers\Report\ReportHelperInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
@@ -170,4 +169,4 @@ class CategoryController extends Controller
}
}
}

View File

@@ -241,4 +241,4 @@ class OperationsController extends Controller
return $expenses;
}
}
}

View File

@@ -22,6 +22,7 @@ use FireflyIII\Models\RuleTrigger;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Rules\TransactionMatcher;
use Illuminate\Http\Request;
use Input;
use Preferences;
use Response;
@@ -86,10 +87,10 @@ class RuleController extends Controller
$subTitle = trans('firefly.make_new_rule', ['title' => $ruleGroup->title]);
// put previous url in session if not redirect from store (not "create another").
if (session('rules.rule.create.fromStore') !== true) {
Session::put('rules.rule.create.url', URL::previous());
if (session('rules.create.fromStore') !== true) {
Session::put('rules.create.url', URL::previous());
}
Session::forget('rules.rule.create.fromStore');
Session::forget('rules.create.fromStore');
Session::flash('gaEventCategory', 'rules');
Session::flash('gaEventAction', 'create-rule');
@@ -110,7 +111,7 @@ class RuleController extends Controller
$subTitle = trans('firefly.delete_rule', ['title' => $rule->title]);
// put previous url in session
Session::put('rules.rule.delete.url', URL::previous());
Session::put('rules.delete.url', URL::previous());
Session::flash('gaEventCategory', 'rules');
Session::flash('gaEventAction', 'delete-rule');
@@ -135,7 +136,7 @@ class RuleController extends Controller
Preferences::mark();
return redirect(session('rules.rule.delete.url'));
return redirect(session('rules.delete.url'));
}
/**
@@ -178,10 +179,10 @@ class RuleController extends Controller
$subTitle = trans('firefly.edit_rule', ['title' => $rule->title]);
// put previous url in session if not redirect from store (not "return_to_edit").
if (session('rules.rule.edit.fromUpdate') !== true) {
Session::put('rules.rule.edit.url', URL::previous());
if (session('rules.edit.fromUpdate') !== true) {
Session::put('rules.edit.url', URL::previous());
}
Session::forget('rules.rule.edit.fromUpdate');
Session::forget('rules.edit.fromUpdate');
Session::flash('gaEventCategory', 'rules');
Session::flash('gaEventAction', 'edit-rule');
@@ -203,14 +204,15 @@ class RuleController extends Controller
}
/**
* @param Request $request
* @param RuleRepositoryInterface $repository
* @param Rule $rule
*
* @return \Illuminate\Http\JsonResponse
*/
public function reorderRuleActions(RuleRepositoryInterface $repository, Rule $rule)
public function reorderRuleActions(Request $request, RuleRepositoryInterface $repository, Rule $rule)
{
$ids = Input::get('actions');
$ids = $request->get('actions');
if (is_array($ids)) {
$repository->reorderRuleActions($rule, $ids);
}
@@ -220,14 +222,15 @@ class RuleController extends Controller
}
/**
* @param Request $request
* @param RuleRepositoryInterface $repository
* @param Rule $rule
*
* @return \Illuminate\Http\JsonResponse
*/
public function reorderRuleTriggers(RuleRepositoryInterface $repository, Rule $rule)
public function reorderRuleTriggers(Request $request, RuleRepositoryInterface $repository, Rule $rule)
{
$ids = Input::get('triggers');
$ids = $request->get('triggers');
if (is_array($ids)) {
$repository->reorderRuleTriggers($rule, $ids);
}
@@ -254,13 +257,13 @@ class RuleController extends Controller
if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('rules.rule.create.fromStore', true);
Session::put('rules.create.fromStore', true);
return redirect(route('rules.rule.create', [$ruleGroup]))->withInput();
return redirect(route('rules.create', [$ruleGroup]))->withInput();
}
// redirect to previous URL.
return redirect(session('rules.rule.create.url'));
return redirect(session('rules.create.url'));
}
@@ -341,13 +344,13 @@ class RuleController extends Controller
if (intval(Input::get('return_to_edit')) === 1) {
// set value so edit routine will not overwrite URL:
Session::put('rules.rule.edit.fromUpdate', true);
Session::put('rules.edit.fromUpdate', true);
return redirect(route('rules.rule.edit', [$rule->id]))->withInput(['return_to_edit' => 1]);
return redirect(route('rules.edit', [$rule->id]))->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.
return redirect(session('rules.rule.edit.url'));
return redirect(session('rules.edit.url'));
}
private function createDefaultRule()

View File

@@ -62,10 +62,10 @@ class RuleGroupController extends Controller
$subTitle = trans('firefly.make_new_rule_group');
// put previous url in session if not redirect from store (not "create another").
if (session('rules.rule-group.create.fromStore') !== true) {
Session::put('rules.rule-group.create.url', URL::previous());
if (session('rule-groups.create.fromStore') !== true) {
Session::put('rule-groups.create.url', URL::previous());
}
Session::forget('rules.rule-group.create.fromStore');
Session::forget('rule-groups.create.fromStore');
Session::flash('gaEventCategory', 'rules');
Session::flash('gaEventAction', 'create-rule-group');
@@ -86,7 +86,7 @@ class RuleGroupController extends Controller
unset($ruleGroupList[$ruleGroup->id]);
// put previous url in session
Session::put('rules.rule-group.delete.url', URL::previous());
Session::put('rule-groups.delete.url', URL::previous());
Session::flash('gaEventCategory', 'rules');
Session::flash('gaEventAction', 'delete-rule-group');
@@ -113,7 +113,7 @@ class RuleGroupController extends Controller
Preferences::mark();
return redirect(session('rules.rule-group.delete.url'));
return redirect(session('rule-groups.delete.url'));
}
/**
@@ -140,10 +140,10 @@ class RuleGroupController extends Controller
$subTitle = trans('firefly.edit_rule_group', ['title' => $ruleGroup->title]);
// put previous url in session if not redirect from store (not "return_to_edit").
if (session('rules.rule-group.edit.fromUpdate') !== true) {
Session::put('rules.rule-group.edit.url', URL::previous());
if (session('rule-groups.edit.fromUpdate') !== true) {
Session::put('rule-groups.edit.url', URL::previous());
}
Session::forget('rules.rule-group.edit.fromUpdate');
Session::forget('rule-groups.edit.fromUpdate');
Session::flash('gaEventCategory', 'rules');
Session::flash('gaEventAction', 'edit-rule-group');
@@ -220,13 +220,13 @@ class RuleGroupController extends Controller
if (intval(Input::get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
Session::put('rules.rule-group.create.fromStore', true);
Session::put('rule-groups.create.fromStore', true);
return redirect(route('rules.rule-group.create'))->withInput();
return redirect(route('rule-groups.create'))->withInput();
}
// redirect to previous URL.
return redirect(session('rules.rule-group.create.url'));
return redirect(session('rule-groups.create.url'));
}
/**
@@ -265,13 +265,13 @@ class RuleGroupController extends Controller
if (intval(Input::get('return_to_edit')) === 1) {
// set value so edit routine will not overwrite URL:
Session::put('rules.rule-group.edit.fromUpdate', true);
Session::put('rule-groups.edit.fromUpdate', true);
return redirect(route('rules.rule-group.edit', [$ruleGroup->id]))->withInput(['return_to_edit' => 1]);
return redirect(route('rule-groups.edit', [$ruleGroup->id]))->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.
return redirect(session('rules.rule-group.edit.url'));
return redirect(session('rule-groups.edit.url'));
}
}

View File

@@ -244,4 +244,4 @@ class ConvertController extends Controller
}
}
}

View File

@@ -153,16 +153,21 @@ class SingleController extends Controller
if ($this->isOpeningBalance($transactionJournal)) {
return $this->redirectToAccount($transactionJournal);
}
$type = TransactionJournal::transactionTypeStr($transactionJournal);
$journalId = $transactionJournal->id;
$type = TransactionJournal::transactionTypeStr($transactionJournal);
Session::flash('success', strval(trans('firefly.deleted_' . strtolower($type), ['description' => e($transactionJournal->description)])));
$repository->delete($transactionJournal);
Preferences::mark();
// redirect to previous URL:
return redirect(session('transactions.delete.url'));
$uri = session('transactions.delete.url');
if (!(strpos($uri, sprintf('transactions/show/%s', $journalId)) === false)) {
// uri would point back to transaction
$uri = route('transactions.index', [strtolower($type)]);
}
return redirect($uri);
}
/**

0
app/Http/Kernel.php Executable file → Normal file
View File

0
app/Http/Middleware/EncryptCookies.php Executable file → Normal file
View File

0
app/Http/Middleware/RedirectIfAuthenticated.php Executable file → Normal file
View File

0
app/Http/Middleware/VerifyCsrfToken.php Executable file → Normal file
View File

View File

@@ -0,0 +1,42 @@
<?php
/**
* BudgetIncomeRequest.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Http\Requests;
/**
* Class BudgetIncomeRequest
*
*
* @package FireflyIII\Http\Requests
*/
class BudgetIncomeRequest extends Request
{
/**
* @return bool
*/
public function authorize()
{
// Only allow logged in users
return auth()->check();
}
/**
* @return array
*/
public function rules()
{
return [
'amount' => 'numeric|required|min:0',
];
}
}

View File

@@ -42,8 +42,8 @@ class PiggyBankFormRequest extends Request
'startdate' => new Carbon,
'account_id' => intval($this->get('account_id')),
'targetamount' => round($this->get('targetamount'), 2),
'targetdate' => strlen($this->get('targetdate')) > 0 ? new Carbon($this->get('targetdate')) : null,
'note' => trim($this->get('note')),
'targetdate' => strlen(strval($this->get('targetdate'))) > 0 ? new Carbon($this->get('targetdate')) : null,
'note' => trim(strval($this->get('note'))),
];
}
@@ -64,7 +64,7 @@ class PiggyBankFormRequest extends Request
'name' => $nameRule,
'account_id' => 'required|belongsToUser:accounts',
'targetamount' => 'required|min:0.01',
'amount_currency_id_targetamount' => 'exists:transaction_currencies,id',
'amount_currency_id_targetamount' => 'required|exists:transaction_currencies,id',
'startdate' => 'date',
'targetdate' => $targetDateRule,
'order' => 'integer|min:1',

View File

@@ -10,13 +10,6 @@
*/
declare(strict_types = 1);
/**
* RuleGroupFormRequest.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Http\Requests;

View File

@@ -413,7 +413,22 @@ Breadcrumbs::register(
'piggy-banks.show', function (BreadCrumbGenerator $breadcrumbs, PiggyBank $piggyBank) {
$breadcrumbs->parent('piggy-banks.index');
$breadcrumbs->push(e($piggyBank->name), route('piggy-banks.show', [$piggyBank->id]));
}
);
Breadcrumbs::register(
'piggy-banks.add-money-mobile', function (BreadCrumbGenerator $breadcrumbs, PiggyBank $piggyBank) {
$breadcrumbs->parent('piggy-banks.show', $piggyBank);
$breadcrumbs->push(trans('firefly.add_money_to_piggy', ['name' => $piggyBank->name]), route('piggy-banks.add-money-mobile', [$piggyBank->id]));
}
);
Breadcrumbs::register(
'piggy-banks.remove-money-mobile', function (BreadCrumbGenerator $breadcrumbs, PiggyBank $piggyBank) {
$breadcrumbs->parent('piggy-banks.show', $piggyBank);
$breadcrumbs->push(
trans('firefly.remove_money_from_piggy_title', ['name' => $piggyBank->name]), route('piggy-banks.remove-money-mobile', [$piggyBank->id])
);
}
);
@@ -500,16 +515,63 @@ Breadcrumbs::register(
);
Breadcrumbs::register(
'reports.report', function (BreadCrumbGenerator $breadcrumbs, Carbon $start, Carbon $end, $reportType, $accountIds) {
'reports.report.audit', function (BreadCrumbGenerator $breadcrumbs, string $accountIds, Carbon $start, Carbon $end) {
$breadcrumbs->parent('reports.index');
$monthFormat = (string)trans('config.month_and_day');
$title = (string)trans(
'firefly.report_' . $reportType,
['start' => $start->formatLocalized($monthFormat), 'end' => $end->formatLocalized($monthFormat)]
);
$startString = $start->formatLocalized($monthFormat);
$endString = $end->formatLocalized($monthFormat);
$title = (string)trans('firefly.report_audit', ['start' => $startString, 'end' => $endString]);
$breadcrumbs->push($title, route('reports.report', [$reportType, $start->format('Ymd'), $end->format('Ymd'), $accountIds]));
$breadcrumbs->push($title, route('reports.report.audit', [$accountIds, $start->format('Ymd'), $end->format('Ymd')]));
}
);
Breadcrumbs::register(
'reports.report.budget', function (BreadCrumbGenerator $breadcrumbs, string $accountIds, string $budgetIds, Carbon $start, Carbon $end) {
$breadcrumbs->parent('reports.index');
$monthFormat = (string)trans('config.month_and_day');
$startString = $start->formatLocalized($monthFormat);
$endString = $end->formatLocalized($monthFormat);
$title = (string)trans('firefly.report_budget', ['start' => $startString, 'end' => $endString]);
$breadcrumbs->push($title, route('reports.report.budget', [$accountIds, $budgetIds, $start->format('Ymd'), $end->format('Ymd')]));
}
);
Breadcrumbs::register(
'reports.report.category', function (BreadCrumbGenerator $breadcrumbs, string $accountIds, string $categoryIds, Carbon $start, Carbon $end) {
$breadcrumbs->parent('reports.index');
$monthFormat = (string)trans('config.month_and_day');
$startString = $start->formatLocalized($monthFormat);
$endString = $end->formatLocalized($monthFormat);
$title = (string)trans('firefly.report_category', ['start' => $startString, 'end' => $endString]);
$breadcrumbs->push($title, route('reports.report.category', [$accountIds, $categoryIds, $start->format('Ymd'), $end->format('Ymd')]));
}
);
Breadcrumbs::register(
'reports.report.default', function (BreadCrumbGenerator $breadcrumbs, string $accountIds, Carbon $start, Carbon $end) {
$breadcrumbs->parent('reports.index');
$monthFormat = (string)trans('config.month_and_day');
$startString = $start->formatLocalized($monthFormat);
$endString = $end->formatLocalized($monthFormat);
$title = (string)trans('firefly.report_default', ['start' => $startString, 'end' => $endString]);
$breadcrumbs->push($title, route('reports.report.default', [$accountIds, $start->format('Ymd'), $end->format('Ymd')]));
}
);
/**
* New user Controller
*/
Breadcrumbs::register(
'new-user.index', function (BreadCrumbGenerator $breadcrumbs) {
$breadcrumbs->parent('home');
$breadcrumbs->push(trans('firefly.getting_started'), route('new-user.index'));
}
);
@@ -524,47 +586,54 @@ Breadcrumbs::register(
);
Breadcrumbs::register(
'rules.rule.create', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
'rules.create', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
$breadcrumbs->parent('rules.index');
$breadcrumbs->push(trans('firefly.make_new_rule', ['title' => $ruleGroup->title]), route('rules.rule.create', [$ruleGroup]));
$breadcrumbs->push(trans('firefly.make_new_rule', ['title' => $ruleGroup->title]), route('rules.create', [$ruleGroup]));
}
);
Breadcrumbs::register(
'rules.rule.edit', function (BreadCrumbGenerator $breadcrumbs, Rule $rule) {
'rules.edit', function (BreadCrumbGenerator $breadcrumbs, Rule $rule) {
$breadcrumbs->parent('rules.index');
$breadcrumbs->push(trans('firefly.edit_rule', ['title' => $rule->title]), route('rules.rule.edit', [$rule]));
$breadcrumbs->push(trans('firefly.edit_rule', ['title' => $rule->title]), route('rules.edit', [$rule]));
}
);
Breadcrumbs::register(
'rules.rule.delete', function (BreadCrumbGenerator $breadcrumbs, Rule $rule) {
'rules.delete', function (BreadCrumbGenerator $breadcrumbs, Rule $rule) {
$breadcrumbs->parent('rules.index');
$breadcrumbs->push(trans('firefly.delete_rule', ['title' => $rule->title]), route('rules.rule.delete', [$rule]));
$breadcrumbs->push(trans('firefly.delete_rule', ['title' => $rule->title]), route('rules.delete', [$rule]));
}
);
Breadcrumbs::register(
'rules.rule-group.create', function (BreadCrumbGenerator $breadcrumbs) {
'rule-groups.create', function (BreadCrumbGenerator $breadcrumbs) {
$breadcrumbs->parent('rules.index');
$breadcrumbs->push(trans('firefly.make_new_rule_group'), route('rules.rule-group.create'));
$breadcrumbs->push(trans('firefly.make_new_rule_group'), route('rule-groups.create'));
}
);
Breadcrumbs::register(
'rules.rule-group.edit', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
'rule-groups.edit', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
$breadcrumbs->parent('rules.index');
$breadcrumbs->push(trans('firefly.edit_rule_group', ['title' => $ruleGroup->title]), route('rules.rule-group.edit', [$ruleGroup]));
$breadcrumbs->push(trans('firefly.edit_rule_group', ['title' => $ruleGroup->title]), route('rule-groups.edit', [$ruleGroup]));
}
);
Breadcrumbs::register(
'rules.rule-group.delete', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
'rule-groups.delete', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
$breadcrumbs->parent('rules.index');
$breadcrumbs->push(trans('firefly.delete_rule_group', ['title' => $ruleGroup->title]), route('rules.rule-group.delete', [$ruleGroup]));
$breadcrumbs->push(trans('firefly.delete_rule_group', ['title' => $ruleGroup->title]), route('rule-groups.delete', [$ruleGroup]));
}
);
Breadcrumbs::register(
'rules.rule-group.select_transactions', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
'rule-groups.select-transactions', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
$breadcrumbs->parent('rules.index');
$breadcrumbs->push(trans('firefly.rule_group_select_transactions', ['title' => $ruleGroup->title]), route('rule-groups.select-transactions', [$ruleGroup]));
}
);
Breadcrumbs::register(
'rule-groups.select_transactions', function (BreadCrumbGenerator $breadcrumbs, RuleGroup $ruleGroup) {
$breadcrumbs->parent('rules.index');
$breadcrumbs->push(
trans('firefly.execute_group_on_existing_transactions', ['title' => $ruleGroup->title]), route('rules.rule-group.select_transactions', [$ruleGroup])
trans('firefly.execute_group_on_existing_transactions', ['title' => $ruleGroup->title]), route('rule-groups.select_transactions', [$ruleGroup])
);
}
);

View File

@@ -82,4 +82,4 @@ class TagSplit
return $set;
}
}
}

View File

@@ -96,6 +96,7 @@ class ImportEntry
case 'account-id':
case 'account-iban':
case 'account-name':
case 'account-number':
$this->setObject('asset-account', $convertedValue, $certainty);
break;
case 'opposing-number':

View File

@@ -23,7 +23,7 @@ use Illuminate\Support\Collection;
*
* @package FireflyIII\Import
*/
class ImportProcedure
class ImportProcedure implements ImportProcedureInterface
{
/**

View File

@@ -0,0 +1,33 @@
<?php
/**
* ImportProcedureInterface.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Import;
use FireflyIII\Models\ImportJob;
use Illuminate\Support\Collection;
/**
* Interface ImportProcedureInterface
*
* @package FireflyIII\Import
*/
interface ImportProcedureInterface
{
/**
* @param ImportJob $job
*
* @return Collection
*/
public function runImport(ImportJob $job): Collection;
}

View File

@@ -376,14 +376,14 @@ class ImportStorage
$sourceData = [
'account_id' => $accounts['source']->id,
'transaction_journal_id' => $journal->id,
'description' => $journal->description,
'description' => null,
'amount' => bcmul($amount, '-1'),
];
$destinationData = [
'account_id' => $accounts['destination']->id,
'transaction_journal_id' => $journal->id,
'description' => $journal->description,
'description' => null,
'amount' => $amount,
];

View File

@@ -81,7 +81,7 @@ class MailError extends Job implements ShouldQueue
['emails.error-html', 'emails.error-text'], $args,
function (Message $message) use ($email) {
if ($email != 'mail@example.com') {
$message->to($email, $email)->subject('Caught an error in Firely III.');
$message->to($email, $email)->subject('Caught an error in Firely III');
}
}
);

View File

@@ -36,12 +36,25 @@ class Account extends Model
{
use SoftDeletes, ValidatingTrait;
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'active' => 'boolean',
'encrypted' => 'boolean',
];
/** @var array */
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/** @var array */
protected $fillable = ['user_id', 'account_type_id', 'name', 'active', 'virtual_balance', 'iban'];
/** @var array */
protected $hidden = ['virtual_balance_encrypted', 'encrypted'];
protected $hidden = ['encrypted'];
protected $rules
= [
'user_id' => 'required|exists:users,id',
@@ -184,7 +197,7 @@ class Account extends Model
public function getNameAttribute($value): string
{
if (intval($this->encrypted) == 1) {
if ($this->encrypted) {
return Crypt::decrypt($value);
}

View File

@@ -24,7 +24,18 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
class AccountMeta extends Model
{
protected $dates = ['created_at', 'updated_at'];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
];
/** @var array */
protected $dates = ['created_at', 'updated_at'];
protected $fillable = ['account_id', 'name', 'data'];
protected $table = 'account_meta';

View File

@@ -33,6 +33,18 @@ class AccountType extends Model
const IMPORT = 'Import account';
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
];
/** @var array */
protected $dates = ['created_at', 'updated_at'];
//

View File

@@ -29,6 +29,21 @@ class Attachment extends Model
{
use SoftDeletes;
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'uploaded' => 'boolean',
];
/** @var array */
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/** @var array */
protected $fillable = ['attachable_id', 'attachable_type', 'user_id', 'md5', 'filename', 'mime', 'title', 'notes', 'description', 'size', 'uploaded'];
/**

View File

@@ -0,0 +1,63 @@
<?php
/**
* AvailableBudget.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class AvailableBudget
*
* @package FireflyIII\Models
*/
class AvailableBudget extends Model
{
use SoftDeletes;
/** @var array */
protected $fillable = ['user_id', 'transaction_currency_id', 'amount', 'start_date', 'end_date'];
/** @var array */
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'start_date' => 'date',
'end_date' => 'date',
];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function transactionCurrency()
{
return $this->belongsTo('FireflyIII\Models\TransactionCurrency');
}
/**
* @return BelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo('FireflyIII\User');
}
}

View File

@@ -29,8 +29,26 @@ class Bill extends Model
{
use ValidatingTrait;
/** @var array */
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
protected $dates = ['created_at', 'updated_at', 'date'];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'date' => 'date',
'skip' => 'int',
'automatch' => 'boolean',
'active' => 'boolean',
'name_encrypted' => 'boolean',
'match_encrypted' => 'boolean',
];
protected $fillable
= ['name', 'match', 'amount_min', 'match_encrypted', 'name_encrypted', 'user_id', 'amount_max', 'date', 'repeat_freq', 'skip',
'automatch', 'active',];

View File

@@ -30,7 +30,23 @@ class Budget extends Model
use SoftDeletes, ValidatingTrait;
protected $dates = ['created_at', 'updated_at', 'deleted_at', 'startdate', 'enddate'];
/** @var array */
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'active' => 'boolean',
'encrypted' => 'boolean',
];
protected $fillable = ['user_id', 'name', 'active'];
protected $hidden = ['encrypted'];
protected $rules = ['name' => 'required|between:1,200',];
@@ -95,7 +111,7 @@ class Budget extends Model
public function getNameAttribute($value)
{
if (intval($this->encrypted) == 1) {
if ($this->encrypted) {
return Crypt::decrypt($value);
}
@@ -115,8 +131,8 @@ class Budget extends Model
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = Crypt::encrypt($value);
$this->attributes['encrypted'] = true;
$this->attributes['name'] = $value;
$this->attributes['encrypted'] = false;
}
/**

View File

@@ -23,7 +23,20 @@ use Illuminate\Database\Eloquent\Model;
class BudgetLimit extends Model
{
protected $dates = ['created_at', 'updated_at', 'startdate'];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'startdate' => 'date',
'repeats' => 'boolean',
];
/** @var array */
protected $dates = ['created_at', 'updated_at'];
protected $hidden = ['amount_encrypted'];
/**

View File

@@ -29,10 +29,26 @@ class Category extends Model
{
use SoftDeletes, ValidatingTrait;
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'encrypted' => 'boolean',
];
/** @var array */
protected $fillable = ['user_id', 'name'];
/** @var array */
protected $hidden = ['encrypted'];
/** @var array */
protected $rules = ['name' => 'required|between:1,200',];
/** @var array */
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* @param array $fields
@@ -86,7 +102,7 @@ class Category extends Model
public function getNameAttribute($value)
{
if (intval($this->encrypted) == 1) {
if ($this->encrypted) {
return Crypt::decrypt($value);
}
@@ -99,8 +115,8 @@ class Category extends Model
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = Crypt::encrypt($value);
$this->attributes['encrypted'] = true;
$this->attributes['name'] = $value;
$this->attributes['encrypted'] = false;
}
/**

View File

@@ -25,6 +25,17 @@ class Configuration extends Model
{
use SoftDeletes;
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
];
/** @var array */
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
protected $table = 'configuration';

View File

@@ -23,6 +23,15 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
*/
class ExportJob extends Model
{
/** @var array */
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
];
/** @var array */
protected $dates = ['created_at', 'updated_at'];
/**
* @param $value
*

View File

@@ -27,6 +27,19 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class ImportJob extends Model
{
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
];
/** @var array */
protected $dates = ['created_at', 'updated_at'];
protected $validStatus
= [
'import_status_never_started', // initial state

View File

@@ -26,6 +26,18 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class LimitRepetition extends Model
{
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'startdate' => 'date',
'enddate' => 'date',
];
protected $dates = ['created_at', 'updated_at', 'startdate', 'enddate'];
protected $hidden = ['amount_encrypted'];
@@ -38,10 +50,10 @@ class LimitRepetition extends Model
{
if (auth()->check()) {
$object = self::where('limit_repetitions.id', $value)
->leftJoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->where('budgets.user_id', auth()->user()->id)
->first(['limit_repetitions.*']);
->leftJoin('budget_limits', 'budget_limits.id', '=', 'limit_repetitions.budget_limit_id')
->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id')
->where('budgets.user_id', auth()->user()->id)
->first(['limit_repetitions.*']);
if ($object) {
return $object;
}

View File

@@ -23,10 +23,20 @@ use League\CommonMark\CommonMarkConverter;
*/
class Note extends Model
{
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
];
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
protected $fillable = ['title', 'text'];
/**
* @return string
*/

View File

@@ -29,10 +29,25 @@ class PiggyBank extends Model
{
use SoftDeletes;
protected $dates = ['created_at', 'updated_at', 'deleted_at', 'startdate', 'targetdate'];
protected $fillable
= ['name', 'account_id', 'order', 'targetamount', 'startdate', 'targetdate'];
protected $hidden = ['targetamount_encrypted', 'encrypted'];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'startdate' => 'date',
'targetdate' => 'date',
'order' => 'int',
'active' => 'boolean',
'encrypted' => 'boolean',
];
protected $dates = ['created_at', 'updated_at', 'deleted_at', 'startdate', 'targetdate'];
protected $fillable = ['name', 'account_id', 'order', 'targetamount', 'startdate', 'targetdate'];
protected $hidden = ['targetamount_encrypted', 'encrypted'];
/**
* @param PiggyBank $value
@@ -86,7 +101,7 @@ class PiggyBank extends Model
public function getNameAttribute($value)
{
if (intval($this->encrypted) == 1) {
if ($this->encrypted) {
return Crypt::decrypt($value);
}
@@ -144,8 +159,8 @@ class PiggyBank extends Model
*/
public function setNameAttribute($value)
{
$this->attributes['name'] = Crypt::encrypt($value);
$this->attributes['encrypted'] = true;
$this->attributes['name'] = $value;
$this->attributes['encrypted'] = false;
}
/**

View File

@@ -23,6 +23,17 @@ use Illuminate\Database\Eloquent\Model;
class PiggyBankEvent extends Model
{
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'date' => 'date',
];
protected $dates = ['created_at', 'updated_at', 'date'];
protected $fillable = ['piggy_bank_id', 'transaction_journal_id', 'date', 'amount'];
protected $hidden = ['amount_encrypted'];

View File

@@ -25,9 +25,21 @@ use Illuminate\Database\Eloquent\Model;
class PiggyBankRepetition extends Model
{
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'startdate' => 'date',
'targetdate' => 'date',
];
protected $dates = ['created_at', 'updated_at', 'startdate', 'targetdate'];
protected $fillable = ['piggy_bank_id', 'startdate', 'targetdate', 'currentamount'];
protected $hidden = ['currentamount_encrypted'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo

View File

@@ -27,6 +27,16 @@ use Log;
class Preference extends Model
{
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
];
protected $dates = ['created_at', 'updated_at'];
protected $fillable = ['user_id', 'data', 'name', 'data'];

View File

@@ -23,6 +23,17 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
*/
class Role extends Model
{
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
];
protected $dates = ['created_at', 'updated_at'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany

View File

@@ -26,6 +26,23 @@ class Rule extends Model
{
use SoftDeletes;
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'active' => 'boolean',
'order' => 'int',
'stop_processing' => 'boolean',
];
/** @var array */
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
/**
* @param Rule $value
*

View File

@@ -10,13 +10,6 @@
*/
declare(strict_types = 1);
/**
* RuleAction.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Models;
@@ -29,6 +22,22 @@ use Illuminate\Database\Eloquent\Model;
*/
class RuleAction extends Model
{
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'active' => 'boolean',
'order' => 'int',
'stop_processing' => 'boolean',
];
/** @var array */
protected $dates = ['created_at', 'updated_at'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/

View File

@@ -25,6 +25,22 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class RuleGroup extends Model
{
use SoftDeletes;
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'active' => 'boolean',
'order' => 'int',
];
/** @var array */
protected $dates = ['created_at', 'updated_at', 'deleted_at'];
protected $fillable = ['user_id', 'order', 'title', 'description', 'active'];

View File

@@ -22,6 +22,22 @@ use Illuminate\Database\Eloquent\Model;
*/
class RuleTrigger extends Model
{
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'active' => 'boolean',
'order' => 'int',
'stop_processing' => 'boolean',
];
/** @var array */
protected $dates = ['created_at', 'updated_at'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/

View File

@@ -15,6 +15,7 @@ namespace FireflyIII\Models;
use Crypt;
use FireflyIII\Support\Models\TagSupport;
use Illuminate\Database\Eloquent\SoftDeletes;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Watson\Validating\ValidatingTrait;
@@ -25,11 +26,25 @@ use Watson\Validating\ValidatingTrait;
*/
class Tag extends TagSupport
{
protected $dates = ['created_at', 'updated_at', 'date'];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'created_at' => 'date',
'updated_at' => 'date',
'deleted_at' => 'date',
'date' => 'date',
'zoomLevel' => 'int',
];
protected $dates = ['created_at', 'updated_at', 'date', 'deleted_at'];
protected $fillable = ['user_id', 'tag', 'date', 'description', 'longitude', 'latitude', 'zoomLevel', 'tagMode'];
protected $rules = ['tag' => 'required|between:1,200',];
use ValidatingTrait;
use ValidatingTrait, SoftDeletes;
/**
* @param array $fields

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