Compare commits

...

57 Commits
3.8.0 ... 3.8.1

Author SHA1 Message Date
James Cole
9250cee9e7 Merge branch 'release/3.8.1' 2016-03-29 17:42:44 +02:00
James Cole
bb075d15ff Add warning about PHP 7.0 2016-03-29 17:42:32 +02:00
James Cole
a31f16bba7 Change log for 3.8.1 [skip ci] 2016-03-29 17:41:43 +02:00
James Cole
88a41c37f3 Bug fix, thank you scrutiniser. 2016-03-29 17:18:42 +02:00
James Cole
d21885ca98 New translations. 2016-03-29 16:38:42 +02:00
James Cole
d774f8e870 Code cleanup. 2016-03-29 16:17:06 +02:00
James Cole
08b5e66628 Some code cleanup. 2016-03-29 16:16:14 +02:00
James Cole
6fdfec3967 Clean up some code. 2016-03-29 16:13:36 +02:00
James Cole
ab4616a3ad Make some vars longer. 2016-03-29 16:10:51 +02:00
James Cole
cb34ff4c83 Clean up some code. 2016-03-29 16:02:54 +02:00
James Cole
bdbead256c Make field a number. 2016-03-29 16:02:09 +02:00
James Cole
f200086d01 Code for #207 2016-03-29 15:55:14 +02:00
James Cole
ef97c3b42d Some new help text for bills. #207 2016-03-29 15:33:09 +02:00
James Cole
ed8b41e8ec Add source account to scan, see issue #226 2016-03-29 15:24:40 +02:00
James Cole
aada3371b7 Better translations for dates and so on. 2016-03-29 15:09:37 +02:00
James Cole
38a9782bdf Debug. 2016-03-29 13:55:57 +02:00
James Cole
c6ac81dcf6 Some more confirmation things. 2016-03-29 13:52:51 +02:00
James Cole
2d3f3f0fde Updated the routes. 2016-03-29 13:45:18 +02:00
James Cole
993a2c7823 New middleware. 2016-03-29 12:23:10 +02:00
James Cole
87b36cf7e3 Update 2FA and account activation 2016-03-29 12:14:01 +02:00
James Cole
742f2c8d9f New middle ware for user activation. 2016-03-29 11:55:49 +02:00
James Cole
0d7ac5f1d8 Move some routes around. 2016-03-29 11:55:38 +02:00
James Cole
3adccff611 New events and their handlers for user activation and other things. 2016-03-29 11:55:25 +02:00
James Cole
08b8bd27f9 Expand Preferences to handle not logged in users. 2016-03-29 11:55:02 +02:00
James Cole
1059c7e2be Updated config for user activation. 2016-03-29 11:54:50 +02:00
James Cole
3ebcd5f738 New translations for user activation. 2016-03-29 11:54:36 +02:00
James Cole
4627ea1dec Updated views for user activation. 2016-03-29 11:54:26 +02:00
James Cole
7ed24e78d5 New emails for the activation. 2016-03-29 11:48:29 +02:00
James Cole
ae02e3fd8d New example configuration that includes user account activation (disabled by default). 2016-03-29 11:46:21 +02:00
James Cole
cc88d5962e Move code to event handlers instead of registration routine. 2016-03-28 19:50:24 +02:00
James Cole
70c8a524cd Should fix the tests 2016-03-22 17:22:48 +01:00
James Cole
9a8efc8a58 Info in tags for #159 2016-03-22 16:59:29 +01:00
James Cole
f0f67b87c4 Code for #159 2016-03-22 16:57:26 +01:00
James Cole
1a3ec98896 Give all icons some context, no value yet. 2016-03-22 16:55:04 +01:00
James Cole
efff44cba9 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  Fix link to non-existing budget
2016-03-22 16:54:31 +01:00
James Cole
7227418c4c More fine-grained cookie control. 2016-03-22 15:04:51 +01:00
James Cole
29f93a9b73 Fix link to non-existing budget 2016-03-22 09:04:32 +01:00
James Cole
532aa2acd0 Fix amount [skip ci] 2016-03-21 19:29:24 +01:00
James Cole
6aca410f37 Fix amount [skip ci] 2016-03-21 19:28:22 +01:00
James Cole
f20656b516 Merge branch 'develop' of https://github.com/JC5/firefly-iii into develop
* 'develop' of https://github.com/JC5/firefly-iii:
  Fix for #227
2016-03-21 19:27:13 +01:00
James Cole
bcd7866e10 For debug, add float. [skip ci] 2016-03-21 19:24:15 +01:00
James Cole
c1b8d44209 Small various fixes. 2016-03-21 19:22:37 +01:00
James Cole
50e947fbbe Fix for #227 2016-03-21 08:48:36 +01:00
James Cole
189d969ee6 Include "no budget" thing for issue #152 2016-03-20 20:06:05 +01:00
James Cole
201790ff8d Cleanup transaction journal edit. #215 2016-03-20 17:12:34 +01:00
James Cole
cc26ce4143 Some scrutiniser related code cleanup. 2016-03-20 16:49:49 +01:00
James Cole
745e0aa525 Move to object held user object. 2016-03-20 16:47:53 +01:00
James Cole
6602b1587a Some scrutiniser related code cleanup. 2016-03-20 16:46:26 +01:00
James Cole
6698b57f52 Fixed a bug that would leave all amounts at zero. #224 2016-03-20 16:41:48 +01:00
James Cole
628268d47c Code to fix #223 2016-03-20 11:47:10 +01:00
James Cole
56a635212a Code for #155 2016-03-20 11:46:27 +01:00
James Cole
7e67eb17e0 All new translations for #218 2016-03-20 11:38:01 +01:00
James Cole
935d72d672 New English text for issue #218 2016-03-20 11:36:50 +01:00
James Cole
fccb510186 Merge pull request #222 from eddyh/patch-1
Fixed small typo.
2016-03-20 11:34:58 +01:00
Edwin
e7ea0dc842 Fixed small typo. 2016-03-19 18:45:12 +01:00
James Cole
a40d6b0649 Merge branch 'master' into develop
* master:
  Code cleanup [skip ci]
  Quick bug fix.
2016-03-19 17:40:24 +01:00
James Cole
48c865e57a Merge branch 'hotfix/account-repos' into develop 2016-03-19 17:28:16 +01:00
104 changed files with 1473 additions and 469 deletions

View File

@@ -13,6 +13,10 @@ CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
COOKIE_PATH="/"
COOKIE_DOMAIN=
COOKIE_SECURE=false
DEFAULT_CURRENCY=EUR
DEFAULT_LANGUAGE=en_US
@@ -28,6 +32,9 @@ MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
SEND_REGISTRATION_MAIL=true
MUST_CONFIRM_ACCOUNT=false
SHOW_INCOMPLETE_TRANSLATIONS=false
ANALYTICS_ID=

View File

