diff --git a/.codeclimate.yml b/.codeclimate.yml index 3beadbce4a..6dbf8e0cae 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,26 +1,50 @@ -# Save as .codeclimate.yml (note leading .) in project root directory -languages: - JavaScript: true - PHP: true +--- +engines: + csslint: + enabled: true + duplication: + enabled: true + config: + languages: + - ruby + - javascript + - python + - php + eslint: + enabled: true + fixme: + enabled: true + phpmd: + enabled: true +ratings: + paths: + - "**.css" + - "**.inc" + - "**.js" + - "**.jsx" + - "**.module" + - "**.php" + - "**.py" + - "**.rb" exclude_paths: -- "gulpfile.js" -- "public/packages/maximebf/php-debugbar/debugbar.js" -- "public/packages/maximebf/php-debugbar/widgets.js" -- "public/packages/maximebf/php-debugbar/openhandler.js" -- "public/packages/maximebf/php-debugbar/widgets/sqlqueries/widget.js" -- "public/js/bootstrap3-typeahead.min.js" -- "public/js/bootstrap-sortable.js" -- "public/js/bootstrap-tagsinput.min.js" -- "public/js/bootstrap-tagsinput.min.js.map" -- "public/js/daterangepicker.js" -- "public/js/jquery-2.1.3.min.js" -- "public/js/jquery-2.1.3.min.js.map" -- "public/js/jquery-ui.min.js" -- "public/js/metisMenu.js" -- "public/js/moment.min.js" -- "public/js/sb-admin-2.js" -- "public/bootstrap/*" -- "resources/lang/*" -- "tests/*" -- "database/*" -- "storage/*" +- gulpfile.js +- public/packages/maximebf/php-debugbar/debugbar.js +- public/packages/maximebf/php-debugbar/widgets.js +- public/packages/maximebf/php-debugbar/openhandler.js +- public/packages/maximebf/php-debugbar/widgets/sqlqueries/widget.js +- public/js/bootstrap3-typeahead.min.js +- public/js/bootstrap-sortable.js +- public/js/bootstrap-tagsinput.min.js +- public/js/bootstrap-tagsinput.min.js.map +- public/js/daterangepicker.js +- public/js/jquery-2.1.3.min.js +- public/js/jquery-2.1.3.min.js.map +- public/js/jquery-ui.min.js +- public/js/metisMenu.js +- public/js/moment.min.js +- public/js/sb-admin-2.js +- public/bootstrap/* +- resources/lang/* +- tests/* +- database/* +- storage/* diff --git a/.csslintrc b/.csslintrc new file mode 100644 index 0000000000..aacba956e5 --- /dev/null +++ b/.csslintrc @@ -0,0 +1,2 @@ +--exclude-exts=.min.css +--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000000..96212a3593 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +**/*{.,-}min.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000000..9faa37508e --- /dev/null +++ b/.eslintrc @@ -0,0 +1,213 @@ +ecmaFeatures: + modules: true + jsx: true + +env: + amd: true + browser: true + es6: true + jquery: true + node: true + +# http://eslint.org/docs/rules/ +rules: + # Possible Errors + comma-dangle: [2, never] + no-cond-assign: 2 + no-console: 0 + no-constant-condition: 2 + no-control-regex: 2 + no-debugger: 2 + no-dupe-args: 2 + no-dupe-keys: 2 + no-duplicate-case: 2 + no-empty: 2 + no-empty-character-class: 2 + no-ex-assign: 2 + no-extra-boolean-cast: 2 + no-extra-parens: 0 + no-extra-semi: 2 + no-func-assign: 2 + no-inner-declarations: [2, functions] + no-invalid-regexp: 2 + no-irregular-whitespace: 2 + no-negated-in-lhs: 2 + no-obj-calls: 2 + no-regex-spaces: 2 + no-sparse-arrays: 2 + no-unexpected-multiline: 2 + no-unreachable: 2 + use-isnan: 2 + valid-jsdoc: 0 + valid-typeof: 2 + + # Best Practices + accessor-pairs: 2 + block-scoped-var: 0 + complexity: [2, 6] + consistent-return: 0 + curly: 0 + default-case: 0 + dot-location: 0 + dot-notation: 0 + eqeqeq: 2 + guard-for-in: 2 + no-alert: 2 + no-caller: 2 + no-case-declarations: 2 + no-div-regex: 2 + no-else-return: 0 + no-empty-label: 2 + no-empty-pattern: 2 + no-eq-null: 2 + no-eval: 2 + no-extend-native: 2 + no-extra-bind: 2 + no-fallthrough: 2 + no-floating-decimal: 0 + no-implicit-coercion: 0 + no-implied-eval: 2 + no-invalid-this: 0 + no-iterator: 2 + no-labels: 0 + no-lone-blocks: 2 + no-loop-func: 2 + no-magic-number: 0 + no-multi-spaces: 0 + no-multi-str: 0 + no-native-reassign: 2 + no-new-func: 2 + no-new-wrappers: 2 + no-new: 2 + no-octal-escape: 2 + no-octal: 2 + no-proto: 2 + no-redeclare: 2 + no-return-assign: 2 + no-script-url: 2 + no-self-compare: 2 + no-sequences: 0 + no-throw-literal: 0 + no-unused-expressions: 2 + no-useless-call: 2 + no-useless-concat: 2 + no-void: 2 + no-warning-comments: 0 + no-with: 2 + radix: 2 + vars-on-top: 0 + wrap-iife: 2 + yoda: 0 + + # Strict + strict: 0 + + # Variables + init-declarations: 0 + no-catch-shadow: 2 + no-delete-var: 2 + no-label-var: 2 + no-shadow-restricted-names: 2 + no-shadow: 0 + no-undef-init: 2 + no-undef: 0 + no-undefined: 0 + no-unused-vars: 0 + no-use-before-define: 0 + + # Node.js and CommonJS + callback-return: 2 + global-require: 2 + handle-callback-err: 2 + no-mixed-requires: 0 + no-new-require: 0 + no-path-concat: 2 + no-process-exit: 2 + no-restricted-modules: 0 + no-sync: 0 + + # Stylistic Issues + array-bracket-spacing: 0 + block-spacing: 0 + brace-style: 0 + camelcase: 0 + comma-spacing: 0 + comma-style: 0 + computed-property-spacing: 0 + consistent-this: 0 + eol-last: 0 + func-names: 0 + func-style: 0 + id-length: 0 + id-match: 0 + indent: 0 + jsx-quotes: 0 + key-spacing: 0 + linebreak-style: 0 + lines-around-comment: 0 + max-depth: 0 + max-len: 0 + max-nested-callbacks: 0 + max-params: 0 + max-statements: [2, 30] + new-cap: 0 + new-parens: 0 + newline-after-var: 0 + no-array-constructor: 0 + no-bitwise: 0 + no-continue: 0 + no-inline-comments: 0 + no-lonely-if: 0 + no-mixed-spaces-and-tabs: 0 + no-multiple-empty-lines: 0 + no-negated-condition: 0 + no-nested-ternary: 0 + no-new-object: 0 + no-plusplus: 0 + no-restricted-syntax: 0 + no-spaced-func: 0 + no-ternary: 0 + no-trailing-spaces: 0 + no-underscore-dangle: 0 + no-unneeded-ternary: 0 + object-curly-spacing: 0 + one-var: 0 + operator-assignment: 0 + operator-linebreak: 0 + padded-blocks: 0 + quote-props: 0 + quotes: 0 + require-jsdoc: 0 + semi-spacing: 0 + semi: 0 + sort-vars: 0 + space-after-keywords: 0 + space-before-blocks: 0 + space-before-function-paren: 0 + space-before-keywords: 0 + space-in-parens: 0 + space-infix-ops: 0 + space-return-throw-case: 0 + space-unary-ops: 0 + spaced-comment: 0 + wrap-regex: 0 + + # ECMAScript 6 + arrow-body-style: 0 + arrow-parens: 0 + arrow-spacing: 0 + constructor-super: 0 + generator-star-spacing: 0 + no-arrow-condition: 0 + no-class-assign: 0 + no-const-assign: 0 + no-dupe-class-members: 0 + no-this-before-super: 0 + no-var: 0 + object-shorthand: 0 + prefer-arrow-callback: 0 + prefer-const: 0 + prefer-reflect: 0 + prefer-spread: 0 + prefer-template: 0 + require-yield: 0 diff --git a/README.md b/README.md index 9145983c08..686bafb2e7 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # Firefly III [![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable)](https://packagist.org/packages/grumpydictator/firefly-iii) -[![Total Downloads](https://poser.pugx.org/grumpydictator/firefly-iii/downloads)](https://packagist.org/packages/grumpydictator/firefly-iii) [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/?branch=master) [![Build Status](https://scrutinizer-ci.com/g/JC5/firefly-iii/badges/build.png?b=master)](https://scrutinizer-ci.com/g/JC5/firefly-iii/build-status/master) [![SensioLabsInsight](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102/mini.png)](https://insight.sensiolabs.com/projects/d44c7012-5f50-41ad-add8-8445330e4102) diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 1abd62f597..99e2dbdaac 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -2,6 +2,7 @@ declare(strict_types = 1); namespace FireflyIII\Exceptions; +use Auth; use ErrorException; use Exception; use Illuminate\Auth\Access\AuthorizationException; @@ -13,7 +14,7 @@ use Mail; use Request; use Swift_TransportException; use Symfony\Component\HttpKernel\Exception\HttpException; -use Auth; + /** * Class Handler * @@ -68,14 +69,11 @@ class Handler extends ExceptionHandler if ($exception instanceof FireflyException || $exception instanceof ErrorException) { - // log - Log::error($exception->getMessage()); - // mail? try { $email = env('SITE_OWNER'); - $user = Auth::user(); - $args = [ + $user = Auth::user(); + $args = [ 'errorMessage' => $exception->getMessage(), 'stacktrace' => $exception->getTraceAsString(), 'file' => $exception->getFile(), @@ -99,7 +97,6 @@ class Handler extends ExceptionHandler // could also not mail! :o Log::error($e->getMessage()); } - } parent::report($exception); diff --git a/app/Helpers/Csv/Converter/AmountComma.php b/app/Helpers/Csv/Converter/AmountComma.php index 8bef0f30bd..46b6ebd606 100644 --- a/app/Helpers/Csv/Converter/AmountComma.php +++ b/app/Helpers/Csv/Converter/AmountComma.php @@ -20,7 +20,7 @@ class AmountComma extends BasicConverter implements ConverterInterface $value = str_replace(',', '.', $this->value); if (is_numeric($value)) { - return floatval($value); + return $value; } return '0'; diff --git a/app/Helpers/Csv/Converter/AssetAccountIban.php b/app/Helpers/Csv/Converter/AssetAccountIban.php index e10ceb344f..8a98e37593 100644 --- a/app/Helpers/Csv/Converter/AssetAccountIban.php +++ b/app/Helpers/Csv/Converter/AssetAccountIban.php @@ -3,8 +3,8 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; use Auth; +use Carbon\Carbon; use FireflyIII\Models\Account; -use FireflyIII\Models\AccountType; /** * Class AssetAccountIban @@ -27,20 +27,29 @@ class AssetAccountIban extends BasicConverter implements ConverterInterface } if (strlen($this->value) > 0) { // find or create new account: - $account = $this->findAccount(); - $accountType = AccountType::where('type', 'Asset account')->first(); + $account = $this->findAccount(); if (is_null($account)) { // create it if doesn't exist. - $account = Account::firstOrCreateEncrypted( // TODO use repository - [ - 'name' => $this->value, - 'iban' => $this->value, - 'user_id' => Auth::user()->id, - 'account_type_id' => $accountType->id, - 'active' => 1, - ] - ); + + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $accountData = [ + 'name' => $this->value, + 'accountType' => 'asset', + 'virtualBalance' => 0, + 'virtualBalanceCurrency' => 1, // hard coded. + 'active' => true, + 'user' => Auth::user()->id, + 'iban' => null, + 'accountNumber' => $this->value, + 'accountRole' => null, + 'openingBalance' => 0, + 'openingBalanceDate' => new Carbon, + 'openingBalanceCurrency' => 1, // hard coded. + + ]; + + $account = $repository->store($accountData); } return $account; diff --git a/app/Helpers/Csv/Converter/AssetAccountName.php b/app/Helpers/Csv/Converter/AssetAccountName.php index 14eb37d1c3..f14e9a6105 100644 --- a/app/Helpers/Csv/Converter/AssetAccountName.php +++ b/app/Helpers/Csv/Converter/AssetAccountName.php @@ -3,6 +3,7 @@ declare(strict_types = 1); namespace FireflyIII\Helpers\Csv\Converter; use Auth; +use Carbon\Carbon; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; @@ -26,7 +27,6 @@ class AssetAccountName extends BasicConverter implements ConverterInterface return $account; } // find or create new account: - $accountType = AccountType::where('type', 'Asset account')->first(); $set = Auth::user()->accounts()->accountTypeIn(['Asset account', 'Default account'])->get(); /** @var Account $entry */ foreach ($set as $entry) { @@ -36,15 +36,25 @@ class AssetAccountName extends BasicConverter implements ConverterInterface } // create it if doesnt exist. - $account = Account::firstOrCreateEncrypted( // TODO use repository - [ - 'name' => $this->value, - 'iban' => '', - 'user_id' => Auth::user()->id, - 'account_type_id' => $accountType->id, - 'active' => 1, - ] - ); + + $repository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface'); + $accountData = [ + 'name' => $this->value, + 'accountType' => 'asset', + 'virtualBalance' => 0, + 'virtualBalanceCurrency' => 1, // hard coded. + 'active' => true, + 'user' => Auth::user()->id, + 'iban' => null, + 'accountNumber' => $this->value, + 'accountRole' => null, + 'openingBalance' => 0, + 'openingBalanceDate' => new Carbon, + 'openingBalanceCurrency' => 1, // hard coded. + + ]; + + $account = $repository->store($accountData); return $account; } diff --git a/app/Helpers/Csv/Converter/AssetAccountNumber.php b/app/Helpers/Csv/Converter/AssetAccountNumber.php index b66ee6a7f4..803fc9763f 100644 --- a/app/Helpers/Csv/Converter/AssetAccountNumber.php +++ b/app/Helpers/Csv/Converter/AssetAccountNumber.php @@ -48,7 +48,7 @@ class AssetAccountNumber extends BasicConverter implements ConverterInterface 'name' => $this->value, 'accountType' => 'asset', 'virtualBalance' => 0, - 'virtualBalanceCurrency' => 1, // TODO hard coded. + 'virtualBalanceCurrency' => 1, // hard coded. 'active' => true, 'user' => Auth::user()->id, 'iban' => null, @@ -56,7 +56,7 @@ class AssetAccountNumber extends BasicConverter implements ConverterInterface 'accountRole' => null, 'openingBalance' => 0, 'openingBalanceDate' => new Carbon, - 'openingBalanceCurrency' => 1, // TODO hard coded. + 'openingBalanceCurrency' => 1, // hard coded. ]; diff --git a/app/Helpers/Csv/Converter/BudgetName.php b/app/Helpers/Csv/Converter/BudgetName.php index e2a017d483..17f80557b5 100644 --- a/app/Helpers/Csv/Converter/BudgetName.php +++ b/app/Helpers/Csv/Converter/BudgetName.php @@ -20,15 +20,10 @@ class BudgetName extends BasicConverter implements ConverterInterface { // is mapped? Then it's easy! if (isset($this->mapped[$this->index][$this->value])) { - $budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]); + $budget = Auth::user()->budgets()->find($this->mapped[$this->index][$this->value]); // see issue #180 } else { - $budget = Budget::firstOrCreateEncrypted( // TODO use repository - [ - 'name' => $this->value, - 'user_id' => Auth::user()->id, - 'active' => true, - ] - ); + $repository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); + $budget = $repository->store(['name' => $this->value, 'user' => Auth::user()->id]); } return $budget; diff --git a/app/Helpers/Csv/Converter/CategoryName.php b/app/Helpers/Csv/Converter/CategoryName.php index 0f1fcc9ccb..c7d7b27aca 100644 --- a/app/Helpers/Csv/Converter/CategoryName.php +++ b/app/Helpers/Csv/Converter/CategoryName.php @@ -22,7 +22,7 @@ class CategoryName extends BasicConverter implements ConverterInterface if (isset($this->mapped[$this->index][$this->value])) { $category = Auth::user()->categories()->find($this->mapped[$this->index][$this->value]); } else { - $category = Category::firstOrCreateEncrypted( // TODO use repository + $category = Category::firstOrCreateEncrypted( // See issue #180 [ 'name' => $this->value, 'user_id' => Auth::user()->id, diff --git a/app/Helpers/Csv/Converter/TagsComma.php b/app/Helpers/Csv/Converter/TagsComma.php index fe1550036a..02ac2bc14a 100644 --- a/app/Helpers/Csv/Converter/TagsComma.php +++ b/app/Helpers/Csv/Converter/TagsComma.php @@ -23,7 +23,7 @@ class TagsComma extends BasicConverter implements ConverterInterface $strings = explode(',', $this->value); foreach ($strings as $string) { - $tag = Tag::firstOrCreateEncrypted( // TODO use repository + $tag = Tag::firstOrCreateEncrypted( // See issue #180 [ 'tag' => $string, 'tagMode' => 'nothing', diff --git a/app/Helpers/Csv/Converter/TagsSpace.php b/app/Helpers/Csv/Converter/TagsSpace.php index d371073679..c0e7b5c4f8 100644 --- a/app/Helpers/Csv/Converter/TagsSpace.php +++ b/app/Helpers/Csv/Converter/TagsSpace.php @@ -23,7 +23,7 @@ class TagsSpace extends BasicConverter implements ConverterInterface $strings = explode(' ', $this->value); foreach ($strings as $string) { - $tag = Tag::firstOrCreateEncrypted( // TODO use repository + $tag = Tag::firstOrCreateEncrypted( // See issue #180 [ 'tag' => $string, 'tagMode' => 'nothing', diff --git a/app/Helpers/Csv/PostProcessing/AssetAccount.php b/app/Helpers/Csv/PostProcessing/AssetAccount.php index a6a8e043c2..e7439bfb7a 100644 --- a/app/Helpers/Csv/PostProcessing/AssetAccount.php +++ b/app/Helpers/Csv/PostProcessing/AssetAccount.php @@ -154,9 +154,9 @@ class AssetAccount implements PostProcessorInterface $name = $this->data['asset-account-name'] ?? ''; $iban = $this->data['asset-account-iban'] ?? ''; - // create if not exists: // TODO should be through repository. + // create if not exists: // See issue #180 $name = strlen($name) > 0 ? $name : $iban; - $account = Account::firstOrCreateEncrypted( // TODO use repository + $account = Account::firstOrCreateEncrypted( [ 'user_id' => Auth::user()->id, 'account_type_id' => $accountType->id, @@ -211,7 +211,8 @@ class AssetAccount implements PostProcessorInterface return $entry; } } - // create if not exists: // TODO use repository + // create if not exists: + // See issue #180 $account = Account::firstOrCreateEncrypted( [ 'user_id' => Auth::user()->id, @@ -249,7 +250,7 @@ class AssetAccount implements PostProcessorInterface 'name' => $accountNumber, 'accountType' => 'asset', 'virtualBalance' => 0, - 'virtualBalanceCurrency' => 1, // TODO hard coded. + 'virtualBalanceCurrency' => 1, // hard coded. 'active' => true, 'user' => Auth::user()->id, 'iban' => null, @@ -257,7 +258,7 @@ class AssetAccount implements PostProcessorInterface 'accountRole' => null, 'openingBalance' => 0, 'openingBalanceDate' => new Carbon, - 'openingBalanceCurrency' => 1, // TODO hard coded. + 'openingBalanceCurrency' => 1, // hard coded. ]; $account = $repository->store($accountData); diff --git a/app/Helpers/Csv/PostProcessing/OpposingAccount.php b/app/Helpers/Csv/PostProcessing/OpposingAccount.php index 969289a636..0bc038bba3 100644 --- a/app/Helpers/Csv/PostProcessing/OpposingAccount.php +++ b/app/Helpers/Csv/PostProcessing/OpposingAccount.php @@ -125,7 +125,7 @@ class OpposingAccount implements PostProcessorInterface // create if not exists: $name = is_string($this->data['opposing-account-name']) && strlen($this->data['opposing-account-name']) > 0 ? $this->data['opposing-account-name'] : $this->data['opposing-account-iban']; - $account = Account::firstOrCreateEncrypted( // TODO use repository + $account = Account::firstOrCreateEncrypted( // See issue #180 [ 'user_id' => Auth::user()->id, 'account_type_id' => $accountType->id, @@ -195,7 +195,7 @@ class OpposingAccount implements PostProcessorInterface } } // create if not exists: - $account = Account::firstOrCreateEncrypted( // TODO use repository + $account = Account::firstOrCreateEncrypted( // See issue #180 [ 'user_id' => Auth::user()->id, 'account_type_id' => $accountType->id, diff --git a/app/Http/Controllers/Chart/CategoryController.php b/app/Http/Controllers/Chart/CategoryController.php index c7e4b02178..a11b148809 100644 --- a/app/Http/Controllers/Chart/CategoryController.php +++ b/app/Http/Controllers/Chart/CategoryController.php @@ -23,6 +23,10 @@ use stdClass; */ class CategoryController extends Controller { + const MAKE_POSITIVE = -1; + const KEEP_POSITIVE = 1; + + /** @var \FireflyIII\Generator\Chart\Category\CategoryChartGeneratorInterface */ protected $generator; @@ -134,32 +138,8 @@ class CategoryController extends Controller return $category->name; } ); - $entries = new Collection; - - while ($start < $end) { // filter the set: - $row = [clone $start]; - $currentSet = $set->filter( // get possibly relevant entries from the big $set - function (Category $category) use ($start) { - return $category->dateFormatted == $start->format('Y-m'); - } - ); - /** @var Category $category */ - foreach ($categories as $category) { // check for each category if its in the current set. - $entry = $currentSet->filter( // if its in there, use the value. - function (Category $cat) use ($category) { - return ($cat->id == $category->id); - } - )->first(); - if (!is_null($entry)) { - $row[] = round($entry->earned, 2); - } else { - $row[] = 0; - } - } - $entries->push($row); - $start->addMonth(); - } - $data = $this->generator->earnedInPeriod($categories, $entries); + $entries = $this->filterCollection($start, $end, $set, $categories); + $data = $this->generator->earnedInPeriod($categories, $entries); $cache->store($data); return $data; @@ -340,42 +320,58 @@ class CategoryController extends Controller return Response::json($cache->get()); // @codeCoverageIgnore } + $set = $repository->spentForAccountsPerMonth($accounts, $start, $end); $categories = $set->unique('id')->sortBy( function (Category $category) { return $category->name; } ); - $entries = new Collection; + + $entries = $this->filterCollection($start, $end, $set, $categories); + $data = $this->generator->spentInPeriod($categories, $entries); + $cache->store($data); + + return $data; + } + + /** + * @param Carbon $start + * @param Carbon $end + * @param Collection $set + * @param Collection $categories + * + * @return Collection + */ + private function filterCollection(Carbon $start, Carbon $end, Collection $set, Collection $categories): Collection + { + $entries = new Collection; while ($start < $end) { // filter the set: $row = [clone $start]; - $currentSet = $set->filter(// get possibly relevant entries from the big $set + $currentSet = $set->filter( // get possibly relevant entries from the big $set function (Category $category) use ($start) { return $category->dateFormatted == $start->format('Y-m'); } ); /** @var Category $category */ - foreach ($categories as $category) {// check for each category if its in the current set. - $entry = $currentSet->filter(// if its in there, use the value. + foreach ($categories as $category) { // check for each category if its in the current set. + $entry = $currentSet->filter( // if its in there, use the value. function (Category $cat) use ($category) { return ($cat->id == $category->id); } )->first(); if (!is_null($entry)) { - $row[] = round(($entry->spent * -1), 2); + $row[] = round($entry->earned, 2); } else { $row[] = 0; } } - $entries->push($row); $start->addMonth(); } - $data = $this->generator->spentInPeriod($categories, $entries); - $cache->store($data); - return $data; + return $entries; } /** @@ -419,5 +415,4 @@ class CategoryController extends Controller return $data; } - } diff --git a/app/Http/Controllers/PiggyBankController.php b/app/Http/Controllers/PiggyBankController.php index 845c5f8e02..2435d37b76 100644 --- a/app/Http/Controllers/PiggyBankController.php +++ b/app/Http/Controllers/PiggyBankController.php @@ -187,8 +187,8 @@ class PiggyBankController extends Controller 'name' => $account->name, 'balance' => Steam::balance($account, $end, true), 'leftForPiggyBanks' => $repository->leftOnAccount($account, $end), - 'sumOfSaved' => $piggyBank->savedSoFar, - 'sumOfTargets' => round($piggyBank->targetamount, 2), + 'sumOfSaved' => strval($piggyBank->savedSoFar), + 'sumOfTargets' => strval(round($piggyBank->targetamount, 2)), 'leftToSave' => $piggyBank->leftToSave, ]; } else { diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index 67869985d0..8a6fe534c9 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -4,7 +4,6 @@ declare(strict_types = 1); namespace FireflyIII\Http\Controllers; use Auth; -use Carbon\Carbon; use FireflyIII\Http\Requests\TagFormRequest; use FireflyIII\Models\Preference; use FireflyIII\Models\Tag; @@ -233,26 +232,7 @@ class TagController extends Controller */ public function store(TagFormRequest $request, TagRepositoryInterface $repository) { - if (Input::get('setTag') == 'true') { - $latitude = $request->get('latitude'); - $longitude = $request->get('longitude'); - $zoomLevel = $request->get('zoomLevel'); - } else { - $latitude = null; - $longitude = null; - $zoomLevel = null; - } - $date = $request->get('date') ?? ''; - - $data = [ - 'tag' => $request->get('tag'), - 'date' => strlen($date) > 0 ? new Carbon($date) : null, - 'description' => $request->get('description') ?? '', - 'latitude' => $latitude, - 'longitude' => $longitude, - 'zoomLevel' => $zoomLevel, - 'tagMode' => $request->get('tagMode'), - ]; + $data = $request->collectTagData(); $repository->store($data); Session::flash('success', 'The tag has been created!'); @@ -279,28 +259,7 @@ class TagController extends Controller */ public function update(TagFormRequest $request, TagRepositoryInterface $repository, Tag $tag) { - if (Input::get('setTag') == 'true') { - $latitude = $request->get('latitude'); - $longitude = $request->get('longitude'); - $zoomLevel = $request->get('zoomLevel'); - } else { - $latitude = null; - $longitude = null; - $zoomLevel = null; - } - $date = $request->get('date') ?? ''; - - $data = [ - 'tag' => $request->get('tag'), - 'date' => strlen($date) > 0 ? new Carbon($date) : null, - 'description' => $request->get('description') ?? '', - 'latitude' => $latitude, - 'longitude' => $longitude, - 'zoomLevel' => $zoomLevel, - 'tagMode' => $request->get('tagMode'), - ]; - - + $data = $request->collectTagData(); $repository->update($tag, $data); Session::flash('success', 'Tag "' . e($data['tag']) . '" updated.'); diff --git a/app/Http/Requests/TagFormRequest.php b/app/Http/Requests/TagFormRequest.php index f9aeafeffc..531770b38f 100644 --- a/app/Http/Requests/TagFormRequest.php +++ b/app/Http/Requests/TagFormRequest.php @@ -3,6 +3,7 @@ declare(strict_types = 1); namespace FireflyIII\Http\Requests; use Auth; +use Carbon\Carbon; use FireflyIII\Models\Tag; use Input; @@ -23,6 +24,37 @@ class TagFormRequest extends Request return Auth::check(); } + /** + * @return array + */ + public function collectTagData() :array + { + if (Input::get('setTag') == 'true') { + $latitude = $this->get('latitude'); + $longitude = $this->get('longitude'); + $zoomLevel = $this->get('zoomLevel'); + } else { + $latitude = null; + $longitude = null; + $zoomLevel = null; + } + $date = $this->get('date') ?? ''; + + $data = [ + 'tag' => $this->get('tag'), + 'date' => strlen($date) > 0 ? new Carbon($date) : null, + 'description' => $this->get('description') ?? '', + 'latitude' => $latitude, + 'longitude' => $longitude, + 'zoomLevel' => $zoomLevel, + 'tagMode' => $this->get('tagMode'), + ]; + + return $data; + + + } + /** * @return array */ diff --git a/app/Models/Permission.php b/app/Models/Permission.php deleted file mode 100644 index 7d0922d493..0000000000 --- a/app/Models/Permission.php +++ /dev/null @@ -1,21 +0,0 @@ -belongsToMany('FireflyIII\User'); + } + } diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 8b3a366166..99cf93bff8 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -333,7 +333,7 @@ class AccountRepository implements AccountRepositoryInterface $balance = Steam::balance($account, $date, true); /** @var PiggyBank $p */ foreach ($account->piggyBanks()->get() as $p) { - $balance = bcsub($p->currentRelevantRep()->currentamount, $balance); + $balance = bcsub($balance, $p->currentRelevantRep()->currentamount); } return $balance; @@ -544,7 +544,7 @@ class AccountRepository implements AccountRepositoryInterface * @return bool */ private function storeMetadata(Account $account, array $data): bool - { + { foreach ($this->validFields as $field) { if (isset($data[$field])) { $metaData = new AccountMeta( diff --git a/app/Repositories/Rule/RuleRepository.php b/app/Repositories/Rule/RuleRepository.php index d53e3aeaae..8f13ede2ee 100644 --- a/app/Repositories/Rule/RuleRepository.php +++ b/app/Repositories/Rule/RuleRepository.php @@ -207,47 +207,10 @@ class RuleRepository implements RuleRepositoryInterface $rule->save(); // start storing triggers: - $order = 1; - $stopProcessing = false; - - $triggerValues = [ - 'action' => 'user_action', - 'value' => $data['trigger'], - 'stopProcessing' => $stopProcessing, - 'order' => $order, - ]; - - $this->storeTrigger($rule, $triggerValues); - foreach ($data['rule-triggers'] as $index => $trigger) { - $value = $data['rule-trigger-values'][$index]; - $stopProcessing = isset($data['rule-trigger-stop'][$index]) ? true : false; - - $triggerValues = [ - 'action' => $trigger, - 'value' => $value, - 'stopProcessing' => $stopProcessing, - 'order' => $order, - ]; - - $this->storeTrigger($rule, $triggerValues); - $order++; - } + $this->storeTriggers($rule, $data); // same for actions. - $order = 1; - foreach ($data['rule-actions'] as $index => $action) { - $value = $data['rule-action-values'][$index]; - $stopProcessing = isset($data['rule-action-stop'][$index]) ? true : false; - - $actionValues = [ - 'action' => $action, - 'value' => $value, - 'stopProcessing' => $stopProcessing, - 'order' => $order, - ]; - - $this->storeAction($rule, $actionValues); - } + $this->storeActions($rule, $data); return $rule; } @@ -315,6 +278,44 @@ class RuleRepository implements RuleRepositoryInterface $rule->ruleActions()->delete(); // recreate triggers: + $this->storeTriggers($rule, $data); + + // recreate actions: + $this->storeActions($rule, $data); + + + return $rule; + } + + /** + * @param Rule $rule + * @param array $data + */ + private function storeActions(Rule $rule, array $data) + { + $order = 1; + foreach ($data['rule-actions'] as $index => $action) { + $value = $data['rule-action-values'][$index]; + $stopProcessing = isset($data['rule-action-stop'][$index]) ? true : false; + + $actionValues = [ + 'action' => $action, + 'value' => $value, + 'stopProcessing' => $stopProcessing, + 'order' => $order, + ]; + + $this->storeAction($rule, $actionValues); + } + + } + + /** + * @param Rule $rule + * @param array $data + */ + private function storeTriggers(Rule $rule, array $data) + { $order = 1; $stopProcessing = false; @@ -340,24 +341,5 @@ class RuleRepository implements RuleRepositoryInterface $this->storeTrigger($rule, $triggerValues); $order++; } - - // recreate actions: - $order = 1; - foreach ($data['rule-actions'] as $index => $action) { - $value = $data['rule-action-values'][$index]; - $stopProcessing = isset($data['rule-action-stop'][$index]) ? true : false; - - $actionValues = [ - 'action' => $action, - 'value' => $value, - 'stopProcessing' => $stopProcessing, - 'order' => $order, - ]; - - $this->storeAction($rule, $actionValues); - } - - - return $rule; } } diff --git a/app/Support/Migration/TestData.php b/app/Support/Migration/TestData.php index 4ea67bbeff..180b5b116e 100644 --- a/app/Support/Migration/TestData.php +++ b/app/Support/Migration/TestData.php @@ -30,7 +30,6 @@ use FireflyIII\Models\Tag; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\User; -use Log; /** * Class TestData @@ -90,20 +89,16 @@ class TestData public static function createAttachments(User $user, Carbon $start): TransactionJournal { - $toAccount = TestData::findAccount($user, 'TestData Checking Account'); - $fromAccount = TestData::findAccount($user, 'Job'); - - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 2, - 'transaction_currency_id' => 1, - 'description' => 'Some journal for attachment', - 'completed' => 1, - 'date' => $start->format('Y-m-d'), - ] - ); - self::createTransactions($journal, $fromAccount, $toAccount, '100'); + $args = [ + 'user' => $user, + 'description' => 'Some journal for attachment', + 'date' => $start, + 'from' => 'Job', + 'to' => 'TestData Checking Account', + 'amount' => '100', + 'transaction_type' => 2, + ]; + $journal = self::createJournal($args); // and now attachments $encrypted = Crypt::encrypt('I are secret'); @@ -245,45 +240,24 @@ class TestData public static function createCar(User $user, Carbon $date): TransactionJournal { // twice: - $date = new Carbon($date->format('Y-m') . '-10'); // paid on 10th - $fromAccount = TestData::findAccount($user, 'TestData Checking Account'); - $toAccount = TestData::findAccount($user, 'Shell'); - $category = Category::firstOrCreateEncrypted(['name' => 'Car', 'user_id' => $user->id]); - $budget = Budget::firstOrCreateEncrypted(['name' => 'Car', 'user_id' => $user->id]); - $amount = strval(rand(4000, 5000) / 100); - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 1, - 'transaction_currency_id' => 1, - 'description' => 'Bought gas', - 'completed' => 1, - 'date' => $date, - ] - ); - self::createTransactions($journal, $fromAccount, $toAccount, $amount); + $amount = strval(rand(4000, 5000) / 100); + $args = [ + 'user' => $user, + 'description' => 'Bought gas', + 'date' => new Carbon($date->format('Y-m') . '-10'),// paid on 10th + 'from' => 'TestData Checking Account', + 'to' => 'Shell', + 'amount' => $amount, + 'category' => 'Car', + 'budget' => 'Car', + ]; + self::createJournal($args); - $journal->categories()->save($category); - $journal->budgets()->save($budget); - - // and again! - $date = new Carbon($date->format('Y-m') . '-20'); // paid on 20th - $amount = rand(4000, 5000) / 100; - - - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 1, - 'transaction_currency_id' => 1, - 'description' => 'Gas for car', - 'completed' => 1, - 'date' => $date, - ] - ); - self::createTransactions($journal, $fromAccount, $toAccount, strval($amount)); - - // and again! + // again! + $args['date'] = new Carbon($date->format('Y-m') . '-20'); // paid on 20th + $args['amount'] = strval(rand(4000, 5000) / 100); + $args['description'] = 'Gas for car'; + $journal = self::createJournal($args); return $journal; } @@ -322,28 +296,18 @@ class TestData // weekly drink: $thisDate = clone $current; $thisDate->addDay(); - $fromAccount = TestData::findAccount($user, 'TestData Checking Account'); - $toAccount = TestData::findAccount($user, 'Cafe Central'); - $category = Category::firstOrCreateEncrypted(['name' => 'Drinks', 'user_id' => $user->id]); - $budget = Budget::firstOrCreateEncrypted(['name' => 'Going out', 'user_id' => $user->id]); - $amount = strval(rand(1500, 3600) / 100); - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 1, - 'transaction_currency_id' => 1, - 'description' => 'Going out for drinks', - 'completed' => 1, - 'date' => $thisDate, - ] - ); - self::createTransactions($journal, $fromAccount, $toAccount, $amount); - - $journal->categories()->save($category); - $journal->budgets()->save($budget); - - // shopping at some (online) shop: - + $amount = strval(rand(1500, 3600) / 100); + $args = [ + 'user' => $user, + 'description' => 'Going out for drinks', + 'date' => $thisDate, + 'from' => 'TestData Checking Account', + 'to' => 'Cafe Central', + 'amount' => $amount, + 'category' => 'Drinks', + 'budget' => 'Going out', + ]; + self::createJournal($args); $current->addWeek(); } @@ -395,36 +359,25 @@ class TestData $start->startOfMonth(); $end->endOfMonth(); - $fromAccount = TestData::findAccount($user, 'TestData Checking Account'); $stores = ['Albert Heijn', 'PLUS', 'Bakker']; $descriptions = ['Groceries', 'Bought some groceries', 'Got groceries']; - $category = Category::firstOrCreateEncrypted(['name' => 'Daily groceries', 'user_id' => $user->id]); - $budget = Budget::firstOrCreateEncrypted(['name' => 'Groceries', 'user_id' => $user->id]); $current = clone $start; while ($current < $end && $current < $today) { // daily groceries: - $toAccount = TestData::findAccount($user, $stores[rand(0, count($stores) - 1)]); - - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 1, - 'transaction_currency_id' => 1, - 'description' => $descriptions[rand(0, count($descriptions) - 1)], - 'completed' => 1, - 'date' => $current, - ] - ); - if ($journal->id) { - $number = (string)round((rand(1500, 2500) / 100), 2); - $amount = $number;//'10';//strval((rand(1500, 2500) / 100)); - self::createTransactions($journal, $fromAccount, $toAccount, $amount); - $journal->categories()->save($category); - $journal->budgets()->save($budget); - } - + $amount = (string)round((rand(1500, 2500) / 100), 2); + $args = [ + 'user' => $user, + 'description' => $descriptions[rand(0, count($descriptions) - 1)], + 'date' => $current, + 'from' => 'TestData Checking Account', + 'to' => $stores[rand(0, count($stores) - 1)], + 'amount' => $amount, + 'category' => 'Daily groceries', + 'budget' => 'Groceries', + ]; + self::createJournal($args); $current->addDay(); } @@ -446,28 +399,54 @@ class TestData if ($date >= $today) { return new TransactionJournal; } - $toAccount = TestData::findAccount($user, 'TestData Checking Account'); - $fromAccount = TestData::findAccount($user, 'Job'); - $category = Category::firstOrCreateEncrypted(['name' => 'Salary', 'user_id' => $user->id]); - // create journal: - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 2, - 'transaction_currency_id' => 1, - 'description' => $description, - 'completed' => 1, - 'date' => $date, - ] - ); - self::createTransactions($journal, $fromAccount, $toAccount, $amount); - $journal->categories()->save($category); + // create journal: + $args = [ + 'user' => $user, + 'description' => $description, + 'date' => $date, + 'from' => 'Job', + 'to' => 'TestData Checking Account', + 'amount' => $amount, + 'category' => 'Salary', + 'transaction_type' => 2, + ]; + $journal = self::createJournal($args); return $journal; } + /** + * @param array $opt + * + * @return TransactionJournal + */ + public static function createJournal(array $opt): TransactionJournal + { + $type = $opt['transaction_type'] ?? 1; + + $journal = TransactionJournal::create( + [ + 'user_id' => $opt['user']->id, + 'transaction_type_id' => $type, + 'transaction_currency_id' => 1, + 'description' => $opt['description'], + 'completed' => 1, + 'date' => $opt['date'], + ] + ); + self::createTransactions($journal, self::findAccount($opt['user'], $opt['from']), self::findAccount($opt['user'], $opt['to']), $opt['amount']); + if (isset($opt['category'])) { + $journal->categories()->save(self::findCategory($opt['user'], $opt['category'])); + } + if (isset($opt['budget'])) { + $journal->budgets()->save(self::findBudget($opt['user'], $opt['budget'])); + } + + return $journal; + } + /** * @param User $user * @@ -620,24 +599,17 @@ class TestData */ public static function createPower(User $user, string $description, Carbon $date, string $amount): TransactionJournal { - $date = new Carbon($date->format('Y-m') . '-06'); // paid on 10th - $fromAccount = TestData::findAccount($user, 'TestData Checking Account'); - $toAccount = TestData::findAccount($user, 'Greenchoice'); - $category = Category::firstOrCreateEncrypted(['name' => 'House', 'user_id' => $user->id]); - $budget = Budget::firstOrCreateEncrypted(['name' => 'Bills', 'user_id' => $user->id]); - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 1, - 'transaction_currency_id' => 1, - 'description' => $description, - 'completed' => 1, - 'date' => $date, - ] - ); - self::createTransactions($journal, $fromAccount, $toAccount, $amount); - $journal->categories()->save($category); - $journal->budgets()->save($budget); + $args = [ + 'user' => $user, + 'description' => $description, + 'date' => new Carbon($date->format('Y-m') . '-06'),// paid on 10th + 'from' => 'TestData Checking Account', + 'to' => 'Greenchoice', + 'amount' => $amount, + 'category' => 'House', + 'budget' => 'Bills', + ]; + $journal = self::createJournal($args); return $journal; @@ -653,25 +625,17 @@ class TestData */ public static function createRent(User $user, string $description, Carbon $date, string $amount): TransactionJournal { - $fromAccount = TestData::findAccount($user, 'TestData Checking Account'); - $toAccount = TestData::findAccount($user, 'Land lord'); - $category = Category::firstOrCreateEncrypted(['name' => 'Rent', 'user_id' => $user->id]); - $budget = Budget::firstOrCreateEncrypted(['name' => 'Bills', 'user_id' => $user->id]); - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 1, - 'transaction_currency_id' => 1, - 'bill_id' => 1, - 'description' => $description, - 'completed' => 1, - 'date' => $date, - ] - ); - self::createTransactions($journal, $fromAccount, $toAccount, $amount); - - $journal->categories()->save($category); - $journal->budgets()->save($budget); + $args = [ + 'user' => $user, + 'description' => $description, + 'date' => $date, + 'from' => 'TestData Checking Account', + 'to' => 'Land lord', + 'amount' => $amount, + 'category' => 'Rent', + 'budget' => 'Bills', + ]; + $journal = self::createJournal($args); return $journal; @@ -792,24 +756,17 @@ class TestData */ public static function createSavings(User $user, Carbon $date): TransactionJournal { - $date = new Carbon($date->format('Y-m') . '-24'); // paid on 24th. - $toAccount = TestData::findAccount($user, 'TestData Savings'); - $fromAccount = TestData::findAccount($user, 'TestData Checking Account'); - $category = Category::firstOrCreateEncrypted(['name' => 'Money management', 'user_id' => $user->id]); - // create journal: - - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 3, - 'transaction_currency_id' => 1, - 'description' => 'Save money', - 'completed' => 1, - 'date' => $date, - ] - ); - self::createTransactions($journal, $fromAccount, $toAccount, '150'); - $journal->categories()->save($category); + $args = [ + 'user' => $user, + 'description' => 'Save money', + 'date' => new Carbon($date->format('Y-m') . '-24'),// paid on 24th. + 'from' => 'TestData Checking Account', + 'to' => 'TestData Savings', + 'amount' => '150', + 'category' => 'Money management', + 'transaction_type' => 3, + ]; + $journal = self::createJournal($args); return $journal; @@ -825,25 +782,17 @@ class TestData */ public static function createTV(User $user, string $description, Carbon $date, string $amount): TransactionJournal { - $date = new Carbon($date->format('Y-m') . '-15'); // paid on 10th - $fromAccount = TestData::findAccount($user, 'TestData Checking Account'); - $toAccount = TestData::findAccount($user, 'XS4All'); - $category = Category::firstOrCreateEncrypted(['name' => 'House', 'user_id' => $user->id]); - $budget = Budget::firstOrCreateEncrypted(['name' => 'Bills', 'user_id' => $user->id]); - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 1, - 'transaction_currency_id' => 1, - 'description' => $description, - 'completed' => 1, - 'date' => $date, - ] - ); - self::createTransactions($journal, $fromAccount, $toAccount, $amount); - - $journal->categories()->save($category); - $journal->budgets()->save($budget); + $args = [ + 'user' => $user, + 'description' => $description, + 'date' => new Carbon($date->format('Y-m') . '-15'), + 'from' => 'TestData Checking Account', + 'to' => 'XS4All', + 'amount' => $amount, + 'category' => 'House', + 'budget' => 'Bills', + ]; + $journal = self::createJournal($args); return $journal; @@ -883,8 +832,6 @@ class TestData */ public static function createTransactions(TransactionJournal $journal, Account $from, Account $to, string $amount): bool { - Log::debug('---- Transaction From: ' . bcmul($amount, '-1')); - Log::debug('---- Transaction To : ' . $amount); Transaction::create( [ 'account_id' => $from->id, @@ -931,24 +878,17 @@ class TestData */ public static function createWater(User $user, string $description, Carbon $date, string $amount): TransactionJournal { - $date = new Carbon($date->format('Y-m') . '-10'); // paid on 10th - $fromAccount = TestData::findAccount($user, 'TestData Checking Account'); - $toAccount = TestData::findAccount($user, 'Vitens'); - $category = Category::firstOrCreateEncrypted(['name' => 'House', 'user_id' => $user->id]); - $budget = Budget::firstOrCreateEncrypted(['name' => 'Bills', 'user_id' => $user->id]); - $journal = TransactionJournal::create( - [ - 'user_id' => $user->id, - 'transaction_type_id' => 1, - 'transaction_currency_id' => 1, - 'description' => $description, - 'completed' => 1, - 'date' => $date, - ] - ); - self::createTransactions($journal, $fromAccount, $toAccount, $amount); - $journal->categories()->save($category); - $journal->budgets()->save($budget); + $args = [ + 'user' => $user, + 'description' => $description, + 'date' => new Carbon($date->format('Y-m') . '-10'), // paid on 10th + 'from' => 'TestData Checking Account', + 'to' => 'Vitens', + 'amount' => $amount, + 'category' => 'House', + 'budget' => 'Bills', + ]; + $journal = self::createJournal($args); return $journal; @@ -987,7 +927,25 @@ class TestData } } - return new Budget; + return Budget::firstOrCreateEncrypted(['name' => $name, 'user_id' => $user->id]); + } + + /** + * @param User $user + * @param $name + * + * @return Category + */ + public static function findCategory(User $user, string $name): Category + { + /** @var Category $category */ + foreach (Category::get() as $category) { + if ($category->name == $name && $user->id == $category->user_id) { + return $category; + } + } + + return Category::firstOrCreateEncrypted(['name' => $name, 'user_id' => $user->id]); } /** @@ -1023,6 +981,7 @@ class TestData ] ); self::createTransactions($journal, $opposing, $savings, '10000'); + return $journal; } diff --git a/app/User.php b/app/User.php index 3f0b86d787..58746d5a6b 100644 --- a/app/User.php +++ b/app/User.php @@ -3,10 +3,10 @@ declare(strict_types = 1); namespace FireflyIII; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Foundation\Auth\User as Authenticatable; -use Zizaco\Entrust\Traits\EntrustUserTrait; /** * Class User @@ -32,11 +32,10 @@ use Zizaco\Entrust\Traits\EntrustUserTrait; * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Role[] $roles * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\RuleGroup[] $ruleGroups * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Rule[] $rules - * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\ExportJob[] $exportjobs + * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\ExportJob[] $exportjobs */ class User extends Authenticatable { - use EntrustUserTrait; /** * The attributes that are mass assignable. @@ -44,16 +43,12 @@ class User extends Authenticatable * @var array */ protected $fillable = ['email', 'password', 'blocked', 'blocked_code']; - - /** * The attributes excluded from the model's JSON form. * * @var array */ protected $hidden = ['password', 'remember_token']; - - /** * The database table used by the model. * @@ -69,6 +64,26 @@ class User extends Authenticatable return $this->hasMany('FireflyIII\Models\Account'); } + /** + * Alias to eloquent many-to-many relation's attach() method. + * + * Full credit goes to: https://github.com/Zizaco/entrust + * + * @param mixed $role + */ + public function attachRole($role) + { + if (is_object($role)) { + $role = $role->getKey(); + } + + if (is_array($role)) { + $role = $role['id']; + } + + $this->roles()->attach($role); + } + /** * @return HasMany */ @@ -109,6 +124,44 @@ class User extends Authenticatable return $this->hasMany('FireflyIII\Models\ExportJob'); } + /** + * Checks if the user has a role by its name. + * + * Full credit goes to: https://github.com/Zizaco/entrust + * + * @param string|array $name Role name or array of role names. + * @param bool $requireAll All roles in the array are required. + * + * @return bool + */ + public function hasRole($name, $requireAll = false) + { + if (is_array($name)) { + foreach ($name as $roleName) { + $hasRole = $this->hasRole($roleName); + + if ($hasRole && !$requireAll) { + return true; + } elseif (!$hasRole && $requireAll) { + return false; + } + } + + // If we've made it this far and $requireAll is FALSE, then NONE of the roles were found + // If we've made it this far and $requireAll is TRUE, then ALL of the roles were found. + // Return the value of $requireAll; + return $requireAll; + } else { + foreach ($this->roles as $role) { + if ($role->name == $name) { + return true; + } + } + } + + return false; + } + /** * @return HasManyThrough */ @@ -125,6 +178,14 @@ class User extends Authenticatable return $this->hasMany('FireflyIII\Models\Preference'); } + /** + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + */ + public function roles(): BelongsToMany + { + return $this->belongsToMany('FireflyIII\Models\Role'); + } + /** * @return HasMany */ diff --git a/app/Validation/FireflyValidator.php b/app/Validation/FireflyValidator.php index fd2594f932..a225b4376f 100644 --- a/app/Validation/FireflyValidator.php +++ b/app/Validation/FireflyValidator.php @@ -199,6 +199,13 @@ class FireflyValidator extends Validator return false; } + /** + * @param $attribute + * @param $value + * @param $parameters + * + * @return bool + */ public function validateUniqueAccountNumberForUser($attribute, $value, $parameters): bool { $accountId = $this->data['id'] ?? 0; diff --git a/composer.json b/composer.json index 152fb7130e..45949b7898 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,6 @@ "doctrine/dbal": "~2.5", "league/commonmark": "~0.7", "rcrowe/twigbridge": "~0.9", - "zizaco/entrust": "dev-laravel-5", "league/csv": "^7.1", "laravelcollective/html": "^5.2" }, diff --git a/database/migrations/2014_07_09_204843_create_session_table.php b/database/migrations/2014_07_09_204843_create_session_table.php index a5ddae291f..fa39883634 100644 --- a/database/migrations/2014_07_09_204843_create_session_table.php +++ b/database/migrations/2014_07_09_204843_create_session_table.php @@ -1,6 +1,7 @@ string('id')->unique(); $table->integer('user_id')->nullable(); $table->string('ip_address', 45)->nullable(); diff --git a/gulpfile.js b/gulpfile.js old mode 100755 new mode 100644 diff --git a/public/js/accounts/show.js b/public/js/accounts/show.js index fb0a5d9ea2..f913802ab3 100644 --- a/public/js/accounts/show.js +++ b/public/js/accounts/show.js @@ -79,7 +79,7 @@ function sortStop(event, ui) { }); // do extra animation when done? - $.post('/transaction/reorder', {items: submit, date: thisDate, _token: token}); + $.post('transaction/reorder', {items: submit, date: thisDate, _token: token}); current.animate({backgroundColor: "#5cb85c"}, 200, function () { $(this).animate({backgroundColor: originalBG}, 200); diff --git a/public/js/piggy-banks/index.js b/public/js/piggy-banks/index.js index 9fa00d2375..de6931be65 100644 --- a/public/js/piggy-banks/index.js +++ b/public/js/piggy-banks/index.js @@ -79,7 +79,7 @@ function stopSorting() { var id = holder.data('id'); order.push(id); }); - $.post('/piggy-banks/sort', {_token: token, order: order}).done(function () { + $.post('piggy-banks/sort', {_token: token, order: order}).done(function () { $('.loadSpin').removeClass('fa fa-refresh fa-spin'); }); } \ No newline at end of file diff --git a/public/manifest.json b/public/manifest.json index ba55871a27..412c8c6bad 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,41 +1,46 @@ { - "name": "geld.nder.be", - "icons": [ - { - "src": "\/android-chrome-36x36.png?v=Lb54KlrQnz", - "sizes": "36x36", - "type": "image\/png", - "density": "0.75" - }, - { - "src": "\/android-chrome-48x48.png?v=Lb54KlrQnz", - "sizes": "48x48", - "type": "image\/png", - "density": "1.0" - }, - { - "src": "\/android-chrome-72x72.png?v=Lb54KlrQnz", - "sizes": "72x72", - "type": "image\/png", - "density": "1.5" - }, - { - "src": "\/android-chrome-96x96.png?v=Lb54KlrQnz", - "sizes": "96x96", - "type": "image\/png", - "density": "2.0" - }, - { - "src": "\/android-chrome-144x144.png?v=Lb54KlrQnz", - "sizes": "144x144", - "type": "image\/png", - "density": "3.0" - }, - { - "src": "\/android-chrome-192x192.png?v=Lb54KlrQnz", - "sizes": "192x192", - "type": "image\/png", - "density": "4.0" - } - ] + "name": "Firefly III", + "short_name": "Firefly III", + + "icons": [ + { + "src": "\/android-chrome-36x36.png?v=Lb54KlrQnz", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/android-chrome-48x48.png?v=Lb54KlrQnz", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/android-chrome-72x72.png?v=Lb54KlrQnz", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/android-chrome-96x96.png?v=Lb54KlrQnz", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/android-chrome-144x144.png?v=Lb54KlrQnz", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/android-chrome-192x192.png?v=Lb54KlrQnz", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ], + "start_url": "/", + "display": "standalone", + "orientation": "portrait" } diff --git a/resources/views/emails/registered-html.twig b/resources/views/emails/registered-html.twig index ef3cc07bbf..43f82cfa74 100644 --- a/resources/views/emails/registered-html.twig +++ b/resources/views/emails/registered-html.twig @@ -13,10 +13,6 @@ Welkome to Firefly III. Your registration has made it, and this email is here to confirm it. Yay!

-

- You can now continue on , if you weren't there already. -

-