Merge early release branch

Code for #749
  Add link to split withdrawal
  Clarifies #751
  Text for #748
  Improve error reporting #752
  Small code cleanup.
  Add copyright markers.
This commit is contained in:
James Cole
2017-08-12 06:59:59 +02:00
21 changed files with 168 additions and 44 deletions

View File

@@ -1,10 +1,20 @@
<?php <?php
/**
* UseEncryption.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
namespace FireflyIII\Console\Commands; namespace FireflyIII\Console\Commands;
use Illuminate\Console\Command; use Illuminate\Console\Command;
use Illuminate\Support\Str; use Illuminate\Support\Str;
/**
* Class UseEncryption
*/
class UseEncryption extends Command class UseEncryption extends Command
{ {
/** /**

View File

@@ -45,11 +45,11 @@ final class Entry
public $transaction_type; public $transaction_type;
public $source_account_id; public $asset_account_id;
public $source_account_name; public $asset_account_name;
public $destination_account_id; public $opposing_account_id;
public $destination_account_name; public $opposing_account_name;
public $budget_id; public $budget_id;
public $budget_name; public $budget_name;
@@ -71,21 +71,21 @@ final class Entry
*/ */
public static function fromObject($object): Entry public static function fromObject($object): Entry
{ {
$entry = new self; $entry = new self;
$entry->journal_id = $object->transaction_journal_id; $entry->journal_id = $object->transaction_journal_id;
$entry->description = Steam::decrypt(intval($object->journal_encrypted), $object->journal_description); $entry->description = Steam::decrypt(intval($object->journal_encrypted), $object->journal_description);
$entry->amount = $object->amount; $entry->amount = $object->amount;
$entry->date = $object->date; $entry->date = $object->date;
$entry->transaction_type = $object->transaction_type; $entry->transaction_type = $object->transaction_type;
$entry->currency_code = $object->transaction_currency_code; $entry->currency_code = $object->transaction_currency_code;
$entry->source_account_id = $object->account_id; $entry->asset_account_id = $object->account_id;
$entry->source_account_name = Steam::decrypt(intval($object->account_name_encrypted), $object->account_name); $entry->asset_account_name = Steam::decrypt(intval($object->account_name_encrypted), $object->account_name);
$entry->destination_account_id = $object->opposing_account_id; $entry->opposing_account_id = $object->opposing_account_id;
$entry->destination_account_name = Steam::decrypt(intval($object->opposing_account_encrypted), $object->opposing_account_name); $entry->opposing_account_name = Steam::decrypt(intval($object->opposing_account_encrypted), $object->opposing_account_name);
$entry->category_id = $object->category_id ?? ''; $entry->category_id = $object->category_id ?? '';
$entry->category_name = $object->category_name ?? ''; $entry->category_name = $object->category_name ?? '';
$entry->budget_id = $object->budget_id ?? ''; $entry->budget_id = $object->budget_id ?? '';
$entry->budget_name = $object->budget_name ?? ''; $entry->budget_name = $object->budget_name ?? '';
// update description when transaction description is different: // update description when transaction description is different:
if (!is_null($object->description) && $object->description !== $entry->description) { if (!is_null($object->description) && $object->description !== $entry->description) {

View File

@@ -53,7 +53,7 @@ class RegisterController extends Controller
} }
/** /**
* @param Request $request * @param UserRegistrationRequest|Request $request
* *
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
*/ */

View File

@@ -227,8 +227,6 @@ class CategoryController extends Controller
$subTitleIcon = 'fa-bar-chart'; $subTitleIcon = 'fa-bar-chart';
$page = intval($request->get('page')); $page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data); $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$count = 0;
$loop = 0;
$range = Preferences::get('viewRange', '1M')->data; $range = Preferences::get('viewRange', '1M')->data;
$start = null; $start = null;
$end = null; $end = null;

View File

@@ -199,10 +199,10 @@ class SingleController extends Controller
} }
/** /**
* @param JournalRepositoryInterface $repository * @param TransactionJournal $transactionJournal
* @param TransactionJournal $transactionJournal
* *
* @return \Illuminate\Http\RedirectResponse * @return \Illuminate\Http\RedirectResponse
* @internal param JournalRepositoryInterface $repository
*/ */
public function destroy(TransactionJournal $transactionJournal) public function destroy(TransactionJournal $transactionJournal)
{ {

View File

@@ -72,8 +72,6 @@ class TransactionController extends Controller
$types = config('firefly.transactionTypesByWhat.' . $what); $types = config('firefly.transactionTypesByWhat.' . $what);
$page = intval($request->get('page')); $page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data); $pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$count = 0;
$loop = 0;
$range = Preferences::get('viewRange', '1M')->data; $range = Preferences::get('viewRange', '1M')->data;
$start = null; $start = null;
$end = null; $end = null;

View File

@@ -151,6 +151,43 @@ class CsvProcessor implements FileProcessorInterface
return $results; return $results;
} }
/**
* Will return string representation of JSON error code.
*
* @param int $jsonError
*
* @return string
*/
private function getJsonError(int $jsonError): string
{
switch ($jsonError) {
default:
return 'Unknown JSON error';
case JSON_ERROR_NONE:
return 'No JSON error';
case JSON_ERROR_DEPTH:
return 'JSON_ERROR_DEPTH';
case JSON_ERROR_STATE_MISMATCH:
return 'JSON_ERROR_STATE_MISMATCH';
case JSON_ERROR_CTRL_CHAR:
return 'JSON_ERROR_CTRL_CHAR';
case JSON_ERROR_SYNTAX:
return 'JSON_ERROR_SYNTAX';
case JSON_ERROR_UTF8:
return 'JSON_ERROR_UTF8';
case JSON_ERROR_RECURSION:
return 'JSON_ERROR_RECURSION';
case JSON_ERROR_INF_OR_NAN:
return 'JSON_ERROR_INF_OR_NAN';
case JSON_ERROR_UNSUPPORTED_TYPE:
return 'JSON_ERROR_UNSUPPORTED_TYPE';
case JSON_ERROR_INVALID_PROPERTY_NAME:
return 'JSON_ERROR_INVALID_PROPERTY_NAME';
case JSON_ERROR_UTF16:
return 'JSON_ERROR_UTF16';
}
}
/** /**
* Take a row, build import journal by annotating each value and storing it in the import journal. * Take a row, build import journal by annotating each value and storing it in the import journal.
* *
@@ -158,14 +195,22 @@ class CsvProcessor implements FileProcessorInterface
* @param array $row * @param array $row
* *
* @return ImportJournal * @return ImportJournal
* @throws FireflyException
*/ */
private function importRow(int $index, array $row): ImportJournal private function importRow(int $index, array $row): ImportJournal
{ {
Log::debug(sprintf('Now at row %d', $index)); Log::debug(sprintf('Now at row %d', $index));
$row = $this->specifics($row); $row = $this->specifics($row);
$json = json_encode($row);
$jsonError = json_last_error();
if ($json === false) {
throw new FireflyException(sprintf('Error while encoding JSON: %s', $this->getJsonError($jsonError)));
}
$journal = new ImportJournal; $journal = new ImportJournal;
$journal->setUser($this->job->user); $journal->setUser($this->job->user);
$journal->setHash(hash('sha256', json_encode($row))); $journal->setHash(hash('sha256', $json));
foreach ($row as $rowIndex => $value) { foreach ($row as $rowIndex => $value) {
$value = trim($value); $value = trim($value);

View File

@@ -1,5 +1,15 @@
<?php <?php
/**
* RegisteredUser.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
namespace FireflyIII\Mail; namespace FireflyIII\Mail;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;

View File

@@ -1,5 +1,15 @@
<?php <?php
/**
* RequestedNewPassword.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
namespace FireflyIII\Mail; namespace FireflyIII\Mail;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;

View File

@@ -1,4 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--
~ browserconfig.xml
~ Copyright (c) 2017 thegrumpydictator@gmail.com
~ This software may be modified and distributed under the terms of the
~ Creative Commons Attribution-ShareAlike 4.0 International License.
~
~ See the LICENSE file for details.
-->
<browserconfig> <browserconfig>
<msapplication> <msapplication>
<tile> <tile>

View File

@@ -7,7 +7,7 @@
* *
* See the LICENSE file for details. * See the LICENSE file for details.
*/ */
/** global: Chart, defaultChartOptions, accounting, defaultPieOptions, noDataForChart, noDataForChart */ /** global: Chart, defaultChartOptions, accounting, defaultPieOptions, noDataForChart */
var allCharts = {}; var allCharts = {};
/* /*

View File

@@ -78,8 +78,7 @@ function showDownload() {
function showError(text) { function showError(text) {
"use strict"; "use strict";
$('#export-error').show(); $('#export-error').show().find('p').text(text);
$('#export-error').find('p').text(text);
} }
function callExport() { function callExport() {

View File

@@ -220,18 +220,24 @@ function resetDivSplits() {
function calculateSum() { function calculateSum() {
"use strict"; "use strict";
var left = originalSum * -1;
var sum = 0; var sum = 0;
var set = $('input[name$="][amount]"]'); var set = $('input[name$="][amount]"]');
for (var i = 0; i < set.length; i++) { for (var i = 0; i < set.length; i++) {
var current = $(set[i]); var current = $(set[i]);
sum += (current.val() === "" ? 0 : parseFloat(current.val())); sum += (current.val() === "" ? 0 : parseFloat(current.val()));
left += (current.val() === "" ? 0 : parseFloat(current.val()));
} }
sum = Math.round(sum * 100) / 100; sum = Math.round(sum * 100) / 100;
left = Math.round(left * 100) / 100;
$('.amount-warning').remove(); $('.amount-warning').remove();
if (sum !== originalSum) { if (sum !== originalSum) {
var holder = $('#journal_amount_holder'); var holder = $('#journal_amount_holder');
var par = holder.find('p.form-control-static'); var par = holder.find('p.form-control-static');
$('<span>').text(' (' + accounting.formatMoney(sum) + ')').addClass('text-danger amount-warning').appendTo(par); $('<span>').text(' (' + accounting.formatMoney(sum) + ')').addClass('text-danger amount-warning').appendTo(par);
// also add what's left to divide (or vice versa)
$('<span>').text(' (' + accounting.formatMoney(left) + ')').addClass('text-danger amount-warning').appendTo(par);
} }
} }

View File

@@ -1,4 +1,13 @@
<?xml version="1.0" standalone="no"?> <?xml version="1.0" standalone="no"?>
<!--
~ safari-pinned-tab.svg
~ Copyright (c) 2017 thegrumpydictator@gmail.com
~ This software may be modified and distributed under the terms of the
~ Creative Commons Attribution-ShareAlike 4.0 International License.
~
~ See the LICENSE file for details.
-->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" <svg version="1.0" xmlns="http://www.w3.org/2000/svg"

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -519,6 +519,7 @@ return [
'update_amount' => 'Update amount', 'update_amount' => 'Update amount',
'update_budget' => 'Update budget', 'update_budget' => 'Update budget',
'update_budget_amount_range' => 'Update (expected) available amount between :start and :end', 'update_budget_amount_range' => 'Update (expected) available amount between :start and :end',
'budget_period_navigator' => 'Period navigator',
// bills: // bills:
'matching_on' => 'Matching on', 'matching_on' => 'Matching on',

View File

@@ -221,7 +221,7 @@
<div class="box-body"> <div class="box-body">
{% if journal.transactionType.type != "Withdrawal" %} {% if journal.transactionType.type != "Withdrawal" %}
<p> <p>
<i class="fa fa-exchange" aria-hidden="true"></i> <i class="fa fa-exchange fa-fw" aria-hidden="true"></i>
<a href="{{ route('transactions.convert.index', ['withdrawal', journal.id]) }}"> <a href="{{ route('transactions.convert.index', ['withdrawal', journal.id]) }}">
{{ ('convert_'~journal.transactionType.type~'_to_withdrawal')|_ }} {{ ('convert_'~journal.transactionType.type~'_to_withdrawal')|_ }}
</a> </a>
@@ -229,7 +229,7 @@
{% endif %} {% endif %}
{% if journal.transactionType.type != "Deposit" %} {% if journal.transactionType.type != "Deposit" %}
<p> <p>
<i class="fa fa-exchange" aria-hidden="true"></i> <i class="fa fa-exchange fa-fw" aria-hidden="true"></i>
<a href="{{ route('transactions.convert.index', ['deposit', journal.id]) }}"> <a href="{{ route('transactions.convert.index', ['deposit', journal.id]) }}">
{{ ('convert_'~journal.transactionType.type~'_to_deposit')|_ }} {{ ('convert_'~journal.transactionType.type~'_to_deposit')|_ }}
</a> </a>
@@ -238,21 +238,24 @@
{% if journal.transactionType.type != "Transfer" %} {% if journal.transactionType.type != "Transfer" %}
<p> <p>
<i class="fa fa-exchange" aria-hidden="true"></i> <i class="fa fa-exchange fa-fw" aria-hidden="true"></i>
<a href="{{ route('transactions.convert.index', ['transfer', journal.id]) }}"> <a href="{{ route('transactions.convert.index', ['transfer', journal.id]) }}">
{{ ('convert_'~journal.transactionType.type~'_to_transfer')|_ }} {{ ('convert_'~journal.transactionType.type~'_to_transfer')|_ }}
</a> </a>
</p> </p>
{% endif %} {% endif %}
{% if transactions|length == 1 %}
<p> <p>
<i class="fa fa-copy" aria-hidden="true"></i> <i class="fa fa-copy fa-fw" aria-hidden="true"></i>
<a href="{{ route('transactions.clone', [journal.id]) }}"> <a href="{{ route('transactions.clone', [journal.id]) }}">
{{ ('clone_'~journal.transactionType.type|lower)|_ }} {{ ('clone_'~journal.transactionType.type|lower)|_ }}
</a> </a>
</p> </p>
{% endif %} <p>
<i class="fa fa-unsorted fa-fw" aria-hidden="true"></i>
<a href="{{ route('transactions.split.edit', journal.id) }}">
{{ ('split_this_'~what)|_ }}
</a>
</p>
</div> </div>
</div> </div>
{% endif %} {% endif %}

View File

@@ -1,5 +1,15 @@
<?php <?php
/**
* CreatesApplication.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
namespace Tests; namespace Tests;
use Illuminate\Contracts\Console\Kernel; use Illuminate\Contracts\Console\Kernel;

View File

@@ -83,7 +83,6 @@ class TagControllerTest extends TestCase
public function testEdit() public function testEdit()
{ {
// mock stuff // mock stuff
$repository = $this->mock(TagRepositoryInterface::class);
$journalRepos = $this->mock(JournalRepositoryInterface::class); $journalRepos = $this->mock(JournalRepositoryInterface::class);
$journalRepos->shouldReceive('first')->once()->andReturn(new TransactionJournal); $journalRepos->shouldReceive('first')->once()->andReturn(new TransactionJournal);

View File

@@ -1,5 +1,15 @@
<?php <?php
/**
* TestCase.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
namespace Tests; namespace Tests;
use Carbon\Carbon; use Carbon\Carbon;

View File

@@ -1,5 +1,15 @@
<?php <?php
/**
* ExampleTest.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
namespace Tests\Unit; namespace Tests\Unit;
use Tests\TestCase; use Tests\TestCase;

View File

@@ -22,9 +22,6 @@ use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction; use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionType; use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Tests\TestCase; use Tests\TestCase;
@@ -62,7 +59,7 @@ class MetaPieChartTest extends TestCase
$collector->shouldReceive('getJournals')->andReturn($collection); $collector->shouldReceive('getJournals')->andReturn($collection);
// mock all repositories: // mock all repositories:
$accountRepos = $this->mock(AccountRepositoryInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class);
$accountRepos->shouldReceive('setUser'); $accountRepos->shouldReceive('setUser');
$accountRepos->shouldReceive('find')->withArgs([1])->andReturn($accounts[1]); $accountRepos->shouldReceive('find')->withArgs([1])->andReturn($accounts[1]);
@@ -122,7 +119,7 @@ class MetaPieChartTest extends TestCase
$collector->shouldReceive('getJournals')->andReturn($others)->once(); $collector->shouldReceive('getJournals')->andReturn($others)->once();
// mock all repositories: // mock all repositories:
$accountRepos = $this->mock(AccountRepositoryInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class);
$accountRepos->shouldReceive('setUser'); $accountRepos->shouldReceive('setUser');
$accountRepos->shouldReceive('find')->withArgs([1])->andReturn($accounts[1]); $accountRepos->shouldReceive('find')->withArgs([1])->andReturn($accounts[1]);