Ability to delete recurring transactions.

This commit is contained in:
James Cole
2018-06-23 08:19:29 +02:00
parent b95dd5c238
commit 19a874b274
11 changed files with 320 additions and 98 deletions

View File

@@ -0,0 +1,70 @@
<?php
/**
* DeleteController.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Recurring;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Recurrence;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use Illuminate\Http\Request;
/**
* Class DeleteController
*/
class DeleteController extends Controller
{
/**
* @param Recurrence $recurrence
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function delete(Recurrence $recurrence)
{
$subTitle = trans('firefly.delete_recurring', ['title' => $recurrence->title]);
// put previous url in session
$this->rememberPreviousUri('recurrences.delete.uri');
// todo actual number.
$journalsCreated = 5;
return view('recurring.delete', compact('recurrence', 'subTitle','journalsCreated'));
}
/**
* @param RecurringRepositoryInterface $repository
* @param Request $request
* @param Recurrence $recurrence
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function destroy(RecurringRepositoryInterface $repository, Request $request, Recurrence $recurrence)
{
$repository->destroy($recurrence);
$request->session()->flash('success', (string)trans('firefly.' . 'recurrence_deleted', ['title' => $recurrence->title]));
app('preferences')->mark();
return redirect($this->getPreviousUri('recurrences.delete.uri'));
}
}

View File

@@ -101,6 +101,7 @@ class SpectreRoutine implements RoutineInterface
$handler = app(StageImportDataHandler::class);
$handler->setImportJob($this->importJob);
$handler->run();
// todo apply rules.
$this->repository->setStatus($this->importJob, 'provider_finished');
$this->repository->setStage($this->importJob, 'final');
}

View File

@@ -56,6 +56,8 @@ class CreateRecurringTransactions implements ShouldQueue
$recurrences = $this->repository->getAll();
Log::debug(sprintf('Count of collection is %d', $recurrences->count()));
$result = [];
/** @var Collection $filtered */
$filtered = $recurrences->filter(
function (Recurrence $recurrence) {
@@ -66,12 +68,24 @@ class CreateRecurringTransactions implements ShouldQueue
Log::debug(sprintf('Left after filtering is %d', $filtered->count()));
/** @var Recurrence $recurrence */
foreach ($filtered as $recurrence) {
if (!isset($result[$recurrence->user_id])) {
$result[$recurrence->user_id] = new Collection;
}
$this->repository->setUser($recurrence->user);
$this->journalRepository->setUser($recurrence->user);
Log::debug(sprintf('Now at recurrence #%d', $recurrence->id));
$this->handleRepetitions($recurrence);
$created = $this->handleRepetitions($recurrence);
Log::debug(sprintf('Done with recurrence #%c', $recurrence->id));
$result[$recurrence->user_id] = $result[$recurrence->user_id]->merge($created);
}
// will now send email to users.
foreach($result as $userId => $journals) {
$this->sendReport($userId, $journals);
}
Log::debug('Done with handle()');
}
@@ -160,10 +174,12 @@ class CreateRecurringTransactions implements ShouldQueue
* @param Recurrence $recurrence
* @param array $occurrences
*
* @return Collection
* @throws \FireflyIII\Exceptions\FireflyException
*/
private function handleOccurrences(Recurrence $recurrence, array $occurrences): void
private function handleOccurrences(Recurrence $recurrence, array $occurrences): Collection
{
$collection = new Collection;
/** @var Carbon $date */
foreach ($occurrences as $date) {
Log::debug(sprintf('Now at date %s.', $date->format('Y-m-d')));
@@ -195,21 +211,29 @@ class CreateRecurringTransactions implements ShouldQueue
];
$journal = $this->journalRepository->store($array);
Log::info(sprintf('Created new journal #%d', $journal->id));
// todo fire rules
$collection->push($journal);
// update recurring thing:
$recurrence->latest_date = $date;
$recurrence->save();
}
return $collection;
}
/**
* Separate method that will loop all repetitions and do something with it:
* Separate method that will loop all repetitions and do something with it. Will return
* all created transaction journals.
*
* @param Recurrence $recurrence
*
* @return Collection
*
* @throws \FireflyIII\Exceptions\FireflyException
*/
private function handleRepetitions(Recurrence $recurrence): void
private function handleRepetitions(Recurrence $recurrence): Collection
{
$collection = new Collection;
/** @var RecurrenceRepetition $repetition */
foreach ($recurrence->recurrenceRepetitions as $repetition) {
Log::debug(
@@ -227,8 +251,11 @@ class CreateRecurringTransactions implements ShouldQueue
), $this->debugArray($occurrences)
);
$this->handleOccurrences($recurrence, $occurrences);
$result = $this->handleOccurrences($recurrence, $occurrences);
$collection = $collection->merge($result);
}
return $collection;
}
/**

View File

@@ -33,6 +33,7 @@ use FireflyIII\Models\RecurrenceMeta;
use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Models\RecurrenceTransaction;
use FireflyIII\Models\RecurrenceTransactionMeta;
use FireflyIII\Services\Internal\Destroy\RecurrenceDestroyService;
use FireflyIII\Services\Internal\Update\RecurrenceUpdateService;
use FireflyIII\User;
use Illuminate\Support\Collection;
@@ -47,6 +48,18 @@ class RecurringRepository implements RecurringRepositoryInterface
/** @var User */
private $user;
/**
* Destroy a recurring transaction.
*
* @param Recurrence $recurrence
*/
public function destroy(Recurrence $recurrence): void
{
/** @var RecurrenceDestroyService $service */
$service = app(RecurrenceDestroyService::class);
$service->destroy($recurrence);
}
/**
* Returns all of the user's recurring transactions.
*

View File

@@ -39,6 +39,13 @@ use Illuminate\Support\Collection;
*/
interface RecurringRepositoryInterface
{
/**
* Destroy a recurring transaction.
*
* @param Recurrence $recurrence
*/
public function destroy(Recurrence $recurrence): void;
/**
* Returns all of the user's recurring transactions.
*
@@ -48,19 +55,11 @@ interface RecurringRepositoryInterface
/**
* Get ALL recurring transactions.
*
* @return Collection
*/
public function getAll(): Collection;
/**
* Get the category from a recurring transaction transaction.
*
* @param RecurrenceTransaction $recurrenceTransaction
*
* @return null|string
*/
public function getCategory(RecurrenceTransaction $recurrenceTransaction): ?string;
/**
* Get the budget ID from a recurring transaction transaction.
*
@@ -70,6 +69,15 @@ interface RecurringRepositoryInterface
*/
public function getBudget(RecurrenceTransaction $recurrenceTransaction): ?int;
/**
* Get the category from a recurring transaction transaction.
*
* @param RecurrenceTransaction $recurrenceTransaction
*
* @return null|string
*/
public function getCategory(RecurrenceTransaction $recurrenceTransaction): ?string;
/**
* Get the notes.
*

View File

@@ -0,0 +1,48 @@
<?php
/**
* RecurrenceDestroyService.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Internal\Destroy;
use Exception;
use FireflyIII\Models\Recurrence;
use Log;
/**
* @codeCoverageIgnore
* Class RecurrenceDestroyService
*/
class RecurrenceDestroyService
{
/**
* @param Recurrence $recurrence
*/
public function destroy(Recurrence $recurrence): void
{
try {
$recurrence->delete();
} catch (Exception $e) { // @codeCoverageIgnore
Log::error(sprintf('Could not delete recurrence: %s', $e->getMessage())); // @codeCoverageIgnore
}
}
}

View File

@@ -1260,4 +1260,6 @@ return [
'update_recurrence' => 'Update recurring transaction',
'updated_recurrence' => 'Updated recurring transaction ":title"',
'recurrence_is_inactive' => 'This recurring transaction is not active and will not generate new transactions.',
'delete_recurring' => 'Delete recurring transaction ":title"',
'recurrence_deleted' => 'Recurring transaction ":title" deleted',
];

View File

@@ -94,90 +94,93 @@ return [
'convert_Deposit' => 'Convert deposit',
'convert_Transfer' => 'Convert transfer',
'amount' => 'Amount',
'foreign_amount' => 'Foreign amount',
'existing_attachments' => 'Existing attachments',
'date' => 'Date',
'interest_date' => 'Interest date',
'book_date' => 'Book date',
'process_date' => 'Processing date',
'category' => 'Category',
'tags' => 'Tags',
'deletePermanently' => 'Delete permanently',
'cancel' => 'Cancel',
'targetdate' => 'Target date',
'startdate' => 'Start date',
'tag' => 'Tag',
'under' => 'Under',
'symbol' => 'Symbol',
'code' => 'Code',
'iban' => 'IBAN',
'accountNumber' => 'Account number',
'creditCardNumber' => 'Credit card number',
'has_headers' => 'Headers',
'date_format' => 'Date format',
'specifix' => 'Bank- or file specific fixes',
'attachments[]' => 'Attachments',
'store_new_withdrawal' => 'Store new withdrawal',
'store_new_deposit' => 'Store new deposit',
'store_new_transfer' => 'Store new transfer',
'add_new_withdrawal' => 'Add a new withdrawal',
'add_new_deposit' => 'Add a new deposit',
'add_new_transfer' => 'Add a new transfer',
'title' => 'Title',
'notes' => 'Notes',
'filename' => 'File name',
'mime' => 'Mime type',
'size' => 'Size',
'trigger' => 'Trigger',
'stop_processing' => 'Stop processing',
'start_date' => 'Start of range',
'end_date' => 'End of range',
'export_start_range' => 'Start of export range',
'export_end_range' => 'End of export range',
'export_format' => 'File format',
'include_attachments' => 'Include uploaded attachments',
'include_old_uploads' => 'Include imported data',
'accounts' => 'Export transactions from these accounts',
'delete_account' => 'Delete account ":name"',
'delete_bill' => 'Delete bill ":name"',
'delete_budget' => 'Delete budget ":name"',
'delete_category' => 'Delete category ":name"',
'delete_currency' => 'Delete currency ":name"',
'delete_journal' => 'Delete transaction with description ":description"',
'delete_attachment' => 'Delete attachment ":name"',
'delete_rule' => 'Delete rule ":title"',
'delete_rule_group' => 'Delete rule group ":title"',
'delete_link_type' => 'Delete link type ":name"',
'delete_user' => 'Delete user ":email"',
'user_areYouSure' => 'If you delete user ":email", everything will be gone. There is no undo, undelete or anything. If you delete yourself, you will lose access to this instance of Firefly III.',
'attachment_areYouSure' => 'Are you sure you want to delete the attachment named ":name"?',
'account_areYouSure' => 'Are you sure you want to delete the account named ":name"?',
'bill_areYouSure' => 'Are you sure you want to delete the bill named ":name"?',
'rule_areYouSure' => 'Are you sure you want to delete the rule titled ":title"?',
'ruleGroup_areYouSure' => 'Are you sure you want to delete the rule group titled ":title"?',
'budget_areYouSure' => 'Are you sure you want to delete the budget named ":name"?',
'category_areYouSure' => 'Are you sure you want to delete the category named ":name"?',
'currency_areYouSure' => 'Are you sure you want to delete the currency named ":name"?',
'piggyBank_areYouSure' => 'Are you sure you want to delete the piggy bank named ":name"?',
'journal_areYouSure' => 'Are you sure you want to delete the transaction described ":description"?',
'mass_journal_are_you_sure' => 'Are you sure you want to delete these transactions?',
'tag_areYouSure' => 'Are you sure you want to delete the tag ":tag"?',
'journal_link_areYouSure' => 'Are you sure you want to delete the link between <a href=":source_link">:source</a> and <a href=":destination_link">:destination</a>?',
'linkType_areYouSure' => 'Are you sure you want to delete the link type ":name" (":inward" / ":outward")?',
'permDeleteWarning' => 'Deleting stuff from Firefly III is permanent and cannot be undone.',
'mass_make_selection' => 'You can still prevent items from being deleted by removing the checkbox.',
'delete_all_permanently' => 'Delete selected permanently',
'update_all_journals' => 'Update these transactions',
'also_delete_transactions' => 'The only transaction connected to this account will be deleted as well.|All :count transactions connected to this account will be deleted as well.',
'also_delete_connections' => 'The only transaction linked with this link type will lose this connection.|All :count transactions linked with this link type will lose their connection.',
'also_delete_rules' => 'The only rule connected to this rule group will be deleted as well.|All :count rules connected to this rule group will be deleted as well.',
'also_delete_piggyBanks' => 'The only piggy bank connected to this account will be deleted as well.|All :count piggy bank connected to this account will be deleted as well.',
'bill_keep_transactions' => 'The only transaction connected to this bill will not be deleted.|All :count transactions connected to this bill will spared deletion.',
'budget_keep_transactions' => 'The only transaction connected to this budget will not be deleted.|All :count transactions connected to this budget will spared deletion.',
'category_keep_transactions' => 'The only transaction connected to this category will not be deleted.|All :count transactions connected to this category will spared deletion.',
'tag_keep_transactions' => 'The only transaction connected to this tag will not be deleted.|All :count transactions connected to this tag will spared deletion.',
'check_for_updates' => 'Check for updates',
'amount' => 'Amount',
'foreign_amount' => 'Foreign amount',
'existing_attachments' => 'Existing attachments',
'date' => 'Date',
'interest_date' => 'Interest date',
'book_date' => 'Book date',
'process_date' => 'Processing date',
'category' => 'Category',
'tags' => 'Tags',
'deletePermanently' => 'Delete permanently',
'cancel' => 'Cancel',
'targetdate' => 'Target date',
'startdate' => 'Start date',
'tag' => 'Tag',
'under' => 'Under',
'symbol' => 'Symbol',
'code' => 'Code',
'iban' => 'IBAN',
'accountNumber' => 'Account number',
'creditCardNumber' => 'Credit card number',
'has_headers' => 'Headers',
'date_format' => 'Date format',
'specifix' => 'Bank- or file specific fixes',
'attachments[]' => 'Attachments',
'store_new_withdrawal' => 'Store new withdrawal',
'store_new_deposit' => 'Store new deposit',
'store_new_transfer' => 'Store new transfer',
'add_new_withdrawal' => 'Add a new withdrawal',
'add_new_deposit' => 'Add a new deposit',
'add_new_transfer' => 'Add a new transfer',
'title' => 'Title',
'notes' => 'Notes',
'filename' => 'File name',
'mime' => 'Mime type',
'size' => 'Size',
'trigger' => 'Trigger',
'stop_processing' => 'Stop processing',
'start_date' => 'Start of range',
'end_date' => 'End of range',
'export_start_range' => 'Start of export range',
'export_end_range' => 'End of export range',
'export_format' => 'File format',
'include_attachments' => 'Include uploaded attachments',
'include_old_uploads' => 'Include imported data',
'accounts' => 'Export transactions from these accounts',
'delete_account' => 'Delete account ":name"',
'delete_bill' => 'Delete bill ":name"',
'delete_budget' => 'Delete budget ":name"',
'delete_category' => 'Delete category ":name"',
'delete_currency' => 'Delete currency ":name"',
'delete_journal' => 'Delete transaction with description ":description"',
'delete_attachment' => 'Delete attachment ":name"',
'delete_rule' => 'Delete rule ":title"',
'delete_rule_group' => 'Delete rule group ":title"',
'delete_link_type' => 'Delete link type ":name"',
'delete_user' => 'Delete user ":email"',
'delete_recurring' => 'Delete recurring transaction ":title"',
'user_areYouSure' => 'If you delete user ":email", everything will be gone. There is no undo, undelete or anything. If you delete yourself, you will lose access to this instance of Firefly III.',
'attachment_areYouSure' => 'Are you sure you want to delete the attachment named ":name"?',
'account_areYouSure' => 'Are you sure you want to delete the account named ":name"?',
'bill_areYouSure' => 'Are you sure you want to delete the bill named ":name"?',
'rule_areYouSure' => 'Are you sure you want to delete the rule titled ":title"?',
'ruleGroup_areYouSure' => 'Are you sure you want to delete the rule group titled ":title"?',
'budget_areYouSure' => 'Are you sure you want to delete the budget named ":name"?',
'category_areYouSure' => 'Are you sure you want to delete the category named ":name"?',
'recurring_areYouSure' => 'Are you sure you want to delete the recurring transaction titled ":title"?',
'currency_areYouSure' => 'Are you sure you want to delete the currency named ":name"?',
'piggyBank_areYouSure' => 'Are you sure you want to delete the piggy bank named ":name"?',
'journal_areYouSure' => 'Are you sure you want to delete the transaction described ":description"?',
'mass_journal_are_you_sure' => 'Are you sure you want to delete these transactions?',
'tag_areYouSure' => 'Are you sure you want to delete the tag ":tag"?',
'journal_link_areYouSure' => 'Are you sure you want to delete the link between <a href=":source_link">:source</a> and <a href=":destination_link">:destination</a>?',
'linkType_areYouSure' => 'Are you sure you want to delete the link type ":name" (":inward" / ":outward")?',
'permDeleteWarning' => 'Deleting stuff from Firefly III is permanent and cannot be undone.',
'mass_make_selection' => 'You can still prevent items from being deleted by removing the checkbox.',
'delete_all_permanently' => 'Delete selected permanently',
'update_all_journals' => 'Update these transactions',
'also_delete_transactions' => 'The only transaction connected to this account will be deleted as well.|All :count transactions connected to this account will be deleted as well.',
'also_delete_connections' => 'The only transaction linked with this link type will lose this connection.|All :count transactions linked with this link type will lose their connection.',
'also_delete_rules' => 'The only rule connected to this rule group will be deleted as well.|All :count rules connected to this rule group will be deleted as well.',
'also_delete_piggyBanks' => 'The only piggy bank connected to this account will be deleted as well.|All :count piggy bank connected to this account will be deleted as well.',
'bill_keep_transactions' => 'The only transaction connected to this bill will not be deleted.|All :count transactions connected to this bill will be spared deletion.',
'budget_keep_transactions' => 'The only transaction connected to this budget will not be deleted.|All :count transactions connected to this budget will be spared deletion.',
'category_keep_transactions' => 'The only transaction connected to this category will not be deleted.|All :count transactions connected to this category will be spared deletion.',
'recurring_keep_transactions' => 'The only transaction created by this recurring transaction will not be deleted.|All :count transactions created by this recurring transaction will be spared deletion.',
'tag_keep_transactions' => 'The only transaction connected to this tag will not be deleted.|All :count transactions connected to this tag will be spared deletion.',
'check_for_updates' => 'Check for updates',
'email' => 'Email address',
'password' => 'Password',

View File

@@ -0,0 +1,41 @@
{% extends "./layout/default" %}
{% block breadcrumbs %}
{{ Breadcrumbs.render(Route.getCurrentRoute.getName, recurrence) }}
{% endblock %}
{% block content %}
<form method="POST" action="{{ route('recurring.destroy',recurrence.id) }}" accept-charset="UTF-8" class="form-horizontal" id="destroy">
<input name="_token" type="hidden" value="{{ csrf_token() }}">
<div class="row">
<div class="col-lg-6 col-lg-offset-3 col-md-12 col-sm-12">
<div class="box box-danger">
<div class="box-header with-border">
<h3 class="box-title">{{ trans('form.delete_recurring', {'title': recurrence.title}) }}</h3>
</div>
<div class="box-body">
<p class="text-danger">
{{ trans('form.permDeleteWarning') }}
</p>
<p>
{{ trans('form.recurring_areYouSure', {'title': recurrence.title}) }}
</p>
<p>
{% if journalsCreated > 0 %}
{{ Lang.choice('form.recurring_keep_transactions', journalsCreated, {count: journalsCreated }) }}
{% endif %}
</p>
</div>
<div class="box-footer">
<input type="submit" name="submit" value="{{ trans('form.deletePermanently') }}" class="btn btn-danger pull-right"/>
<a href="{{ URL.previous() }}" class="btn-default btn">{{ trans('form.cancel') }}</a>
</div>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@@ -778,6 +778,14 @@ try {
}
);
Breadcrumbs::register(
'recurring.delete',
function (BreadCrumbsGenerator $breadcrumbs, Recurrence $recurrence) {
$breadcrumbs->parent('recurring.index');
$breadcrumbs->push(trans('firefly.delete_recurring', ['title' => $recurrence->title]), route('recurring.delete', [$recurrence->id]));
}
);
Breadcrumbs::register(
'recurring.edit',
function (BreadCrumbsGenerator $breadcrumbs, Recurrence $recurrence) {

View File

@@ -626,6 +626,7 @@ Route::group(
Route::post('store', ['uses' => 'CreateController@store', 'as' => 'store']);
Route::post('update/{recurrence}', ['uses' => 'EditController@update', 'as' => 'update']);
Route::post('destroy/{recurrence}', ['uses' => 'DeleteController@destroy', 'as' => 'destroy']);
}
);