Merge branch 'develop' of github.com:JC5/firefly-iii into develop

This commit is contained in:
James Cole 2016-02-16 13:25:48 +01:00
commit 0a91a40c1b
35 changed files with 744 additions and 516 deletions

View File

@ -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/*

2
.csslintrc Normal file
View File

@ -0,0 +1,2 @@
--exclude-exts=.min.css
--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes

1
.eslintignore Normal file
View File

@ -0,0 +1 @@
**/*{.,-}min.js

213
.eslintrc Normal file
View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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';

View File

@ -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;

View File

@ -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;
}

View File

@ -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.
];

View File

@ -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;

View File

@ -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,

View File

@ -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',

View File

@ -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',

View File

@ -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);

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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 {

View File

@ -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.');

View File

@ -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
*/

View File

@ -1,21 +0,0 @@
<?php
declare(strict_types = 1);
namespace FireflyIII\Models;
use Zizaco\Entrust\EntrustPermission;
/**
* FireflyIII\Models\Permission
*
* @property integer $id
* @property string $name
* @property string $display_name
* @property string $description
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection|Role[] $roles
*/
class Permission extends EntrustPermission
{
}

View File

@ -3,21 +3,19 @@ declare(strict_types = 1);
namespace FireflyIII\Models;
use Zizaco\Entrust\EntrustRole;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
/**
* FireflyIII\Models\Role
*
* @property integer $id
* @property string $name
* @property string $display_name
* @property string $description
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\User[] $users
* @property-read \Illuminate\Database\Eloquent\Collection|Permission[] $perms
*/
class Role extends EntrustRole
class Role extends Model
{
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function users(): BelongsToMany
{
return $this->belongsToMany('FireflyIII\User');
}
}

View File

@ -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(

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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
*/

View File

@ -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;

View File

@ -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"
},

View File

@ -1,6 +1,7 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
/**
* @SuppressWarnings(PHPMD.ShortMethodName)
@ -29,7 +30,7 @@ class CreateSessionTable extends Migration
public function up()
{
Schema::create(
'sessions', function ($table) {
'sessions', function (Blueprint $table) {
$table->string('id')->unique();
$table->integer('user_id')->nullable();
$table->string('ip_address', 45)->nullable();

0
gulpfile.js Executable file → Normal file
View File

View File

@ -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);

View File

@ -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');
});
}

View File

@ -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"
}

View File

@ -13,10 +13,6 @@
Welkome to <a style="color:#337ab7" href="{{ address }}">
<span itemprop="name">Firefly III</span></a>. Your registration has made it, and this email is here to confirm it. Yay!
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
You can now continue on <span itemprop="url"><a href="{{ address }}">{{ address }}</a></span>, if you weren't there already.
</p>
<ul>
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">

View File

@ -15,7 +15,11 @@
<a href="{{ route('accounts.show',income.id) }}" title="{{ income.name }}">{{ income.name }}</a>
{% if income.count > 1 %}
<br/>
<small>{{ income.count }} {{ 'transactions'|_|lower }}</small>
<small>
{{ income.count }} {{ 'transactions'|_|lower }}
<i class="fa fa-fw text-muted fa-info-circle"></i>
</small>
{% endif %}
</td>
<td>{{ income.amount|formatAmount }}</td>