Merge branch 'develop'

* develop:
  Fixed some rare bugs.
  Extra clear button to reapply rules #307
  Fix trim when null [skip ci]
  Fixed a bug where incoming transactions would not be properly filtered in several reports.
  Removed for #334
  Fix #337 [skip ci]
  Fix #335
  Remove account extra text #336 [skip ci]
  Fixes bug #338
  Refer to correct page [skip ci]
  Catch unset row.
This commit is contained in:
James Cole 2016-10-04 20:08:35 +02:00
commit 724d25f2c2
16 changed files with 89 additions and 129 deletions

View File

@ -221,6 +221,33 @@ class AccountCrud implements AccountCrudInterface
return $result; return $result;
} }
/**
* @param array $types
*
* @return Collection
*/
public function getActiveAccountsByType(array $types): Collection
{
/** @var Collection $result */
$query = $this->user->accounts()->with(
['accountmeta' => function (HasMany $query) {
$query->where('name', 'accountRole');
}]
);
if (count($types) > 0) {
$query->accountTypeIn($types);
}
$query->where('active', 1);
$result = $query->get(['accounts.*']);
$result = $result->sortBy(
function (Account $account) {
return strtolower($account->name);
}
);
return $result;
}
/** /**
* @param array $data * @param array $data
* *

View File

@ -75,6 +75,13 @@ interface AccountCrudInterface
*/ */
public function getAccountsByType(array $types): Collection; public function getAccountsByType(array $types): Collection;
/**
* @param array $types
*
* @return Collection
*/
public function getActiveAccountsByType(array $types): Collection;
/** /**
* @param array $data * @param array $data
* *

View File

@ -295,14 +295,14 @@ class AccountController extends Controller
public function store(AccountFormRequest $request, AccountCrudInterface $crud) public function store(AccountFormRequest $request, AccountCrudInterface $crud)
{ {
$accountData = [ $accountData = [
'name' => $request->input('name'), 'name' => trim($request->input('name')),
'accountType' => $request->input('what'), 'accountType' => $request->input('what'),
'virtualBalance' => round($request->input('virtualBalance'), 2), 'virtualBalance' => round($request->input('virtualBalance'), 2),
'virtualBalanceCurrency' => intval($request->input('amount_currency_id_virtualBalance')), 'virtualBalanceCurrency' => intval($request->input('amount_currency_id_virtualBalance')),
'active' => true, 'active' => true,
'user' => auth()->user()->id, 'user' => auth()->user()->id,
'iban' => $request->input('iban'), 'iban' => trim($request->input('iban')),
'accountNumber' => $request->input('accountNumber'), 'accountNumber' => trim($request->input('accountNumber')),
'accountRole' => $request->input('accountRole'), 'accountRole' => $request->input('accountRole'),
'openingBalance' => round($request->input('openingBalance'), 2), 'openingBalance' => round($request->input('openingBalance'), 2),
'openingBalanceDate' => new Carbon((string)$request->input('openingBalanceDate')), 'openingBalanceDate' => new Carbon((string)$request->input('openingBalanceDate')),

View File

@ -1,84 +0,0 @@
<?php
/**
* AuthController.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
declare(strict_types = 1);
namespace FireflyIII\Http\Controllers\Auth;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\User;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Validator;
/**
* Class AuthController
*
* @package FireflyIII\Http\Controllers\Auth
*/
class AuthController extends Controller
{
use AuthenticatesAndRegistersUsers, ThrottlesLogins;
/**
* Where to redirect users after login / registration.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new authentication controller instance.
*
*/
public function __construct()
{
$this->middleware('guest', ['except' => 'logout']);
parent::__construct();
}
/**
* Create a new user instance after a valid registration.
*
* @param array $data
*
* @return User
*/
protected function create(array $data)
{
return User::create(
[
'email' => $data['email'],
'password' => bcrypt($data['password']),
]
);
}
/**
* Get a validator for an incoming registration request.
*
* @param array $data
*
* @return \Illuminate\Contracts\Validation\Validator
*/
protected function validator(array $data)
{
return Validator::make(
$data, [
'email' => 'required|email|max:255|unique:users',
'password' => 'required|confirmed|min:6',
]
);
}
}

