diff --git a/app/Api/V1/Controllers/AttachmentController.php b/app/Api/V1/Controllers/AttachmentController.php index a2895d4847..562f1f81e2 100644 --- a/app/Api/V1/Controllers/AttachmentController.php +++ b/app/Api/V1/Controllers/AttachmentController.php @@ -23,10 +23,12 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers; +use FireflyIII\Api\V1\Middleware\ApiDemoUser; use FireflyIII\Api\V1\Requests\AttachmentStoreRequest; use FireflyIII\Api\V1\Requests\AttachmentUpdateRequest; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; +use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Models\Attachment; use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; use FireflyIII\Transformers\AttachmentTransformer; @@ -58,6 +60,7 @@ class AttachmentController extends Controller public function __construct() { parent::__construct(); + $this->middleware(ApiDemoUser::class)->except(['delete', 'download', 'show', 'index']); $this->middleware( function ($request, $next) { /** @var User $user */ @@ -65,6 +68,7 @@ class AttachmentController extends Controller $this->repository = app(AttachmentRepositoryInterface::class); $this->repository->setUser($user); + return $next($request); } ); diff --git a/app/Api/V1/Controllers/TransactionController.php b/app/Api/V1/Controllers/TransactionController.php index 717598f32f..becaa0af87 100644 --- a/app/Api/V1/Controllers/TransactionController.php +++ b/app/Api/V1/Controllers/TransactionController.php @@ -269,6 +269,7 @@ class TransactionController extends Controller * * @param TransactionStoreRequest $request * + * @throws FireflyException * @return JsonResponse */ public function store(TransactionStoreRequest $request): JsonResponse @@ -283,7 +284,7 @@ class TransactionController extends Controller try { $transactionGroup = $this->groupRepository->store($data); } catch (DuplicateTransactionException $e) { - Log::warning('Caught a duplicate. Return error message.'); + Log::warning('Caught a duplicate transaction. Return error message.'); // return bad validation message. // TODO use Laravel's internal validation thing to do this. $response = [ @@ -326,7 +327,7 @@ class TransactionController extends Controller $selectedGroup = $collector->getGroups()->first(); if (null === $selectedGroup) { - throw new NotFoundHttpException(); // @codeCoverageIgnore + throw new FireflyException('Cannot find transaction. Possibly, a rule deleted this transaction after its creation.'); } /** @var TransactionGroupTransformer $transformer */ $transformer = app(TransactionGroupTransformer::class); diff --git a/app/Api/V1/Middleware/ApiDemoUser.php b/app/Api/V1/Middleware/ApiDemoUser.php new file mode 100644 index 0000000000..5323877208 --- /dev/null +++ b/app/Api/V1/Middleware/ApiDemoUser.php @@ -0,0 +1,61 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Middleware; + +use Closure; +use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\User; +use Illuminate\Http\Request; + +/** + * Class ApiDemoUser. + */ +class ApiDemoUser +{ + /** + * Handle an incoming request. + * + * @param Request $request + * @param Closure $next + * + * @return mixed + */ + public function handle(Request $request, Closure $next) + { + /** @var User $user */ + $user = $request->user(); + + if (null === $user) { + return $next($request); + } + + /** @var UserRepositoryInterface $repository */ + $repository = app(UserRepositoryInterface::class); + + if ($repository->hasRole($user, 'demo')) { + return response('', 403); + } + + return $next($request); + } +} diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index ce558d2858..6ffeca74e2 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -87,7 +87,7 @@ class Handler extends ExceptionHandler ); } - return response()->json(['message' => 'Internal Firefly III Exception. See log files.', 'exception' => get_class($exception)], 500); + return response()->json(['message' => sprintf('Internal Firefly III Exception: %s', $exception->getMessage()), 'exception' => get_class($exception)], 500); } if ($exception instanceof NotFoundHttpException) { diff --git a/app/Factory/TransactionJournalFactory.php b/app/Factory/TransactionJournalFactory.php index e40043e593..58eddad0f9 100644 --- a/app/Factory/TransactionJournalFactory.php +++ b/app/Factory/TransactionJournalFactory.php @@ -428,7 +428,7 @@ class TransactionJournalFactory ->first(); } if (null !== $result) { - Log::warning('Found a duplicate!'); + Log::warning(sprintf('Found a duplicate in errorIfDuplicate because hash %s is not unique!', $hash)); throw new DuplicateTransactionException(sprintf('Duplicate of transaction #%d.', $result->transactionJournal->transaction_group_id)); } } diff --git a/app/Http/Controllers/Account/CreateController.php b/app/Http/Controllers/Account/CreateController.php index 928f656b69..ef9c1ba411 100644 --- a/app/Http/Controllers/Account/CreateController.php +++ b/app/Http/Controllers/Account/CreateController.php @@ -151,7 +151,12 @@ class CreateController extends Controller // store attachment(s): /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($account, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($account, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore diff --git a/app/Http/Controllers/Account/EditController.php b/app/Http/Controllers/Account/EditController.php index 007f3ec1f2..4afb528e68 100644 --- a/app/Http/Controllers/Account/EditController.php +++ b/app/Http/Controllers/Account/EditController.php @@ -190,9 +190,13 @@ class EditController extends Controller app('preferences')->mark(); // store new attachment(s): - /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($account, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($account, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore diff --git a/app/Http/Controllers/Admin/TelemetryController.php b/app/Http/Controllers/Admin/TelemetryController.php index 7aa60cad8d..2b9163992b 100644 --- a/app/Http/Controllers/Admin/TelemetryController.php +++ b/app/Http/Controllers/Admin/TelemetryController.php @@ -101,7 +101,8 @@ class TelemetryController extends Controller app('view')->share('subTitleIcon', 'fa-eye'); app('view')->share('subTitle', (string) trans('firefly.telemetry_admin_index')); $version = config('firefly.version'); - $enabled = config('firefly.telemetry', false); + $enabled = config('firefly.send_telemetry', false) && config('firefly.feature_flags.telemetry'); + $count = $this->repository->count(); return view('admin.telemetry.index', compact('version', 'enabled', 'count')); diff --git a/app/Http/Controllers/BillController.php b/app/Http/Controllers/BillController.php index 58a5c5edf7..d8c02e30e9 100644 --- a/app/Http/Controllers/BillController.php +++ b/app/Http/Controllers/BillController.php @@ -383,7 +383,12 @@ class BillController extends Controller /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($bill, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($bill, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore @@ -410,7 +415,12 @@ class BillController extends Controller /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($bill, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($bill, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } // flash messages if (count($this->attachments->getMessages()->get('attachments')) > 0) { diff --git a/app/Http/Controllers/Budget/AvailableBudgetController.php b/app/Http/Controllers/Budget/AvailableBudgetController.php index f48358b0be..4d1047cc53 100644 --- a/app/Http/Controllers/Budget/AvailableBudgetController.php +++ b/app/Http/Controllers/Budget/AvailableBudgetController.php @@ -157,6 +157,7 @@ class AvailableBudgetController extends Controller */ public function edit(AvailableBudget $availableBudget, Carbon $start, Carbon $end) { + $availableBudget->amount = round($availableBudget->amount, $availableBudget->transactionCurrency->decimal_places); return view('budgets.available-budgets.edit', compact('availableBudget', 'start', 'end')); } diff --git a/app/Http/Controllers/Budget/CreateController.php b/app/Http/Controllers/Budget/CreateController.php index fd88ef52a9..f7d0c48482 100644 --- a/app/Http/Controllers/Budget/CreateController.php +++ b/app/Http/Controllers/Budget/CreateController.php @@ -130,9 +130,13 @@ class CreateController extends Controller app('preferences')->mark(); // store attachment(s): - /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($budget, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($budget, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore diff --git a/app/Http/Controllers/Budget/EditController.php b/app/Http/Controllers/Budget/EditController.php index 7dc7ce3495..5b0bb4b4ed 100644 --- a/app/Http/Controllers/Budget/EditController.php +++ b/app/Http/Controllers/Budget/EditController.php @@ -137,9 +137,13 @@ class EditController extends Controller $redirect = redirect($this->getPreviousUri('budgets.edit.uri')); // store new attachment(s): - /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($budget, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($budget, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore diff --git a/app/Http/Controllers/Category/CreateController.php b/app/Http/Controllers/Category/CreateController.php index fa19ddfcd1..771932ab96 100644 --- a/app/Http/Controllers/Category/CreateController.php +++ b/app/Http/Controllers/Category/CreateController.php @@ -102,9 +102,13 @@ class CreateController extends Controller app('preferences')->mark(); // store attachment(s): - /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($category, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($category, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore diff --git a/app/Http/Controllers/Category/EditController.php b/app/Http/Controllers/Category/EditController.php index f5050899ce..1aa925a062 100644 --- a/app/Http/Controllers/Category/EditController.php +++ b/app/Http/Controllers/Category/EditController.php @@ -107,9 +107,13 @@ class EditController extends Controller app('preferences')->mark(); // store new attachment(s): - /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($category, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($category, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore diff --git a/app/Http/Controllers/Chart/TransactionController.php b/app/Http/Controllers/Chart/TransactionController.php index 31b888847e..ed7d5ad143 100644 --- a/app/Http/Controllers/Chart/TransactionController.php +++ b/app/Http/Controllers/Chart/TransactionController.php @@ -82,21 +82,11 @@ class TransactionController extends Controller foreach ($result as $journal) { $budget = $journal['budget_name'] ?? (string) trans('firefly.no_budget'); $title = sprintf('%s (%s)', $budget, $journal['currency_symbol']); - // key => [value => x, 'currency_symbol' => 'x'] $data[$title] = $data[$title] ?? [ 'amount' => '0', 'currency_symbol' => $journal['currency_symbol'], ]; $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['amount']); - - if (null !== $journal['foreign_amount']) { - $title = sprintf('%s (%s)', $budget, $journal['foreign_currency_symbol']); - $data[$title] = $data[$title] ?? [ - 'amount' => $journal['foreign_amount'], - 'currency_symbol' => $journal['currency_symbol'], - ]; - $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['foreign_amount']); - } } $chart = $this->generator->multiCurrencyPieChart($data); $cache->store($chart); @@ -150,21 +140,12 @@ class TransactionController extends Controller foreach ($result as $journal) { $category = $journal['category_name'] ?? (string) trans('firefly.no_category'); $title = sprintf('%s (%s)', $category, $journal['currency_symbol']); - // key => [value => x, 'currency_symbol' => 'x'] $data[$title] = $data[$title] ?? [ 'amount' => '0', 'currency_symbol' => $journal['currency_symbol'], ]; $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['amount']); - if (null !== $journal['foreign_amount']) { - $title = sprintf('%s (%s)', $category, $journal['foreign_currency_symbol']); - $data[$title] = $data[$title] ?? [ - 'amount' => $journal['foreign_amount'], - 'currency_symbol' => $journal['currency_symbol'], - ]; - $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['foreign_amount']); - } } $chart = $this->generator->multiCurrencyPieChart($data); $cache->store($chart); @@ -223,15 +204,6 @@ class TransactionController extends Controller 'currency_symbol' => $journal['currency_symbol'], ]; $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['amount']); - - if (null !== $journal['foreign_amount']) { - $title = sprintf('%s (%s)', $name, $journal['foreign_currency_symbol']); - $data[$title] = $data[$title] ?? [ - 'amount' => $journal['foreign_amount'], - 'currency_symbol' => $journal['currency_symbol'], - ]; - $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['foreign_amount']); - } } $chart = $this->generator->multiCurrencyPieChart($data); $cache->store($chart); @@ -291,14 +263,6 @@ class TransactionController extends Controller ]; $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['amount']); - if (null !== $journal['foreign_amount']) { - $title = sprintf('%s (%s)', $name, $journal['foreign_currency_symbol']); - $data[$title] = $data[$title] ?? [ - 'amount' => $journal['foreign_amount'], - 'currency_symbol' => $journal['currency_symbol'], - ]; - $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['foreign_amount']); - } } $chart = $this->generator->multiCurrencyPieChart($data); $cache->store($chart); diff --git a/app/Http/Controllers/PiggyBankController.php b/app/Http/Controllers/PiggyBankController.php index ff3a4d0738..2890991529 100644 --- a/app/Http/Controllers/PiggyBankController.php +++ b/app/Http/Controllers/PiggyBankController.php @@ -456,7 +456,12 @@ class PiggyBankController extends Controller // store attachment(s): /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($piggyBank, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($piggyBank, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore @@ -495,7 +500,12 @@ class PiggyBankController extends Controller // store new attachment(s): /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($piggyBank, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($piggyBank, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore diff --git a/app/Http/Controllers/Recurring/IndexController.php b/app/Http/Controllers/Recurring/IndexController.php index 449cca69cc..bcb6123a43 100644 --- a/app/Http/Controllers/Recurring/IndexController.php +++ b/app/Http/Controllers/Recurring/IndexController.php @@ -85,6 +85,8 @@ class IndexController extends Controller $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; $collection = $this->recurring->get(); + $today = new Carbon; + $year = new Carbon; // split collection $total = $collection->count(); @@ -98,8 +100,7 @@ class IndexController extends Controller $recurring = []; /** @var Recurrence $recurrence */ foreach ($recurrences as $recurrence) { - $today = new Carbon; - $year = new Carbon; + $year->addYear(); if ($recurrence->first_date > $today) { $today = clone $recurrence->first_date; @@ -110,12 +111,18 @@ class IndexController extends Controller $array['first_date'] = new Carbon($array['first_date']); $array['repeat_until'] = null === $array['repeat_until'] ? null : new Carbon($array['repeat_until']); $array['latest_date'] = null === $array['latest_date'] ? null : new Carbon($array['latest_date']); - $array['occurrences'] = []; - if (0 !== $recurrence->recurrenceRepetitions->count()) { - $array['ocurrences'] = array_slice($this->recurring->getOccurrencesInRange($recurrence->recurrenceRepetitions->first(), $today, $year), 0, 1); + // make carbon objects out of occurrences + foreach ($array['repetitions'] as $repIndex => $repetition) { + foreach ($repetition['occurrences'] as $occIndex => $occurrence) { + $array['repetitions'][$repIndex]['occurrences'][$occIndex] = new Carbon($occurrence); + } } + //if (0 !== $recurrence->recurrenceRepetitions->count()) { + //$array['ocurrences'] = array_slice($this->recurring->getOccurrencesInRange($recurrence->recurrenceRepetitions->first(), $today, $year), 0, 1); + //} + $recurring[] = $array; } $paginator = new LengthAwarePaginator($recurring, $total, $pageSize, $page); @@ -123,7 +130,7 @@ class IndexController extends Controller $this->verifyRecurringCronJob(); - return view('recurring.index', compact('paginator', 'page', 'pageSize', 'total')); + return view('recurring.index', compact('paginator', 'today', 'page', 'pageSize', 'total')); } } diff --git a/app/Http/Controllers/Recurring/ShowController.php b/app/Http/Controllers/Recurring/ShowController.php index 23ddd02444..4833c983b1 100644 --- a/app/Http/Controllers/Recurring/ShowController.php +++ b/app/Http/Controllers/Recurring/ShowController.php @@ -82,8 +82,10 @@ class ShowController extends Controller $transformer = app(RecurrenceTransformer::class); $transformer->setParameters(new ParameterBag); - $array = $transformer->transform($recurrence); - $groups = $this->recurring->getTransactions($recurrence); + $array = $transformer->transform($recurrence); + $groups = $this->recurring->getTransactions($recurrence); + $today = new Carbon; + $array['repeat_until'] = null !== $array['repeat_until'] ? new Carbon($array['repeat_until']) : null; // transform dates back to Carbon objects: foreach ($array['repetitions'] as $index => $repetition) { @@ -94,6 +96,6 @@ class ShowController extends Controller $subTitle = (string) trans('firefly.overview_for_recurrence', ['title' => $recurrence->title]); - return view('recurring.show', compact('recurrence', 'subTitle', 'array', 'groups')); + return view('recurring.show', compact('recurrence', 'subTitle', 'array', 'groups','today')); } } diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index ffa4e50092..85e9ff526a 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -321,7 +321,12 @@ class TagController extends Controller // store attachment(s): /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($result, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($result, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore @@ -359,7 +364,12 @@ class TagController extends Controller // store new attachment(s): /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; - $this->attachments->saveAttachmentsForModel($tag, $files); + if (null !== $files && !auth()->user()->hasRole('demo')) { + $this->attachments->saveAttachmentsForModel($tag, $files); + } + if (null !== $files && auth()->user()->hasRole('demo')) { + session()->flash('info',(string)trans('firefly.no_att_demo_user')); + } if (count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 16dce54039..32d02df306 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -28,6 +28,7 @@ use FireflyIII\Factory\AccountFactory; use FireflyIII\Models\Account; use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountType; +use FireflyIII\Models\Attachment; use FireflyIII\Models\Location; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionGroup; @@ -39,6 +40,7 @@ use FireflyIII\User; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Collection; use Log; +use Storage; /** * Class AccountRepository. @@ -473,27 +475,34 @@ class AccountRepository implements AccountRepositoryInterface if (AccountType::ASSET !== $account->accountType->type) { throw new FireflyException(sprintf('%s is not an asset account.', $account->name)); } - - $name = trans('firefly.reconciliation_account_name', ['name' => $account->name]); + $currency = $this->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); + $name = trans('firefly.reconciliation_account_name', ['name' => $account->name, 'currency' => $currency->code]); /** @var AccountType $type */ - $type = AccountType::where('type', AccountType::RECONCILIATION)->first(); - $accounts = $this->user->accounts()->where('account_type_id', $type->id)->get(); - - // TODO no longer need to loop like this + $type = AccountType::where('type', AccountType::RECONCILIATION)->first(); + $current = $this->user->accounts()->where('account_type_id', $type->id) + ->where('name', $name) + ->first(); /** @var Account $current */ - foreach ($accounts as $current) { - if ($current->name === $name) { - return $current; - } + if (null !== $current) { + return $current; } + + $data = [ + 'account_type_id' => null, + 'account_type' => AccountType::RECONCILIATION, + 'active' => true, + 'name' => $name, + 'currency_id' => $currency->id, + 'currency_code' => $currency->code, + ]; + /** @var AccountFactory $factory */ $factory = app(AccountFactory::class); $factory->setUser($account->user); - $account = $factory->findOrCreate($name, $type->type); - return $account; + return $factory->create($data); } /** @@ -651,7 +660,22 @@ class AccountRepository implements AccountRepositoryInterface */ public function getAttachments(Account $account): Collection { - return $account->attachments()->get(); + $set = $account->attachments()->get(); + + /** @var Storage $disk */ + $disk = Storage::disk('upload'); + + $set = $set->each( + static function (Attachment $attachment) use ($disk) { + $notes = $attachment->notes()->first(); + $attachment->file_exists = $disk->exists($attachment->fileName()); + $attachment->notes = $notes ? $notes->text : ''; + + return $attachment; + } + ); + + return $set; } /** diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index 1183e353ad..124612a6ca 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use DB; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\BillFactory; +use FireflyIII\Models\Attachment; use FireflyIII\Models\Bill; use FireflyIII\Models\Note; use FireflyIII\Models\Transaction; @@ -39,6 +40,7 @@ use Illuminate\Database\Query\JoinClause; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Log; +use Storage; /** * Class BillRepository. @@ -164,7 +166,22 @@ class BillRepository implements BillRepositoryInterface */ public function getAttachments(Bill $bill): Collection { - return $bill->attachments()->get(); + $set = $bill->attachments()->get(); + + /** @var Storage $disk */ + $disk = Storage::disk('upload'); + + $set = $set->each( + static function (Attachment $attachment) use ($disk) { + $notes = $attachment->notes()->first(); + $attachment->file_exists = $disk->exists($attachment->fileName()); + $attachment->notes = $notes ? $notes->text : ''; + + return $attachment; + } + ); + + return $set; } /** diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index af9fd47e50..c68acfa141 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use DB; use Exception; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Attachment; use FireflyIII\Models\AutoBudget; use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; @@ -38,6 +39,7 @@ use FireflyIII\User; use Illuminate\Database\QueryException; use Illuminate\Support\Collection; use Log; +use Storage; /** * Class BudgetRepository. @@ -489,7 +491,22 @@ class BudgetRepository implements BudgetRepositoryInterface */ public function getAttachments(Budget $budget): Collection { - return $budget->attachments()->get(); + $set = $budget->attachments()->get(); + + /** @var Storage $disk */ + $disk = Storage::disk('upload'); + + $set = $set->each( + static function (Attachment $attachment) use ($disk) { + $notes = $attachment->notes()->first(); + $attachment->file_exists = $disk->exists($attachment->fileName()); + $attachment->notes = $notes ? $notes->text : ''; + + return $attachment; + } + ); + + return $set; } public function getMaxOrder(): int diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index ffd61461e4..e4e8736586 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use DB; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\CategoryFactory; +use FireflyIII\Models\Attachment; use FireflyIII\Models\Category; use FireflyIII\Models\RecurrenceTransactionMeta; use FireflyIII\Models\RuleAction; @@ -34,6 +35,7 @@ use FireflyIII\Services\Internal\Update\CategoryUpdateService; use FireflyIII\User; use Illuminate\Support\Collection; use Log; +use Storage; /** * Class CategoryRepository. @@ -380,6 +382,21 @@ class CategoryRepository implements CategoryRepositoryInterface */ public function getAttachments(Category $category): Collection { - return $category->attachments()->get(); + $set = $category->attachments()->get(); + + /** @var Storage $disk */ + $disk = Storage::disk('upload'); + + $set = $set->each( + static function (Attachment $attachment) use ($disk) { + $notes = $attachment->notes()->first(); + $attachment->file_exists = $disk->exists($attachment->fileName()); + $attachment->notes = $notes ? $notes->text : ''; + + return $attachment; + } + ); + + return $set; } } diff --git a/app/Repositories/Journal/JournalAPIRepository.php b/app/Repositories/Journal/JournalAPIRepository.php index a4ff6c3df4..9b51937fb3 100644 --- a/app/Repositories/Journal/JournalAPIRepository.php +++ b/app/Repositories/Journal/JournalAPIRepository.php @@ -23,12 +23,14 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Journal; +use FireflyIII\Models\Attachment; use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\User; use Illuminate\Support\Collection; use Log; +use Storage; /** * Class JournalAPIRepository @@ -74,7 +76,22 @@ class JournalAPIRepository implements JournalAPIRepositoryInterface */ public function getAttachments(TransactionJournal $journal): Collection { - return $journal->attachments; + $set = $journal->attachments; + + /** @var Storage $disk */ + $disk = Storage::disk('upload'); + + $set = $set->each( + static function (Attachment $attachment) use ($disk) { + $notes = $attachment->notes()->first(); + $attachment->file_exists = $disk->exists($attachment->fileName()); + $attachment->notes = $notes ? $notes->text : ''; + + return $attachment; + } + ); + + return $set; } /** diff --git a/app/Repositories/PiggyBank/PiggyBankRepository.php b/app/Repositories/PiggyBank/PiggyBankRepository.php index 42654efe5b..3be16b5c9e 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepository.php +++ b/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Repositories\PiggyBank; use Carbon\Carbon; +use FireflyIII\Models\Attachment; use FireflyIII\Models\Note; use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBankRepetition; @@ -33,6 +34,7 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\User; use Illuminate\Support\Collection; use Log; +use Storage; /** * Class PiggyBankRepository. @@ -374,6 +376,21 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface */ public function getAttachments(PiggyBank $piggyBank): Collection { - return $piggyBank->attachments()->get(); + $set = $piggyBank->attachments()->get(); + + /** @var Storage $disk */ + $disk = Storage::disk('upload'); + + $set = $set->each( + static function (Attachment $attachment) use ($disk) { + $notes = $attachment->notes()->first(); + $attachment->file_exists = $disk->exists($attachment->fileName()); + $attachment->notes = $notes ? $notes->text : ''; + + return $attachment; + } + ); + + return $set; } } diff --git a/app/Repositories/Recurring/RecurringRepository.php b/app/Repositories/Recurring/RecurringRepository.php index b91d6efdab..363c4be13c 100644 --- a/app/Repositories/Recurring/RecurringRepository.php +++ b/app/Repositories/Recurring/RecurringRepository.php @@ -535,6 +535,31 @@ class RecurringRepository implements RecurringRepositoryInterface // filter out all the weekend days: $occurrences = $this->filterWeekends($repetition, $occurrences); + // filter out everything if "repeat_until" is set. + $repeatUntil = $repetition->recurrence->repeat_until; + $occurrences = $this->filterMaxDate($repeatUntil, $occurrences); + return $occurrences; } + + /** + * @param Carbon|null $max + * @param array $occurrences + * + * @return array + */ + private function filterMaxDate(?Carbon $max, array $occurrences): array + { + if (null === $max) { + return $occurrences; + } + $filtered = []; + foreach ($occurrences as $date) { + if ($date->lte($max)) { + $filtered[] = $date; + } + } + + return $filtered; + } } diff --git a/app/Repositories/Tag/TagRepository.php b/app/Repositories/Tag/TagRepository.php index a83997d54d..970978a746 100644 --- a/app/Repositories/Tag/TagRepository.php +++ b/app/Repositories/Tag/TagRepository.php @@ -26,6 +26,7 @@ use Carbon\Carbon; use DB; use FireflyIII\Factory\TagFactory; use FireflyIII\Helpers\Collector\GroupCollectorInterface; +use FireflyIII\Models\Attachment; use FireflyIII\Models\Location; use FireflyIII\Models\RuleAction; use FireflyIII\Models\RuleTrigger; @@ -34,6 +35,7 @@ use FireflyIII\Models\TransactionType; use FireflyIII\User; use Illuminate\Support\Collection; use Log; +use Storage; /** * Class TagRepository. @@ -549,7 +551,21 @@ class TagRepository implements TagRepositoryInterface */ public function getAttachments(Tag $tag): Collection { - return $tag->attachments()->get(); + $set= $tag->attachments()->get(); + /** @var Storage $disk */ + $disk = Storage::disk('upload'); + + $set = $set->each( + static function (Attachment $attachment) use ($disk) { + $notes = $attachment->notes()->first(); + $attachment->file_exists = $disk->exists($attachment->fileName()); + $attachment->notes = $notes ? $notes->text : ''; + + return $attachment; + } + ); + + return $set; } /** diff --git a/app/Repositories/TransactionGroup/TransactionGroupRepository.php b/app/Repositories/TransactionGroup/TransactionGroupRepository.php index e1444af843..98c489b8b7 100644 --- a/app/Repositories/TransactionGroup/TransactionGroupRepository.php +++ b/app/Repositories/TransactionGroup/TransactionGroupRepository.php @@ -346,6 +346,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface Log::warning('Group repository caught group factory with a duplicate exception!'); throw new DuplicateTransactionException($e->getMessage()); } catch(FireflyException $e) { + Log::warning('Group repository caught group factory with an exception!'); Log::error($e->getMessage()); Log::error($e->getTraceAsString()); throw new FireflyException($e->getMessage()); diff --git a/app/Services/Internal/Destroy/JournalDestroyService.php b/app/Services/Internal/Destroy/JournalDestroyService.php index 148eac82b4..219f8657e9 100644 --- a/app/Services/Internal/Destroy/JournalDestroyService.php +++ b/app/Services/Internal/Destroy/JournalDestroyService.php @@ -95,8 +95,6 @@ class JournalDestroyService // update events $journal->piggyBankEvents()->update(['transaction_journal_id' => null]); - - $journal->delete(); } catch (Exception $e) { Log::error(sprintf('Could not delete bill: %s', $e->getMessage())); // @codeCoverageIgnore diff --git a/app/Services/Internal/Support/JournalServiceTrait.php b/app/Services/Internal/Support/JournalServiceTrait.php index 8b3188fd1d..cdcc7172bb 100644 --- a/app/Services/Internal/Support/JournalServiceTrait.php +++ b/app/Services/Internal/Support/JournalServiceTrait.php @@ -112,8 +112,8 @@ trait JournalServiceTrait $result = $this->findAccountById($data, $expectedTypes[$transactionType]); $result = $this->findAccountByName($result, $data, $expectedTypes[$transactionType]); $result = $this->findAccountByIban($result, $data, $expectedTypes[$transactionType]); - $result = $this->getCashAccount($result, $data, $expectedTypes[$transactionType]); $result = $this->createAccount($result, $data, $expectedTypes[$transactionType][0]); + $result = $this->getCashAccount($result, $data, $expectedTypes[$transactionType]); return $result; } @@ -301,7 +301,7 @@ trait JournalServiceTrait { // third attempt, find by IBAN if (null === $account && null !== $data['iban']) { - Log::debug('Found nothing by account name.'); + Log::debug(sprintf('Found nothing by account iban "%s".', $data['iban'])); // find by preferred type. $source = $this->accountRepository->findByIbanNull($data['iban'], [$types[0]]); // or any expected type. @@ -347,13 +347,28 @@ trait JournalServiceTrait { Log::debug('Now in createAccount()', $data); // return new account. + if (null !== $account) { + Log::debug( + sprintf( + 'Was also given %s account #%d ("%s") so will simply return that.', + $account->accountType->type, $account->id, $account->name + + ) + ); + } if (null === $account) { - $data['name'] = $data['name'] ?? '(no name)'; // final attempt, create it. if (AccountType::ASSET === $preferredType) { throw new FireflyException('TransactionFactory: Cannot create asset account with these values', $data); } + // fix name of account if only IBAN is given: + if ('' === (string) $data['name'] && '' !== (string) $data['iban']) { + Log::debug(sprintf('Account name is now IBAN ("%s")', $data['iban'])); + $data['name'] = $data['iban']; + } + + $data['name'] = $data['name'] ?? '(no name)'; $account = $this->accountRepository->store( [ diff --git a/app/Support/Binder/JournalList.php b/app/Support/Binder/JournalList.php index fa3b0d118d..2ae8f9ad94 100644 --- a/app/Support/Binder/JournalList.php +++ b/app/Support/Binder/JournalList.php @@ -48,7 +48,7 @@ class JournalList implements BinderInterface // get the journals by using the collector. /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); - $collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER]); + $collector->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::RECONCILIATION]); $collector->withCategoryInformation()->withBudgetInformation()->withTagInformation()->withAccountInformation(); $collector->setJournalIds($list); $result = $collector->getExtractedJournals(); diff --git a/app/Support/Cronjobs/RecurringCronjob.php b/app/Support/Cronjobs/RecurringCronjob.php index dfd7fd413b..6e5cd4b7a3 100644 --- a/app/Support/Cronjobs/RecurringCronjob.php +++ b/app/Support/Cronjobs/RecurringCronjob.php @@ -86,6 +86,7 @@ class RecurringCronjob extends AbstractCronjob $job->setForce($this->force); $job->handle(); app('fireflyconfig')->set('last_rt_job', (int)$this->date->format('U')); + Log::info(sprintf('Marked the last time this job has run as "%s" (%d)',$this->date->format('Y-m-d H:i:s'),(int)$this->date->format('U'))); Log::info('Done with recurring cron job task.'); } } diff --git a/app/Support/ParseDateString.php b/app/Support/ParseDateString.php new file mode 100644 index 0000000000..1b45b4defb --- /dev/null +++ b/app/Support/ParseDateString.php @@ -0,0 +1,157 @@ +keywords, true)) { + return $this->parseKeyword($date); + } + + // if regex for YYYY-MM-DD: + $pattern = '/^(19|20)\d\d-(0[1-9]|1[012])-(0[1-9]|[12][\d]|3[01])$/'; + if (preg_match($pattern, $date)) { + return $this->parseDefaultDate($date); + } + + // if + or -: + if (0 === strpos($date, '+') || 0 === strpos($date, '-')) { + return $this->parseRelativeDate($date); + } + + throw new FireflyException('Not recognised.'); + } + + /** + * @param string $date + * + * @return Carbon + */ + private function parseDefaultDate(string $date): Carbon + { + return Carbon::createFromFormat('Y-m-d', $date); + } + + /** + * @param string $keyword + * + * @return Carbon + */ + private function parseKeyword(string $keyword): Carbon + { + $today = Carbon::today()->startOfDay(); + switch ($keyword) { + default: + case 'today': + return $today; + case 'yesterday': + return $today->subDay(); + case 'tomorrow': + return $today->addDay(); + case 'start of this week': + return $today->startOfWeek(); + case 'end of this week': + return $today->endOfWeek(); + case 'start of this month': + return $today->startOfMonth(); + case 'end of this month': + return $today->endOfMonth(); + case 'start of this quarter': + return $today->startOfQuarter(); + case 'end of this quarter': + return $today->endOfQuarter(); + case 'start of this year': + return $today->startOfYear(); + case 'end of this year': + return $today->endOfYear(); + } + } + + /** + * @param string $date + * + * @return Carbon + */ + private function parseRelativeDate(string $date): Carbon + { + Log::debug(sprintf('Now in parseRelativeDate("%s")', $date)); + $parts = explode(' ', $date); + $today = Carbon::today()->startOfDay(); + $functions = [ + [ + 'd' => 'subDays', + 'w' => 'subWeeks', + 'm' => 'subMonths', + 'q' => 'subQuarters', + 'y' => 'subYears', + ], [ + 'd' => 'addDays', + 'w' => 'addWeeks', + 'm' => 'addMonths', + 'q' => 'addQuarters', + 'y' => 'addYears', + ], + ]; + + /** @var string $part */ + foreach ($parts as $part) { + Log::debug(sprintf('Now parsing part "%s"', $part)); + $part = trim($part); + + // verify if correct + $pattern = '/[+-]\d+[wqmdy]/'; + $res = preg_match($pattern, $part); + if (0 === $res || false === $res) { + Log::error(sprintf('Part "%s" does not match regular expression. Will be skipped.', $part)); + continue; + } + $direction = 0 === strpos($part, '+') ? 1 : 0; + $period = $part[strlen($part) - 1]; + $number = (int) substr($part, 1, -1); + if (!isset($functions[$direction][$period])) { + Log::error(sprintf('No method for direction %d and period "%s".', $direction, $period)); + continue; + } + $func = $functions[$direction][$period]; + Log::debug(sprintf('Will now do %s(%d) on %s', $func, $number, $today->format('Y-m-d'))); + $today->$func($number); + Log::debug(sprintf('Resulting date is %s', $today->format('Y-m-d'))); + + } + + return $today; + } + +} diff --git a/app/Support/Telemetry.php b/app/Support/Telemetry.php index 905ca18233..cc9c3aacb6 100644 --- a/app/Support/Telemetry.php +++ b/app/Support/Telemetry.php @@ -22,7 +22,9 @@ declare(strict_types=1); namespace FireflyIII\Support; +use Carbon\Carbon; use FireflyIII\Models\Telemetry as TelemetryModel; +use JsonException; use Log; /** @@ -65,6 +67,25 @@ class Telemetry } } + /** + * @param string $key + * @param string $value + * @param int $days + */ + public function recurring(string $key, string $value, int $days): void + { + if (false === config('firefly.send_telemetry') || false === config('firefly.feature_flags.telemetry')) { + // hard stop if not allowed to do telemetry. + // do nothing! + return; + } + + $cutoffDate = Carbon::today()->subDays($days); + if (!$this->hasRecentEntry('recurring', $key, $value, $cutoffDate)) { + $this->storeEntry('recurring', $key, $value); + } + } + /** * String telemetry stores a string value as a telemetry entry. Values could include: * @@ -85,7 +106,6 @@ class Telemetry } Log::info(sprintf('Logged telemetry string "%s" with value "%s".', $name, $value)); - // no storage backend yet, do nothing. $this->storeEntry('string', $name, $value); } @@ -98,16 +118,49 @@ class Telemetry */ private function hasEntry(string $type, string $key, string $value): bool { + try { + $jsonEncoded = json_encode($value, JSON_THROW_ON_ERROR, 512); + } catch (JsonException $e) { + Log::error(sprintf('JSON Exception encoding the following value: %s: %s', $value, $e->getMessage())); + $jsonEncoded = []; + } + return TelemetryModel ::where('type', $type) ->where('key', $key) - ->where('value', json_encode($value, JSON_THROW_ON_ERROR, 512)) + ->where('value', $jsonEncoded) + ->count() > 0; + } + + /** + * @param string $type + * @param string $key + * @param string $value + * @param Carbon $date + * + * @return bool + */ + private function hasRecentEntry(string $type, string $key, string $value, Carbon $date): bool + { + try { + $jsonEncoded = json_encode($value, JSON_THROW_ON_ERROR, 512); + } catch (JsonException $e) { + Log::error(sprintf('JSON Exception encoding the following value: %s: %s', $value, $e->getMessage())); + $jsonEncoded = []; + } + + return TelemetryModel + ::where('type', $type) + ->where('key', $key) + ->where('created_at', '>=', $date->format('Y-m-d H:i:s')) + ->where('value', $jsonEncoded) ->count() > 0; } /** * Store new entry in DB. * + * @param string $type * @param string $name * @param string $value */ @@ -123,4 +176,4 @@ class Telemetry ); } -} \ No newline at end of file +} diff --git a/app/TransactionRules/Actions/DeleteTransaction.php b/app/TransactionRules/Actions/DeleteTransaction.php new file mode 100644 index 0000000000..394537c59b --- /dev/null +++ b/app/TransactionRules/Actions/DeleteTransaction.php @@ -0,0 +1,81 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Actions; + +use Exception; +use FireflyIII\Models\RuleAction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Services\Internal\Destroy\JournalDestroyService; +use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService; +use Log; + +/** + * Class DeleteTransaction. + */ +class DeleteTransaction implements ActionInterface +{ + /** + * TriggerInterface constructor. + * + * @param RuleAction $action + */ + public function __construct(RuleAction $action) + { + } + + /** + * Will delete transaction journal. Also the group if no other journals are in the group. + * + * @param TransactionJournal $journal + * + * @throws Exception + * @return bool + */ + public function act(TransactionJournal $journal): bool + { + + $count = $journal->transactionGroup->transactionJournals()->count(); + + // destroy entire group. + if (1 === $count) { + Log::debug( + sprintf( + 'RuleAction DeleteTransaction DELETED the entire transaction group of journal #%d ("%s").', + $journal->id, $journal->description + ) + ); + $service = app(TransactionGroupDestroyService::class); + $service->destroy($journal->transactionGroup); + + return true; + } + Log::debug(sprintf('RuleAction DeleteTransaction DELETED transaction journal #%d ("%s").', $journal->id, $journal->description)); + + // trigger delete factory: + /** @var JournalDestroyService $service */ + $service = app(JournalDestroyService::class); + $service->destroy($journal); + + return true; + } +} diff --git a/app/TransactionRules/Actions/UpdatePiggybank.php b/app/TransactionRules/Actions/UpdatePiggybank.php new file mode 100644 index 0000000000..2ee81e812e --- /dev/null +++ b/app/TransactionRules/Actions/UpdatePiggybank.php @@ -0,0 +1,166 @@ +action = $action; + } + + /** + * @inheritDoc + */ + public function act(TransactionJournal $journal): bool + { + Log::debug(sprintf('Triggered rule action UpdatePiggybank on journal #%d', $journal->id)); + if (TransactionType::TRANSFER !== $journal->transactionType->type) { + Log::info(sprintf('Journal #%d is a "%s" so skip this action.', $journal->id, $journal->transactionType->type)); + + return false; + } + $piggyBank = $this->findPiggybank($journal->user); + if (null === $piggyBank) { + Log::info( + sprintf( + 'No piggy bank names "%s", cant execute action #%d of rule #%d ("%s")', + $this->action->value, $this->action->id, $this->action->rule_id, $this->action->rule->title, + ) + ); + + return false; + } + + Log::debug(sprintf('Found piggy bank #%d ("%s")', $piggyBank->id, $piggyBank->name)); + + /** @var Transaction $source */ + $source = $journal->transactions()->where('amount', '<', 0)->first(); + /** @var Transaction $destination */ + $destination = $journal->transactions()->where('amount', '>', 0)->first(); + + if ((int) $source->account_id === (int) $piggyBank->account_id) { + Log::debug('Piggy bank account is linked to source, so remove amount.'); + $this->removeAmount($journal, $piggyBank, $destination->amount); + + + return true; + } + if ((int) $destination->account_id === (int) $piggyBank->account_id) { + Log::debug('Piggy bank account is linked to source, so add amount.'); + $this->addAmount($journal, $piggyBank, $destination->amount); + + return true; + } + Log::info('Piggy bank is not linked to source or destination, so no action will be taken.'); + + return true; + } + + /** + * @param TransactionJournal $journal + * @param PiggyBank $piggyBank + * @param string $amount + */ + private function addAmount(TransactionJournal $journal, PiggyBank $piggyBank, string $amount): void + { + $repository = app(PiggyBankRepositoryInterface::class); + $repository->setUser($journal->user); + + // how much can we add to the piggy bank? + $toAdd = bcsub($piggyBank->targetamount, $repository->getCurrentAmount($piggyBank)); + Log::debug(sprintf('Max amount to add to piggy bank is %s, amount is %s', $toAdd, $amount)); + + // update amount to fit: + $amount = -1 === bccomp($amount, $toAdd) ? $amount : $toAdd; + Log::debug(sprintf('Amount is now %s', $amount)); + + // if amount is zero, stop. + if (0 === bccomp('0', $amount)) { + Log::warning('Amount left is zero, stop.'); + + return; + } + + // make sure we can add amount: + if (false === $repository->canAddAmount($piggyBank, $amount)) { + Log::warning(sprintf('Cannot add %s to piggy bank.', $amount)); + + return; + } + Log::debug(sprintf('Will now add %s to piggy bank.', $amount)); + + $repository->addAmount($piggyBank, $amount); + $repository->createEventWithJournal($piggyBank, app('steam')->positive($amount), $journal); + } + + /** + * @param User $user + * + * @return PiggyBank|null + */ + private function findPiggybank(User $user): ?PiggyBank + { + return $user->piggyBanks()->where('piggy_banks.name', $this->action->action_value)->first(); + } + + /** + * @param TransactionJournal $journal + * @param PiggyBank $piggyBank + * @param string $amount + */ + private function removeAmount(TransactionJournal $journal, PiggyBank $piggyBank, string $amount): void + { + $repository = app(PiggyBankRepositoryInterface::class); + $repository->setUser($journal->user); + + // how much can we remove from piggy bank? + $toRemove = $repository->getCurrentAmount($piggyBank); + Log::debug(sprintf('Amount is %s, max to remove is %s', $amount, $toRemove)); + // if $amount is bigger than $toRemove, shrink it. + $amount = -1 === bccomp($amount, $toRemove) ? $amount : $toRemove; + Log::debug(sprintf('Amount is now %s', $amount)); + + // if amount is zero, stop. + if (0 === bccomp('0', $amount)) { + Log::warning('Amount left is zero, stop.'); + + return; + } + + // make sure we can remove amount: + if (false === $repository->canRemoveAmount($piggyBank, $amount)) { + Log::warning(sprintf('Cannot remove %s from piggy bank.', $amount)); + + return; + } + Log::debug(sprintf('Will now remove %s from piggy bank.', $amount)); + + $repository->removeAmount($piggyBank, $amount); + $repository->createEventWithJournal($piggyBank, app('steam')->negative($amount), $journal); + } +} diff --git a/app/TransactionRules/Triggers/BudgetIs.php b/app/TransactionRules/Triggers/BudgetIs.php index fa6997a281..272ae84ae1 100644 --- a/app/TransactionRules/Triggers/BudgetIs.php +++ b/app/TransactionRules/Triggers/BudgetIs.php @@ -22,7 +22,6 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Triggers; -use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use Log; @@ -76,31 +75,6 @@ final class BudgetIs extends AbstractTrigger implements TriggerInterface return true; } } - - if (null === $budget) { - // perhaps transactions have this budget? - /** @var Transaction $transaction */ - foreach ($journal->transactions as $transaction) { - $budget = $transaction->budgets()->first(); - if (null !== $budget) { - $name = strtolower($budget->name); - if ($name === strtolower($this->triggerValue)) { - Log::debug( - sprintf( - 'RuleTrigger BudgetIs for journal #%d (transaction #%d): "%s" is "%s", return true.', - $journal->id, - $transaction->id, - $name, - $this->triggerValue - ) - ); - - return true; - } - } - } - } - Log::debug(sprintf('RuleTrigger BudgetIs for journal #%d: does not have budget "%s", return false.', $journal->id, $this->triggerValue)); return false; diff --git a/app/TransactionRules/Triggers/CategoryIs.php b/app/TransactionRules/Triggers/CategoryIs.php index df09b9bba7..2388139623 100644 --- a/app/TransactionRules/Triggers/CategoryIs.php +++ b/app/TransactionRules/Triggers/CategoryIs.php @@ -22,7 +22,6 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Triggers; -use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use Log; @@ -76,31 +75,6 @@ final class CategoryIs extends AbstractTrigger implements TriggerInterface return true; } } - - if (null === $category) { - // perhaps transactions have this category? - /** @var Transaction $transaction */ - foreach ($journal->transactions as $transaction) { - $category = $transaction->categories()->first(); - if (null !== $category) { - $name = strtolower($category->name); - if ($name === strtolower($this->triggerValue)) { - Log::debug( - sprintf( - 'RuleTrigger CategoryIs for journal #%d (transaction #%d): "%s" is "%s", return true.', - $journal->id, - $transaction->id, - $name, - $this->triggerValue - ) - ); - - return true; - } - } - } - } - Log::debug(sprintf('RuleTrigger CategoryIs for journal #%d: does not have category "%s", return false.', $journal->id, $this->triggerValue)); return false; diff --git a/app/TransactionRules/Triggers/DateAfter.php b/app/TransactionRules/Triggers/DateAfter.php new file mode 100644 index 0000000000..71ac2cdbcf --- /dev/null +++ b/app/TransactionRules/Triggers/DateAfter.php @@ -0,0 +1,107 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Triggers; + +use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Support\ParseDateString; +use Log; + +/** + * Class DateAfter. + */ +final class DateAfter extends AbstractTrigger implements TriggerInterface +{ + /** + * A trigger is said to "match anything", or match any given transaction, + * when the trigger value is very vague or has no restrictions. Easy examples + * are the "AmountMore"-trigger combined with an amount of 0: any given transaction + * has an amount of more than zero! Other examples are all the "Description"-triggers + * which have hard time handling empty trigger values such as "" or "*" (wild cards). + * + * If the user tries to create such a trigger, this method MUST return true so Firefly III + * can stop the storing / updating the trigger. If the trigger is in any way restrictive + * (even if it will still include 99.9% of the users transactions), this method MUST return + * false. + * + * @param mixed $value + * + * @return bool + */ + public static function willMatchEverything($value = null): bool + { + if (null !== $value) { + return false; + } + Log::error(sprintf('Cannot use %s with a null value.', self::class)); + + return true; + } + + /** + * Returns true when category is X. + * + * @param TransactionJournal $journal + * + * @return bool + */ + public function triggered(TransactionJournal $journal): bool + { + /** @var Carbon $date */ + $date = $journal->date; + Log::debug(sprintf('Found date on journal: %s', $date->format('Y-m-d'))); + $dateParser = new ParseDateString(); + + + try { + $ruleDate = $dateParser->parseDate($this->triggerValue); + } catch (FireflyException $e) { + Log::error('Cannot execute rule trigger.'); + Log::error($e->getMessage()); + + return false; + } + if ($date->isAfter($ruleDate)) { + Log::debug( + sprintf( + '%s is after %s, so return true.', + $date->format('Y-m-d H:i:s'), + $ruleDate->format('Y-m-d H:i:s'), + ) + ); + + return true; + } + + Log::debug( + sprintf( + '%s is NOT after %s, so return true.', + $date->format('Y-m-d H:i:s'), + $ruleDate->format('Y-m-d H:i:s'), + ) + ); + + return false; + } +} diff --git a/app/TransactionRules/Triggers/DateBefore.php b/app/TransactionRules/Triggers/DateBefore.php new file mode 100644 index 0000000000..0b6a6e7c40 --- /dev/null +++ b/app/TransactionRules/Triggers/DateBefore.php @@ -0,0 +1,107 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Triggers; + +use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Support\ParseDateString; +use Log; + +/** + * Class DateBefore. + */ +final class DateBefore extends AbstractTrigger implements TriggerInterface +{ + /** + * A trigger is said to "match anything", or match any given transaction, + * when the trigger value is very vague or has no restrictions. Easy examples + * are the "AmountMore"-trigger combined with an amount of 0: any given transaction + * has an amount of more than zero! Other examples are all the "Description"-triggers + * which have hard time handling empty trigger values such as "" or "*" (wild cards). + * + * If the user tries to create such a trigger, this method MUST return true so Firefly III + * can stop the storing / updating the trigger. If the trigger is in any way restrictive + * (even if it will still include 99.9% of the users transactions), this method MUST return + * false. + * + * @param mixed $value + * + * @return bool + */ + public static function willMatchEverything($value = null): bool + { + if (null !== $value) { + return false; + } + Log::error(sprintf('Cannot use %s with a null value.', self::class)); + + return true; + } + + /** + * Returns true when category is X. + * + * @param TransactionJournal $journal + * + * @return bool + */ + public function triggered(TransactionJournal $journal): bool + { + /** @var Carbon $date */ + $date = $journal->date; + Log::debug(sprintf('Found date on journal: %s', $date->format('Y-m-d'))); + $dateParser = new ParseDateString(); + + + try { + $ruleDate = $dateParser->parseDate($this->triggerValue); + } catch (FireflyException $e) { + Log::error('Cannot execute rule trigger.'); + Log::error($e->getMessage()); + + return false; + } + if ($date->isBefore($ruleDate)) { + Log::debug( + sprintf( + '%s is before %s, so return true.', + $date->format('Y-m-d H:i:s'), + $ruleDate->format('Y-m-d H:i:s'), + ) + ); + + return true; + } + + Log::debug( + sprintf( + '%s is NOT before %s, so return true.', + $date->format('Y-m-d H:i:s'), + $ruleDate->format('Y-m-d H:i:s'), + ) + ); + + return false; + } +} diff --git a/app/TransactionRules/Triggers/DateIs.php b/app/TransactionRules/Triggers/DateIs.php new file mode 100644 index 0000000000..6661b4e441 --- /dev/null +++ b/app/TransactionRules/Triggers/DateIs.php @@ -0,0 +1,107 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Triggers; + +use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Support\ParseDateString; +use Log; + +/** + * Class DateIs. + */ +final class DateIs extends AbstractTrigger implements TriggerInterface +{ + /** + * A trigger is said to "match anything", or match any given transaction, + * when the trigger value is very vague or has no restrictions. Easy examples + * are the "AmountMore"-trigger combined with an amount of 0: any given transaction + * has an amount of more than zero! Other examples are all the "Description"-triggers + * which have hard time handling empty trigger values such as "" or "*" (wild cards). + * + * If the user tries to create such a trigger, this method MUST return true so Firefly III + * can stop the storing / updating the trigger. If the trigger is in any way restrictive + * (even if it will still include 99.9% of the users transactions), this method MUST return + * false. + * + * @param mixed $value + * + * @return bool + */ + public static function willMatchEverything($value = null): bool + { + if (null !== $value) { + return false; + } + Log::error(sprintf('Cannot use %s with a null value.', self::class)); + + return true; + } + + /** + * Returns true when category is X. + * + * @param TransactionJournal $journal + * + * @return bool + */ + public function triggered(TransactionJournal $journal): bool + { + /** @var Carbon $date */ + $date = $journal->date; + Log::debug(sprintf('Found date on journal: %s', $date->format('Y-m-d'))); + $dateParser = new ParseDateString(); + + + try { + $ruleDate = $dateParser->parseDate($this->triggerValue); + } catch (FireflyException $e) { + Log::error('Cannot execute rule trigger.'); + Log::error($e->getMessage()); + + return false; + } + if ($ruleDate->isSameDay($date)) { + Log::debug( + sprintf( + '%s is on the same day as %s, so return true.', + $date->format('Y-m-d H:i:s'), + $ruleDate->format('Y-m-d H:i:s'), + ) + ); + + return true; + } + + Log::debug( + sprintf( + '%s is NOT on the same day as %s, so return true.', + $date->format('Y-m-d H:i:s'), + $ruleDate->format('Y-m-d H:i:s'), + ) + ); + + return false; + } +} diff --git a/app/User.php b/app/User.php index c13227cd2c..53f1cdf805 100644 --- a/app/User.php +++ b/app/User.php @@ -138,10 +138,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property-read int|null $transactions_count * @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\User whereMfaSecret($value) * @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\User whereObjectguid($value) - * @property string $password - * @property bool $blocked - * @property string|null $blocked_code - * @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Role[] $roles */ class User extends Authenticatable { @@ -217,6 +213,16 @@ class User extends Authenticatable return $this->hasMany(Attachment::class); } + /** + * @param string $role + * + * @return bool + */ + public function hasRole(string $role): bool + { + return $this->roles()->where('name', $role)->count() === 1; + } + /** * @codeCoverageIgnore * Link to available budgets diff --git a/app/Validation/FireflyValidator.php b/app/Validation/FireflyValidator.php index e8c50939d9..208a6c87f8 100644 --- a/app/Validation/FireflyValidator.php +++ b/app/Validation/FireflyValidator.php @@ -24,6 +24,7 @@ namespace FireflyIII\Validation; use Config; use DB; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\AccountMeta; use FireflyIII\Models\AccountType; @@ -34,11 +35,13 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Services\Password\Verifier; +use FireflyIII\Support\ParseDateString; use FireflyIII\TransactionRules\Triggers\TriggerInterface; use FireflyIII\User; use Google2FA; use Illuminate\Support\Collection; use Illuminate\Validation\Validator; +use Log; /** * Class FireflyValidator. @@ -333,6 +336,20 @@ class FireflyValidator extends Validator return 1 === $count; } + // if the type is date, the simply try to parse it and throw error when it's bad. + if (in_array($triggerType, ['date_is'], true)) { + /** @var ParseDateString $parser */ + $parser = app(ParseDateString::class); + try { + $parser->parseDate($value); + } catch (FireflyException $e) { + + Log::error($e->getMessage()); + + return false; + } + } + // and finally a "will match everything check": $classes = app('config')->get('firefly.rule-triggers'); /** @var TriggerInterface $class */ diff --git a/composer.lock b/composer.lock index deed74711f..9485a15603 100644 --- a/composer.lock +++ b/composer.lock @@ -8,16 +8,16 @@ "packages": [ { "name": "adldap2/adldap2", - "version": "v10.2.3", + "version": "v10.3.0", "source": { "type": "git", "url": "https://github.com/Adldap2/Adldap2.git", - "reference": "2baffac2dfef308f0a94afa360b6a77540730fd2" + "reference": "1294c92746e3fb3bb59cd7756ca7838a1e705a2a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Adldap2/Adldap2/zipball/2baffac2dfef308f0a94afa360b6a77540730fd2", - "reference": "2baffac2dfef308f0a94afa360b6a77540730fd2", + "url": "https://api.github.com/repos/Adldap2/Adldap2/zipball/1294c92746e3fb3bb59cd7756ca7838a1e705a2a", + "reference": "1294c92746e3fb3bb59cd7756ca7838a1e705a2a", "shasum": "" }, "require": { @@ -63,7 +63,7 @@ "ldap", "windows" ], - "time": "2020-03-08T23:04:47+00:00" + "time": "2020-05-04T21:10:15+00:00" }, { "name": "adldap2/adldap2-laravel", @@ -606,33 +606,37 @@ }, { "name": "doctrine/inflector", - "version": "1.3.1", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/doctrine/inflector.git", - "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1" + "reference": "18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/inflector/zipball/ec3a55242203ffa6a4b27c58176da97ff0a7aec1", - "reference": "ec3a55242203ffa6a4b27c58176da97ff0a7aec1", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7", + "reference": "18b995743e7ec8b15fd6efc594f0fa3de4bfe6d7", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.2" }, "require-dev": { - "phpunit/phpunit": "^6.2" + "doctrine/coding-standard": "^7.0", + "phpstan/phpstan": "^0.11", + "phpstan/phpstan-phpunit": "^0.11", + "phpstan/phpstan-strict-rules": "^0.11", + "phpunit/phpunit": "^7.0 || ^8.0 || ^9.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { "psr-4": { - "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + "Doctrine\\Inflector\\": "lib/Doctrine/Inflector" } }, "notification-url": "https://packagist.org/downloads/", @@ -661,15 +665,35 @@ "email": "schmittjoh@gmail.com" } ], - "description": "Common String Manipulations with regard to casing and singular/plural rules.", - "homepage": "http://www.doctrine-project.org", + "description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.", + "homepage": "https://www.doctrine-project.org/projects/inflector.html", "keywords": [ "inflection", - "pluralize", - "singularize", - "string" + "inflector", + "lowercase", + "manipulation", + "php", + "plural", + "singular", + "strings", + "uppercase", + "words" ], - "time": "2019-10-30T19:59:35+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector", + "type": "tidelift" + } + ], + "time": "2020-05-11T11:25:59+00:00" }, { "name": "doctrine/lexer", @@ -1406,20 +1430,20 @@ }, { "name": "laravel/framework", - "version": "v6.18.11", + "version": "v6.18.14", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "73bc10bb23aab7539c8ffae6d5dc3c4b277de557" + "reference": "503d1511d6792b0b8d0a4bfed47f7c2f29634e1c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/73bc10bb23aab7539c8ffae6d5dc3c4b277de557", - "reference": "73bc10bb23aab7539c8ffae6d5dc3c4b277de557", + "url": "https://api.github.com/repos/laravel/framework/zipball/503d1511d6792b0b8d0a4bfed47f7c2f29634e1c", + "reference": "503d1511d6792b0b8d0a4bfed47f7c2f29634e1c", "shasum": "" }, "require": { - "doctrine/inflector": "^1.1", + "doctrine/inflector": "^1.4|^2.0", "dragonmantank/cron-expression": "^2.0", "egulias/email-validator": "^2.1.10", "ext-json": "*", @@ -1548,20 +1572,20 @@ "framework", "laravel" ], - "time": "2020-04-28T15:18:58+00:00" + "time": "2020-05-12T14:41:15+00:00" }, { "name": "laravel/passport", - "version": "v8.4.4", + "version": "v8.5.0", "source": { "type": "git", "url": "https://github.com/laravel/passport.git", - "reference": "dd4b1d96eb1fe556a6eb2c55c942360364aa02c1" + "reference": "6affa6ed600c5f8909385fbae7cf6f8af3db2d39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/dd4b1d96eb1fe556a6eb2c55c942360364aa02c1", - "reference": "dd4b1d96eb1fe556a6eb2c55c942360364aa02c1", + "url": "https://api.github.com/repos/laravel/passport/zipball/6affa6ed600c5f8909385fbae7cf6f8af3db2d39", + "reference": "6affa6ed600c5f8909385fbae7cf6f8af3db2d39", "shasum": "" }, "require": { @@ -1621,7 +1645,7 @@ "oauth", "passport" ], - "time": "2020-04-21T19:24:59+00:00" + "time": "2020-05-05T14:25:53+00:00" }, { "name": "laravelcollective/html", @@ -1748,16 +1772,16 @@ }, { "name": "league/commonmark", - "version": "1.4.2", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "9e780d972185e4f737a03bade0fd34a9e67bbf31" + "reference": "412639f7cfbc0b31ad2455b2fe965095f66ae505" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/9e780d972185e4f737a03bade0fd34a9e67bbf31", - "reference": "9e780d972185e4f737a03bade0fd34a9e67bbf31", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/412639f7cfbc0b31ad2455b2fe965095f66ae505", + "reference": "412639f7cfbc0b31ad2455b2fe965095f66ae505", "shasum": "" }, "require": { @@ -1844,7 +1868,7 @@ "type": "tidelift" } ], - "time": "2020-04-24T13:39:56+00:00" + "time": "2020-05-04T22:15:21+00:00" }, { "name": "league/csv", @@ -1969,16 +1993,16 @@ }, { "name": "league/flysystem", - "version": "1.0.67", + "version": "1.0.68", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "5b1f36c75c4bdde981294c2a0ebdb437ee6f275e" + "reference": "3e4198372276ec99ac3409a21d7c9d1ced9026e4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/5b1f36c75c4bdde981294c2a0ebdb437ee6f275e", - "reference": "5b1f36c75c4bdde981294c2a0ebdb437ee6f275e", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/3e4198372276ec99ac3409a21d7c9d1ced9026e4", + "reference": "3e4198372276ec99ac3409a21d7c9d1ced9026e4", "shasum": "" }, "require": { @@ -2049,7 +2073,13 @@ "sftp", "storage" ], - "time": "2020-04-16T13:21:26+00:00" + "funding": [ + { + "url": "https://offset.earth/frankdejonge", + "type": "other" + } + ], + "time": "2020-05-12T20:33:44+00:00" }, { "name": "league/flysystem-replicate-adapter", @@ -2445,16 +2475,16 @@ }, { "name": "nesbot/carbon", - "version": "2.33.0", + "version": "2.34.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "4d93cb95a80d9ffbff4018fe58ae3b7dd7f4b99b" + "reference": "52ea68aebbad8a3b27b5d24e4c66ebe1933f8399" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4d93cb95a80d9ffbff4018fe58ae3b7dd7f4b99b", - "reference": "4d93cb95a80d9ffbff4018fe58ae3b7dd7f4b99b", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/52ea68aebbad8a3b27b5d24e4c66ebe1933f8399", + "reference": "52ea68aebbad8a3b27b5d24e4c66ebe1933f8399", "shasum": "" }, "require": { @@ -2478,7 +2508,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "2.x-dev", + "dev-3.x": "3.x-dev" }, "laravel": { "providers": [ @@ -2523,7 +2554,7 @@ "type": "tidelift" } ], - "time": "2020-04-20T15:05:43+00:00" + "time": "2020-05-12T19:53:34+00:00" }, { "name": "nyholm/psr7", @@ -4503,16 +4534,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", - "reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9", + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9", "shasum": "" }, "require": { @@ -4524,7 +4555,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4571,20 +4602,20 @@ "type": "tidelift" } ], - "time": "2020-02-27T09:26:54+00:00" + "time": "2020-05-12T16:14:59+00:00" }, { "name": "symfony/polyfill-iconv", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-iconv.git", - "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8" + "reference": "c4de7601eefbf25f9d47190abe07f79fe0a27424" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/ad6d62792bfbcfc385dd34b424d4fcf9712a32c8", - "reference": "ad6d62792bfbcfc385dd34b424d4fcf9712a32c8", + "url": "https://api.github.com/repos/symfony/polyfill-iconv/zipball/c4de7601eefbf25f9d47190abe07f79fe0a27424", + "reference": "c4de7601eefbf25f9d47190abe07f79fe0a27424", "shasum": "" }, "require": { @@ -4596,7 +4627,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4644,20 +4675,20 @@ "type": "tidelift" } ], - "time": "2020-03-09T19:04:49+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf" + "reference": "3bff59ea7047e925be6b7f2059d60af31bb46d6a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", - "reference": "47bd6aa45beb1cd7c6a16b7d1810133b728bdfcf", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/3bff59ea7047e925be6b7f2059d60af31bb46d6a", + "reference": "3bff59ea7047e925be6b7f2059d60af31bb46d6a", "shasum": "" }, "require": { @@ -4671,7 +4702,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4720,20 +4751,20 @@ "type": "tidelift" } ], - "time": "2020-03-09T19:04:49+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac" + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/81ffd3a9c6d707be22e3012b827de1c9775fc5ac", - "reference": "81ffd3a9c6d707be22e3012b827de1c9775fc5ac", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c", + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c", "shasum": "" }, "require": { @@ -4745,7 +4776,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4793,20 +4824,20 @@ "type": "tidelift" } ], - "time": "2020-03-09T19:04:49+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-php56", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php56.git", - "reference": "d51ec491c8ddceae7dca8dd6c7e30428f543f37d" + "reference": "e3c8c138280cdfe4b81488441555583aa1984e23" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/d51ec491c8ddceae7dca8dd6c7e30428f543f37d", - "reference": "d51ec491c8ddceae7dca8dd6c7e30428f543f37d", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/e3c8c138280cdfe4b81488441555583aa1984e23", + "reference": "e3c8c138280cdfe4b81488441555583aa1984e23", "shasum": "" }, "require": { @@ -4816,7 +4847,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4863,20 +4894,20 @@ "type": "tidelift" } ], - "time": "2020-03-09T19:04:49+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "37b0976c78b94856543260ce09b460a7bc852747" + "reference": "f048e612a3905f34931127360bdd2def19a5e582" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/37b0976c78b94856543260ce09b460a7bc852747", - "reference": "37b0976c78b94856543260ce09b460a7bc852747", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/f048e612a3905f34931127360bdd2def19a5e582", + "reference": "f048e612a3905f34931127360bdd2def19a5e582", "shasum": "" }, "require": { @@ -4885,7 +4916,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -4932,20 +4963,20 @@ "type": "tidelift" } ], - "time": "2020-02-27T09:26:54+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7" + "reference": "a760d8964ff79ab9bf057613a5808284ec852ccc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", - "reference": "0f27e9f464ea3da33cbe7ca3bdf4eb66def9d0f7", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a760d8964ff79ab9bf057613a5808284ec852ccc", + "reference": "a760d8964ff79ab9bf057613a5808284ec852ccc", "shasum": "" }, "require": { @@ -4954,7 +4985,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -5004,20 +5035,20 @@ "type": "tidelift" } ], - "time": "2020-02-27T09:26:54+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-util", - "version": "v1.15.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-util.git", - "reference": "d8e76c104127675d0ea3df3be0f2ae24a8619027" + "reference": "4afb4110fc037752cf0ce9869f9ab8162c4e20d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/d8e76c104127675d0ea3df3be0f2ae24a8619027", - "reference": "d8e76c104127675d0ea3df3be0f2ae24a8619027", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/4afb4110fc037752cf0ce9869f9ab8162c4e20d7", + "reference": "4afb4110fc037752cf0ce9869f9ab8162c4e20d7", "shasum": "" }, "require": { @@ -5026,7 +5057,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.15-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -5070,7 +5101,7 @@ "type": "tidelift" } ], - "time": "2020-03-02T11:55:35+00:00" + "time": "2020-05-12T16:14:59+00:00" }, { "name": "symfony/process", @@ -5586,16 +5617,16 @@ }, { "name": "tightenco/collect", - "version": "v7.9.2", + "version": "v7.11.0", "source": { "type": "git", "url": "https://github.com/tightenco/collect.git", - "reference": "372230e88129364638d2d9809143fafbb993d7d4" + "reference": "ba504e959241f1f408867ffd03159b040f66e00b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tightenco/collect/zipball/372230e88129364638d2d9809143fafbb993d7d4", - "reference": "372230e88129364638d2d9809143fafbb993d7d4", + "url": "https://api.github.com/repos/tightenco/collect/zipball/ba504e959241f1f408867ffd03159b040f66e00b", + "reference": "ba504e959241f1f408867ffd03159b040f66e00b", "shasum": "" }, "require": { @@ -5632,7 +5663,7 @@ "collection", "laravel" ], - "time": "2020-04-29T16:33:30+00:00" + "time": "2020-05-08T22:25:37+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -6160,16 +6191,16 @@ }, { "name": "composer/composer", - "version": "1.10.5", + "version": "1.10.6", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "7a4d5b6aa30d2118af27c04f5e897b57156ccfa9" + "reference": "be81b9c4735362c26876bdbfd3b5bc7e7f711c88" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/7a4d5b6aa30d2118af27c04f5e897b57156ccfa9", - "reference": "7a4d5b6aa30d2118af27c04f5e897b57156ccfa9", + "url": "https://api.github.com/repos/composer/composer/zipball/be81b9c4735362c26876bdbfd3b5bc7e7f711c88", + "reference": "be81b9c4735362c26876bdbfd3b5bc7e7f711c88", "shasum": "" }, "require": { @@ -6188,7 +6219,8 @@ "symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0" }, "conflict": { - "symfony/console": "2.8.38" + "symfony/console": "2.8.38", + "symfony/phpunit-bridge": "3.4.40" }, "require-dev": { "phpspec/prophecy": "^1.10", @@ -6246,7 +6278,7 @@ "type": "tidelift" } ], - "time": "2020-04-10T09:44:22+00:00" + "time": "2020-05-06T08:28:10+00:00" }, { "name": "composer/semver", @@ -6565,16 +6597,16 @@ }, { "name": "filp/whoops", - "version": "2.7.1", + "version": "2.7.2", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "fff6f1e4f36be0e0d0b84d66b413d9dcb0c49130" + "reference": "17d0d3f266c8f925ebd035cd36f83cf802b47d4a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/fff6f1e4f36be0e0d0b84d66b413d9dcb0c49130", - "reference": "fff6f1e4f36be0e0d0b84d66b413d9dcb0c49130", + "url": "https://api.github.com/repos/filp/whoops/zipball/17d0d3f266c8f925ebd035cd36f83cf802b47d4a", + "reference": "17d0d3f266c8f925ebd035cd36f83cf802b47d4a", "shasum": "" }, "require": { @@ -6622,7 +6654,7 @@ "throwable", "whoops" ], - "time": "2020-01-15T10:00:00+00:00" + "time": "2020-05-05T12:28:07+00:00" }, { "name": "fzaninotto/faker", @@ -7952,16 +7984,16 @@ }, { "name": "psalm/plugin-laravel", - "version": "1.2.0", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/psalm/psalm-plugin-laravel.git", - "reference": "31b48d7f5863f1b935f65daaea3b9472b4390608" + "reference": "db2f1a2769e383f820eb5e38dd4a0d58fdba069d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/psalm/psalm-plugin-laravel/zipball/31b48d7f5863f1b935f65daaea3b9472b4390608", - "reference": "31b48d7f5863f1b935f65daaea3b9472b4390608", + "url": "https://api.github.com/repos/psalm/psalm-plugin-laravel/zipball/db2f1a2769e383f820eb5e38dd4a0d58fdba069d", + "reference": "db2f1a2769e383f820eb5e38dd4a0d58fdba069d", "shasum": "" }, "require": { @@ -7974,7 +8006,7 @@ "illuminate/support": "5.8.* || ^6.0 || ^7.0", "orchestra/testbench": "^3.8 || ^4.0 || ^5.0", "php": "^7.1.3|^8", - "vimeo/psalm": "^3.8.2" + "vimeo/psalm": "^3.8.2 || dev-master" }, "require-dev": { "codeception/codeception": "^4.1", @@ -7982,7 +8014,7 @@ "codeception/module-phpbrowser": "^1.0.0", "slevomat/coding-standard": "^6.2", "squizlabs/php_codesniffer": "*", - "weirdan/codeception-psalm-module": "^0.5.0" + "weirdan/codeception-psalm-module": "^0.7.1" }, "type": "psalm-plugin", "extra": { @@ -8006,7 +8038,7 @@ } ], "description": "A Laravel plugin for Psalm", - "time": "2020-04-21T12:52:20+00:00" + "time": "2020-05-12T05:52:51+00:00" }, { "name": "roave/security-advisories", @@ -8014,12 +8046,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "478dd17a48d0eb007ff854f4b885034df5db7c29" + "reference": "885e8b1e0bc2096989fd20938342e407e8045186" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/478dd17a48d0eb007ff854f4b885034df5db7c29", - "reference": "478dd17a48d0eb007ff854f4b885034df5db7c29", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/885e8b1e0bc2096989fd20938342e407e8045186", + "reference": "885e8b1e0bc2096989fd20938342e407e8045186", "shasum": "" }, "conflict": { @@ -8032,6 +8064,8 @@ "asymmetricrypt/asymmetricrypt": ">=0,<9.9.99", "aws/aws-sdk-php": ">=3,<3.2.1", "bagisto/bagisto": "<0.1.5", + "barrelstrength/sprout-base-email": "<1.2.7", + "barrelstrength/sprout-forms": "<3.9", "bolt/bolt": "<3.6.10", "brightlocal/phpwhois": "<=4.2.5", "buddypress/buddypress": "<5.1.2", @@ -8109,7 +8143,7 @@ "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", "monolog/monolog": ">=1.8,<1.12", "namshi/jose": "<2.2", - "nzo/url-encryptor-bundle": "<5.0.1", + "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", "onelogin/php-saml": "<2.10.4", "oneup/uploader-bundle": "<1.9.3|>=2,<2.1.5", "openid/php-openid": "<2.3", @@ -8164,7 +8198,7 @@ "socalnick/scn-social-auth": "<1.15.2", "spoonity/tcpdf": "<6.2.22", "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", - "ssddanbrown/bookstack": "<0.25.3", + "ssddanbrown/bookstack": "<0.29.2", "stormpath/sdk": ">=0,<9.9.99", "studio-42/elfinder": "<2.1.49", "swiftmailer/swiftmailer": ">=4,<5.4.5", @@ -8202,6 +8236,7 @@ "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", + "t3g/svg-sanitizer": "<1.0.3", "tecnickcom/tcpdf": "<6.2.22", "thelia/backoffice-default-template": ">=2.1,<2.1.2", "thelia/thelia": ">=2.1-beta.1,<2.1.3", @@ -8209,8 +8244,8 @@ "titon/framework": ">=0,<9.9.99", "truckersmp/phpwhois": "<=4.3.1", "twig/twig": "<1.38|>=2,<2.7", - "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.30|>=9,<9.5.12|>=10,<10.2.1", - "typo3/cms-core": ">=8,<8.7.30|>=9,<9.5.12|>=10,<10.2.1", + "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.30|>=9,<9.5.17|>=10,<10.4.2", + "typo3/cms-core": ">=8,<8.7.30|>=9,<9.5.17|>=10,<10.4.2", "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5", "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4", "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", @@ -8283,7 +8318,7 @@ "type": "tidelift" } ], - "time": "2020-05-03T18:57:18+00:00" + "time": "2020-05-16T00:00:31+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -9109,16 +9144,16 @@ }, { "name": "vimeo/psalm", - "version": "3.11.2", + "version": "3.11.4", "source": { "type": "git", "url": "https://github.com/vimeo/psalm.git", - "reference": "d470903722cfcbc1cd04744c5491d3e6d13ec3d9" + "reference": "58e1d8e68e5098bf4fbfdfb420c38d563f882549" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/vimeo/psalm/zipball/d470903722cfcbc1cd04744c5491d3e6d13ec3d9", - "reference": "d470903722cfcbc1cd04744c5491d3e6d13ec3d9", + "url": "https://api.github.com/repos/vimeo/psalm/zipball/58e1d8e68e5098bf4fbfdfb420c38d563f882549", + "reference": "58e1d8e68e5098bf4fbfdfb420c38d563f882549", "shasum": "" }, "require": { @@ -9203,7 +9238,7 @@ "inspection", "php" ], - "time": "2020-04-13T12:47:11+00:00" + "time": "2020-05-11T13:39:25+00:00" }, { "name": "webmozart/assert", diff --git a/config/firefly.php b/config/firefly.php index a33661b0b6..9d7f3ab02a 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -66,6 +66,7 @@ use FireflyIII\TransactionRules\Actions\ClearNotes; use FireflyIII\TransactionRules\Actions\ConvertToDeposit; use FireflyIII\TransactionRules\Actions\ConvertToTransfer; use FireflyIII\TransactionRules\Actions\ConvertToWithdrawal; +use FireflyIII\TransactionRules\Actions\DeleteTransaction; use FireflyIII\TransactionRules\Actions\LinkToBill; use FireflyIII\TransactionRules\Actions\PrependDescription; use FireflyIII\TransactionRules\Actions\PrependNotes; @@ -77,12 +78,16 @@ use FireflyIII\TransactionRules\Actions\SetDescription; use FireflyIII\TransactionRules\Actions\SetDestinationAccount; use FireflyIII\TransactionRules\Actions\SetNotes; use FireflyIII\TransactionRules\Actions\SetSourceAccount; +use FireflyIII\TransactionRules\Actions\UpdatePiggybank; use FireflyIII\TransactionRules\Triggers\AmountExactly; use FireflyIII\TransactionRules\Triggers\AmountLess; use FireflyIII\TransactionRules\Triggers\AmountMore; use FireflyIII\TransactionRules\Triggers\BudgetIs; use FireflyIII\TransactionRules\Triggers\CategoryIs; use FireflyIII\TransactionRules\Triggers\CurrencyIs; +use FireflyIII\TransactionRules\Triggers\DateIs; +use FireflyIII\TransactionRules\Triggers\DateBefore; +use FireflyIII\TransactionRules\Triggers\DateAfter; use FireflyIII\TransactionRules\Triggers\DescriptionContains; use FireflyIII\TransactionRules\Triggers\DescriptionEnds; use FireflyIII\TransactionRules\Triggers\DescriptionIs; @@ -466,6 +471,9 @@ return [ 'description_ends' => DescriptionEnds::class, 'description_contains' => DescriptionContains::class, 'description_is' => DescriptionIs::class, + 'date_is' => DateIs::class, + 'date_before' => DateBefore::class, + 'date_after' => DateAfter::class, 'transaction_type' => TransactionType::class, 'category_is' => CategoryIs::class, 'budget_is' => BudgetIs::class, @@ -506,6 +514,8 @@ return [ 'convert_withdrawal' => ConvertToWithdrawal::class, 'convert_deposit' => ConvertToDeposit::class, 'convert_transfer' => ConvertToTransfer::class, + 'update_piggy' => UpdatePiggybank::class, + 'delete_transaction' => DeleteTransaction::class, ], 'context-rule-actions' => [ 'set_category', @@ -550,6 +560,9 @@ return [ 'notes_start', 'notes_end', 'notes_are', + 'date_is', + 'date_before', + 'date_after', ], 'test-triggers' => [ diff --git a/config/import.php b/config/import.php index 0959ed2bdd..21f5d74422 100644 --- a/config/import.php +++ b/config/import.php @@ -47,11 +47,11 @@ return [ 'file' => false, 'bunq' => false, 'spectre' => true, - 'ynab' => true, + 'ynab' => false, 'plaid' => false, 'quovo' => false, 'yodlee' => false, - 'fints' => true, + 'fints' => false, 'bad' => false, // always disabled ], // demo user can use these import providers (when enabled): diff --git a/public/v1/js/create_transaction.js b/public/v1/js/create_transaction.js index fe2333de97..c48a2e0d53 100644 --- a/public/v1/js/create_transaction.js +++ b/public/v1/js/create_transaction.js @@ -8471,4 +8471,4 @@ module.exports = __webpack_require__(/*! C:\Users\Florian\github\firefly-iii\res /***/ }) -/******/ }); \ No newline at end of file +/******/ }); diff --git a/public/v1/js/edit_transaction.js b/public/v1/js/edit_transaction.js index 7c2cea7709..d21bda57f3 100644 --- a/public/v1/js/edit_transaction.js +++ b/public/v1/js/edit_transaction.js @@ -8531,4 +8531,4 @@ module.exports = __webpack_require__(/*! C:\Users\Florian\github\firefly-iii\res /***/ }) -/******/ }); \ No newline at end of file +/******/ }); diff --git a/public/v1/js/ff/accounts/reconcile.js b/public/v1/js/ff/accounts/reconcile.js index 3cd50df687..45aafed7ed 100644 --- a/public/v1/js/ff/accounts/reconcile.js +++ b/public/v1/js/ff/accounts/reconcile.js @@ -71,6 +71,44 @@ $(function () { }); +function selectAllReconcile(e) { + // loop all, check. + var el = $(e.target); + var doCheck = true; + if (el.prop('checked') === true) { + $('.check_all_btn').prop('checked', true); + } + if (el.prop('checked') === false) { + $('.check_all_btn').prop('checked', false); + doCheck = false; + } + + $('.reconcile_checkbox').each(function (i, v) { + var check = $(v); + var amount = parseFloat(check.val()); + var journalId = parseInt(check.data('id')); + var identifier = 'checked_' + journalId; + console.log('in selectAllReconcile(' + journalId + ') with amount ' + amount + ' and selected amount ' + selectedAmount); + + check.prop('checked', doCheck); + // if checked, add to selected amount + if (doCheck === true && check.data('younger') === false) { + selectedAmount = selectedAmount - amount; + console.log('checked = true and younger = false so selected amount = ' + selectedAmount); + localStorage.setItem(identifier, 'true'); + } + if (doCheck === false && check.data('younger') === false) { + selectedAmount = selectedAmount + amount; + console.log('checked = false and younger = false so selected amount = ' + selectedAmount); + localStorage.setItem(identifier, 'false'); + } + difference = balanceDifference - selectedAmount; + console.log('Difference is now ' + difference); + }); + + updateDifference(); +} + function storeReconcile() { console.log('in storeReconcile()'); // get modal HTML: @@ -116,15 +154,19 @@ function checkReconciledBox(e) { var el = $(e.target); var amount = parseFloat(el.val()); - console.log('in checkReconciledBox() with amount ' + amount + ' and selected amount ' + selectedAmount); + var journalId = parseInt(el.data('id')); + var identifier = 'checked_' + journalId; + console.log('in checkReconciledBox(' + journalId + ') with amount ' + amount + ' and selected amount ' + selectedAmount); // if checked, add to selected amount if (el.prop('checked') === true && el.data('younger') === false) { selectedAmount = selectedAmount - amount; console.log('checked = true and younger = false so selected amount = ' + selectedAmount); + localStorage.setItem(identifier, 'true'); } if (el.prop('checked') === false && el.data('younger') === false) { selectedAmount = selectedAmount + amount; console.log('checked = false and younger = false so selected amount = ' + selectedAmount); + localStorage.setItem(identifier, 'false'); } difference = balanceDifference - selectedAmount; console.log('Difference is now ' + difference); @@ -198,6 +240,10 @@ function includeClearedTransactions() { function placeTransactions(data) { console.log('in placeTransactions()'); $('#transactions_holder').empty().html(data.html); + + // add checkbox thing + $('.check_all_btn').click(selectAllReconcile); + selectedAmount = 0; // update start + end balance when user has not touched them. if (!changedBalances) { @@ -214,6 +260,10 @@ function placeTransactions(data) { difference = balanceDifference - selectedAmount; updateDifference(); + // loop al placed checkboxes and check them if necessary. + restoreFromLocalStorage(); + + // enable the check buttons: $('.reconcile_checkbox').prop('disabled', false).unbind('change').change(checkReconciledBox); @@ -223,6 +273,30 @@ function placeTransactions(data) { $('.store_reconcile').prop('disabled', false); } +function restoreFromLocalStorage() { + $('.reconcile_checkbox').each(function (i, v) { + var el = $(v); + var journalId = el.data('id') + var identifier = 'checked_' + journalId; + var amount = parseFloat(el.val()); + if (localStorage.getItem(identifier) === 'true') { + el.prop('checked', true); + // do balance thing: + console.log('in restoreFromLocalStorage(' + journalId + ') with amount ' + amount + ' and selected amount ' + selectedAmount); + // if checked, add to selected amount + if (el.data('younger') === false) { + selectedAmount = selectedAmount - amount; + console.log('checked = true and younger = false so selected amount = ' + selectedAmount); + localStorage.setItem(identifier, 'true'); + } + difference = balanceDifference - selectedAmount; + console.log('Difference is now ' + difference); + } + + }); + updateDifference(); +} + /** * * @returns {boolean} @@ -259,4 +333,4 @@ function updateDifference() { addClass = 'text-danger'; } $('#difference').addClass(addClass).text(accounting.formatMoney(difference)); -} \ No newline at end of file +} diff --git a/public/v1/js/ff/rules/create-edit.js b/public/v1/js/ff/rules/create-edit.js index 4a39675c43..69d0b95a97 100644 --- a/public/v1/js/ff/rules/create-edit.js +++ b/public/v1/js/ff/rules/create-edit.js @@ -233,6 +233,7 @@ function updateActionInput(selectList) { case 'clear_category': case 'clear_budget': case 'clear_notes': + case 'delete_transaction': case 'remove_all_tags': console.log('Select list value is ' + selectList.val() + ', so input needs to be disabled.'); inputResult.attr('disabled', 'disabled'); @@ -274,6 +275,10 @@ function updateActionInput(selectList) { console.log('Select list value is ' + selectList.val() + ', so input needs auto complete.'); createAutoComplete(inputResult, 'json/bills'); break; + case 'update_piggy': + console.log('Select list value is ' + selectList.val() + ', so input needs auto complete.'); + createAutoComplete(inputResult, 'json/piggy-banks'); + break; default: console.log('Select list value is ' + selectList.val() + ', destroy auto complete, do nothing else.'); inputResult.typeahead('destroy'); diff --git a/resources/assets/js/components/transactions/CreateTransaction.vue b/resources/assets/js/components/transactions/CreateTransaction.vue index 2c7318276a..33e1d45d8e 100644 --- a/resources/assets/js/components/transactions/CreateTransaction.vue +++ b/resources/assets/js/components/transactions/CreateTransaction.vue @@ -598,7 +598,18 @@ // console.log('Upload complete!'); return false; }); - }); + }).catch(error => { + console.error('Could not create upload.'); + console.error(error); + uploads++; + if (uploads === count) { + // finally we can redirect the user onwards. + // console.log('FINAL UPLOAD'); + this.redirectUser(groupId, transactionData); + } + // console.log('Upload complete!'); + return false; + }); } } diff --git a/resources/assets/js/components/transactions/EditTransaction.vue b/resources/assets/js/components/transactions/EditTransaction.vue index 70ba0d79ed..6ce93126b6 100644 --- a/resources/assets/js/components/transactions/EditTransaction.vue +++ b/resources/assets/js/components/transactions/EditTransaction.vue @@ -773,7 +773,18 @@ // console.error(error); return false; }); - }); + }).catch(error => { + console.error('Could not create upload.'); + console.error(error); + uploads++; + if (uploads === count) { + // finally we can redirect the user onwards. + // console.log('FINAL UPLOAD'); + this.redirectUser(groupId, null); + } + // console.log('Upload complete!'); + return false; + }); } } diff --git a/resources/lang/cs_CZ/firefly.php b/resources/lang/cs_CZ/firefly.php index dd5819ebbf..37cb8c7312 100644 --- a/resources/lang/cs_CZ/firefly.php +++ b/resources/lang/cs_CZ/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Vytvořit novou věc', 'new_withdrawal' => 'Nový výběr', 'create_new_transaction' => 'Přidat novou transakci', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Nová transakce', 'no_rules_for_bill' => 'Tento účet nemá přiřazena žádná pravidla.', 'go_to_asset_accounts' => 'Zobrazit účty s aktivy', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Zapomenuté heslo do Firefly III', 'reset_pw_page_title' => 'Reset hesla do Firefly III', 'cannot_reset_demo_user' => 'Heslo uživatele pro ukázku (demo) nelze resetovat.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Zaregistrovat se', 'authorization' => 'Pověření', 'active_bills_only' => 'pouze aktivní účty', 'active_exp_bills_only' => 'pouze aktivní a očekávané účty', 'average_per_bill' => 'průměr na účet', 'expected_total' => 'očekávaný celkový součet', - 'reconciliation_account_name' => ':name reconciliation', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Požadavek na ověření – Firefly III verze :version', 'authorization_request_intro' => ':client žádá oprávnění pro přístup k vaší finanční správě. Chcete autorizovat :client pro přístup k těmto záznamům?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Odebrat štítek…', 'rule_action_remove_all_tags_choice' => 'Odebrat veškeré štítky', 'rule_action_set_description_choice' => 'Nastavit popis na…', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Připojit k popisu…', 'rule_action_prepend_description_choice' => 'Přidat před popis…', 'rule_action_set_source_account_choice' => 'Nastavit zdrojový účet na…', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Reconciliation (:from to :to)', 'sum_of_reconciliation' => 'Sum of reconciliation', 'reconcile_this_account' => 'Vyúčtovat tento účet', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Potvrdit vyúčtování', 'submitted_start_balance' => 'Předložený počáteční zůstatek', 'selected_transactions' => 'Vybrané transakce (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Opakované transakce', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Kalendář', 'no_recurring_title_default' => 'Pojďme vytvořit opakující se transakci!', 'no_recurring_intro_default' => 'You have no recurring transactions yet. You can use these to make Firefly III automatically create transactions for you.', diff --git a/resources/lang/de_DE/firefly.php b/resources/lang/de_DE/firefly.php index f62956847f..1fd969a7e5 100644 --- a/resources/lang/de_DE/firefly.php +++ b/resources/lang/de_DE/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Erstelle neue Dinge', 'new_withdrawal' => 'Neue Ausgabe', 'create_new_transaction' => 'Neue Buchung erstellen', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Neue Buchung', 'no_rules_for_bill' => 'Diese Rechnung enthält keine mit ihr verbundenen Regeln.', 'go_to_asset_accounts' => 'Bestandskonten anzeigen', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Haben Sie Ihr Passwort für Firefly III vergessen?', 'reset_pw_page_title' => 'Passwort für Firefly III zurücksetzen', 'cannot_reset_demo_user' => 'Sie können das Passwort des Demo-Benutzers nicht zurücksetzen.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Registrieren', 'authorization' => 'Autorisierung', 'active_bills_only' => 'Nur aktive Rechnungen', 'active_exp_bills_only' => 'nur aktive und erwartete Rechnungen', 'average_per_bill' => 'Durchschnitt je Rechnung', 'expected_total' => 'Voraussichtliche Summe', - 'reconciliation_account_name' => ':name Kontenabgleich', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version Autorisierungsanfrage', 'authorization_request_intro' => ':client bittet um Erlaubnis, auf Ihre Finanzverwaltung zuzugreifen. Möchten Sie :client erlauben auf diese Datensätze zuzugreifen?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Schlagwort entfernen …', 'rule_action_remove_all_tags_choice' => 'Alle Schlagwörter entfernen', 'rule_action_set_description_choice' => 'Beschreibung festlegen auf..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'An Beschreibung anhängen..', 'rule_action_prepend_description_choice' => 'Vor Beschreibung voranstellen..', 'rule_action_set_source_account_choice' => 'Lege Quellkonto fest...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Ausgleich (:from zu :to)', 'sum_of_reconciliation' => 'Summe der Überleitungsrechnung', 'reconcile_this_account' => 'Dieses Konto abgleichen', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Kontenabgleich bestätigen', 'submitted_start_balance' => 'Übermitteltes Startguthaben', 'selected_transactions' => 'Ausgewählte Umsätze (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Regelmäßige Buchungen', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Kalender', 'no_recurring_title_default' => 'Lassen Sie uns eine regelmäßige Buchung erstellen!', 'no_recurring_intro_default' => 'Sie verfügen noch über keine regelmäßigen Buchungen. Mit diesen können Sie Firefly III dazu einsetzen, automatisch Buchungen für Sie zu erstellen.', diff --git a/resources/lang/de_DE/list.php b/resources/lang/de_DE/list.php index 46da230b9a..81b2165caf 100644 --- a/resources/lang/de_DE/list.php +++ b/resources/lang/de_DE/list.php @@ -77,7 +77,7 @@ return [ 'type' => 'Typ', 'completed' => 'Abgeschlossen', 'iban' => 'IBAN', - 'paid_current_period' => 'Diese Periode bezahlt', + 'paid_current_period' => 'Diesen Zeitraum bezahlt', 'email' => 'E-Mail', 'registered_at' => 'Registriert am', 'is_blocked' => 'Ist blockiert', diff --git a/resources/lang/el_GR/firefly.php b/resources/lang/el_GR/firefly.php index bb8106a89c..00ad437f46 100644 --- a/resources/lang/el_GR/firefly.php +++ b/resources/lang/el_GR/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Νέα καταχώρηση', 'new_withdrawal' => 'Νέα ανάληψη', 'create_new_transaction' => 'Δημιουργία νέας συναλλαγής', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Νέα συναλλαγή', 'no_rules_for_bill' => 'Αυτό το πάγιο έξοδο δεν έχει σχετιζόμενους κανόνες.', 'go_to_asset_accounts' => 'Δείτε τους λογαριασμούς κεφαλαίου σας', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Ξεχάσατε τον κωδικό πρόσβασης για το Firefly III', 'reset_pw_page_title' => 'Επαναφέρετε τον κωδικό πρόσβασης για το Firefly III', 'cannot_reset_demo_user' => 'Δε μπορείτε να επαναφέρετε τον κωδικό πρόσβασης του χρήστη επίδειξης.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Εγγραφή', 'authorization' => 'Εξουσιοδότηση', 'active_bills_only' => 'μόνο ενεργά πάγια έξοδα', 'active_exp_bills_only' => 'ενεργοί και αναμενόμενοι λογαριασμοί μόνο', 'average_per_bill' => 'μέσος όρος ανά πάγιο έξοδο', 'expected_total' => 'αναμενόμενο σύνολο', - 'reconciliation_account_name' => 'τακτοποίηση :name', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Αίτημα Εξουσιοδότησης Firefly III v:version', 'authorization_request_intro' => 'Ο :client αιτείται άδεια πρόσβασης στην οικονομική σας διαχείριση. Θέλετε να εξουσιοδοτήσετε τον :client ώστε να έχει πρόσβαση σε αυτές τις εγγραφές;', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Αφαίρεση ετικέτας..', 'rule_action_remove_all_tags_choice' => 'Αφαίρεση όλων των ετικετών', 'rule_action_set_description_choice' => 'Ορισμός της περιγραφής σε..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Προσάρτηση περιγραφής με..', 'rule_action_prepend_description_choice' => 'Προεπιλογή περιγραφής με..', 'rule_action_set_source_account_choice' => 'Ορισμός του λογαριασμού προέλευσης σε...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Τακτοποίηση (:from σε :to)', 'sum_of_reconciliation' => 'Άθροισμα της τακτοποίησης', 'reconcile_this_account' => 'Τακτοποίηση αυτού του λογαριασμού', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Επιβεβαίωση τακτοποίησης', 'submitted_start_balance' => 'Υποβλήθηκε το αρχικό υπόλοιπο', 'selected_transactions' => 'Επιλεγμένες συναλλαγές (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Επαναλαμβανόμενες συναλλαγές', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Ημερολόγιο', 'no_recurring_title_default' => 'Ας δημιουργήσουμε μια επαναλαμβανόμενη συναλλαγή!', 'no_recurring_intro_default' => 'Δεν έχετε ακόμα επαναλαμβανόμενες συναλλαγές. Μπορείτε να τις χρησιμοποιήσετε για να κάνετε το Firefly III να δημιουργεί αυτόματα συναλλαγές για εσάς.', diff --git a/resources/lang/en_GB/firefly.php b/resources/lang/en_GB/firefly.php index 8dd0acf104..708b21542e 100644 --- a/resources/lang/en_GB/firefly.php +++ b/resources/lang/en_GB/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Create new stuff', 'new_withdrawal' => 'New withdrawal', 'create_new_transaction' => 'Create new transaction', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'New transaction', 'no_rules_for_bill' => 'This bill has no rules associated to it.', 'go_to_asset_accounts' => 'View your asset accounts', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Forgot your password for Firefly III', 'reset_pw_page_title' => 'Reset your password for Firefly III', 'cannot_reset_demo_user' => 'You cannot reset the password of the demo user.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Register', 'authorization' => 'Authorisation', 'active_bills_only' => 'active bills only', 'active_exp_bills_only' => 'active and expected bills only', 'average_per_bill' => 'average per bill', 'expected_total' => 'expected total', - 'reconciliation_account_name' => ':name reconciliation', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version Authorisation Request', 'authorization_request_intro' => ':client is requesting permission to access your financial administration. Would you like to authorise :client to access these records?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Remove tag..', 'rule_action_remove_all_tags_choice' => 'Remove all tags', 'rule_action_set_description_choice' => 'Set description to..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Append description with..', 'rule_action_prepend_description_choice' => 'Prepend description with..', 'rule_action_set_source_account_choice' => 'Set source account to...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Reconciliation (:from to :to)', 'sum_of_reconciliation' => 'Sum of reconciliation', 'reconcile_this_account' => 'Reconcile this account', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Confirm reconciliation', 'submitted_start_balance' => 'Submitted start balance', 'selected_transactions' => 'Selected transactions (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Recurring transactions', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Calendar', 'no_recurring_title_default' => 'Let\'s create a recurring transaction!', 'no_recurring_intro_default' => 'You have no recurring transactions yet. You can use these to make Firefly III automatically create transactions for you.', diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index 2707ff6e11..8ce6d58ee1 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Create new stuff', 'new_withdrawal' => 'New withdrawal', 'create_new_transaction' => 'Create new transaction', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'New transaction', 'no_rules_for_bill' => 'This bill has no rules associated to it.', 'go_to_asset_accounts' => 'View your asset accounts', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Forgot your password for Firefly III', 'reset_pw_page_title' => 'Reset your password for Firefly III', 'cannot_reset_demo_user' => 'You cannot reset the password of the demo user.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Register', 'authorization' => 'Authorization', 'active_bills_only' => 'active bills only', 'active_exp_bills_only' => 'active and expected bills only', 'average_per_bill' => 'average per bill', 'expected_total' => 'expected total', - 'reconciliation_account_name' => ':name reconciliation', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version Authorization Request', 'authorization_request_intro' => ':client is requesting permission to access your financial administration. Would you like to authorize :client to access these records?', @@ -419,6 +421,14 @@ return [ 'rule_trigger_description_contains' => 'Description contains ":trigger_value"', 'rule_trigger_description_is_choice' => 'Description is..', 'rule_trigger_description_is' => 'Description is ":trigger_value"', + + 'rule_trigger_date_is_choice' => 'Transaction date is..', + 'rule_trigger_date_is' => 'Transaction date is ":trigger_value"', + 'rule_trigger_date_before_choice' => 'Transaction date is before..', + 'rule_trigger_date_before' => 'Transaction date is before ":trigger_value"', + 'rule_trigger_date_after_choice' => 'Transaction date is after..', + 'rule_trigger_date_after' => 'Transaction date is after ":trigger_value"', + 'rule_trigger_budget_is_choice' => 'Budget is..', 'rule_trigger_budget_is' => 'Budget is ":trigger_value"', 'rule_trigger_tag_is_choice' => '(A) tag is..', @@ -453,6 +463,8 @@ return [ 'rule_trigger_notes_start' => 'Notes start with ":trigger_value"', 'rule_trigger_notes_end_choice' => 'Notes end with..', 'rule_trigger_notes_end' => 'Notes end with ":trigger_value"', + 'rule_action_delete_transaction_choice' => 'DELETE transaction (!)', + 'rule_action_delete_transaction' => 'DELETE transaction (!)', 'rule_action_set_category' => 'Set category to ":action_value"', 'rule_action_clear_category' => 'Clear category', 'rule_action_set_budget' => 'Set budget to ":action_value"', @@ -471,6 +483,8 @@ return [ 'rule_action_remove_tag_choice' => 'Remove tag..', 'rule_action_remove_all_tags_choice' => 'Remove all tags', 'rule_action_set_description_choice' => 'Set description to..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Append description with..', 'rule_action_prepend_description_choice' => 'Prepend description with..', 'rule_action_set_source_account_choice' => 'Set source account to...', @@ -925,6 +939,8 @@ return [ 'reconciliation_transaction_title' => 'Reconciliation (:from to :to)', 'sum_of_reconciliation' => 'Sum of reconciliation', 'reconcile_this_account' => 'Reconcile this account', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Confirm reconciliation', 'submitted_start_balance' => 'Submitted start balance', 'selected_transactions' => 'Selected transactions (:count)', @@ -1519,6 +1535,7 @@ return [ // recurring transactions 'recurrences' => 'Recurring transactions', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Calendar', 'no_recurring_title_default' => 'Let\'s create a recurring transaction!', 'no_recurring_intro_default' => 'You have no recurring transactions yet. You can use these to make Firefly III automatically create transactions for you.', @@ -1617,6 +1634,7 @@ return [ 'not_yet_submitted' => 'Not yet submitted', 'telemetry_type_feature' => 'Feature flag', 'telemetry_submit_all' => 'Submit records', + 'telemetry_type_recurring' => 'Recurring', 'telemetry_delete_submitted_records' => 'Delete submitted records', 'telemetry_submission_executed' => 'Records have been submitted. Check your log files for more info.', 'telemetry_all_deleted' => 'All telemetry records have been deleted.', diff --git a/resources/lang/es_ES/firefly.php b/resources/lang/es_ES/firefly.php index 12f2b9d723..f9e6c7849f 100644 --- a/resources/lang/es_ES/firefly.php +++ b/resources/lang/es_ES/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Crear nueva etiqueta', 'new_withdrawal' => 'Nuevo retiro', 'create_new_transaction' => 'Crear una nueva transacción', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Nueva transacción', 'no_rules_for_bill' => 'Esta factura no tiene reglas asociadas a ella.', 'go_to_asset_accounts' => 'Ver tus cuentas de activos', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Olvidó su contraseña para Firefly III', 'reset_pw_page_title' => 'Restablecer contraseña para Firefly III', 'cannot_reset_demo_user' => 'No puedes restablecer la contraseña del usuario demo.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Registrarse', 'authorization' => 'Autorización', 'active_bills_only' => 'sólo facturas activas', 'active_exp_bills_only' => 'sólo facturas activas y esperadas', 'average_per_bill' => 'promedio por cuenta', 'expected_total' => 'total esperado', - 'reconciliation_account_name' => 'Reconciliación :name', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version Solicitud de autorización', 'authorization_request_intro' => ':client está solicitando permiso para acceder a su administración financiera. ¿Desea autorizar a :client para acceder a estos registros?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Eliminar etiqueta..', 'rule_action_remove_all_tags_choice' => 'Eliminar todas las etiquetas', 'rule_action_set_description_choice' => 'Establecer descripción para..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Adjuntar descripción con..', 'rule_action_prepend_description_choice' => 'Anteponer descripción con..', 'rule_action_set_source_account_choice' => 'Configurar cuenta de origen para...', @@ -540,9 +544,9 @@ return [ 'pref_languages' => 'Idiomas', 'pref_locale' => 'Configuración del idioma', 'pref_languages_help' => 'Firefly III apoya varios idiomas. cual usted prefiere?', - 'pref_locale_help' => 'Firefly III allows you to set other local settings, like how currencies, numbers and dates are formatted. Entries in this list may not be supported by your system. Firefly III doesn\'t have the correct date settings for every locale; contact me for improvements.', - 'pref_locale_no_windows' => 'This feature may not work on Windows.', - 'pref_locale_no_docker' => 'The Docker image only has a small set of installed locales.', + 'pref_locale_help' => 'Firefly III le permite configurar otros ajustes locales, como cómo se da formato a las monedas, números y fechas. Las entradas en esta lista pueden no ser soportadas por su sistema. Firefly III no tiene los ajustes de fecha correctos para cada local; póngase en contacto conmigo para obtener mejoras.', + 'pref_locale_no_windows' => 'Esta característica puede no funcionar en Windows.', + 'pref_locale_no_docker' => 'La imagen de Docker sólo tiene un pequeño conjunto de locales instalados.', 'pref_custom_fiscal_year' => 'Configuraciónes del año fiscal', 'pref_custom_fiscal_year_label' => 'Habilitado', 'pref_custom_fiscal_year_help' => 'En países que utilizan año fiscal diferente del 1 al 31 de diciembre, usted puede cambiarlo y especificar los días de inicio / y termino del año fiscal', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Reconciliación (:from a :to)', 'sum_of_reconciliation' => 'Suma de reconciliación', 'reconcile_this_account' => 'Reconciliar esta cuenta', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Confirmar la reconciliacion', 'submitted_start_balance' => 'Balance final enviado', 'selected_transactions' => 'Transacciones seleccionadas (:count)', @@ -1132,11 +1138,11 @@ return [ 'interest_period_help' => 'Este campo es meramente cosmético y no se calculará para usted. Como resulta que los bancos son muy estrepitosos, por lo que Firefly III nunca lo hace bien.', 'store_new_liabilities_account' => 'Crear nuevo pasivo', 'edit_liabilities_account' => 'Editar pasivo ":name"', - 'financial_control' => 'Financial control', - 'accounting' => 'Accounting', - 'automation' => 'Automation', - 'others' => 'Others', - 'classification' => 'Classification', + 'financial_control' => 'Control financiero', + 'accounting' => 'Contabilidad', + 'automation' => 'Automatización', + 'others' => 'Otros', + 'classification' => 'Clasificación', // reports: 'report_default' => 'Reporte financiero por defecto entre :start y :end', @@ -1461,7 +1467,7 @@ return [ 'tools_index_intro' => 'Existen varias herramientas para importar datos en Firefly III. Reviselas a continuación. Para más información, consulte esta página.', 'firefly_iii_csv_importer_name' => 'Importador CSV de Firefly III', 'firefly_iii_bunq_importer_name' => 'Importador de Firefly III bunq', - 'firefly_iii_ynab_importer_name' => 'Firefly III YNAB importer', + 'firefly_iii_ynab_importer_name' => 'Importador YNAB de Firefly III', 'ludo_revolut_importer_name' => 'Importador Ludo444\'s Revolut', // // sandstorm.io errors and messages: @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Transacciones Recurrentes', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Calendario', 'no_recurring_title_default' => 'Vamos a crear una transacción recurrente!', 'no_recurring_intro_default' => 'Usted no tiene transacciones recurrentes aún. Puede usar esto para hacer que Firefly III cree transacciones por usted.', @@ -1615,7 +1622,7 @@ return [ 'telemetry_admin_overview' => 'Resumen de telemetría', 'telemetry_back_to_index' => 'Volver al índice de telemetría', 'not_yet_submitted' => 'No enviada', - 'telemetry_type_feature' => 'Feature flag', + 'telemetry_type_feature' => 'Marca de características', 'telemetry_submit_all' => 'Enviar registros', 'telemetry_delete_submitted_records' => 'Eliminar los registros enviados', 'telemetry_submission_executed' => 'Los registros han sido enviados. Revise sus archivos de registro para más información.', diff --git a/resources/lang/es_ES/form.php b/resources/lang/es_ES/form.php index 344af853b6..8481505a31 100644 --- a/resources/lang/es_ES/form.php +++ b/resources/lang/es_ES/form.php @@ -266,9 +266,9 @@ return [ 'auto_budget_amount' => 'Monto del autopresupuesto', 'auto_budget_period' => 'Período del autopresupuesto', - 'collected' => 'Collected', + 'collected' => 'Cobrado', 'submitted' => 'Enviado', - 'key' => 'Key', + 'key' => 'Clave', 'value' => 'Contenido del registro' diff --git a/resources/lang/fi_FI/firefly.php b/resources/lang/fi_FI/firefly.php index 4de0ac222f..d38f22d1da 100644 --- a/resources/lang/fi_FI/firefly.php +++ b/resources/lang/fi_FI/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Luo uusia juttuja', 'new_withdrawal' => 'Uusi nosto', 'create_new_transaction' => 'Luo uusi tapahtuma', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Uusi tapahtuma', 'no_rules_for_bill' => 'Tälle laskulle ei ole lisätty yhtään sääntöä.', 'go_to_asset_accounts' => 'Tarkastele omaisuustilejäsi', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Unohdit salasanasi Firefly III:een', 'reset_pw_page_title' => 'Nollaa salasanasi Firefly III:een', 'cannot_reset_demo_user' => 'Demokäyttäjän salasanaa ei voi nollata.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Rekisteröidy', 'authorization' => 'Valtuutus', 'active_bills_only' => 'vain aktiiviset laskut', 'active_exp_bills_only' => 'vain aktiiviset ja odotettavissa olevat laskut', 'average_per_bill' => 'keskiarvo laskuittain', 'expected_total' => 'odotettavissa yhteensä', - 'reconciliation_account_name' => 'täsmäytetään :name', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version Valtuutus Pyyntö', 'authorization_request_intro' => ':client pyytää valtuutustasi nähdäkseen sinun taloushallintosi. Haluatko antaa hänelle pääsyn näihin tietoihin?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Poista tägi ...', 'rule_action_remove_all_tags_choice' => 'Poista kaikki tägit', 'rule_action_set_description_choice' => 'Aseta kuvaus ...', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Liitä kuvauksen loppuun teksti ...', 'rule_action_prepend_description_choice' => 'Aloita kuvaus tekstillä ...', 'rule_action_set_source_account_choice' => 'Aseta lähdetiliksi ...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Täsmäytys (:from - :to)', 'sum_of_reconciliation' => 'Täsmäytykset yhteensä', 'reconcile_this_account' => 'Täsmäytä tämä tili', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Vahvista täsmäytys', 'submitted_start_balance' => 'Annettu avaussaldo', 'selected_transactions' => 'Valitut tapahtumat (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Toistuvat tapahtumat', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Kalenteri', 'no_recurring_title_default' => 'Luodaan toistuva tapahtuma!', 'no_recurring_intro_default' => 'Sinulla ei ole vielä yhtään toistuvaa tapahtumaa. Niiden avulla Firefly III osaa luoda automaattisesti tapahtumia sinulle.', diff --git a/resources/lang/fr_FR/firefly.php b/resources/lang/fr_FR/firefly.php index e83e40db33..69c0656edf 100644 --- a/resources/lang/fr_FR/firefly.php +++ b/resources/lang/fr_FR/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Créer de nouvelles choses', 'new_withdrawal' => 'Nouvelle dépense', 'create_new_transaction' => 'Créer une nouvelle opération', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Nouvelle opération', 'no_rules_for_bill' => 'Cette facture n\'a aucune règle associée.', 'go_to_asset_accounts' => 'Afficher vos comptes d\'actifs', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Mot de passe Firefly III oublié', 'reset_pw_page_title' => 'Réinitialiser votre mot de passe Firefly III', 'cannot_reset_demo_user' => 'Vous ne pouvez pas réinitialiser le mot de passe de l\'utilisateur de démonstration.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'S\'inscrire', 'authorization' => 'Autorisation', 'active_bills_only' => 'factures actives seulement', 'active_exp_bills_only' => 'uniquement les factures actives et attendues', 'average_per_bill' => 'moyenne par facture', 'expected_total' => 'total prévu', - 'reconciliation_account_name' => 'Régularisation :name', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version demande d\'autorisation', 'authorization_request_intro' => ':client demande l\'autorisation d\'accéder à votre administration financière. Souhaitez-vous autoriser :client à accéder à ces enregistrements?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Retirer le tag..', 'rule_action_remove_all_tags_choice' => 'Supprimer tous les tags', 'rule_action_set_description_choice' => 'Définir la description à..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Suffixer la description avec..', 'rule_action_prepend_description_choice' => 'Préfixer la description avec..', 'rule_action_set_source_account_choice' => 'Définissez le compte source à...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Régularisation (du :from au :to)', 'sum_of_reconciliation' => 'Total des rapprochements', 'reconcile_this_account' => 'Rapprocher ce compte', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Confirmer le rapprochement', 'submitted_start_balance' => 'Solde initial soumis', 'selected_transactions' => 'Opérations sélectionnées ( :count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Opérations périodiques', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Calendrier', 'no_recurring_title_default' => 'Créons une opération périodique !', 'no_recurring_intro_default' => 'Vous n’avez pas encore d\'opérations périodiques. Vous pouvez en utiliser pour que Firefly III crée automatiquement des opérations pour vous.', diff --git a/resources/lang/hu_HU/firefly.php b/resources/lang/hu_HU/firefly.php index cde7b5d315..581f7cc8b3 100644 --- a/resources/lang/hu_HU/firefly.php +++ b/resources/lang/hu_HU/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Új dolog létrehozása', 'new_withdrawal' => 'Új költség', 'create_new_transaction' => 'Új tranzakció létrehozása', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Új tranzakció', 'no_rules_for_bill' => 'Ehhez a számlához nincsenek szabályok kapcsolva.', 'go_to_asset_accounts' => 'Eszközszámlák megtekintése', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Elfelejtette a jelszavát a Firefly III-hoz', 'reset_pw_page_title' => 'Firefly III jelszó visszaállítása', 'cannot_reset_demo_user' => 'A bemutató felhasználónak nem nem lehet visszaállítani a jelszavát.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Regisztráció', 'authorization' => 'Hitelesítés', 'active_bills_only' => 'csak az aktív számlák', 'active_exp_bills_only' => 'csak az aktív és a várható számlák', 'average_per_bill' => 'számlánkénti átlag', 'expected_total' => 'várható teljes összeg', - 'reconciliation_account_name' => ':name egyeztetés', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version engedély kérelem', 'authorization_request_intro' => ':client hozzáférést kért az Ön pénzügyi adminisztrációjához. Szeretne hozzáférést ezekhez adatokhoz :client részére?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Címke eltávolítása..', 'rule_action_remove_all_tags_choice' => 'Minden címke eltávolítása', 'rule_action_set_description_choice' => 'Leírás megadása..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Hozzáfűzés a leíráshoz..', 'rule_action_prepend_description_choice' => 'Hozzáfűzés a leírás elejéhez..', 'rule_action_set_source_account_choice' => 'Forrásszámla beállítása...', @@ -541,8 +545,8 @@ return [ 'pref_locale' => 'Területi beállítások', 'pref_languages_help' => 'A Firefly III több nyelven is elérhető. Melyiket szeretné használni?', 'pref_locale_help' => 'Firefly III allows you to set other local settings, like how currencies, numbers and dates are formatted. Entries in this list may not be supported by your system. Firefly III doesn\'t have the correct date settings for every locale; contact me for improvements.', - 'pref_locale_no_windows' => 'This feature may not work on Windows.', - 'pref_locale_no_docker' => 'The Docker image only has a small set of installed locales.', + 'pref_locale_no_windows' => 'Lehet, hogy ez a szolgáltatás nem működik Windows rendszeren.', + 'pref_locale_no_docker' => 'A Docker-képfájlnak kevés előretelepített regionális beállítása van.', 'pref_custom_fiscal_year' => 'Költségvetési év beállításai', 'pref_custom_fiscal_year_label' => 'Engedélyezett', 'pref_custom_fiscal_year_help' => 'Azokban az országokban ahol a pénzügyi év nem Január 1 és December 31 közé esik, be lehet ezt kapcsolni és meg lehet adni a pénzügyi év kezdő- és végdátumát', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Egyeztetés (:from - :to)', 'sum_of_reconciliation' => 'Egyeztetés összege', 'reconcile_this_account' => 'Számla egyeztetése', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Számla megerősítése', 'submitted_start_balance' => 'Beküldött kezdő egyenleg', 'selected_transactions' => 'Kiválasztott tranzakciók (:count)', @@ -1132,11 +1138,11 @@ return [ 'interest_period_help' => 'Ez kizárólag kozmetikázásra használt mező, nem fog a számláláshoz hozzáadódni. Mint kiderült, a bankok néha sunyik és Firefly III tévedhet.', 'store_new_liabilities_account' => 'Új kötelezettség eltárolása', 'edit_liabilities_account' => '":name" kötelezettség szerkesztése', - 'financial_control' => 'Financial control', - 'accounting' => 'Accounting', - 'automation' => 'Automation', - 'others' => 'Others', - 'classification' => 'Classification', + 'financial_control' => 'Pénzügyi felügyelet', + 'accounting' => 'Számlázás', + 'automation' => 'Automatizálás', + 'others' => 'Egyebek', + 'classification' => 'Besorolás', // reports: 'report_default' => 'Alapértelmezett pénzügyi jelentés :start és :end között', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Ismétlődő tranzakciók', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Naptár', 'no_recurring_title_default' => 'Hozzunk létre egy ismétlődő tranzakciót!', 'no_recurring_intro_default' => 'Még nincsenek ismétlődő tranzakciók. Ezek használatával a Firefly III automatikusan létrehozza a tranzakciókat.', diff --git a/resources/lang/id_ID/firefly.php b/resources/lang/id_ID/firefly.php index 771fdc89e6..4d166594cb 100644 --- a/resources/lang/id_ID/firefly.php +++ b/resources/lang/id_ID/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Buat barang baru', 'new_withdrawal' => 'Penarikan baru', 'create_new_transaction' => 'Membuat transaksi baru', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Transaksi baru', 'no_rules_for_bill' => 'Tagihan ini tidak terkait dengan aturan yang telah ada.', 'go_to_asset_accounts' => 'Menampilkan rekening aset', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Forgot your password for Firefly III', 'reset_pw_page_title' => 'Reset your password for Firefly III', 'cannot_reset_demo_user' => 'You cannot reset the password of the demo user.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Register', 'authorization' => 'Authorization', 'active_bills_only' => 'active bills only', 'active_exp_bills_only' => 'active and expected bills only', 'average_per_bill' => 'average per bill', 'expected_total' => 'expected total', - 'reconciliation_account_name' => ':name reconciliation', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version Authorization Request', 'authorization_request_intro' => ':client is requesting permission to access your financial administration. Would you like to authorize :client to access these records?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Hapus tanda..', 'rule_action_remove_all_tags_choice' => 'Hapus semua tag', 'rule_action_set_description_choice' => 'Setel deskripsi ke..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Tambahkan deskripsi dengan..', 'rule_action_prepend_description_choice' => 'Tambahkan deskripsi dengan..', 'rule_action_set_source_account_choice' => 'Tetapkan akun sumber ke...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Reconciliation (:from to :to)', 'sum_of_reconciliation' => 'Sum of reconciliation', 'reconcile_this_account' => 'Rekonsiliasi akun ini', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Konfirmasikan rekonsiliasi', 'submitted_start_balance' => 'Saldo awal yang dikirim', 'selected_transactions' => 'Transaksi yang dipilih (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Recurring transactions', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Calendar', 'no_recurring_title_default' => 'Let\'s create a recurring transaction!', 'no_recurring_intro_default' => 'You have no recurring transactions yet. You can use these to make Firefly III automatically create transactions for you.', diff --git a/resources/lang/it_IT/firefly.php b/resources/lang/it_IT/firefly.php index 074d5c59ec..4e63b86760 100644 --- a/resources/lang/it_IT/firefly.php +++ b/resources/lang/it_IT/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Crea nuove cose', 'new_withdrawal' => 'Nuova uscita', 'create_new_transaction' => 'Crea nuova transazione', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Nuova transazione', 'no_rules_for_bill' => 'Questa bolletta non ha regole ad essa associate.', 'go_to_asset_accounts' => 'Visualizza i tuoi conti attività', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Hai dimenticato la password per Firefly III', 'reset_pw_page_title' => 'Reimposta la password per Firefly III', 'cannot_reset_demo_user' => 'Non puoi reimpostare la password dell\'utente demo.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Registrare', 'authorization' => 'Autorizzazione', 'active_bills_only' => 'solo bollette attive', 'active_exp_bills_only' => 'solo bollette attive e previste', 'average_per_bill' => 'media per bolletta', 'expected_total' => 'totale previsto', - 'reconciliation_account_name' => 'Riconciliazione di :name', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version Richiesta Autorizzazione', 'authorization_request_intro' => ':client sta richiedendo l\'autorizzazione per accedere alla tua amministrazione finanziaria. Desideri autorizzare :client ad accedere a questi record?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Rimuovi l\'etichetta...', 'rule_action_remove_all_tags_choice' => 'Rimuovi tutte le etichette', 'rule_action_set_description_choice' => 'Imposta come descrizione...', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Aggiungi alla descrizione...', 'rule_action_prepend_description_choice' => 'Anteponi alla descrizione...', 'rule_action_set_source_account_choice' => 'Imposta come conto di origine...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Riconciliazione (:from - :to)', 'sum_of_reconciliation' => 'Somma riconciliazione', 'reconcile_this_account' => 'Riconcilia questo conto', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Conferma riconciliazione', 'submitted_start_balance' => 'Saldo iniziale inserito', 'selected_transactions' => 'Transazioni selezionate (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Transazioni ricorrenti', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Calendario', 'no_recurring_title_default' => 'Creiamo una transazione ricorrente!', 'no_recurring_intro_default' => 'Non hai ancora una transazione ricorrente. Puoi utilizzare queste per lasciare che Firefly III crei automaticamente le transazioni per te.', diff --git a/resources/lang/nb_NO/firefly.php b/resources/lang/nb_NO/firefly.php index 81f5654613..c0fda3a9ca 100644 --- a/resources/lang/nb_NO/firefly.php +++ b/resources/lang/nb_NO/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Lag nye ting', 'new_withdrawal' => 'Nytt uttak', 'create_new_transaction' => 'Opprett ny transaksjon', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'New transaction', 'no_rules_for_bill' => 'This bill has no rules associated to it.', 'go_to_asset_accounts' => 'Se aktivakontoene dine', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Glemt passord for Firefly III', 'reset_pw_page_title' => 'Nullstill passord for Firefly III', 'cannot_reset_demo_user' => 'Du kan ikke nustille passordet til demo bruker.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Registrer', 'authorization' => 'Autorisasjon', 'active_bills_only' => 'kun aktive regninger', 'active_exp_bills_only' => 'active and expected bills only', 'average_per_bill' => 'gjennomsnitt per regning', 'expected_total' => 'forventet totalt', - 'reconciliation_account_name' => ':name reconciliation', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version autorisasjonsforespørsel', 'authorization_request_intro' => ':client ber om tillatelse til å få tilgang til finansadministrasjonen din. Vil du autorisere :client slik at den får tilgang til disse dine data?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Fjern tagg..', 'rule_action_remove_all_tags_choice' => 'Fjern alle tagger', 'rule_action_set_description_choice' => 'Sett beskrivelse til..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Legg til etter beskrivelse..', 'rule_action_prepend_description_choice' => 'Legg til foran beskrivelse..', 'rule_action_set_source_account_choice' => 'Sett kildekonto til...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Reconciliation (:from to :to)', 'sum_of_reconciliation' => 'Sum of reconciliation', 'reconcile_this_account' => 'Avstem denne kontoen', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Bekreft avstemming', 'submitted_start_balance' => 'Innsendt startsaldo', 'selected_transactions' => 'Valgte transaksjoner (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Gjentakende transaksjoner', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Kalender', 'no_recurring_title_default' => 'La oss opprette en gjentakende transaksjon!', 'no_recurring_intro_default' => 'Du har ingen gjentakende transaksjoner ennå. Du kan bruke disse for å få Firefly III til å automatisk opprette transaksjoner for deg.', diff --git a/resources/lang/nl_NL/firefly.php b/resources/lang/nl_NL/firefly.php index c69cb6a131..cf123aeef5 100644 --- a/resources/lang/nl_NL/firefly.php +++ b/resources/lang/nl_NL/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Nieuw', 'new_withdrawal' => 'Nieuwe uitgave', 'create_new_transaction' => 'Maak nieuwe transactie', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Nieuwe transactie', 'no_rules_for_bill' => 'Dit contract heeft geen regels.', 'go_to_asset_accounts' => 'Bekijk je betaalrekeningen', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Je wachtwoord voor Firefly III vergeten', 'reset_pw_page_title' => 'Reset je Firefly III wachtwoord', 'cannot_reset_demo_user' => 'Je kan het wachtwoord van de demo-gebruiker niet resetten.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Registreren', 'authorization' => 'Toestemming', 'active_bills_only' => 'alleen actieve contracten', 'active_exp_bills_only' => 'alleen actieve en verwachte contracten', 'average_per_bill' => 'gemiddeld per contract', 'expected_total' => 'verwacht totaal', - 'reconciliation_account_name' => ':name afstemmingsrekening', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version autorisatieverzoek', 'authorization_request_intro' => ':client vraagt ​​toestemming om toegang te krijgen tot je financiële administratie. Wil je :client autoriseren om toegang te krijgen tot je gegevens?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Haal tag weg..', 'rule_action_remove_all_tags_choice' => 'Haal alle tags weg', 'rule_action_set_description_choice' => 'Geef omschrijving..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Zet .. achter de omschrijving', 'rule_action_prepend_description_choice' => 'Zet .. voor de omschrijving', 'rule_action_set_source_account_choice' => 'Verander bronrekening naar...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Afstemming (:from tot :to)', 'sum_of_reconciliation' => 'Som van afstemming', 'reconcile_this_account' => 'Stem deze rekening af', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Bevestig afstemming', 'submitted_start_balance' => 'Ingevoerd startsaldo', 'selected_transactions' => 'Geselecteerde transacties (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Periodieke transacties', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Kalender', 'no_recurring_title_default' => 'Maak een periodieke transactie!', 'no_recurring_intro_default' => 'Je hebt nog geen periodieke transacties. Je kan deze gebruiken om er voor te zorgen dat Firefly III automatisch nieuwe transacties voor je maakt.', diff --git a/resources/lang/pl_PL/firefly.php b/resources/lang/pl_PL/firefly.php index 4a36517ed8..5000aea37f 100644 --- a/resources/lang/pl_PL/firefly.php +++ b/resources/lang/pl_PL/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Utwórz nowe rzeczy', 'new_withdrawal' => 'Nowa wypłata', 'create_new_transaction' => 'Stwórz nową transakcję', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Nowa transakcja', 'no_rules_for_bill' => 'Ten rachunek nie ma przypisanych reguł.', 'go_to_asset_accounts' => 'Zobacz swoje konta aktywów', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Nie pamiętam hasła do Firefly III', 'reset_pw_page_title' => 'Resetowanie hasła do Firefly III', 'cannot_reset_demo_user' => 'Nie można zresetować hasła dla użytkownika demonstracyjnego.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Zarejestruj', 'authorization' => 'Autoryzacja', 'active_bills_only' => 'tylko aktywne rachunki', 'active_exp_bills_only' => 'tylko aktywne i oczekiwane rachunki', 'average_per_bill' => 'średnia za rachunek', 'expected_total' => 'oczekiwana suma', - 'reconciliation_account_name' => 'Uzgodnienie :name', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Żądanie autoryzacji Firefly III v:version', 'authorization_request_intro' => ':client prosi o pozwolenie na dostęp do Twojej administracji finansowej. Czy chcesz pozwolić :client na dostęp do tych danych?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Usuń tag..', 'rule_action_remove_all_tags_choice' => 'Usuń wszystkie tagi', 'rule_action_set_description_choice' => 'Ustaw opis na..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Dołącz do opisu..', 'rule_action_prepend_description_choice' => 'Poprzedź opis..', 'rule_action_set_source_account_choice' => 'Ustaw konto źródłowe na...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Rozrachunek (od :from do :to)', 'sum_of_reconciliation' => 'Suma rozrachunku', 'reconcile_this_account' => 'Uzgodnij to konto', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Potwierdź rozrachunek', 'submitted_start_balance' => 'Przesłane saldo początkowe', 'selected_transactions' => 'Wybrane transakcje (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Cykliczne transakcje', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Kalendarz', 'no_recurring_title_default' => 'Utwórzmy cykliczną transakcję!', 'no_recurring_intro_default' => 'Nie masz jeszcze żadnych cyklicznych transakcji. Możesz ich użyć, aby Firefly III automatycznie tworzył transakcje za Ciebie.', diff --git a/resources/lang/pt_BR/firefly.php b/resources/lang/pt_BR/firefly.php index 0d7dfeb38d..95938f57a0 100644 --- a/resources/lang/pt_BR/firefly.php +++ b/resources/lang/pt_BR/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Criar novas coisas', 'new_withdrawal' => 'Nova retirada', 'create_new_transaction' => 'Criar nova transação', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Nova transação', 'no_rules_for_bill' => 'Esta conta não tem regras associadas a ela.', 'go_to_asset_accounts' => 'Veja suas contas ativas', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Esqueceu sua senha do Firefly III', 'reset_pw_page_title' => 'Redefinir sua senha para Firefly III', 'cannot_reset_demo_user' => 'Você não pode redefinir a senha do usuário demo.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Registrar', 'authorization' => 'Autorização', 'active_bills_only' => 'apenas faturas ativas', 'active_exp_bills_only' => 'somente faturas ativas e esperadas', 'average_per_bill' => 'média por fatura', 'expected_total' => 'total esperado', - 'reconciliation_account_name' => ':name reconciliação', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version Pedido de autorização', 'authorization_request_intro' => ':client está pedindo permissão para acessar sua administração financeira. Gostaria de autorizar :client para acessar esses registros?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Remover tag..', 'rule_action_remove_all_tags_choice' => 'Remover todas as tags', 'rule_action_set_description_choice' => 'Definir descrição para..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Acrescentar a descrição com..', 'rule_action_prepend_description_choice' => 'Preceder a descrição com..', 'rule_action_set_source_account_choice' => 'Definir a conta de origem...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Reconciliação (:from a :to)', 'sum_of_reconciliation' => 'Total reconciliado', 'reconcile_this_account' => 'Concilie esta conta', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Confirmar reconciliação', 'submitted_start_balance' => 'Saldo inicial enviado', 'selected_transactions' => 'Transações selecionadas (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Transações recorrentes', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Calendário', 'no_recurring_title_default' => 'Vamos criar uma transação recorrente!', 'no_recurring_intro_default' => 'Você ainda não tem nenhuma transação recorrente. Você pode usá-las para que o Firefly III crie transações para você automaticamente.', diff --git a/resources/lang/ro_RO/firefly.php b/resources/lang/ro_RO/firefly.php index 8623263d53..08e472d023 100644 --- a/resources/lang/ro_RO/firefly.php +++ b/resources/lang/ro_RO/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Creați lucruri noi', 'new_withdrawal' => 'Tranzacție nouă', 'create_new_transaction' => 'Creați o nouă tranzacție', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Tranzacţie nouă', 'no_rules_for_bill' => 'Acestă factură nu are asociate reguli.', 'go_to_asset_accounts' => 'Vizualizați conturile de active', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Am uitat parola', 'reset_pw_page_title' => 'Reseteaza parola', 'cannot_reset_demo_user' => 'Nu puteți reseta parola utilizatorului demo.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Înregistrare', 'authorization' => 'Autorizare', 'active_bills_only' => 'numai facturi active', 'active_exp_bills_only' => 'numai facturi active și așteptate', 'average_per_bill' => 'media pe factură', 'expected_total' => 'total așteptat', - 'reconciliation_account_name' => ':name reconciliation', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'v: Solicitare de autorizare', 'authorization_request_intro' => ' :client solicită permisiunea de a accesa administrația financiară. Doriți să autorizați :client pentru a accesa aceste înregistrări?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Eliminați eticheta..', 'rule_action_remove_all_tags_choice' => 'Eliminați toate etichetele', 'rule_action_set_description_choice' => 'Setați descrierea la..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Adăugați descrierea cu..', 'rule_action_prepend_description_choice' => 'Prefixați descrierea cu..', 'rule_action_set_source_account_choice' => 'Setați contul sursă la...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Reconciliere (:from la :to)', 'sum_of_reconciliation' => 'Suma împăcărilor', 'reconcile_this_account' => 'Reconciliați acest cont', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Confirmați reconcilierea', 'submitted_start_balance' => 'Balanța inițială afișată', 'selected_transactions' => 'Tranzacții selectate (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Tranzacții recurente', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Calendar', 'no_recurring_title_default' => 'Să cream o tranzacție recurentă!', 'no_recurring_intro_default' => 'Nu ai încă nici o tranzacție recurentă. Puteți utiliza aceste pentru a face Firefly III să creeze automat tranzacții pentru dvs..', diff --git a/resources/lang/ru_RU/firefly.php b/resources/lang/ru_RU/firefly.php index 8e28607190..71406e91fe 100644 --- a/resources/lang/ru_RU/firefly.php +++ b/resources/lang/ru_RU/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Создать новый объект', 'new_withdrawal' => 'Новый расход', 'create_new_transaction' => 'Создать новую транзакцию', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Новая транзакция', 'no_rules_for_bill' => 'С этим счётом не связано ни одно правило.', 'go_to_asset_accounts' => 'Просмотр ваших основных счетов', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Забыли свой пароль к Firefly III?', 'reset_pw_page_title' => 'Сбросить свой пароль к Firefly III', 'cannot_reset_demo_user' => 'Вы не можете сбросить пароль демонстрационной учётной записи.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Регистрация', 'authorization' => 'Авторизация', 'active_bills_only' => 'только активные счета', 'active_exp_bills_only' => 'только активные и ожидаемые счета на оплату', 'average_per_bill' => 'в среднем на счёт', 'expected_total' => 'ожидаемый итог', - 'reconciliation_account_name' => 'Сверка :name', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Запрос авторизации Firefly III v:version', 'authorization_request_intro' => ':client запрашивает доступ к управлению вашими финансами. Вы хотите разрешить :client доступ к этой информации?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Удалить метку...', 'rule_action_remove_all_tags_choice' => 'Удалить все метки...', 'rule_action_set_description_choice' => 'Назначить описание...', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Добавить в конце описание с...', 'rule_action_prepend_description_choice' => 'Добавить в начале описание с...', 'rule_action_set_source_account_choice' => 'Назначить счёт-источник...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Сверка (с :from по :to)', 'sum_of_reconciliation' => 'Сумма по сверке', 'reconcile_this_account' => 'Произвести сверку данного счёта', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Подтвердить сверку', 'submitted_start_balance' => 'Подтверждённый начальный баланс', 'selected_transactions' => 'Выбранный транзакции (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Повторяющиеся транзакции', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Календарь', 'no_recurring_title_default' => 'Давайте создадим повторяющуюся транзакцию!', 'no_recurring_intro_default' => 'У вас пока нет повторяющихся транзакций. Вы можете использовать их для автоматического создания транзакций в Firefly III.', diff --git a/resources/lang/sv_SE/firefly.php b/resources/lang/sv_SE/firefly.php index c0b5d56d93..de076f429f 100644 --- a/resources/lang/sv_SE/firefly.php +++ b/resources/lang/sv_SE/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Skapa nya saker', 'new_withdrawal' => 'Nytt uttag', 'create_new_transaction' => 'Skapa ny transaktion', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Lägg till transaktion', 'no_rules_for_bill' => 'Notan saknar associerade regler.', 'go_to_asset_accounts' => 'Visa dina tillgångskonton', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Glömt ditt lösenord till Firefly III', 'reset_pw_page_title' => 'Återställ ditt lösenord för Firefly III', 'cannot_reset_demo_user' => 'Går inte att återställa lösenordet för demo användaren.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Registrera', 'authorization' => 'Auktorisering', 'active_bills_only' => 'endast aktiva notor', 'active_exp_bills_only' => 'endast aktiva och väntade notor', 'average_per_bill' => 'medel per nota', 'expected_total' => 'total förväntad', - 'reconciliation_account_name' => ':name reconciliation', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v:version Auktorisationsbegäran', 'authorization_request_intro' => ':client begär tillstånd för åtkomst till din ekonomi administration. Vill du tillåta :client åtkomst till dessa poster?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Ta bort etikett..', 'rule_action_remove_all_tags_choice' => 'Ta bort alla etiketter', 'rule_action_set_description_choice' => 'Sätt beskrivning till..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Lägg till beskrivning med..', 'rule_action_prepend_description_choice' => 'Förbered beskrivning med..', 'rule_action_set_source_account_choice' => 'Sätt källkonto till...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Avstämning (:from till :to)', 'sum_of_reconciliation' => 'Summa av avstämning', 'reconcile_this_account' => 'Stäm av detta konto', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Bekräfta avstämning', 'submitted_start_balance' => 'Inskickad startbalans', 'selected_transactions' => 'Valda transaktioner (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Recurring transactions', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Calendar', 'no_recurring_title_default' => 'Let\'s create a recurring transaction!', 'no_recurring_intro_default' => 'You have no recurring transactions yet. You can use these to make Firefly III automatically create transactions for you.', diff --git a/resources/lang/tr_TR/firefly.php b/resources/lang/tr_TR/firefly.php index 95a6954103..35bd422328 100644 --- a/resources/lang/tr_TR/firefly.php +++ b/resources/lang/tr_TR/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Yeni bir şey oluştur', 'new_withdrawal' => 'Yeni para çekme', 'create_new_transaction' => 'Yeni işlem oluştur', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Yeni işlem', 'no_rules_for_bill' => 'Bu faturaya bağlı bir kural yok.', 'go_to_asset_accounts' => 'Varlık hesaplarınızı görüntüleyin @@ -200,13 +201,14 @@ return [ 'forgot_pw_page_title' => 'Firefly III için şifrenizi mi unuttunuz', 'reset_pw_page_title' => 'Firefly III şifrenizi sıfırlayın', 'cannot_reset_demo_user' => 'Demo kullanıcısının şifresini sıfırlayamazsınız.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Kayıt ol', 'authorization' => 'Yetkilendirme', 'active_bills_only' => 'sadece aktif faturalar', 'active_exp_bills_only' => 'sadece aktif ve beklenen faturalar', 'average_per_bill' => 'fatura başına ortalama', 'expected_total' => 'beklenen toplam', - 'reconciliation_account_name' => ':name reconciliation', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v: version Yetkilendirme İsteği', 'authorization_request_intro' => ':client finansal yönetiminize erişmek için izin istiyor. Bu kayıtlara erişmek için :client \'yi yetkilendirmek ister misiniz?', @@ -473,6 +475,8 @@ işlemlerin kontrol edildiğini lütfen unutmayın.', 'rule_action_remove_tag_choice' => 'Etiketi kaldır..', 'rule_action_remove_all_tags_choice' => 'Tüm etiketleri kaldır', 'rule_action_set_description_choice' => 'Açıklama belirtiniz..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'İle açıklamayı ekle..', 'rule_action_prepend_description_choice' => 'Açıklamanın başlığını ekleyin..', 'rule_action_set_source_account_choice' => 'Kaynak hesabı ayarla...', @@ -927,6 +931,8 @@ işlemlerin kontrol edildiğini lütfen unutmayın.', 'reconciliation_transaction_title' => 'Reconciliation (:from to :to)', 'sum_of_reconciliation' => 'Sum of reconciliation', 'reconcile_this_account' => 'Bu hesabı bağdaştırınız', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Mutabakatı onayla', 'submitted_start_balance' => 'Gönderilen başlangıç bakiyesi', 'selected_transactions' => 'Seçilen İşlemler (:count)', @@ -1521,6 +1527,7 @@ işlemlerin kontrol edildiğini lütfen unutmayın.', // recurring transactions 'recurrences' => 'Tekrar Eden İşlemler', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Calendar', 'no_recurring_title_default' => 'Yinelenen bir işlem yapalım!', 'no_recurring_intro_default' => 'Henüz yinelenen işleminiz yok. Firefly III\'ün sizin için otomatik olarak işlemler oluşturmasını sağlamak için bunları kullanabilirsiniz.', diff --git a/resources/lang/vi_VN/firefly.php b/resources/lang/vi_VN/firefly.php index d6edc4efe5..2612e7ab95 100644 --- a/resources/lang/vi_VN/firefly.php +++ b/resources/lang/vi_VN/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => 'Tạo công cụ mới', 'new_withdrawal' => 'Rút tiền mới', 'create_new_transaction' => 'Tạo giao dịch mới', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => 'Giao dịch mới', 'no_rules_for_bill' => 'Hóa đơn này không có quy tắc nào liên quan đến nó.', 'go_to_asset_accounts' => 'Xem tài khoản của bạn', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => 'Quên mật khẩu của bạn cho Firefly III', 'reset_pw_page_title' => 'Đặt lại mật khẩu của bạn cho Firefly III', 'cannot_reset_demo_user' => 'Bạn không thể đặt lại mật khẩu của người dùng demo.', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => 'Đăng ký', 'authorization' => 'Ủy quyền', 'active_bills_only' => 'Chỉ hóa đơn hoạt động', 'active_exp_bills_only' => 'hóa đơn hoạt động và dự kiến', 'average_per_bill' => 'trung bình mỗi hóa đơn', 'expected_total' => 'tổng dự kiến', - 'reconciliation_account_name' => ':tên bản đối chiếu số dư tiền gửi ngân hàng', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III v: phiên bản Yêu cầu ủy quyền', 'authorization_request_intro' => ':client đang yêu cầu sự cho phép truy cập quản trị tài chính của bạn. Bạn có muốn ủy quyền :client để truy cập những hồ sơ này?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => 'Xóa thẻ..', 'rule_action_remove_all_tags_choice' => 'Xóa tất cả các thẻ', 'rule_action_set_description_choice' => 'Đặt mô tả thành..', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => 'Nối mô tả với..', 'rule_action_prepend_description_choice' => 'Chuẩn bị mô tả với..', 'rule_action_set_source_account_choice' => 'Đặt tài khoản nguồn thành...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Đối chiếu (:từ đến :)', 'sum_of_reconciliation' => 'Tổng đối chiếu', 'reconcile_this_account' => 'Điều chỉnh tài khoản này', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => 'Xác nhận đối chiếu', 'submitted_start_balance' => 'Gửi số dư bắt đầu', 'selected_transactions' => 'Giao dịch được chọn (: tính)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => 'Giao dịch định kỳ', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => 'Lịch', 'no_recurring_title_default' => 'Hãy tạo một giao dịch định kỳ!', 'no_recurring_intro_default' => 'Bạn chưa có giao dịch định kỳ. Bạn có thể sử dụng những thứ này để Firefly III tự động tạo giao dịch cho bạn.', diff --git a/resources/lang/zh_CN/firefly.php b/resources/lang/zh_CN/firefly.php index 157267b729..0208a3d26a 100644 --- a/resources/lang/zh_CN/firefly.php +++ b/resources/lang/zh_CN/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => '建立新内容', 'new_withdrawal' => '新提款', 'create_new_transaction' => '建立新交易', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => '新交易', 'no_rules_for_bill' => '该账单没有与之相关的规则。', 'go_to_asset_accounts' => '检视您的资产帐户', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => '忘记您 Firefly III 的密码', 'reset_pw_page_title' => '重设您 Firefly III 的密码', 'cannot_reset_demo_user' => '您不能重置 演示使用者 的密码。', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => '注册帐号', 'authorization' => '认证', 'active_bills_only' => '只显示进行中的工作', 'active_exp_bills_only' => '只显示有效和预期的账单', 'average_per_bill' => '每张帐单的平均数', 'expected_total' => '期望总数', - 'reconciliation_account_name' => ':name 对账', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III :version 版授权请求', 'authorization_request_intro' => ':client 正在要求通行您的财务管理后台的许可,您是否愿意授权 :client 通行这些纪录?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => '移除标签…', 'rule_action_remove_all_tags_choice' => '移除所有标签', 'rule_action_set_description_choice' => '把描述设置为…', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => '描述后加上…', 'rule_action_prepend_description_choice' => '描述前加上…', 'rule_action_set_source_account_choice' => '将来源帐户设为...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => 'Reconciliation (:from to :to)', 'sum_of_reconciliation' => 'Sum of reconciliation', 'reconcile_this_account' => '对帐此帐户', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => '确认对帐', 'submitted_start_balance' => '初始余额已提交', 'selected_transactions' => '已选择交易 (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => '周期性交易', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => '日历', 'no_recurring_title_default' => '一起建立一笔周期性交易!', 'no_recurring_intro_default' => '您目前没有定期重复的交易。您可使用此功能让 Firefly III 自动为您建立交易。', diff --git a/resources/lang/zh_TW/firefly.php b/resources/lang/zh_TW/firefly.php index 85d8372357..1e3f4e31a4 100644 --- a/resources/lang/zh_TW/firefly.php +++ b/resources/lang/zh_TW/firefly.php @@ -54,6 +54,7 @@ return [ 'create_new_stuff' => '建立新內容', 'new_withdrawal' => '新提款', 'create_new_transaction' => '建立新交易', + 'sidebar_frontpage_create' => 'Create', 'new_transaction' => '新交易', 'no_rules_for_bill' => '此帳單未設定相關的規則。', 'go_to_asset_accounts' => '檢視您的資產帳戶', @@ -199,13 +200,14 @@ return [ 'forgot_pw_page_title' => '忘記您 Firefly III 的密碼', 'reset_pw_page_title' => '重設您 Firefly III 的密碼', 'cannot_reset_demo_user' => '您不能重設 展示使用者 的密碼。', + 'no_att_demo_user' => 'The demo user can\'t upload attachments.', 'button_register' => '註冊帳號', 'authorization' => '身份認證', 'active_bills_only' => '僅限使用中帳單', 'active_exp_bills_only' => 'active and expected bills only', 'average_per_bill' => '每張帳單的平均數', 'expected_total' => '預期總數', - 'reconciliation_account_name' => ':name reconciliation', + 'reconciliation_account_name' => ':name reconciliation (:currency)', // API access 'authorization_request' => 'Firefly III :version 版授權請求', 'authorization_request_intro' => ':client 正要求權限存取您的財務管理,您是否願意授權 :client 存取這些紀錄?', @@ -471,6 +473,8 @@ return [ 'rule_action_remove_tag_choice' => '移除標籤…', 'rule_action_remove_all_tags_choice' => '移除所有標籤', 'rule_action_set_description_choice' => '把描述設置為…', + 'rule_action_update_piggy_choice' => 'Add/remove transaction amount in piggy bank..', + 'rule_action_update_piggy' => 'Add/remove transaction amount in piggy bank ":action_value"', 'rule_action_append_description_choice' => '描述後加上…', 'rule_action_prepend_description_choice' => '描述前加上…', 'rule_action_set_source_account_choice' => '將來源帳戶設為...', @@ -925,6 +929,8 @@ return [ 'reconciliation_transaction_title' => '對帳 (:from 至 :to)', 'sum_of_reconciliation' => '對帳加總', 'reconcile_this_account' => '對帳此帳戶', + 'reconcile' => 'Reconcile', + 'show' => 'Show', 'confirm_reconciliation' => '確認對帳', 'submitted_start_balance' => '初始餘額已送出', 'selected_transactions' => '已選擇交易 (:count)', @@ -1519,6 +1525,7 @@ return [ // recurring transactions 'recurrences' => '週期性交易', + 'repeat_until_in_past' => 'This recurring transaction stopped repeating on :date.', 'recurring_calendar_view' => '月曆', 'no_recurring_title_default' => '一起建立一筆週期性交易!', 'no_recurring_intro_default' => '您目前沒有週期性交易。您可使用此功能讓 Firefly III 自動為您建立交易。', diff --git a/resources/views/v1/accounts/reconcile/transactions.twig b/resources/views/v1/accounts/reconcile/transactions.twig index 73944ce267..81ab7a1786 100644 --- a/resources/views/v1/accounts/reconcile/transactions.twig +++ b/resources/views/v1/accounts/reconcile/transactions.twig @@ -20,9 +20,12 @@ {# start marker #} {% if journal.date < start and startSet == false %} - +   + + + {{ trans('firefly.start_of_reconcile_period', {period: start.formatLocalized(monthAndDayFormat) }) }} @@ -38,9 +41,12 @@ {# end marker #} {% if journal.date <= end and endSet == false %} - +   + + + {{ trans('firefly.end_of_reconcile_period', {period: end.formatLocalized(monthAndDayFormat) }) }} diff --git a/resources/views/v1/index.twig b/resources/views/v1/index.twig index 480041b5da..7672dd17b0 100644 --- a/resources/views/v1/index.twig +++ b/resources/views/v1/index.twig @@ -80,34 +80,28 @@ {% endfor %} diff --git a/resources/views/v1/list/attachments.twig b/resources/views/v1/list/attachments.twig index abfdba55d3..3b87ffcdc3 100644 --- a/resources/views/v1/list/attachments.twig +++ b/resources/views/v1/list/attachments.twig @@ -44,4 +44,4 @@ {% endfor %} - \ No newline at end of file + diff --git a/resources/views/v1/recurring/index.twig b/resources/views/v1/recurring/index.twig index 98f53febe2..9220451138 100644 --- a/resources/views/v1/recurring/index.twig +++ b/resources/views/v1/recurring/index.twig @@ -85,6 +85,11 @@ + {% if null != rt.repeat_until and today > rt.repeat_until %} + + {{ trans('firefly.repeat_until_in_past', {date: rt.repeat_until.formatLocalized(monthAndDayFormat) }) }} + + {% endif %}
    {% for rep in rt.repetitions %}
  • {{ rep.description }} @@ -95,13 +100,13 @@ ({{ trans('firefly.recurring_skips_more', {count: rep.repetition_skip})|lower }}). {% endif %} {% if rep.weekend == 3 %} - {{ 'will_jump_friday'|_ }} +
    {{ 'will_jump_friday'|_ }} {% endif %} {% if rep.weekend == 4 %} - {{ 'will_jump_monday'|_ }} +
    {{ 'will_jump_monday'|_ }} {% endif %} {% if rep.weekend == 2 %} - {{ 'except_weekends'|_ }} +
    {{ 'except_weekends'|_ }} {% endif %}
  • {% endfor %} @@ -118,11 +123,15 @@ {% endif %}

    - {% if rt.occurrences|length == 0 %} -   - {% else %} - {{ rt.occurrences[0].formatLocalized(monthAndDayFormat) }} - {% endif %} + +
      + {% for rep in rt.repetitions %} + {% for occ in rep.occurrences %} +
    • {{ occ.formatLocalized(monthAndDayFormat) }}
    • + {% endfor %} + {% endfor %} +
    + {% endfor %} diff --git a/resources/views/v1/recurring/show.twig b/resources/views/v1/recurring/show.twig index f0c97dd750..1669c522aa 100644 --- a/resources/views/v1/recurring/show.twig +++ b/resources/views/v1/recurring/show.twig @@ -52,7 +52,11 @@
    - + {% if null != array.repeat_until and today > array.repeat_until %} + + {{ trans('firefly.repeat_until_in_past', {date: array.repeat_until.formatLocalized(monthAndDayFormat) }) }} + + {% endif %}
      {% for rep in array.repetitions %}
    • diff --git a/resources/views/v1/reports/partials/bills.twig b/resources/views/v1/reports/partials/bills.twig index f5106a04d0..1e523a1dbf 100644 --- a/resources/views/v1/reports/partials/bills.twig +++ b/resources/views/v1/reports/partials/bills.twig @@ -21,7 +21,7 @@ {{ formatAmountBySymbol(bill.amount_max, bill.currency_symbol, bill.currency_decimal_places) }} - + {% for date in bill.expected_dates %} {{ date.formatLocalized(monthAndDayFormat) }}
      {% endfor %}