@@ -5,6 +5,31 @@ This project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
- No unreleased changes yet.
## [3.8.1] - 2016-03-29
### Added
- More translations
- Extended cookie control.
- User accounts can now be activated (disabled by default).
- Bills can now take the source and destination account name into account.
### Changed
- The pages related to rules have new URL's.
### Deprecated
- Initial release.
### Removed
- Initial release.
### Fixed
- Spelling errors.
- Problems related to the "account repository".
- Some views showed empty (0.0) amounts.
### Security
- Initial release.
## [3.8.0] - 2016-03-20
### Added
- Two factor authentication, thanks to the excellent work of [zjean](https://github.com/zjean).

View File

@@ -0,0 +1,38 @@
<?php
/**
* ResendConfirmation.php
* Copyright (C) 2016 Sander Dorigo
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Events;
use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
/**
* Class ResendConfirmation
*
* @package FireflyIII\Events
*/
class ResendConfirmation extends Event
{
use SerializesModels;
public $ipAddress;
public $user;
/**
* Create a new event instance.
*
* @param User $user
* @param string $ipAddress
*/
public function __construct(User $user, string $ipAddress)
{
$this->user = $user;
$this->ipAddress = $ipAddress;
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* UserRegistration.php
* Copyright (C) 2016 Sander Dorigo
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Events;
use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
/**
* Class UserRegistration
*
* @package FireflyIII\Events
*/
class UserRegistration extends Event
{
use SerializesModels;
public $ipAddress;
public $user;
/**
* Create a new event instance.
*
* @param User $user
* @param string $ipAddress
*/
public function __construct(User $user, string $ipAddress)
{
$this->user = $user;
$this->ipAddress = $ipAddress;
}
}

View File

@@ -159,6 +159,9 @@ class ChartJsBudgetChartGenerator implements BudgetChartGeneratorInterface
foreach ($budgets as $budget) {
$data['labels'][] = $budget->name;
}
// also add "no budget"
$data['labels'][] = strval(trans('firefly.no_budget'));
/** @var array $entry */
foreach ($entries as $entry) {
$array = [

View File

@@ -0,0 +1,51 @@
<?php
/**
* AttachUserRole.php
* Copyright (C) 2016 Sander Dorigo
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\UserRegistration;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use Log;
/**
* Class AttachUserRole
*
* @package FireflyIII\Handlers\Events
*/
class AttachUserRole
{
/**
* Create the event listener.
*
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param UserRegistration $event
*/
public function handle(UserRegistration $event)
{
Log::debug('Trigger attachuserrole');
/** @var UserRepositoryInterface $repository */
$repository = app('FireflyIII\Repositories\User\UserRepositoryInterface');
// first user ever?
if ($repository->count() == 1) {
Log::debug('Will attach role.');
$repository->attachRole($event->user, 'owner');
}
}
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* SendRegistrationMail.php
* Copyright (C) 2016 Sander Dorigo
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\UserRegistration;
use Illuminate\Mail\Message;
use Log;
use Mail;
use Swift_TransportException;
/**
* Class SendRegistrationMail
*
* @package FireflyIII\Handlers\Events
*/
class SendRegistrationMail
{
/**
* Create the event listener.
*
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* @param UserRegistration $event
*
* @return void
*/
public function handle(UserRegistration $event)
{
$sendMail = env('SEND_REGISTRATION_MAIL', true);
if (!$sendMail) {
return;
}
// get the email address
$email = $event->user->email;
$address = route('index');
$ipAddress = $event->ipAddress;
// send email.
try {
Mail::send(
['emails.registered-html', 'emails.registered'], ['address' => $address, 'ip' => $ipAddress], function (Message $message) use ($email) {
$message->to($email, $email)->subject('Welcome to Firefly III! ');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
}
}

View File

@@ -0,0 +1,114 @@
<?php
/**
* UserConfirmation.php
* Copyright (C) 2016 Sander Dorigo
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Handlers\Events;
use Exception;
use FireflyIII\Events\ResendConfirmation;
use FireflyIII\Events\UserRegistration;
use FireflyIII\User;
use Illuminate\Mail\Message;
use Log;
use Mail;
use Preferences;
use Swift_TransportException;
/**
* Class UserConfirmation
*
* @package FireflyIII\Handlers\Events
*/
class UserConfirmation
{
/**
* Create the event listener.
*
*/
public function __construct()
{
//
}
/**
* @param ResendConfirmation $event
*/
public function resendConfirmation(ResendConfirmation $event)
{
$user = $event->user;
$ipAddress = $event->ipAddress;
$this->doConfirm($user, $ipAddress);
}
/**
* Handle the event.
*
* @param UserRegistration $event
*/
public function sendConfirmation(UserRegistration $event)
{
$user = $event->user;
$ipAddress = $event->ipAddress;
$this->doConfirm($user, $ipAddress);
}
/**
* @param User $user
* @param string $ipAddress
*/
private function doConfirm(User $user, string $ipAddress)
{
Log::debug('Trigger UserConfirmation::doConfirm');
// if user must confirm account, send email
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
// otherwise, auto-confirm:
if ($confirmAccount === false) {
Log::debug('Confirm account is false, so user will be auto-confirmed.');
Preferences::setForUser($user, 'user_confirmed', true);
Preferences::setForUser($user, 'user_confirmed_last_mail', 0);
Preferences::mark();
return;
}
// send email message:
$email = $user->email;
$code = str_random(16);
$route = route('do_confirm_account', [$code]);
// set preferences:
Preferences::setForUser($user, 'user_confirmed', false);
Preferences::setForUser($user, 'user_confirmed_last_mail', time());
Preferences::setForUser($user, 'user_confirmed_code', $code);
Log::debug('Set preferences for user.');
// send email.
try {
Log::debug('Now in try block for user email message thing to ' . $email . '.');
Mail::send(
['emails.confirm-account-html', 'emails.confirm-account'], ['route' => $route, 'ip' => $ipAddress],
function (Message $message) use ($email) {
$message->to($email, $email)->subject('Please confirm your Firefly III account');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
} catch (Exception $e) {
Log::debug('Caught general exception.');
Log::error($e->getMessage());
}
Log::debug('Finished mail handling for activation.');
return;
}
}

View File

@@ -21,7 +21,7 @@ class UserEventListener
/**
* Handle user logout events.
*/
public function onUserLogout($event)
public function onUserLogout()
{
// dump stuff from the session:
Session::forget('twofactor-authenticated');
@@ -29,4 +29,4 @@ class UserEventListener
return true;
}
}
}

View File

@@ -102,7 +102,7 @@ class BalanceLine
return $this->getBudget()->name;
}
if ($this->getRole() == self::ROLE_DEFAULTROLE) {
return trans('firefly.noBudget');
return trans('firefly.no_budget');
}
if ($this->getRole() == self::ROLE_TAGROLE) {
return trans('firefly.coveredWithTags');

View File

@@ -91,7 +91,7 @@ class AccountController extends Controller
$repository->destroy($account, $moveTo);
Session::flash('success', trans('firefly.' . $typeName . '_deleted', ['name' => $name]));
Session::flash('success', strval(trans('firefly.' . $typeName . '_deleted', ['name' => $name])));
Preferences::mark();
return redirect(session('accounts.delete.url'));
@@ -224,7 +224,7 @@ class AccountController extends Controller
$account = $repository->store($accountData);
Session::flash('success', 'New account "' . $account->name . '" stored!');
Session::flash('success', strval(trans('firefly.stored_new_account', ['name' => $account->name])));
Preferences::mark();
// update preferences if necessary:
@@ -271,7 +271,7 @@ class AccountController extends Controller
];
$repository->update($account, $accountData);
Session::flash('success', 'Account "' . $account->name . '" updated.');
Session::flash('success', strval(trans('firefly.updated_account', ['name' => $account->name])));
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {

View File

@@ -64,7 +64,7 @@ class AttachmentController extends Controller
$repository->destroy($attachment);
Session::flash('success', trans('firefly.attachment_deleted', ['name' => $name]));
Session::flash('success', strval(trans('firefly.attachment_deleted', ['name' => $name])));
Preferences::mark();
return redirect(session('attachments.delete.url'));
@@ -159,7 +159,7 @@ class AttachmentController extends Controller
$repository->update($attachment, $attachmentData);
Session::flash('success', 'Attachment "' . $attachment->filename . '" updated.');
Session::flash('success', strval(trans('firefly.attachment_updated', ['name' => $attachment->filename])));
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {

View File

@@ -4,9 +4,9 @@ declare(strict_types = 1);
namespace FireflyIII\Http\Controllers\Auth;
use Auth;
use FireflyIII\Events\UserRegistration;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
use Illuminate\Foundation\Auth\ThrottlesLogins;
@@ -91,14 +91,13 @@ class AuthController extends Controller
/**
* Handle a registration request for the application.
*
* @param UserRepositoryInterface $repository
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\Response
* @throws FireflyException
* @throws \Illuminate\Foundation\Validation\ValidationException
*/
public function register(UserRepositoryInterface $repository, Request $request)
public function register(Request $request)
{
$validator = $this->validator($request->all());
@@ -123,37 +122,18 @@ class AuthController extends Controller
}
Auth::login($this->create($request->all()));
$user = $this->create($request->all());
// get the email address
if (Auth::user() instanceof User) {
$email = Auth::user()->email;
$address = route('index');
$ipAddress = $request->ip();
// send email.
try {
Mail::send(
['emails.registered-html', 'emails.registered'], ['address' => $address, 'ip' => $ipAddress], function (Message $message) use ($email) {
$message->to($email, $email)->subject('Welcome to Firefly III! ');
}
);
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
// trigger user registration event:
event(new UserRegistration($user, $request->ip()));
// set flash message
Session::flash('success', 'You have registered successfully!');
Session::flash('gaEventCategory', 'user');
Session::flash('gaEventAction', 'new-registration');
Auth::login($user);
// first user ever?
if ($repository->count() == 1) {
$repository->attachRole(Auth::user(), 'owner');
}
Session::flash('success', strval(trans('firefly.registered')));
Session::flash('gaEventCategory', 'user');
Session::flash('gaEventAction', 'new-registration');
return redirect($this->redirectPath());
}
throw new FireflyException('The authenticated user object is invalid.');
return redirect($this->redirectPath());
}
/**

View File

@@ -0,0 +1,82 @@
<?php
/**
* ConfirmationController.php
* Copyright (C) 2016 Sander Dorigo
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace FireflyIII\Http\Controllers\Auth;
use Auth;
use Config;
use FireflyIII\Events\ResendConfirmation;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Preferences;
use Session;
/**
* Class ConfirmationController
*
* @package FireflyIII\Http\Controllers\Auth
*/
class ConfirmationController extends Controller
{
/**
* @return mixed
*/
public function confirmationError()
{
return view('auth.confirmation.error');
}
/**
* @param string $code
*
* @return mixed
* @throws FireflyException
*/
public function doConfirmation(string $code)
{
// check user_confirmed_last_mail
$database = Preferences::get('user_confirmed_code')->data;
$time = Preferences::get('user_confirmed_last_mail', 0)->data;
$now = time();
$maxDiff = Config::get('firefly.confirmation_age');
if ($database === $code && ($now - $time <= $maxDiff)) {
Preferences::setForUser(Auth::user(), 'user_confirmed', true);
Preferences::setForUser(Auth::user(), 'user_confirmed_confirmed', time());
Session::flash('success', strval(trans('firefly.account_is_confirmed')));
return redirect(route('home'));
} else {
throw new FireflyException(trans('firefly.invalid_activation_code'));
}
}
/**
* @param Request $request
*/
public function resendConfirmation(Request $request)
{
$time = Preferences::get('user_confirmed_last_mail', 0)->data;
$now = time();
$maxDiff = Config::get('firefly.resend_confirmation');
$owner = env('SITE_OWNER', 'mail@example.com');
if ($now - $time > $maxDiff) {
event(new ResendConfirmation(Auth::user(), $request->ip()));
return view('auth.confirmation.resent', ['owner' => $owner]);
} else {
return view('auth.confirmation.no-resent', ['owner' => $owner]);
}
}
}

View File

@@ -38,7 +38,7 @@ class TwoFactorController extends Controller
$secret = Preferences::get('twoFactorAuthSecret', '')->data;
if (strlen($secret) === 0) {
throw new FireflyException('Your two factor authentication secret is empty, which it should be at this point. Please check the log files.');
throw new FireflyException('Your two factor authentication secret is empty, which it cannot be at this point. Please check the log files.');
}
Session::flash('two-factor-secret', $secret);
@@ -76,4 +76,4 @@ class TwoFactorController extends Controller
return redirect(route('home'));
}
}
}

View File

@@ -73,9 +73,10 @@ class BillController extends Controller
*/
public function destroy(BillRepositoryInterface $repository, Bill $bill)
{
$name = $bill->name;
$repository->destroy($bill);
Session::flash('success', 'The bill was deleted.');
Session::flash('success', strval(trans('firefly.deleted_bill', ['name' => $name])));
Preferences::mark();
return redirect(session('bills.delete.url'));
@@ -109,11 +110,29 @@ class BillController extends Controller
*/
public function index(BillRepositoryInterface $repository)
{
$start = session('start');
$end = session('end');
$bills = $repository->getBills();
$bills->each(
function (Bill $bill) use ($repository) {
function (Bill $bill) use ($repository, $start, $end) {
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill);
$bill->lastFoundMatch = $repository->lastFoundMatch($bill);
$journals = $repository->getJournalsInRange($bill, $start, $end);
// loop journals, find average:
$average = '0';
$count = $journals->count();
if ($count > 0) {
$sum = '0';
foreach ($journals as $journal) {
$sum = bcadd($sum, TransactionJournal::amountPositive($journal));
}
$average = bcdiv($sum, strval($count));
}
$bill->lastPaidAmount = $average;
$bill->paidInPeriod = ($start <= $bill->lastFoundMatch) && ($end >= $bill->lastFoundMatch);
}
);
@@ -129,7 +148,7 @@ class BillController extends Controller
public function rescan(BillRepositoryInterface $repository, Bill $bill)
{
if (intval($bill->active) == 0) {
Session::flash('warning', 'Inactive bills cannot be scanned.');
Session::flash('warning', strval(trans('firefly.cannot_scan_inactive_bill')));
return redirect(URL::previous());
}
@@ -141,7 +160,7 @@ class BillController extends Controller
}
Session::flash('success', 'Rescanned everything.');
Session::flash('success', strval(trans('firefly.rescanned_bill')));
Preferences::mark();
return redirect(URL::previous());
@@ -173,7 +192,7 @@ class BillController extends Controller
{
$billData = $request->getBillData();
$bill = $repository->store($billData);
Session::flash('success', 'Bill "' . e($bill->name) . '" stored.');
Session::flash('success', strval(trans('firefly.stored_new_bill', ['name' => e($bill->name)])));
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
@@ -200,7 +219,7 @@ class BillController extends Controller
$billData = $request->getBillData();
$bill = $repository->update($bill, $billData);
Session::flash('success', 'Bill "' . e($bill->name) . '" updated.');
Session::flash('success', strval(trans('firefly.updated_bill', ['name' => e($bill->name)])));
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {

View File

@@ -105,7 +105,7 @@ class BudgetController extends Controller
$repository->destroy($budget);
Session::flash('success', 'The budget "' . e($name) . '" was deleted.');
Session::flash('success', strval(trans('firefly.deleted_budget', ['name' => e($name)])));
Preferences::mark();
@@ -277,7 +277,7 @@ class BudgetController extends Controller
];
$budget = $repository->store($budgetData);
Session::flash('success', 'New budget "' . $budget->name . '" stored!');
Session::flash('success', strval(trans('firefly.stored_new_budget', ['name' => e($budget->name)])));
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
@@ -308,7 +308,7 @@ class BudgetController extends Controller
$repository->update($budget, $budgetData);
Session::flash('success', 'Budget "' . $budget->name . '" updated.');
Session::flash('success', strval(trans('firefly.updated_budget', ['name' => e($budget->name)])));
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {

View File

@@ -80,7 +80,7 @@ class CategoryController extends Controller
$name = $category->name;
$repository->destroy($category);
Session::flash('success', 'The category "' . e($name) . '" was deleted.');
Session::flash('success', strval(trans('firefly.deleted_category', ['name' => e($name)])));
Preferences::mark();
return redirect(session('categories.delete.url'));
@@ -248,7 +248,7 @@ class CategoryController extends Controller
];
$category = $repository->store($categoryData);
Session::flash('success', 'New category "' . $category->name . '" stored!');
Session::flash('success', strval(trans('firefly.stored_category', ['name' => e($category->name)])));
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
@@ -276,7 +276,7 @@ class CategoryController extends Controller
$repository->update($category, $categoryData);
Session::flash('success', 'Category "' . $category->name . '" updated.');
Session::flash('success', strval(trans('firefly.updated_category', ['name' => e($category->name)])));
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {

View File

@@ -198,7 +198,7 @@ class BudgetController extends Controller
}
$noBudgetExpenses = $repository->getWithoutBudgetSum($accounts, $start, $end);
$allEntries->push([trans('firefly.noBudget'), '0', '0', $noBudgetExpenses, '0', '0']);
$allEntries->push([trans('firefly.no_budget'), '0', '0', $noBudgetExpenses, '0', '0']);
$data = $this->generator->frontpage($allEntries);
$cache->store($data);
@@ -258,7 +258,7 @@ class BudgetController extends Controller
// basic information:
$year = $currentStart->year;
$entry['name'] = $budget->name ?? (string)trans('firefly.noBudget');
$entry['name'] = $budget->name ?? (string)trans('firefly.no_budget');
$spent = 0;
// this might be a good moment to collect no budget stuff.
if (is_null($budget->id)) {
@@ -321,7 +321,6 @@ class BudgetController extends Controller
foreach ($budgetInformation as $row) {
$budgets->push($row['budget']);
}
while ($start < $end) {
// month is the current end of the period:
$month = clone $start;
@@ -338,10 +337,13 @@ class BudgetController extends Controller
}
$row[] = $spent;
}
// add "no budget" thing.
$row[] = round(bcmul($repository->getWithoutBudgetSum($accounts, $start, $month), '-1'), 4);
$entries->push($row);
$start->endOfMonth()->addDay();
}
$data = $this->generator->year($budgets, $entries);
$cache->store($data);

View File

@@ -41,11 +41,8 @@ class Controller extends BaseController
View::share('hideTags', false);
if (Auth::check()) {
$pref = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US'));
$lang = $pref->data;
$this->monthFormat = (string)trans('config.month');
$this->monthAndDayFormat = (string)trans('config.month_and_day');
$this->dateTimeFormat = (string)trans('config.date_time');
$pref = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US'));
$lang = $pref->data;
App::setLocale($lang);
Carbon::setLocale(substr($lang, 0, 2));
@@ -55,6 +52,11 @@ class Controller extends BaseController
setlocale(LC_TIME, $locale);
setlocale(LC_MONETARY, $locale);
// save some formats:
$this->monthFormat = (string)trans('config.month');
$this->monthAndDayFormat = (string)trans('config.month_and_day');
$this->dateTimeFormat = (string)trans('config.date_time');
// change localeconv to a new array:
$numberFormatter = numfmt_create($lang, NumberFormatter::CURRENCY);
$localeconv = [

View File

@@ -61,7 +61,7 @@ class CsvController extends Controller
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-import-account', 'csv-specifix', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Log::error('Could not recover upload.');
Session::flash('warning', 'Could not recover upload.');
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
@@ -101,7 +101,7 @@ class CsvController extends Controller
{
$fields = ['csv-date-format', 'csv-has-headers', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', 'Could not recover upload.');
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
@@ -144,7 +144,7 @@ class CsvController extends Controller
{
$fields = ['csv-date-format', 'csv-has-headers', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', 'Could not recover upload.');
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
@@ -211,7 +211,7 @@ class CsvController extends Controller
{
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', 'Could not recover upload.');
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
@@ -227,7 +227,7 @@ class CsvController extends Controller
// Go back when no roles defined:
if (count($roles) === 0) {
Session::flash('warning', 'Please select some roles.');
Session::flash('warning', strval(trans('firefly.must_select_roles')));
return redirect(route('csv.column-roles'));
}
@@ -263,7 +263,7 @@ class CsvController extends Controller
// Make sure all fields we need are accounted for.
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', 'Could not recover upload.');
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
@@ -307,7 +307,7 @@ class CsvController extends Controller
*/
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles', 'csv-mapped', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', 'Could not recover upload.');
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
@@ -348,7 +348,7 @@ class CsvController extends Controller
*/
$fields = ['csv-file', 'csv-date-format', 'csv-has-headers', 'csv-map', 'csv-roles', 'csv-delimiter'];
if (!$this->wizard->sessionHasValues($fields)) {
Session::flash('warning', 'Could not recover upload.');
Session::flash('warning', strval(trans('firefly.could_not_recover')));
return redirect(route('csv.index'));
}
@@ -356,7 +356,7 @@ class CsvController extends Controller
// save mapping to session.
$mapped = [];
if (!is_array(Input::get('mapping'))) {
Session::flash('warning', 'Invalid mapping.');
Session::flash('warning', strval(trans('firefly.invalid_mapping')));
return redirect(route('csv.map'));
}
@@ -393,7 +393,7 @@ class CsvController extends Controller
public function upload(Request $request)
{
if (!$request->hasFile('csv')) {
Session::flash('warning', 'No file uploaded.');
Session::flash('warning', strval(trans('firefly.no_file_uploaded')));
return redirect(route('csv.index'));
}

View File

@@ -38,7 +38,7 @@ class HomeController extends Controller
$diff = $start->diffInDays($end);
if ($diff > 50) {
Session::flash('warning', $diff . ' days of data may take a while to load.');
Session::flash('warning', strval(trans('firefly.warning_much_data', ['days' => $diff])));
}
Session::put('start', $start);

View File

@@ -55,6 +55,7 @@ class NewUserController extends Controller
*/
public function submit(NewUserFormRequest $request, ARI $repository)
{
$count = 1;
// create normal asset account:
$assetAccount = [
'name' => $request->get('bank_name'),
@@ -86,6 +87,7 @@ class NewUserController extends Controller
'openingBalanceCurrency' => intval($request->input('amount_currency_id_savings_balance')),
];
$repository->store($savingsAccount);
$count++;
}
@@ -108,9 +110,14 @@ class NewUserController extends Controller
// store meta for CC:
$repository->storeMeta($creditCard, 'ccType', 'monthlyFull');
$repository->storeMeta($creditCard, 'ccMonthlyPaymentDate', Carbon::now()->year . '-01-01');
$count++;
}
Session::flash('success', 'New account(s) created!');
if ($count == 1) {
Session::flash('success', strval(trans('firefly.stored_new_account_new_user')));
} else {
Session::flash('success', strval(trans('firefly.stored_new_accounts_new_user')));
}
Preferences::mark();
return redirect(route('index'));

View File

@@ -108,7 +108,7 @@ class PiggyBankController extends Controller
{
Session::flash('success', 'Piggy bank "' . e($piggyBank->name) . '" deleted.');
Session::flash('success', strval(trans('firefly.deleted_piggy_bank', ['name' => e($piggyBank->name)])));
Preferences::mark();
$repository->destroy($piggyBank);
@@ -242,11 +242,15 @@ class PiggyBankController extends Controller
// create event
$repository->createEvent($piggyBank, $amount);
Session::flash('success', 'Added ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".');
Session::flash(
'success', strval(trans('firefly.added_amount_to_piggy', ['amount' => Amount::format($amount, false), 'name' => e($piggyBank->name)]))
);
Preferences::mark();
} else {
Log::error('Cannot add ' . $amount . ' because max amount is ' . $maxAmount . ' (left on account is ' . $leftOnAccount . ')');
Session::flash('error', 'Could not add ' . Amount::format($amount, false) . ' to "' . e($piggyBank->name) . '".');
Session::flash(
'error', strval(trans('firefly.cannot_add_amount_piggy', ['amount' => Amount::format($amount, false), 'name' => e($piggyBank->name)]))
);
}
return redirect(route('piggy-banks.index'));
@@ -272,10 +276,14 @@ class PiggyBankController extends Controller
// create event
$repository->createEvent($piggyBank, bcmul($amount, '-1'));
Session::flash('success', 'Removed ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".');
Session::flash(
'success', strval(trans('firefly.removed_amount_from_piggy', ['amount' => Amount::format($amount, false), 'name' => e($piggyBank->name)]))
);
Preferences::mark();
} else {
Session::flash('error', 'Could not remove ' . Amount::format($amount, false) . ' from "' . e($piggyBank->name) . '".');
Session::flash(
'error', strval(trans('firefly.cannot_remove_from_piggy', ['amount' => Amount::format($amount, false), 'name' => e($piggyBank->name)]))
);
}
return redirect(route('piggy-banks.index'));
@@ -329,7 +337,7 @@ class PiggyBankController extends Controller
$piggyBank = $repository->store($piggyBankData);
Session::flash('success', 'Stored piggy bank "' . e($piggyBank->name) . '".');
Session::flash('success', strval(trans('firefly.stored_piggy_bank', ['name' => e($piggyBank->name)])));
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
@@ -364,7 +372,7 @@ class PiggyBankController extends Controller
$piggyBank = $repository->update($piggyBank, $piggyBankData);
Session::flash('success', 'Updated piggy bank "' . e($piggyBank->name) . '".');
Session::flash('success', strval(trans('firefly.updated_piggy_bank', ['name' => e($piggyBank->name)])));
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {

View File

@@ -64,26 +64,26 @@ class PreferencesController extends Controller
*/
public function index(ARI $repository)
{
$accounts = $repository->getAccounts(['Default account', 'Asset account']);
$viewRangePref = Preferences::get('viewRange', '1M');
$viewRange = $viewRangePref->data;
$frontPageAccounts = Preferences::get('frontPageAccounts', []);
$budgetMax = Preferences::get('budgetMaximum', 1000);
$language = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US'))->data;
$budgetMaximum = $budgetMax->data;
$customFiscalYear = Preferences::get('customFiscalYear', 0)->data;
$fiscalYearStartStr = Preferences::get('fiscalYearStart', '01-01')->data;
$fiscalYearStart = date('Y') . '-' . $fiscalYearStartStr;
$twoFactorAuthEnabled = Preferences::get('twoFactorAuthEnabled', 0)->data;
$hasTwoFactorAuthSecret = !is_null(Preferences::get('twoFactorAuthSecret'));
$showIncomplete = env('SHOW_INCOMPLETE_TRANSLATIONS', false) === true;
$accounts = $repository->getAccounts(['Default account', 'Asset account']);
$viewRangePref = Preferences::get('viewRange', '1M');
$viewRange = $viewRangePref->data;
$frontPageAccounts = Preferences::get('frontPageAccounts', []);
$budgetMax = Preferences::get('budgetMaximum', 1000);
$language = Preferences::get('language', env('DEFAULT_LANGUAGE', 'en_US'))->data;
$budgetMaximum = $budgetMax->data;
$customFiscalYear = Preferences::get('customFiscalYear', 0)->data;
$fiscalYearStartStr = Preferences::get('fiscalYearStart', '01-01')->data;
$fiscalYearStart = date('Y') . '-' . $fiscalYearStartStr;
$is2faEnabled = Preferences::get('twoFactorAuthEnabled', 0)->data; // twoFactorAuthEnabled
$has2faSecret = !is_null(Preferences::get('twoFactorAuthSecret')); // hasTwoFactorAuthSecret
$showIncomplete = env('SHOW_INCOMPLETE_TRANSLATIONS', false) === true;
return view(
'preferences.index',
compact(
'budgetMaximum', 'language', 'accounts', 'frontPageAccounts',
'viewRange', 'customFiscalYear', 'fiscalYearStart', 'twoFactorAuthEnabled',
'hasTwoFactorAuthSecret', 'showIncomplete'
'viewRange', 'customFiscalYear', 'fiscalYearStart', 'is2faEnabled',
'has2faSecret', 'showIncomplete'
)
);
}
@@ -98,7 +98,7 @@ class PreferencesController extends Controller
Preferences::set('twoFactorAuthEnabled', 1);
Preferences::set('twoFactorAuthSecret', Session::get('two-factor-secret'));
Session::flash('success', 'Preferences saved!');
Session::flash('success', strval(trans('firefly.saved_preferences')));
Preferences::mark();
return redirect(route('preferences'));
@@ -151,7 +151,7 @@ class PreferencesController extends Controller
}
Session::flash('success', 'Preferences saved!');
Session::flash('success', strval(trans('firefly.saved_preferences')));
Preferences::mark();
// if we don't have a valid secret yet, redirect to the code page.

View File

@@ -60,7 +60,7 @@ class ProfileController extends Controller
{
// old, new1, new2
if (!Hash::check($request->get('current_password'), Auth::user()->password)) {
Session::flash('error', trans('firefly.invalid_current_password'));
Session::flash('error', strval(trans('firefly.invalid_current_password')));
return redirect(route('profile.change-password'));
}
@@ -75,7 +75,7 @@ class ProfileController extends Controller
Auth::user()->password = bcrypt($request->get('new_password'));
Auth::user()->save();
Session::flash('success', trans('firefly.password_changed'));
Session::flash('success', strval(trans('firefly.password_changed')));
return redirect(route('profile'));
}
@@ -90,7 +90,7 @@ class ProfileController extends Controller
{
// old, new1, new2
if (!Hash::check($request->get('password'), Auth::user()->password)) {
Session::flash('error', trans('firefly.invalid_password'));
Session::flash('error', strval(trans('firefly.invalid_password')));
return redirect(route('profile.delete-account'));
}

View File

@@ -91,7 +91,7 @@ class RuleGroupController extends Controller
$repository->destroy($ruleGroup, $moveTo);
Session::flash('success', trans('firefly.deleted_rule_group', ['title' => $title]));
Session::flash('success', strval(trans('firefly.deleted_rule_group', ['title' => $title])));
Preferences::mark();
@@ -162,7 +162,7 @@ class RuleGroupController extends Controller
$this->dispatch($job);
// Tell the user that the job is queued
Session::flash('success', trans('firefly.executed_group_on_existing_transactions', ['title' => $ruleGroup->title]));
Session::flash('success', strval(trans('firefly.executed_group_on_existing_transactions', ['title' => $ruleGroup->title])));
return redirect()->route('rules.index');
}
@@ -204,7 +204,7 @@ class RuleGroupController extends Controller
$ruleGroup = $repository->store($data);
Session::flash('success', trans('firefly.created_new_rule_group', ['title' => $ruleGroup->title]));
Session::flash('success', strval(trans('firefly.created_new_rule_group', ['title' => $ruleGroup->title])));
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
@@ -249,7 +249,7 @@ class RuleGroupController extends Controller
$repository->update($ruleGroup, $data);
Session::flash('success', trans('firefly.updated_rule_group', ['title' => $ruleGroup->title]));
Session::flash('success', strval(trans('firefly.updated_rule_group', ['title' => $ruleGroup->title])));
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {

View File

@@ -106,7 +106,7 @@ class TagController extends Controller
$tagName = $tag->tag;
$repository->destroy($tag);
Session::flash('success', 'Tag "' . e($tagName) . '" was deleted.');
Session::flash('success', strval(trans('firefly.deleted_tag', ['tag' => e($tagName)])));
Preferences::mark();
return redirect(route('tags.index'));
@@ -244,7 +244,7 @@ class TagController extends Controller
$data = $request->collectTagData();
$repository->store($data);
Session::flash('success', 'The tag has been created!');
Session::flash('success', strval(trans('firefly.created_tag', ['tag' => e($data['tag'])])));
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
@@ -271,7 +271,7 @@ class TagController extends Controller
$data = $request->collectTagData();
$repository->update($tag, $data);
Session::flash('success', 'Tag "' . e($data['tag']) . '" updated.');
Session::flash('success', strval(trans('firefly.updated_tag', ['tag' => e($data['tag'])])));
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {

View File

@@ -7,7 +7,6 @@ use Config;
use ExpandedForm;
use FireflyIII\Events\TransactionJournalStored;
use FireflyIII\Events\TransactionJournalUpdated;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Requests\JournalFormRequest;
use FireflyIII\Models\PiggyBank;
@@ -16,7 +15,9 @@ use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface as ARI;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use Illuminate\Support\Collection;
use Input;
use Preferences;
@@ -57,7 +58,7 @@ class TransactionController extends Controller
$uploadSize = min($maxFileSize, $maxPostSize);
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = trans('form.noBudget');
$budgets[0] = trans('firefly.no_budget');
$piggyBanks = Auth::user()->piggyBanks()->orderBy('order', 'ASC')->get();
/** @var PiggyBank $piggy */
foreach ($piggyBanks as $piggy) {
@@ -119,7 +120,8 @@ class TransactionController extends Controller
*/
public function destroy(JournalRepositoryInterface $repository, TransactionJournal $transactionJournal)
{
Session::flash('success', 'Transaction "' . e($transactionJournal->description) . '" destroyed.');
$type = strtolower($transactionJournal->transaction_type_type ?? TransactionJournal::transactionTypeStr($transactionJournal));
Session::flash('success', strval(trans('firefly.deleted_' . $type, ['description' => e($transactionJournal->description)])));
$repository->delete($transactionJournal);
@@ -130,53 +132,45 @@ class TransactionController extends Controller
}
/**
* Shows the view to edit a transaction.
*
* @param ARI $repository
* @param TransactionJournal $journal
*
* @return $this
* @throws FireflyException
* @return mixed
*/
public function edit(ARI $repository, TransactionJournal $journal)
public function edit(TransactionJournal $journal)
{
$maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize'));
$maxPostSize = Steam::phpBytes(ini_get('post_max_size'));
$uploadSize = min($maxFileSize, $maxPostSize);
$what = strtolower(TransactionJournal::transactionTypeStr($journal));
$accounts = ExpandedForm::makeSelectList($repository->getAccounts(['Default account', 'Asset account']));
$budgets = ExpandedForm::makeSelectList(Auth::user()->budgets()->get());
$budgets[0] = trans('form.noBudget');
$piggies = ExpandedForm::makeSelectList(Auth::user()->piggyBanks()->get());
$piggies[0] = trans('form.noPiggybank');
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
$preFilled = [
'date' => $journal->date->format('Y-m-d'),
'interest_date' => $journal->interest_date ? $journal->interest_date->format('Y-m-d') : '',
'book_date' => $journal->book_date ? $journal->book_date->format('Y-m-d') : '',
'process_date' => $journal->process_date ? $journal->process_date->format('Y-m-d') : '',
'category' => '',
'budget_id' => 0,
'piggy_bank_id' => 0,
'tags' => join(',', $journal->tags->pluck('tag')->toArray()),
/** @var ARI $accountRepository */
$accountRepository = app('FireflyIII\Repositories\Account\AccountRepositoryInterface');
/** @var BudgetRepositoryInterface $budgetRepository */
$budgetRepository = app('FireflyIII\Repositories\Budget\BudgetRepositoryInterface');
/** @var PiggyBankRepositoryInterface $piggyRepository */
$piggyRepository = app('FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface');
$accountList = ExpandedForm::makeSelectList($accountRepository->getAccounts(['Default account', 'Asset account']));
$budgetList = ExpandedForm::makeSelectList($budgetRepository->getActiveBudgets());
$piggyBankList = ExpandedForm::makeSelectList($piggyRepository->getPiggyBanks());
$budgetList[0] = trans('firefly.no_budget');
$piggyBankList[0] = trans('form.noPiggybank');
$maxFileSize = Steam::phpBytes(ini_get('upload_max_filesize'));
$maxPostSize = Steam::phpBytes(ini_get('post_max_size'));
$uploadSize = min($maxFileSize, $maxPostSize);
$what = strtolower(TransactionJournal::transactionTypeStr($journal));
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
$preFilled = [
'date' => TransactionJournal::dateAsString($journal),
'interest_date' => TransactionJournal::dateAsString($journal, 'interest_date'),
'book_date' => TransactionJournal::dateAsString($journal, 'book_date'),
'process_date' => TransactionJournal::dateAsString($journal, 'process_date'),
'category' => TransactionJournal::categoryAsString($journal),
'budget_id' => TransactionJournal::budgetId($journal),
'piggy_bank_id' => TransactionJournal::piggyBankId($journal),
'tags' => join(',', $journal->tags->pluck('tag')->toArray()),
'account_from_id' => TransactionJournal::sourceAccount($journal)->id,
'account_to_id' => TransactionJournal::destinationAccount($journal)->id,
'amount' => TransactionJournal::amountPositive($journal),
];
$category = $journal->categories()->first();
if (!is_null($category)) {
$preFilled['category'] = $category->name;
}
$budget = $journal->budgets()->first();
if (!is_null($budget)) {
$preFilled['budget_id'] = $budget->id;
}
if ($journal->piggyBankEvents()->count() > 0) {
$preFilled['piggy_bank_id'] = $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id;
}
$preFilled['amount'] = TransactionJournal::amountPositive($journal);
if ($journal->isWithdrawal()) {
$preFilled['account_id'] = TransactionJournal::sourceAccount($journal)->id;
if (TransactionJournal::destinationAccountTypeStr($journal) != 'Cash account') {
@@ -189,8 +183,6 @@ class TransactionController extends Controller
}
}
$preFilled['account_from_id'] = TransactionJournal::sourceAccount($journal)->id;
$preFilled['account_to_id'] = TransactionJournal::destinationAccount($journal)->id;
Session::flash('preFilled', $preFilled);
Session::flash('gaEventCategory', 'transactions');
@@ -203,7 +195,9 @@ class TransactionController extends Controller
Session::forget('transactions.edit.fromUpdate');
return view('transactions.edit', compact('journal', 'uploadSize', 'accounts', 'what', 'budgets', 'piggies', 'subTitle'))->with('data', $preFilled);
return view('transactions.edit', compact('journal', 'uploadSize', 'accountList', 'what', 'budgetList', 'piggyBankList', 'subTitle'))->with(
'data', $preFilled
);
}
/**
@@ -315,7 +309,7 @@ class TransactionController extends Controller
event(new TransactionJournalStored($journal, intval($request->get('piggy_bank_id'))));
Session::flash('success', 'New transaction "' . $journal->description . '" stored!');
Session::flash('success', strval(trans('firefly.stored_journal', ['description' => e($journal->description)])));
Preferences::mark();
if (intval(Input::get('create_another')) === 1) {
@@ -360,7 +354,8 @@ class TransactionController extends Controller
event(new TransactionJournalUpdated($journal));
// update, get events by date and sort DESC
Session::flash('success', 'Transaction "' . e($journalData['description']) . '" updated.');
$type = strtolower($journal->transaction_type_type ?? TransactionJournal::transactionTypeStr($journal));
Session::flash('success', strval(trans('firefly.updated_' . $type, ['description' => e($journalData['description'])])));
Preferences::mark();
if (intval(Input::get('return_to_edit')) === 1) {

View File

@@ -7,6 +7,8 @@ use FireflyIII\Http\Middleware\Authenticate;
use FireflyIII\Http\Middleware\AuthenticateTwoFactor;
use FireflyIII\Http\Middleware\Binder;
use FireflyIII\Http\Middleware\EncryptCookies;
use FireflyIII\Http\Middleware\IsConfirmed;
use FireflyIII\Http\Middleware\IsNotConfirmed;
use FireflyIII\Http\Middleware\Range;
use FireflyIII\Http\Middleware\RedirectIfAuthenticated;
use FireflyIII\Http\Middleware\RedirectIfTwoFactorAuthenticated;
@@ -45,23 +47,30 @@ class Kernel extends HttpKernel
*/
protected $middlewareGroups
= [
'web' => [
// does not check login
// does not check 2fa
// does not check activation
'web' => [
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
],
'web-auth' => [
// MUST NOT be logged in. Does not care about 2FA or confirmation.
'user-not-logged-in' => [
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
Authenticate::class,
AuthenticateTwoFactor::class,
RedirectIfAuthenticated::class,
],
'web-auth-no-two-factor' => [
// MUST be logged in.
// MUST NOT have 2FA
// don't care about confirmation:
'user-logged-in-no-2fa' => [
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
@@ -70,7 +79,10 @@ class Kernel extends HttpKernel
Authenticate::class,
RedirectIfTwoFactorAuthenticated::class,
],
'web-auth-range' => [
// MUST be logged in
// MUST have 2FA
// MUST NOT have confirmation.
'user-logged-in-2fa-no-activation' => [
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
@@ -78,6 +90,34 @@ class Kernel extends HttpKernel
VerifyCsrfToken::class,
Authenticate::class,
AuthenticateTwoFactor::class,
IsNotConfirmed::class,
],
// MUST be logged in
// don't care about 2fa
// don't care about confirmation.
'user-simple-auth' => [
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
Authenticate::class,
],
// MUST be logged in
// MUST have 2fa
// MUST be confirmed.
// (this group includes the other Firefly middleware)
'user-full-auth' => [
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
Authenticate::class,
AuthenticateTwoFactor::class,
IsConfirmed::class,
Range::class,
Binder::class,
],

View File

@@ -52,10 +52,10 @@ class AuthenticateTwoFactor
return redirect()->guest('login');
}
}
$twoFactorAuthEnabled = Preferences::get('twoFactorAuthEnabled', false)->data;
$hasTwoFactorAuthSecret = !is_null(Preferences::get('twoFactorAuthSecret'));
$isTwoFactorAuthenticated = Session::get('twofactor-authenticated');
if ($twoFactorAuthEnabled && $hasTwoFactorAuthSecret && !$isTwoFactorAuthenticated) {
$is2faEnabled = Preferences::get('twoFactorAuthEnabled', false)->data;
$has2faSecret = !is_null(Preferences::get('twoFactorAuthSecret'));
$is2faAuthed = Session::get('twofactor-authenticated');
if ($is2faEnabled && $has2faSecret && !$is2faAuthed) {
return redirect(route('two-factor'));
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* IsConfirmed.php
* Copyright (C) 2016 Sander Dorigo
*
* 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\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Preferences;
/**
* Class IsConfirmed
*
* @package FireflyIII\Http\Middleware
*/
class IsConfirmed
{
/**
* Handle an incoming request. User account must be confirmed for this routine to let
* the user pass.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
*
* @return mixed
*/
public function handle(Request $request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
} else {
// must the user be confirmed in the first place?
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
// user must be logged in, then continue:
$isConfirmed = Preferences::get('user_confirmed', false)->data;
if ($isConfirmed === false && $confirmAccount === true) {
// user account is not confirmed, redirect to
// confirmation page:
return redirect(route('confirmation_error'));
}
}
return $next($request);
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* IsNotConfirmed.php
* Copyright (C) 2016 Sander Dorigo
*
* 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\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Preferences;
/**
* Class IsNotConfirmed
*
* @package FireflyIII\Http\Middleware
*/
class IsNotConfirmed
{
/**
* Handle an incoming request. User account must be confirmed for this routine to let
* the user pass.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string|null $guard
*
* @return mixed
*/
public function handle(Request $request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->guest()) {
if ($request->ajax()) {
return response('Unauthorized.', 401);
} else {
return redirect()->guest('login');
}
} else {
// must the user be confirmed in the first place?
$confirmAccount = env('MUST_CONFIRM_ACCOUNT', false);
// user must be logged in, then continue:
$isConfirmed = Preferences::get('user_confirmed', false)->data;
if ($isConfirmed || $confirmAccount === false) {
// user account is confirmed, simply send them home.
return redirect(route('home'));
}
}
return $next($request);
}
}

View File

@@ -36,10 +36,10 @@ class RedirectIfTwoFactorAuthenticated
{
if (Auth::guard($guard)->check()) {
$twoFactorAuthEnabled = Preferences::get('twoFactorAuthEnabled', false)->data;
$hasTwoFactorAuthSecret = !is_null(Preferences::get('twoFactorAuthSecret'));
$isTwoFactorAuthenticated = Session::get('twofactor-authenticated');
if ($twoFactorAuthEnabled && $hasTwoFactorAuthSecret && $isTwoFactorAuthenticated) {
$is2faEnabled = Preferences::get('twoFactorAuthEnabled', false)->data;
$has2faSecret = !is_null(Preferences::get('twoFactorAuthSecret'));
$is2faAuthed = Session::get('twofactor-authenticated');
if ($is2faEnabled && $has2faSecret && $is2faAuthed) {
return redirect('/');
}
}

View File

@@ -1,14 +1,16 @@
<?php
declare(strict_types = 1);
// auth routes, i think
/**
* These routes only work when the user is NOT logged in.
*/
Route::group(
['middleware' => 'web'], function () {
['middleware' => 'user-not-logged-in'], function () {
// Authentication Routes...
Route::get('/login', 'Auth\AuthController@showLoginForm');
Route::post('/login', 'Auth\AuthController@login');
Route::get('/logout', 'Auth\AuthController@logout');
// Registration Routes...
Route::get('/register', ['uses' => 'Auth\AuthController@showRegistrationForm', 'as' => 'register']);
@@ -22,25 +24,51 @@ Route::group(
Route::post('/password/reset', 'Auth\PasswordController@reset');
// display error:
Route::get('/error', 'HomeController@displayError');
}
);
/**
* For other routes, it is only relevant that the user is authenticated.
*/
Route::group(
['middleware' => 'web-auth-no-two-factor'], function () {
Route::get('/two-factor', ['uses' => 'Auth\TwoFactorController@index', 'as' => 'two-factor']);
Route::get('/lost-two-factor', ['uses' => 'Auth\TwoFactorController@lostTwoFactor', 'as' => 'lost-two-factor']);
Route::post('/two-factor', ['uses' => 'Auth\TwoFactorController@postIndex', 'as' => 'two-factor-post']);
['middleware' => 'user-simple-auth'], function () {
Route::get('/error', 'HomeController@displayError');
Route::get('/logout', ['uses' => 'Auth\AuthController@logout', 'as' => 'logout']);
Route::get('/flush', ['uses' => 'HomeController@flush']);
}
);
/**
* For the two factor routes, the user must be logged in, but NOT 2FA. Account confirmation does not matter here.
*/
Route::group(
['middleware' => ['web-auth-range']], function () {
['middleware' => 'user-logged-in-no-2fa'], function () {
Route::get('/two-factor', ['uses' => 'Auth\TwoFactorController@index', 'as' => 'two-factor']);
Route::get('/lost-two-factor', ['uses' => 'Auth\TwoFactorController@lostTwoFactor', 'as' => 'lost-two-factor']);
Route::post('/two-factor', ['uses' => 'Auth\TwoFactorController@postIndex', 'as' => 'two-factor-post']);
}
);
/**
* For the confirmation routes, the user must be logged in, also 2FA, but his account must not be confirmed.
*/
Route::group(
['middleware' => 'user-logged-in-2fa-no-activation'], function () {
//
Route::get('/confirm-your-account', ['uses' => 'Auth\ConfirmationController@confirmationError', 'as' => 'confirmation_error']);
Route::get('/resend-confirmation', ['uses' => 'Auth\ConfirmationController@resendConfirmation', 'as' => 'resend_confirmation']);
Route::get('/confirmation/{code}', ['uses' => 'Auth\ConfirmationController@doConfirmation', 'as' => 'do_confirm_account']);
}
);
/**
* For all other routes, the user must be fully authenticated and have an activated account.
*/
Route::group(
['middleware' => ['user-full-auth']], function () {
/**
* Home Controller
@@ -48,7 +76,6 @@ Route::group(
Route::get('/', ['uses' => 'HomeController@index', 'as' => 'index']);
Route::get('/home', ['uses' => 'HomeController@index', 'as' => 'home']);
Route::post('/daterange', ['uses' => 'HomeController@dateRange', 'as' => 'daterange']);
Route::get('/routes', ['uses' => 'HomeController@routes']);
/**
* Account Controller
@@ -282,35 +309,33 @@ Route::group(
// rules GET:
Route::get('/rules/create/{ruleGroup}', ['uses' => 'RuleController@create', 'as' => 'rules.rule.create']);
Route::get('/rules/rules/up/{rule}', ['uses' => 'RuleController@up', 'as' => 'rules.rule.up']);
Route::get('/rules/rules/down/{rule}', ['uses' => 'RuleController@down', 'as' => 'rules.rule.down']);
Route::get('/rules/rules/edit/{rule}', ['uses' => 'RuleController@edit', 'as' => 'rules.rule.edit']);
Route::get('/rules/rules/delete/{rule}', ['uses' => 'RuleController@delete', 'as' => 'rules.rule.delete']);
Route::get('/rules/rules/test_triggers', ['uses' => 'RuleController@testTriggers', 'as' => 'rules.rule.test_triggers']);
Route::get('/rules/up/{rule}', ['uses' => 'RuleController@up', 'as' => 'rules.rule.up']);
Route::get('/rules/down/{rule}', ['uses' => 'RuleController@down', 'as' => 'rules.rule.down']);
Route::get('/rules/edit/{rule}', ['uses' => 'RuleController@edit', 'as' => 'rules.rule.edit']);
Route::get('/rules/delete/{rule}', ['uses' => 'RuleController@delete', 'as' => 'rules.rule.delete']);
Route::get('/rules/test', ['uses' => 'RuleController@testTriggers', 'as' => 'rules.rule.test_triggers']);
// rules POST:
Route::post('/rules/rules/trigger/reorder/{rule}', ['uses' => 'RuleController@reorderRuleTriggers']);
Route::post('/rules/rules/action/reorder/{rule}', ['uses' => 'RuleController@reorderRuleActions']);
Route::post('/rules/trigger/order/{rule}', ['uses' => 'RuleController@reorderRuleTriggers']);
Route::post('/rules/action/order/{rule}', ['uses' => 'RuleController@reorderRuleActions']);
Route::post('/rules/store/{ruleGroup}', ['uses' => 'RuleController@store', 'as' => 'rules.rule.store']);
Route::post('/rules/update/{rule}', ['uses' => 'RuleController@update', 'as' => 'rules.rule.update']);
Route::post('/rules/destroy/{rule}', ['uses' => 'RuleController@destroy', 'as' => 'rules.rule.destroy']);
// rule groups GET
Route::get('/rules/groups/create', ['uses' => 'RuleGroupController@create', 'as' => 'rules.rule-group.create']);
Route::get('/rules/groups/edit/{ruleGroup}', ['uses' => 'RuleGroupController@edit', 'as' => 'rules.rule-group.edit']);
Route::get('/rules/groups/delete/{ruleGroup}', ['uses' => 'RuleGroupController@delete', 'as' => 'rules.rule-group.delete']);
Route::get('/rules/groups/up/{ruleGroup}', ['uses' => 'RuleGroupController@up', 'as' => 'rules.rule-group.up']);
Route::get('/rules/groups/down/{ruleGroup}', ['uses' => 'RuleGroupController@down', 'as' => 'rules.rule-group.down']);
Route::get(
'/rules/groups/select_transactions/{ruleGroup}', ['uses' => 'RuleGroupController@selectTransactions', 'as' => 'rules.rule-group.select_transactions']
);
Route::get('/rule-groups/create', ['uses' => 'RuleGroupController@create', 'as' => 'rules.rule-group.create']);
Route::get('/rule-groups/edit/{ruleGroup}', ['uses' => 'RuleGroupController@edit', 'as' => 'rules.rule-group.edit']);
Route::get('/rule-groups/delete/{ruleGroup}', ['uses' => 'RuleGroupController@delete', 'as' => 'rules.rule-group.delete']);
Route::get('/rule-groups/up/{ruleGroup}', ['uses' => 'RuleGroupController@up', 'as' => 'rules.rule-group.up']);
Route::get('/rule-groups/down/{ruleGroup}', ['uses' => 'RuleGroupController@down', 'as' => 'rules.rule-group.down']);
Route::get('/rule-groups/select/{ruleGroup}', ['uses' => 'RuleGroupController@selectTransactions', 'as' => 'rules.rule-group.select_transactions']);
// rule groups POST
Route::post('/rules/groups/store', ['uses' => 'RuleGroupController@store', 'as' => 'rules.rule-group.store']);
Route::post('/rules/groups/update/{ruleGroup}', ['uses' => 'RuleGroupController@update', 'as' => 'rules.rule-group.update']);
Route::post('/rules/groups/destroy/{ruleGroup}', ['uses' => 'RuleGroupController@destroy', 'as' => 'rules.rule-group.destroy']);
Route::post('/rules/groups/execute/{ruleGroup}', ['uses' => 'RuleGroupController@execute', 'as' => 'rules.rule-group.execute']);
Route::post('/rule-groups/store', ['uses' => 'RuleGroupController@store', 'as' => 'rules.rule-group.store']);
Route::post('/rule-groups/update/{ruleGroup}', ['uses' => 'RuleGroupController@update', 'as' => 'rules.rule-group.update']);
Route::post('/rule-groups/destroy/{ruleGroup}', ['uses' => 'RuleGroupController@destroy', 'as' => 'rules.rule-group.destroy']);
Route::post('/rule-groups/execute/{ruleGroup}', ['uses' => 'RuleGroupController@execute', 'as' => 'rules.rule-group.execute']);
/**
* Search Controller
@@ -353,12 +378,6 @@ Route::group(
Route::post('/transaction/destroy/{tj}', ['uses' => 'TransactionController@destroy', 'as' => 'transactions.destroy']);
Route::post('/transaction/reorder', ['uses' => 'TransactionController@reorder', 'as' => 'transactions.reorder']);
/**
* Auth\Auth Controller
*/
Route::get('/logout', ['uses' => 'Auth\AuthController@logout', 'as' => 'logout']);
}
);

View File

@@ -27,6 +27,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property-read \FireflyIII\User $user
* @property \Carbon\Carbon $nextExpectedMatch
* @property \Carbon\Carbon $lastFoundMatch
* @property bool $paidInPeriod
* @property string $lastPaidAmount
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereId($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\FireflyIII\Models\Bill whereUpdatedAt($value)
@@ -47,11 +49,26 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class Bill extends Model
{
protected $fillable
= ['name', 'match', 'amount_min', 'match_encrypted', 'name_encrypted', 'user_id', 'amount_max', 'date', 'repeat_freq', 'skip', 'automatch', 'active',];
protected $hidden = ['amount_min_encrypted', 'amount_max_encrypted', 'name_encrypted', 'match_encrypted'];
protected $dates = ['created_at', 'updated_at', 'date'];
protected $fillable
= ['name', 'match', 'amount_min', 'match_encrypted', 'name_encrypted', 'user_id', 'amount_max', 'date', 'repeat_freq', 'skip',
'automatch', 'active',];
protected $hidden = ['amount_min_encrypted', 'amount_max_encrypted', 'name_encrypted', 'match_encrypted'];
/**
* @param Bill $value
*
* @return Bill
*/
public static function routeBinder(Bill $value)
{
if (Auth::check()) {
if ($value->user_id == Auth::user()->id) {
return $value;
}
}
throw new NotFoundHttpException;
}
/**
* @param $value
@@ -134,20 +151,4 @@ class Bill extends Model
}
/**
* @param Bill $value
*
* @return Bill
*/
public static function routeBinder(Bill $value)
{
if (Auth::check()) {
if ($value->user_id == Auth::user()->id) {
return $value;
}
}
throw new NotFoundHttpException;
}
}

View File

@@ -44,6 +44,14 @@ class EventServiceProvider extends ServiceProvider
'Illuminate\Auth\Events\Logout' => [
'FireflyIII\Handlers\Events\UserEventListener@onUserLogout',
],
'FireflyIII\Events\UserRegistration' => [
'FireflyIII\Handlers\Events\SendRegistrationMail',
'FireflyIII\Handlers\Events\AttachUserRole',
'FireflyIII\Handlers\Events\UserConfirmation@sendConfirmation',
],
'FireflyIII\Events\ResendConfirmation' => [
'FireflyIII\Handlers\Events\UserConfirmation@resendConfirmation',
],
];
/**

View File

@@ -2,7 +2,6 @@
namespace FireflyIII\Repositories\Account;
use Auth;
use Carbon\Carbon;
use Config;
use DB;
@@ -14,6 +13,7 @@ use FireflyIII\Models\Preference;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
@@ -31,6 +31,19 @@ use Steam;
class AccountRepository implements AccountRepositoryInterface
{
/** @var User */
private $user;
/**
* AttachmentRepository constructor.
*
* @param User $user
*/
public function __construct(User $user)
{
$this->user = $user;
}
/**
* @param array $types
*
@@ -38,7 +51,7 @@ class AccountRepository implements AccountRepositoryInterface
*/
public function countAccounts(array $types): int
{
$count = Auth::user()->accounts()->accountTypeIn($types)->count();
$count = $this->user->accounts()->accountTypeIn($types)->count();
return $count;
}
@@ -70,7 +83,7 @@ class AccountRepository implements AccountRepositoryInterface
*/
public function find(int $accountId): Account
{
return Auth::user()->accounts()->findOrNew($accountId);
return $this->user->accounts()->findOrNew($accountId);
}
/**
@@ -93,7 +106,7 @@ class AccountRepository implements AccountRepositoryInterface
public function getAccounts(array $types): Collection
{
/** @var Collection $result */
$result = Auth::user()->accounts()->with(
$result = $this->user->accounts()->with(
['accountmeta' => function (HasMany $query) {
$query->where('name', 'accountRole');
}]
@@ -121,22 +134,22 @@ class AccountRepository implements AccountRepositoryInterface
*/
public function getCreditCards(Carbon $date): Collection
{
$set = Auth::user()->accounts()
->hasMetaValue('accountRole', 'ccAsset')
->hasMetaValue('ccType', 'monthlyFull')
->leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->whereNull('transactions.deleted_at')
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))
->groupBy('accounts.id')
->get(
[
'accounts.*',
'ccType.data as ccType',
'accountRole.data as accountRole',
DB::Raw('SUM(`transactions`.`amount`) AS `balance`'),
]
);
$set = $this->user->accounts()
->hasMetaValue('accountRole', 'ccAsset')
->hasMetaValue('ccType', 'monthlyFull')
->leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->whereNull('transactions.deleted_at')
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))
->groupBy('accounts.id')
->get(
[
'accounts.*',
'ccType.data as ccType',
'accountRole.data as accountRole',
DB::Raw('SUM(`transactions`.`amount`) AS `balance`'),
]
);
return $set;
}
@@ -164,7 +177,7 @@ class AccountRepository implements AccountRepositoryInterface
*/
public function getFrontpageAccounts(Preference $preference): Collection
{
$query = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account']);
$query = $this->user->accounts()->accountTypeIn(['Default account', 'Asset account']);
if (count($preference->data) > 0) {
$query->whereIn('accounts.id', $preference->data);
@@ -188,20 +201,20 @@ class AccountRepository implements AccountRepositoryInterface
*/
public function getFrontpageTransactions(Account $account, Carbon $start, Carbon $end): Collection
{
$set = Auth::user()
->transactionjournals()
->with(['transactions'])
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $account->id)
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transaction_journals.transaction_currency_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->before($end)
->after($start)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->take(10)
->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']);
$set = $this->user
->transactionjournals()
->with(['transactions'])
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')->where('accounts.id', $account->id)
->leftJoin('transaction_currencies', 'transaction_currencies.id', '=', 'transaction_journals.transaction_currency_id')
->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->before($end)
->after($start)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC')
->take(10)
->get(['transaction_journals.*', 'transaction_currencies.symbol', 'transaction_types.type']);
return $set;
}
@@ -215,17 +228,17 @@ class AccountRepository implements AccountRepositoryInterface
public function getJournals(Account $account, $page): LengthAwarePaginator
{
$offset = ($page - 1) * 50;
$query = Auth::user()
->transactionJournals()
->withRelevantData()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.account_id', $account->id)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC');
$query = $this->user
->transactionJournals()
->expanded()
->leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->where('transactions.account_id', $account->id)
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transaction_journals.order', 'ASC')
->orderBy('transaction_journals.id', 'DESC');
$count = $query->count();
$set = $query->take(50)->offset($offset)->get(['transaction_journals.*']);
$set = $query->take(50)->offset($offset)->get(TransactionJournal::QUERYFIELDS);
$paginator = new LengthAwarePaginator($set, $count, 50, $page);
return $paginator;
@@ -248,7 +261,7 @@ class AccountRepository implements AccountRepositoryInterface
$ids = array_unique($ids);
if (count($ids) > 0) {
$accounts = Auth::user()->accounts()->whereIn('id', $ids)->where('accounts.active', 1)->get();
$accounts = $this->user->accounts()->whereIn('id', $ids)->where('accounts.active', 1)->get();
}
bcscale(2);
@@ -282,12 +295,12 @@ class AccountRepository implements AccountRepositoryInterface
*/
public function getSavingsAccounts(): Collection
{
$accounts = Auth::user()->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
->where('account_meta.name', 'accountRole')
->where('accounts.active', 1)
->where('account_meta.data', '"savingAsset"')
->get(['accounts.*']);
$accounts = $this->user->accounts()->accountTypeIn(['Default account', 'Asset account'])->orderBy('accounts.name', 'ASC')
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
->where('account_meta.name', 'accountRole')
->where('accounts.active', 1)
->where('account_meta.data', '"savingAsset"')
->get(['accounts.*']);
$start = clone Session::get('start', new Carbon);
$end = clone Session::get('end', new Carbon);
@@ -412,7 +425,7 @@ class AccountRepository implements AccountRepositoryInterface
*/
public function sumOfEverything(): string
{
return strval(Auth::user()->transactions()->sum('amount'));
return strval($this->user->transactions()->sum('amount'));
}
/**

View File

@@ -464,6 +464,10 @@ class BillRepository implements BillRepositoryInterface
$matches = explode(',', $bill->match);
$description = strtolower($journal->description) . ' ' . strtolower(TransactionJournal::destinationAccount($journal)->name);
// new: add source to word match:
$description .= ' ' . strtolower(TransactionJournal::sourceAccount($journal)->name);
$wordMatch = $this->doWordMatch($matches, $description);
$amountMatch = $this->doAmountMatch(TransactionJournal::amountPositive($journal), $bill->amount_min, $bill->amount_max);

View File

@@ -31,6 +31,7 @@ class UserRepository implements UserRepositoryInterface
{
$admin = Role::where('name', 'owner')->first();
$user->attachRole($admin);
$user->save();
return true;
}

View File

@@ -47,14 +47,17 @@ class Amount
$result = $formatter->formatCurrency($float, $format->code);
if ($coloured === true) {
if ($amount == 0) {
return '<span style="color:#999">' . $result . '</span>';
}
if ($amount > 0) {
return '<span class="text-success">' . $result . '</span>';
return '<span class="text-success" title="' . e($float) . '">' . $result . '</span>';
} else {
if ($amount < 0) {
return '<span class="text-danger" title="' . e($float) . '">' . $result . '</span>';
}
}
return '<span class="text-danger">' . $result . '</span>';
return '<span style="color:#999" title="' . e($float) . '">' . $result . '</span>';
}
@@ -70,16 +73,13 @@ class Amount
*/
public function formatJournal(TransactionJournal $journal, bool $coloured = true): string
{
$locale = setlocale(LC_MONETARY, 0);
$float = round($journal->destination_amount, 2);
if ($journal->isWithdrawal()) {
$float = round($journal->source_amount, 2);
}
$locale = setlocale(LC_MONETARY, 0);
$float = round(TransactionJournal::amount($journal), 2);
$formatter = new NumberFormatter($locale, NumberFormatter::CURRENCY);
$currencyCode = $journal->transaction_currency_code ?? $journal->transactionCurrency->code;
$result = $formatter->formatCurrency($float, $currencyCode);
if ($coloured === true && $float == 0) {
if ($coloured === true && $float === 0.00) {
return '<span style="color:#999">' . $result . '</span>'; // always grey.
}
if (!$coloured) {

View File

@@ -10,6 +10,7 @@
namespace FireflyIII\Support\Models;
use Carbon\Carbon;
use FireflyIII\Models\Account;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
@@ -79,6 +80,56 @@ class TransactionJournalSupport extends Model
return $amount;
}
/**
* @param TransactionJournal $journal
*
* @return int
*/
public static function budgetId(TransactionJournal $journal): int
{
$budget = $journal->budgets()->first();
if (!is_null($budget)) {
return $budget->id;
}
return 0;
}
/**
* @param TransactionJournal $journal
*
* @return string
*/
public static function categoryAsString(TransactionJournal $journal): string
{
$category = $journal->categories()->first();
if (!is_null($category)) {
return $category->name;
}
return '';
}
/**
* @param TransactionJournal $journal
* @param string $dateField
*
* @return string
*/
public static function dateAsString(TransactionJournal $journal, string $dateField = ''): string
{
if ($dateField === '') {
return $journal->date->format('Y-m-d');
}
if (!is_null($journal->$dateField) && $journal->$dateField instanceof Carbon) {
return $journal->$dateField->format('Y-m-d');
}
return '';
}
/**
* @param TransactionJournal $journal
*
@@ -147,6 +198,20 @@ class TransactionJournalSupport extends Model
return false;
}
/**
* @param TransactionJournal $journal
*
* @return int
*/
public static function piggyBankId(TransactionJournal $journal): int
{
if ($journal->piggyBankEvents()->count() > 0) {
return $journal->piggyBankEvents()->orderBy('date', 'DESC')->first()->piggy_bank_id;
}
return 0;
}
/**
* @param TransactionJournal $journal
*

View File

@@ -6,6 +6,7 @@ namespace FireflyIII\Support;
use Auth;
use Cache;
use FireflyIII\Models\Preference;
use FireflyIII\User;
/**
* Class Preferences
@@ -91,16 +92,34 @@ class Preferences
*/
public function set($name, $value)
{
$fullName = 'preference' . Auth::user()->id . $name;
$user = Auth::user();
if (is_null($user)) {
return $value;
}
return $this->setForUser(Auth::user(), $name, $value);
}
/**
* @param \FireflyIII\User $user
* @param $name
* @param string $value
*
* @return Preference
*/
public function setForUser(User $user, $name, $value)
{
$fullName = 'preference' . $user->id . $name;
Cache::forget($fullName);
$pref = Preference::where('user_id', Auth::user()->id)->where('name', $name)->first(['id', 'name', 'data_encrypted']);
if ($pref) {
$pref = Preference::where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data_encrypted']);
if (!is_null($pref)) {
$pref->data = $value;
} else {
$pref = new Preference;
$pref->name = $name;
$pref->data = $value;
$pref->user()->associate(Auth::user());
$pref->user()->associate($user);
}
$pref->save();

View File

@@ -16,6 +16,7 @@ use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Rules\Triggers\TriggerInterface;
use FireflyIII\User;
use Google2FA;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Validation\Validator;
use Log;
@@ -53,13 +54,14 @@ class FireflyValidator extends Validator
*
* @return bool
*/
public function validate2faCode($attribute, $value, $parameters): bool
public function validate2faCode($attribute, $value): bool
{
if (!is_string($value) || is_null($value) || strlen($value) <> 6) {
return false;
}
$secret = Session::get('two-factor-secret');
$secret = Session::get('two-factor-secret');
/** @var Google2FA $google2fa */
$google2fa = app('PragmaRX\Google2FA\Google2FA');
return $google2fa->verifyKey($secret, $value);

View File

@@ -1,13 +1,15 @@
<?php
return [
'chart' => 'chartjs',
'version' => '3.8.0',
'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'],
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'csv_import_enabled' => true,
'maxUploadSize' => 5242880,
'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'],
'chart' => 'chartjs',
'version' => '3.8.1',
'index_periods' => ['1D', '1W', '1M', '3M', '6M', '1Y', 'custom'],
'budget_periods' => ['daily', 'weekly', 'monthly', 'quarterly', 'half-year', 'yearly'],
'csv_import_enabled' => true,
'maxUploadSize' => 5242880,
'allowedMimes' => ['image/png', 'image/jpeg', 'application/pdf'],
'resend_confirmation' => 3600,
'confirmation_age' => 14400, // four hours
'export_formats' => [
'csv' => 'FireflyIII\Export\Exporter\CsvExporter',
@@ -219,11 +221,11 @@ return [
'append_description',
'prepend_description',
],
'test-triggers' => [
'test-triggers' => [
// The maximum number of transactions shown when testing a list of triggers
'limit' => 10,
// The maximum number of transactions to analyse, when testing a list of triggers
'range' => 200
]
'range' => 200,
],
];

View File

@@ -122,7 +122,7 @@ return [
|
*/
'path' => '/',
'path' => env('COOKIE_PATH', '/'),
/*
|--------------------------------------------------------------------------
@@ -135,7 +135,7 @@ return [
|
*/
'domain' => null,
'domain' => env('COOKIE_DOMAIN', null),
/*
|--------------------------------------------------------------------------
@@ -148,6 +148,6 @@ return [
|
*/
'secure' => false,
'secure' => env('COOKIE_SECURE', false),
];

View File

@@ -23,5 +23,6 @@ return [
'3.7.2.3' => 'Because of the upgrade to Laravel 5.2, several manual changes must be made to your Firefly III installation. ' .
'Please follow the instructions on the following page: https://github.com/JC5/firefly-iii/wiki/Upgrade-to-3.7.0',
'3.8.0' => 'This version of Firefly III requires PHP 7.0.',
'3.8.1' => 'This version of Firefly III requires PHP 7.0.',
],
];

View File

@@ -38,5 +38,6 @@
/* cursors */
.rule-triggers {cursor:move;}
.rule-actions {cursor:move;}
.firefly-info-button {cursor:pointer;}
#testTriggerModal .modal-body { max-height: 500px; overflow-y: scroll; }

View File

@@ -91,7 +91,7 @@ function testRuleTriggers() {
var triggerData = $( ".rule-trigger-tbody" ).find( "input[type=text], input[type=checkbox], select" ).serializeArray();
// Find a list of existing transactions that match these triggers
$.get('rules/rules/test_triggers', triggerData).done(function (data) {
$.get('rules/test', triggerData).done(function (data) {
var modal = $( "#testTriggerModal" );
var numTriggers = $( ".rule-trigger-body > tr" ).length;

View File

@@ -62,6 +62,21 @@ return [
'two_factor_lost_intro' => 'Unfortunately, this is not something you can reset from the web interface. You have two choices.',
'two_factor_lost_fix_self' => 'If you run your own instance of Firefly III, check the logs in <code>storage/logs</code> for instructions.',
'two_factor_lost_fix_owner' => 'Otherwise, email the site owner, <a href="mailto::site_owner">:site_owner</a> and ask them to reset your two factor authentication.',
'warning_much_data' => ':days days of data may take a while to load.',
'registered' => 'You have registered successfully!',
// account confirmation:
'confirm_account_header' => 'Please confirm your account',
'confirm_account_intro' => 'An email has been sent to the address you used during your registration. Please check it out for further instructions. If you did not get this message, you can have Firefly send it again.',
'confirm_account_resend_email' => 'Send me the confirmation message I need to activate my account.',
'account_is_confirmed' => 'Your account has been confirmed!',
'invalid_activation_code' => 'It seems the code you are using is not valid, or has expired.',
'confirm_account_is_resent_header' => 'The confirmation has been resent',
'confirm_account_is_resent_text' => 'The confirmation message has been resent. If you still did not receive the confirmation message, please contact the site owner at <a href="mailto::owner">:owner</a> or check the log files to see what went wrong.',
'confirm_account_is_resent_go_home' => 'Go to the index page of Firefly',
'confirm_account_not_resent_header' => 'Something went wrong :(',
'confirm_account_not_resent_intro' => 'The confirmation message has been not resent. If you still did not receive the confirmation message, please contact the site owner at <a href="mailto::owner">:owner</a> instead. Possibly, you have tried to resend the activation message too often. You can have Firefly III try to resend the confirmation message every hour.',
'confirm_account_not_resent_go_home' => 'Go to the index page of Firefly',
// export data:
'import_and_export' => 'Import and export',
@@ -247,6 +262,7 @@ return [
'pref_two_factor_auth_remove_code' => 'Remove verification code',
'pref_two_factor_auth_remove_will_disable' => '(this will also disable two-factor authentication)',
'pref_save_settings' => 'Save settings',
'saved_preferences' => 'Preferences saved!',
// profile:
'change_your_password' => 'Change your password',
@@ -273,6 +289,7 @@ return [
'update_attachment' => 'Update attachment',
'delete_attachment' => 'Delete attachment ":name"',
'attachment_deleted' => 'Deleted attachment ":name"',
'attachment_updated' => 'Updated attachment ":name"',
'upload_max_file_size' => 'Maximum file size: :size',
// tour:
@@ -374,6 +391,11 @@ return [
'csv_import_account_help' => 'If your CSV file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the CSV belong to.',
'csv_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
'csv_date_parse_error' => 'Could not parse a valid date from ":value", using the format ":format". Are you sure your CSV is correct?',
'could_not_recover' => 'Could not continue from the previous step. Your progress has been lost :(. The log files will tell you what happened.',
'must_select_roles' => 'You must select some roles for your file content, or the process cannot continue.',
'invalid_mapping' => 'You have submitted an invalid mapping. The process cannot continue.',
'no_file_uploaded' => 'It seems you did not upload a file.',
// create new stuff:
'create_new_withdrawal' => 'Create new withdrawal',
@@ -406,6 +428,8 @@ return [
'to_get_started' => 'To get started with Firefly, please enter your current bank\'s name, and the balance of your checking account:',
'savings_balance_text' => 'If you have a savings account, please enter the current balance of your savings account:',
'cc_balance_text' => 'If you have a credit card, please enter your credit card\'s limit.',
'stored_new_account_new_user' => 'Yay! Your new account has been stored.',
'stored_new_accounts_new_user' => 'Yay! Your new accounts have been stored.',
// forms:
'mandatoryFields' => 'Mandatory fields',
@@ -415,7 +439,8 @@ return [
// budgets:
'create_new_budget' => 'Create a new budget',
'store_new_budget' => ' Store new budget',
'store_new_budget' => 'Store new budget',
'stored_new_budget' => 'Stored new budget ":name"',
'availableIn' => 'Available in :date',
'transactionsWithoutBudget' => 'Expenses without budget',
'transactionsWithoutBudgetDate' => 'Expenses without budget in :date',
@@ -424,15 +449,23 @@ return [
'without_budget_between' => 'Transactions without a budget between :start and :end',
'budget_in_month' => ':name in :month',
'delete_budget' => 'Delete budget ":name"',
'deleted_budget' => 'Deleted budget ":name"',
'edit_budget' => 'Edit budget ":name"',
'updated_budget' => 'Updated budget ":name"',
'update_amount' => 'Update amount',
'update_budget' => 'Update budget',
// bills:
'delete_bill' => 'Delete bill ":name"',
'deleted_bill' => 'Deleted bill ":name"',
'edit_bill' => 'Edit bill ":name"',
'update_bill' => 'Update bill',
'updated_bill' => 'Updated bill ":name"',
'store_new_bill' => 'Store new bill',
'stored_new_bill' => 'Stored new bill ":name"',
'cannot_scan_inactive_bill' => 'Inactive bills cannot be scanned.',
'rescanned_bill' => 'Rescanned everything.',
'bill_date_little_relevance' => 'The only part of this date used by Firefly is the day. It is only useful when your bill arrives at exactly the same date every month. If the payment date of your bills varies, simply use the first of the month.',
// accounts:
'details_for_asset' => 'Details for asset account ":name"',
@@ -460,32 +493,46 @@ return [
'asset_accounts' => 'Asset accounts',
'expense_accounts' => 'Expense accounts',
'revenue_accounts' => 'Revenue accounts',
'cash_accounts' => 'Cash accounts',
'Cash account' => 'Cash account',
'accountExtraHelp_asset' => '',
'accountExtraHelp_expense' => '',
'accountExtraHelp_revenue' => '',
'account_type' => 'Account type',
'save_transactions_by_moving' => 'Save these transaction(s) by moving them to another account:',
'stored_new_account' => 'New account ":name" stored!',
'updated_account' => 'Updated account ":name"',
// categories:
'new_category' => 'New category',
'create_new_category' => 'Create a new category',
'without_category' => 'Without a category',
'update_category' => 'Wijzig categorie',
'update_category' => 'Update category',
'updated_category' => 'Updated category ":name"',
'categories' => 'Categories',
'edit_category' => 'Edit category ":name"',
'no_category' => '(no category)',
'category' => 'Category',
'delete_category' => 'Delete category ":name"',
'deleted_category' => 'Deleted category ":name"',
'store_category' => 'Store new category',
'stored_category' => 'Stored new category ":name"',
'without_category_between' => 'Without category between :start and :end',
// transactions:
'update_withdrawal' => 'Update withdrawal',
'update_deposit' => 'Update deposit',
'update_transfer' => 'Update transfer',
'updated_withdrawal' => 'Updated withdrawal ":description"',
'updated_deposit' => 'Updated deposit ":description"',
'updated_transfer' => 'Updated transfer ":description"',
'delete_withdrawal' => 'Delete withdrawal ":description"',
'delete_deposit' => 'Delete deposit ":description"',
'delete_transfer' => 'Delete transfer ":description"',
'deleted_withdrawal' => 'Successfully deleted withdrawal ":description"',
'deleted_deposit' => 'Successfully deleted deposit ":description"',
'deleted_transfer' => 'Successfully deleted transfer ":description"',
'stored_journal' => 'Successfully created new transaction ":description"',
// new user:
'welcome' => 'Welcome to Firefly!',
@@ -619,7 +666,7 @@ return [
'earned' => 'Earned',
'overspent' => 'Overspent',
'left' => 'Left',
'noBudget' => '(no budget)',
'no_budget' => '(no budget)',
'maxAmount' => 'Maximum amount',
'minAmount' => 'Minumum amount',
'billEntry' => 'Current bill entry',
@@ -640,6 +687,7 @@ return [
'piggy_bank' => 'Piggy bank',
'new_piggy_bank' => 'Create new piggy bank',
'store_piggy_bank' => 'Store new piggy bank',
'stored_piggy_bank' => 'Store new piggy bank ":name"',
'account_status' => 'Account status',
'left_for_piggy_banks' => 'Left for piggy banks',
'sum_of_piggy_banks' => 'Sum of piggy banks',
@@ -653,6 +701,7 @@ return [
'max_amount_remove' => 'The maximum amount you can remove is',
'update_piggy_button' => 'Update piggy bank',
'update_piggy_title' => 'Update piggy bank ":name"',
'updated_piggy_bank' => 'Updated piggy bank ":name"',
'details' => 'Details',
'events' => 'Events',
'target_amount' => 'Target amount',
@@ -665,14 +714,22 @@ return [
'add_any_amount_to_piggy' => 'Add money to this piggy bank to reach your target of :amount.',
'add_set_amount_to_piggy' => 'Add :amount to fill this piggy bank on :date',
'delete_piggy_bank' => 'Delete piggy bank ":name"',
'cannot_add_amount_piggy' => 'Could not add :amount to ":name".',
'deleted_piggy_bank' => 'Deleted piggy bank ":name"',
'added_amount_to_piggy' => 'Added :amount to ":name"',
'removed_amount_from_piggy' => 'Removed :amount from ":name"',
'cannot_remove_amount_piggy' => 'Could not remove :amount from ":name".',
// tags
'regular_tag' => 'Just a regular tag.',
'balancing_act' => 'The tag takes at most two transactions; an expense and a transfer. They\'ll balance each other out.',
'advance_payment' => 'The tag accepts one expense and any number of deposits aimed to repay the original expense.',
'delete_tag' => 'Delete tag ":tag"',
'deleted_tag' => 'Deleted tag ":tag"',
'new_tag' => 'Make new tag',
'edit_tag' => 'Edit tag ":tag"',
'updated_tag' => 'Updated tag ":tag"',
'created_tag' => 'Tag ":tag" has been created!',
'no_year' => 'No year set',
'no_month' => 'No month set',
'tag_title_nothing' => 'Default tags',

View File

@@ -74,7 +74,6 @@ return [
'add_new_deposit' => 'Add a new deposit',
'add_new_transfer' => 'Add a new transfer',
'noPiggybank' => '(no piggy bank)',
'noBudget' => '(no budget)',
'title' => 'Title',
'notes' => 'Notes',
'filename' => 'File name',

View File

@@ -19,7 +19,7 @@ return [
'budget-menu-title' => 'Budgets',
'budget-menu-text' => 'Use this page to organise your finances and limit spending.',
'report-menu-title' => 'Reports',
'report-menu-text' => 'Check this out when you want a solid overview of your fiances.',
'report-menu-text' => 'Check this out when you want a solid overview of your finances.',
'transaction-menu-title' => 'Transactions',
'transaction-menu-text' => 'All transactions you\'ve created can be found here.',
'option-menu-title' => 'Options',

View File

@@ -8,34 +8,35 @@
*/
return [
'name' => 'Name',
'role' => 'Role',
'currentBalance' => 'Current balance',
'active' => 'Is active?',
'lastActivity' => 'Last activity',
'balanceDiff' => 'Balance difference between :start and :end',
'matchedOn' => 'Matched on',
'matchesOn' => 'Matched on',
'matchingAmount' => 'Amount',
'lastMatch' => 'Last match',
'expectedMatch' => 'Expected match',
'automatch' => 'Auto match?',
'repeat_freq' => 'Repeats',
'description' => 'Description',
'amount' => 'Amount',
'date' => 'Date',
'interest_date' => 'Interest date',
'book_date' => 'Book date',
'process_date' => 'Processing date',
'from' => 'From',
'to' => 'To',
'budget' => 'Budget',
'category' => 'Category',
'bill' => 'Bill',
'withdrawal' => 'Withdrawal',
'deposit' => 'Deposit',
'transfer' => 'Transfer',
'type' => 'Type',
'completed' => 'Completed',
'iban' => 'IBAN',
'name' => 'Name',
'role' => 'Role',
'currentBalance' => 'Current balance',
'active' => 'Is active?',
'lastActivity' => 'Last activity',
'balanceDiff' => 'Balance difference between :start and :end',
'matchedOn' => 'Matched on',
'matchesOn' => 'Matched on',
'matchingAmount' => 'Amount',
'lastMatch' => 'Last match',
'expectedMatch' => 'Expected match',
'automatch' => 'Auto match?',
'repeat_freq' => 'Repeats',
'description' => 'Description',
'amount' => 'Amount',
'date' => 'Date',
'interest_date' => 'Interest date',
'book_date' => 'Book date',
'process_date' => 'Processing date',
'from' => 'From',
'to' => 'To',
'budget' => 'Budget',
'category' => 'Category',
'bill' => 'Bill',
'withdrawal' => 'Withdrawal',
'deposit' => 'Deposit',
'transfer' => 'Transfer',
'type' => 'Type',
'completed' => 'Completed',
'iban' => 'IBAN',
'paid_current_period' => 'Paid this period',
];

0
resources/lang/fr_FR/breadcrumbs.php Executable file → Normal file
View File

0
resources/lang/fr_FR/config.php Executable file → Normal file
View File

0
resources/lang/fr_FR/firefly.php Executable file → Normal file
View File

0
resources/lang/fr_FR/form.php Executable file → Normal file
View File

0
resources/lang/fr_FR/help.php Executable file → Normal file
View File

0
resources/lang/fr_FR/list.php Executable file → Normal file
View File

0
resources/lang/fr_FR/pagination.php Executable file → Normal file
View File

0
resources/lang/fr_FR/passwords.php Executable file → Normal file
View File

0
resources/lang/fr_FR/validation.php Executable file → Normal file
View File

0
resources/lang/nl_NL/breadcrumbs.php Executable file → Normal file
View File

0
resources/lang/nl_NL/config.php Executable file → Normal file
View File

61
resources/lang/nl_NL/firefly.php Executable file → Normal file
View File

@@ -62,6 +62,21 @@ return [
'two_factor_lost_intro' => 'Dit is helaas niet iets dat je kan resetten vanaf de site. Je hebt twee keuzes.',
'two_factor_lost_fix_self' => 'Als dit jouw installatie van Firefly III is, vind je in de logboeken (<code>storage/logs</code>) instructies.',
'two_factor_lost_fix_owner' => 'Zo niet, stuur dan een e-mail naar <a href="mailto::site_owner">:site_owner</a> en vraag of ze je authenticatie in twee stappen willen resetten.',
'warning_much_data' => 'Het kan even duren voor :days dagen aan gegevens geladen zijn.',
'registered' => 'Je bent geregistreerd!',
// account confirmation:
'confirm_account_header' => 'Bevestig je account',
'confirm_account_intro' => 'TIjdens het registreren heb je een mailtje gehad. Kijk daar in voor instructies. Als je het mailtje niet hebt gehad, kan Firefly je een nieuwe sturen.',
'confirm_account_resend_email' => 'Stuur me het bevestigingsmailtje dat ik nodig heb om mijn account te activeren.',
'account_is_confirmed' => 'Je account is geactiveerd!',
'invalid_activation_code' => 'Het lijkt er op dat de code die je gebruikt niet geldig is (of wellicht verlopen).',
'confirm_account_is_resent_header' => 'De bevestiging is verstuurd',
'confirm_account_is_resent_text' => 'De bevestiging is opnieuw verstuurd. Als je hem nu nog niet krijgt, stuur dan zelf een mailtje naar <a href="mailto::owner">:owner</a> of kijk in de logboeken om te zien wat er is fout gegaan.',
'confirm_account_is_resent_go_home' => 'Ga naar de index van Firefly',
'confirm_account_not_resent_header' => 'Er ging iets fout :(',
'confirm_account_not_resent_intro' => 'Het bevestigingsmailtje is niet verstuurd. Als je het bevestigingsmailtje nog niet hebt gehad, neem dan even contact op met <a href="mailto::owner">:owner</a>.Het kan zijn dat je het bevestigingsmailtje te vaak laat versturen. Je kan dit slechts één keer per uur laten doen.',
'confirm_account_not_resent_go_home' => 'Ga naar de index van Firefly',
// export data:
'import_and_export' => 'Import en export',
@@ -247,6 +262,7 @@ return [
'pref_two_factor_auth_remove_code' => 'Verwijder de verificatiecode',
'pref_two_factor_auth_remove_will_disable' => '(hiermee zet je authenticatie in twee stappen ook uit)',
'pref_save_settings' => 'Instellingen opslaan',
'saved_preferences' => 'Voorkeuren opgeslagen!',
// profile:
'change_your_password' => 'Verander je wachtwoord',
@@ -273,6 +289,7 @@ return [
'update_attachment' => 'Update bijlage',
'delete_attachment' => 'Verwijder bijlage ":name"',
'attachment_deleted' => 'Bijlage ":name" verwijderd',
'attachment_updated' => 'Attachment ":name" geüpdatet',
'upload_max_file_size' => 'Maximale grootte: :size',
// tour:
@@ -374,6 +391,11 @@ return [
'csv_import_account_help' => 'Als jouw CSV bestand geen referenties bevat naar jouw rekening(en), geef dan hier aan om welke rekening het gaat.',
'csv_delimiter_help' => 'Kies het veldscheidingsteken dat in het invoerbestand is gebruikt. Bij twijfel is de komma de veiligste optie.',
'csv_date_parse_error' => 'Firefly kan van ":value" geen datum maken, gegeven het formaat ":format". Weet je zeker dat je CSV goed is?',
'could_not_recover' => 'Helaas, kan niet doorgaan vanaf de vorige stap. Je voortgang is verloren gegaan :(. De logbestanden bevatten meer informatie.',
'must_select_roles' => 'Je moet enkele rollen selecteren voor de kolommen in je bestand, anders kan je niet verder.',
'invalid_mapping' => 'Je hebt verkeerde gegevens ingevoerd. Je kan helaas niet verder.',
'no_file_uploaded' => 'Het lijkt er op dat je niets hebt geüpload.',
// create new stuff:
'create_new_withdrawal' => 'Nieuwe uitgave',
@@ -406,6 +428,8 @@ return [
'to_get_started' => 'Begin met de naam van de bank waar je je betaalrekening hebt, en het saldo van die rekening.',
'savings_balance_text' => 'Voer ook het saldo van je spaarrekening in, als je die hebt.',
'cc_balance_text' => 'Als je een credit card hebt, vul dan hier je credit cardlimiet in.',
'stored_new_account_new_user' => 'Hoera! Je nieuwe account is opgeslagen.',
'stored_new_accounts_new_user' => 'Hoera! Je nieuwe accounts zijn opgeslagen.',
// forms:
'mandatoryFields' => 'Verplichte velden',
@@ -416,6 +440,7 @@ return [
// budgets:
'create_new_budget' => 'Maak een nieuw budget',
'store_new_budget' => 'Sla nieuw budget op',
'stored_new_budget' => 'Nieuw budget ":name" opgeslagen',
'availableIn' => 'Beschikbaar in :date',
'transactionsWithoutBudget' => 'Uitgaven zonder budget',
'transactionsWithoutBudgetDate' => 'Uitgaven zonder budget in :date',
@@ -424,15 +449,23 @@ return [
'without_budget_between' => 'Transacties zonder budget tussen :start en :end',
'budget_in_month' => ':name in :month',
'delete_budget' => 'Verwijder budget ":name"',
'deleted_budget' => 'Budget ":name" verwijderd',
'edit_budget' => 'Wijzig budget ":name"',
'updated_budget' => 'Budget ":name" geüpdatet',
'update_amount' => 'Bedrag bijwerken',
'update_budget' => 'Budget bijwerken',
// bills:
'delete_bill' => 'Verwijder contract ":name"',
'deleted_bill' => 'Contract ":name" verwijderd',
'edit_bill' => 'Wijzig contract ":name"',
'update_bill' => 'Wijzig contract',
'updated_bill' => 'Contract ":name" geüpdatet',
'store_new_bill' => 'Sla nieuw contract op',
'stored_new_bill' => 'Nieuw contract ":name" opgeslagen',
'cannot_scan_inactive_bill' => 'Inactieve contracten kunnen niet worden gescand.',
'rescanned_bill' => 'Alles is opnieuw gescand.',
'bill_date_little_relevance' => 'Firefly gebruikt alleen de dag van dit datumveld. Dit veld heeft alleen zin als je rekening ook echt op die dag van de maand komt. Zo niet, vul dan gewoon de 1e van de maand in.',
// accounts:
'details_for_asset' => 'Overzicht voor betaalrekening ":name"',
@@ -460,32 +493,46 @@ return [
'asset_accounts' => 'Betaalrekeningen',
'expense_accounts' => 'Crediteuren',
'revenue_accounts' => 'Debiteuren',
'cash_accounts' => 'Contant geldrekeningen',
'Cash account' => 'Contant geldrekening',
'accountExtraHelp_asset' => '',
'accountExtraHelp_expense' => '',
'accountExtraHelp_revenue' => '',
'account_type' => 'Rekeningtype',
'save_transactions_by_moving' => 'Bewaar deze transacties door ze aan een andere rekening te koppelen:',
'stored_new_account' => 'Nieuwe rekening ":name" opgeslagen!',
'updated_account' => 'Rekening ":name" geüpdatet',
// categories:
'new_category' => 'Nieuwe categorie',
'create_new_category' => 'Nieuwe categorie',
'without_category' => 'Zonder categorie',
'update_category' => 'Wijzig categorie',
'update_category' => 'Update categorie',
'updated_category' => 'Categorie ":name" geüpdatet',
'categories' => 'Categorieën',
'edit_category' => 'Wijzig categorie ":name"',
'no_category' => '(geen categorie)',
'category' => 'Categorie',
'delete_category' => 'Verwijder categorie ":name"',
'deleted_category' => 'Categorie ":name" verwijderd',
'store_category' => 'Sla nieuwe categorie op',
'stored_category' => 'Nieuwe categorie ":name" opgeslagen',
'without_category_between' => 'Zonder categorie tussen :start en :end',
// transactions:
'update_withdrawal' => 'Wijzig uitgave',
'update_deposit' => 'Wijzig inkomsten',
'update_transfer' => 'Wijzig overschrijving',
'updated_withdrawal' => 'Uitgave ":description" geüpdatet',
'updated_deposit' => 'Inkomsten ":description" geüpdatet',
'updated_transfer' => 'Overschrijving ":description" geüpdatet',
'delete_withdrawal' => 'Verwijder uitgave ":description"',
'delete_deposit' => 'Verwijder inkomsten ":description"',
'delete_transfer' => 'Verwijder overschrijving ":description"',
'deleted_withdrawal' => 'Uitgave ":description" verwijderd',
'deleted_deposit' => 'Inkomsten ":description" verwijderd',
'deleted_transfer' => 'Overschrijving ":description" verwijderd',
'stored_journal' => 'Nieuw transactie ":description" opgeslagen',
// new user:
'welcome' => 'Welkom bij Firefly!',
@@ -619,7 +666,7 @@ return [
'earned' => 'Verdiend',
'overspent' => 'Teveel uitgegeven',
'left' => 'Over',
'noBudget' => '(geen budget)',
'no_budget' => '(geen budget)',
'maxAmount' => 'Maximaal bedrag',
'minAmount' => 'Minimaal bedrag',
'billEntry' => 'Bedrag voor dit contract',
@@ -640,6 +687,7 @@ return [
'piggy_bank' => 'Spaarpotje',
'new_piggy_bank' => 'Nieuw spaarpotje',
'store_piggy_bank' => 'Sla spaarpotje op',
'stored_piggy_bank' => 'Nieuw spaarpotje ":name" opgeslagen',
'account_status' => 'Rekeningoverzicht',
'left_for_piggy_banks' => 'Over voor spaarpotjes',
'sum_of_piggy_banks' => 'Som van spaarpotjes',
@@ -653,6 +701,7 @@ return [
'max_amount_remove' => 'Hooguit te verwijderen',
'update_piggy_button' => 'Wijzig spaarpotje',
'update_piggy_title' => 'Wijzig spaarpotje ":name"',
'updated_piggy_bank' => 'Spaarpotje ":name" geüpdatet',
'details' => 'Details',
'events' => 'Gebeurtenissen',
'target_amount' => 'Doelbedrag',
@@ -665,14 +714,22 @@ return [
'add_any_amount_to_piggy' => 'Stop geld in dit spaarpotje om het doel van :amount te halen.',
'add_set_amount_to_piggy' => 'Stop voor :date :amount in dit spaarpotje om hem op tijd te vullen.',
'delete_piggy_bank' => 'Verwijder spaarpotje ":name"',
'cannot_add_amount_piggy' => 'Kon bedrag :amount niet aan ":name" toevoegen.',
'deleted_piggy_bank' => 'Spaarpotje ":name" verwijderd',
'added_amount_to_piggy' => ':amount aan ":name" toegevoegd',
'removed_amount_from_piggy' => ':amount uit ":name" gehaald',
'cannot_remove_amount_piggy' => 'Kon :amount niet uit ":name" halen.',
// tags
'regular_tag' => 'Een gewone tag.',
'balancing_act' => 'Er kunnen maar twee transacties worden getagged; een uitgaven en inkomsten. Ze balanceren elkaar.',
'advance_payment' => 'Je kan een uitgave taggen en zoveel inkomsten om de uitgave (helemaal) te compenseren.',
'delete_tag' => 'Verwijder tag ":tag"',
'deleted_tag' => 'Tag ":tag" verwijderd',
'new_tag' => 'Maak nieuwe tag',
'edit_tag' => 'Wijzig tag ":tag"',
'updated_tag' => 'Tag ":tag" geüpdatet',
'created_tag' => 'Tag ":tag" opgeslagen!',
'no_year' => 'Zonder jaar',
'no_month' => 'Zonder maand',
'tag_title_nothing' => 'Standaard tags',

1
resources/lang/nl_NL/form.php Executable file → Normal file
View File

@@ -72,7 +72,6 @@ return [
'add_new_deposit' => 'Maak nieuwe inkomsten',
'add_new_transfer' => 'Maak nieuwe overschrijving',
'noPiggybank' => '(geen spaarpotje)',
'noBudget' => '(geen budget)',
'title' => 'Titel',
'notes' => 'Notities',
'filename' => 'Bestandsnaam',

4
resources/lang/nl_NL/help.php Executable file → Normal file
View File

@@ -8,6 +8,8 @@
*/
return [
// tour!
'main-content-title' => 'Welkom bij Firefly III',
'main-content-text' => 'Doe jezelf een lol en volg deze korte tour. Je weet dan precies hoe alles werkt.',
'sidebar-toggle-title' => 'Sidebar om nieuwe dingen te maken',
@@ -17,7 +19,7 @@ return [
'budget-menu-title' => 'Budgetten',
'budget-menu-text' => 'Gebruik deze pagina voor budgetten.',
'report-menu-title' => 'Overzichten',
'report-menu-text' => 'Hier vind je allerlei financiele rapportages.',
'report-menu-text' => 'Bekijk dit als je een goed overzicht van je financiën wil.',
'transaction-menu-title' => 'Transacties',
'transaction-menu-text' => 'Hier vind je al je bijschrijvingen, afschrijvingen en overboekingen.',
'option-menu-title' => 'Opties',

61
resources/lang/nl_NL/list.php Executable file → Normal file
View File

@@ -8,34 +8,35 @@
*/
return [
'name' => 'Naam',
'role' => 'Rol',
'currentBalance' => 'Huidig saldo',
'active' => 'Actief?',
'lastActivity' => 'Laatste activiteit',
'balanceDiff' => 'Saldoverschil tussen :start en :end',
'matchedOn' => 'Wordt herkend',
'matchesOn' => 'Wordt herkend',
'matchingAmount' => 'Bedrag',
'lastMatch' => 'Laatste keer gezien',
'expectedMatch' => 'Wordt verwacht',
'automatch' => 'Automatisch herkennen?',
'repeat_freq' => 'Herhaling',
'description' => 'Omschrijving',
'amount' => 'Bedrag',
'date' => 'Datum',
'interest_date' => 'Rentedatum',
'book_date' => 'Boekdatum',
'process_date' => 'Verwerkingsdatum',
'from' => 'Van',
'to' => 'Naar',
'budget' => 'Budget',
'category' => 'Categorie',
'bill' => 'Contract',
'withdrawal' => 'Uitgave',
'deposit' => 'Inkomsten',
'transfer' => 'Overschrijving',
'type' => 'Type',
'completed' => 'Opgeslagen',
'iban' => 'IBAN',
'name' => 'Naam',
'role' => 'Rol',
'currentBalance' => 'Huidig saldo',
'active' => 'Actief?',
'lastActivity' => 'Laatste activiteit',
'balanceDiff' => 'Saldoverschil tussen :start en :end',
'matchedOn' => 'Wordt herkend',
'matchesOn' => 'Wordt herkend',
'matchingAmount' => 'Bedrag',
'lastMatch' => 'Laatste keer gezien',
'expectedMatch' => 'Wordt verwacht',
'automatch' => 'Automatisch herkennen?',
'repeat_freq' => 'Herhaling',
'description' => 'Omschrijving',
'amount' => 'Bedrag',
'date' => 'Datum',
'interest_date' => 'Rentedatum',
'book_date' => 'Boekdatum',
'process_date' => 'Verwerkingsdatum',
'from' => 'Van',
'to' => 'Naar',
'budget' => 'Budget',
'category' => 'Categorie',
'bill' => 'Contract',
'withdrawal' => 'Uitgave',
'deposit' => 'Inkomsten',
'transfer' => 'Overschrijving',
'type' => 'Type',
'completed' => 'Opgeslagen',
'iban' => 'IBAN',
'paid_current_period' => 'Betaald deze periode',
];

0
resources/lang/nl_NL/pagination.php Executable file → Normal file
View File

0
resources/lang/nl_NL/passwords.php Executable file → Normal file
View File

View File

@@ -1,4 +1,11 @@
<?php
/**
* validation.php
* Copyright (C) 2016 Sander Dorigo
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
return [
'iban' => 'Dit is niet een geldige IBAN.',

0
resources/lang/pt_BR/breadcrumbs.php Executable file → Normal file
View File

0
resources/lang/pt_BR/config.php Executable file → Normal file
View File

0
resources/lang/pt_BR/firefly.php Executable file → Normal file
View File

0
resources/lang/pt_BR/form.php Executable file → Normal file
View File

0
resources/lang/pt_BR/help.php Executable file → Normal file
View File

0
resources/lang/pt_BR/list.php Executable file → Normal file
View File

0
resources/lang/pt_BR/pagination.php Executable file → Normal file
View File

0
resources/lang/pt_BR/passwords.php Executable file → Normal file
View File

0
resources/lang/pt_BR/validation.php Executable file → Normal file
View File

View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex, nofolllow, noarchive, noodp, NoImageIndex, noydir">
<title>Firefly III</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<base href="{{ route('index') }}/">
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" type="text/css" media="all"/>
<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css" type="text/css" media="all"/>
<link href="dist/css/AdminLTE.min.css" rel="stylesheet" type="text/css"/>
<link href="css/firefly.css" rel="stylesheet" type="text/css"/>
<!-- favicons -->
{% include('partials/favicons.twig') %}
</head>
<body class="ff-error-page">
<div class="ff-error-box">
<div class="login-logo">
<a href="{{ route('index') }}"><b>Firefly</b>III</a>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<h3 class="text-info">{{ 'confirm_account_header'|_ }}</h3>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<p>
{{ 'confirm_account_intro'|_ }}
</p>
<p>
<a href="{{ route('resend_confirmation') }}">{{ 'confirm_account_resend_email'|_ }}</a>
</p>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex, nofolllow, noarchive, noodp, NoImageIndex, noydir">
<title>Firefly III</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<base href="{{ route('index') }}/">
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" type="text/css" media="all"/>
<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css" type="text/css" media="all"/>
<link href="dist/css/AdminLTE.min.css" rel="stylesheet" type="text/css"/>
<link href="css/firefly.css" rel="stylesheet" type="text/css"/>
<!-- favicons -->
{% include('partials/favicons.twig') %}
</head>
<body class="ff-error-page">
<div class="ff-error-box">
<div class="login-logo">
<a href="{{ route('index') }}"><b>Firefly</b>III</a>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<h3 class="text-info">{{ 'confirm_account_not_resent_header'|_ }}</h3>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<p>
{{ trans('firefly.confirm_account_not_resent_intro', {owner:owner})|raw }}
</p>
<p>
<a href="{{ route('home') }}">{{ 'confirm_account_not_resent_go_home'|_ }}</a>
</p>
</div>
</div>
</div>
</body>
</html>

View File

@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="robots" content="noindex, nofolllow, noarchive, noodp, NoImageIndex, noydir">
<title>Firefly III</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<base href="{{ route('index') }}/">
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" type="text/css" media="all"/>
<link rel="stylesheet" href="font-awesome/css/font-awesome.min.css" type="text/css" media="all"/>
<link href="dist/css/AdminLTE.min.css" rel="stylesheet" type="text/css"/>
<link href="css/firefly.css" rel="stylesheet" type="text/css"/>
<!-- favicons -->
{% include('partials/favicons.twig') %}
</head>
<body class="ff-error-page">
<div class="ff-error-box">
<div class="login-logo">
<a href="{{ route('index') }}"><b>Firefly</b>III</a>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<h3 class="text-info">{{ 'confirm_account_is_resent_header'|_ }}</h3>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12">
<p>
{{ trans('firefly.confirm_account_is_resent_text', {owner:owner})|raw }}
</p>
<p>
<a href="{{ route('home') }}">{{ 'confirm_account_is_resent_go_home'|_ }}</a>
</p>
</div>
</div>
</div>
</body>
</html>

View File

@@ -50,7 +50,9 @@
{% endif %}
<a href="{{ URL.to('/login') }}">I want to login</a><br>
<a href="{{ URL.to('/password/reset') }}">I forgot my password</a>
{% if Config.get('auth.allow_register') %}
<a href="{{ route('register') }}" class="text-center">Register a new account</a><br>
{% endif %}
</div><!-- /.login-box-body -->

View File

@@ -22,7 +22,7 @@
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
<div class="form-group has-feedback">
<input type="text" name="code" class="form-control" placeholder="{{ 'two_factor_code_here'|_ }}"/>
<input type="number" name="code" class="form-control" placeholder="{{ 'two_factor_code_here'|_ }}"/>
</div>
<div class="row">

View File

@@ -19,7 +19,7 @@
{{ ExpandedForm.tags('match') }}
{{ ExpandedForm.amount('amount_min') }}
{{ ExpandedForm.amount('amount_max') }}
{{ ExpandedForm.date('date',phpdate('Y-m-d')) }}
{{ ExpandedForm.date('date',phpdate('Y-m-d'), {helpText: trans('firefly.bill_date_little_relevance')}) }}
{{ ExpandedForm.select('repeat_freq',periods,'monthly') }}
</div>
</div>

View File

@@ -21,7 +21,7 @@
{{ ExpandedForm.tags('match') }}
{{ ExpandedForm.amount('amount_min') }}
{{ ExpandedForm.amount('amount_max') }}
{{ ExpandedForm.date('date',bill.date.format('Y-m-d')) }}
{{ ExpandedForm.date('date',bill.date.format('Y-m-d'), {helpText: trans('firefly.bill_date_little_relevance')}) }}
{{ ExpandedForm.select('repeat_freq',periods) }}
</div>
</div>

View File

@@ -0,0 +1,28 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Hey there,
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
First of all: delete this email message if you did not expect it.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Otherwise, in order to use your account, please
<a href="{{ route }}" style="color:#337ab7">confirm this email address is yours</a>.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
This link is valid for about 4 hours.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:11px;color:#aaa;">
The registration has been created from IP {{ ip }}
</p>

View File

@@ -0,0 +1,11 @@
Hey there,
First of all: delete this email message if you did not expect it.
Otherwise, in order to use your account, please confirm this email address is yours, by clicking on this link:
{{ route }}
This link is valid for about 4 hours.
The registration has been created from IP {{ ip }}

View File

@@ -4,14 +4,13 @@
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body itemscope itemtype="http://schema.org/SoftwareApplication">
<body>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Hey there,
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
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!
Welkome to <a style="color:#337ab7" href="{{ address }}">Firefly III</a>. Your registration has made it, and this email is here to confirm it. Yay!
</p>
<ul>
@@ -27,45 +26,22 @@
<a style="color:#337ab7" href="https://github.com/JC5/firefly-iii/wiki/First-use">first use guide</a> and the
<a style="color:#337ab7" href="http://jc5.github.io/firefly-iii//description/">full description</a>.
</li>
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
If this installation of Firefly is configured to send activation mails as well, you should get an activation
link very soon!
</li>
</ul>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Enjoy!
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
<span itemprop="author" itemscope itemtype="http://schema.org/Person"><span itemprop="name">James Cole</span></span>
James Cole
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:11px;color:#aaa;">
The registration has been created from IP {{ ip }}
</p>
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "EmailMessage",
"description": "Visit Firefly III",
"potentialAction": {
"@type": "ViewAction",
"target": "{{ address }}",
"url": "{{ address }}",
"name": "Visit Firefly III"
},
"publisher": {
"@type": "Organization",
"name": "Firefly III",
"url": "{{ address }}"
}
}
</script>
</body>
</html>

View File

@@ -5,7 +5,7 @@
<th>{{ trans('list.name') }}</th>
<th class="hidden-sm hidden-xs">{{ trans('list.matchesOn') }}</th>
<th colspan="2">{{ trans('list.matchingAmount') }}</th>
<th class="hidden-sm hidden-xs">{{ trans('list.lastMatch') }}</th>
<th class="hidden-sm hidden-xs">{{ trans('list.paid_current_period') }}</th>
<th class="hidden-sm hidden-xs">{{ trans('list.expectedMatch') }}</th>
<th class="hidden-sm hidden-xs">{{ trans('list.active') }}</th>
<th class="hidden-sm hidden-xs">{{ trans('list.automatch') }}</th>
@@ -36,8 +36,19 @@
{{ entry.amount_max|formatAmount }}
</td>
{% if not entry.lastFoundMatch.isFuture %}
<td class="hidden-sm hidden-xs" data-value="{{ entry.lastFoundMatch.format('U') }}">
<td class="hidden-sm hidden-xs
{% if entry.active %}
{% if entry.paidInPeriod %}
bg-success
{% else %}
bg-danger
{% endif %}
{% endif %}
" data-value="{{ entry.lastFoundMatch.format('U') }}">
{{ entry.lastFoundMatch.formatLocalized(monthAndDayFormat) }}
{% if entry.active and entry.paidInPeriod %}
({{ entry.lastPaidAmount|formatAmountPlain }})
{% endif %}
</td>
{% else %}
<td class="hidden-sm hidden-xs" data-value="0">
@@ -51,7 +62,7 @@
</td>
{% else %}
<td class="hidden-sm hidden-xs" data-value="{{ entry.nextExpectedMatch.format('U') }}">
{{ entry.nextExpectedMatch.formatLocalized(monthAndDayFormat) }}
~ {{ entry.nextExpectedMatch.formatLocalized(monthAndDayFormat) }}
</td>
{% endif %}

View File

@@ -1,24 +1,17 @@
<div class="list-group">
{% for journal in transactions %}
<a class="list-group-item" title="{{ journal.date.formatLocalized(trans('config.month_and_day')) }}"
{% if journal.isOpeningBalance() %}
href="#"
{% else %}
href="{{ route('transactions.show',journal.id) }}"
{% endif %}
>
{{ journal|typeIcon }}
{{ journal.description }}
<span class="pull-right small">
{{ journal|formatJournal }}
</span>
{{ journal|typeIcon }}
{{ journal.description }}
<span class="pull-right small">
{{ journal|formatJournal }}
</span>
</a>
{% endfor %}
</div>

View File

@@ -150,12 +150,12 @@
<div class="checkbox">
<label>
<input type="checkbox" name="twoFactorAuthEnabled" value="1"
{% if twoFactorAuthEnabled == '1' %} checked {% endif %}> {{ 'pref_enable_two_factor_auth'|_ }}
{% if is2faEnabled == '1' %} checked {% endif %}> {{ 'pref_enable_two_factor_auth'|_ }}
</label>
</div>
</div>
{% if twoFactorAuthEnabled == 1 and hasTwoFactorAuthSecret == true %}
{% if is2faEnabled == 1 and has2faSecret == true %}
<div class="col-sm-10">
<div class="checkbox">

View File

@@ -100,7 +100,7 @@
<div class="row">
<div class="col-lg-12">
<label class="checkbox-inline">
<input type="checkbox" class="budget-checkbox" name="budgets[]" value="0"> {{ 'noBudget'|_ }}
<input type="checkbox" class="budget-checkbox" name="budgets[]" value="0"> {{ 'no_budget'|_ }}
</label>
{% for budget in budgets %}
<label class="checkbox-inline">

View File

@@ -22,7 +22,7 @@
{% for balanceLine in balance.getBalanceLines %}
<tr>
{% if balanceLine.getBudget %}
{% if balanceLine.getBudget.id %}
<td>
<a href="{{ route('budgets.show',balanceLine.getBudget.id) }}">{{ balanceLine.getTitle }}</a>
</td>
@@ -41,7 +41,10 @@
<td>
{% if balanceEntry.getSpent != 0 %}
<span class="text-danger">{{ (balanceEntry.getSpent)|formatAmountPlain }}</span>
<i class="fa fa-fw text-muted fa-info-circle"></i>
<i class="fa fa-fw text-muted fa-info-circle firefly-info-button" data-location="balance-amount"
data-account-id="{{ balanceEntry.getAccount.id }}"
data-budget-id="{{ balanceLine.getBudget.id }}"></i>
{% endif %}
{% if balanceEntry.getLeft != 0 %}
<span class="text-success">{{ (balanceEntry.getLeft)|formatAmountPlain }}</span>

View File

@@ -22,7 +22,7 @@
{% if budgetLine.getBudget.id %}
<a href="{{ route('budgets.show',budgetLine.getBudget.id) }}">{{ budgetLine.getBudget.name }}</a>
{% else %}
<em>{{ 'noBudget'|_ }}</em>
<em>{{ 'no_budget'|_ }}</em>
{% endif %}
</td>
<td>
@@ -39,7 +39,9 @@
</td>
<td>
{% if budgetLine.getSpent != 0 %}
{{ budgetLine.getSpent|formatAmount }} <i class="fa fa-fw text-muted fa-info-circle"></i>
{{ budgetLine.getSpent|formatAmount }} <i class="fa fa-fw text-muted fa-info-circle firefly-info-button"
data-location="budget-spent-amount" data-budget-id="{{ budgetLine.getBudget.id }}"
></i>
{% endif %}
{% if budgetLine.getSpent == 0 %}

View File

@@ -18,7 +18,9 @@
</td>
<td>{{ cat.spent|formatAmount }}</td>
<td style="width:20px;">
<i class="fa fa-fw fa-info-circle text-muted"></i>
<i class="fa fa-fw fa-info-circle text-muted firefly-info-button"
data-location="category-entry" data-category-id="{{ cat.id }}"
></i>
</td>
</tr>
{% endfor %}

View File

@@ -17,7 +17,7 @@
<br/>
<small>
{{ expense.count }} {{ 'transactions'|_|lower }}
<i class="fa fa-fw text-muted fa-info-circle"></i>
<i class="fa fa-fw text-muted fa-info-circle firefly-info-button" data-location="expense-entry" data-account-id="{{ expense.id }}"></i>
</small>
{% endif %}
</td>

View File

@@ -17,7 +17,7 @@
<br/>
<small>
{{ income.count }} {{ 'transactions'|_|lower }}
<i class="fa fa-fw text-muted fa-info-circle"></i>
<i class="fa fa-fw text-muted fa-info-circle firefly-info-button" data-location="income-entry" data-account-id="{{ income.id }}"></i>
</small>
{% endif %}

View File

@@ -24,7 +24,7 @@
<!-- SHOW ACCOUNT (FROM) ONLY FOR WITHDRAWALS AND DEPOSITS -->
{% if what == 'deposit' or what == 'withdrawal' %}
{{ ExpandedForm.select('account_id',accounts,data['account_id']) }}
{{ ExpandedForm.select('account_id',accountList,data['account_id']) }}
{% endif %}
<!-- SHOW EXPENSE ACCOUNT ONLY FOR WITHDRAWALS -->
@@ -39,8 +39,8 @@
<!-- ONLY SHOW FROM/TO ACCOUNT WHEN CREATING TRANSFER -->
{% if what == 'transfer' %}
{{ ExpandedForm.select('account_from_id',accounts,data['account_from_id']) }}
{{ ExpandedForm.select('account_to_id',accounts,data['account_to_id']) }}
{{ ExpandedForm.select('account_from_id',accountList,data['account_from_id']) }}
{{ ExpandedForm.select('account_to_id',accountList,data['account_to_id']) }}
{% endif %}
<!-- ALWAYS SHOW AMOUNT -->
@@ -61,7 +61,7 @@
<div class="box-body">
<!-- BUDGET ONLY WHEN CREATING A WITHDRAWAL -->
{% if what == 'withdrawal' %}
{{ ExpandedForm.select('budget_id',budgets,data['budget_id']) }}
{{ ExpandedForm.select('budget_id',budgetList,data['budget_id']) }}
{% endif %}
<!-- CATEGORY ALWAYS -->
@@ -80,8 +80,8 @@
{{ ExpandedForm.text('tags') }}
<!-- RELATE THIS TRANSFER TO A PIGGY BANK -->
{% if what == 'withdrawal' and piggies|length > 0 %}
{{ ExpandedForm.select('piggy_bank_id',piggies,data['piggy_bank_id']) }}
{% if what == 'transfer' and piggyBankList|length > 0 %}
{{ ExpandedForm.select('piggy_bank_id',piggyBankList,data['piggy_bank_id']) }}
{% endif %}
<!-- ATTACHMENTS -->

Some files were not shown because too many files have changed in this diff Show More