View File

@ -263,7 +263,7 @@ class CategoryController extends Controller
public function store(CategoryFormRequest $request, CRI $repository) public function store(CategoryFormRequest $request, CRI $repository)
{ {
$categoryData = [ $categoryData = [
'name' => $request->input('name'), 'name' => trim($request->input('name')),
'user' => auth()->user()->id, 'user' => auth()->user()->id,
]; ];
$category = $repository->store($categoryData); $category = $repository->store($categoryData);

View File

@ -13,6 +13,7 @@ namespace FireflyIII\Http\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use ExpandedForm; use ExpandedForm;
use FireflyIII\Crud\Account\AccountCrudInterface;
use FireflyIII\Events\TransactionJournalStored; use FireflyIII\Events\TransactionJournalStored;
use FireflyIII\Events\TransactionJournalUpdated; use FireflyIII\Events\TransactionJournalUpdated;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
@ -59,12 +60,12 @@ class TransactionController extends Controller
*/ */
public function create(string $what = TransactionType::DEPOSIT) public function create(string $what = TransactionType::DEPOSIT)
{ {
$crud = app('FireflyIII\Crud\Account\AccountCrudInterface'); $crud = app(AccountCrudInterface::class);
$budgetRepository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface'); $budgetRepository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
$piggyRepository = app('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface'); $piggyRepository = app('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface');
$what = strtolower($what); $what = strtolower($what);
$uploadSize = min(Steam::phpBytes(ini_get('upload_max_filesize')), Steam::phpBytes(ini_get('post_max_size'))); $uploadSize = min(Steam::phpBytes(ini_get('upload_max_filesize')), Steam::phpBytes(ini_get('post_max_size')));
$assetAccounts = ExpandedForm::makeSelectList($crud->getAccountsByType(['Default account', 'Asset account'])); $assetAccounts = ExpandedForm::makeSelectList($crud->getActiveAccountsByType(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectListWithEmpty($budgetRepository->getActiveBudgets()); $budgets = ExpandedForm::makeSelectListWithEmpty($budgetRepository->getActiveBudgets());
$piggyBanks = $piggyRepository->getPiggyBanksWithAmount(); $piggyBanks = $piggyRepository->getPiggyBanksWithAmount();
$piggies = ExpandedForm::makeSelectListWithEmpty($piggyBanks); $piggies = ExpandedForm::makeSelectListWithEmpty($piggyBanks);

View File

@ -43,11 +43,11 @@ class JournalFormRequest extends Request
return [ return [
'what' => $this->get('what'), 'what' => $this->get('what'),
'description' => $this->get('description'), 'description' => trim($this->get('description')),
'source_account_id' => intval($this->get('source_account_id')), 'source_account_id' => intval($this->get('source_account_id')),
'source_account_name' => $this->getFieldOrEmptyString('source_account_name'), 'source_account_name' => trim($this->getFieldOrEmptyString('source_account_name')),
'destination_account_id' => intval($this->get('destination_account_id')), 'destination_account_id' => intval($this->get('destination_account_id')),
'destination_account_name' => $this->getFieldOrEmptyString('destination_account_name'), 'destination_account_name' => trim($this->getFieldOrEmptyString('destination_account_name')),
'amount' => round($this->get('amount'), 2), 'amount' => round($this->get('amount'), 2),
'user' => auth()->user()->id, 'user' => auth()->user()->id,
'amount_currency_id_amount' => intval($this->get('amount_currency_id_amount')), 'amount_currency_id_amount' => intval($this->get('amount_currency_id_amount')),
@ -56,7 +56,7 @@ class JournalFormRequest extends Request
'book_date' => $this->getDateOrNull('book_date'), 'book_date' => $this->getDateOrNull('book_date'),
'process_date' => $this->getDateOrNull('process_date'), 'process_date' => $this->getDateOrNull('process_date'),
'budget_id' => intval($this->get('budget_id')), 'budget_id' => intval($this->get('budget_id')),
'category' => $this->getFieldOrEmptyString('category'), 'category' => trim($this->getFieldOrEmptyString('category')),
'tags' => explode(',', $tags), 'tags' => explode(',', $tags),
'piggy_bank_id' => intval($this->get('piggy_bank_id')), 'piggy_bank_id' => intval($this->get('piggy_bank_id')),
@ -64,8 +64,8 @@ class JournalFormRequest extends Request
'due_date' => $this->getDateOrNull('due_date'), 'due_date' => $this->getDateOrNull('due_date'),
'payment_date' => $this->getDateOrNull('payment_date'), 'payment_date' => $this->getDateOrNull('payment_date'),
'invoice_date' => $this->getDateOrNull('invoice_date'), 'invoice_date' => $this->getDateOrNull('invoice_date'),
'internal_reference' => $this->get('internal_reference'), 'internal_reference' => trim(strval($this->get('internal_reference'))),
'notes' => $this->get('notes'), 'notes' => trim(strval($this->get('notes'))),
]; ];
} }

View File

@ -181,13 +181,13 @@ class ImportValidator
Log::debug(sprintf('No account named %s of type %s, create new account.', $account->name, $type)); Log::debug(sprintf('No account named %s of type %s, create new account.', $account->name, $type));
$result = $repository->store( $result = $repository->store(
[ [
'user' => $this->user->id, 'user' => $this->user->id,
'accountType' => config('firefly.shortNamesByFullName.' . $type), 'accountType' => config('firefly.shortNamesByFullName.' . $type),
'name' => $account->name, 'name' => $account->name,
'virtualBalance' => 0, 'virtualBalance' => 0,
'active' => true, 'active' => true,
'iban' => null, 'iban' => null,
'openingBalance' => 0, 'openingBalance' => 0,
] ]
); );
} }
@ -262,6 +262,7 @@ class ImportValidator
$entry->valid = false; $entry->valid = false;
Log::warning('Cannot import entry. Asset account is NULL and import account is also NULL.'); Log::warning('Cannot import entry. Asset account is NULL and import account is also NULL.');
return $entry;
} }
Log::debug('Asset account is OK.', ['id' => $entry->fields['asset-account']->id, 'name' => $entry->fields['asset-account']->name]); Log::debug('Asset account is OK.', ['id' => $entry->fields['asset-account']->id, 'name' => $entry->fields['asset-account']->name]);

