mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Merge branch 'release/4.6.12'
This commit is contained in:
commit
59d732cba7
@ -3,7 +3,7 @@ APP_DEBUG=false
|
||||
APP_NAME=FireflyIII
|
||||
APP_KEY=SomeRandomStringOf32CharsExactly
|
||||
APP_LOG=daily
|
||||
APP_LOG_LEVEL=warning
|
||||
APP_LOG_LEVEL=notice
|
||||
APP_URL=http://localhost
|
||||
TRUSTED_PROXIES=
|
||||
|
||||
|
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
@ -4,7 +4,7 @@
|
||||
|
||||
## Feature requests
|
||||
|
||||
I am always interested in expanding Firefly III's many features. If you are requesting a new feature, please check out the list of [often requested features](https://firefly-iii.github.io/requested-features/).
|
||||
I am always interested in expanding Firefly III's many features. If you are requesting a new feature, please check out the list of [often requested features](https://firefly-iii.org/requested-features/).
|
||||
|
||||
## Pull requests
|
||||
|
||||
|
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@ -8,4 +8,4 @@ I am running Firefly III version x.x.x
|
||||
|
||||
#### Other important details (log files, system info):
|
||||
|
||||
Please visit the /debug page to get extra debug information.
|
||||
Please click the version number in the right corner of any Firefly III page to get debug information.
|
4
.github/SUPPORT.md
vendored
4
.github/SUPPORT.md
vendored
@ -4,8 +4,8 @@
|
||||
|
||||
## Bugs
|
||||
|
||||
First of all: thank you for reporting a bug instead of ditching the tool altogether. If you find a bug, please take the time and see if the [demo site](https://firefly-iii.nder.be/) is also suffering from this bug. Include as many log files and details as you think are necessary. Bugs have a lot of priority!
|
||||
First of all: thank you for reporting a bug instead of ditching the tool altogether. If you find a bug, please take the time and see if the [demo site](https://demo.firefly-iii.org/) is also suffering from this bug. Include as many log files and details as you think are necessary. Bugs have a lot of priority!
|
||||
|
||||
## Installation problems
|
||||
|
||||
Please take the time to read the [installation guide FAQ](https://firefly-iii.github.io/installation-guide-faq/) and make sure you search through closed issues for the problems other people have had. Your problem may be among them! If not, open an issue and I will help where I can.
|
||||
Please take the time to read the [installation guide FAQ](https://firefly-iii.org/installation-guide-faq/) and make sure you search through closed issues for the problems other people have had. Your problem may be among them! If not, open an issue and I will help where I can.
|
@ -1,5 +1,24 @@
|
||||
# 4.6.1.1
|
||||
|
||||
# 4.6.12
|
||||
- Support for Indonesian.
|
||||
- New report, see [issue 384](https://github.com/firefly-iii/firefly-iii/issues/384)
|
||||
- [Issue 964](https://github.com/firefly-iii/firefly-iii/issues/964) as suggested by [gavu](https://github.com/gavu)
|
||||
- Greatly improved Docker support and documentation.
|
||||
- [Issue 1046](https://github.com/firefly-iii/firefly-iii/issues/1046), as reported by [pkoziol](https://github.com/pkoziol)
|
||||
- [Issue 1047](https://github.com/firefly-iii/firefly-iii/issues/1047), as reported by [pkoziol](https://github.com/pkoziol)
|
||||
- [Issue 1048](https://github.com/firefly-iii/firefly-iii/issues/1048), as reported by [webence](https://github.com/webence)
|
||||
- [Issue 1049](https://github.com/firefly-iii/firefly-iii/issues/1049), as reported by [nicoschreiner](https://github.com/nicoschreiner)
|
||||
- [Issue 1015](https://github.com/firefly-iii/firefly-iii/issues/1015), as reporterd by a user on Tweakers.net
|
||||
- [Issue 1056](https://github.com/firefly-iii/firefly-iii/issues/1056), as reported by [repercussion](https://github.com/repercussion)
|
||||
- [Issue 1061](https://github.com/firefly-iii/firefly-iii/issues/1061), as reported by [Meizikyn](https://github.com/Meizikyn)
|
||||
- [Issue 1045](https://github.com/firefly-iii/firefly-iii/issues/1045), as reported by [gavu](https://github.com/gavu)
|
||||
- First code for [issue 1040](https://github.com/firefly-iii/firefly-iii/issues/1040) ([simonsmiley](https://github.com/simonsmiley))
|
||||
- [Issue 1059](https://github.com/firefly-iii/firefly-iii/issues/1059), as reported by [4oo4](https://github.com/4oo4)
|
||||
- [Issue 1063](https://github.com/firefly-iii/firefly-iii/issues/1063), as reported by [pkoziol](https://github.com/pkoziol)
|
||||
- [Issue 1064](https://github.com/firefly-iii/firefly-iii/issues/1064), as reported by [pkoziol](https://github.com/pkoziol)
|
||||
- [Issue 1066](https://github.com/firefly-iii/firefly-iii/issues/1066), reported by [wtercato](https://github.com/wtercato)
|
||||
|
||||
# 4.6.1.1
|
||||
- Import routine can scan for matching bills, [issue 956](https://github.com/firefly-iii/firefly-iii/issues/956)
|
||||
- Import will no longer scan for rules, this has become optional. Originally suggested in [issue 956](https://github.com/firefly-iii/firefly-iii/issues/956) by [gavu](https://github.com/gavu)
|
||||
- [Issue 1033](https://github.com/firefly-iii/firefly-iii/issues/1033), as reported by [Jumanjii](https://github.com/Jumanjii)
|
||||
|
@ -208,14 +208,6 @@ opt/app/.env.heroku
|
||||
opt/app/.env.sandstorm
|
||||
opt/app/.gitattributes
|
||||
opt/app/.sandstorm/.gitattributes
|
||||
opt/app/.sandstorm/.vagrant/machines/default/virtualbox/action_provision
|
||||
opt/app/.sandstorm/.vagrant/machines/default/virtualbox/action_set_name
|
||||
opt/app/.sandstorm/.vagrant/machines/default/virtualbox/creator_uid
|
||||
opt/app/.sandstorm/.vagrant/machines/default/virtualbox/id
|
||||
opt/app/.sandstorm/.vagrant/machines/default/virtualbox/index_uuid
|
||||
opt/app/.sandstorm/.vagrant/machines/default/virtualbox/private_key
|
||||
opt/app/.sandstorm/.vagrant/machines/default/virtualbox/synced_folders
|
||||
opt/app/.sandstorm/.vagrant/machines/default/virtualbox/vagrant_cwd
|
||||
opt/app/.sandstorm/Vagrantfile
|
||||
opt/app/.sandstorm/app-graphics/firefly-iii-128.png
|
||||
opt/app/.sandstorm/app-graphics/firefly-iii-150.png
|
||||
@ -260,6 +252,7 @@ opt/app/app/Events/AdminRequestedTestMessage.php
|
||||
opt/app/app/Events/Event.php
|
||||
opt/app/app/Events/RegisteredUser.php
|
||||
opt/app/app/Events/RequestedNewPassword.php
|
||||
opt/app/app/Events/RequestedVersionCheckStatus.php
|
||||
opt/app/app/Events/StoredTransactionJournal.php
|
||||
opt/app/app/Events/UpdatedTransactionJournal.php
|
||||
opt/app/app/Events/UserChangedEmail.php
|
||||
@ -279,6 +272,9 @@ opt/app/app/Export/Exporter/ExporterInterface.php
|
||||
opt/app/app/Export/ProcessorInterface.php
|
||||
opt/app/app/Generator/Chart/Basic/ChartJsGenerator.php
|
||||
opt/app/app/Generator/Chart/Basic/GeneratorInterface.php
|
||||
opt/app/app/Generator/Report/Account/MonthReportGenerator.php
|
||||
opt/app/app/Generator/Report/Account/MultiYearReportGenerator.php
|
||||
opt/app/app/Generator/Report/Account/YearReportGenerator.php
|
||||
opt/app/app/Generator/Report/Audit/MonthReportGenerator.php
|
||||
opt/app/app/Generator/Report/Audit/MultiYearReportGenerator.php
|
||||
opt/app/app/Generator/Report/Audit/YearReportGenerator.php
|
||||
@ -301,6 +297,7 @@ opt/app/app/Handlers/Events/AdminEventHandler.php
|
||||
opt/app/app/Handlers/Events/StoredJournalEventHandler.php
|
||||
opt/app/app/Handlers/Events/UpdatedJournalEventHandler.php
|
||||
opt/app/app/Handlers/Events/UserEventHandler.php
|
||||
opt/app/app/Handlers/Events/VersionCheckEventHandler.php
|
||||
opt/app/app/Helpers/Attachments/AttachmentHelper.php
|
||||
opt/app/app/Helpers/Attachments/AttachmentHelperInterface.php
|
||||
opt/app/app/Helpers/Chart/MetaPieChart.php
|
||||
@ -339,6 +336,7 @@ opt/app/app/Http/Controllers/AccountController.php
|
||||
opt/app/app/Http/Controllers/Admin/ConfigurationController.php
|
||||
opt/app/app/Http/Controllers/Admin/HomeController.php
|
||||
opt/app/app/Http/Controllers/Admin/LinkController.php
|
||||
opt/app/app/Http/Controllers/Admin/UpdateController.php
|
||||
opt/app/app/Http/Controllers/Admin/UserController.php
|
||||
opt/app/app/Http/Controllers/AttachmentController.php
|
||||
opt/app/app/Http/Controllers/Auth/ForgotPasswordController.php
|
||||
@ -355,6 +353,7 @@ opt/app/app/Http/Controllers/Chart/BudgetController.php
|
||||
opt/app/app/Http/Controllers/Chart/BudgetReportController.php
|
||||
opt/app/app/Http/Controllers/Chart/CategoryController.php
|
||||
opt/app/app/Http/Controllers/Chart/CategoryReportController.php
|
||||
opt/app/app/Http/Controllers/Chart/ExpenseReportController.php
|
||||
opt/app/app/Http/Controllers/Chart/PiggyBankController.php
|
||||
opt/app/app/Http/Controllers/Chart/ReportController.php
|
||||
opt/app/app/Http/Controllers/Chart/TagReportController.php
|
||||
@ -363,9 +362,10 @@ opt/app/app/Http/Controllers/CurrencyController.php
|
||||
opt/app/app/Http/Controllers/ExportController.php
|
||||
opt/app/app/Http/Controllers/HelpController.php
|
||||
opt/app/app/Http/Controllers/HomeController.php
|
||||
opt/app/app/Http/Controllers/Import/BankController.php
|
||||
opt/app/app/Http/Controllers/Import/FileController.php
|
||||
opt/app/app/Http/Controllers/ImportController.php
|
||||
opt/app/app/Http/Controllers/Import/ConfigurationController.php
|
||||
opt/app/app/Http/Controllers/Import/IndexController.php
|
||||
opt/app/app/Http/Controllers/Import/PrerequisitesController.php
|
||||
opt/app/app/Http/Controllers/Import/StatusController.php
|
||||
opt/app/app/Http/Controllers/JavascriptController.php
|
||||
opt/app/app/Http/Controllers/Json/AutoCompleteController.php
|
||||
opt/app/app/Http/Controllers/Json/BoxController.php
|
||||
@ -382,6 +382,7 @@ opt/app/app/Http/Controllers/Report/AccountController.php
|
||||
opt/app/app/Http/Controllers/Report/BalanceController.php
|
||||
opt/app/app/Http/Controllers/Report/BudgetController.php
|
||||
opt/app/app/Http/Controllers/Report/CategoryController.php
|
||||
opt/app/app/Http/Controllers/Report/ExpenseController.php
|
||||
opt/app/app/Http/Controllers/Report/OperationsController.php
|
||||
opt/app/app/Http/Controllers/ReportController.php
|
||||
opt/app/app/Http/Controllers/RuleController.php
|
||||
@ -400,7 +401,8 @@ opt/app/app/Http/Middleware/AuthenticateTwoFactor.php
|
||||
opt/app/app/Http/Middleware/Binder.php
|
||||
opt/app/app/Http/Middleware/EncryptCookies.php
|
||||
opt/app/app/Http/Middleware/IsAdmin.php
|
||||
opt/app/app/Http/Middleware/IsLimitedUser.php
|
||||
opt/app/app/Http/Middleware/IsDemoUser.php
|
||||
opt/app/app/Http/Middleware/IsSandStormUser.php
|
||||
opt/app/app/Http/Middleware/Range.php
|
||||
opt/app/app/Http/Middleware/RedirectIfAuthenticated.php
|
||||
opt/app/app/Http/Middleware/RedirectIfTwoFactorAuthenticated.php
|
||||
@ -420,7 +422,6 @@ opt/app/app/Http/Requests/CurrencyFormRequest.php
|
||||
opt/app/app/Http/Requests/DeleteAccountFormRequest.php
|
||||
opt/app/app/Http/Requests/EmailFormRequest.php
|
||||
opt/app/app/Http/Requests/ExportFormRequest.php
|
||||
opt/app/app/Http/Requests/ImportUploadRequest.php
|
||||
opt/app/app/Http/Requests/JournalFormRequest.php
|
||||
opt/app/app/Http/Requests/JournalLinkRequest.php
|
||||
opt/app/app/Http/Requests/LinkTypeFormRequest.php
|
||||
@ -441,15 +442,15 @@ opt/app/app/Http/Requests/TestRuleFormRequest.php
|
||||
opt/app/app/Http/Requests/TokenFormRequest.php
|
||||
opt/app/app/Http/Requests/UserFormRequest.php
|
||||
opt/app/app/Http/Requests/UserRegistrationRequest.php
|
||||
opt/app/app/Http/breadcrumbs.php
|
||||
opt/app/app/Import/Configurator/ConfiguratorInterface.php
|
||||
opt/app/app/Import/Configurator/CsvConfigurator.php
|
||||
opt/app/app/Import/Configuration/ConfiguratorInterface.php
|
||||
opt/app/app/Import/Configuration/FileConfigurator.php
|
||||
opt/app/app/Import/Configuration/SpectreConfigurator.php
|
||||
opt/app/app/Import/Converter/Amount.php
|
||||
opt/app/app/Import/Converter/AmountCredit.php
|
||||
opt/app/app/Import/Converter/AmountDebet.php
|
||||
opt/app/app/Import/Converter/AmountDebit.php
|
||||
opt/app/app/Import/Converter/ConverterInterface.php
|
||||
opt/app/app/Import/Converter/INGDebetCredit.php
|
||||
opt/app/app/Import/Converter/RabobankDebetCredit.php
|
||||
opt/app/app/Import/Converter/INGDebitCredit.php
|
||||
opt/app/app/Import/Converter/RabobankDebitCredit.php
|
||||
opt/app/app/Import/FileProcessor/CsvProcessor.php
|
||||
opt/app/app/Import/FileProcessor/FileProcessorInterface.php
|
||||
opt/app/app/Import/Logging/CommandHandler.php
|
||||
@ -472,7 +473,13 @@ opt/app/app/Import/Object/ImportBudget.php
|
||||
opt/app/app/Import/Object/ImportCategory.php
|
||||
opt/app/app/Import/Object/ImportCurrency.php
|
||||
opt/app/app/Import/Object/ImportJournal.php
|
||||
opt/app/app/Import/Routine/ImportRoutine.php
|
||||
opt/app/app/Import/Prerequisites/BunqPrerequisites.php
|
||||
opt/app/app/Import/Prerequisites/FilePrerequisites.php
|
||||
opt/app/app/Import/Prerequisites/PrerequisitesInterface.php
|
||||
opt/app/app/Import/Prerequisites/SpectrePrerequisites.php
|
||||
opt/app/app/Import/Routine/FileRoutine.php
|
||||
opt/app/app/Import/Routine/RoutineInterface.php
|
||||
opt/app/app/Import/Routine/SpectreRoutine.php
|
||||
opt/app/app/Import/Specifics/AbnAmroDescription.php
|
||||
opt/app/app/Import/Specifics/IngDescription.php
|
||||
opt/app/app/Import/Specifics/PresidentsChoice.php
|
||||
@ -612,8 +619,18 @@ opt/app/app/Services/Bunq/Token/InstallationToken.php
|
||||
opt/app/app/Services/Bunq/Token/SessionToken.php
|
||||
opt/app/app/Services/Currency/ExchangeRateInterface.php
|
||||
opt/app/app/Services/Currency/FixerIO.php
|
||||
opt/app/app/Services/Github/Object/GithubObject.php
|
||||
opt/app/app/Services/Github/Object/Release.php
|
||||
opt/app/app/Services/Github/Request/GithubRequest.php
|
||||
opt/app/app/Services/Github/Request/UpdateRequest.php
|
||||
opt/app/app/Services/Password/PwndVerifier.php
|
||||
opt/app/app/Services/Password/Verifier.php
|
||||
opt/app/app/Services/Spectre/Object/Customer.php
|
||||
opt/app/app/Services/Spectre/Object/SpectreObject.php
|
||||
opt/app/app/Services/Spectre/Object/Token.php
|
||||
opt/app/app/Services/Spectre/Request/CreateTokenRequest.php
|
||||
opt/app/app/Services/Spectre/Request/NewCustomerRequest.php
|
||||
opt/app/app/Services/Spectre/Request/SpectreRequest.php
|
||||
opt/app/app/Support/Amount.php
|
||||
opt/app/app/Support/Binder/AccountList.php
|
||||
opt/app/app/Support/Binder/BinderInterface.php
|
||||
@ -637,13 +654,12 @@ opt/app/app/Support/Facades/Preferences.php
|
||||
opt/app/app/Support/Facades/Steam.php
|
||||
opt/app/app/Support/FireflyConfig.php
|
||||
opt/app/app/Support/Import/Configuration/ConfigurationInterface.php
|
||||
opt/app/app/Support/Import/Configuration/Csv/Initial.php
|
||||
opt/app/app/Support/Import/Configuration/Csv/Map.php
|
||||
opt/app/app/Support/Import/Configuration/Csv/Roles.php
|
||||
opt/app/app/Support/Import/Configuration/File/Initial.php
|
||||
opt/app/app/Support/Import/Configuration/File/Map.php
|
||||
opt/app/app/Support/Import/Configuration/File/Roles.php
|
||||
opt/app/app/Support/Import/Configuration/File/Upload.php
|
||||
opt/app/app/Support/Import/Information/BunqInformation.php
|
||||
opt/app/app/Support/Import/Information/InformationInterface.php
|
||||
opt/app/app/Support/Import/Prerequisites/BunqPrerequisites.php
|
||||
opt/app/app/Support/Import/Prerequisites/PrerequisitesInterface.php
|
||||
opt/app/app/Support/Models/TransactionJournalTrait.php
|
||||
opt/app/app/Support/Navigation.php
|
||||
opt/app/app/Support/Preferences.php
|
||||
@ -730,12 +746,15 @@ opt/app/composer.lock
|
||||
opt/app/composer.phar
|
||||
opt/app/config/app.php
|
||||
opt/app/config/auth.php
|
||||
opt/app/config/breadcrumbs.php
|
||||
opt/app/config/broadcasting.php
|
||||
opt/app/config/cache.php
|
||||
opt/app/config/csv.php
|
||||
opt/app/config/database.php
|
||||
opt/app/config/filesystems.php
|
||||
opt/app/config/firefly.php
|
||||
opt/app/config/google2fa.php
|
||||
opt/app/config/import.php
|
||||
opt/app/config/intro.php
|
||||
opt/app/config/mail.php
|
||||
opt/app/config/queue.php
|
||||
@ -766,9 +785,6 @@ opt/app/database/seeds/LinkTypeSeeder.php
|
||||
opt/app/database/seeds/PermissionSeeder.php
|
||||
opt/app/database/seeds/TransactionCurrencySeeder.php
|
||||
opt/app/database/seeds/TransactionTypeSeeder.php
|
||||
opt/app/docker-compose.dockerhub.yml
|
||||
opt/app/docker-compose.override.yml
|
||||
opt/app/docker-compose.prod.yml
|
||||
opt/app/docker-compose.yml
|
||||
opt/app/nginx_app.conf
|
||||
opt/app/phpunit.coverage.xml
|
||||
@ -850,6 +866,10 @@ opt/app/public/images/image.png
|
||||
opt/app/public/images/loading-small.gif
|
||||
opt/app/public/images/loading-wide.gif
|
||||
opt/app/public/images/logos/bunq.png
|
||||
opt/app/public/images/logos/csv.png
|
||||
opt/app/public/images/logos/file.png
|
||||
opt/app/public/images/logos/plaid.png
|
||||
opt/app/public/images/logos/spectre.png
|
||||
opt/app/public/images/page_green.png
|
||||
opt/app/public/images/page_white_acrobat.png
|
||||
opt/app/public/index.php
|
||||
@ -858,6 +878,7 @@ opt/app/public/js/ff/accounts/edit-reconciliation.js
|
||||
opt/app/public/js/ff/accounts/edit.js
|
||||
opt/app/public/js/ff/accounts/reconcile.js
|
||||
opt/app/public/js/ff/accounts/show.js
|
||||
opt/app/public/js/ff/admin/update/index.js
|
||||
opt/app/public/js/ff/bills/create.js
|
||||
opt/app/public/js/ff/bills/edit.js
|
||||
opt/app/public/js/ff/bills/show.js
|
||||
@ -880,17 +901,16 @@ opt/app/public/js/ff/piggy-banks/edit.js
|
||||
opt/app/public/js/ff/piggy-banks/index.js
|
||||
opt/app/public/js/ff/piggy-banks/show.js
|
||||
opt/app/public/js/ff/preferences/index.js
|
||||
opt/app/public/js/ff/reports/account/month.js
|
||||
opt/app/public/js/ff/reports/all.js
|
||||
opt/app/public/js/ff/reports/audit/all.js
|
||||
opt/app/public/js/ff/reports/budget/all.js
|
||||
opt/app/public/js/ff/reports/budget/month.js
|
||||
opt/app/public/js/ff/reports/category/all.js
|
||||
opt/app/public/js/ff/reports/category/month.js
|
||||
opt/app/public/js/ff/reports/default/all.js
|
||||
opt/app/public/js/ff/reports/default/month.js
|
||||
opt/app/public/js/ff/reports/default/multi-year.js
|
||||
opt/app/public/js/ff/reports/default/year.js
|
||||
opt/app/public/js/ff/reports/index.js
|
||||
opt/app/public/js/ff/reports/tag/all.js
|
||||
opt/app/public/js/ff/reports/tag/month.js
|
||||
opt/app/public/js/ff/rules/create-edit.js
|
||||
opt/app/public/js/ff/rules/index.js
|
||||
@ -975,6 +995,7 @@ opt/app/resources/lang/de_DE/demo.php
|
||||
opt/app/resources/lang/de_DE/firefly.php
|
||||
opt/app/resources/lang/de_DE/form.php
|
||||
opt/app/resources/lang/de_DE/help.php
|
||||
opt/app/resources/lang/de_DE/import.php
|
||||
opt/app/resources/lang/de_DE/intro.php
|
||||
opt/app/resources/lang/de_DE/list.php
|
||||
opt/app/resources/lang/de_DE/pagination.php
|
||||
@ -988,6 +1009,7 @@ opt/app/resources/lang/en_US/csv.php
|
||||
opt/app/resources/lang/en_US/demo.php
|
||||
opt/app/resources/lang/en_US/firefly.php
|
||||
opt/app/resources/lang/en_US/form.php
|
||||
opt/app/resources/lang/en_US/import.php
|
||||
opt/app/resources/lang/en_US/intro.php
|
||||
opt/app/resources/lang/en_US/list.php
|
||||
opt/app/resources/lang/en_US/pagination.php
|
||||
@ -1002,11 +1024,26 @@ opt/app/resources/lang/fr_FR/demo.php
|
||||
opt/app/resources/lang/fr_FR/firefly.php
|
||||
opt/app/resources/lang/fr_FR/form.php
|
||||
opt/app/resources/lang/fr_FR/help.php
|
||||
opt/app/resources/lang/fr_FR/import.php
|
||||
opt/app/resources/lang/fr_FR/intro.php
|
||||
opt/app/resources/lang/fr_FR/list.php
|
||||
opt/app/resources/lang/fr_FR/pagination.php
|
||||
opt/app/resources/lang/fr_FR/passwords.php
|
||||
opt/app/resources/lang/fr_FR/validation.php
|
||||
opt/app/resources/lang/id_ID/auth.php
|
||||
opt/app/resources/lang/id_ID/bank.php
|
||||
opt/app/resources/lang/id_ID/breadcrumbs.php
|
||||
opt/app/resources/lang/id_ID/config.php
|
||||
opt/app/resources/lang/id_ID/csv.php
|
||||
opt/app/resources/lang/id_ID/demo.php
|
||||
opt/app/resources/lang/id_ID/firefly.php
|
||||
opt/app/resources/lang/id_ID/form.php
|
||||
opt/app/resources/lang/id_ID/import.php
|
||||
opt/app/resources/lang/id_ID/intro.php
|
||||
opt/app/resources/lang/id_ID/list.php
|
||||
opt/app/resources/lang/id_ID/pagination.php
|
||||
opt/app/resources/lang/id_ID/passwords.php
|
||||
opt/app/resources/lang/id_ID/validation.php
|
||||
opt/app/resources/lang/nl_NL/auth.php
|
||||
opt/app/resources/lang/nl_NL/bank.php
|
||||
opt/app/resources/lang/nl_NL/breadcrumbs.php
|
||||
@ -1016,6 +1053,7 @@ opt/app/resources/lang/nl_NL/demo.php
|
||||
opt/app/resources/lang/nl_NL/firefly.php
|
||||
opt/app/resources/lang/nl_NL/form.php
|
||||
opt/app/resources/lang/nl_NL/help.php
|
||||
opt/app/resources/lang/nl_NL/import.php
|
||||
opt/app/resources/lang/nl_NL/intro.php
|
||||
opt/app/resources/lang/nl_NL/list.php
|
||||
opt/app/resources/lang/nl_NL/pagination.php
|
||||
@ -1030,6 +1068,7 @@ opt/app/resources/lang/pl_PL/demo.php
|
||||
opt/app/resources/lang/pl_PL/firefly.php
|
||||
opt/app/resources/lang/pl_PL/form.php
|
||||
opt/app/resources/lang/pl_PL/help.php
|
||||
opt/app/resources/lang/pl_PL/import.php
|
||||
opt/app/resources/lang/pl_PL/intro.php
|
||||
opt/app/resources/lang/pl_PL/list.php
|
||||
opt/app/resources/lang/pl_PL/pagination.php
|
||||
@ -1057,6 +1096,7 @@ opt/app/resources/views/admin/link/delete.twig
|
||||
opt/app/resources/views/admin/link/edit.twig
|
||||
opt/app/resources/views/admin/link/index.twig
|
||||
opt/app/resources/views/admin/link/show.twig
|
||||
opt/app/resources/views/admin/update/index.twig
|
||||
opt/app/resources/views/admin/users/delete.twig
|
||||
opt/app/resources/views/admin/users/edit.twig
|
||||
opt/app/resources/views/admin/users/index.twig
|
||||
@ -1151,13 +1191,17 @@ opt/app/resources/views/form/text.twig
|
||||
opt/app/resources/views/form/textarea.twig
|
||||
opt/app/resources/views/import/bank/form.twig
|
||||
opt/app/resources/views/import/bunq/prerequisites.twig
|
||||
opt/app/resources/views/import/csv/initial.twig
|
||||
opt/app/resources/views/import/csv/map.twig
|
||||
opt/app/resources/views/import/csv/roles.twig
|
||||
opt/app/resources/views/import/file/finished.twig
|
||||
opt/app/resources/views/import/file/index.twig
|
||||
opt/app/resources/views/import/file/status.twig
|
||||
opt/app/resources/views/import/file/initial.twig
|
||||
opt/app/resources/views/import/file/map.twig
|
||||
opt/app/resources/views/import/file/roles.twig
|
||||
opt/app/resources/views/import/file/upload.twig
|
||||
opt/app/resources/views/import/index.twig
|
||||
opt/app/resources/views/import/spectre/input-fields.twig
|
||||
opt/app/resources/views/import/spectre/prerequisites.twig
|
||||
opt/app/resources/views/import/spectre/redirect.twig
|
||||
opt/app/resources/views/import/spectre/select-country.twig
|
||||
opt/app/resources/views/import/spectre/select-provider.twig
|
||||
opt/app/resources/views/import/status.twig
|
||||
opt/app/resources/views/index.twig
|
||||
opt/app/resources/views/javascript/accounts.twig
|
||||
opt/app/resources/views/javascript/currencies.twig
|
||||
@ -1204,6 +1248,7 @@ opt/app/resources/views/profile/change-email.twig
|
||||
opt/app/resources/views/profile/change-password.twig
|
||||
opt/app/resources/views/profile/delete-account.twig
|
||||
opt/app/resources/views/profile/index.twig
|
||||
opt/app/resources/views/reports/account/report.twig
|
||||
opt/app/resources/views/reports/audit/report.twig
|
||||
opt/app/resources/views/reports/budget/month.twig
|
||||
opt/app/resources/views/reports/category/month.twig
|
||||
@ -1211,6 +1256,7 @@ opt/app/resources/views/reports/default/month.twig
|
||||
opt/app/resources/views/reports/default/multi-year.twig
|
||||
opt/app/resources/views/reports/default/year.twig
|
||||
opt/app/resources/views/reports/index.twig
|
||||
opt/app/resources/views/reports/options/account.twig
|
||||
opt/app/resources/views/reports/options/budget.twig
|
||||
opt/app/resources/views/reports/options/category.twig
|
||||
opt/app/resources/views/reports/options/no-options.twig
|
||||
@ -1222,10 +1268,14 @@ opt/app/resources/views/reports/partials/budget-period.twig
|
||||
opt/app/resources/views/reports/partials/budgets.twig
|
||||
opt/app/resources/views/reports/partials/categories.twig
|
||||
opt/app/resources/views/reports/partials/category-period.twig
|
||||
opt/app/resources/views/reports/partials/exp-budgets.twig
|
||||
opt/app/resources/views/reports/partials/exp-categories.twig
|
||||
opt/app/resources/views/reports/partials/exp-not-grouped.twig
|
||||
opt/app/resources/views/reports/partials/income-expenses.twig
|
||||
opt/app/resources/views/reports/partials/journals-audit.twig
|
||||
opt/app/resources/views/reports/partials/operations.twig
|
||||
opt/app/resources/views/reports/partials/tags.twig
|
||||
opt/app/resources/views/reports/partials/top-transactions.twig
|
||||
opt/app/resources/views/reports/tag/month.twig
|
||||
opt/app/resources/views/rules/index.twig
|
||||
opt/app/resources/views/rules/partials/action.twig
|
||||
@ -1246,6 +1296,7 @@ opt/app/resources/views/tags/delete.twig
|
||||
opt/app/resources/views/tags/edit.twig
|
||||
opt/app/resources/views/tags/index.twig
|
||||
opt/app/resources/views/tags/show.twig
|
||||
opt/app/resources/views/test/test.twig
|
||||
opt/app/resources/views/transactions/convert.twig
|
||||
opt/app/resources/views/transactions/index.twig
|
||||
opt/app/resources/views/transactions/links/delete.twig
|
||||
@ -1257,6 +1308,7 @@ opt/app/resources/views/transactions/single/delete.twig
|
||||
opt/app/resources/views/transactions/single/edit.twig
|
||||
opt/app/resources/views/transactions/split/edit.twig
|
||||
opt/app/routes/api.php
|
||||
opt/app/routes/breadcrumbs.php
|
||||
opt/app/routes/channels.php
|
||||
opt/app/routes/console.php
|
||||
opt/app/routes/web.php
|
||||
@ -1325,14 +1377,6 @@ opt/app/vendor/bacon/bacon-qr-code/tests/BaconQrCode/Renderer/Text/TextTest.php
|
||||
opt/app/vendor/bacon/bacon-qr-code/tests/bootstrap.php
|
||||
opt/app/vendor/bin/commonmark
|
||||
opt/app/vendor/bin/doctrine-dbal
|
||||
opt/app/vendor/christian-riesen/base32/LICENSE
|
||||
opt/app/vendor/christian-riesen/base32/README.md
|
||||
opt/app/vendor/christian-riesen/base32/build.xml
|
||||
opt/app/vendor/christian-riesen/base32/composer.json
|
||||
opt/app/vendor/christian-riesen/base32/phpunit.xml.dist
|
||||
opt/app/vendor/christian-riesen/base32/src/Base32.php
|
||||
opt/app/vendor/christian-riesen/base32/tests/Base32Test.php
|
||||
opt/app/vendor/christian-riesen/base32/tests/bootstrap.php
|
||||
opt/app/vendor/composer/ClassLoader.php
|
||||
opt/app/vendor/composer/LICENSE
|
||||
opt/app/vendor/composer/autoload_classmap.php
|
||||
@ -1342,37 +1386,24 @@ opt/app/vendor/composer/autoload_psr4.php
|
||||
opt/app/vendor/composer/autoload_real.php
|
||||
opt/app/vendor/composer/autoload_static.php
|
||||
opt/app/vendor/composer/installed.json
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/.editorconfig
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/README.md
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/RELEASE-CHECKLIST.md
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/composer.json
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/config/breadcrumbs.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/scripts/test-coverage.sh
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/CurrentRoute.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/Exception.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/Facade.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/Generator.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/Manager.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/ServiceProvider.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/View.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/TestCase.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/bootstrap.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/fixtures/CustomServiceProvider.html
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/fixtures/DependantServiceProvider.html
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/fixtures/bootstrap2.html
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/fixtures/bootstrap3.html
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/fixtures/integration.html
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/integration/CustomServiceProviderTest.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/integration/DependantServiceProviderErrorTest.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/integration/DependantServiceProviderTest.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/integration/IntegrationTest.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/unit/CurrentRouteTest.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/unit/FacadeTest.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/unit/GeneratorTest.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/unit/ManagerTest.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/tests/unit/ViewTest.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/BreadcrumbsException.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/BreadcrumbsGenerator.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/BreadcrumbsManager.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/BreadcrumbsServiceProvider.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/Exceptions/DuplicateBreadcrumbException.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/Exceptions/InvalidBreadcrumbException.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/Exceptions/UnnamedRouteException.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/Exceptions/ViewNotSetException.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/src/Facades/Breadcrumbs.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/bootstrap2.blade.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/bootstrap3.blade.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/bootstrap4.blade.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/bulma.blade.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/foundation6.blade.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/json-ld.php
|
||||
opt/app/vendor/davejamesmiller/laravel-breadcrumbs/views/materialize.blade.php
|
||||
opt/app/vendor/doctrine/annotations/CHANGELOG.md
|
||||
opt/app/vendor/doctrine/annotations/LICENSE
|
||||
opt/app/vendor/doctrine/annotations/README.md
|
||||
@ -2188,6 +2219,7 @@ opt/app/vendor/laravel/framework/src/Illuminate/Events/CallQueuedListener.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Events/Dispatcher.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Events/EventServiceProvider.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Events/composer.json
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Filesystem/Cache.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemAdapter.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Filesystem/FilesystemManager.php
|
||||
@ -2663,6 +2695,7 @@ opt/app/vendor/laravel/framework/src/Illuminate/Support/MessageBag.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Support/NamespacedItemResolver.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Support/Optional.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Support/Pluralizer.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Support/ProcessUtils.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Support/ServiceProvider.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Support/Str.php
|
||||
opt/app/vendor/laravel/framework/src/Illuminate/Support/Testing/Fakes/BusFake.php
|
||||
@ -2865,23 +2898,29 @@ opt/app/vendor/league/commonmark/src/Util/Html5Entities.php
|
||||
opt/app/vendor/league/commonmark/src/Util/LinkParserHelper.php
|
||||
opt/app/vendor/league/commonmark/src/Util/RegexHelper.php
|
||||
opt/app/vendor/league/commonmark/src/Util/UrlEncoder.php
|
||||
opt/app/vendor/league/commonmark/src/Util/Xml.php
|
||||
opt/app/vendor/league/csv/LICENSE
|
||||
opt/app/vendor/league/csv/autoload.php
|
||||
opt/app/vendor/league/csv/composer.json
|
||||
opt/app/vendor/league/csv/src/AbstractCsv.php
|
||||
opt/app/vendor/league/csv/src/Config/Controls.php
|
||||
opt/app/vendor/league/csv/src/Config/Output.php
|
||||
opt/app/vendor/league/csv/src/Exception/InvalidRowException.php
|
||||
opt/app/vendor/league/csv/src/Modifier/MapIterator.php
|
||||
opt/app/vendor/league/csv/src/Modifier/QueryFilter.php
|
||||
opt/app/vendor/league/csv/src/Modifier/RowFilter.php
|
||||
opt/app/vendor/league/csv/src/Modifier/StreamFilter.php
|
||||
opt/app/vendor/league/csv/src/Modifier/StreamIterator.php
|
||||
opt/app/vendor/league/csv/src/Plugin/ColumnConsistencyValidator.php
|
||||
opt/app/vendor/league/csv/src/Plugin/ForbiddenNullValuesValidator.php
|
||||
opt/app/vendor/league/csv/src/Plugin/SkipNullValuesFormatter.php
|
||||
opt/app/vendor/league/csv/src/ByteSequence.php
|
||||
opt/app/vendor/league/csv/src/CannotInsertRecord.php
|
||||
opt/app/vendor/league/csv/src/CharsetConverter.php
|
||||
opt/app/vendor/league/csv/src/ColumnConsistency.php
|
||||
opt/app/vendor/league/csv/src/EncloseField.php
|
||||
opt/app/vendor/league/csv/src/EscapeFormula.php
|
||||
opt/app/vendor/league/csv/src/Exception.php
|
||||
opt/app/vendor/league/csv/src/HTMLConverter.php
|
||||
opt/app/vendor/league/csv/src/MapIterator.php
|
||||
opt/app/vendor/league/csv/src/RFC4180Field.php
|
||||
opt/app/vendor/league/csv/src/Reader.php
|
||||
opt/app/vendor/league/csv/src/ResultSet.php
|
||||
opt/app/vendor/league/csv/src/Statement.php
|
||||
opt/app/vendor/league/csv/src/Stream.php
|
||||
opt/app/vendor/league/csv/src/Writer.php
|
||||
opt/app/vendor/league/csv/src/XMLConverter.php
|
||||
opt/app/vendor/league/csv/src/functions.php
|
||||
opt/app/vendor/league/csv/src/functions_include.php
|
||||
opt/app/vendor/league/flysystem/LICENSE
|
||||
opt/app/vendor/league/flysystem/composer.json
|
||||
opt/app/vendor/league/flysystem/docs/CNAME
|
||||
@ -3229,6 +3268,31 @@ opt/app/vendor/nesbot/carbon/src/Carbon/Lang/uz.php
|
||||
opt/app/vendor/nesbot/carbon/src/Carbon/Lang/vi.php
|
||||
opt/app/vendor/nesbot/carbon/src/Carbon/Lang/zh.php
|
||||
opt/app/vendor/nesbot/carbon/src/Carbon/Lang/zh_TW.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/LICENSE.txt
|
||||
opt/app/vendor/paragonie/constant_time_encoding/README.md
|
||||
opt/app/vendor/paragonie/constant_time_encoding/composer.json
|
||||
opt/app/vendor/paragonie/constant_time_encoding/phpunit.xml.dist
|
||||
opt/app/vendor/paragonie/constant_time_encoding/psalm.xml
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/Base32.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/Base32Hex.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/Base64.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/Binary.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/EncoderInterface.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/Encoding.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/Hex.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/src/RFC4648.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/tests/Base32HexTest.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/tests/Base32Test.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/tests/Base64DotSlashOrderedTest.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/tests/Base64DotSlashTest.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/tests/Base64Test.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/tests/Base64UrlSafeTest.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/tests/EncodingTest.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/tests/HexTest.php
|
||||
opt/app/vendor/paragonie/constant_time_encoding/tests/RFC4648Test.php
|
||||
opt/app/vendor/paragonie/random_compat/LICENSE
|
||||
opt/app/vendor/paragonie/random_compat/build-phar.sh
|
||||
opt/app/vendor/paragonie/random_compat/composer.json
|
||||
@ -3247,19 +3311,45 @@ opt/app/vendor/paragonie/random_compat/lib/random_int.php
|
||||
opt/app/vendor/paragonie/random_compat/other/build_phar.php
|
||||
opt/app/vendor/paragonie/random_compat/psalm-autoload.php
|
||||
opt/app/vendor/paragonie/random_compat/psalm.xml
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/LICENSE
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/changelog.md
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/composer.json
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/docs/middleware.jpg
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/phpspec.yml
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/readme.md
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Events/OneTimePasswordRequested.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Exceptions/InvalidOneTimePassword.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Exceptions/InvalidSecretKey.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Facade.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Middleware.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/ServiceProvider.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Support/Auth.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Support/Authenticator.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Support/Config.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Support/Constants.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Support/ErrorBag.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Support/Input.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Support/Request.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Support/Response.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/Support/Session.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/src/config/config.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/tests/spec/Support/AuthenticatorSpec.php
|
||||
opt/app/vendor/pragmarx/google2fa-laravel/upgrading.md
|
||||
opt/app/vendor/pragmarx/google2fa/LICENSE
|
||||
opt/app/vendor/pragmarx/google2fa/changelog.md
|
||||
opt/app/vendor/pragmarx/google2fa/composer.json
|
||||
opt/app/vendor/pragmarx/google2fa/phpspec.yml
|
||||
opt/app/vendor/pragmarx/google2fa/docs/playground.jpg
|
||||
opt/app/vendor/pragmarx/google2fa/readme.md
|
||||
opt/app/vendor/pragmarx/google2fa/src/Contracts/Google2FA.php
|
||||
opt/app/vendor/pragmarx/google2fa/src/Exceptions/IncompatibleWithGoogleAuthenticatorException.php
|
||||
opt/app/vendor/pragmarx/google2fa/src/Exceptions/InvalidCharactersException.php
|
||||
opt/app/vendor/pragmarx/google2fa/src/Exceptions/SecretKeyTooShortException.php
|
||||
opt/app/vendor/pragmarx/google2fa/src/Google2FA.php
|
||||
opt/app/vendor/pragmarx/google2fa/src/Support/Base32.php
|
||||
opt/app/vendor/pragmarx/google2fa/src/Support/Constants.php
|
||||
opt/app/vendor/pragmarx/google2fa/src/Support/QRCode.php
|
||||
opt/app/vendor/pragmarx/google2fa/src/Support/Url.php
|
||||
opt/app/vendor/pragmarx/google2fa/src/Vendor/Laravel/Facade.php
|
||||
opt/app/vendor/pragmarx/google2fa/src/Vendor/Laravel/ServiceProvider.php
|
||||
opt/app/vendor/pragmarx/google2fa/tests/spec/Google2FASpec.php
|
||||
opt/app/vendor/pragmarx/google2fa/tests/Google2FATest.php
|
||||
opt/app/vendor/pragmarx/google2fa/tests/bootstrap.php
|
||||
opt/app/vendor/pragmarx/google2fa/upgrading.md
|
||||
opt/app/vendor/psr/container/LICENSE
|
||||
opt/app/vendor/psr/container/README.md
|
||||
@ -4245,10 +4335,11 @@ opt/app/vendor/symfony/debug/Tests/Fixtures/reallyNotPsr0.php
|
||||
opt/app/vendor/symfony/debug/Tests/Fixtures2/RequiredTwice.php
|
||||
opt/app/vendor/symfony/debug/Tests/HeaderMock.php
|
||||
opt/app/vendor/symfony/debug/Tests/MockExceptionHandler.php
|
||||
opt/app/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt
|
||||
opt/app/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt
|
||||
opt/app/vendor/symfony/debug/composer.json
|
||||
opt/app/vendor/symfony/debug/phpunit.xml.dist
|
||||
opt/app/vendor/symfony/event-dispatcher/CHANGELOG.md
|
||||
opt/app/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php
|
||||
opt/app/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php
|
||||
opt/app/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php
|
||||
opt/app/vendor/symfony/event-dispatcher/Debug/WrappedListener.php
|
||||
@ -4262,7 +4353,6 @@ opt/app/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php
|
||||
opt/app/vendor/symfony/event-dispatcher/LICENSE
|
||||
opt/app/vendor/symfony/event-dispatcher/README.md
|
||||
opt/app/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php
|
||||
opt/app/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php
|
||||
opt/app/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php
|
||||
opt/app/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php
|
||||
opt/app/vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php
|
||||
@ -4453,6 +4543,8 @@ opt/app/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/st
|
||||
opt/app/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/storage.php
|
||||
opt/app/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_cookie.expected
|
||||
opt/app/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_cookie.php
|
||||
opt/app/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_cookie_and_session.expected
|
||||
opt/app/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_cookie_and_session.php
|
||||
opt/app/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php
|
||||
opt/app/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php
|
||||
opt/app/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php
|
||||
@ -4529,9 +4621,12 @@ opt/app/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueRe
|
||||
opt/app/vendor/symfony/http-kernel/DependencyInjection/Extension.php
|
||||
opt/app/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php
|
||||
opt/app/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php
|
||||
opt/app/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php
|
||||
opt/app/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php
|
||||
opt/app/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php
|
||||
opt/app/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php
|
||||
opt/app/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php
|
||||
opt/app/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php
|
||||
opt/app/vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.php
|
||||
opt/app/vendor/symfony/http-kernel/Event/FilterControllerEvent.php
|
||||
opt/app/vendor/symfony/http-kernel/Event/FilterResponseEvent.php
|
||||
@ -4600,11 +4695,14 @@ opt/app/vendor/symfony/http-kernel/KernelEvents.php
|
||||
opt/app/vendor/symfony/http-kernel/KernelInterface.php
|
||||
opt/app/vendor/symfony/http-kernel/LICENSE
|
||||
opt/app/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php
|
||||
opt/app/vendor/symfony/http-kernel/Log/Logger.php
|
||||
opt/app/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php
|
||||
opt/app/vendor/symfony/http-kernel/Profiler/Profile.php
|
||||
opt/app/vendor/symfony/http-kernel/Profiler/Profiler.php
|
||||
opt/app/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php
|
||||
opt/app/vendor/symfony/http-kernel/README.md
|
||||
opt/app/vendor/symfony/http-kernel/RebootableInterface.php
|
||||
opt/app/vendor/symfony/http-kernel/Resources/welcome.html.php
|
||||
opt/app/vendor/symfony/http-kernel/TerminableInterface.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Bundle/BundleTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/CacheClearer/ChainCacheClearerTest.php
|
||||
@ -4614,11 +4712,13 @@ opt/app/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/ClientTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Config/EnvParametersResourceTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Config/FileLocatorTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolverTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Controller/ContainerControllerResolverTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Controller/ControllerResolverTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DataCollector/Compiler.log
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DataCollector/ConfigDataCollectorTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DataCollector/DataCollectorTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DataCollector/DumpDataCollectorTest.php
|
||||
@ -4634,9 +4734,13 @@ opt/app/vendor/symfony/http-kernel/Tests/DependencyInjection/AddAnnotatedClasses
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DependencyInjection/FragmentRendererPassTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DependencyInjection/LoggerPassTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DependencyInjection/ResettableServicePassTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/DependencyInjection/ServicesResetterTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Event/FilterControllerArgumentsEventTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Event/GetResponseForExceptionEventTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/EventListener/AddRequestFormatsListenerTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/EventListener/DebugHandlersListenerTest.php
|
||||
@ -4676,6 +4780,7 @@ opt/app/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/foo.txt
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/Bundle2Bundle/foo.txt
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/foo.txt
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/hide.txt
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/ClearableService.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/Controller/BasicTypesController.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/Controller/ExtendingRequest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/Controller/ExtendingSession.php
|
||||
@ -4694,6 +4799,7 @@ opt/app/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Extensi
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/KernelForOverrideName.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/KernelForTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/KernelWithoutBundles.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/ResettableService.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/Resources/BaseBundle/hide.txt
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Fixtures/Resources/ChildBundle/foo.txt
|
||||
@ -4716,6 +4822,7 @@ opt/app/vendor/symfony/http-kernel/Tests/HttpCache/TestHttpKernel.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/HttpCache/TestMultipleHttpKernel.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/HttpKernelTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/KernelTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Log/LoggerTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Logger.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Profiler/FileProfilerStorageTest.php
|
||||
opt/app/vendor/symfony/http-kernel/Tests/Profiler/ProfilerTest.php
|
||||
@ -5297,6 +5404,7 @@ opt/app/vendor/twig/twig/lib/Twig/Cache/Null.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/CacheInterface.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Compiler.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/CompilerInterface.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/ContainerRuntimeLoader.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Environment.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Error.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Error/Loader.php
|
||||
@ -5417,6 +5525,7 @@ opt/app/vendor/twig/twig/lib/Twig/Node/SetTemp.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Node/Spaceless.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Node/Text.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Node/With.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/NodeCaptureInterface.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/NodeInterface.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/NodeOutputInterface.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/NodeTraverser.php
|
||||
@ -5427,6 +5536,7 @@ opt/app/vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/NodeVisitorInterface.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Parser.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/ParserInterface.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Profiler/Dumper/Base.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Profiler/Dumper/Text.php
|
||||
@ -5486,15 +5596,188 @@ opt/app/vendor/twig/twig/lib/Twig/TokenStream.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Util/DeprecationCollector.php
|
||||
opt/app/vendor/twig/twig/lib/Twig/Util/TemplateDirIterator.php
|
||||
opt/app/vendor/twig/twig/phpunit.xml.dist
|
||||
opt/app/vendor/twig/twig/src/Cache/CacheInterface.php
|
||||
opt/app/vendor/twig/twig/src/Cache/FilesystemCache.php
|
||||
opt/app/vendor/twig/twig/src/Cache/NullCache.php
|
||||
opt/app/vendor/twig/twig/src/Compiler.php
|
||||
opt/app/vendor/twig/twig/src/Environment.php
|
||||
opt/app/vendor/twig/twig/src/Error/Error.php
|
||||
opt/app/vendor/twig/twig/src/Error/LoaderError.php
|
||||
opt/app/vendor/twig/twig/src/Error/RuntimeError.php
|
||||
opt/app/vendor/twig/twig/src/Error/SyntaxError.php
|
||||
opt/app/vendor/twig/twig/src/ExpressionParser.php
|
||||
opt/app/vendor/twig/twig/src/Extension/AbstractExtension.php
|
||||
opt/app/vendor/twig/twig/src/Extension/CoreExtension.php
|
||||
opt/app/vendor/twig/twig/src/Extension/DebugExtension.php
|
||||
opt/app/vendor/twig/twig/src/Extension/EscaperExtension.php
|
||||
opt/app/vendor/twig/twig/src/Extension/ExtensionInterface.php
|
||||
opt/app/vendor/twig/twig/src/Extension/GlobalsInterface.php
|
||||
opt/app/vendor/twig/twig/src/Extension/InitRuntimeInterface.php
|
||||
opt/app/vendor/twig/twig/src/Extension/OptimizerExtension.php
|
||||
opt/app/vendor/twig/twig/src/Extension/ProfilerExtension.php
|
||||
opt/app/vendor/twig/twig/src/Extension/RuntimeExtensionInterface.php
|
||||
opt/app/vendor/twig/twig/src/Extension/SandboxExtension.php
|
||||
opt/app/vendor/twig/twig/src/Extension/StagingExtension.php
|
||||
opt/app/vendor/twig/twig/src/Extension/StringLoaderExtension.php
|
||||
opt/app/vendor/twig/twig/src/FileExtensionEscapingStrategy.php
|
||||
opt/app/vendor/twig/twig/src/Lexer.php
|
||||
opt/app/vendor/twig/twig/src/Loader/ArrayLoader.php
|
||||
opt/app/vendor/twig/twig/src/Loader/ChainLoader.php
|
||||
opt/app/vendor/twig/twig/src/Loader/ExistsLoaderInterface.php
|
||||
opt/app/vendor/twig/twig/src/Loader/FilesystemLoader.php
|
||||
opt/app/vendor/twig/twig/src/Loader/LoaderInterface.php
|
||||
opt/app/vendor/twig/twig/src/Loader/SourceContextLoaderInterface.php
|
||||
opt/app/vendor/twig/twig/src/Markup.php
|
||||
opt/app/vendor/twig/twig/src/Node/AutoEscapeNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/BlockNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/BlockReferenceNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/BodyNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/CheckSecurityNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/DoNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/EmbedNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/AbstractExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/ArrayExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/AssignNameExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/AbstractBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/AddBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/AndBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/ConcatBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/DivBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/EqualBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/GreaterBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/InBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/LessBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/MatchesBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/ModBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/MulBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/NotInBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/OrBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/PowerBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/RangeBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Binary/SubBinary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/CallExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/ConditionalExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/ConstantExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Filter/DefaultFilter.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/FilterExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/FunctionExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/NameExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/NullCoalesceExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/ParentExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/TempNameExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Test/ConstantTest.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Test/DefinedTest.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Test/EvenTest.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Test/NullTest.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Test/OddTest.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Test/SameasTest.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/TestExpression.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Unary/AbstractUnary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Unary/NegUnary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Unary/NotUnary.php
|
||||
opt/app/vendor/twig/twig/src/Node/Expression/Unary/PosUnary.php
|
||||
opt/app/vendor/twig/twig/src/Node/FlushNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/ForLoopNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/ForNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/IfNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/ImportNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/IncludeNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/MacroNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/ModuleNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/Node.php
|
||||
opt/app/vendor/twig/twig/src/Node/NodeCaptureInterface.php
|
||||
opt/app/vendor/twig/twig/src/Node/NodeOutputInterface.php
|
||||
opt/app/vendor/twig/twig/src/Node/PrintNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/SandboxNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/SandboxedPrintNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/SetNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/SetTempNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/SpacelessNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/TextNode.php
|
||||
opt/app/vendor/twig/twig/src/Node/WithNode.php
|
||||
opt/app/vendor/twig/twig/src/NodeTraverser.php
|
||||
opt/app/vendor/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php
|
||||
opt/app/vendor/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php
|
||||
opt/app/vendor/twig/twig/src/NodeVisitor/NodeVisitorInterface.php
|
||||
opt/app/vendor/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php
|
||||
opt/app/vendor/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php
|
||||
opt/app/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php
|
||||
opt/app/vendor/twig/twig/src/Parser.php
|
||||
opt/app/vendor/twig/twig/src/Profiler/Dumper/BaseDumper.php
|
||||
opt/app/vendor/twig/twig/src/Profiler/Dumper/BlackfireDumper.php
|
||||
opt/app/vendor/twig/twig/src/Profiler/Dumper/HtmlDumper.php
|
||||
opt/app/vendor/twig/twig/src/Profiler/Dumper/TextDumper.php
|
||||
opt/app/vendor/twig/twig/src/Profiler/Node/EnterProfileNode.php
|
||||
opt/app/vendor/twig/twig/src/Profiler/Node/LeaveProfileNode.php
|
||||
opt/app/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php
|
||||
opt/app/vendor/twig/twig/src/Profiler/Profile.php
|
||||
opt/app/vendor/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php
|
||||
opt/app/vendor/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php
|
||||
opt/app/vendor/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php
|
||||
opt/app/vendor/twig/twig/src/Sandbox/SecurityError.php
|
||||
opt/app/vendor/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php
|
||||
opt/app/vendor/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php
|
||||
opt/app/vendor/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php
|
||||
opt/app/vendor/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php
|
||||
opt/app/vendor/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php
|
||||
opt/app/vendor/twig/twig/src/Sandbox/SecurityPolicy.php
|
||||
opt/app/vendor/twig/twig/src/Sandbox/SecurityPolicyInterface.php
|
||||
opt/app/vendor/twig/twig/src/Source.php
|
||||
opt/app/vendor/twig/twig/src/Template.php
|
||||
opt/app/vendor/twig/twig/src/TemplateWrapper.php
|
||||
opt/app/vendor/twig/twig/src/Test/IntegrationTestCase.php
|
||||
opt/app/vendor/twig/twig/src/Test/NodeTestCase.php
|
||||
opt/app/vendor/twig/twig/src/Token.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/AbstractTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/AutoEscapeTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/BlockTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/DoTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/EmbedTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/ExtendsTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/FilterTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/FlushTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/ForTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/FromTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/IfTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/ImportTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/IncludeTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/MacroTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/SandboxTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/SetTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/SpacelessTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/TokenParserInterface.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/UseTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenParser/WithTokenParser.php
|
||||
opt/app/vendor/twig/twig/src/TokenStream.php
|
||||
opt/app/vendor/twig/twig/src/TwigFilter.php
|
||||
opt/app/vendor/twig/twig/src/TwigFunction.php
|
||||
opt/app/vendor/twig/twig/src/TwigTest.php
|
||||
opt/app/vendor/twig/twig/src/Util/DeprecationCollector.php
|
||||
opt/app/vendor/twig/twig/src/Util/TemplateDirIterator.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/AutoloaderTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Cache/FilesystemTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/CompilerTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/ContainerRuntimeLoaderTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/CustomExtensionTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/ErrorTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/ExpressionParserTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Extension/CoreTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/FactoryRuntimeLoaderTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/FileCachingTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/FileExtensionEscapingStrategyTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/FilesystemHelper.php
|
||||
@ -5561,6 +5844,7 @@ opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/default.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/dynamic_filter.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_html_attr.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_javascript.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_non_supported_charset.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/first.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/force_escape.test
|
||||
@ -5751,6 +6035,7 @@ opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/multiple_aliases.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block2.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block3.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/use_with_parent.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/basic.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/mixed_usage_with_raw.test
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/whitespace_control.test
|
||||
@ -5851,12 +6136,11 @@ opt/app/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/BlackfireTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/HtmlTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/TextTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Profiler/ProfileTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/RuntimeFactoryLoaderTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/TemplateTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/TemplateWrapperTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/TokenStreamTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/Util/DeprecationCollectorTest.php
|
||||
opt/app/vendor/twig/twig/test/Twig/Tests/escapingTest.php
|
||||
opt/app/vendor/twig/twig/test/bootstrap.php
|
||||
opt/app/vendor/vlucas/phpdotenv/LICENSE.txt
|
||||
opt/app/vendor/vlucas/phpdotenv/composer.json
|
||||
opt/app/vendor/vlucas/phpdotenv/src/Dotenv.php
|
||||
@ -6010,6 +6294,8 @@ usr/lib/x86_64-linux-gnu/libxml2.so.2
|
||||
usr/lib/x86_64-linux-gnu/libxml2.so.2.9.1
|
||||
usr/lib/x86_64-linux-gnu/libxslt.so.1
|
||||
usr/lib/x86_64-linux-gnu/libxslt.so.1.1.28
|
||||
usr/lib/x86_64-linux-gnu/libzip.so.5
|
||||
usr/lib/x86_64-linux-gnu/libzip.so.5.0.0
|
||||
usr/sbin/mysqld
|
||||
usr/sbin/nginx
|
||||
usr/sbin/php-fpm7.1
|
||||
|
@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
|
||||
manifest = (
|
||||
appTitle = (defaultText = "Firefly III"),
|
||||
appVersion = 5,
|
||||
appMarketingVersion = (defaultText = "4.6.11.1"),
|
||||
appVersion = 6,
|
||||
appMarketingVersion = (defaultText = "4.6.12"),
|
||||
|
||||
actions = [
|
||||
# Define your "new document" handlers here.
|
||||
@ -41,7 +41,7 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
market = (png = (dpi1x = embed "app-graphics/firefly-iii-150.png"))
|
||||
),
|
||||
|
||||
website = "https://firefly-iii.github.io/",
|
||||
website = "https://firefly-iii.org/",
|
||||
codeUrl = "https://github.com/firefly-iii/firefly-iii",
|
||||
license = (openSource = gpl3),
|
||||
# The license this package is distributed under. See
|
||||
|
@ -1,6 +1,7 @@
|
||||
language: php
|
||||
php:
|
||||
- 7.1
|
||||
- 7.2
|
||||
|
||||
cache:
|
||||
directories:
|
||||
@ -22,7 +23,7 @@ script:
|
||||
- phpunit -c phpunit.coverage.xml
|
||||
|
||||
after_success:
|
||||
- travis_retry php vendor/bin/coveralls -x storage/build/clover-all.xml
|
||||
- travis_retry php vendor/bin/php-coveralls -x storage/build/clover-all.xml
|
||||
|
||||
# safelist
|
||||
branches:
|
||||
|
25
CHANGELOG.md
25
CHANGELOG.md
@ -2,6 +2,31 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
This project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
## [4.6.12] - 2017-12-31
|
||||
### Added
|
||||
- Support for Indonesian.
|
||||
- New report, see [issue 384](https://github.com/firefly-iii/firefly-iii/issues/384)
|
||||
- [Issue 964](https://github.com/firefly-iii/firefly-iii/issues/964) as suggested by [gavu](https://github.com/gavu)
|
||||
|
||||
### Changed
|
||||
- Greatly improved Docker support and documentation.
|
||||
|
||||
### Fixed
|
||||
- [Issue 1046](https://github.com/firefly-iii/firefly-iii/issues/1046), as reported by [pkoziol](https://github.com/pkoziol)
|
||||
- [Issue 1047](https://github.com/firefly-iii/firefly-iii/issues/1047), as reported by [pkoziol](https://github.com/pkoziol)
|
||||
- [Issue 1048](https://github.com/firefly-iii/firefly-iii/issues/1048), as reported by [webence](https://github.com/webence)
|
||||
- [Issue 1049](https://github.com/firefly-iii/firefly-iii/issues/1049), as reported by [nicoschreiner](https://github.com/nicoschreiner)
|
||||
- [Issue 1015](https://github.com/firefly-iii/firefly-iii/issues/1015), as reporterd by a user on Tweakers.net
|
||||
- [Issue 1056](https://github.com/firefly-iii/firefly-iii/issues/1056), as reported by [repercussion](https://github.com/repercussion)
|
||||
- [Issue 1061](https://github.com/firefly-iii/firefly-iii/issues/1061), as reported by [Meizikyn](https://github.com/Meizikyn)
|
||||
- [Issue 1045](https://github.com/firefly-iii/firefly-iii/issues/1045), as reported by [gavu](https://github.com/gavu)
|
||||
- First code for [issue 1040](https://github.com/firefly-iii/firefly-iii/issues/1040) ([simonsmiley](https://github.com/simonsmiley))
|
||||
- [Issue 1059](https://github.com/firefly-iii/firefly-iii/issues/1059), as reported by [4oo4](https://github.com/4oo4)
|
||||
- [Issue 1063](https://github.com/firefly-iii/firefly-iii/issues/1063), as reported by [pkoziol](https://github.com/pkoziol)
|
||||
- [Issue 1064](https://github.com/firefly-iii/firefly-iii/issues/1064), as reported by [pkoziol](https://github.com/pkoziol)
|
||||
- [Issue 1066](https://github.com/firefly-iii/firefly-iii/issues/1066), reported by [wtercato](https://github.com/wtercato)
|
||||
|
||||
|
||||
## [4.6.11.1] - 2017-12-08
|
||||
### Added
|
||||
- Import routine can scan for matching bills, [issue 956](https://github.com/firefly-iii/firefly-iii/issues/956)
|
||||
|
31
Dockerfile
31
Dockerfile
@ -1,5 +1,12 @@
|
||||
# use PHP 7.1 and Apache as a base.
|
||||
FROM php:7.1-apache
|
||||
|
||||
# set working dir
|
||||
ENV FIREFLY_PATH /var/www/firefly-iii
|
||||
WORKDIR $FIREFLY_PATH
|
||||
ADD . $FIREFLY_PATH
|
||||
|
||||
# install packages
|
||||
RUN apt-get update -y && \
|
||||
apt-get install -y --no-install-recommends libcurl4-openssl-dev \
|
||||
zlib1g-dev \
|
||||
@ -17,11 +24,13 @@ RUN apt-get update -y && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install PHP exentions.
|
||||
RUN docker-php-ext-install -j$(nproc) curl gd intl json readline tidy zip bcmath xml mbstring pdo_sqlite pdo_mysql bz2 pdo_pgsql
|
||||
|
||||
# Generate locales supported by firefly
|
||||
RUN echo "en_US.UTF-8 UTF-8\nde_DE.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8" > /etc/locale.gen && locale-gen
|
||||
# Generate locales supported by Firefly III
|
||||
RUN echo "de_DE.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nid_ID.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8" > /etc/locale.gen && locale-gen
|
||||
|
||||
# copy Apache config to correct spot.
|
||||
COPY ./docker/apache2.conf /etc/apache2/apache2.conf
|
||||
|
||||
# Enable apache mod rewrite..
|
||||
@ -30,23 +39,23 @@ RUN a2enmod rewrite
|
||||
# Enable apache mod ssl..
|
||||
RUN a2enmod ssl
|
||||
|
||||
# Create volumes for several directories:
|
||||
VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload
|
||||
|
||||
# Setup the Composer installer
|
||||
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
# Copy Apache Configs
|
||||
# Enable default site (Firefly III)
|
||||
COPY ./docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
|
||||
|
||||
ENV FIREFLY_PATH /var/www/firefly-iii
|
||||
|
||||
WORKDIR $FIREFLY_PATH
|
||||
|
||||
# The working directory
|
||||
COPY . $FIREFLY_PATH
|
||||
|
||||
# Make sure we own Firefly III directory
|
||||
RUN chown -R www-data:www-data /var/www && chmod -R 775 $FIREFLY_PATH/storage
|
||||
|
||||
RUN composer install --prefer-dist --no-dev --no-scripts
|
||||
# Run composer
|
||||
RUN composer install --prefer-dist --no-dev --no-scripts --no-suggest
|
||||
|
||||
# Expose port 80
|
||||
EXPOSE 80
|
||||
|
||||
# Run entrypoint thing
|
||||
ENTRYPOINT ["docker/entrypoint.sh"]
|
22
README.md
22
README.md
@ -2,9 +2,11 @@
|
||||
|
||||
[](https://secure.php.net/downloads.php) [](https://packagist.org/packages/grumpydictator/firefly-iii) [](https://www.gnu.org/licenses/gpl.html) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA)
|
||||
|
||||
[](https://i.nder.be/h327vx3y) [](https://i.nder.be/hkpynqr9)
|
||||
[](https://firefly-iii.org/static/screenshots/4.6.12/index.png) [](https://firefly-iii.org/static/screenshots/4.6.12/account.png)
|
||||
|
||||
[](https://i.nder.be/cwznmryd) [](https://i.nder.be/gum2qf8z)
|
||||
[](https://firefly-iii.org/static/screenshots/4.6.12/budget.png) [](https://firefly-iii.org/static/screenshots/4.6.12/category.png)
|
||||
|
||||
[](https://firefly-iii.org/static/screenshots/4.6.12/report1.png) [](https://firefly-iii.org/static/screenshots/4.6.12/report2.png)
|
||||
|
||||
"Firefly III" is a financial manager for your personal finances. It can help you keep track of your expenses and income.
|
||||
Firefly III supports the use of budgets. You can categorize and tag your transactions.
|
||||
@ -13,17 +15,17 @@ There are many financial reports available.
|
||||
|
||||
## Want to try Firefly III?
|
||||
|
||||
There is a **[demo site](https://firefly-iii.nder.be)** with an example financial administration already present. You can use Docker, Heroku or Sandstorm.io (see below) to quickly setup your own instance.
|
||||
There is a **[demo site](https://demo.firefly-iii.org)** with an example financial administration already present. You can use Docker, Heroku or Sandstorm.io (see below) to quickly setup your own instance.
|
||||
|
||||
## Install Firefly III
|
||||
|
||||
### Using docker
|
||||
|
||||
You can use docker-compose to [set up your personal secure](https://firefly-iii.github.io/using-docker.html) Firefly III environment. Advanced users can use the Dockerfile directly.
|
||||
You can use docker-compose to [set up your personal secure](https://firefly-iii.org/using-docker.html) Firefly III environment. Advanced users can use the Dockerfile directly.
|
||||
|
||||
### Using vagrant (or other VMs)
|
||||
|
||||
You can install Firefly III on any Linux or Windows machine. You'll need a web server (preferrably on Linux) and access to the command line. Please read the [installation guide](https://firefly-iii.github.io/using-installing.html).
|
||||
You can install Firefly III on any Linux or Windows machine. You'll need a web server (preferrably on Linux) and access to the command line. Please read the [installation guide](https://firefly-iii.org/using-installing.html).
|
||||
|
||||
### Using Heroku
|
||||
|
||||
@ -31,8 +33,6 @@ You can install Firefly III on any Linux or Windows machine. You'll need a web s
|
||||
|
||||
Register for a free Heroku account and instantly run Firefly III on your very own cloud instance.
|
||||
|
||||
_My Heroku configuration is currently broken, but I'm trying to fix it._
|
||||
|
||||
### Using Sandstorm.io
|
||||
|
||||
You can find Firefly III in [the Sandstorm.io marketplace](https://apps.sandstorm.io/app/uws252ya9mep4t77tevn85333xzsgrpgth8q4y1rhknn1hammw70). You can run it on your own installation or on Oasis.
|
||||
@ -53,7 +53,7 @@ Firefly works on the principle that if you know where you're money is going, you
|
||||
- If you feel you're missing something you can just ask me and I'll add it!
|
||||
|
||||
Firefly III has become pretty awesome over the years! (but please excuse me for bragging, it's just that I'm proud of it).
|
||||
[You can read more about Firefly III, and its features, on the Github Pages](https://firefly-iii.github.io/).
|
||||
[You can read more about Firefly III, and its features, on the website](https://firefly-iii.org/).
|
||||
|
||||
### Contributing
|
||||
|
||||
@ -74,8 +74,12 @@ This work [is licensed](https://github.com/firefly-iii/firefly-iii/blob/master/L
|
||||
|
||||
### Other stuff
|
||||
|
||||
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 like Firefly III 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).
|
||||
|
||||
### Alternatives
|
||||
|
||||
If you are looking for alternatives, check out [Kickball's Awesome-Selfhosted list](https://github.com/Kickball/awesome-selfhosted) which features not only Firefly III but also noteworthy alternatives such as [Silverstrike](https://github.com/agstrike/silverstrike).
|
||||
|
||||
[](https://travis-ci.org/firefly-iii/firefly-iii) [](https://scrutinizer-ci.com/g/firefly-iii/firefly-iii/?branch=master) [](https://coveralls.io/github/firefly-iii/firefly-iii?branch=master)
|
||||
|
2
app.json
2
app.json
@ -2,7 +2,7 @@
|
||||
"name": "Firefly III",
|
||||
"description": "A free and open source personal finances manager",
|
||||
"repository": "https://github.com/firefly-iii/firefly-iii",
|
||||
"website": "https://firefly-iii.github.io/",
|
||||
"website": "https://firefly-iii.org/",
|
||||
"logo": "https://raw.githubusercontent.com/firefly-iii/firefly-iii/master/public/mstile-150x150.png",
|
||||
"keywords": [
|
||||
"finance",
|
||||
|
@ -23,8 +23,9 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Artisan;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Import\Logging\CommandHandler;
|
||||
use FireflyIII\Import\Routine\ImportRoutine;
|
||||
use FireflyIII\Import\Routine\RoutineInterface;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Illuminate\Console\Command;
|
||||
@ -54,7 +55,7 @@ class CreateImport extends Command
|
||||
protected $signature
|
||||
= 'firefly:create-import
|
||||
{file : The file to import.}
|
||||
{configuration : The configuration file to use for the import/}
|
||||
{configuration : The configuration file to use for the import.}
|
||||
{--type=csv : The file type of the import.}
|
||||
{--user= : The user ID that the import should import for.}
|
||||
{--token= : The user\'s access token.}
|
||||
@ -73,6 +74,8 @@ class CreateImport extends Command
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@ -93,7 +96,7 @@ class CreateImport extends Command
|
||||
return;
|
||||
}
|
||||
|
||||
$configurationData = json_decode(file_get_contents($configuration));
|
||||
$configurationData = json_decode(file_get_contents($configuration), true);
|
||||
if (null === $configurationData) {
|
||||
$this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd));
|
||||
|
||||
@ -114,9 +117,8 @@ class CreateImport extends Command
|
||||
Artisan::call('firefly:encrypt-file', ['file' => $file, 'key' => $job->key]);
|
||||
$this->line('Stored import data...');
|
||||
|
||||
$job->configuration = $configurationData;
|
||||
$job->status = 'configured';
|
||||
$job->save();
|
||||
$jobRepository->setConfiguration($job, $configurationData);
|
||||
$jobRepository->updateStatus($job, 'configured');
|
||||
$this->line('Stored configuration...');
|
||||
|
||||
if (true === $this->option('start')) {
|
||||
@ -131,18 +133,26 @@ class CreateImport extends Command
|
||||
$monolog->pushHandler($handler);
|
||||
|
||||
// start the actual routine:
|
||||
/** @var ImportRoutine $routine */
|
||||
$routine = app(ImportRoutine::class);
|
||||
$type = 'csv' === $job->file_type ? 'file' : $job->file_type;
|
||||
$key = sprintf('import.routine.%s', $type);
|
||||
$className = config($key);
|
||||
if (null === $className || !class_exists($className)) {
|
||||
throw new FireflyException(sprintf('Cannot find import routine class for job of type "%s".', $type)); // @codeCoverageIgnore
|
||||
}
|
||||
/** @var RoutineInterface $routine */
|
||||
$routine = app($className);
|
||||
$routine->setJob($job);
|
||||
$routine->run();
|
||||
|
||||
// give feedback.
|
||||
/** @var MessageBag $error */
|
||||
foreach ($routine->errors as $index => $error) {
|
||||
foreach ($routine->getErrors() as $index => $error) {
|
||||
$this->error(sprintf('Error importing line #%d: %s', $index, $error));
|
||||
}
|
||||
$this->line(
|
||||
sprintf('The import has finished. %d transactions have been imported out of %d records.', $routine->journals->count(), $routine->lines)
|
||||
sprintf(
|
||||
'The import has finished. %d transactions have been imported out of %d records.', $routine->getJournals()->count(), $routine->getLines()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -166,7 +176,7 @@ class CreateImport extends Command
|
||||
$configuration = $this->argument('configuration');
|
||||
$user = $userRepository->find(intval($this->option('user')));
|
||||
$cwd = getcwd();
|
||||
$validTypes = array_keys(config('firefly.import_formats'));
|
||||
$validTypes = config('import.options.file.import_formats');
|
||||
$type = strtolower($this->option('type'));
|
||||
if (null === $user->id) {
|
||||
$this->error(sprintf('There is no user with ID %d.', $this->option('user')));
|
||||
|
@ -22,8 +22,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Import\Logging\CommandHandler;
|
||||
use FireflyIII\Import\Routine\ImportRoutine;
|
||||
use FireflyIII\Import\Routine\RoutineInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\MessageBag;
|
||||
@ -58,6 +59,8 @@ class Import extends Command
|
||||
|
||||
/**
|
||||
* Run the import routine.
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@ -81,17 +84,27 @@ class Import extends Command
|
||||
$handler = new CommandHandler($this);
|
||||
$monolog->pushHandler($handler);
|
||||
|
||||
/** @var ImportRoutine $routine */
|
||||
$routine = app(ImportRoutine::class);
|
||||
// actually start job:
|
||||
$type = 'csv' === $job->file_type ? 'file' : $job->file_type;
|
||||
$key = sprintf('import.routine.%s', $type);
|
||||
$className = config($key);
|
||||
if (null === $className || !class_exists($className)) {
|
||||
throw new FireflyException(sprintf('Cannot find import routine class for job of type "%s".', $type)); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/** @var RoutineInterface $routine */
|
||||
$routine = app($className);
|
||||
$routine->setJob($job);
|
||||
$routine->run();
|
||||
|
||||
/** @var MessageBag $error */
|
||||
foreach ($routine->errors as $index => $error) {
|
||||
foreach ($routine->getErrors() as $index => $error) {
|
||||
$this->error(sprintf('Error importing line #%d: %s', $index, $error));
|
||||
}
|
||||
|
||||
$this->line(sprintf('The import has finished. %d transactions have been imported out of %d records.', $routine->journals->count(), $routine->lines));
|
||||
$this->line(
|
||||
sprintf('The import has finished. %d transactions have been imported out of %d records.', $routine->getJournals()->count(), $routine->getLines())
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -26,8 +26,6 @@ use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\BudgetLimit;
|
||||
use FireflyIII\Models\LimitRepetition;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionCurrency;
|
||||
@ -75,6 +73,8 @@ class UpgradeDatabase extends Command
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@ -282,6 +282,8 @@ class UpgradeDatabase extends Command
|
||||
|
||||
/**
|
||||
* Move all the journal_meta notes to their note object counter parts.
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function migrateNotes(): void
|
||||
{
|
||||
|
@ -21,14 +21,6 @@
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* UseEncryption.php
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
@ -65,6 +57,12 @@ class UseEncryption extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if (config('firefly.encryption') === true) {
|
||||
$this->info('Firefly III configuration calls for encrypted data.');
|
||||
}
|
||||
if (config('firefly.encryption') === false) {
|
||||
$this->info('Firefly III configuration calls for unencrypted data.');
|
||||
}
|
||||
$this->handleObjects('Account', 'name', 'encrypted');
|
||||
$this->handleObjects('Bill', 'name', 'name_encrypted');
|
||||
$this->handleObjects('Bill', 'match', 'match_encrypted');
|
||||
@ -84,7 +82,7 @@ class UseEncryption extends Command
|
||||
public function handleObjects(string $class, string $field, string $indicator)
|
||||
{
|
||||
$fqn = sprintf('FireflyIII\Models\%s', $class);
|
||||
$encrypt = config('firefly.encryption') ? 0 : 1;
|
||||
$encrypt = config('firefly.encryption') === true ? 0 : 1;
|
||||
$set = $fqn::where($indicator, $encrypt)->get();
|
||||
|
||||
foreach ($set as $entry) {
|
||||
|
@ -68,6 +68,7 @@ trait VerifiesAccessToken
|
||||
}
|
||||
if (!($accessToken->data === $token)) {
|
||||
Log::error(sprintf('Invalid access token for user #%d.', $userId));
|
||||
Log::error(sprintf('Token given is "%s", expected "%s".', $token, $accessToken->data));
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Console\Commands;
|
||||
|
||||
use Crypt;
|
||||
use DB;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Budget;
|
||||
@ -93,6 +94,7 @@ class VerifyDatabase extends Command
|
||||
$this->repairPiggyBanks();
|
||||
$this->createLinkTypes();
|
||||
$this->createAccessTokens();
|
||||
$this->fixDoubleAmounts();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -100,6 +102,7 @@ class VerifyDatabase extends Command
|
||||
*/
|
||||
private function createAccessTokens()
|
||||
{
|
||||
$count = 0;
|
||||
$users = User::get();
|
||||
/** @var User $user */
|
||||
foreach ($users as $user) {
|
||||
@ -108,8 +111,12 @@ class VerifyDatabase extends Command
|
||||
$token = $user->generateAccessToken();
|
||||
Preferences::setForUser($user, 'access_token', $token);
|
||||
$this->line(sprintf('Generated access token for user %s', $user->email));
|
||||
++$count;
|
||||
}
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('All access tokens OK!');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,6 +124,7 @@ class VerifyDatabase extends Command
|
||||
*/
|
||||
private function createLinkTypes()
|
||||
{
|
||||
$count = 0;
|
||||
$set = [
|
||||
'Related' => ['relates to', 'relates to'],
|
||||
'Refund' => ['(partially) refunds', 'is (partially) refunded by'],
|
||||
@ -130,10 +138,64 @@ class VerifyDatabase extends Command
|
||||
$link->name = $name;
|
||||
$link->outward = $values[0];
|
||||
$link->inward = $values[1];
|
||||
++$count;
|
||||
}
|
||||
$link->editable = false;
|
||||
$link->save();
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('All link types OK!');
|
||||
}
|
||||
}
|
||||
|
||||
private function fixDoubleAmounts()
|
||||
{
|
||||
$count = 0;
|
||||
// get invalid journals
|
||||
$errored = [];
|
||||
$journals = DB::table('transactions')
|
||||
->groupBy('transaction_journal_id')
|
||||
->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')]);
|
||||
/** @var stdClass $entry */
|
||||
foreach ($journals as $entry) {
|
||||
if (0 !== bccomp(strval($entry->the_sum), '0')) {
|
||||
$errored[] = $entry->transaction_journal_id;
|
||||
}
|
||||
}
|
||||
foreach ($errored as $journalId) {
|
||||
// select and update:
|
||||
$res = Transaction::whereNull('deleted_at')->where('transaction_journal_id', $journalId)->groupBy('amount')->get([DB::raw('MIN(id) as first_id')]);
|
||||
$ids = $res->pluck('first_id')->toArray();
|
||||
DB::table('transactions')->whereIn('id', $ids)->update(['amount' => DB::raw('amount * -1')]);
|
||||
++$count;
|
||||
// report about it
|
||||
/** @var TransactionJournal $journal */
|
||||
$journal = TransactionJournal::find($journalId);
|
||||
if (is_null($journal)) {
|
||||
continue;
|
||||
}
|
||||
if (TransactionType::OPENING_BALANCE === $journal->transactionType->type) {
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Transaction #%d was stored incorrectly. One of your asset accounts may show the wrong balance. Please visit /transactions/show/%d to verify the opening balance.',
|
||||
$journalId, $journalId
|
||||
)
|
||||
);
|
||||
}
|
||||
if (TransactionType::OPENING_BALANCE !== $journal->transactionType->type) {
|
||||
$this->error(
|
||||
sprintf(
|
||||
'Transaction #%d was stored incorrectly. Could be that the transaction shows the wrong amount. Please visit /transactions/show/%d to verify the opening balance.',
|
||||
$journalId, $journalId
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('Amount integrity OK!');
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -290,6 +352,7 @@ class VerifyDatabase extends Command
|
||||
*/
|
||||
private function reportJournals()
|
||||
{
|
||||
$count = 0;
|
||||
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->whereNotNull('transaction_journals.deleted_at')// USE THIS
|
||||
->whereNull('transactions.deleted_at')
|
||||
@ -308,6 +371,10 @@ class VerifyDatabase extends Command
|
||||
'Error: Transaction #' . $entry->transaction_id . ' should have been deleted, but has not.' .
|
||||
' Find it in the table called "transactions" and change the "deleted_at" field to: "' . $entry->journal_deleted . '"'
|
||||
);
|
||||
++$count;
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('No orphaned transactions!');
|
||||
}
|
||||
}
|
||||
|
||||
@ -316,6 +383,7 @@ class VerifyDatabase extends Command
|
||||
*/
|
||||
private function reportNoTransactions()
|
||||
{
|
||||
$count = 0;
|
||||
$set = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
|
||||
->groupBy('transaction_journals.id')
|
||||
->whereNull('transactions.transaction_journal_id')
|
||||
@ -325,6 +393,10 @@ class VerifyDatabase extends Command
|
||||
$this->error(
|
||||
'Error: Journal #' . $entry->id . ' has zero transactions. Open table "transaction_journals" and delete the entry with id #' . $entry->id
|
||||
);
|
||||
++$count;
|
||||
}
|
||||
if (0 === $count) {
|
||||
$this->info('No orphaned journals!');
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,6 +451,8 @@ class VerifyDatabase extends Command
|
||||
$sum = strval($user->transactions()->sum('amount'));
|
||||
if (0 !== bccomp($sum, '0')) {
|
||||
$this->error('Error: Transactions for user #' . $user->id . ' (' . $user->email . ') are off by ' . $sum . '!');
|
||||
} else {
|
||||
$this->info(sprintf('Amount integrity OK for user #%d', $user->id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,15 +20,6 @@
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Kernel.php
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Console;
|
||||
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
|
@ -33,7 +33,13 @@ class AdminRequestedTestMessage extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $ipAddress;
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,13 @@ class RegisteredUser extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $ipAddress;
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
|
@ -32,8 +32,17 @@ class RequestedNewPassword extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $ipAddress;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $token;
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
|
52
app/Events/RequestedVersionCheckStatus.php
Normal file
52
app/Events/RequestedVersionCheckStatus.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/**
|
||||
* RequestedVersionCheckStatus.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Events;
|
||||
|
||||
use FireflyIII\User;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
|
||||
/**
|
||||
* Class RequestedVersionCheckStatus
|
||||
*/
|
||||
class RequestedVersionCheckStatus extends Event
|
||||
{
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* Create a new event instance. This event is triggered when Firefly III wants to know
|
||||
* what the deal is with the version checker.
|
||||
*
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
}
|
@ -20,15 +20,6 @@
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Handler.php
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Exceptions;
|
||||
|
||||
use ErrorException;
|
||||
@ -37,6 +28,9 @@ use FireflyIII\Jobs\MailError;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Request;
|
||||
|
||||
/**
|
||||
* Class Handler
|
||||
*/
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
@ -87,6 +81,8 @@ class Handler extends ExceptionHandler
|
||||
* @param \Exception $exception
|
||||
*
|
||||
* @return mixed|void
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function report(Exception $exception)
|
||||
{
|
||||
|
@ -45,44 +45,131 @@ use FireflyIII\Models\Transaction;
|
||||
final class Entry
|
||||
{
|
||||
// @formatter:off
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $journal_id;
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $transaction_id = 0;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $date;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $description;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $currency_code;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $amount;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $foreign_currency_code = '';
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $foreign_amount = '0';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $transaction_type;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $asset_account_id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $asset_account_name;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $asset_account_iban;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $asset_account_bic;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $asset_account_number;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $asset_currency_code;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $opposing_account_id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $opposing_account_name;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $opposing_account_iban;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $opposing_account_bic;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $opposing_account_number;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $opposing_currency_code;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $budget_id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $budget_name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $category_id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $category_name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $bill_id;
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $bill_name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $notes;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $tags;
|
||||
|
||||
|
||||
@ -116,7 +203,7 @@ final class Entry
|
||||
$entry->description = $transaction->transaction_description . '(' . $transaction->description . ')';
|
||||
}
|
||||
$entry->currency_code = $transaction->transactionCurrency->code;
|
||||
$entry->amount = round($transaction->transaction_amount, $transaction->transactionCurrency->decimal_places);
|
||||
$entry->amount = strval(round($transaction->transaction_amount, $transaction->transactionCurrency->decimal_places));
|
||||
|
||||
$entry->foreign_currency_code = null === $transaction->foreign_currency_id ? null : $transaction->foreignCurrency->code;
|
||||
$entry->foreign_amount = null === $transaction->foreign_currency_id
|
||||
@ -129,14 +216,14 @@ final class Entry
|
||||
);
|
||||
|
||||
$entry->transaction_type = $transaction->transaction_type_type;
|
||||
$entry->asset_account_id = $transaction->account_id;
|
||||
$entry->asset_account_id = strval($transaction->account_id);
|
||||
$entry->asset_account_name = app('steam')->tryDecrypt($transaction->account_name);
|
||||
$entry->asset_account_iban = $transaction->account_iban;
|
||||
$entry->asset_account_number = $transaction->account_number;
|
||||
$entry->asset_account_bic = $transaction->account_bic;
|
||||
$entry->asset_currency_code = $transaction->account_currency_code;
|
||||
|
||||
$entry->opposing_account_id = $transaction->opposing_account_id;
|
||||
$entry->opposing_account_id = strval($transaction->opposing_account_id);
|
||||
$entry->opposing_account_name = app('steam')->tryDecrypt($transaction->opposing_account_name);
|
||||
$entry->opposing_account_iban = $transaction->opposing_account_iban;
|
||||
$entry->opposing_account_number = $transaction->opposing_account_number;
|
||||
@ -144,7 +231,7 @@ final class Entry
|
||||
$entry->opposing_currency_code = $transaction->opposing_currency_code;
|
||||
|
||||
// budget
|
||||
$entry->budget_id = $transaction->transaction_budget_id;
|
||||
$entry->budget_id = strval($transaction->transaction_budget_id);
|
||||
$entry->budget_name = app('steam')->tryDecrypt($transaction->transaction_budget_name);
|
||||
if (null === $transaction->transaction_budget_id) {
|
||||
$entry->budget_id = $transaction->transaction_journal_budget_id;
|
||||
@ -152,7 +239,7 @@ final class Entry
|
||||
}
|
||||
|
||||
// category
|
||||
$entry->category_id = $transaction->transaction_category_id;
|
||||
$entry->category_id = strval($transaction->transaction_category_id);
|
||||
$entry->category_name = app('steam')->tryDecrypt($transaction->transaction_category_name);
|
||||
if (null === $transaction->transaction_category_id) {
|
||||
$entry->category_id = $transaction->transaction_journal_category_id;
|
||||
@ -160,7 +247,7 @@ final class Entry
|
||||
}
|
||||
|
||||
// budget
|
||||
$entry->bill_id = $transaction->bill_id;
|
||||
$entry->bill_id = strval($transaction->bill_id);
|
||||
$entry->bill_name = app('steam')->tryDecrypt($transaction->bill_name);
|
||||
|
||||
$entry->tags = $transaction->tags;
|
||||
|
@ -32,8 +32,8 @@ use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Helpers\Filter\InternalTransferFilter;
|
||||
use FireflyIII\Models\AccountMeta;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionJournalMeta;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
@ -114,7 +114,7 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
$notes = $this->getNotes($ids);
|
||||
$tags = $this->getTags($ids);
|
||||
/** @var array $ibans */
|
||||
$ibans = $this->getIbans($assetIds) + $this->getIbans($opposingIds);
|
||||
$ibans = array_merge($this->getIbans($assetIds), $this->getIbans($opposingIds));
|
||||
$currencies = $this->getAccountCurrencies($ibans);
|
||||
$transactions->each(
|
||||
function (Transaction $transaction) use ($notes, $tags, $ibans, $currencies) {
|
||||
@ -173,6 +173,7 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
* @return bool
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function createZipFile(): bool
|
||||
{
|
||||
@ -309,17 +310,16 @@ class ExpandedProcessor implements ProcessorInterface
|
||||
private function getNotes(array $array): array
|
||||
{
|
||||
$array = array_unique($array);
|
||||
$set = TransactionJournalMeta::whereIn('journal_meta.transaction_journal_id', $array)
|
||||
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id')
|
||||
->where('transaction_journals.user_id', $this->job->user_id)
|
||||
->where('journal_meta.name', 'notes')->get(
|
||||
['journal_meta.transaction_journal_id', 'journal_meta.data', 'journal_meta.id']
|
||||
);
|
||||
$notes = Note::where('notes.noteable_type', 'FireflyIII\\Models\\TransactionJournal')
|
||||
->whereIn('notes.noteable_id', $array)
|
||||
->get(['notes.*']);
|
||||
$return = [];
|
||||
/** @var TransactionJournalMeta $meta */
|
||||
foreach ($set as $meta) {
|
||||
$id = intval($meta->transaction_journal_id);
|
||||
$return[$id] = $meta->data;
|
||||
/** @var Note $note */
|
||||
foreach ($notes as $note) {
|
||||
if (strlen(trim(strval($note->text))) > 0) {
|
||||
$id = intval($note->noteable_id);
|
||||
$return[$id] = $note->text;
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
|
@ -24,7 +24,7 @@ namespace FireflyIII\Export\Exporter;
|
||||
|
||||
use FireflyIII\Export\Entry\Entry;
|
||||
use League\Csv\Writer;
|
||||
use SplFileObject;
|
||||
use Storage;
|
||||
|
||||
/**
|
||||
* Class CsvExporter.
|
||||
@ -52,6 +52,8 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*
|
||||
* @throws \TypeError
|
||||
*/
|
||||
public function run(): bool
|
||||
{
|
||||
@ -60,7 +62,10 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
|
||||
// necessary for CSV writer:
|
||||
$fullPath = storage_path('export') . DIRECTORY_SEPARATOR . $this->fileName;
|
||||
$writer = Writer::createFromPath(new SplFileObject($fullPath, 'a+'), 'w');
|
||||
|
||||
|
||||
//we create the CSV into memory
|
||||
$writer = Writer::createFromPath($fullPath);
|
||||
$rows = [];
|
||||
|
||||
// get field names for header row:
|
||||
@ -88,5 +93,8 @@ class CsvExporter extends BasicExporter implements ExporterInterface
|
||||
private function tempFile()
|
||||
{
|
||||
$this->fileName = $this->job->key . '-records.csv';
|
||||
// touch file in export directory:
|
||||
$disk = Storage::disk('export');
|
||||
$disk->put($this->fileName, '');
|
||||
}
|
||||
}
|
||||
|
146
app/Generator/Report/Account/MonthReportGenerator.php
Normal file
146
app/Generator/Report/Account/MonthReportGenerator.php
Normal file
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* MonthReportGenerator.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Account;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Generator\Report\ReportGeneratorInterface;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class MonthReportGenerator.
|
||||
*/
|
||||
class MonthReportGenerator implements ReportGeneratorInterface
|
||||
{
|
||||
/** @var Collection */
|
||||
private $accounts;
|
||||
/** @var Carbon */
|
||||
private $end;
|
||||
/** @var Collection */
|
||||
private $expense;
|
||||
/** @var Carbon */
|
||||
private $start;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function generate(): string
|
||||
{
|
||||
$accountIds = join(',', $this->accounts->pluck('id')->toArray());
|
||||
$expenseIds = join(',', $this->expense->pluck('id')->toArray());
|
||||
$reportType = 'account';
|
||||
$preferredPeriod = $this->preferredPeriod();
|
||||
|
||||
return view(
|
||||
'reports.account.report',
|
||||
compact('accountIds', 'reportType', 'expenseIds', 'preferredPeriod')
|
||||
)->with('start', $this->start)->with('end', $this->end)->render();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setAccounts(Collection $accounts): ReportGeneratorInterface
|
||||
{
|
||||
$this->accounts = $accounts;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $budgets
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setBudgets(Collection $budgets): ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $categories
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setCategories(Collection $categories): ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setEndDate(Carbon $date): ReportGeneratorInterface
|
||||
{
|
||||
$this->end = $date;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setExpense(Collection $expense): ReportGeneratorInterface
|
||||
{
|
||||
$this->expense = $expense;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setStartDate(Carbon $date): ReportGeneratorInterface
|
||||
{
|
||||
$this->start = $date;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $tags
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setTags(Collection $tags): ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function preferredPeriod(): string
|
||||
{
|
||||
return 'day';
|
||||
}
|
||||
}
|
39
app/Generator/Report/Account/MultiYearReportGenerator.php
Normal file
39
app/Generator/Report/Account/MultiYearReportGenerator.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* MultiYearReportGenerator.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Account;
|
||||
|
||||
/**
|
||||
* Class MultiYearReportGenerator.
|
||||
*/
|
||||
class MultiYearReportGenerator extends MonthReportGenerator
|
||||
{
|
||||
// Doesn't do anything different.
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function preferredPeriod(): string
|
||||
{
|
||||
return 'year';
|
||||
}
|
||||
}
|
39
app/Generator/Report/Account/YearReportGenerator.php
Normal file
39
app/Generator/Report/Account/YearReportGenerator.php
Normal file
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* YearReportGenerator.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Generator\Report\Account;
|
||||
|
||||
/**
|
||||
* Class YearReportGenerator.
|
||||
*/
|
||||
class YearReportGenerator extends MonthReportGenerator
|
||||
{
|
||||
// Doesn't do anything different.
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected function preferredPeriod(): string
|
||||
{
|
||||
return 'month';
|
||||
}
|
||||
}
|
@ -119,6 +119,16 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setExpense(Collection $expense): ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
|
@ -128,6 +128,16 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setExpense(Collection $expense): ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
|
@ -146,6 +146,16 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setExpense(Collection $expense): ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
|
@ -63,6 +63,13 @@ interface ReportGeneratorInterface
|
||||
*/
|
||||
public function setEndDate(Carbon $date): ReportGeneratorInterface;
|
||||
|
||||
/**
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setExpense(Collection $expense): ReportGeneratorInterface;
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
|
@ -41,6 +41,8 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function generate(): string
|
||||
{
|
||||
@ -101,6 +103,16 @@ class MonthReportGenerator implements ReportGeneratorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setExpense(Collection $expense): ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
|
@ -40,6 +40,8 @@ class MultiYearReportGenerator implements ReportGeneratorInterface
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function generate(): string
|
||||
{
|
||||
@ -98,6 +100,16 @@ class MultiYearReportGenerator implements ReportGeneratorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setExpense(Collection $expense): ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
|
@ -40,6 +40,8 @@ class YearReportGenerator implements ReportGeneratorInterface
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function generate(): string
|
||||
{
|
||||
@ -98,6 +100,16 @@ class YearReportGenerator implements ReportGeneratorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setExpense(Collection $expense): ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
|
@ -65,6 +65,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function generate(): string
|
||||
{
|
||||
@ -141,6 +142,16 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $expense
|
||||
*
|
||||
* @return ReportGeneratorInterface
|
||||
*/
|
||||
public function setExpense(Collection $expense): ReportGeneratorInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $date
|
||||
*
|
||||
|
@ -76,6 +76,7 @@ class UserEventHandler
|
||||
{
|
||||
Log::debug('In checkSingleUserIsAdmin');
|
||||
|
||||
/** @var User $user */
|
||||
$user = $event->user;
|
||||
$count = User::count();
|
||||
|
||||
@ -86,7 +87,7 @@ class UserEventHandler
|
||||
return true;
|
||||
}
|
||||
// user is only user but has admin role
|
||||
if ($count === 1 && $user->hasRole('owner')) {
|
||||
if (1 === $count && $user->hasRole('owner')) {
|
||||
Log::debug(sprintf('User #%d is only user but has role owner so all is well.', $user->id));
|
||||
|
||||
return true;
|
||||
|
78
app/Handlers/Events/VersionCheckEventHandler.php
Normal file
78
app/Handlers/Events/VersionCheckEventHandler.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* VersionCheckEventHandler.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Handlers\Events;
|
||||
|
||||
use FireflyConfig;
|
||||
use FireflyIII\Events\RequestedVersionCheckStatus;
|
||||
use FireflyIII\User;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class VersionCheckEventHandler
|
||||
*/
|
||||
class VersionCheckEventHandler
|
||||
{
|
||||
|
||||
/**
|
||||
* @param RequestedVersionCheckStatus $event
|
||||
*/
|
||||
public function checkForUpdates(RequestedVersionCheckStatus $event)
|
||||
{
|
||||
// in Sandstorm, cannot check for updates:
|
||||
$sandstorm = 1 === intval(getenv('SANDSTORM'));
|
||||
if ($sandstorm === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var User $user */
|
||||
$user = $event->user;
|
||||
if (!$user->hasRole('owner')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$permission = FireflyConfig::get('permission_update_check', -1);
|
||||
$lastCheckTime = FireflyConfig::get('last_update_check', time());
|
||||
$now = time();
|
||||
if ($now - $lastCheckTime->data < 604800) {
|
||||
Log::debug('Checked for updates less than a week ago.');
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
// last check time was more than a week ago.
|
||||
Log::debug('Have not checked for a new version in a week!');
|
||||
|
||||
// have actual permission?
|
||||
if ($permission->data === -1) {
|
||||
// never asked before.
|
||||
session()->flash('info', strval(trans('firefly.check_for_updates_permission', ['link' => route('admin.update-check')])));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// actually check for update and inform the user.
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -32,8 +32,17 @@ use Illuminate\Support\Collection;
|
||||
*/
|
||||
class BalanceLine
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const ROLE_DEFAULTROLE = 1;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const ROLE_TAGROLE = 2;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const ROLE_DIFFROLE = 3;
|
||||
|
||||
/** @var Collection */
|
||||
|
@ -41,40 +41,14 @@ class BillLine
|
||||
/** @var string */
|
||||
protected $min;
|
||||
/** @var Carbon */
|
||||
private $endOfPayDate;
|
||||
/** @var Carbon */
|
||||
private $lastHitDate;
|
||||
/** @var Carbon */
|
||||
private $payDate;
|
||||
/** @var Carbon */
|
||||
private $endOfPayDate;
|
||||
/** @var int */
|
||||
private $transactionJournalId;
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getPayDate(): Carbon
|
||||
{
|
||||
return $this->payDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getEndOfPayDate(): Carbon
|
||||
{
|
||||
return $this->endOfPayDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $endOfPayDate
|
||||
*/
|
||||
public function setEndOfPayDate(Carbon $endOfPayDate): void
|
||||
{
|
||||
$this->endOfPayDate = $endOfPayDate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* BillLine constructor.
|
||||
*/
|
||||
@ -115,6 +89,22 @@ class BillLine
|
||||
$this->bill = $bill;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getEndOfPayDate(): Carbon
|
||||
{
|
||||
return $this->endOfPayDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $endOfPayDate
|
||||
*/
|
||||
public function setEndOfPayDate(Carbon $endOfPayDate): void
|
||||
{
|
||||
$this->endOfPayDate = $endOfPayDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
@ -163,6 +153,22 @@ class BillLine
|
||||
$this->min = $min;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Carbon
|
||||
*/
|
||||
public function getPayDate(): Carbon
|
||||
{
|
||||
return $this->payDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $payDate
|
||||
*/
|
||||
public function setPayDate(Carbon $payDate): void
|
||||
{
|
||||
$this->payDate = $payDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
@ -202,12 +208,4 @@ class BillLine
|
||||
{
|
||||
$this->hit = $hit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Carbon $payDate
|
||||
*/
|
||||
public function setPayDate(Carbon $payDate): void
|
||||
{
|
||||
$this->payDate = $payDate;
|
||||
}
|
||||
}
|
||||
|
@ -497,6 +497,20 @@ class JournalCollector implements JournalCollectorInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function setOpposingAccounts(Collection $accounts): JournalCollectorInterface
|
||||
{
|
||||
$this->withOpposingAccount();
|
||||
|
||||
$this->query->whereIn('opposing.account_id', $accounts->pluck('id')->toArray());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $page
|
||||
*
|
||||
|
@ -160,6 +160,13 @@ interface JournalCollectorInterface
|
||||
*/
|
||||
public function setOffset(int $offset): JournalCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return JournalCollectorInterface
|
||||
*/
|
||||
public function setOpposingAccounts(Collection $accounts): JournalCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param int $page
|
||||
*
|
||||
@ -196,6 +203,11 @@ interface JournalCollectorInterface
|
||||
*/
|
||||
public function setTypes(array $types): JournalCollectorInterface;
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function setUser(User $user);
|
||||
|
||||
/**
|
||||
|
@ -37,6 +37,11 @@ class AmountFilter implements FilterInterface
|
||||
/** @var int */
|
||||
private $modifier = 0;
|
||||
|
||||
/**
|
||||
* AmountFilter constructor.
|
||||
*
|
||||
* @param int $modifier
|
||||
*/
|
||||
public function __construct(int $modifier)
|
||||
{
|
||||
$this->modifier = $modifier;
|
||||
|
@ -24,6 +24,9 @@ namespace FireflyIII\Helpers\Filter;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Interface FilterInterface
|
||||
*/
|
||||
interface FilterInterface
|
||||
{
|
||||
/**
|
||||
|
@ -34,6 +34,9 @@ use Route;
|
||||
*/
|
||||
class Help implements HelpInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const CACHEKEY = 'help_%s_%s';
|
||||
/** @var string */
|
||||
protected $userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36';
|
||||
|
@ -37,14 +37,13 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class ReconcileController.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
*/
|
||||
class ReconcileController extends Controller
|
||||
@ -59,8 +58,8 @@ class ReconcileController extends Controller
|
||||
// translations:
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('mainTitleIcon', 'fa-credit-card');
|
||||
View::share('title', trans('firefly.accounts'));
|
||||
app('view')->share('mainTitleIcon', 'fa-credit-card');
|
||||
app('view')->share('title', trans('firefly.accounts'));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@ -74,7 +73,7 @@ class ReconcileController extends Controller
|
||||
*/
|
||||
public function edit(TransactionJournal $journal)
|
||||
{
|
||||
if ($journal->transactionType->type !== TransactionType::RECONCILIATION) {
|
||||
if (TransactionType::RECONCILIATION !== $journal->transactionType->type) {
|
||||
return redirect(route('transactions.edit', [$journal->id]));
|
||||
}
|
||||
// view related code
|
||||
@ -90,8 +89,6 @@ class ReconcileController extends Controller
|
||||
];
|
||||
|
||||
Session::flash('preFilled', $preFilled);
|
||||
Session::flash('gaEventCategory', 'transactions');
|
||||
Session::flash('gaEventAction', 'edit-reconciliation');
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('reconcile.edit.fromUpdate')) {
|
||||
@ -103,7 +100,6 @@ class ReconcileController extends Controller
|
||||
'accounts.reconcile.edit',
|
||||
compact('journal', 'subTitle')
|
||||
)->with('data', $preFilled);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,6 +111,7 @@ class ReconcileController extends Controller
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function overview(Request $request, Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -151,7 +148,13 @@ class ReconcileController extends Controller
|
||||
$diffCompare = bccomp($difference, '0');
|
||||
$return = [
|
||||
'post_uri' => $route,
|
||||
'html' => view('accounts.reconcile.overview', compact('account', 'start', 'diffCompare', 'difference', 'end', 'clearedIds', 'transactionIds', 'clearedAmount', 'startBalance', 'endBalance', 'amount', 'route', 'countCleared'))->render(),
|
||||
'html' => view(
|
||||
'accounts.reconcile.overview', compact(
|
||||
'account', 'start', 'diffCompare', 'difference', 'end', 'clearedIds', 'transactionIds', 'clearedAmount',
|
||||
'startBalance', 'endBalance', 'amount',
|
||||
'route', 'countCleared'
|
||||
)
|
||||
)->render(),
|
||||
];
|
||||
|
||||
return Response::json($return);
|
||||
@ -163,6 +166,8 @@ class ReconcileController extends Controller
|
||||
* @param Carbon|null $end
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function reconcile(Account $account, Carbon $start = null, Carbon $end = null)
|
||||
{
|
||||
@ -179,7 +184,7 @@ class ReconcileController extends Controller
|
||||
$currencyId = intval($account->getMeta('currency_id'));
|
||||
$currency = $currencyRepos->find($currencyId);
|
||||
if (0 === $currencyId) {
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
$currency = app('amount')->getDefaultCurrency(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// no start or end:
|
||||
@ -187,11 +192,11 @@ class ReconcileController extends Controller
|
||||
|
||||
// get start and end
|
||||
if (null === $start && null === $end) {
|
||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', app('navigation')->endOfPeriod(new Carbon, $range));
|
||||
}
|
||||
if (null === $end) {
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$end = app('navigation')->endOfPeriod($start, $range);
|
||||
}
|
||||
|
||||
$startDate = clone $start;
|
||||
@ -206,7 +211,12 @@ class ReconcileController extends Controller
|
||||
$overviewUri = route('accounts.reconcile.overview', [$account->id, '%start%', '%end%']);
|
||||
$indexUri = route('accounts.reconcile', [$account->id, '%start%', '%end%']);
|
||||
|
||||
return view('accounts.reconcile.index', compact('account', 'currency', 'subTitleIcon', 'start', 'end', 'subTitle', 'startBalance', 'endBalance', 'transactionsUri', 'overviewUri', 'indexUri'));
|
||||
return view(
|
||||
'accounts.reconcile.index', compact(
|
||||
'account', 'currency', 'subTitleIcon', 'start', 'end', 'subTitle', 'startBalance', 'endBalance', 'transactionsUri',
|
||||
'overviewUri', 'indexUri'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -217,16 +227,16 @@ class ReconcileController extends Controller
|
||||
*/
|
||||
public function show(JournalRepositoryInterface $repository, TransactionJournal $journal)
|
||||
{
|
||||
if ($journal->transactionType->type !== TransactionType::RECONCILIATION) {
|
||||
if (TransactionType::RECONCILIATION !== $journal->transactionType->type) {
|
||||
return redirect(route('transactions.show', [$journal->id]));
|
||||
}
|
||||
$subTitle = trans('firefly.reconciliation') . ' "' . $journal->description . '"';
|
||||
|
||||
// get main transaction:
|
||||
$transaction = $repository->getAssetTransaction($journal);
|
||||
$account = $transaction->account;
|
||||
|
||||
|
||||
return view('accounts.reconcile.show', compact('journal', 'subTitle', 'transaction'));
|
||||
return view('accounts.reconcile.show', compact('journal', 'subTitle', 'transaction', 'account'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -241,7 +251,7 @@ class ReconcileController extends Controller
|
||||
{
|
||||
/** @var JournalRepositoryInterface $repository */
|
||||
$repository = app(JournalRepositoryInterface::class);
|
||||
$transactions = $repository->getTransactionsById($request->get('transactions'));
|
||||
$transactions = $repository->getTransactionsById($request->get('transactions') ?? []);
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($transactions as $transaction) {
|
||||
$repository->reconcile($transaction); // mark as reconciled.
|
||||
@ -287,6 +297,9 @@ class ReconcileController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Throwable
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function transactions(Account $account, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -302,7 +315,7 @@ class ReconcileController extends Controller
|
||||
$currencyId = intval($account->getMeta('currency_id'));
|
||||
$currency = $currencyRepos->find($currencyId);
|
||||
if (0 === $currencyId) {
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
$currency = app('amount')->getDefaultCurrency(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$startBalance = round(app('steam')->balance($account, $startDate), $currency->decimal_places);
|
||||
@ -334,10 +347,10 @@ class ReconcileController extends Controller
|
||||
*/
|
||||
public function update(ReconciliationFormRequest $request, AccountRepositoryInterface $repository, TransactionJournal $journal)
|
||||
{
|
||||
if ($journal->transactionType->type !== TransactionType::RECONCILIATION) {
|
||||
if (TransactionType::RECONCILIATION !== $journal->transactionType->type) {
|
||||
return redirect(route('transactions.show', [$journal->id]));
|
||||
}
|
||||
if (bccomp('0', $request->get('amount')) === 0) {
|
||||
if (0 === bccomp('0', $request->get('amount'))) {
|
||||
Session::flash('error', trans('firefly.amount_cannot_be_zero'));
|
||||
|
||||
return redirect(route('accounts.reconcile.edit', [$journal->id]))->withInput();
|
||||
@ -356,10 +369,8 @@ class ReconcileController extends Controller
|
||||
|
||||
// redirect to previous URL.
|
||||
return redirect($this->getPreviousUri('reconcile.edit.uri'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Account $account
|
||||
*
|
||||
@ -372,7 +383,7 @@ class ReconcileController extends Controller
|
||||
/** @var Transaction $transaction */
|
||||
$transaction = $account->transactions()->first();
|
||||
if (null === $transaction) {
|
||||
throw new FireflyException('Expected a transaction. This account has none. BEEP, error.');
|
||||
throw new FireflyException(sprintf('Expected a transaction. Account #%d has none. BEEP, error.', $account->id)); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$journal = $transaction->transactionJournal;
|
||||
|
@ -36,9 +36,9 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Steam;
|
||||
use View;
|
||||
@ -60,8 +60,8 @@ class AccountController extends Controller
|
||||
// translations:
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('mainTitleIcon', 'fa-credit-card');
|
||||
View::share('title', trans('firefly.accounts'));
|
||||
app('view')->share('mainTitleIcon', 'fa-credit-card');
|
||||
app('view')->share('title', trans('firefly.accounts'));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@ -96,20 +96,17 @@ class AccountController extends Controller
|
||||
$this->rememberPreviousUri('accounts.create.uri');
|
||||
}
|
||||
$request->session()->forget('accounts.create.fromStore');
|
||||
$request->session()->flash('gaEventCategory', 'accounts');
|
||||
$request->session()->flash('gaEventAction', 'create-' . $what);
|
||||
|
||||
return view('accounts.create', compact('subTitleIcon', 'what', 'subTitle', 'currencySelectList', 'allCurrencies', 'roles'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param AccountRepositoryInterface $repository
|
||||
* @param Account $account
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Request $request, AccountRepositoryInterface $repository, Account $account)
|
||||
public function delete(AccountRepositoryInterface $repository, Account $account)
|
||||
{
|
||||
$typeName = config('firefly.shortNamesByFullName.' . $account->accountType->type);
|
||||
$subTitle = trans('firefly.delete_' . $typeName . '_account', ['name' => $account->name]);
|
||||
@ -118,8 +115,6 @@ class AccountController extends Controller
|
||||
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('accounts.delete.uri');
|
||||
$request->session()->flash('gaEventCategory', 'accounts');
|
||||
$request->session()->flash('gaEventAction', 'delete-' . $typeName);
|
||||
|
||||
return view('accounts.delete', compact('account', 'subTitle', 'accountList'));
|
||||
}
|
||||
@ -156,6 +151,10 @@ class AccountController extends Controller
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*
|
||||
* @return View
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws FireflyException
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function edit(Request $request, Account $account)
|
||||
{
|
||||
@ -198,8 +197,6 @@ class AccountController extends Controller
|
||||
'currency_id' => $currency->id,
|
||||
];
|
||||
$request->session()->flash('preFilled', $preFilled);
|
||||
$request->session()->flash('gaEventCategory', 'accounts');
|
||||
$request->session()->flash('gaEventAction', 'edit-' . $what);
|
||||
|
||||
return view(
|
||||
'accounts.edit',
|
||||
@ -218,18 +215,24 @@ class AccountController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param AccountRepositoryInterface $repository
|
||||
* @param string $what
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index(AccountRepositoryInterface $repository, string $what)
|
||||
public function index(Request $request, AccountRepositoryInterface $repository, string $what)
|
||||
{
|
||||
$what = $what ?? 'asset';
|
||||
$subTitle = trans('firefly.' . $what . '_accounts');
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $what);
|
||||
$types = config('firefly.accountTypesByIdentifier.' . $what);
|
||||
$accounts = $repository->getAccountsByType($types);
|
||||
$collection = $repository->getAccountsByType($types);
|
||||
$total = $collection->count();
|
||||
$page = 0 === intval($request->get('page')) ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
$accounts = $collection->slice(($page - 1) * $pageSize, $pageSize);
|
||||
unset($collection);
|
||||
/** @var Carbon $start */
|
||||
$start = clone session('start', Carbon::now()->startOfMonth());
|
||||
/** @var Carbon $end */
|
||||
@ -250,7 +253,11 @@ class AccountController extends Controller
|
||||
}
|
||||
);
|
||||
|
||||
return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'accounts'));
|
||||
// make paginator:
|
||||
$accounts = new LengthAwarePaginator($accounts, $total, $pageSize, $page);
|
||||
$accounts->setPath(route('accounts.index', [$what]));
|
||||
|
||||
return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'page', 'accounts'));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -265,6 +272,8 @@ class AccountController extends Controller
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // long and complex but not that excessively so.
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function show(Request $request, JournalRepositoryInterface $repository, Account $account, string $moment = '')
|
||||
{
|
||||
@ -276,7 +285,7 @@ class AccountController extends Controller
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
|
||||
$page = intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
$chartUri = route('chart.account.single', [$account->id]);
|
||||
$start = null;
|
||||
$end = null;
|
||||
@ -299,7 +308,7 @@ class AccountController extends Controller
|
||||
// prep for "specific date" view.
|
||||
if (strlen($moment) > 0 && 'all' !== $moment) {
|
||||
$start = new Carbon($moment);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$end = app('navigation')->endOfPeriod($start, $range);
|
||||
$fStart = $start->formatLocalized($this->monthAndDayFormat);
|
||||
$fEnd = $end->formatLocalized($this->monthAndDayFormat);
|
||||
$subTitle = trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]);
|
||||
@ -309,8 +318,8 @@ class AccountController extends Controller
|
||||
|
||||
// prep for current period view
|
||||
if (0 === strlen($moment)) {
|
||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', app('navigation')->endOfPeriod(new Carbon, $range));
|
||||
$fStart = $start->formatLocalized($this->monthAndDayFormat);
|
||||
$fEnd = $end->formatLocalized($this->monthAndDayFormat);
|
||||
$subTitle = trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]);
|
||||
@ -423,8 +432,8 @@ class AccountController extends Controller
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$start = $repository->oldestJournalDate($account);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfX(new Carbon, $range, null);
|
||||
$start = app('navigation')->startOfPeriod($start, $range);
|
||||
$end = app('navigation')->endOfX(new Carbon, $range, null);
|
||||
$entries = new Collection;
|
||||
$count = 0;
|
||||
// properties for cache
|
||||
@ -440,8 +449,8 @@ class AccountController extends Controller
|
||||
|
||||
Log::debug('Going to get period expenses and incomes.');
|
||||
while ($end >= $start && $count < 90) {
|
||||
$end = Navigation::startOfPeriod($end, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||
$end = app('navigation')->startOfPeriod($end, $range);
|
||||
$currentEnd = app('navigation')->endOfPeriod($end, $range);
|
||||
|
||||
// try a collector for income:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
@ -455,7 +464,7 @@ class AccountController extends Controller
|
||||
$collector->setAccounts(new Collection([$account]))->setRange($end, $currentEnd)->setTypes([TransactionType::WITHDRAWAL])->withOpposingAccount();
|
||||
$spent = strval($collector->getJournals()->sum('transaction_amount'));
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$dateName = app('navigation')->periodShow($end, $range);
|
||||
$entries->push(
|
||||
[
|
||||
'string' => $dateStr,
|
||||
@ -464,7 +473,7 @@ class AccountController extends Controller
|
||||
'earned' => $earned,
|
||||
'date' => clone $end,]
|
||||
);
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
$end = app('navigation')->subtractPeriod($end, $range, 1);
|
||||
++$count;
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Http\Middleware\IsSandStormUser;
|
||||
use FireflyIII\Http\Requests\ConfigurationRequest;
|
||||
use FireflyIII\Support\Facades\FireflyConfig;
|
||||
use Preferences;
|
||||
@ -44,12 +46,14 @@ class ConfigurationController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', strval(trans('firefly.administration')));
|
||||
View::share('mainTitleIcon', 'fa-hand-spock-o');
|
||||
app('view')->share('title', strval(trans('firefly.administration')));
|
||||
app('view')->share('mainTitleIcon', 'fa-hand-spock-o');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class)->except(['index']);
|
||||
$this->middleware(IsSandStormUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,8 @@ namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
use FireflyIII\Events\AdminRequestedTestMessage;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Http\Middleware\IsSandStormUser;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
use Session;
|
||||
@ -33,6 +35,16 @@ use Session;
|
||||
*/
|
||||
class HomeController extends Controller
|
||||
{
|
||||
/**
|
||||
* ConfigurationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(IsDemoUser::class)->except(['index']);
|
||||
$this->middleware(IsSandStormUser::class)->except(['index']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
*/
|
||||
|
@ -23,6 +23,7 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Http\Requests\LinkTypeFormRequest;
|
||||
use FireflyIII\Models\LinkType;
|
||||
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
|
||||
@ -44,12 +45,13 @@ class LinkController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', strval(trans('firefly.administration')));
|
||||
View::share('mainTitleIcon', 'fa-hand-spock-o');
|
||||
app('view')->share('title', strval(trans('firefly.administration')));
|
||||
app('view')->share('mainTitleIcon', 'fa-hand-spock-o');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class)->except(['index', 'show']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,6 +206,13 @@ class LinkController extends Controller
|
||||
return redirect($this->getPreviousUri('link_types.create.uri'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param LinkTypeFormRequest $request
|
||||
* @param LinkTypeRepositoryInterface $repository
|
||||
* @param LinkType $linkType
|
||||
*
|
||||
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function update(LinkTypeFormRequest $request, LinkTypeRepositoryInterface $repository, LinkType $linkType)
|
||||
{
|
||||
if (!$linkType->editable) {
|
||||
|
142
app/Http/Controllers/Admin/UpdateController.php
Normal file
142
app/Http/Controllers/Admin/UpdateController.php
Normal file
@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/**
|
||||
* UpdateController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
use FireflyConfig;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Http\Middleware\IsSandStormUser;
|
||||
use FireflyIII\Services\Github\Object\Release;
|
||||
use FireflyIII\Services\Github\Request\UpdateRequest;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
use Response;
|
||||
use Session;
|
||||
|
||||
/**
|
||||
* Class HomeController.
|
||||
*/
|
||||
class UpdateController extends Controller
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* ConfigurationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('title', strval(trans('firefly.administration')));
|
||||
app('view')->share('mainTitleIcon', 'fa-hand-spock-o');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class)->except(['index']);
|
||||
$this->middleware(IsSandStormUser::class)->except(['index']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @throws \Illuminate\Container\EntryNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$subTitle = trans('firefly.update_check_title');
|
||||
$subTitleIcon = 'fa-star';
|
||||
$permission = app('fireflyconfig')->get('permission_update_check', -1);
|
||||
$selected = $permission->data;
|
||||
$options = [
|
||||
'-1' => trans('firefly.updates_ask_me_later'),
|
||||
'0' => trans('firefly.updates_do_not_check'),
|
||||
'1' => trans('firefly.updates_enable_check'),
|
||||
];
|
||||
|
||||
return view('admin.update.index', compact('subTitle', 'subTitleIcon', 'selected', 'options'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function post(Request $request)
|
||||
{
|
||||
$checkForUpdates = intval($request->get('check_for_updates'));
|
||||
FireflyConfig::set('permission_update_check', $checkForUpdates);
|
||||
FireflyConfig::set('last_update_check', time());
|
||||
Session::flash('success', strval(trans('firefly.configuration_updated')));
|
||||
|
||||
return redirect(route('admin.update-check'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a manual update check.
|
||||
*/
|
||||
public function updateCheck()
|
||||
{
|
||||
$current = config('firefly.version');
|
||||
/** @var UpdateRequest $request */
|
||||
$request = app(UpdateRequest::class);
|
||||
$check = -2;
|
||||
$first = new Release(['id' => '0', 'title' => '0', 'updated' => '2017-01-01', 'content' => '']);
|
||||
$string = '';
|
||||
try {
|
||||
$request->call();
|
||||
$releases = $request->getReleases();
|
||||
// first entry should be the latest entry:
|
||||
/** @var Release $first */
|
||||
$first = reset($releases);
|
||||
$check = version_compare($current, $first->getTitle());
|
||||
FireflyConfig::set('last_update_check', time());
|
||||
} catch (FireflyException $e) {
|
||||
Log::error(sprintf('Could not check for updates: %s', $e->getMessage()));
|
||||
}
|
||||
if ($check === -2) {
|
||||
$string = strval(trans('firefly.update_check_error'));
|
||||
}
|
||||
|
||||
if ($check === -1) {
|
||||
// there is a new FF version!
|
||||
$string = strval(
|
||||
trans(
|
||||
'firefly.update_new_version_alert',
|
||||
['your_version' => $current, 'new_version' => $first->getTitle(), 'date' => $first->getUpdated()->formatLocalized($this->monthAndDayFormat)]
|
||||
)
|
||||
);
|
||||
}
|
||||
if ($check === 0) {
|
||||
// you are running the current version!
|
||||
$string = strval(trans('firefly.update_current_version_alert', ['version' => $current]));
|
||||
}
|
||||
if ($check === 1) {
|
||||
// you are running a newer version!
|
||||
$string = strval(trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $first->getTitle()]));
|
||||
}
|
||||
|
||||
return Response::json(['result' => $string]);
|
||||
}
|
||||
}
|
@ -23,6 +23,8 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Controllers\Admin;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Http\Middleware\IsSandStormUser;
|
||||
use FireflyIII\Http\Requests\UserFormRequest;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use FireflyIII\User;
|
||||
@ -45,12 +47,14 @@ class UserController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', strval(trans('firefly.administration')));
|
||||
View::share('mainTitleIcon', 'fa-hand-spock-o');
|
||||
app('view')->share('title', strval(trans('firefly.administration')));
|
||||
app('view')->share('mainTitleIcon', 'fa-hand-spock-o');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class)->except(['index', 'show']);
|
||||
$this->middleware(IsSandStormUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,8 +50,8 @@ class AttachmentController extends Controller
|
||||
// translations:
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('mainTitleIcon', 'fa-paperclip');
|
||||
View::share('title', trans('firefly.attachments'));
|
||||
app('view')->share('mainTitleIcon', 'fa-paperclip');
|
||||
app('view')->share('title', trans('firefly.attachments'));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@ -59,19 +59,16 @@ class AttachmentController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Request $request, Attachment $attachment)
|
||||
public function delete(Attachment $attachment)
|
||||
{
|
||||
$subTitle = trans('firefly.delete_attachment', ['name' => $attachment->filename]);
|
||||
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('attachments.delete.uri');
|
||||
$request->session()->flash('gaEventCategory', 'attachments');
|
||||
$request->session()->flash('gaEventAction', 'delete-attachment');
|
||||
|
||||
return view('attachments.delete', compact('attachment', 'subTitle'));
|
||||
}
|
||||
@ -151,6 +148,8 @@ class AttachmentController extends Controller
|
||||
* @param Attachment $attachment
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
|
||||
*/
|
||||
public function preview(Attachment $attachment)
|
||||
{
|
||||
|
@ -20,20 +20,14 @@
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ForgotPasswordController.php
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
|
||||
/**
|
||||
* Class ForgotPasswordController
|
||||
*/
|
||||
class ForgotPasswordController extends Controller
|
||||
{
|
||||
/*
|
||||
|
@ -20,15 +20,6 @@
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* LoginController.php
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
use FireflyConfig;
|
||||
@ -40,19 +31,16 @@ use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Http\Request;
|
||||
use Schema;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* Class LoginController
|
||||
*
|
||||
* This controller handles authenticating users for the application and
|
||||
* redirecting them to your home screen. The controller uses a trait
|
||||
* to conveniently provide its functionality to your applications.
|
||||
*/
|
||||
class LoginController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Login Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles authenticating users for the application and
|
||||
| redirecting them to your home screen. The controller uses a trait
|
||||
| to conveniently provide its functionality to your applications.
|
||||
|
|
||||
*/
|
||||
|
||||
use AuthenticatesUsers;
|
||||
|
||||
/**
|
||||
@ -76,7 +64,9 @@ class LoginController extends Controller
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response|void
|
||||
* @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function login(Request $request)
|
||||
{
|
||||
@ -112,7 +102,7 @@ class LoginController extends Controller
|
||||
* @param Request $request
|
||||
* @param CookieJar $cookieJar
|
||||
*
|
||||
* @return $this
|
||||
* @return $this|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function logout(Request $request, CookieJar $cookieJar)
|
||||
{
|
||||
|
@ -20,15 +20,6 @@
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* RegisterController.php
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
use FireflyConfig;
|
||||
@ -40,19 +31,16 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Session;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* Class RegisterController
|
||||
*
|
||||
* This controller handles the registration of new users as well as their
|
||||
* validation and creation. By default this controller uses a trait to
|
||||
* provide this functionality without requiring any additional code.
|
||||
*/
|
||||
class RegisterController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Register Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller handles the registration of new users as well as their
|
||||
| validation and creation. By default this controller uses a trait to
|
||||
| provide this functionality without requiring any additional code.
|
||||
|
|
||||
*/
|
||||
|
||||
use RegistersUsers;
|
||||
|
||||
/**
|
||||
|
@ -20,33 +20,21 @@
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* ResetPasswordController.php
|
||||
* Copyright (c) 2017 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.
|
||||
*/
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Auth;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
|
||||
/**
|
||||
* @codeCoverageIgnore
|
||||
* Class ResetPasswordController
|
||||
*
|
||||
* This controller is responsible for handling password reset requests
|
||||
* and uses a simple trait to include this behavior. You're free to
|
||||
* explore this trait and override any methods you wish to tweak.
|
||||
*/
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Password Reset Controller
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This controller is responsible for handling password reset requests
|
||||
| and uses a simple trait to include this behavior. You're free to
|
||||
| explore this trait and override any methods you wish to tweak.
|
||||
|
|
||||
*/
|
||||
|
||||
use ResetsPasswords;
|
||||
|
||||
/**
|
||||
|
@ -69,8 +69,6 @@ class TwoFactorController extends Controller
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function lostTwoFactor()
|
||||
{
|
||||
|
@ -31,6 +31,7 @@ use FireflyIII\Models\Note;
|
||||
use FireflyIII\Models\TransactionJournal;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Preferences;
|
||||
use URL;
|
||||
@ -58,8 +59,8 @@ class BillController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', trans('firefly.bills'));
|
||||
View::share('mainTitleIcon', 'fa-calendar-o');
|
||||
app('view')->share('title', trans('firefly.bills'));
|
||||
app('view')->share('mainTitleIcon', 'fa-calendar-o');
|
||||
$this->attachments = app(AttachmentHelperInterface::class);
|
||||
|
||||
return $next($request);
|
||||
@ -85,24 +86,19 @@ class BillController extends Controller
|
||||
$this->rememberPreviousUri('bills.create.uri');
|
||||
}
|
||||
$request->session()->forget('bills.create.fromStore');
|
||||
$request->session()->flash('gaEventCategory', 'bills');
|
||||
$request->session()->flash('gaEventAction', 'create');
|
||||
|
||||
return view('bills.create', compact('periods', 'subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Bill $bill
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Request $request, Bill $bill)
|
||||
public function delete(Bill $bill)
|
||||
{
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('bills.delete.uri');
|
||||
$request->session()->flash('gaEventCategory', 'bills');
|
||||
$request->session()->flash('gaEventAction', 'delete');
|
||||
$subTitle = trans('firefly.delete_bill', ['name' => $bill->name]);
|
||||
|
||||
return view('bills.delete', compact('bill', 'subTitle'));
|
||||
@ -162,8 +158,6 @@ class BillController extends Controller
|
||||
$request->session()->flash('preFilled', $preFilled);
|
||||
|
||||
$request->session()->forget('bills.edit.fromUpdate');
|
||||
$request->session()->flash('gaEventCategory', 'bills');
|
||||
$request->session()->flash('gaEventAction', 'edit');
|
||||
|
||||
return view('bills.edit', compact('subTitle', 'periods', 'bill'));
|
||||
}
|
||||
@ -173,15 +167,19 @@ class BillController extends Controller
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index(BillRepositoryInterface $repository)
|
||||
public function index(Request $request, BillRepositoryInterface $repository)
|
||||
{
|
||||
/** @var Carbon $start */
|
||||
$start = session('start');
|
||||
/** @var Carbon $end */
|
||||
$end = session('end');
|
||||
$page = 0 === intval($request->get('page')) ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
$collection = $repository->getBills();
|
||||
$total = $collection->count();
|
||||
$collection = $collection->slice(($page - 1) * $pageSize, $pageSize);
|
||||
|
||||
$bills = $repository->getBills();
|
||||
$bills->each(
|
||||
$collection->each(
|
||||
function (Bill $bill) use ($repository, $start, $end) {
|
||||
// paid in this period?
|
||||
$bill->paidDates = $repository->getPaidDatesInRange($bill, $start, $end);
|
||||
@ -194,6 +192,9 @@ class BillController extends Controller
|
||||
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, $lastPaidDate);
|
||||
}
|
||||
);
|
||||
// paginate bills
|
||||
$bills = new LengthAwarePaginator($collection, $total, $pageSize, $page);
|
||||
$bills->setPath(route('bills.index'));
|
||||
|
||||
return view('bills.index', compact('bills'));
|
||||
}
|
||||
@ -240,7 +241,7 @@ class BillController extends Controller
|
||||
$end = session('end');
|
||||
$year = $date->year;
|
||||
$page = intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
$yearAverage = $repository->getYearAverage($bill, $date);
|
||||
$overallAverage = $repository->getOverallAverage($bill);
|
||||
|
||||
@ -252,7 +253,6 @@ class BillController extends Controller
|
||||
$transactions = $collector->getPaginatedJournals();
|
||||
$transactions->setPath(route('bills.show', [$bill->id]));
|
||||
|
||||
|
||||
$bill->paidDates = $repository->getPaidDatesInRange($bill, $date, $end);
|
||||
$bill->payDates = $repository->getPayDatesInRange($bill, $date, $end);
|
||||
$lastPaidDate = $this->lastPaidDate($repository->getPaidDatesInRange($bill, $date, $end), $date);
|
||||
@ -280,14 +280,13 @@ class BillController extends Controller
|
||||
$request->session()->flash('success', strval(trans('firefly.stored_new_bill', ['name' => $bill->name])));
|
||||
Preferences::mark();
|
||||
|
||||
|
||||
/** @var array $files */
|
||||
$files = $request->hasFile('attachments') ? $request->file('attachments') : null;
|
||||
$this->attachments->saveAttachmentsForModel($bill, $files);
|
||||
|
||||
// flash messages
|
||||
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
|
||||
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments'));
|
||||
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if (1 === intval($request->get('create_another'))) {
|
||||
@ -323,7 +322,7 @@ class BillController extends Controller
|
||||
|
||||
// flash messages
|
||||
if (count($this->attachments->getMessages()->get('attachments')) > 0) {
|
||||
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments'));
|
||||
$request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if (1 === intval($request->get('return_to_edit'))) {
|
||||
@ -347,8 +346,8 @@ class BillController extends Controller
|
||||
*/
|
||||
private function lastPaidDate(Collection $dates, Carbon $default): Carbon
|
||||
{
|
||||
if ($dates->count() === 0) {
|
||||
return $default;
|
||||
if (0 === $dates->count()) {
|
||||
return $default; // @codeCoverageIgnore
|
||||
}
|
||||
$latest = $dates->first();
|
||||
/** @var Carbon $date */
|
||||
@ -359,6 +358,5 @@ class BillController extends Controller
|
||||
}
|
||||
|
||||
return $latest;
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -35,9 +35,9 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use View;
|
||||
@ -64,8 +64,8 @@ class BudgetController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', trans('firefly.budgets'));
|
||||
View::share('mainTitleIcon', 'fa-tasks');
|
||||
app('view')->share('title', trans('firefly.budgets'));
|
||||
app('view')->share('mainTitleIcon', 'fa-tasks');
|
||||
$this->repository = app(BudgetRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
@ -75,6 +75,7 @@ class BudgetController extends Controller
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param BudgetRepositoryInterface $repository
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
@ -85,7 +86,7 @@ class BudgetController extends Controller
|
||||
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
|
||||
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
|
||||
$budgetLimit = $this->repository->updateLimitAmount($budget, $start, $end, $amount);
|
||||
if (bccomp($amount,'0') === 0) {
|
||||
if (0 === bccomp($amount, '0')) {
|
||||
$budgetLimit = null;
|
||||
}
|
||||
|
||||
@ -111,27 +112,22 @@ class BudgetController extends Controller
|
||||
$this->rememberPreviousUri('budgets.create.uri');
|
||||
}
|
||||
$request->session()->forget('budgets.create.fromStore');
|
||||
$request->session()->flash('gaEventCategory', 'budgets');
|
||||
$request->session()->flash('gaEventAction', 'create');
|
||||
$subTitle = (string)trans('firefly.create_new_budget');
|
||||
|
||||
return view('budgets.create', compact('subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Budget $budget
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Request $request, Budget $budget)
|
||||
public function delete(Budget $budget)
|
||||
{
|
||||
$subTitle = trans('firefly.delete_budget', ['name' => $budget->name]);
|
||||
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('budgets.delete.uri');
|
||||
$request->session()->flash('gaEventCategory', 'budgets');
|
||||
$request->session()->flash('gaEventAction', 'delete');
|
||||
|
||||
return view('budgets.delete', compact('budget', 'subTitle'));
|
||||
}
|
||||
@ -167,8 +163,6 @@ class BudgetController extends Controller
|
||||
$this->rememberPreviousUri('budgets.edit.uri');
|
||||
}
|
||||
$request->session()->forget('budgets.edit.fromUpdate');
|
||||
$request->session()->flash('gaEventCategory', 'budgets');
|
||||
$request->session()->flash('gaEventAction', 'edit');
|
||||
|
||||
return view('budgets.edit', compact('budget', 'subTitle'));
|
||||
}
|
||||
@ -181,17 +175,19 @@ class BudgetController extends Controller
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity) complex because of while loop
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*/
|
||||
public function index(string $moment = null)
|
||||
public function index(Request $request, string $moment = null)
|
||||
{
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = session('start', new Carbon);
|
||||
$end = session('end', new Carbon);
|
||||
$page = 0 === intval($request->get('page')) ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
|
||||
// make date if present:
|
||||
if (null !== $moment || 0 !== strlen(strval($moment))) {
|
||||
try {
|
||||
$start = new Carbon($moment);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$end = app('navigation')->endOfPeriod($start, $range);
|
||||
} catch (Exception $e) {
|
||||
// start and end are already defined.
|
||||
}
|
||||
@ -200,9 +196,11 @@ class BudgetController extends Controller
|
||||
$next->addDay();
|
||||
$prev = clone $start;
|
||||
$prev->subDay();
|
||||
$prev = Navigation::startOfPeriod($prev, $range);
|
||||
$prev = app('navigation')->startOfPeriod($prev, $range);
|
||||
$this->repository->cleanupBudgets();
|
||||
$budgets = $this->repository->getActiveBudgets();
|
||||
$total = $budgets->count();
|
||||
$budgets = $budgets->slice(($page - 1) * $pageSize, $pageSize);
|
||||
$inactive = $this->repository->getInactiveBudgets();
|
||||
$periodStart = $start->formatLocalized($this->monthAndDayFormat);
|
||||
$periodEnd = $end->formatLocalized($this->monthAndDayFormat);
|
||||
@ -212,15 +210,19 @@ class BudgetController extends Controller
|
||||
$spent = array_sum(array_column($budgetInformation, 'spent'));
|
||||
$budgeted = array_sum(array_column($budgetInformation, 'budgeted'));
|
||||
|
||||
// paginate budgets
|
||||
$budgets = new LengthAwarePaginator($budgets, $total, $pageSize, $page);
|
||||
$budgets->setPath(route('budgets.index'));
|
||||
|
||||
// select thing for last 12 periods:
|
||||
$previousLoop = [];
|
||||
$previousDate = clone $start;
|
||||
$count = 0;
|
||||
while ($count < 12) {
|
||||
$previousDate->subDay();
|
||||
$previousDate = Navigation::startOfPeriod($previousDate, $range);
|
||||
$previousDate = app('navigation')->startOfPeriod($previousDate, $range);
|
||||
$format = $previousDate->format('Y-m-d');
|
||||
$previousLoop[$format] = Navigation::periodShow($previousDate, $range);
|
||||
$previousLoop[$format] = app('navigation')->periodShow($previousDate, $range);
|
||||
++$count;
|
||||
}
|
||||
|
||||
@ -232,16 +234,16 @@ class BudgetController extends Controller
|
||||
|
||||
while ($count < 12) {
|
||||
$format = $nextDate->format('Y-m-d');
|
||||
$nextLoop[$format] = Navigation::periodShow($nextDate, $range);
|
||||
$nextDate = Navigation::endOfPeriod($nextDate, $range);
|
||||
$nextLoop[$format] = app('navigation')->periodShow($nextDate, $range);
|
||||
$nextDate = app('navigation')->endOfPeriod($nextDate, $range);
|
||||
++$count;
|
||||
$nextDate->addDay();
|
||||
}
|
||||
|
||||
// display info
|
||||
$currentMonth = Navigation::periodShow($start, $range);
|
||||
$nextText = Navigation::periodShow($next, $range);
|
||||
$prevText = Navigation::periodShow($prev, $range);
|
||||
$currentMonth = app('navigation')->periodShow($start, $range);
|
||||
$nextText = app('navigation')->periodShow($next, $range);
|
||||
$prevText = app('navigation')->periodShow($prev, $range);
|
||||
|
||||
return view(
|
||||
'budgets.index',
|
||||
@ -254,6 +256,7 @@ class BudgetController extends Controller
|
||||
'prevText',
|
||||
'periodStart',
|
||||
'periodEnd',
|
||||
'page',
|
||||
'budgetInformation',
|
||||
'inactive',
|
||||
'budgets',
|
||||
@ -282,10 +285,15 @@ class BudgetController extends Controller
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('info-income');
|
||||
|
||||
Log::debug(sprintf('infoIncome start is %s', $start->format('Y-m-d')));
|
||||
Log::debug(sprintf('infoIncome end is %s', $end->format('Y-m-d')));
|
||||
|
||||
if ($cache->has()) {
|
||||
$result = $cache->get(); // @codeCoverageIgnore
|
||||
// @codeCoverageIgnoreStart
|
||||
$result = $cache->get();
|
||||
|
||||
return view('budgets.info', compact('result', 'begin', 'currentEnd'));
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
$result = [
|
||||
'available' => '0',
|
||||
@ -294,18 +302,27 @@ class BudgetController extends Controller
|
||||
];
|
||||
$currency = app('amount')->getDefaultCurrency();
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$begin = Navigation::subtractPeriod($start, $range, 3);
|
||||
$begin = app('navigation')->subtractPeriod($start, $range, 3);
|
||||
|
||||
Log::debug(sprintf('Range is %s', $range));
|
||||
Log::debug(sprintf('infoIncome begin is %s', $begin->format('Y-m-d')));
|
||||
|
||||
// get average amount available.
|
||||
$total = '0';
|
||||
$count = 0;
|
||||
$currentStart = clone $begin;
|
||||
while ($currentStart < $start) {
|
||||
$currentEnd = Navigation::endOfPeriod($currentStart, $range);
|
||||
Log::debug(sprintf('Loop: currentStart is %s', $currentStart->format('Y-m-d')));
|
||||
$currentEnd = app('navigation')->endOfPeriod($currentStart, $range);
|
||||
$total = bcadd($total, $this->repository->getAvailableBudget($currency, $currentStart, $currentEnd));
|
||||
$currentStart = Navigation::addPeriod($currentStart, $range, 0);
|
||||
$currentStart = app('navigation')->addPeriod($currentStart, $range, 0);
|
||||
++$count;
|
||||
}
|
||||
Log::debug('Loop end');
|
||||
|
||||
if (0 === $count) {
|
||||
$count = 1;
|
||||
}
|
||||
$result['available'] = bcdiv($total, strval($count));
|
||||
|
||||
// amount earned in this period:
|
||||
@ -360,7 +377,7 @@ class BudgetController extends Controller
|
||||
// prep for "specific date" view.
|
||||
if (strlen($moment) > 0 && 'all' !== $moment) {
|
||||
$start = new Carbon($moment);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$end = app('navigation')->endOfPeriod($start, $range);
|
||||
$subTitle = trans(
|
||||
'firefly.without_budget_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
@ -370,8 +387,8 @@ class BudgetController extends Controller
|
||||
|
||||
// prep for current period
|
||||
if (0 === strlen($moment)) {
|
||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', app('navigation')->endOfPeriod(new Carbon, $range));
|
||||
$periods = $this->getPeriodOverview();
|
||||
$subTitle = trans(
|
||||
'firefly.without_budget_between',
|
||||
@ -380,7 +397,7 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
$page = intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
@ -422,7 +439,7 @@ class BudgetController extends Controller
|
||||
$start = session('first', Carbon::create()->startOfYear());
|
||||
$end = new Carbon;
|
||||
$page = intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
$limits = $this->getLimits($budget, $start, $end);
|
||||
$repetition = null;
|
||||
// collector:
|
||||
@ -453,7 +470,7 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
$page = intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
$subTitle = trans(
|
||||
'firefly.budget_in_period',
|
||||
[
|
||||
@ -583,8 +600,8 @@ class BudgetController extends Controller
|
||||
$first = $repository->first();
|
||||
$start = $first->date ?? new Carbon;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfX(new Carbon, $range, null);
|
||||
$start = app('navigation')->startOfPeriod($start, $range);
|
||||
$end = app('navigation')->endOfX(new Carbon, $range, null);
|
||||
$entries = new Collection;
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
@ -597,8 +614,8 @@ class BudgetController extends Controller
|
||||
|
||||
Log::debug('Going to get period expenses and incomes.');
|
||||
while ($end >= $start) {
|
||||
$end = Navigation::startOfPeriod($end, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||
$end = app('navigation')->startOfPeriod($end, $range);
|
||||
$currentEnd = app('navigation')->endOfPeriod($end, $range);
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAllAssetAccounts()->setRange($end, $currentEnd)->withoutBudget()->withOpposingAccount()->setTypes([TransactionType::WITHDRAWAL]);
|
||||
@ -606,9 +623,9 @@ class BudgetController extends Controller
|
||||
$sum = strval($set->sum('transaction_amount') ?? '0');
|
||||
$journals = $set->count();
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$dateName = app('navigation')->periodShow($end, $range);
|
||||
$entries->push(['string' => $dateStr, 'name' => $dateName, 'count' => $journals, 'sum' => $sum, 'date' => clone $end]);
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
$end = app('navigation')->subtractPeriod($end, $range, 1);
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
||||
|
@ -34,9 +34,9 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Steam;
|
||||
use View;
|
||||
@ -55,8 +55,8 @@ class CategoryController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', trans('firefly.categories'));
|
||||
View::share('mainTitleIcon', 'fa-bar-chart');
|
||||
app('view')->share('title', trans('firefly.categories'));
|
||||
app('view')->share('mainTitleIcon', 'fa-bar-chart');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@ -74,27 +74,22 @@ class CategoryController extends Controller
|
||||
$this->rememberPreviousUri('categories.create.uri');
|
||||
}
|
||||
$request->session()->forget('categories.create.fromStore');
|
||||
$request->session()->flash('gaEventCategory', 'categories');
|
||||
$request->session()->flash('gaEventAction', 'create');
|
||||
$subTitle = trans('firefly.create_new_category');
|
||||
|
||||
return view('categories.create', compact('subTitle'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Category $category
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function delete(Request $request, Category $category)
|
||||
public function delete(Category $category)
|
||||
{
|
||||
$subTitle = trans('firefly.delete_category', ['name' => $category->name]);
|
||||
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('categories.delete.uri');
|
||||
$request->session()->flash('gaEventCategory', 'categories');
|
||||
$request->session()->flash('gaEventAction', 'delete');
|
||||
|
||||
return view('categories.delete', compact('category', 'subTitle'));
|
||||
}
|
||||
@ -132,8 +127,6 @@ class CategoryController extends Controller
|
||||
$this->rememberPreviousUri('categories.edit.uri');
|
||||
}
|
||||
$request->session()->forget('categories.edit.fromUpdate');
|
||||
$request->session()->flash('gaEventCategory', 'categories');
|
||||
$request->session()->flash('gaEventAction', 'edit');
|
||||
|
||||
return view('categories.edit', compact('category', 'subTitle'));
|
||||
}
|
||||
@ -143,16 +136,24 @@ class CategoryController extends Controller
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index(CategoryRepositoryInterface $repository)
|
||||
public function index(Request $request, CategoryRepositoryInterface $repository)
|
||||
{
|
||||
$categories = $repository->getCategories();
|
||||
$page = 0 === intval($request->get('page')) ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
$collection = $repository->getCategories();
|
||||
$total = $collection->count();
|
||||
$collection = $collection->slice(($page - 1) * $pageSize, $pageSize);
|
||||
|
||||
$categories->each(
|
||||
$collection->each(
|
||||
function (Category $category) use ($repository) {
|
||||
$category->lastActivity = $repository->lastUseDate($category, new Collection);
|
||||
}
|
||||
);
|
||||
|
||||
// paginate categories
|
||||
$categories = new LengthAwarePaginator($collection, $total, $pageSize, $page);
|
||||
$categories->setPath(route('categories.index'));
|
||||
|
||||
return view('categories.index', compact('categories'));
|
||||
}
|
||||
|
||||
@ -171,7 +172,7 @@ class CategoryController extends Controller
|
||||
$end = null;
|
||||
$periods = new Collection;
|
||||
$page = intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
|
||||
// prep for "all" view.
|
||||
if ('all' === $moment) {
|
||||
@ -184,7 +185,7 @@ class CategoryController extends Controller
|
||||
// prep for "specific date" view.
|
||||
if (strlen($moment) > 0 && 'all' !== $moment) {
|
||||
$start = new Carbon($moment);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$end = app('navigation')->endOfPeriod($start, $range);
|
||||
$subTitle = trans(
|
||||
'firefly.without_category_between',
|
||||
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
|
||||
@ -194,8 +195,8 @@ class CategoryController extends Controller
|
||||
|
||||
// prep for current period
|
||||
if (0 === strlen($moment)) {
|
||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', app('navigation')->endOfPeriod(new Carbon, $range));
|
||||
$periods = $this->getNoCategoryPeriodOverview();
|
||||
$subTitle = trans(
|
||||
'firefly.without_category_between',
|
||||
@ -228,11 +229,12 @@ class CategoryController extends Controller
|
||||
$subTitle = $category->name;
|
||||
$subTitleIcon = 'fa-bar-chart';
|
||||
$page = intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = null;
|
||||
$end = null;
|
||||
$periods = new Collection;
|
||||
$path = route('categories.show', [$category->id]);
|
||||
|
||||
// prep for "all" view.
|
||||
if ('all' === $moment) {
|
||||
@ -241,26 +243,28 @@ class CategoryController extends Controller
|
||||
/** @var Carbon $start */
|
||||
$start = null === $first ? new Carbon : $first;
|
||||
$end = new Carbon;
|
||||
$path = route('categories.show', [$category->id, 'all']);
|
||||
}
|
||||
|
||||
// prep for "specific date" view.
|
||||
if (strlen($moment) > 0 && 'all' !== $moment) {
|
||||
$start = new Carbon($moment);
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$end = app('navigation')->endOfPeriod($start, $range);
|
||||
$subTitle = trans(
|
||||
'firefly.journals_in_period_for_category',
|
||||
['name' => $category->name,
|
||||
'start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat),]
|
||||
);
|
||||
$periods = $this->getPeriodOverview($category);
|
||||
$path = route('categories.show', [$category->id, $moment]);
|
||||
}
|
||||
|
||||
// prep for current period
|
||||
if (0 === strlen($moment)) {
|
||||
/** @var Carbon $start */
|
||||
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
|
||||
$start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range));
|
||||
/** @var Carbon $end */
|
||||
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
|
||||
$end = clone session('end', app('navigation')->endOfPeriod(new Carbon, $range));
|
||||
$periods = $this->getPeriodOverview($category);
|
||||
$subTitle = trans(
|
||||
'firefly.journals_in_period_for_category',
|
||||
@ -275,7 +279,7 @@ class CategoryController extends Controller
|
||||
->setCategory($category)->withBudgetInformation()->withCategoryInformation();
|
||||
$collector->removeFilter(InternalTransferFilter::class);
|
||||
$transactions = $collector->getPaginatedJournals();
|
||||
$transactions->setPath(route('categories.show', [$category->id]));
|
||||
$transactions->setPath($path);
|
||||
|
||||
return view('categories.show', compact('category', 'moment', 'transactions', 'periods', 'subTitle', 'subTitleIcon', 'start', 'end'));
|
||||
}
|
||||
@ -340,8 +344,8 @@ class CategoryController extends Controller
|
||||
$first = $repository->first();
|
||||
$start = $first->date ?? new Carbon;
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$end = Navigation::endOfX(new Carbon, $range, null);
|
||||
$start = app('navigation')->startOfPeriod($start, $range);
|
||||
$end = app('navigation')->endOfX(new Carbon, $range, null);
|
||||
$entries = new Collection;
|
||||
|
||||
// properties for cache
|
||||
@ -357,8 +361,8 @@ class CategoryController extends Controller
|
||||
Log::debug(sprintf('Going to get period expenses and incomes between %s and %s.', $start->format('Y-m-d'), $end->format('Y-m-d')));
|
||||
while ($end >= $start) {
|
||||
Log::debug('Loop!');
|
||||
$end = Navigation::startOfPeriod($end, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||
$end = app('navigation')->startOfPeriod($end, $range);
|
||||
$currentEnd = app('navigation')->endOfPeriod($end, $range);
|
||||
|
||||
// count journals without category in this period:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
@ -389,7 +393,7 @@ class CategoryController extends Controller
|
||||
$earned = $collector->getJournals()->sum('transaction_amount');
|
||||
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$dateName = app('navigation')->periodShow($end, $range);
|
||||
$entries->push(
|
||||
[
|
||||
'string' => $dateStr,
|
||||
@ -401,7 +405,7 @@ class CategoryController extends Controller
|
||||
'date' => clone $end,
|
||||
]
|
||||
);
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
$end = app('navigation')->subtractPeriod($end, $range, 1);
|
||||
}
|
||||
Log::debug('End of loops');
|
||||
$cache->store($entries);
|
||||
@ -423,11 +427,11 @@ class CategoryController extends Controller
|
||||
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$first = $repository->firstUseDate($category);
|
||||
if (null === $first) {
|
||||
$first = new Carbon;
|
||||
$first = new Carbon; // @codeCoverageIgnore
|
||||
}
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$first = Navigation::startOfPeriod($first, $range);
|
||||
$end = Navigation::endOfX(new Carbon, $range, null);
|
||||
$first = app('navigation')->startOfPeriod($first, $range);
|
||||
$end = app('navigation')->endOfX(new Carbon, $range, null);
|
||||
$entries = new Collection;
|
||||
$count = 0;
|
||||
|
||||
@ -442,12 +446,12 @@ class CategoryController extends Controller
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
while ($end >= $first && $count < 90) {
|
||||
$end = Navigation::startOfPeriod($end, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($end, $range);
|
||||
$end = app('navigation')->startOfPeriod($end, $range);
|
||||
$currentEnd = app('navigation')->endOfPeriod($end, $range);
|
||||
$spent = $repository->spentInPeriod(new Collection([$category]), $accounts, $end, $currentEnd);
|
||||
$earned = $repository->earnedInPeriod(new Collection([$category]), $accounts, $end, $currentEnd);
|
||||
$dateStr = $end->format('Y-m-d');
|
||||
$dateName = Navigation::periodShow($end, $range);
|
||||
$dateName = app('navigation')->periodShow($end, $range);
|
||||
|
||||
// amount transferred
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
@ -468,7 +472,7 @@ class CategoryController extends Controller
|
||||
'date' => clone $end,
|
||||
]
|
||||
);
|
||||
$end = Navigation::subtractPeriod($end, $range, 1);
|
||||
$end = app('navigation')->subtractPeriod($end, $range, 1);
|
||||
++$count;
|
||||
}
|
||||
$cache->store($entries);
|
||||
|
@ -23,7 +23,6 @@ declare(strict_types=1);
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
@ -38,7 +37,6 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Steam;
|
||||
@ -342,13 +340,11 @@ class AccountController extends Controller
|
||||
* @param Carbon $start
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function period(Account $account, Carbon $start)
|
||||
{
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$end = Navigation::endOfPeriod($start, $range);
|
||||
$end = app('navigation')->endOfPeriod($start, $range);
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
|
@ -37,7 +37,6 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Steam;
|
||||
@ -81,7 +80,7 @@ class BudgetController extends Controller
|
||||
{
|
||||
$first = $this->repository->firstUseDate($budget);
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$currentStart = Navigation::startOfPeriod($first, $range);
|
||||
$currentStart = app('navigation')->startOfPeriod($first, $range);
|
||||
$last = session('end', new Carbon);
|
||||
$cache = new CacheProperties();
|
||||
$cache->addProperty($first);
|
||||
@ -95,15 +94,15 @@ class BudgetController extends Controller
|
||||
$final = clone $last;
|
||||
$final->addYears(2);
|
||||
$budgetCollection = new Collection([$budget]);
|
||||
$last = Navigation::endOfX($last, $range, $final); // not to overshoot.
|
||||
$last = app('navigation')->endOfX($last, $range, $final); // not to overshoot.
|
||||
$entries = [];
|
||||
while ($currentStart < $last) {
|
||||
// periodspecific dates:
|
||||
$currentEnd = Navigation::endOfPeriod($currentStart, $range);
|
||||
$currentEnd = app('navigation')->endOfPeriod($currentStart, $range);
|
||||
// sub another day because reasons.
|
||||
$currentEnd->subDay();
|
||||
$spent = $this->repository->spentInPeriod($budgetCollection, new Collection, $currentStart, $currentEnd);
|
||||
$format = Navigation::periodShow($currentStart, $range);
|
||||
$format = app('navigation')->periodShow($currentStart, $range);
|
||||
$entries[$format] = bcmul($spent, '-1');
|
||||
$currentStart = clone $currentEnd;
|
||||
$currentStart->addDays(2);
|
||||
@ -374,7 +373,7 @@ class BudgetController extends Controller
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$periods = app('navigation')->listOfPeriods($start, $end);
|
||||
$entries = $this->repository->getBudgetPeriodReport(new Collection([$budget]), $accounts, $start, $end); // get the expenses
|
||||
$budgeted = $this->getBudgetedInPeriod($budget, $start, $end);
|
||||
|
||||
@ -417,7 +416,7 @@ class BudgetController extends Controller
|
||||
}
|
||||
|
||||
// the expenses:
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$periods = app('navigation')->listOfPeriods($start, $end);
|
||||
$entries = $this->repository->getNoBudgetPeriodReport($accounts, $start, $end);
|
||||
$chartData = [];
|
||||
|
||||
@ -464,13 +463,13 @@ class BudgetController extends Controller
|
||||
*/
|
||||
private function getBudgetedInPeriod(Budget $budget, Carbon $start, Carbon $end): array
|
||||
{
|
||||
$key = Navigation::preferredCarbonFormat($start, $end);
|
||||
$range = Navigation::preferredRangeFormat($start, $end);
|
||||
$key = app('navigation')->preferredCarbonFormat($start, $end);
|
||||
$range = app('navigation')->preferredRangeFormat($start, $end);
|
||||
$current = clone $start;
|
||||
$budgeted = [];
|
||||
while ($current < $end) {
|
||||
$currentStart = Navigation::startOfPeriod($current, $range);
|
||||
$currentEnd = Navigation::endOfPeriod($current, $range);
|
||||
$currentStart = app('navigation')->startOfPeriod($current, $range);
|
||||
$currentEnd = app('navigation')->endOfPeriod($current, $range);
|
||||
$budgetLimits = $this->repository->getBudgetLimits($budget, $currentStart, $currentEnd);
|
||||
$index = $currentStart->format($key);
|
||||
$budgeted[$index] = $budgetLimits->sum('amount');
|
||||
|
@ -37,7 +37,6 @@ use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Response;
|
||||
|
||||
/**
|
||||
@ -135,8 +134,8 @@ class BudgetReportController extends Controller
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
|
||||
$function = Navigation::preferredEndOfPeriod($start, $end);
|
||||
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
|
||||
$function = app('navigation')->preferredEndOfPeriod($start, $end);
|
||||
$chartData = [];
|
||||
$currentStart = clone $start;
|
||||
|
||||
|
@ -31,7 +31,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
use Response;
|
||||
|
||||
@ -74,11 +73,11 @@ class CategoryController extends Controller
|
||||
$start = $repository->firstUseDate($category);
|
||||
|
||||
if (null === $start) {
|
||||
$start = new Carbon;
|
||||
$start = new Carbon; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($start, $range);
|
||||
$start = app('navigation')->startOfPeriod($start, $range);
|
||||
$end = new Carbon;
|
||||
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
|
||||
$chartData = [
|
||||
@ -101,15 +100,15 @@ class CategoryController extends Controller
|
||||
];
|
||||
|
||||
while ($start <= $end) {
|
||||
$currentEnd = Navigation::endOfPeriod($start, $range);
|
||||
$currentEnd = app('navigation')->endOfPeriod($start, $range);
|
||||
$spent = $repository->spentInPeriod(new Collection([$category]), $accounts, $start, $currentEnd);
|
||||
$earned = $repository->earnedInPeriod(new Collection([$category]), $accounts, $start, $currentEnd);
|
||||
$sum = bcadd($spent, $earned);
|
||||
$label = Navigation::periodShow($start, $range);
|
||||
$label = app('navigation')->periodShow($start, $range);
|
||||
$chartData[0]['entries'][$label] = round(bcmul($spent, '-1'), 12);
|
||||
$chartData[1]['entries'][$label] = round($earned, 12);
|
||||
$chartData[2]['entries'][$label] = round($sum, 12);
|
||||
$start = Navigation::addPeriod($start, $range, 0);
|
||||
$start = app('navigation')->addPeriod($start, $range, 0);
|
||||
}
|
||||
|
||||
$data = $this->generator->multiSet($chartData);
|
||||
@ -180,7 +179,7 @@ class CategoryController extends Controller
|
||||
}
|
||||
$expenses = $repository->periodExpenses(new Collection([$category]), $accounts, $start, $end);
|
||||
$income = $repository->periodIncome(new Collection([$category]), $accounts, $start, $end);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$periods = app('navigation')->listOfPeriods($start, $end);
|
||||
$chartData = [
|
||||
[
|
||||
'label' => strval(trans('firefly.spent')),
|
||||
@ -236,7 +235,7 @@ class CategoryController extends Controller
|
||||
}
|
||||
$expenses = $repository->periodExpensesNoCategory($accounts, $start, $end);
|
||||
$income = $repository->periodIncomeNoCategory($accounts, $start, $end);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$periods = app('navigation')->listOfPeriods($start, $end);
|
||||
$chartData = [
|
||||
[
|
||||
'label' => strval(trans('firefly.spent')),
|
||||
@ -281,8 +280,8 @@ class CategoryController extends Controller
|
||||
public function specificPeriod(CategoryRepositoryInterface $repository, Category $category, Carbon $date)
|
||||
{
|
||||
$range = Preferences::get('viewRange', '1M')->data;
|
||||
$start = Navigation::startOfPeriod($date, $range);
|
||||
$end = Navigation::endOfPeriod($date, $range);
|
||||
$start = app('navigation')->startOfPeriod($date, $range);
|
||||
$end = app('navigation')->endOfPeriod($date, $range);
|
||||
$data = $this->makePeriodChart($repository, $category, $start, $end);
|
||||
|
||||
return Response::json($data);
|
||||
@ -336,7 +335,7 @@ class CategoryController extends Controller
|
||||
$spent = $repository->spentInPeriod(new Collection([$category]), $accounts, $start, $start);
|
||||
$earned = $repository->earnedInPeriod(new Collection([$category]), $accounts, $start, $start);
|
||||
$sum = bcadd($spent, $earned);
|
||||
$label = trim(Navigation::periodShow($start, '1D'));
|
||||
$label = trim(app('navigation')->periodShow($start, '1D'));
|
||||
|
||||
$chartData[0]['entries'][$label] = round(bcmul($spent, '-1'), 12);
|
||||
$chartData[1]['entries'][$label] = round($earned, 12);
|
||||
|
@ -36,7 +36,6 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Response;
|
||||
|
||||
/**
|
||||
@ -177,8 +176,8 @@ class CategoryReportController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
|
||||
$function = Navigation::preferredEndOfPeriod($start, $end);
|
||||
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
|
||||
$function = app('navigation')->preferredEndOfPeriod($start, $end);
|
||||
$chartData = [];
|
||||
$currentStart = clone $start;
|
||||
|
||||
|
266
app/Http/Controllers/Chart/ExpenseReportController.php
Normal file
266
app/Http/Controllers/Chart/ExpenseReportController.php
Normal file
@ -0,0 +1,266 @@
|
||||
<?php
|
||||
/**
|
||||
* ExpenseReportController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Chart;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Generator\Chart\Basic\GeneratorInterface;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Response;
|
||||
|
||||
/**
|
||||
* Separate controller because many helper functions are shared.
|
||||
*
|
||||
* Class ExpenseReportController
|
||||
*/
|
||||
class ExpenseReportController extends Controller
|
||||
{
|
||||
/** @var AccountRepositoryInterface */
|
||||
protected $accountRepository;
|
||||
/** @var GeneratorInterface */
|
||||
protected $generator;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->generator = app(GeneratorInterface::class);
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $expense
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function mainChart(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
|
||||
{
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty('chart.expense.report.main');
|
||||
$cache->addProperty($accounts);
|
||||
$cache->addProperty($expense);
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
if ($cache->has()) {
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
|
||||
$function = app('navigation')->preferredEndOfPeriod($start, $end);
|
||||
$chartData = [];
|
||||
$currentStart = clone $start;
|
||||
$combined = $this->combineAccounts($expense);
|
||||
|
||||
// make "all" set:
|
||||
$all = new Collection;
|
||||
foreach ($combined as $name => $combi) {
|
||||
$all = $all->merge($combi);
|
||||
}
|
||||
|
||||
// prep chart data:
|
||||
foreach ($combined as $name => $combi) {
|
||||
// first is always expense account:
|
||||
/** @var Account $exp */
|
||||
$exp = $combi->first();
|
||||
$chartData[$exp->id . '-in'] = [
|
||||
'label' => $name . ' (' . strtolower(strval(trans('firefly.income'))) . ')',
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 'y-axis-0',
|
||||
'entries' => [],
|
||||
];
|
||||
$chartData[$exp->id . '-out'] = [
|
||||
'label' => $name . ' (' . strtolower(strval(trans('firefly.expenses'))) . ')',
|
||||
'type' => 'bar',
|
||||
'yAxisID' => 'y-axis-0',
|
||||
'entries' => [],
|
||||
];
|
||||
// total in, total out:
|
||||
$chartData[$exp->id . '-total-in'] = [
|
||||
'label' => $name . ' (' . strtolower(strval(trans('firefly.sum_of_income'))) . ')',
|
||||
'type' => 'line',
|
||||
'fill' => false,
|
||||
'yAxisID' => 'y-axis-1',
|
||||
'entries' => [],
|
||||
];
|
||||
$chartData[$exp->id . '-total-out'] = [
|
||||
'label' => $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;
|
||||
$currentEnd = $currentEnd->$function();
|
||||
|
||||
// get expenses grouped by opposing name:
|
||||
$expenses = $this->groupByName($this->getExpenses($accounts, $all, $currentStart, $currentEnd));
|
||||
$income = $this->groupByName($this->getIncome($accounts, $all, $currentStart, $currentEnd));
|
||||
$label = $currentStart->formatLocalized($format);
|
||||
|
||||
foreach ($combined as $name => $combi) {
|
||||
// first is always expense account:
|
||||
/** @var Account $exp */
|
||||
$exp = $combi->first();
|
||||
$labelIn = $exp->id . '-in';
|
||||
$labelOut = $exp->id . '-out';
|
||||
$labelSumIn = $exp->id . '-total-in';
|
||||
$labelSumOut = $exp->id . '-total-out';
|
||||
$currentIncome = $income[$name] ?? '0';
|
||||
$currentExpense = $expenses[$name] ?? '0';
|
||||
|
||||
// add to sum:
|
||||
$sumOfIncome[$exp->id] = $sumOfIncome[$exp->id] ?? '0';
|
||||
$sumOfExpense[$exp->id] = $sumOfExpense[$exp->id] ?? '0';
|
||||
$sumOfIncome[$exp->id] = bcadd($sumOfIncome[$exp->id], $currentIncome);
|
||||
$sumOfExpense[$exp->id] = bcadd($sumOfExpense[$exp->id], $currentExpense);
|
||||
|
||||
// add to chart:
|
||||
$chartData[$labelIn]['entries'][$label] = $currentIncome;
|
||||
$chartData[$labelOut]['entries'][$label] = $currentExpense;
|
||||
$chartData[$labelSumIn]['entries'][$label] = $sumOfIncome[$exp->id];
|
||||
$chartData[$labelSumOut]['entries'][$label] = $sumOfExpense[$exp->id];
|
||||
}
|
||||
$currentStart = clone $currentEnd;
|
||||
$currentStart->addDay();
|
||||
}
|
||||
// remove all empty entries to prevent cluttering:
|
||||
$newSet = [];
|
||||
foreach ($chartData as $key => $entry) {
|
||||
if (0 === !array_sum($entry['entries'])) {
|
||||
$newSet[$key] = $chartData[$key];
|
||||
}
|
||||
}
|
||||
if (0 === count($newSet)) {
|
||||
$newSet = $chartData; // @codeCoverageIgnore
|
||||
}
|
||||
$data = $this->generator->multiSet($newSet);
|
||||
$cache->store($data);
|
||||
|
||||
return Response::json($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function combineAccounts(Collection $accounts): array
|
||||
{
|
||||
$combined = [];
|
||||
/** @var Account $expenseAccount */
|
||||
foreach ($accounts as $expenseAccount) {
|
||||
$collection = new Collection;
|
||||
$collection->push($expenseAccount);
|
||||
|
||||
$revenue = $this->accountRepository->findByName($expenseAccount->name, [AccountType::REVENUE]);
|
||||
if (!is_null($revenue->id)) {
|
||||
$collection->push($revenue);
|
||||
}
|
||||
$combined[$expenseAccount->name] = $collection;
|
||||
}
|
||||
|
||||
return $combined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $opposing
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function getExpenses(Collection $accounts, Collection $opposing, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setOpposingAccounts($opposing);
|
||||
|
||||
$transactions = $collector->getJournals();
|
||||
|
||||
return $transactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $opposing
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return Collection
|
||||
*/
|
||||
private function getIncome(Collection $accounts, Collection $opposing, Carbon $start, Carbon $end): Collection
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setAccounts($accounts)->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setOpposingAccounts($opposing);
|
||||
|
||||
$transactions = $collector->getJournals();
|
||||
|
||||
return $transactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $set
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function groupByName(Collection $set): array
|
||||
{
|
||||
// group by opposing account name.
|
||||
$grouped = [];
|
||||
/** @var Transaction $transaction */
|
||||
foreach ($set as $transaction) {
|
||||
$name = $transaction->opposing_account_name;
|
||||
$grouped[$name] = $grouped[$name] ?? '0';
|
||||
$grouped[$name] = bcadd($transaction->transaction_amount, $grouped[$name]);
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}
|
||||
}
|
@ -29,7 +29,6 @@ use FireflyIII\Repositories\Account\AccountTaskerInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Response;
|
||||
use Steam;
|
||||
|
||||
@ -89,7 +88,7 @@ class ReportController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows income and expense, debet/credit: operations.
|
||||
* Shows income and expense, debit/credit: operations.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
@ -109,7 +108,7 @@ class ReportController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
Log::debug('Going to do operations for accounts ', $accounts->pluck('id')->toArray());
|
||||
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
|
||||
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
|
||||
$source = $this->getChartData($accounts, $start, $end);
|
||||
$chartData = [
|
||||
[
|
||||
@ -144,7 +143,7 @@ class ReportController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows sum income and expense, debet/credit: operations.
|
||||
* Shows sum income and expense, debit/credit: operations.
|
||||
*
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
@ -256,7 +255,7 @@ class ReportController extends Controller
|
||||
$tasker = app(AccountTaskerInterface::class);
|
||||
|
||||
while ($currentStart <= $end) {
|
||||
$currentEnd = Navigation::endOfPeriod($currentStart, '1M');
|
||||
$currentEnd = app('navigation')->endOfPeriod($currentStart, '1M');
|
||||
$earned = strval(
|
||||
array_sum(
|
||||
array_map(
|
||||
@ -282,7 +281,7 @@ class ReportController extends Controller
|
||||
$label = $currentStart->format('Y-m') . '-01';
|
||||
$spentArray[$label] = bcmul($spent, '-1');
|
||||
$earnedArray[$label] = $earned;
|
||||
$currentStart = Navigation::addPeriod($currentStart, '1M', 0);
|
||||
$currentStart = app('navigation')->addPeriod($currentStart, '1M', 0);
|
||||
}
|
||||
$result = [
|
||||
'spent' => $spentArray,
|
||||
|
@ -36,9 +36,11 @@ use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
use Response;
|
||||
|
||||
/**
|
||||
* Class TagReportController
|
||||
*/
|
||||
class TagReportController extends Controller
|
||||
{
|
||||
/** @var GeneratorInterface */
|
||||
@ -168,8 +170,8 @@ class TagReportController extends Controller
|
||||
return Response::json($cache->get()); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$format = Navigation::preferredCarbonLocalizedFormat($start, $end);
|
||||
$function = Navigation::preferredEndOfPeriod($start, $end);
|
||||
$format = app('navigation')->preferredCarbonLocalizedFormat($start, $end);
|
||||
$function = app('navigation')->preferredEndOfPeriod($start, $end);
|
||||
$chartData = [];
|
||||
$currentStart = clone $start;
|
||||
|
||||
|
@ -126,7 +126,7 @@ class Controller extends BaseController
|
||||
$uri = $this->redirectUri;
|
||||
}
|
||||
if (!(false === strpos($uri, 'jscript'))) {
|
||||
$uri = $this->redirectUri;
|
||||
$uri = $this->redirectUri; // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
return $uri;
|
||||
|
@ -28,6 +28,7 @@ use FireflyIII\Models\TransactionCurrency;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use View;
|
||||
@ -52,8 +53,8 @@ class CurrencyController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', trans('firefly.currencies'));
|
||||
View::share('mainTitleIcon', 'fa-usd');
|
||||
app('view')->share('title', trans('firefly.currencies'));
|
||||
app('view')->share('mainTitleIcon', 'fa-usd');
|
||||
$this->repository = app(CurrencyRepositoryInterface::class);
|
||||
$this->userRepository = app(UserRepositoryInterface::class);
|
||||
|
||||
@ -83,8 +84,6 @@ class CurrencyController extends Controller
|
||||
$this->rememberPreviousUri('currencies.create.uri');
|
||||
}
|
||||
$request->session()->forget('currencies.create.fromStore');
|
||||
$request->session()->flash('gaEventCategory', 'currency');
|
||||
$request->session()->flash('gaEventAction', 'create');
|
||||
|
||||
return view('currencies.create', compact('subTitleIcon', 'subTitle'));
|
||||
}
|
||||
@ -131,8 +130,6 @@ class CurrencyController extends Controller
|
||||
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('currencies.delete.uri');
|
||||
$request->session()->flash('gaEventCategory', 'currency');
|
||||
$request->session()->flash('gaEventAction', 'delete');
|
||||
$subTitle = trans('form.delete_currency', ['name' => $currency->name]);
|
||||
|
||||
return view('currencies.delete', compact('currency', 'subTitle'));
|
||||
@ -191,8 +188,6 @@ class CurrencyController extends Controller
|
||||
$this->rememberPreviousUri('currencies.edit.uri');
|
||||
}
|
||||
$request->session()->forget('currencies.edit.fromUpdate');
|
||||
$request->session()->flash('gaEventCategory', 'currency');
|
||||
$request->session()->flash('gaEventAction', 'edit');
|
||||
|
||||
return view('currencies.edit', compact('currency', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
@ -204,12 +199,19 @@ class CurrencyController extends Controller
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$currencies = $this->repository->get();
|
||||
$currencies = $currencies->sortBy(
|
||||
$page = 0 === intval($request->get('page')) ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
$collection = $this->repository->get();
|
||||
$total = $collection->count();
|
||||
$collection = $collection->sortBy(
|
||||
function (TransactionCurrency $currency) {
|
||||
return $currency->name;
|
||||
}
|
||||
);
|
||||
$collection = $collection->slice(($page - 1) * $pageSize, $pageSize);
|
||||
$currencies = new LengthAwarePaginator($collection, $total, $pageSize, $page);
|
||||
$currencies->setPath(route('currencies.index'));
|
||||
|
||||
$defaultCurrency = $this->repository->getCurrencyByPreference(Preferences::get('currencyPreference', config('firefly.default_currency', 'EUR')));
|
||||
$isOwner = true;
|
||||
if (!$this->userRepository->hasRole(auth()->user(), 'owner')) {
|
||||
|
@ -26,6 +26,7 @@ use Carbon\Carbon;
|
||||
use ExpandedForm;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Export\ProcessorInterface;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Http\Requests\ExportFormRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\ExportJob;
|
||||
@ -50,12 +51,13 @@ class ExportController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('mainTitleIcon', 'fa-file-archive-o');
|
||||
View::share('title', trans('firefly.export_and_backup_data'));
|
||||
app('view')->share('mainTitleIcon', 'fa-file-archive-o');
|
||||
app('view')->share('title', trans('firefly.export_and_backup_data'));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class)->except(['index']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,8 +25,12 @@ namespace FireflyIII\Http\Controllers;
|
||||
use Artisan;
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use Exception;
|
||||
use FireflyIII\Events\RequestedVersionCheckStatus;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Http\Middleware\IsSandStormUser;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
|
||||
@ -36,8 +40,8 @@ use Illuminate\Support\Collection;
|
||||
use Log;
|
||||
use Monolog\Handler\RotatingFileHandler;
|
||||
use Preferences;
|
||||
use Response;
|
||||
use Route as RouteFacade;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
/**
|
||||
@ -51,12 +55,16 @@ class HomeController extends Controller
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
View::share('title', 'Firefly III');
|
||||
View::share('mainTitleIcon', 'fa-fire');
|
||||
app('view')->share('title', 'Firefly III');
|
||||
app('view')->share('mainTitleIcon', 'fa-fire');
|
||||
$this->middleware(IsDemoUser::class)->except(['dateRange', 'index']);
|
||||
$this->middleware(IsSandStormUser::class)->only('routes');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function dateRange(Request $request)
|
||||
{
|
||||
@ -77,12 +85,17 @@ class HomeController extends Controller
|
||||
$diff = $start->diffInDays($end);
|
||||
|
||||
if ($diff > 50) {
|
||||
Session::flash('warning', strval(trans('firefly.warning_much_data', ['days' => $diff])));
|
||||
$request->session()->flash('warning', strval(trans('firefly.warning_much_data', ['days' => $diff])));
|
||||
}
|
||||
|
||||
Session::put('is_custom_range', $isCustomRange);
|
||||
Session::put('start', $start);
|
||||
Session::put('end', $end);
|
||||
$request->session()->put('is_custom_range', $isCustomRange);
|
||||
Log::debug(sprintf('Set is_custom_range to %s', var_export($isCustomRange, true)));
|
||||
$request->session()->put('start', $start);
|
||||
Log::debug(sprintf('Set start to %s', $start->format('Y-m-d H:i:s')));
|
||||
$request->session()->put('end', $end);
|
||||
Log::debug(sprintf('Set end to %s', $end->format('Y-m-d H:i:s')));
|
||||
|
||||
return Response::json(['ok' => 'ok']);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,7 +105,7 @@ class HomeController extends Controller
|
||||
*/
|
||||
public function displayDebug(Request $request)
|
||||
{
|
||||
$phpVersion = PHP_VERSION;
|
||||
$phpVersion = str_replace('~', '\~', PHP_VERSION);
|
||||
$phpOs = php_uname();
|
||||
$interface = PHP_SAPI;
|
||||
$now = Carbon::create()->format('Y-m-d H:i:s e');
|
||||
@ -164,7 +177,21 @@ class HomeController extends Controller
|
||||
{
|
||||
Preferences::mark();
|
||||
$request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range']);
|
||||
Log::debug('Call cache:clear...');
|
||||
Artisan::call('cache:clear');
|
||||
Log::debug('Call config:clear...');
|
||||
Artisan::call('config:clear');
|
||||
Log::debug('Call route:clear...');
|
||||
Artisan::call('route:clear');
|
||||
Log::debug('Call twig:clean...');
|
||||
try {
|
||||
Artisan::call('twig:clean');
|
||||
} catch (Exception $e) {
|
||||
// dont care
|
||||
}
|
||||
Log::debug('Call view:clear...');
|
||||
Artisan::call('view:clear');
|
||||
Log::debug('Done! Redirecting...');
|
||||
|
||||
return redirect(route('index'));
|
||||
}
|
||||
@ -182,7 +209,6 @@ class HomeController extends Controller
|
||||
if (0 === $count) {
|
||||
return redirect(route('new-user.index'));
|
||||
}
|
||||
|
||||
$subTitle = trans('firefly.welcomeBack');
|
||||
$transactions = [];
|
||||
$frontPage = Preferences::get(
|
||||
@ -209,12 +235,18 @@ class HomeController extends Controller
|
||||
$transactions[] = [$set, $account];
|
||||
}
|
||||
|
||||
// fire check update event:
|
||||
event(new RequestedVersionCheckStatus(auth()->user()));
|
||||
|
||||
return view(
|
||||
'index',
|
||||
compact('count', 'subTitle', 'transactions', 'showDeps', 'billCount', 'start', 'end', 'today')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function routes()
|
||||
{
|
||||
$set = RouteFacade::getRoutes();
|
||||
@ -225,7 +257,7 @@ class HomeController extends Controller
|
||||
'rules.select', 'search.search', 'test-flash', 'transactions.link.delete', 'transactions.link.switch',
|
||||
'two-factor.lost', 'report.options',
|
||||
];
|
||||
|
||||
$return = ' ';
|
||||
/** @var Route $route */
|
||||
foreach ($set as $route) {
|
||||
$name = $route->getName();
|
||||
@ -237,23 +269,25 @@ class HomeController extends Controller
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
echo 'touch ' . $route->getName() . '.md;';
|
||||
$return .= 'touch ' . $route->getName() . '.md;';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ' ';
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function testFlash()
|
||||
public function testFlash(Request $request)
|
||||
{
|
||||
Session::flash('success', 'This is a success message.');
|
||||
Session::flash('info', 'This is an info message.');
|
||||
Session::flash('warning', 'This is a warning.');
|
||||
Session::flash('error', 'This is an error!');
|
||||
$request->session()->flash('success', 'This is a success message.');
|
||||
$request->session()->flash('info', 'This is an info message.');
|
||||
$request->session()->flash('warning', 'This is a warning.');
|
||||
$request->session()->flash('error', 'This is an error!');
|
||||
|
||||
return redirect(route('home'));
|
||||
}
|
||||
|
@ -1,158 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* BankController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Support\Import\Information\InformationInterface;
|
||||
use FireflyIII\Support\Import\Prerequisites\PrerequisitesInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
use Session;
|
||||
|
||||
class BankController extends Controller
|
||||
{
|
||||
/**
|
||||
* This method must ask the user all parameters necessary to start importing data. This may not be enough
|
||||
* to finish the import itself (ie. mapping) but it should be enough to begin: accounts to import from,
|
||||
* accounts to import into, data ranges, etc.
|
||||
*
|
||||
* @param string $bank
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
||||
*/
|
||||
public function form(string $bank)
|
||||
{
|
||||
$class = config(sprintf('firefly.import_pre.%s', $bank));
|
||||
/** @var PrerequisitesInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser(auth()->user());
|
||||
|
||||
if ($object->hasPrerequisites()) {
|
||||
return redirect(route('import.bank.prerequisites', [$bank]));
|
||||
}
|
||||
$class = config(sprintf('firefly.import_info.%s', $bank));
|
||||
/** @var InformationInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser(auth()->user());
|
||||
$remoteAccounts = $object->getAccounts();
|
||||
|
||||
return view('import.bank.form', compact('remoteAccounts', 'bank'));
|
||||
}
|
||||
|
||||
/**
|
||||
* With the information given in the submitted form Firefly III will call upon the bank's classes to return transaction
|
||||
* information as requested. The user will be able to map unknown data and continue. Or maybe, it's put into some kind of
|
||||
* fake CSV file and forwarded to the import routine.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $bank
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|null
|
||||
*/
|
||||
public function postForm(Request $request, string $bank)
|
||||
{
|
||||
$class = config(sprintf('firefly.import_pre.%s', $bank));
|
||||
/** @var PrerequisitesInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser(auth()->user());
|
||||
|
||||
if ($object->hasPrerequisites()) {
|
||||
return redirect(route('import.bank.prerequisites', [$bank]));
|
||||
}
|
||||
$remoteAccounts = $request->get('do_import');
|
||||
if (!is_array($remoteAccounts) || 0 === count($remoteAccounts)) {
|
||||
Session::flash('error', 'Must select accounts');
|
||||
|
||||
return redirect(route('import.bank.form', [$bank]));
|
||||
}
|
||||
$remoteAccounts = array_keys($remoteAccounts);
|
||||
$class = config(sprintf('firefly.import_pre.%s', $bank));
|
||||
// get import file
|
||||
unset($remoteAccounts, $class);
|
||||
|
||||
// get import config
|
||||
}
|
||||
|
||||
/**
|
||||
* This method processes the prerequisites the user has entered in the previous step.
|
||||
*
|
||||
* Whatever storePrerequisites does, it should make sure that the system is ready to continue immediately. So
|
||||
* no extra calls or stuff, except maybe to open a session
|
||||
*
|
||||
* @see PrerequisitesInterface::storePrerequisites
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $bank
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function postPrerequisites(Request $request, string $bank)
|
||||
{
|
||||
Log::debug(sprintf('Now in postPrerequisites for %s', $bank));
|
||||
$class = config(sprintf('firefly.import_pre.%s', $bank));
|
||||
/** @var PrerequisitesInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser(auth()->user());
|
||||
if (!$object->hasPrerequisites()) {
|
||||
Log::debug(sprintf('No more prerequisites for %s, move to form.', $bank));
|
||||
|
||||
return redirect(route('import.bank.form', [$bank]));
|
||||
}
|
||||
Log::debug('Going to store entered preprerequisites.');
|
||||
// store post data
|
||||
$result = $object->storePrerequisites($request);
|
||||
|
||||
if ($result->count() > 0) {
|
||||
Session::flash('error', $result->first());
|
||||
|
||||
return redirect(route('import.bank.prerequisites', [$bank]));
|
||||
}
|
||||
|
||||
return redirect(route('import.bank.form', [$bank]));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method shows you, if necessary, a form that allows you to enter any required values, such as API keys,
|
||||
* login passwords or other values.
|
||||
*
|
||||
* @param string $bank
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
||||
*/
|
||||
public function prerequisites(string $bank)
|
||||
{
|
||||
$class = config(sprintf('firefly.import_pre.%s', $bank));
|
||||
/** @var PrerequisitesInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser(auth()->user());
|
||||
|
||||
if ($object->hasPrerequisites()) {
|
||||
$view = $object->getView();
|
||||
$parameters = $object->getViewParameters();
|
||||
|
||||
return view($view, $parameters);
|
||||
}
|
||||
|
||||
return redirect(route('import.bank.form', [$bank]));
|
||||
}
|
||||
}
|
144
app/Http/Controllers/Import/ConfigurationController.php
Normal file
144
app/Http/Controllers/Import/ConfigurationController.php
Normal file
@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/**
|
||||
* ConfigurationController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Import\Configuration\ConfiguratorInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class ConfigurationController
|
||||
*/
|
||||
class ConfigurationController extends Controller
|
||||
{
|
||||
/** @var ImportJobRepositoryInterface */
|
||||
public $repository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-archive');
|
||||
app('view')->share('title', trans('firefly.import_index_title'));
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class)->except(['index']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the job. This method is returned to until job is deemed "configured".
|
||||
*
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function index(ImportJob $job)
|
||||
{
|
||||
// create configuration class:
|
||||
$configurator = $this->makeConfigurator($job);
|
||||
|
||||
// is the job already configured?
|
||||
if ($configurator->isJobConfigured()) {
|
||||
$this->repository->updateStatus($job, 'configured');
|
||||
|
||||
return redirect(route('import.status', [$job->key]));
|
||||
}
|
||||
$this->repository->updateStatus($job, 'configuring');
|
||||
$view = $configurator->getNextView();
|
||||
$data = $configurator->getNextData();
|
||||
$subTitle = trans('firefly.import_config_bread_crumb');
|
||||
$subTitleIcon = 'fa-wrench';
|
||||
|
||||
return view($view, compact('data', 'job', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the configuration. Returns to "configure" method until job is configured.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function post(Request $request, ImportJob $job)
|
||||
{
|
||||
Log::debug('Now in postConfigure()', ['job' => $job->key]);
|
||||
$configurator = $this->makeConfigurator($job);
|
||||
|
||||
// is the job already configured?
|
||||
if ($configurator->isJobConfigured()) {
|
||||
return redirect(route('import.status', [$job->key]));
|
||||
}
|
||||
$data = $request->all();
|
||||
$configurator->configureJob($data);
|
||||
|
||||
// get possible warning from configurator:
|
||||
$warning = $configurator->getWarningMessage();
|
||||
|
||||
if (strlen($warning) > 0) {
|
||||
$request->session()->flash('warning', $warning);
|
||||
}
|
||||
|
||||
// return to configure
|
||||
return redirect(route('import.configure', [$job->key]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return ConfiguratorInterface
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function makeConfigurator(ImportJob $job): ConfiguratorInterface
|
||||
{
|
||||
$type = $job->file_type;
|
||||
$key = sprintf('import.configuration.%s', $type);
|
||||
$className = config($key);
|
||||
if (null === $className || !class_exists($className)) {
|
||||
throw new FireflyException(sprintf('Cannot find configurator class for job of type "%s".', $type)); // @codeCoverageIgnore
|
||||
}
|
||||
/** @var ConfiguratorInterface $configurator */
|
||||
$configurator = app($className);
|
||||
$configurator->setJob($job);
|
||||
|
||||
return $configurator;
|
||||
}
|
||||
}
|
@ -1,311 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* FileController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Requests\ImportUploadRequest;
|
||||
use FireflyIII\Import\Configurator\ConfiguratorInterface;
|
||||
use FireflyIII\Import\Routine\ImportRoutine;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response as LaravelResponse;
|
||||
use Log;
|
||||
use Response;
|
||||
use Session;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class FileController.
|
||||
*/
|
||||
class FileController extends Controller
|
||||
{
|
||||
/** @var ImportJobRepositoryInterface */
|
||||
public $repository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('mainTitleIcon', 'fa-archive');
|
||||
View::share('title', trans('firefly.import_index_title'));
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is step 3. This repeats until the job is configured.
|
||||
*
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return View
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function configure(ImportJob $job)
|
||||
{
|
||||
// create configuration class:
|
||||
$configurator = $this->makeConfigurator($job);
|
||||
|
||||
// is the job already configured?
|
||||
if ($configurator->isJobConfigured()) {
|
||||
$this->repository->updateStatus($job, 'configured');
|
||||
|
||||
return redirect(route('import.file.status', [$job->key]));
|
||||
}
|
||||
$view = $configurator->getNextView();
|
||||
$data = $configurator->getNextData();
|
||||
$subTitle = trans('firefly.import_config_bread_crumb');
|
||||
$subTitleIcon = 'fa-wrench';
|
||||
|
||||
return view($view, compact('data', 'job', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a JSON file of the job's configuration and send it to the user.
|
||||
*
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return LaravelResponse
|
||||
*/
|
||||
public function download(ImportJob $job)
|
||||
{
|
||||
Log::debug('Now in download()', ['job' => $job->key]);
|
||||
$config = $job->configuration;
|
||||
|
||||
// This is CSV import specific:
|
||||
$config['column-roles-complete'] = false;
|
||||
$config['column-mapping-complete'] = false;
|
||||
$config['initial-config-complete'] = false;
|
||||
$config['delimiter'] = "\t" === $config['delimiter'] ? 'tab' : $config['delimiter'];
|
||||
|
||||
$result = json_encode($config, JSON_PRETTY_PRINT);
|
||||
$name = sprintf('"%s"', addcslashes('import-configuration-' . date('Y-m-d') . '.json', '"\\'));
|
||||
|
||||
/** @var LaravelResponse $response */
|
||||
$response = response($result, 200);
|
||||
$response->header('Content-disposition', 'attachment; filename=' . $name)
|
||||
->header('Content-Type', 'application/json')
|
||||
->header('Content-Description', 'File Transfer')
|
||||
->header('Connection', 'Keep-Alive')
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', strlen($result));
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is step 1. Upload a file.
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$subTitle = trans('firefly.import_index_sub_title');
|
||||
$subTitleIcon = 'fa-home';
|
||||
$importFileTypes = [];
|
||||
$defaultImportType = config('firefly.default_import_format');
|
||||
|
||||
foreach (array_keys(config('firefly.import_formats')) as $type) {
|
||||
$importFileTypes[$type] = trans('firefly.import_file_type_' . $type);
|
||||
}
|
||||
|
||||
return view('import.file.index', compact('subTitle', 'subTitleIcon', 'importFileTypes', 'defaultImportType'));
|
||||
}
|
||||
|
||||
/**
|
||||
* This is step 2. It creates an Import Job. Stores the import.
|
||||
*
|
||||
* @param ImportUploadRequest $request
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function initialize(ImportUploadRequest $request)
|
||||
{
|
||||
Log::debug('Now in initialize()');
|
||||
|
||||
// create import job:
|
||||
$type = $request->get('import_file_type');
|
||||
$job = $this->repository->create($type);
|
||||
Log::debug('Created new job', ['key' => $job->key, 'id' => $job->id]);
|
||||
|
||||
// process file:
|
||||
$this->repository->processFile($job, $request->files->get('import_file'));
|
||||
|
||||
// process config, if present:
|
||||
if ($request->files->has('configuration_file')) {
|
||||
$this->repository->processConfiguration($job, $request->files->get('configuration_file'));
|
||||
}
|
||||
|
||||
$this->repository->updateStatus($job, 'initialized');
|
||||
|
||||
return redirect(route('import.file.configure', [$job->key]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show status of import job in JSON.
|
||||
*
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function json(ImportJob $job)
|
||||
{
|
||||
$result = [
|
||||
'started' => false,
|
||||
'finished' => false,
|
||||
'running' => false,
|
||||
'errors' => array_values($job->extended_status['errors']),
|
||||
'percentage' => 0,
|
||||
'show_percentage' => false,
|
||||
'steps' => $job->extended_status['steps'],
|
||||
'done' => $job->extended_status['done'],
|
||||
'statusText' => trans('firefly.import_status_job_' . $job->status),
|
||||
'status' => $job->status,
|
||||
'finishedText' => '',
|
||||
];
|
||||
|
||||
if (0 !== $job->extended_status['steps']) {
|
||||
$result['percentage'] = round(($job->extended_status['done'] / $job->extended_status['steps']) * 100, 0);
|
||||
$result['show_percentage'] = true;
|
||||
}
|
||||
|
||||
if ('finished' === $job->status) {
|
||||
$tagId = $job->extended_status['tag'];
|
||||
/** @var TagRepositoryInterface $repository */
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$tag = $repository->find($tagId);
|
||||
$result['finished'] = true;
|
||||
$result['finishedText'] = trans('firefly.import_status_finished_job', ['link' => route('tags.show', [$tag->id, 'all']), 'tag' => $tag->tag]);
|
||||
}
|
||||
|
||||
if ('running' === $job->status) {
|
||||
$result['started'] = true;
|
||||
$result['running'] = true;
|
||||
}
|
||||
|
||||
return Response::json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Step 4. Save the configuration.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function postConfigure(Request $request, ImportJob $job)
|
||||
{
|
||||
Log::debug('Now in postConfigure()', ['job' => $job->key]);
|
||||
$configurator = $this->makeConfigurator($job);
|
||||
|
||||
// is the job already configured?
|
||||
if ($configurator->isJobConfigured()) {
|
||||
return redirect(route('import.file.status', [$job->key]));
|
||||
}
|
||||
$data = $request->all();
|
||||
$configurator->configureJob($data);
|
||||
|
||||
// get possible warning from configurator:
|
||||
$warning = $configurator->getWarningMessage();
|
||||
|
||||
if (strlen($warning) > 0) {
|
||||
Session::flash('warning', $warning);
|
||||
}
|
||||
|
||||
// return to configure
|
||||
return redirect(route('import.file.configure', [$job->key]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function start(ImportJob $job)
|
||||
{
|
||||
/** @var ImportRoutine $routine */
|
||||
$routine = app(ImportRoutine::class);
|
||||
$routine->setJob($job);
|
||||
$result = $routine->run();
|
||||
if ($result) {
|
||||
return Response::json(['run' => 'ok']);
|
||||
}
|
||||
|
||||
throw new FireflyException('Job did not complete succesfully.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
|
||||
*/
|
||||
public function status(ImportJob $job)
|
||||
{
|
||||
$statuses = ['configured', 'running', 'finished'];
|
||||
if (!in_array($job->status, $statuses)) {
|
||||
return redirect(route('import.file.configure', [$job->key]));
|
||||
}
|
||||
$subTitle = trans('firefly.import_status_sub_title');
|
||||
$subTitleIcon = 'fa-star';
|
||||
|
||||
return view('import.file.status', compact('job', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return ConfiguratorInterface
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
private function makeConfigurator(ImportJob $job): ConfiguratorInterface
|
||||
{
|
||||
$type = $job->file_type;
|
||||
$key = sprintf('firefly.import_configurators.%s', $type);
|
||||
$className = config($key);
|
||||
if (null === $className) {
|
||||
throw new FireflyException('Cannot find configurator class for this job.'); // @codeCoverageIgnore
|
||||
}
|
||||
/** @var ConfiguratorInterface $configurator */
|
||||
$configurator = app($className);
|
||||
$configurator->setJob($job);
|
||||
|
||||
return $configurator;
|
||||
}
|
||||
}
|
162
app/Http/Controllers/Import/IndexController.php
Normal file
162
app/Http/Controllers/Import/IndexController.php
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
/**
|
||||
* IndexController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Import\Routine\RoutineInterface;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use Illuminate\Http\Response as LaravelResponse;
|
||||
use Log;
|
||||
use Response;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class FileController.
|
||||
*/
|
||||
class IndexController extends Controller
|
||||
{
|
||||
/** @var ImportJobRepositoryInterface */
|
||||
public $repository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-archive');
|
||||
app('view')->share('title', trans('firefly.import_index_title'));
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
|
||||
$this->middleware(IsDemoUser::class)->except(['create', 'index']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new import job for $bank with the default (global) job configuration.
|
||||
*
|
||||
* @param string $bank
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function create(string $bank)
|
||||
{
|
||||
if (true === !(config(sprintf('import.enabled.%s', $bank)))) {
|
||||
throw new FireflyException(sprintf('Cannot import from "%s" at this time.', $bank)); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$importJob = $this->repository->create($bank);
|
||||
|
||||
// from here, always go to configure step.
|
||||
return redirect(route('import.configure', [$importJob->key]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a JSON file of the job's configuration and send it to the user.
|
||||
*
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return LaravelResponse
|
||||
*/
|
||||
public function download(ImportJob $job)
|
||||
{
|
||||
Log::debug('Now in download()', ['job' => $job->key]);
|
||||
$config = $job->configuration;
|
||||
|
||||
// This is CSV import specific:
|
||||
$config['column-roles-complete'] = false;
|
||||
$config['column-mapping-complete'] = false;
|
||||
$config['initial-config-complete'] = false;
|
||||
$config['has-file-upload'] = false;
|
||||
$config['delimiter'] = "\t" === $config['delimiter'] ? 'tab' : $config['delimiter'];
|
||||
|
||||
$result = json_encode($config, JSON_PRETTY_PRINT);
|
||||
$name = sprintf('"%s"', addcslashes('import-configuration-' . date('Y-m-d') . '.json', '"\\'));
|
||||
|
||||
/** @var LaravelResponse $response */
|
||||
$response = response($result, 200);
|
||||
$response->header('Content-disposition', 'attachment; filename=' . $name)
|
||||
->header('Content-Type', 'application/json')
|
||||
->header('Content-Description', 'File Transfer')
|
||||
->header('Connection', 'Keep-Alive')
|
||||
->header('Expires', '0')
|
||||
->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
|
||||
->header('Pragma', 'public')
|
||||
->header('Content-Length', strlen($result));
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* General import index.
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$subTitle = trans('firefly.import_index_sub_title');
|
||||
$subTitleIcon = 'fa-home';
|
||||
$routines = config('import.enabled');
|
||||
|
||||
return view('import.index', compact('subTitle', 'subTitleIcon', 'routines'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function start(ImportJob $job)
|
||||
{
|
||||
$type = $job->file_type;
|
||||
$key = sprintf('import.routine.%s', $type);
|
||||
$className = config($key);
|
||||
if (null === $className || !class_exists($className)) {
|
||||
throw new FireflyException(sprintf('Cannot find import routine class for job of type "%s".', $type)); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/** @var RoutineInterface $routine */
|
||||
$routine = app($className);
|
||||
$routine->setJob($job);
|
||||
$result = $routine->run();
|
||||
|
||||
if ($result) {
|
||||
return Response::json(['run' => 'ok']);
|
||||
}
|
||||
|
||||
throw new FireflyException('Job did not complete successfully. Please review the log files.');
|
||||
}
|
||||
}
|
138
app/Http/Controllers/Import/PrerequisitesController.php
Normal file
138
app/Http/Controllers/Import/PrerequisitesController.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
/**
|
||||
* PrerequisitesController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Import\Prerequisites\PrerequisitesInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* Class PrerequisitesController
|
||||
*/
|
||||
class PrerequisitesController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-archive');
|
||||
app('view')->share('title', trans('firefly.import_index_title'));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsDemoUser::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Once there are no prerequisites, this method will create an importjob object and
|
||||
* redirect the user to a view where this object can be used by a bank specific
|
||||
* class to process.
|
||||
*
|
||||
* @param string $bank
|
||||
*
|
||||
* @return \Illuminate\View\View|\Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function index(string $bank)
|
||||
{
|
||||
if (true === !(config(sprintf('import.enabled.%s', $bank)))) {
|
||||
throw new FireflyException(sprintf('Cannot import from "%s" at this time.', $bank)); // @codeCoverageIgnore
|
||||
}
|
||||
$class = strval(config(sprintf('import.prerequisites.%s', $bank)));
|
||||
if (!class_exists($class)) {
|
||||
throw new FireflyException(sprintf('No class to handle "%s".', $bank)); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
/** @var PrerequisitesInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser(auth()->user());
|
||||
|
||||
if ($object->hasPrerequisites()) {
|
||||
$view = $object->getView();
|
||||
$parameters = ['title' => strval(trans('firefly.import_index_title')), 'mainTitleIcon' => 'fa-archive'];
|
||||
$parameters = array_merge($object->getViewParameters(), $parameters);
|
||||
|
||||
return view($view, $parameters);
|
||||
}
|
||||
|
||||
// if no (more) prerequisites, return to create a job:
|
||||
return redirect(route('import.create-job', [$bank]));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method processes the prerequisites the user has entered in the previous step.
|
||||
*
|
||||
* Whatever storePrerequisites does, it should make sure that the system is ready to continue immediately. So
|
||||
* no extra calls or stuff, except maybe to open a session
|
||||
*
|
||||
* @see PrerequisitesInterface::storePrerequisites
|
||||
*
|
||||
* @param Request $request
|
||||
* @param string $bank
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function post(Request $request, string $bank)
|
||||
{
|
||||
Log::debug(sprintf('Now in postPrerequisites for %s', $bank));
|
||||
|
||||
if (true === !(config(sprintf('import.enabled.%s', $bank)))) {
|
||||
throw new FireflyException(sprintf('Cannot import from "%s" at this time.', $bank)); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$class = strval(config(sprintf('import.prerequisites.%s', $bank)));
|
||||
if (!class_exists($class)) {
|
||||
throw new FireflyException(sprintf('Cannot find class %s', $class)); // @codeCoverageIgnore
|
||||
}
|
||||
/** @var PrerequisitesInterface $object */
|
||||
$object = app($class);
|
||||
$object->setUser(auth()->user());
|
||||
if (!$object->hasPrerequisites()) {
|
||||
Log::debug(sprintf('No more prerequisites for %s, move to form.', $bank));
|
||||
|
||||
return redirect(route('import.create-job', [$bank]));
|
||||
}
|
||||
Log::debug('Going to store entered prerequisites.');
|
||||
// store post data
|
||||
$result = $object->storePrerequisites($request);
|
||||
|
||||
if ($result->count() > 0) {
|
||||
$request->session()->flash('error', $result->first());
|
||||
}
|
||||
|
||||
return redirect(route('import.prerequisites', [$bank]));
|
||||
}
|
||||
}
|
113
app/Http/Controllers/Import/StatusController.php
Normal file
113
app/Http/Controllers/Import/StatusController.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
/**
|
||||
* StatusController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Import;
|
||||
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\ImportJob;
|
||||
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
|
||||
use Response;
|
||||
|
||||
/**
|
||||
* Class StatusController
|
||||
*/
|
||||
class StatusController extends Controller
|
||||
{
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
app('view')->share('mainTitleIcon', 'fa-archive');
|
||||
app('view')->share('title', trans('firefly.import_index_title'));
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
||||
*/
|
||||
public function index(ImportJob $job)
|
||||
{
|
||||
$statuses = ['configured', 'running', 'finished', 'error'];
|
||||
if (!in_array($job->status, $statuses)) {
|
||||
return redirect(route('import.configure', [$job->key]));
|
||||
}
|
||||
$subTitle = trans('import.status_sub_title');
|
||||
$subTitleIcon = 'fa-star';
|
||||
|
||||
return view('import.status', compact('job', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show status of import job in JSON.
|
||||
*
|
||||
* @param ImportJob $job
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function json(ImportJob $job)
|
||||
{
|
||||
$result = [
|
||||
'started' => false,
|
||||
'finished' => false,
|
||||
'running' => false,
|
||||
'errors' => array_values($job->extended_status['errors']),
|
||||
'percentage' => 0,
|
||||
'show_percentage' => false,
|
||||
'steps' => $job->extended_status['steps'],
|
||||
'done' => $job->extended_status['done'],
|
||||
'statusText' => trans('import.status_job_' . $job->status),
|
||||
'status' => $job->status,
|
||||
'finishedText' => '',
|
||||
];
|
||||
|
||||
if (0 !== $job->extended_status['steps']) {
|
||||
$result['percentage'] = round(($job->extended_status['done'] / $job->extended_status['steps']) * 100, 0);
|
||||
$result['show_percentage'] = true;
|
||||
}
|
||||
|
||||
if ('finished' === $job->status) {
|
||||
$tagId = $job->extended_status['tag'];
|
||||
/** @var TagRepositoryInterface $repository */
|
||||
$repository = app(TagRepositoryInterface::class);
|
||||
$tag = $repository->find($tagId);
|
||||
$result['finished'] = true;
|
||||
$result['finishedText'] = trans('import.status_finished_job', ['link' => route('tags.show', [$tag->id, 'all']), 'tag' => $tag->tag]);
|
||||
}
|
||||
|
||||
if ('running' === $job->status) {
|
||||
$result['started'] = true;
|
||||
$result['running'] = true;
|
||||
}
|
||||
|
||||
return Response::json($result);
|
||||
}
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* ImportController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers;
|
||||
|
||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||
use View;
|
||||
|
||||
/**
|
||||
* Class ImportController.
|
||||
*/
|
||||
class ImportController extends Controller
|
||||
{
|
||||
/** @var ImportJobRepositoryInterface */
|
||||
public $repository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('mainTitleIcon', 'fa-archive');
|
||||
View::share('title', trans('firefly.import_index_title'));
|
||||
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* General import index.
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$subTitle = trans('firefly.import_index_sub_title');
|
||||
$subTitleIcon = 'fa-home';
|
||||
$importFileTypes = [];
|
||||
$defaultImportType = config('firefly.default_import_format');
|
||||
|
||||
foreach (array_keys(config('firefly.import_formats')) as $type) {
|
||||
$importFileTypes[$type] = trans('firefly.import_file_type_' . $type);
|
||||
}
|
||||
|
||||
return view('import.index', compact('subTitle', 'subTitleIcon', 'importFileTypes', 'defaultImportType'));
|
||||
}
|
||||
}
|
@ -30,7 +30,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
use Navigation;
|
||||
use Preferences;
|
||||
|
||||
/**
|
||||
@ -89,6 +88,8 @@ class JavascriptController extends Controller
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param AccountRepositoryInterface $repository
|
||||
* @param CurrencyRepositoryInterface $currencyRepository
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
@ -139,34 +140,43 @@ class JavascriptController extends Controller
|
||||
$end = session('end');
|
||||
$first = session('first');
|
||||
$title = sprintf('%s - %s', $start->formatLocalized($this->monthAndDayFormat), $end->formatLocalized($this->monthAndDayFormat));
|
||||
$isCustom = session('is_custom_range');
|
||||
$isCustom = true === session('is_custom_range', false);
|
||||
$today = new Carbon;
|
||||
$ranges = [
|
||||
// first range is the current range:
|
||||
$title => [$start, $end],
|
||||
];
|
||||
Log::debug(sprintf('viewRange is %s', $viewRange));
|
||||
Log::debug(sprintf('isCustom is %s', var_export($isCustom, true)));
|
||||
|
||||
// when current range is a custom range, add the current period as the next range.
|
||||
if ($isCustom) {
|
||||
Log::debug('Custom is true.');
|
||||
$index = Navigation::periodShow($start, $viewRange);
|
||||
$customPeriodStart = Navigation::startOfPeriod($start, $viewRange);
|
||||
$customPeriodEnd = Navigation::endOfPeriod($customPeriodStart, $viewRange);
|
||||
$index = app('navigation')->periodShow($start, $viewRange);
|
||||
$customPeriodStart = app('navigation')->startOfPeriod($start, $viewRange);
|
||||
$customPeriodEnd = app('navigation')->endOfPeriod($customPeriodStart, $viewRange);
|
||||
$ranges[$index] = [$customPeriodStart, $customPeriodEnd];
|
||||
}
|
||||
// then add previous range and next range
|
||||
$previousDate = Navigation::subtractPeriod($start, $viewRange);
|
||||
$index = Navigation::periodShow($previousDate, $viewRange);
|
||||
$previousStart = Navigation::startOfPeriod($previousDate, $viewRange);
|
||||
$previousEnd = Navigation::endOfPeriod($previousStart, $viewRange);
|
||||
$previousDate = app('navigation')->subtractPeriod($start, $viewRange);
|
||||
$index = app('navigation')->periodShow($previousDate, $viewRange);
|
||||
$previousStart = app('navigation')->startOfPeriod($previousDate, $viewRange);
|
||||
$previousEnd = app('navigation')->endOfPeriod($previousStart, $viewRange);
|
||||
$ranges[$index] = [$previousStart, $previousEnd];
|
||||
|
||||
$nextDate = Navigation::addPeriod($start, $viewRange, 0);
|
||||
$index = Navigation::periodShow($nextDate, $viewRange);
|
||||
$nextStart = Navigation::startOfPeriod($nextDate, $viewRange);
|
||||
$nextEnd = Navigation::endOfPeriod($nextStart, $viewRange);
|
||||
$nextDate = app('navigation')->addPeriod($start, $viewRange, 0);
|
||||
$index = app('navigation')->periodShow($nextDate, $viewRange);
|
||||
$nextStart = app('navigation')->startOfPeriod($nextDate, $viewRange);
|
||||
$nextEnd = app('navigation')->endOfPeriod($nextStart, $viewRange);
|
||||
$ranges[$index] = [$nextStart, $nextEnd];
|
||||
|
||||
// today:
|
||||
$todayStart = app('navigation')->startOfPeriod($today, $viewRange);
|
||||
$todayEnd = app('navigation')->endOfPeriod($todayStart, $viewRange);
|
||||
if ($todayStart->ne($start) || $todayEnd->ne($end)) {
|
||||
$ranges[ucfirst(strval(trans('firefly.today')))] = [$todayStart, $todayEnd];
|
||||
}
|
||||
|
||||
// everything
|
||||
$index = strval(trans('firefly.everything'));
|
||||
$ranges[$index] = [$first, new Carbon];
|
||||
|
@ -81,7 +81,7 @@ class AutoCompleteController extends Controller
|
||||
$set = $repository->getAccountsByType([AccountType::EXPENSE, AccountType::BENEFICIARY]);
|
||||
$filtered = $set->filter(
|
||||
function (Account $account) {
|
||||
if ($account->active) {
|
||||
if ($account->active === true) {
|
||||
return $account;
|
||||
}
|
||||
|
||||
@ -138,7 +138,7 @@ class AutoCompleteController extends Controller
|
||||
$set = $repository->getAccountsByType([AccountType::REVENUE]);
|
||||
$filtered = $set->filter(
|
||||
function (Account $account) {
|
||||
if ($account->active) {
|
||||
if ($account->active === true) {
|
||||
return $account;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,8 @@ class FrontpageController extends Controller
|
||||
* @param PiggyBankRepositoryInterface $repository
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function piggyBanks(PiggyBankRepositoryInterface $repository)
|
||||
{
|
||||
|
@ -32,6 +32,8 @@ use Response;
|
||||
class IntroController
|
||||
{
|
||||
/**
|
||||
* Get the intro steps. There are currently no specific routes with an outro step.
|
||||
*
|
||||
* @param string $route
|
||||
* @param string $specificPage
|
||||
*
|
||||
@ -39,12 +41,16 @@ class IntroController
|
||||
*/
|
||||
public function getIntroSteps(string $route, string $specificPage = '')
|
||||
{
|
||||
Log::debug(sprintf('getIntroSteps for route "%s" and page "%s"', $route, $specificPage));
|
||||
$steps = $this->getBasicSteps($route);
|
||||
$specificSteps = $this->getSpecificSteps($route, $specificPage);
|
||||
if (0 === count($specificSteps)) {
|
||||
Log::debug(sprintf('No specific steps for route "%s" and page "%s"', $route, $specificPage));
|
||||
|
||||
return Response::json($steps);
|
||||
}
|
||||
if ($this->hasOutroStep($route)) {
|
||||
// @codeCoverageIgnoreStart
|
||||
// save last step:
|
||||
$lastStep = $steps[count($steps) - 1];
|
||||
// remove last step:
|
||||
@ -52,6 +58,7 @@ class IntroController
|
||||
// merge arrays and add last step again
|
||||
$steps = array_merge($steps, $specificSteps);
|
||||
$steps[] = $lastStep;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
if (!$this->hasOutroStep($route)) {
|
||||
$steps = array_merge($steps, $specificSteps);
|
||||
@ -68,13 +75,16 @@ class IntroController
|
||||
public function hasOutroStep(string $route): bool
|
||||
{
|
||||
$routeKey = str_replace('.', '_', $route);
|
||||
Log::debug(sprintf('Has outro step for route %s', $routeKey));
|
||||
$elements = config(sprintf('intro.%s', $routeKey));
|
||||
if (!is_array($elements)) {
|
||||
return false;
|
||||
}
|
||||
$keys = array_keys($elements);
|
||||
Log::debug('Elements is array', $elements);
|
||||
Log::debug('Keys is', array_keys($elements));
|
||||
Log::debug(sprintf('Keys has "outro": %s', var_export(in_array('outro', array_keys($elements)), true)));
|
||||
|
||||
return in_array('outro', $keys);
|
||||
return in_array('outro', array_keys($elements));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,6 +145,7 @@ class IntroController
|
||||
$steps[] = $currentStep;
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Total basic steps for %s is %d', $routeKey, count($steps)));
|
||||
|
||||
return $steps;
|
||||
}
|
||||
@ -148,6 +159,7 @@ class IntroController
|
||||
private function getSpecificSteps(string $route, string $specificPage): array
|
||||
{
|
||||
$steps = [];
|
||||
$routeKey = '';
|
||||
|
||||
// user is on page with specific instructions:
|
||||
if (strlen($specificPage) > 0) {
|
||||
@ -165,6 +177,7 @@ class IntroController
|
||||
}
|
||||
}
|
||||
}
|
||||
Log::debug(sprintf('Total specific steps for route "%s" and page "%s" (routeKey is "%s") is %d', $route, $specificPage, $routeKey, count($steps)));
|
||||
|
||||
return $steps;
|
||||
}
|
||||
|
@ -46,6 +46,8 @@ class JsonController extends Controller
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function action(Request $request)
|
||||
{
|
||||
@ -120,6 +122,8 @@ class JsonController extends Controller
|
||||
* @param Request $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function trigger(Request $request)
|
||||
{
|
||||
|
@ -56,8 +56,8 @@ class NewUserController extends Controller
|
||||
*/
|
||||
public function index(AccountRepositoryInterface $repository)
|
||||
{
|
||||
View::share('title', trans('firefly.welcome'));
|
||||
View::share('mainTitleIcon', 'fa-fire');
|
||||
app('view')->share('title', trans('firefly.welcome'));
|
||||
app('view')->share('mainTitleIcon', 'fa-fire');
|
||||
|
||||
$types = config('firefly.accountTypesByIdentifier.asset');
|
||||
$count = $repository->count($types);
|
||||
@ -114,7 +114,7 @@ class NewUserController extends Controller
|
||||
'virtualBalance' => 0,
|
||||
'active' => true,
|
||||
'accountRole' => 'defaultAsset',
|
||||
'openingBalance' => round($request->input('bank_balance'), 12),
|
||||
'openingBalance' => $request->input('bank_balance'),
|
||||
'openingBalanceDate' => new Carbon,
|
||||
'currency_id' => intval($request->input('amount_currency_id_bank_balance')),
|
||||
];
|
||||
@ -139,7 +139,7 @@ class NewUserController extends Controller
|
||||
'virtualBalance' => 0,
|
||||
'active' => true,
|
||||
'accountRole' => 'savingAsset',
|
||||
'openingBalance' => round($request->input('savings_balance'), 12),
|
||||
'openingBalance' => $request->input('savings_balance'),
|
||||
'openingBalanceDate' => new Carbon,
|
||||
'currency_id' => intval($request->input('amount_currency_id_bank_balance')),
|
||||
];
|
||||
|
@ -30,7 +30,7 @@ use FireflyIII\Models\PiggyBank;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Log;
|
||||
use Preferences;
|
||||
use Response;
|
||||
@ -52,8 +52,8 @@ class PiggyBankController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', trans('firefly.piggyBanks'));
|
||||
View::share('mainTitleIcon', 'fa-sort-amount-asc');
|
||||
app('view')->share('title', trans('firefly.piggyBanks'));
|
||||
app('view')->share('mainTitleIcon', 'fa-sort-amount-asc');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@ -120,8 +120,6 @@ class PiggyBankController extends Controller
|
||||
$this->rememberPreviousUri('piggy-banks.create.uri');
|
||||
}
|
||||
Session::forget('piggy-banks.create.fromStore');
|
||||
Session::flash('gaEventCategory', 'piggy-banks');
|
||||
Session::flash('gaEventAction', 'create');
|
||||
|
||||
return view('piggy-banks.create', compact('accounts', 'subTitle', 'subTitleIcon'));
|
||||
}
|
||||
@ -137,8 +135,6 @@ class PiggyBankController extends Controller
|
||||
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('piggy-banks.delete.uri');
|
||||
Session::flash('gaEventCategory', 'piggy-banks');
|
||||
Session::flash('gaEventAction', 'delete');
|
||||
|
||||
return view('piggy-banks.delete', compact('piggyBank', 'subTitle'));
|
||||
}
|
||||
@ -188,8 +184,6 @@ class PiggyBankController extends Controller
|
||||
'note' => null === $note ? '' : $note->text,
|
||||
];
|
||||
Session::flash('preFilled', $preFilled);
|
||||
Session::flash('gaEventCategory', 'piggy-banks');
|
||||
Session::flash('gaEventAction', 'edit');
|
||||
|
||||
// put previous url in session if not redirect from store (not "return_to_edit").
|
||||
if (true !== session('piggy-banks.edit.fromUpdate')) {
|
||||
@ -205,17 +199,19 @@ class PiggyBankController extends Controller
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index(PiggyBankRepositoryInterface $piggyRepository)
|
||||
public function index(Request $request, PiggyBankRepositoryInterface $piggyRepository)
|
||||
{
|
||||
/** @var Collection $piggyBanks */
|
||||
$piggyBanks = $piggyRepository->getPiggyBanks();
|
||||
$collection = $piggyRepository->getPiggyBanks();
|
||||
$total = $collection->count();
|
||||
$page = 0 === intval($request->get('page')) ? 1 : intval($request->get('page'));
|
||||
$pageSize = intval(Preferences::get('listPageSize', 50)->data);
|
||||
/** @var Carbon $end */
|
||||
$end = session('end', Carbon::now()->endOfMonth());
|
||||
|
||||
$accounts = [];
|
||||
Log::debug('Looping piggues');
|
||||
/** @var PiggyBank $piggyBank */
|
||||
foreach ($piggyBanks as $piggyBank) {
|
||||
foreach ($collection as $piggyBank) {
|
||||
$piggyBank->savedSoFar = $piggyBank->currentRelevantRep()->currentamount ?? '0';
|
||||
$piggyBank->percentage = 0 !== bccomp('0', $piggyBank->savedSoFar) ? intval($piggyBank->savedSoFar / $piggyBank->targetamount * 100) : 0;
|
||||
$piggyBank->leftToSave = bcsub($piggyBank->targetamount, strval($piggyBank->savedSoFar));
|
||||
@ -242,6 +238,11 @@ class PiggyBankController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
// paginate piggy banks
|
||||
$collection = $collection->slice(($page - 1) * $pageSize, $pageSize);
|
||||
$piggyBanks = new LengthAwarePaginator($collection, $total, $pageSize, $page);
|
||||
$piggyBanks->setPath(route('piggy-banks.index'));
|
||||
|
||||
return view('piggy-banks.index', compact('piggyBanks', 'accounts'));
|
||||
}
|
||||
|
||||
@ -401,7 +402,6 @@ class PiggyBankController extends Controller
|
||||
}
|
||||
$piggyBank = $repository->store($data);
|
||||
|
||||
|
||||
Session::flash('success', strval(trans('firefly.stored_piggy_bank', ['name' => $piggyBank->name])));
|
||||
Preferences::mark();
|
||||
|
||||
|
@ -32,6 +32,7 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\Binder\AccountList;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Route;
|
||||
use InvalidArgumentException;
|
||||
use Response;
|
||||
use View;
|
||||
@ -81,6 +82,11 @@ class ReportController extends Controller
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws \Throwable
|
||||
* @throws \Throwable
|
||||
* @throws \Throwable
|
||||
* @throws \Throwable
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function general(Request $request)
|
||||
{
|
||||
@ -119,6 +125,7 @@ class ReportController extends Controller
|
||||
* @return string
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function balanceAmount(array $attributes): string
|
||||
{
|
||||
@ -156,7 +163,7 @@ class ReportController extends Controller
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function budgetSpentAmount(array $attributes): string
|
||||
{
|
||||
@ -170,11 +177,11 @@ class ReportController extends Controller
|
||||
/**
|
||||
* Returns all expenses in category in range.
|
||||
*
|
||||
* @param $attributes
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function categoryEntry(array $attributes): string
|
||||
{
|
||||
@ -188,11 +195,11 @@ class ReportController extends Controller
|
||||
/**
|
||||
* Returns all the expenses that went to the given expense account.
|
||||
*
|
||||
* @param $attributes
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function expenseEntry(array $attributes): string
|
||||
{
|
||||
@ -206,11 +213,11 @@ class ReportController extends Controller
|
||||
/**
|
||||
* Returns all the incomes that went to the given asset account.
|
||||
*
|
||||
* @param $attributes
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws FireflyException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function incomeEntry(array $attributes): string
|
||||
{
|
||||
@ -231,7 +238,7 @@ class ReportController extends Controller
|
||||
private function parseAttributes(array $attributes): array
|
||||
{
|
||||
$attributes['location'] = $attributes['location'] ?? '';
|
||||
$attributes['accounts'] = AccountList::routeBinder($attributes['accounts'] ?? '', '');
|
||||
$attributes['accounts'] = AccountList::routeBinder($attributes['accounts'] ?? '', new Route('get', '', []));
|
||||
try {
|
||||
$attributes['startDate'] = Carbon::createFromFormat('Ymd', $attributes['startDate']);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
|
@ -26,8 +26,8 @@ use FireflyIII\Http\Requests\TokenFormRequest;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||
use Google2FA;
|
||||
use Illuminate\Http\Request;
|
||||
use PragmaRX\Google2FA\Contracts\Google2FA;
|
||||
use Preferences;
|
||||
use Session;
|
||||
use View;
|
||||
@ -46,8 +46,8 @@ class PreferencesController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', trans('firefly.preferences'));
|
||||
View::share('mainTitleIcon', 'fa-gear');
|
||||
app('view')->share('title', trans('firefly.preferences'));
|
||||
app('view')->share('mainTitleIcon', 'fa-gear');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@ -55,22 +55,23 @@ class PreferencesController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Google2FA $google2fa
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function code(Google2FA $google2fa)
|
||||
public function code()
|
||||
{
|
||||
$domain = $this->getDomain();
|
||||
$secret = $google2fa->generateSecretKey();
|
||||
$secret = Google2FA::generateSecretKey();
|
||||
Session::flash('two-factor-secret', $secret);
|
||||
$image = $google2fa->getQRCodeInline($domain, auth()->user()->email, $secret, 200);
|
||||
$image = Google2FA::getQRCodeInline($domain, auth()->user()->email, $secret, 200);
|
||||
|
||||
return view('preferences.code', compact('image'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function deleteCode()
|
||||
{
|
||||
@ -94,7 +95,7 @@ class PreferencesController extends Controller
|
||||
$viewRange = $viewRangePref->data;
|
||||
$frontPageAccounts = Preferences::get('frontPageAccounts', []);
|
||||
$language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data;
|
||||
$transactionPageSize = Preferences::get('transactionPageSize', 50)->data;
|
||||
$listPageSize = Preferences::get('listPageSize', 50)->data;
|
||||
$customFiscalYear = Preferences::get('customFiscalYear', 0)->data;
|
||||
$showDeps = Preferences::get('showDepositsFrontpage', false)->data;
|
||||
$fiscalYearStartStr = Preferences::get('fiscalYearStart', '01-01')->data;
|
||||
@ -112,7 +113,7 @@ class PreferencesController extends Controller
|
||||
'tjOptionalFields',
|
||||
'viewRange',
|
||||
'customFiscalYear',
|
||||
'transactionPageSize',
|
||||
'listPageSize',
|
||||
'fiscalYearStart',
|
||||
'is2faEnabled',
|
||||
'has2faSecret',
|
||||
@ -173,10 +174,10 @@ class PreferencesController extends Controller
|
||||
Preferences::set('showDepositsFrontpage', $showDepositsFrontpage);
|
||||
|
||||
// save page size:
|
||||
Preferences::set('transactionPageSize', 50);
|
||||
$transactionPageSize = intval($request->get('transactionPageSize'));
|
||||
if ($transactionPageSize > 0 && $transactionPageSize < 1337) {
|
||||
Preferences::set('transactionPageSize', $transactionPageSize);
|
||||
Preferences::set('listPageSize', 50);
|
||||
$listPageSize = intval($request->get('listPageSize'));
|
||||
if ($listPageSize > 0 && $listPageSize < 1337) {
|
||||
Preferences::set('listPageSize', $listPageSize);
|
||||
}
|
||||
|
||||
$twoFactorAuthEnabled = false;
|
||||
|
@ -26,7 +26,8 @@ use Auth;
|
||||
use FireflyIII\Events\UserChangedEmail;
|
||||
use FireflyIII\Exceptions\FireflyException;
|
||||
use FireflyIII\Exceptions\ValidationException;
|
||||
use FireflyIII\Http\Middleware\IsLimitedUser;
|
||||
use FireflyIII\Http\Middleware\IsDemoUser;
|
||||
use FireflyIII\Http\Middleware\IsSandStormUser;
|
||||
use FireflyIII\Http\Requests\DeleteAccountFormRequest;
|
||||
use FireflyIII\Http\Requests\EmailFormRequest;
|
||||
use FireflyIII\Http\Requests\ProfileFormRequest;
|
||||
@ -56,13 +57,14 @@ class ProfileController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', trans('firefly.profile'));
|
||||
View::share('mainTitleIcon', 'fa-user');
|
||||
app('view')->share('title', trans('firefly.profile'));
|
||||
app('view')->share('mainTitleIcon', 'fa-user');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
$this->middleware(IsLimitedUser::class)->except(['confirmEmailChange', 'undoEmailChange']);
|
||||
$this->middleware(IsDemoUser::class)->except(['index']);
|
||||
$this->middleware(IsSandStormUser::class)->except('index');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -91,30 +93,33 @@ class ProfileController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserRepositoryInterface $repository
|
||||
* @param string $token
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function confirmEmailChange(string $token)
|
||||
public function confirmEmailChange(UserRepositoryInterface $repository, string $token)
|
||||
{
|
||||
// find preference with this token value.
|
||||
$set = Preferences::findByName('email_change_confirm_token');
|
||||
$user = null;
|
||||
Log::debug(sprintf('Found %d preferences', $set->count()));
|
||||
/** @var Preference $preference */
|
||||
foreach ($set as $preference) {
|
||||
if ($preference->data === $token) {
|
||||
Log::debug('Found user');
|
||||
$user = $preference->user;
|
||||
}
|
||||
}
|
||||
// update user to clear blocked and blocked_code.
|
||||
if (null === $user) {
|
||||
Log::debug('Found no user');
|
||||
throw new FireflyException('Invalid token.');
|
||||
}
|
||||
$user->blocked = 0;
|
||||
$user->blocked_code = '';
|
||||
$user->save();
|
||||
Log::debug('Will unblock user.');
|
||||
$repository->unblockUser($user);
|
||||
|
||||
// return to login.
|
||||
Session::flash('success', strval(trans('firefly.login_with_new_email')));
|
||||
@ -172,7 +177,7 @@ class ProfileController extends Controller
|
||||
$existing = $repository->findByEmail($newEmail);
|
||||
if (null !== $existing) {
|
||||
// force user logout.
|
||||
$this->guard()->logout();
|
||||
Auth::guard()->logout();
|
||||
$request->session()->invalidate();
|
||||
|
||||
Session::flash('success', strval(trans('firefly.email_changed')));
|
||||
@ -241,14 +246,11 @@ class ProfileController extends Controller
|
||||
Session::flush();
|
||||
$repository->destroy($user);
|
||||
|
||||
Session::flash('gaEventCategory', 'user');
|
||||
Session::flash('gaEventAction', 'delete-account');
|
||||
|
||||
return redirect(route('index'));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*/
|
||||
public function regenerate()
|
||||
{
|
||||
@ -260,6 +262,7 @@ class ProfileController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param UserRepositoryInterface $repository
|
||||
* @param string $token
|
||||
* @param string $hash
|
||||
*
|
||||
@ -267,7 +270,7 @@ class ProfileController extends Controller
|
||||
*
|
||||
* @throws FireflyException
|
||||
*/
|
||||
public function undoEmailChange(string $token, string $hash)
|
||||
public function undoEmailChange(UserRepositoryInterface $repository, string $token, string $hash)
|
||||
{
|
||||
// find preference with this token value.
|
||||
$set = Preferences::findByName('email_change_undo_token');
|
||||
@ -285,6 +288,7 @@ class ProfileController extends Controller
|
||||
// found user.
|
||||
// which email address to return to?
|
||||
$set = Preferences::beginsWith($user, 'previous_email_');
|
||||
/** @var string $match */
|
||||
$match = null;
|
||||
foreach ($set as $entry) {
|
||||
$hashed = hash('sha256', $entry->data);
|
||||
@ -297,10 +301,9 @@ class ProfileController extends Controller
|
||||
throw new FireflyException('Invalid token.');
|
||||
}
|
||||
// change user back
|
||||
$user->email = $match;
|
||||
$user->blocked = 0;
|
||||
$user->blocked_code = '';
|
||||
$user->save();
|
||||
// now actually update user:
|
||||
$repository->changeEmail($user, $match);
|
||||
$repository->unblockUser($user);
|
||||
|
||||
// return to login.
|
||||
Session::flash('success', strval(trans('firefly.login_with_old_email')));
|
||||
|
@ -39,6 +39,8 @@ class AccountController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function general(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
|
@ -40,6 +40,8 @@ class BalanceController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function general(BalanceReportHelperInterface $helper, Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
|
@ -28,7 +28,6 @@ use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
|
||||
/**
|
||||
* Class BudgetController.
|
||||
@ -42,6 +41,8 @@ class BudgetController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function general(BudgetReportHelperInterface $helper, Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -69,6 +70,8 @@ class BudgetController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function period(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -88,7 +91,7 @@ class BudgetController extends Controller
|
||||
$data = $repository->getBudgetPeriodReport($budgets, $accounts, $start, $end);
|
||||
$data[0] = $repository->getNoBudgetPeriodReport($accounts, $start, $end); // append report data for "no budget"
|
||||
$report = $this->filterBudgetPeriodReport($data);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$periods = app('navigation')->listOfPeriods($start, $end);
|
||||
|
||||
$result = view('reports.partials.budget-period', compact('report', 'periods'))->render();
|
||||
$cache->store($result);
|
||||
|
@ -28,7 +28,6 @@ use FireflyIII\Models\Category;
|
||||
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
use Navigation;
|
||||
|
||||
/**
|
||||
* Class CategoryController.
|
||||
@ -41,6 +40,8 @@ class CategoryController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function expenses(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -58,7 +59,7 @@ class CategoryController extends Controller
|
||||
$data = $repository->periodExpenses($categories, $accounts, $start, $end);
|
||||
$data[0] = $repository->periodExpensesNoCategory($accounts, $start, $end);
|
||||
$report = $this->filterReport($data);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$periods = app('navigation')->listOfPeriods($start, $end);
|
||||
$result = view('reports.partials.category-period', compact('report', 'periods'))->render();
|
||||
|
||||
$cache->store($result);
|
||||
@ -72,6 +73,8 @@ class CategoryController extends Controller
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function income(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -89,7 +92,7 @@ class CategoryController extends Controller
|
||||
$data = $repository->periodIncome($categories, $accounts, $start, $end);
|
||||
$data[0] = $repository->periodIncomeNoCategory($accounts, $start, $end);
|
||||
$report = $this->filterReport($data);
|
||||
$periods = Navigation::listOfPeriods($start, $end);
|
||||
$periods = app('navigation')->listOfPeriods($start, $end);
|
||||
$result = view('reports.partials.category-period', compact('report', 'periods'))->render();
|
||||
|
||||
$cache->store($result);
|
||||
@ -105,6 +108,8 @@ class CategoryController extends Controller
|
||||
* @return mixed|string
|
||||
*
|
||||
* @internal param ReportHelperInterface $helper
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function operations(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
|
591
app/Http/Controllers/Report/ExpenseController.php
Normal file
591
app/Http/Controllers/Report/ExpenseController.php
Normal file
@ -0,0 +1,591 @@
|
||||
<?php
|
||||
/**
|
||||
* ExpenseController.php
|
||||
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||
*
|
||||
* This file is part of Firefly III.
|
||||
*
|
||||
* Firefly III is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Firefly III is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace FireflyIII\Http\Controllers\Report;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
|
||||
use FireflyIII\Http\Controllers\Controller;
|
||||
use FireflyIII\Models\Account;
|
||||
use FireflyIII\Models\AccountType;
|
||||
use FireflyIII\Models\Transaction;
|
||||
use FireflyIII\Models\TransactionType;
|
||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||
use FireflyIII\Support\CacheProperties;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Class ExpenseController
|
||||
*/
|
||||
class ExpenseController extends Controller
|
||||
{
|
||||
/** @var AccountRepositoryInterface */
|
||||
protected $accountRepository;
|
||||
|
||||
/**
|
||||
* Constructor for ExpenseController
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
// translations:
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
$this->accountRepository = app(AccountRepositoryInterface::class);
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the overview per budget.
|
||||
*
|
||||
* @param Collection $accounts
|
||||
* @param Collection $expense
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function budget(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
|
||||
{
|
||||
// Properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('expense-budget');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
$cache->addProperty($expense->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
$combined = $this->combineAccounts($expense);
|
||||
$all = new Collection;
|
||||
foreach ($combined as $name => $combi) {
|
||||
$all = $all->merge($combi);
|
||||
}
|
||||
// now find spent / earned:
|
||||
$spent = $this->spentByBudget($accounts, $all, $start, $end);
|
||||
// join arrays somehow:
|
||||
$together = [];
|
||||
foreach ($spent as $categoryId => $spentInfo) {
|
||||
if (!isset($together[$categoryId])) {
|
||||
$together[$categoryId]['spent'] = $spentInfo;
|
||||
$together[$categoryId]['budget'] = $spentInfo['name'];
|
||||
$together[$categoryId]['grand_total'] = '0';
|
||||
}
|
||||
$together[$categoryId]['grand_total'] = bcadd($spentInfo['grand_total'], $together[$categoryId]['grand_total']);
|
||||
}
|
||||
unset($spentInfo);
|
||||
$result = view('reports.partials.exp-budgets', compact('together'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the overview per category (spent and earned).
|
||||
*
|
||||
* @param Collection $accounts
|
||||
* @param Collection $expense
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function category(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
|
||||
{
|
||||
// Properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('expense-category');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
$cache->addProperty($expense->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
$combined = $this->combineAccounts($expense);
|
||||
$all = new Collection;
|
||||
foreach ($combined as $name => $combi) {
|
||||
$all = $all->merge($combi);
|
||||
}
|
||||
// now find spent / earned:
|
||||
$spent = $this->spentByCategory($accounts, $all, $start, $end);
|
||||
$earned = $this->earnedByCategory($accounts, $all, $start, $end);
|
||||
// join arrays somehow:
|
||||
$together = [];
|
||||
foreach ($spent as $categoryId => $spentInfo) {
|
||||
if (!isset($together[$categoryId])) {
|
||||
$together[$categoryId]['spent'] = $spentInfo;
|
||||
$together[$categoryId]['category'] = $spentInfo['name'];
|
||||
$together[$categoryId]['grand_total'] = '0';
|
||||
}
|
||||
$together[$categoryId]['grand_total'] = bcadd($spentInfo['grand_total'], $together[$categoryId]['grand_total']);
|
||||
}
|
||||
unset($spentInfo);
|
||||
foreach ($earned as $categoryId => $earnedInfo) {
|
||||
if (!isset($together[$categoryId])) {
|
||||
$together[$categoryId]['earned'] = $earnedInfo;
|
||||
$together[$categoryId]['category'] = $earnedInfo['name'];
|
||||
$together[$categoryId]['grand_total'] = '0';
|
||||
}
|
||||
$together[$categoryId]['grand_total'] = bcadd($earnedInfo['grand_total'], $together[$categoryId]['grand_total']);
|
||||
}
|
||||
|
||||
$result = view('reports.partials.exp-categories', compact('together'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overview of spending
|
||||
*
|
||||
* @param Collection $accounts
|
||||
* @param Collection $expense
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array|mixed|string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function spent(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
|
||||
{
|
||||
// chart properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('expense-spent');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
$cache->addProperty($expense->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$combined = $this->combineAccounts($expense);
|
||||
$result = [];
|
||||
|
||||
foreach ($combined as $name => $combi) {
|
||||
/**
|
||||
* @var string
|
||||
* @var Collection $combi
|
||||
*/
|
||||
$spent = $this->spentInPeriod($accounts, $combi, $start, $end);
|
||||
$earned = $this->earnedInPeriod($accounts, $combi, $start, $end);
|
||||
$result[$name] = [
|
||||
'spent' => $spent,
|
||||
'earned' => $earned,
|
||||
];
|
||||
}
|
||||
$result = view('reports.partials.exp-not-grouped', compact('result'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
// for period, get spent and earned for each account (by name)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $expense
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function topExpense(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
|
||||
{
|
||||
// Properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('expense-budget');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
$cache->addProperty($expense->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
$combined = $this->combineAccounts($expense);
|
||||
$all = new Collection;
|
||||
foreach ($combined as $name => $combi) {
|
||||
$all = $all->merge($combi);
|
||||
}
|
||||
// get all expenses in period:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($accounts);
|
||||
$collector->setOpposingAccounts($all);
|
||||
$set = $collector->getJournals();
|
||||
$sorted = $set->sortBy(
|
||||
function (Transaction $transaction) {
|
||||
return floatval($transaction->transaction_amount);
|
||||
}
|
||||
);
|
||||
$result = view('reports.partials.top-transactions', compact('sorted'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $expense
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function topIncome(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
|
||||
{
|
||||
// Properties for cache:
|
||||
$cache = new CacheProperties;
|
||||
$cache->addProperty($start);
|
||||
$cache->addProperty($end);
|
||||
$cache->addProperty('expense-budget');
|
||||
$cache->addProperty($accounts->pluck('id')->toArray());
|
||||
$cache->addProperty($expense->pluck('id')->toArray());
|
||||
if ($cache->has()) {
|
||||
return $cache->get(); // @codeCoverageIgnore
|
||||
}
|
||||
$combined = $this->combineAccounts($expense);
|
||||
$all = new Collection;
|
||||
foreach ($combined as $name => $combi) {
|
||||
$all = $all->merge($combi);
|
||||
}
|
||||
// get all expenses in period:
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAccounts($accounts);
|
||||
$collector->setOpposingAccounts($all);
|
||||
$set = $collector->getJournals();
|
||||
$sorted = $set->sortByDesc(
|
||||
function (Transaction $transaction) {
|
||||
return floatval($transaction->transaction_amount);
|
||||
}
|
||||
);
|
||||
$result = view('reports.partials.top-transactions', compact('sorted'))->render();
|
||||
$cache->store($result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function combineAccounts(Collection $accounts): array
|
||||
{
|
||||
$combined = [];
|
||||
/** @var Account $expenseAccount */
|
||||
foreach ($accounts as $expenseAccount) {
|
||||
$collection = new Collection;
|
||||
$collection->push($expenseAccount);
|
||||
|
||||
$revenue = $this->accountRepository->findByName($expenseAccount->name, [AccountType::REVENUE]);
|
||||
if (!is_null($revenue->id)) {
|
||||
$collection->push($revenue);
|
||||
}
|
||||
$combined[$expenseAccount->name] = $collection;
|
||||
}
|
||||
|
||||
return $combined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $assets
|
||||
* @param Collection $opposing
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function earnedByCategory(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAccounts($assets);
|
||||
$collector->setOpposingAccounts($opposing)->withCategoryInformation();
|
||||
$set = $collector->getJournals();
|
||||
$sum = [];
|
||||
// loop to support multi currency
|
||||
foreach ($set as $transaction) {
|
||||
$currencyId = $transaction->transaction_currency_id;
|
||||
$categoryName = $transaction->transaction_category_name;
|
||||
$categoryId = intval($transaction->transaction_category_id);
|
||||
// if null, grab from journal:
|
||||
if (0 === $categoryId) {
|
||||
$categoryName = $transaction->transaction_journal_category_name;
|
||||
$categoryId = intval($transaction->transaction_journal_category_id);
|
||||
}
|
||||
if (0 !== $categoryId) {
|
||||
$categoryName = app('steam')->tryDecrypt($categoryName);
|
||||
}
|
||||
|
||||
// if not set, set to zero:
|
||||
if (!isset($sum[$categoryId][$currencyId])) {
|
||||
$sum[$categoryId] = [
|
||||
'grand_total' => '0',
|
||||
'name' => $categoryName,
|
||||
'per_currency' => [
|
||||
$currencyId => [
|
||||
'sum' => '0',
|
||||
'category' => [
|
||||
'id' => $categoryId,
|
||||
'name' => $categoryName,
|
||||
],
|
||||
'currency' => [
|
||||
'symbol' => $transaction->transaction_currency_symbol,
|
||||
'dp' => $transaction->transaction_currency_dp,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
// add amount
|
||||
$sum[$categoryId]['per_currency'][$currencyId]['sum'] = bcadd(
|
||||
$sum[$categoryId]['per_currency'][$currencyId]['sum'], $transaction->transaction_amount
|
||||
);
|
||||
$sum[$categoryId]['grand_total'] = bcadd($sum[$categoryId]['grand_total'], $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $assets
|
||||
* @param Collection $opposing
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function earnedInPeriod(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setTypes([TransactionType::DEPOSIT])->setAccounts($assets);
|
||||
$collector->setOpposingAccounts($opposing);
|
||||
$set = $collector->getJournals();
|
||||
$sum = [
|
||||
'grand_sum' => '0',
|
||||
'per_currency' => [],
|
||||
];
|
||||
// loop to support multi currency
|
||||
foreach ($set as $transaction) {
|
||||
$currencyId = $transaction->transaction_currency_id;
|
||||
|
||||
// if not set, set to zero:
|
||||
if (!isset($sum['per_currency'][$currencyId])) {
|
||||
$sum['per_currency'][$currencyId] = [
|
||||
'sum' => '0',
|
||||
'currency' => [
|
||||
'symbol' => $transaction->transaction_currency_symbol,
|
||||
'dp' => $transaction->transaction_currency_dp,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
// add amount
|
||||
$sum['per_currency'][$currencyId]['sum'] = bcadd($sum['per_currency'][$currencyId]['sum'], $transaction->transaction_amount);
|
||||
$sum['grand_sum'] = bcadd($sum['grand_sum'], $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $assets
|
||||
* @param Collection $opposing
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function spentByBudget(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($assets);
|
||||
$collector->setOpposingAccounts($opposing)->withBudgetInformation();
|
||||
$set = $collector->getJournals();
|
||||
$sum = [];
|
||||
// loop to support multi currency
|
||||
foreach ($set as $transaction) {
|
||||
$currencyId = $transaction->transaction_currency_id;
|
||||
$budgetName = $transaction->transaction_budget_name;
|
||||
$budgetId = intval($transaction->transaction_budget_id);
|
||||
// if null, grab from journal:
|
||||
if (0 === $budgetId) {
|
||||
$budgetName = $transaction->transaction_journal_budget_name;
|
||||
$budgetId = intval($transaction->transaction_journal_budget_id);
|
||||
}
|
||||
if (0 !== $budgetId) {
|
||||
$budgetName = app('steam')->tryDecrypt($budgetName);
|
||||
}
|
||||
|
||||
// if not set, set to zero:
|
||||
if (!isset($sum[$budgetId][$currencyId])) {
|
||||
$sum[$budgetId] = [
|
||||
'grand_total' => '0',
|
||||
'name' => $budgetName,
|
||||
'per_currency' => [
|
||||
$currencyId => [
|
||||
'sum' => '0',
|
||||
'budget' => [
|
||||
'id' => $budgetId,
|
||||
'name' => $budgetName,
|
||||
],
|
||||
'currency' => [
|
||||
'symbol' => $transaction->transaction_currency_symbol,
|
||||
'dp' => $transaction->transaction_currency_dp,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
// add amount
|
||||
$sum[$budgetId]['per_currency'][$currencyId]['sum'] = bcadd(
|
||||
$sum[$budgetId]['per_currency'][$currencyId]['sum'], $transaction->transaction_amount
|
||||
);
|
||||
$sum[$budgetId]['grand_total'] = bcadd($sum[$budgetId]['grand_total'], $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $assets
|
||||
* @param Collection $opposing
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function spentByCategory(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($assets);
|
||||
$collector->setOpposingAccounts($opposing)->withCategoryInformation();
|
||||
$set = $collector->getJournals();
|
||||
$sum = [];
|
||||
// loop to support multi currency
|
||||
foreach ($set as $transaction) {
|
||||
$currencyId = $transaction->transaction_currency_id;
|
||||
$categoryName = $transaction->transaction_category_name;
|
||||
$categoryId = intval($transaction->transaction_category_id);
|
||||
// if null, grab from journal:
|
||||
if (0 === $categoryId) {
|
||||
$categoryName = $transaction->transaction_journal_category_name;
|
||||
$categoryId = intval($transaction->transaction_journal_category_id);
|
||||
}
|
||||
if (0 !== $categoryId) {
|
||||
$categoryName = app('steam')->tryDecrypt($categoryName);
|
||||
}
|
||||
|
||||
// if not set, set to zero:
|
||||
if (!isset($sum[$categoryId][$currencyId])) {
|
||||
$sum[$categoryId] = [
|
||||
'grand_total' => '0',
|
||||
'name' => $categoryName,
|
||||
'per_currency' => [
|
||||
$currencyId => [
|
||||
'sum' => '0',
|
||||
'category' => [
|
||||
'id' => $categoryId,
|
||||
'name' => $categoryName,
|
||||
],
|
||||
'currency' => [
|
||||
'symbol' => $transaction->transaction_currency_symbol,
|
||||
'dp' => $transaction->transaction_currency_dp,
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
// add amount
|
||||
$sum[$categoryId]['per_currency'][$currencyId]['sum'] = bcadd(
|
||||
$sum[$categoryId]['per_currency'][$currencyId]['sum'], $transaction->transaction_amount
|
||||
);
|
||||
$sum[$categoryId]['grand_total'] = bcadd($sum[$categoryId]['grand_total'], $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $assets
|
||||
* @param Collection $opposing
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function spentInPeriod(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array
|
||||
{
|
||||
/** @var JournalCollectorInterface $collector */
|
||||
$collector = app(JournalCollectorInterface::class);
|
||||
$collector->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setAccounts($assets);
|
||||
$collector->setOpposingAccounts($opposing);
|
||||
$set = $collector->getJournals();
|
||||
$sum = [
|
||||
'grand_sum' => '0',
|
||||
'per_currency' => [],
|
||||
];
|
||||
// loop to support multi currency
|
||||
foreach ($set as $transaction) {
|
||||
$currencyId = $transaction->transaction_currency_id;
|
||||
|
||||
// if not set, set to zero:
|
||||
if (!isset($sum['per_currency'][$currencyId])) {
|
||||
$sum['per_currency'][$currencyId] = [
|
||||
'sum' => '0',
|
||||
'currency' => [
|
||||
'symbol' => $transaction->transaction_currency_symbol,
|
||||
'dp' => $transaction->transaction_currency_dp,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
// add amount
|
||||
$sum['per_currency'][$currencyId]['sum'] = bcadd($sum['per_currency'][$currencyId]['sum'], $transaction->transaction_amount);
|
||||
$sum['grand_sum'] = bcadd($sum['grand_sum'], $transaction->transaction_amount);
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
}
|
@ -40,6 +40,8 @@ class OperationsController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function expenses(AccountTaskerInterface $tasker, Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -67,6 +69,8 @@ class OperationsController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function income(AccountTaskerInterface $tasker, Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -95,6 +99,8 @@ class OperationsController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return mixed|string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function operations(AccountTaskerInterface $tasker, Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
|
@ -59,8 +59,8 @@ class ReportController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', trans('firefly.reports'));
|
||||
View::share('mainTitleIcon', 'fa-line-chart');
|
||||
app('view')->share('title', trans('firefly.reports'));
|
||||
app('view')->share('mainTitleIcon', 'fa-line-chart');
|
||||
View::share('subTitleIcon', 'fa-calendar');
|
||||
|
||||
return $next($request);
|
||||
@ -70,10 +70,47 @@ class ReportController extends Controller
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Collection $expense
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function accountReport(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
|
||||
{
|
||||
if ($end < $start) {
|
||||
return view('error')->with('message', trans('firefly.end_after_start_date')); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
if ($start < session('first')) {
|
||||
$start = session('first');
|
||||
}
|
||||
|
||||
View::share(
|
||||
'subTitle', trans(
|
||||
'firefly.report_account',
|
||||
['start' => $start->formatLocalized($this->monthFormat), 'end' => $end->formatLocalized($this->monthFormat)]
|
||||
)
|
||||
);
|
||||
|
||||
$generator = ReportGeneratorFactory::reportGenerator('Account', $start, $end);
|
||||
$generator->setAccounts($accounts);
|
||||
$generator->setExpense($expense);
|
||||
$result = $generator->generate();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Collection $accounts
|
||||
* @param Carbon $start
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function auditReport(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -109,6 +146,8 @@ class ReportController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function budgetReport(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -145,6 +184,8 @@ class ReportController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function categoryReport(Collection $accounts, Collection $categories, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -180,6 +221,8 @@ class ReportController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function defaultReport(Collection $accounts, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -230,6 +273,8 @@ class ReportController extends Controller
|
||||
* @param string $reportType
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function options(string $reportType)
|
||||
{
|
||||
@ -246,6 +291,9 @@ class ReportController extends Controller
|
||||
case 'tag':
|
||||
$result = $this->tagReportOptions();
|
||||
break;
|
||||
case 'account':
|
||||
$result = $this->accountReportOptions();
|
||||
break;
|
||||
}
|
||||
|
||||
return Response::json(['html' => $result]);
|
||||
@ -255,6 +303,8 @@ class ReportController extends Controller
|
||||
* @param ReportFormRequest $request
|
||||
*
|
||||
* @return RedirectResponse|\Illuminate\Routing\Redirector
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
||||
*/
|
||||
public function postIndex(ReportFormRequest $request)
|
||||
@ -267,6 +317,7 @@ class ReportController extends Controller
|
||||
$categories = join(',', $request->getCategoryList()->pluck('id')->toArray());
|
||||
$budgets = join(',', $request->getBudgetList()->pluck('id')->toArray());
|
||||
$tags = join(',', $request->getTagList()->pluck('tag')->toArray());
|
||||
$expense = join(',', $request->getExpenseList()->pluck('id')->toArray());
|
||||
$uri = route('reports.index');
|
||||
|
||||
if (0 === $request->getAccountList()->count()) {
|
||||
@ -314,6 +365,9 @@ class ReportController extends Controller
|
||||
case 'tag':
|
||||
$uri = route('reports.report.tag', [$accounts, $tags, $start, $end]);
|
||||
break;
|
||||
case 'account':
|
||||
$uri = route('reports.report.account', [$accounts, $expense, $start, $end]);
|
||||
break;
|
||||
}
|
||||
|
||||
return redirect($uri);
|
||||
@ -326,6 +380,8 @@ class ReportController extends Controller
|
||||
* @param Carbon $end
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \FireflyIII\Exceptions\FireflyException
|
||||
*/
|
||||
public function tagReport(Collection $accounts, Collection $tags, Carbon $start, Carbon $end)
|
||||
{
|
||||
@ -357,6 +413,32 @@ class ReportController extends Controller
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function accountReportOptions(): string
|
||||
{
|
||||
/** @var AccountRepositoryInterface $repository */
|
||||
$repository = app(AccountRepositoryInterface::class);
|
||||
$expense = $repository->getActiveAccountsByType([AccountType::EXPENSE]);
|
||||
$revenue = $repository->getActiveAccountsByType([AccountType::REVENUE]);
|
||||
$set = new Collection;
|
||||
$names = $revenue->pluck('name')->toArray();
|
||||
foreach ($expense as $exp) {
|
||||
if (in_array($exp->name, $names)) {
|
||||
$set->push($exp);
|
||||
}
|
||||
}
|
||||
|
||||
$result = view('reports.options.account', compact('set'))->render();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function budgetReportOptions(): string
|
||||
{
|
||||
@ -370,6 +452,8 @@ class ReportController extends Controller
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function categoryReportOptions(): string
|
||||
{
|
||||
@ -383,6 +467,8 @@ class ReportController extends Controller
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function noReportOptions(): string
|
||||
{
|
||||
@ -391,6 +477,8 @@ class ReportController extends Controller
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function tagReportOptions(): string
|
||||
{
|
||||
|
@ -57,8 +57,8 @@ class RuleController extends Controller
|
||||
|
||||
$this->middleware(
|
||||
function ($request, $next) {
|
||||
View::share('title', trans('firefly.rules'));
|
||||
View::share('mainTitleIcon', 'fa-random');
|
||||
app('view')->share('title', trans('firefly.rules'));
|
||||
app('view')->share('mainTitleIcon', 'fa-random');
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
@ -72,6 +72,9 @@ class RuleController extends Controller
|
||||
* @param RuleGroup $ruleGroup
|
||||
*
|
||||
* @return View
|
||||
*
|
||||
* @throws \Throwable
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function create(Request $request, RuleGroup $ruleGroup)
|
||||
{
|
||||
@ -102,8 +105,6 @@ class RuleController extends Controller
|
||||
$this->rememberPreviousUri('rules.create.uri');
|
||||
}
|
||||
Session::forget('rules.create.fromStore');
|
||||
Session::flash('gaEventCategory', 'rules');
|
||||
Session::flash('gaEventAction', 'create-rule');
|
||||
|
||||
return view(
|
||||
'rules.rule.create',
|
||||
@ -124,8 +125,6 @@ class RuleController extends Controller
|
||||
|
||||
// put previous url in session
|
||||
$this->rememberPreviousUri('rules.delete.uri');
|
||||
Session::flash('gaEventCategory', 'rules');
|
||||
Session::flash('gaEventAction', 'delete-rule');
|
||||
|
||||
return view('rules.rule.delete', compact('rule', 'subTitle'));
|
||||
}
|
||||
@ -168,6 +167,11 @@ class RuleController extends Controller
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return View
|
||||
*
|
||||
* @throws \Throwable
|
||||
* @throws \Throwable
|
||||
* @throws \Throwable
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function edit(Request $request, RuleRepositoryInterface $repository, Rule $rule)
|
||||
{
|
||||
@ -203,8 +207,6 @@ class RuleController extends Controller
|
||||
$this->rememberPreviousUri('rules.edit.uri');
|
||||
}
|
||||
Session::forget('rules.edit.fromUpdate');
|
||||
Session::flash('gaEventCategory', 'rules');
|
||||
Session::flash('gaEventAction', 'edit-rule');
|
||||
|
||||
return view(
|
||||
'rules.rule.edit',
|
||||
@ -362,6 +364,8 @@ class RuleController extends Controller
|
||||
* @param TestRuleFormRequest $request
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function testTriggers(TestRuleFormRequest $request)
|
||||
{
|
||||
@ -369,11 +373,11 @@ class RuleController extends Controller
|
||||
$triggers = $this->getValidTriggerList($request);
|
||||
|
||||
if (0 === count($triggers)) {
|
||||
return Response::json(['html' => '', 'warning' => trans('firefly.warning_no_valid_triggers')]);
|
||||
return Response::json(['html' => '', 'warning' => trans('firefly.warning_no_valid_triggers')]); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$limit = config('firefly.test-triggers.limit');
|
||||
$range = config('firefly.test-triggers.range');
|
||||
$limit = intval(config('firefly.test-triggers.limit'));
|
||||
$range = intval(config('firefly.test-triggers.range'));
|
||||
|
||||
/** @var TransactionMatcher $matcher */
|
||||
$matcher = app(TransactionMatcher::class);
|
||||
@ -385,10 +389,10 @@ class RuleController extends Controller
|
||||
// Warn the user if only a subset of transactions is returned
|
||||
$warning = '';
|
||||
if (count($matchingTransactions) === $limit) {
|
||||
$warning = trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]);
|
||||
$warning = trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]); // @codeCoverageIgnore
|
||||
}
|
||||
if (0 === count($matchingTransactions)) {
|
||||
$warning = trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]);
|
||||
$warning = trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// Return json response
|
||||
@ -409,17 +413,19 @@ class RuleController extends Controller
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function testTriggersByRule(Rule $rule)
|
||||
{
|
||||
$triggers = $rule->ruleTriggers;
|
||||
|
||||
if (0 === count($triggers)) {
|
||||
return Response::json(['html' => '', 'warning' => trans('firefly.warning_no_valid_triggers')]);
|
||||
return Response::json(['html' => '', 'warning' => trans('firefly.warning_no_valid_triggers')]); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
$limit = config('firefly.test-triggers.limit');
|
||||
$range = config('firefly.test-triggers.range');
|
||||
$limit = intval(config('firefly.test-triggers.limit'));
|
||||
$range = intval(config('firefly.test-triggers.range'));
|
||||
|
||||
/** @var TransactionMatcher $matcher */
|
||||
$matcher = app(TransactionMatcher::class);
|
||||
@ -431,10 +437,10 @@ class RuleController extends Controller
|
||||
// Warn the user if only a subset of transactions is returned
|
||||
$warning = '';
|
||||
if (count($matchingTransactions) === $limit) {
|
||||
$warning = trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]);
|
||||
$warning = trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]); // @codeCoverageIgnore
|
||||
}
|
||||
if (0 === count($matchingTransactions)) {
|
||||
$warning = trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]);
|
||||
$warning = trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]); // @codeCoverageIgnore
|
||||
}
|
||||
|
||||
// Return json response
|
||||
@ -533,6 +539,8 @@ class RuleController extends Controller
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function getCurrentActions(Rule $rule)
|
||||
{
|
||||
@ -561,6 +569,8 @@ class RuleController extends Controller
|
||||
* @param Rule $rule
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function getCurrentTriggers(Rule $rule)
|
||||
{
|
||||
@ -591,6 +601,8 @@ class RuleController extends Controller
|
||||
* @param Request $request
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function getPreviousActions(Request $request)
|
||||
{
|
||||
@ -620,6 +632,8 @@ class RuleController extends Controller
|
||||
* @param Request $request
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
private function getPreviousTriggers(Request $request)
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user