View File

@ -50,9 +50,15 @@ class AbnAmroDescription implements SpecificInterface
public function run(array $row): array public function run(array $row): array
{ {
$this->row = $row; $this->row = $row;
if (!isset($row[7])) {
return $row;
}
// Try to parse the description in known formats. // Try to parse the description in known formats.
$parsed = $this->parseSepaDescription() || $this->parseTRTPDescription() || $this->parseGEABEADescription() || $this->parseABNAMRODescription(); $parsed = $this->parseSepaDescription() || $this->parseTRTPDescription() || $this->parseGEABEADescription() || $this->parseABNAMRODescription();
// If the description could not be parsed, specify an unknown opposing // If the description could not be parsed, specify an unknown opposing
// account, as an opposing account is required // account, as an opposing account is required
if (!$parsed) { if (!$parsed) {

View File

@ -377,7 +377,10 @@ class AccountRepository implements AccountRepositoryInterface
* The destination of a transfer must be one of the $accounts in order to * The destination of a transfer must be one of the $accounts in order to
* be included. Otherwise, it would not be income. * be included. Otherwise, it would not be income.
*/ */
if (in_array($journal->destination_account_id, $accountIds)) { $destinations = TransactionJournal::destinationAccountList($journal)->pluck('id')->toArray();
if (count(array_intersect($destinations, $accountIds)) > 0) {
// at least one of $target is in $haystack
return true; return true;
} }

View File

@ -189,22 +189,22 @@ class BillRepository implements BillRepositoryInterface
'bills.active', 'bills.active',
'bills.name_encrypted', 'bills.name_encrypted',
'bills.match_encrypted']; 'bills.match_encrypted'];
$ids = $accounts->pluck('id')->toArray(); $ids = $accounts->pluck('id')->toArray();
$set = $this->user->bills() $set = $this->user->bills()
->leftJoin( ->leftJoin(
'transaction_journals', function (JoinClause $join) { 'transaction_journals', function (JoinClause $join) {
$join->on('transaction_journals.bill_id', '=', 'bills.id')->whereNull('transaction_journals.deleted_at'); $join->on('transaction_journals.bill_id', '=', 'bills.id')->whereNull('transaction_journals.deleted_at');
} }
) )
->leftJoin( ->leftJoin(
'transactions', function (JoinClause $join) { 'transactions', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0); $join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', '<', 0);
} }
) )
->whereIn('transactions.account_id', $ids) ->whereIn('transactions.account_id', $ids)
->whereNull('transaction_journals.deleted_at') ->whereNull('transaction_journals.deleted_at')
->groupBy($fields) ->groupBy($fields)
->get($fields); ->get($fields);
$set = $set->sortBy( $set = $set->sortBy(
function (Bill $bill) { function (Bill $bill) {

View File

@ -143,7 +143,7 @@ class TagRepository implements TagRepositoryInterface
->transactionJournals() ->transactionJournals()
->sortCorrectly() ->sortCorrectly()
->expanded() ->expanded()
->groupBy(['tag_transaction_journal.tag_id']) ->groupBy(['tag_transaction_journal.tag_id','tag_transaction_journal.transaction_journal_id'])
->get(TransactionJournal::queryFields()); ->get(TransactionJournal::queryFields());
return $journals; return $journals;

View File

@ -48,7 +48,7 @@ class SetBudget implements ActionInterface
public function act(TransactionJournal $journal): bool public function act(TransactionJournal $journal): bool
{ {
/** @var BudgetRepositoryInterface $repository */ /** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class); $repository = app(BudgetRepositoryInterface::class, [$journal->user]);
$search = $this->action->action_value; $search = $this->action->action_value;
$budgets = $repository->getActiveBudgets(); $budgets = $repository->getActiveBudgets();
$budget = $budgets->filter( $budget = $budgets->filter(

View File

@ -17,6 +17,6 @@ return [
'Please follow the instructions on the following page: https://github.com/JC5/firefly-iii/wiki/Upgrade-to-3.7.0', 'Please follow the instructions on the following page: https://github.com/JC5/firefly-iii/wiki/Upgrade-to-3.7.0',
'3.8' => 'This version of Firefly III requires PHP 7.0.', '3.8' => 'This version of Firefly III requires PHP 7.0.',
'3.10' => 'Please find the full upgrade instructions here: https://github.com/JC5/firefly-iii/wiki/Upgrade-to-3.10', '3.10' => 'Please find the full upgrade instructions here: https://github.com/JC5/firefly-iii/wiki/Upgrade-to-3.10',
'4.0' => 'Please find the full upgrade instructions here: https://github.com/JC5/firefly-iii/wiki/Upgrade-to-3.10', '4.0' => 'Please find the full upgrade instructions here: https://github.com/JC5/firefly-iii/wiki/Upgrade-to-4.0',
], ],
]; ];

View File

@ -6,13 +6,6 @@
{% block content %} {% block content %}
<div class="row">
<div class="col-lg-6 col-md-8 col-sm-12 col-xs-12">
<p>
{{ ('accountExtraHelp_'~what)|_ }}
</p>
</div>
</div>
<div class="row"> <div class="row">
<div class="col-lg-12 col-md-12 col-sm-12"> <div class="col-lg-12 col-md-12 col-sm-12">
<div class="box" id="account-index-{{ what }}"> <div class="box" id="account-index-{{ what }}">

View File

@ -104,6 +104,12 @@
class="btn btn-danger"><span class="btn btn-danger"><span
class="fa fa-fw fa-trash"></span></a> class="fa fa-fw fa-trash"></span></a>
</div> </div>
<br />
<div class="btn-group btn-group-xs">
<a href="{{ route('rules.rule-group.select_transactions',ruleGroup.id) }}" class="btn btn-default"
title=" {{ 'execute_on_existing_transactions_short'|_ }}">
<i class="fa fa-fw fa-check-circle"></i></a>
</div>
</td> </td>
<td> <td>