mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Can now create recurring transactions. #1469
This commit is contained in:
parent
54e3e3f051
commit
d73cd4b515
@ -27,7 +27,10 @@ namespace FireflyIII\Factory;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
use FireflyIII\Models\Recurrence;
|
use FireflyIII\Models\Recurrence;
|
||||||
|
use FireflyIII\Models\RecurrenceMeta;
|
||||||
|
use FireflyIII\Models\RecurrenceRepetition;
|
||||||
use FireflyIII\Models\RecurrenceTransaction;
|
use FireflyIII\Models\RecurrenceTransaction;
|
||||||
|
use FireflyIII\Models\RecurrenceTransactionMeta;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Services\Internal\Support\TransactionServiceTrait;
|
use FireflyIII\Services\Internal\Support\TransactionServiceTrait;
|
||||||
use FireflyIII\Services\Internal\Support\TransactionTypeTrait;
|
use FireflyIII\Services\Internal\Support\TransactionTypeTrait;
|
||||||
@ -51,9 +54,6 @@ class RecurrenceFactory
|
|||||||
*/
|
*/
|
||||||
public function create(array $data): Recurrence
|
public function create(array $data): Recurrence
|
||||||
{
|
{
|
||||||
echo '<pre>';
|
|
||||||
print_r($data);
|
|
||||||
echo '</pre>';
|
|
||||||
$type = $this->findTransactionType(ucfirst($data['recurrence']['type']));
|
$type = $this->findTransactionType(ucfirst($data['recurrence']['type']));
|
||||||
$recurrence = new Recurrence(
|
$recurrence = new Recurrence(
|
||||||
[
|
[
|
||||||
@ -70,10 +70,49 @@ class RecurrenceFactory
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
$recurrence->save();
|
$recurrence->save();
|
||||||
var_dump($recurrence->toArray());
|
|
||||||
|
|
||||||
// create transactions
|
// create recurrence meta (tags)
|
||||||
|
if (\count($data['meta']['tags']) > 0) {
|
||||||
|
// todo move to factory
|
||||||
|
$tags = implode(',', $data['meta']['tags']);
|
||||||
|
if ('' !== $tags) {
|
||||||
|
$metaValue = RecurrenceMeta::create(
|
||||||
|
[
|
||||||
|
'recurrence_id' => $recurrence->id,
|
||||||
|
'name' => 'tags',
|
||||||
|
'value' => $tags,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// create recurrence meta (piggy bank ID):
|
||||||
|
if ($data['meta']['piggy_bank_id'] > 0) {
|
||||||
|
// todo move to factory
|
||||||
|
$metaValue = RecurrenceMeta::create(
|
||||||
|
[
|
||||||
|
'recurrence_id' => $recurrence->id,
|
||||||
|
'name' => 'piggy_bank_id',
|
||||||
|
'value' => $data['meta']['piggy_bank_id'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store recurrence repetitions:
|
||||||
|
foreach ($data['repetitions'] as $repArray) {
|
||||||
|
// todo move to factory
|
||||||
|
$repetition = RecurrenceRepetition::create(
|
||||||
|
[
|
||||||
|
'recurrence_id' => $recurrence->id,
|
||||||
|
'repetition_type' => $repArray['type'],
|
||||||
|
'repetition_moment' => $repArray['moment'],
|
||||||
|
'repetition_skip' => $repArray['skip'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create recurrence transactions
|
||||||
foreach ($data['transactions'] as $trArray) {
|
foreach ($data['transactions'] as $trArray) {
|
||||||
|
// todo move to factory
|
||||||
$source = null;
|
$source = null;
|
||||||
$destination = null;
|
$destination = null;
|
||||||
// search source account, depends on type
|
// search source account, depends on type
|
||||||
@ -84,6 +123,14 @@ class RecurrenceFactory
|
|||||||
$source = $this->findAccount(AccountType::ASSET, $trArray['source_account_id'], null);
|
$source = $this->findAccount(AccountType::ASSET, $trArray['source_account_id'], null);
|
||||||
$destination = $this->findAccount(AccountType::EXPENSE, null, $trArray['destination_account_name']);
|
$destination = $this->findAccount(AccountType::EXPENSE, null, $trArray['destination_account_name']);
|
||||||
break;
|
break;
|
||||||
|
case TransactionType::DEPOSIT:
|
||||||
|
$source = $this->findAccount(AccountType::REVENUE, null, $trArray['source_account_name']);
|
||||||
|
$destination = $this->findAccount(AccountType::ASSET, $trArray['destination_account_id'], null);
|
||||||
|
break;
|
||||||
|
case TransactionType::TRANSFER:
|
||||||
|
$source = $this->findAccount(AccountType::ASSET, $trArray['source_account_id'], null);
|
||||||
|
$destination = $this->findAccount(AccountType::ASSET, $trArray['destination_account_id'], null);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// search destination account
|
// search destination account
|
||||||
@ -101,16 +148,30 @@ class RecurrenceFactory
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
$transaction->save();
|
$transaction->save();
|
||||||
var_dump($transaction->toArray());
|
|
||||||
|
// create recurrence transaction meta:
|
||||||
|
// todo move to factory
|
||||||
|
if ($trArray['budget_id'] > 0) {
|
||||||
|
$trMeta = RecurrenceTransactionMeta::create(
|
||||||
|
[
|
||||||
|
'rt_id' => $transaction->id,
|
||||||
|
'name' => 'budget_id',
|
||||||
|
'value' => $trArray['budget_id'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ('' !== (string)$trArray['category_name']) {
|
||||||
|
$trMeta = RecurrenceTransactionMeta::create(
|
||||||
|
[
|
||||||
|
'rt_id' => $transaction->id,
|
||||||
|
'name' => 'category_name',
|
||||||
|
'value' => $trArray['category_name'],
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create meta data:
|
return $recurrence;
|
||||||
if(\count($data['meta']['tags']) > 0) {
|
|
||||||
// todo store tags
|
|
||||||
}
|
|
||||||
|
|
||||||
exit;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,7 +28,6 @@ use Carbon\Carbon;
|
|||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Http\Requests\RecurrenceFormRequest;
|
use FireflyIII\Http\Requests\RecurrenceFormRequest;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
|
||||||
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
@ -40,8 +39,6 @@ class CreateController extends Controller
|
|||||||
{
|
{
|
||||||
/** @var BudgetRepositoryInterface */
|
/** @var BudgetRepositoryInterface */
|
||||||
private $budgets;
|
private $budgets;
|
||||||
/** @var PiggyBankRepositoryInterface */
|
|
||||||
private $piggyBanks;
|
|
||||||
/** @var RecurringRepositoryInterface */
|
/** @var RecurringRepositoryInterface */
|
||||||
private $recurring;
|
private $recurring;
|
||||||
|
|
||||||
@ -59,9 +56,8 @@ class CreateController extends Controller
|
|||||||
app('view')->share('title', trans('firefly.recurrences'));
|
app('view')->share('title', trans('firefly.recurrences'));
|
||||||
app('view')->share('subTitle', trans('firefly.create_new_recurrence'));
|
app('view')->share('subTitle', trans('firefly.create_new_recurrence'));
|
||||||
|
|
||||||
$this->recurring = app(RecurringRepositoryInterface::class);
|
$this->recurring = app(RecurringRepositoryInterface::class);
|
||||||
$this->budgets = app(BudgetRepositoryInterface::class);
|
$this->budgets = app(BudgetRepositoryInterface::class);
|
||||||
$this->piggyBanks = app(PiggyBankRepositoryInterface::class);
|
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
@ -75,14 +71,18 @@ class CreateController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function create(Request $request)
|
public function create(Request $request)
|
||||||
{
|
{
|
||||||
// todo refactor to expandedform method.
|
$budgets = app('expandedform')->makeSelectListWithEmpty($this->budgets->getActiveBudgets());
|
||||||
$budgets = app('expandedform')->makeSelectListWithEmpty($this->budgets->getActiveBudgets());
|
$defaultCurrency = app('amount')->getDefaultCurrency();
|
||||||
$defaultCurrency = app('amount')->getDefaultCurrency();
|
$tomorrow = new Carbon;
|
||||||
$piggyBanks = $this->piggyBanks->getPiggyBanksWithAmount();
|
$oldRepetitionType = $request->old('repetition_type');
|
||||||
$piggies = app('expandedform')->makeSelectListWithEmpty($piggyBanks);
|
|
||||||
$tomorrow = new Carbon;
|
|
||||||
$tomorrow->addDay();
|
$tomorrow->addDay();
|
||||||
|
|
||||||
|
// put previous url in session if not redirect from store (not "create another").
|
||||||
|
if (true !== session('recurring.create.fromStore')) {
|
||||||
|
$this->rememberPreviousUri('recurring.create.uri');
|
||||||
|
}
|
||||||
|
$request->session()->forget('recurring.create.fromStore');
|
||||||
|
|
||||||
// types of repetitions:
|
// types of repetitions:
|
||||||
$typesOfRepetitions = [
|
$typesOfRepetitions = [
|
||||||
'forever' => trans('firefly.repeat_forever'),
|
'forever' => trans('firefly.repeat_forever'),
|
||||||
@ -99,18 +99,33 @@ class CreateController extends Controller
|
|||||||
];
|
];
|
||||||
$request->session()->flash('preFilled', $preFilled);
|
$request->session()->flash('preFilled', $preFilled);
|
||||||
|
|
||||||
return view('recurring.create', compact('tomorrow', 'preFilled', 'piggies', 'typesOfRepetitions', 'defaultCurrency', 'budgets'));
|
return view('recurring.create', compact('tomorrow', 'oldRepetitionType', 'preFilled', 'piggies', 'typesOfRepetitions', 'defaultCurrency', 'budgets'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param RecurrenceFormRequest $request
|
* @param RecurrenceFormRequest $request
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
|
||||||
|
* @throws \FireflyIII\Exceptions\FireflyException
|
||||||
*/
|
*/
|
||||||
public function store(RecurrenceFormRequest $request)
|
public function store(RecurrenceFormRequest $request)
|
||||||
{
|
{
|
||||||
$data = $request->getAll();
|
$data = $request->getAll();
|
||||||
$this->recurring->store($data);
|
$recurrence = $this->recurring->store($data);
|
||||||
var_dump($data);
|
|
||||||
exit;
|
$request->session()->flash('success', (string)trans('firefly.stored_new_recurrence', ['title' => $recurrence->title]));
|
||||||
|
app('preferences')->mark();
|
||||||
|
|
||||||
|
if (1 === (int)$request->get('create_another')) {
|
||||||
|
// set value so create routine will not overwrite URL:
|
||||||
|
$request->session()->put('recurring.create.fromStore', true);
|
||||||
|
|
||||||
|
return redirect(route('recurring.create'))->withInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
// redirect to previous URL.
|
||||||
|
return redirect($this->getPreviousUri('recurring.create.uri'));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -26,6 +26,8 @@ namespace FireflyIII\Http\Controllers\Recurring;
|
|||||||
|
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
use FireflyIII\Models\Recurrence;
|
use FireflyIII\Models\Recurrence;
|
||||||
|
use FireflyIII\Models\RecurrenceRepetition;
|
||||||
|
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -33,6 +35,9 @@ use FireflyIII\Models\Recurrence;
|
|||||||
*/
|
*/
|
||||||
class EditController extends Controller
|
class EditController extends Controller
|
||||||
{
|
{
|
||||||
|
/** @var RecurringRepositoryInterface */
|
||||||
|
private $recurring;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -56,10 +61,23 @@ class EditController extends Controller
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Recurrence $recurrence
|
* @param Recurrence $recurrence
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function edit(Recurrence $recurrence) {
|
public function edit(Recurrence $recurrence)
|
||||||
|
{
|
||||||
|
// get recurrence type:
|
||||||
|
// todo move to repository
|
||||||
|
/** @var RecurrenceRepetition $repetition */
|
||||||
|
$repetition = $recurrence->recurrenceRepetitions()->first();
|
||||||
|
$currentRepetitionType = $repetition->repetition_type;
|
||||||
|
if ('' !== $repetition->repetition_moment) {
|
||||||
|
$currentRepetitionType .= ',' . $repetition->repetition_moment;
|
||||||
|
}
|
||||||
|
|
||||||
return view('recurring.edit', compact('recurrence'));
|
// todo handle old repetition type as well.
|
||||||
|
|
||||||
|
return view('recurring.edit', compact('recurrence','currentRepetitionType'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ class IndexController extends Controller
|
|||||||
* @throws FireflyException
|
* @throws FireflyException
|
||||||
* @return JsonResponse
|
* @return JsonResponse
|
||||||
*/
|
*/
|
||||||
function events(RecurringRepositoryInterface $repository, Request $request): JsonResponse
|
function events(Request $request): JsonResponse
|
||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
|
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
|
||||||
@ -118,14 +118,14 @@ class IndexController extends Controller
|
|||||||
throw new FireflyException(sprintf('Cannot generate events for type that ends at "%s".', $endsAt));
|
throw new FireflyException(sprintf('Cannot generate events for type that ends at "%s".', $endsAt));
|
||||||
case 'forever':
|
case 'forever':
|
||||||
// simply generate up until $end. No change from default behavior.
|
// simply generate up until $end. No change from default behavior.
|
||||||
$occurrences = $repository->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
|
$occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
|
||||||
break;
|
break;
|
||||||
case 'until_date':
|
case 'until_date':
|
||||||
$actualEnd = $endDate ?? clone $end;
|
$actualEnd = $endDate ?? clone $end;
|
||||||
$occurrences = $repository->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
|
$occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
|
||||||
break;
|
break;
|
||||||
case 'times':
|
case 'times':
|
||||||
$occurrences = $repository->getXOccurrences($repetition, $actualStart, $repetitions);
|
$occurrences = $this->recurring->getXOccurrences($repetition, $actualStart, $repetitions);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ class IndexController extends Controller
|
|||||||
$today = new Carbon;
|
$today = new Carbon;
|
||||||
$date = Carbon::createFromFormat('Y-m-d', $request->get('date'));
|
$date = Carbon::createFromFormat('Y-m-d', $request->get('date'));
|
||||||
$result = [];
|
$result = [];
|
||||||
if ($date > $today) {
|
if ($date > $today || $request->get('past') === 'true') {
|
||||||
$weekly = sprintf('weekly,%s', $date->dayOfWeekIso);
|
$weekly = sprintf('weekly,%s', $date->dayOfWeekIso);
|
||||||
$monthly = sprintf('monthly,%s', $date->day);
|
$monthly = sprintf('monthly,%s', $date->day);
|
||||||
$dayOfWeek = trans(sprintf('config.dow_%s', $date->dayOfWeekIso));
|
$dayOfWeek = trans(sprintf('config.dow_%s', $date->dayOfWeekIso));
|
||||||
|
@ -50,14 +50,8 @@ class SingleController extends Controller
|
|||||||
{
|
{
|
||||||
/** @var AttachmentHelperInterface */
|
/** @var AttachmentHelperInterface */
|
||||||
private $attachments;
|
private $attachments;
|
||||||
|
|
||||||
/** @var BudgetRepositoryInterface */
|
/** @var BudgetRepositoryInterface */
|
||||||
private $budgets;
|
private $budgets;
|
||||||
/** @var CurrencyRepositoryInterface */
|
|
||||||
private $currency;
|
|
||||||
/** @var PiggyBankRepositoryInterface */
|
|
||||||
private $piggyBanks;
|
|
||||||
|
|
||||||
/** @var JournalRepositoryInterface */
|
/** @var JournalRepositoryInterface */
|
||||||
private $repository;
|
private $repository;
|
||||||
|
|
||||||
@ -77,9 +71,7 @@ class SingleController extends Controller
|
|||||||
$this->middleware(
|
$this->middleware(
|
||||||
function ($request, $next) {
|
function ($request, $next) {
|
||||||
$this->budgets = app(BudgetRepositoryInterface::class);
|
$this->budgets = app(BudgetRepositoryInterface::class);
|
||||||
$this->piggyBanks = app(PiggyBankRepositoryInterface::class);
|
|
||||||
$this->attachments = app(AttachmentHelperInterface::class);
|
$this->attachments = app(AttachmentHelperInterface::class);
|
||||||
$this->currency = app(CurrencyRepositoryInterface::class);
|
|
||||||
$this->repository = app(JournalRepositoryInterface::class);
|
$this->repository = app(JournalRepositoryInterface::class);
|
||||||
|
|
||||||
app('view')->share('title', trans('firefly.transactions'));
|
app('view')->share('title', trans('firefly.transactions'));
|
||||||
@ -101,7 +93,6 @@ class SingleController extends Controller
|
|||||||
$destination = $this->repository->getJournalDestinationAccounts($journal)->first();
|
$destination = $this->repository->getJournalDestinationAccounts($journal)->first();
|
||||||
$budgetId = $this->repository->getJournalBudgetId($journal);
|
$budgetId = $this->repository->getJournalBudgetId($journal);
|
||||||
$categoryName = $this->repository->getJournalCategoryName($journal);
|
$categoryName = $this->repository->getJournalCategoryName($journal);
|
||||||
|
|
||||||
$tags = implode(',', $this->repository->getTags($journal));
|
$tags = implode(',', $this->repository->getTags($journal));
|
||||||
/** @var Transaction $transaction */
|
/** @var Transaction $transaction */
|
||||||
$transaction = $journal->transactions()->first();
|
$transaction = $journal->transactions()->first();
|
||||||
@ -156,8 +147,6 @@ class SingleController extends Controller
|
|||||||
$what = strtolower($what);
|
$what = strtolower($what);
|
||||||
$what = $request->old('what') ?? $what;
|
$what = $request->old('what') ?? $what;
|
||||||
$budgets = ExpandedForm::makeSelectListWithEmpty($this->budgets->getActiveBudgets());
|
$budgets = ExpandedForm::makeSelectListWithEmpty($this->budgets->getActiveBudgets());
|
||||||
$piggyBanks = $this->piggyBanks->getPiggyBanksWithAmount();
|
|
||||||
$piggies = ExpandedForm::makeSelectListWithEmpty($piggyBanks);
|
|
||||||
$preFilled = session()->has('preFilled') ? session('preFilled') : [];
|
$preFilled = session()->has('preFilled') ? session('preFilled') : [];
|
||||||
$subTitle = trans('form.add_new_' . $what);
|
$subTitle = trans('form.add_new_' . $what);
|
||||||
$subTitleIcon = 'fa-plus';
|
$subTitleIcon = 'fa-plus';
|
||||||
@ -179,11 +168,9 @@ class SingleController extends Controller
|
|||||||
}
|
}
|
||||||
session()->forget('transactions.create.fromStore');
|
session()->forget('transactions.create.fromStore');
|
||||||
|
|
||||||
asort($piggies);
|
|
||||||
|
|
||||||
return view(
|
return view(
|
||||||
'transactions.single.create',
|
'transactions.single.create',
|
||||||
compact('subTitleIcon', 'budgets', 'what', 'piggies', 'subTitle', 'optionalFields', 'preFilled')
|
compact('subTitleIcon', 'budgets', 'what', 'subTitle', 'optionalFields', 'preFilled')
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ use Carbon\Carbon;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Rules\ValidRecurrenceRepetitionType;
|
use FireflyIII\Rules\ValidRecurrenceRepetitionType;
|
||||||
|
use FireflyIII\Rules\ValidRecurrenceRepetitionValue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RecurrenceFormRequest
|
* Class RecurrenceFormRequest
|
||||||
@ -49,8 +50,8 @@ class RecurrenceFormRequest extends Request
|
|||||||
*/
|
*/
|
||||||
public function getAll(): array
|
public function getAll(): array
|
||||||
{
|
{
|
||||||
$data = $this->all();
|
$repetitionData = $this->parseRepetitionData();
|
||||||
$return = [
|
$return = [
|
||||||
'recurrence' => [
|
'recurrence' => [
|
||||||
'type' => $this->string('transaction_type'),
|
'type' => $this->string('transaction_type'),
|
||||||
'title' => $this->string('title'),
|
'title' => $this->string('title'),
|
||||||
@ -81,7 +82,9 @@ class RecurrenceFormRequest extends Request
|
|||||||
],
|
],
|
||||||
'repetitions' => [
|
'repetitions' => [
|
||||||
[
|
[
|
||||||
'skip' => $this->integer('skip'),
|
'type' => $repetitionData['type'],
|
||||||
|
'moment' => $repetitionData['moment'],
|
||||||
|
'skip' => $this->integer('skip'),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
@ -101,6 +104,14 @@ class RecurrenceFormRequest extends Request
|
|||||||
$return['transactions'][0]['source_account_id'] = $this->integer('source_account_id');
|
$return['transactions'][0]['source_account_id'] = $this->integer('source_account_id');
|
||||||
$return['transactions'][0]['destination_account_name'] = $this->string('destination_account_name');
|
$return['transactions'][0]['destination_account_name'] = $this->string('destination_account_name');
|
||||||
break;
|
break;
|
||||||
|
case 'deposit':
|
||||||
|
$return['transactions'][0]['source_account_name'] = $this->string('source_account_name');
|
||||||
|
$return['transactions'][0]['destination_account_id'] = $this->integer('destination_account_id');
|
||||||
|
break;
|
||||||
|
case 'transfer':
|
||||||
|
$return['transactions'][0]['source_account_id'] = $this->integer('source_account_id');
|
||||||
|
$return['transactions'][0]['destination_account_id'] = $this->integer('destination_account_id');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
@ -120,7 +131,7 @@ class RecurrenceFormRequest extends Request
|
|||||||
//'title' => 'required|between:1,255|uniqueObjectForUser:recurrences,title',
|
//'title' => 'required|between:1,255|uniqueObjectForUser:recurrences,title',
|
||||||
'title' => 'required|between:1,255',
|
'title' => 'required|between:1,255',
|
||||||
'first_date' => 'required|date|after:' . $today->format('Y-m-d'),
|
'first_date' => 'required|date|after:' . $today->format('Y-m-d'),
|
||||||
'repetition_type' => ['required', new ValidRecurrenceRepetitionType, 'between:1,20'],
|
'repetition_type' => ['required', new ValidRecurrenceRepetitionValue, new ValidRecurrenceRepetitionType, 'between:1,20'],
|
||||||
'skip' => 'required|numeric|between:0,31',
|
'skip' => 'required|numeric|between:0,31',
|
||||||
|
|
||||||
// optional for recurrence:
|
// optional for recurrence:
|
||||||
@ -186,4 +197,38 @@ class RecurrenceFormRequest extends Request
|
|||||||
|
|
||||||
return $rules;
|
return $rules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function parseRepetitionData(): array
|
||||||
|
{
|
||||||
|
$value = $this->string('repetition_type');
|
||||||
|
$return = [
|
||||||
|
'type' => '',
|
||||||
|
'moment' => '',
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($value === 'daily') {
|
||||||
|
$return['type'] = $value;
|
||||||
|
}
|
||||||
|
//monthly,17
|
||||||
|
//ndom,3,7
|
||||||
|
if (\in_array(substr($value, 0, 6), ['yearly', 'weekly'])) {
|
||||||
|
$return['type'] = substr($value, 0, 6);
|
||||||
|
$return['moment'] = substr($value, 7);
|
||||||
|
}
|
||||||
|
if (0 === strpos($value, 'monthly')) {
|
||||||
|
$return['type'] = substr($value, 0, 7);
|
||||||
|
$return['moment'] = substr($value, 8);
|
||||||
|
}
|
||||||
|
if (0 === strpos($value, 'ndom')) {
|
||||||
|
$return['type'] = substr($value, 0, 4);
|
||||||
|
$return['moment'] = substr($value, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
@ -65,14 +65,19 @@ class Recurrence extends Model
|
|||||||
*/
|
*/
|
||||||
protected $casts
|
protected $casts
|
||||||
= [
|
= [
|
||||||
'created_at' => 'datetime',
|
'created_at' => 'datetime',
|
||||||
'updated_at' => 'datetime',
|
'updated_at' => 'datetime',
|
||||||
'first_date' => 'date',
|
'deleted_at' => 'datetime',
|
||||||
'latest_date' => 'date',
|
'title' => 'string',
|
||||||
'active' => 'bool',
|
'description' => 'string',
|
||||||
'apply_rules' => 'bool',
|
'first_date' => 'date',
|
||||||
|
'repeat_until' => 'date',
|
||||||
|
'latest_date' => 'date',
|
||||||
|
'repetitions' => 'int',
|
||||||
|
'active' => 'bool',
|
||||||
|
'apply_rules' => 'bool',
|
||||||
];
|
];
|
||||||
/** @var array */
|
/** @var array */
|
||||||
protected $fillable
|
protected $fillable
|
||||||
= ['user_id', 'transaction_type_id', 'title', 'description', 'first_date', 'repeat_until', 'latest_date', 'repetitions', 'apply_rules', 'active'];
|
= ['user_id', 'transaction_type_id', 'title', 'description', 'first_date', 'repeat_until', 'latest_date', 'repetitions', 'apply_rules', 'active'];
|
||||||
/** @var string */
|
/** @var string */
|
||||||
|
@ -35,6 +35,18 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
*/
|
*/
|
||||||
class RecurrenceMeta extends Model
|
class RecurrenceMeta extends Model
|
||||||
{
|
{
|
||||||
|
/** @var array */
|
||||||
|
protected $casts
|
||||||
|
= [
|
||||||
|
'created_at' => 'datetime',
|
||||||
|
'updated_at' => 'datetime',
|
||||||
|
'deleted_at' => 'datetime',
|
||||||
|
'name' => 'string',
|
||||||
|
'value' => 'string',
|
||||||
|
];
|
||||||
|
/** @var array */
|
||||||
|
protected $fillable = ['recurrence_id', 'name', 'value'];
|
||||||
|
/** @var string */
|
||||||
protected $table = 'recurrences_meta';
|
protected $table = 'recurrences_meta';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,6 +40,18 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
*/
|
*/
|
||||||
class RecurrenceRepetition extends Model
|
class RecurrenceRepetition extends Model
|
||||||
{
|
{
|
||||||
|
/** @var array */
|
||||||
|
protected $casts
|
||||||
|
= [
|
||||||
|
'created_at' => 'datetime',
|
||||||
|
'updated_at' => 'datetime',
|
||||||
|
'deleted_at' => 'datetime',
|
||||||
|
'repetition_type' => 'string',
|
||||||
|
'repetition_moment' => 'string',
|
||||||
|
'repetition_skip' => 'int',
|
||||||
|
];
|
||||||
|
protected $fillable = ['recurrence_id', 'repetition_type', 'repetition_moment', 'repetition_skip'];
|
||||||
|
/** @var string */
|
||||||
protected $table = 'recurrences_repetitions';
|
protected $table = 'recurrences_repetitions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,6 +48,16 @@ use Illuminate\Database\Eloquent\Relations\HasMany;
|
|||||||
class RecurrenceTransaction extends Model
|
class RecurrenceTransaction extends Model
|
||||||
{
|
{
|
||||||
/** @var array */
|
/** @var array */
|
||||||
|
protected $casts
|
||||||
|
= [
|
||||||
|
'created_at' => 'datetime',
|
||||||
|
'updated_at' => 'datetime',
|
||||||
|
'deleted_at' => 'datetime',
|
||||||
|
'amount' => 'string',
|
||||||
|
'foreign_amount' => 'string',
|
||||||
|
'description' => 'string',
|
||||||
|
];
|
||||||
|
/** @var array */
|
||||||
protected $fillable
|
protected $fillable
|
||||||
= ['recurrence_id', 'transaction_currency_id', 'foreign_currency_id', 'source_account_id', 'destination_account_id', 'amount', 'foreign_amount',
|
= ['recurrence_id', 'transaction_currency_id', 'foreign_currency_id', 'source_account_id', 'destination_account_id', 'amount', 'foreign_amount',
|
||||||
'description'];
|
'description'];
|
||||||
|
@ -35,6 +35,17 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
|||||||
*/
|
*/
|
||||||
class RecurrenceTransactionMeta extends Model
|
class RecurrenceTransactionMeta extends Model
|
||||||
{
|
{
|
||||||
|
/** @var array */
|
||||||
|
protected $casts
|
||||||
|
= [
|
||||||
|
'created_at' => 'datetime',
|
||||||
|
'updated_at' => 'datetime',
|
||||||
|
'deleted_at' => 'datetime',
|
||||||
|
'name' => 'string',
|
||||||
|
'value' => 'string',
|
||||||
|
];
|
||||||
|
protected $fillable = ['rt_id', 'name', 'value'];
|
||||||
|
/** @var string */
|
||||||
protected $table = 'rt_meta';
|
protected $table = 'rt_meta';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,7 +54,7 @@ class RecurrenceTransactionMeta extends Model
|
|||||||
*/
|
*/
|
||||||
public function recurrenceTransaction(): BelongsTo
|
public function recurrenceTransaction(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(RecurrenceTransaction::class);
|
return $this->belongsTo(RecurrenceTransaction::class, 'rt_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
107
app/Rules/ValidRecurrenceRepetitionValue.php
Normal file
107
app/Rules/ValidRecurrenceRepetitionValue.php
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ValidRecurrenceRepetitionValue.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\Rules;
|
||||||
|
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Contracts\Validation\Rule;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ValidRecurrenceRepetitionValue
|
||||||
|
*/
|
||||||
|
class ValidRecurrenceRepetitionValue implements Rule
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation error message.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function message(): string
|
||||||
|
{
|
||||||
|
return trans('validation.valid_recurrence_rep_type');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine if the validation rule passes.
|
||||||
|
*
|
||||||
|
* @param string $attribute
|
||||||
|
* @param mixed $value
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function passes($attribute, $value): bool
|
||||||
|
{
|
||||||
|
$value = (string)$value;
|
||||||
|
|
||||||
|
if ($value === 'daily') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 === strpos($value, 'monthly')) {
|
||||||
|
$dayOfMonth = (int)substr($value, 8);
|
||||||
|
|
||||||
|
return $dayOfMonth > 0 && $dayOfMonth < 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ndom,3,7
|
||||||
|
// nth x-day of the month.
|
||||||
|
if (0 === strpos($value, 'ndom')) {
|
||||||
|
$parameters = explode(',', substr($value, 5));
|
||||||
|
if (\count($parameters) !== 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$nthDay = (int)($parameters[0] ?? 0.0);
|
||||||
|
$dayOfWeek = (int)($parameters[1] ?? 0.0);
|
||||||
|
if ($nthDay < 1 || $nthDay > 5) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dayOfWeek > 0 && $dayOfWeek < 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
//weekly,7
|
||||||
|
if (0 === strpos($value, 'weekly')) {
|
||||||
|
$dayOfWeek = (int)substr($value, 7);
|
||||||
|
|
||||||
|
return $dayOfWeek > 0 && $dayOfWeek < 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
//yearly,2018-01-01
|
||||||
|
if (0 === strpos($value, 'yearly')) {
|
||||||
|
// rest of the string must be valid date:
|
||||||
|
$dateString = substr($value, 7);
|
||||||
|
try {
|
||||||
|
$date = Carbon::createFromFormat('Y-m-d', $dateString);
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -27,10 +27,12 @@ use Carbon\Carbon;
|
|||||||
use Eloquent;
|
use Eloquent;
|
||||||
use FireflyIII\Models\Account;
|
use FireflyIII\Models\Account;
|
||||||
use FireflyIII\Models\AccountType;
|
use FireflyIII\Models\AccountType;
|
||||||
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Models\RuleGroup;
|
use FireflyIII\Models\RuleGroup;
|
||||||
use FireflyIII\Models\TransactionCurrency;
|
use FireflyIII\Models\TransactionCurrency;
|
||||||
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
|
||||||
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
|
||||||
use Form;
|
use Form;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@ -183,6 +185,7 @@ class ExpandedForm
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
* @throws \FireflyIII\Exceptions\FireflyException
|
* @throws \FireflyIII\Exceptions\FireflyException
|
||||||
|
* @throws \Throwable
|
||||||
*/
|
*/
|
||||||
public function balance(string $name, $value = null, array $options = []): string
|
public function balance(string $name, $value = null, array $options = []): string
|
||||||
{
|
{
|
||||||
@ -506,8 +509,9 @@ class ExpandedForm
|
|||||||
* @return string
|
* @return string
|
||||||
* @throws \Throwable
|
* @throws \Throwable
|
||||||
*/
|
*/
|
||||||
public function password(string $name, array $options = []): string
|
public function password(string $name, array $options = null): string
|
||||||
{
|
{
|
||||||
|
$options = $options ?? [];
|
||||||
$label = $this->label($name, $options);
|
$label = $this->label($name, $options);
|
||||||
$options = $this->expandOptionArray($name, $label, $options);
|
$options = $this->expandOptionArray($name, $label, $options);
|
||||||
$classes = $this->getHolderClasses($name);
|
$classes = $this->getHolderClasses($name);
|
||||||
@ -516,6 +520,30 @@ class ExpandedForm
|
|||||||
return $html;
|
return $html;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $name
|
||||||
|
* @param null $value
|
||||||
|
* @param array $options
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
* @throws \Throwable
|
||||||
|
*/
|
||||||
|
public function piggyBankList(string $name, $value = null, array $options = null): string
|
||||||
|
{
|
||||||
|
$options = $options ?? [];
|
||||||
|
// make repositories
|
||||||
|
/** @var PiggyBankRepositoryInterface $repository */
|
||||||
|
$repository = app(PiggyBankRepositoryInterface::class);
|
||||||
|
$piggyBanks = $repository->getPiggyBanksWithAmount();
|
||||||
|
$array = [];
|
||||||
|
/** @var PiggyBank $piggy */
|
||||||
|
foreach ($piggyBanks as $piggy) {
|
||||||
|
$array[$piggy->id] = $piggy->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->select($name, $array, $value, $options);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $name
|
* @param string $name
|
||||||
* @param null $value
|
* @param null $value
|
||||||
|
@ -188,7 +188,8 @@ return [
|
|||||||
'is_safe' => [
|
'is_safe' => [
|
||||||
'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location',
|
'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location',
|
||||||
'multiRadio', 'file', 'multiCheckbox', 'staticText', 'amountSmall', 'password', 'nonSelectableBalance', 'nonSelectableAmount',
|
'multiRadio', 'file', 'multiCheckbox', 'staticText', 'amountSmall', 'password', 'nonSelectableBalance', 'nonSelectableAmount',
|
||||||
'number', 'assetAccountList','amountNoCurrency','currencyList','ruleGroupList','assetAccountCheckList','ruleGroupListWithEmpty'
|
'number', 'assetAccountList','amountNoCurrency','currencyList','ruleGroupList','assetAccountCheckList','ruleGroupListWithEmpty',
|
||||||
|
'piggyBankList'
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
'Form' => [
|
'Form' => [
|
||||||
|
7
public/js/ff/recurring/create.js
vendored
7
public/js/ff/recurring/create.js
vendored
@ -114,9 +114,14 @@ function parseRepetitionSuggestions(data) {
|
|||||||
|
|
||||||
var select = $('#ffInput_repetition_type');
|
var select = $('#ffInput_repetition_type');
|
||||||
select.empty();
|
select.empty();
|
||||||
|
var opt;
|
||||||
for (var k in data) {
|
for (var k in data) {
|
||||||
if (data.hasOwnProperty(k)) {
|
if (data.hasOwnProperty(k)) {
|
||||||
select.append($('<option>').val(k).attr('label', data[k]).text(data[k]));
|
opt = $('<option>').val(k).attr('label', data[k]).text(data[k]);
|
||||||
|
if(k === oldRepetitionType) {
|
||||||
|
opt.attr('selected','selected');
|
||||||
|
}
|
||||||
|
select.append(opt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
select.removeAttr('disabled');
|
select.removeAttr('disabled');
|
||||||
|
237
public/js/ff/recurring/edit.js
vendored
Normal file
237
public/js/ff/recurring/edit.js
vendored
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
* edit.js
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** global: Modernizr, currencies */
|
||||||
|
|
||||||
|
var calendar;
|
||||||
|
|
||||||
|
$(document).ready(function () {
|
||||||
|
"use strict";
|
||||||
|
if (!Modernizr.inputtypes.date) {
|
||||||
|
$('input[type="date"]').datepicker(
|
||||||
|
{
|
||||||
|
dateFormat: 'yy-mm-dd'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
initializeButtons();
|
||||||
|
initializeAutoComplete();
|
||||||
|
respondToFirstDateChange();
|
||||||
|
respondToRepetitionEnd();
|
||||||
|
$('.switch-button').on('click', switchTransactionType);
|
||||||
|
$('#ffInput_repetition_end').on('change', respondToRepetitionEnd);
|
||||||
|
$('#ffInput_first_date').on('change', respondToFirstDateChange);
|
||||||
|
|
||||||
|
// create calendar on load:
|
||||||
|
calendar = $('#recurring_calendar').fullCalendar(
|
||||||
|
{
|
||||||
|
defaultDate: '2018-06-13',
|
||||||
|
editable: false,
|
||||||
|
height: 400,
|
||||||
|
width: 200,
|
||||||
|
contentHeight: 400,
|
||||||
|
aspectRatio: 1.25,
|
||||||
|
eventLimit: true,
|
||||||
|
eventSources: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#calendar-link').on('click', showRepCalendar);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function showRepCalendar() {
|
||||||
|
|
||||||
|
// pre-append URL with repetition info:
|
||||||
|
var newEventsUri = eventsUri + '?type=' + $('#ffInput_repetition_type').val();
|
||||||
|
newEventsUri += '&skip=' + $('#ffInput_skip').val();
|
||||||
|
newEventsUri += '&ends=' + $('#ffInput_repetition_end').val();
|
||||||
|
newEventsUri += '&end_date=' + $('#ffInput_repeat_until').val();
|
||||||
|
newEventsUri += '&reps=' + $('#ffInput_repetitions').val();
|
||||||
|
newEventsUri += '&first_date=' + $('#ffInput_first_date').val();
|
||||||
|
|
||||||
|
// remove all event sources from calendar:
|
||||||
|
calendar.fullCalendar('removeEventSources');
|
||||||
|
|
||||||
|
// add a new one:
|
||||||
|
calendar.fullCalendar('addEventSource', newEventsUri);
|
||||||
|
$('#calendarModal').modal('show');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function respondToRepetitionEnd() {
|
||||||
|
var obj = $('#ffInput_repetition_end');
|
||||||
|
var value = obj.val();
|
||||||
|
switch (value) {
|
||||||
|
case 'forever':
|
||||||
|
$('#repeat_until_holder').hide();
|
||||||
|
$('#repetitions_holder').hide();
|
||||||
|
break;
|
||||||
|
case 'until_date':
|
||||||
|
$('#repeat_until_holder').show();
|
||||||
|
$('#repetitions_holder').hide();
|
||||||
|
break;
|
||||||
|
case 'times':
|
||||||
|
$('#repeat_until_holder').hide();
|
||||||
|
$('#repetitions_holder').show();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function respondToFirstDateChange() {
|
||||||
|
var obj = $('#ffInput_first_date');
|
||||||
|
var select = $('#ffInput_repetition_type');
|
||||||
|
var date = obj.val();
|
||||||
|
select.prop('disabled', true);
|
||||||
|
$.getJSON(suggestUri, {date: date,past:true}).fail(function () {
|
||||||
|
console.error('Could not load repetition suggestions');
|
||||||
|
alert('Could not load repetition suggestions');
|
||||||
|
}).done(parseRepetitionSuggestions);
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseRepetitionSuggestions(data) {
|
||||||
|
|
||||||
|
var select = $('#ffInput_repetition_type');
|
||||||
|
select.empty();
|
||||||
|
var opt;
|
||||||
|
for (var k in data) {
|
||||||
|
if (data.hasOwnProperty(k)) {
|
||||||
|
opt = $('<option>').val(k).attr('label', data[k]).text(data[k]);
|
||||||
|
if(k === currentRepetitionType) {
|
||||||
|
opt.attr('selected','selected');
|
||||||
|
}
|
||||||
|
select.append(opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
select.removeAttr('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
function initializeAutoComplete() {
|
||||||
|
// auto complete things:
|
||||||
|
$.getJSON('json/tags').done(function (data) {
|
||||||
|
var opt = {
|
||||||
|
typeahead: {
|
||||||
|
source: data,
|
||||||
|
afterSelect: function () {
|
||||||
|
this.$element.val("");
|
||||||
|
},
|
||||||
|
autoSelect: false,
|
||||||
|
},
|
||||||
|
autoSelect: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
$('input[name="tags"]').tagsinput(
|
||||||
|
opt
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($('input[name="destination_account_name"]').length > 0) {
|
||||||
|
$.getJSON('json/expense-accounts').done(function (data) {
|
||||||
|
$('input[name="destination_account_name"]').typeahead({source: data, autoSelect: false});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($('input[name="source_account_name"]').length > 0) {
|
||||||
|
$.getJSON('json/revenue-accounts').done(function (data) {
|
||||||
|
$('input[name="source_account_name"]').typeahead({source: data, autoSelect: false});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$.getJSON('json/categories').done(function (data) {
|
||||||
|
$('input[name="category"]').typeahead({source: data, autoSelect: false});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param e
|
||||||
|
*/
|
||||||
|
function switchTransactionType(e) {
|
||||||
|
var target = $(e.target);
|
||||||
|
transactionType = target.data('value');
|
||||||
|
initializeButtons();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loop the three buttons and do some magic.
|
||||||
|
*/
|
||||||
|
function initializeButtons() {
|
||||||
|
console.log('Now in initializeButtons()');
|
||||||
|
$.each($('.switch-button'), function (i, v) {
|
||||||
|
var btn = $(v);
|
||||||
|
console.log('Value is ' + btn.data('value'));
|
||||||
|
if (btn.data('value') === transactionType) {
|
||||||
|
btn.addClass('btn-info disabled').removeClass('btn-default');
|
||||||
|
$('input[name="transaction_type"]').val(transactionType);
|
||||||
|
} else {
|
||||||
|
btn.removeClass('btn-info disabled').addClass('btn-default');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
updateFormFields();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide and/or show stuff when switching:
|
||||||
|
*/
|
||||||
|
function updateFormFields() {
|
||||||
|
|
||||||
|
if (transactionType === 'withdrawal') {
|
||||||
|
// hide source account name:
|
||||||
|
$('#source_account_name_holder').hide();
|
||||||
|
|
||||||
|
// show source account ID:
|
||||||
|
$('#source_account_id_holder').show();
|
||||||
|
|
||||||
|
// show destination name:
|
||||||
|
$('#destination_account_name_holder').show();
|
||||||
|
|
||||||
|
// hide destination ID:
|
||||||
|
$('#destination_account_id_holder').hide();
|
||||||
|
|
||||||
|
// show budget
|
||||||
|
$('#budget_id_holder').show();
|
||||||
|
|
||||||
|
// hide piggy bank:
|
||||||
|
$('#piggy_bank_id_holder').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transactionType === 'deposit') {
|
||||||
|
$('#source_account_name_holder').show();
|
||||||
|
$('#source_account_id_holder').hide();
|
||||||
|
$('#destination_account_name_holder').hide();
|
||||||
|
$('#destination_account_id_holder').show();
|
||||||
|
$('#budget_id_holder').hide();
|
||||||
|
$('#piggy_bank_id_holder').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (transactionType === 'transfer') {
|
||||||
|
$('#source_account_name_holder').hide();
|
||||||
|
$('#source_account_id_holder').show();
|
||||||
|
$('#destination_account_name_holder').hide();
|
||||||
|
$('#destination_account_id_holder').show();
|
||||||
|
$('#budget_id_holder').hide();
|
||||||
|
$('#piggy_bank_id_holder').show();
|
||||||
|
}
|
||||||
|
}
|
2
public/js/ff/transactions/single/create.js
vendored
2
public/js/ff/transactions/single/create.js
vendored
@ -224,7 +224,7 @@ function updateForm() {
|
|||||||
|
|
||||||
// optional piggies
|
// optional piggies
|
||||||
var showPiggies = 'block';
|
var showPiggies = 'block';
|
||||||
if (piggiesLength === 0) {
|
if ($('#ffInput_piggy_bank_id option').length === 0) {
|
||||||
showPiggies = 'none';
|
showPiggies = 'none';
|
||||||
}
|
}
|
||||||
document.getElementById('piggy_bank_id_holder').style.display = showPiggies;
|
document.getElementById('piggy_bank_id_holder').style.display = showPiggies;
|
||||||
|
@ -1229,6 +1229,7 @@ return [
|
|||||||
'recurring_meta_field_piggy_bank_id' => 'Piggy bank',
|
'recurring_meta_field_piggy_bank_id' => 'Piggy bank',
|
||||||
'create_new_recurrence' => 'Create new recurring transaction',
|
'create_new_recurrence' => 'Create new recurring transaction',
|
||||||
'help_first_date' => 'Indicate the first expected recurrence. This must be in the future.',
|
'help_first_date' => 'Indicate the first expected recurrence. This must be in the future.',
|
||||||
|
'help_first_date_no_past' => 'Indicate the first expected recurrence. Firefly III will not create transactions in the past.',
|
||||||
'mandatory_for_recurring' => 'Mandatory recurrence information',
|
'mandatory_for_recurring' => 'Mandatory recurrence information',
|
||||||
'mandatory_for_transaction' => 'Mandatory transaction information',
|
'mandatory_for_transaction' => 'Mandatory transaction information',
|
||||||
'optional_for_recurring' => 'Optional recurrence information',
|
'optional_for_recurring' => 'Optional recurrence information',
|
||||||
@ -1242,4 +1243,6 @@ return [
|
|||||||
'recurring_skips_one' => 'Every other',
|
'recurring_skips_one' => 'Every other',
|
||||||
'recurring_skips_more' => 'Skips :count occurrences',
|
'recurring_skips_more' => 'Skips :count occurrences',
|
||||||
'store_new_recurrence' => 'Store recurring transaction',
|
'store_new_recurrence' => 'Store recurring transaction',
|
||||||
|
'stored_new_recurrence' => 'Recurring transaction ":title" stored successfully.',
|
||||||
|
'edit_recurrence' => 'Edit recurring transaction ":title"',
|
||||||
];
|
];
|
||||||
|
@ -77,7 +77,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
<li class="{{ activeRoutePartial('bills') }} {{ activeRoutePartial('piggy-banks') }} {{ activeRoutePartial('rules') }} treeview">
|
<li class="{{ activeRoutePartial('bills') }} {{ activeRoutePartial('recurring') }} {{ activeRoutePartial('piggy-banks') }} {{ activeRoutePartial('rules') }} treeview">
|
||||||
<a href="#">
|
<a href="#">
|
||||||
<i class="fa fa-euro fa-fw"></i>
|
<i class="fa fa-euro fa-fw"></i>
|
||||||
<span>{{ 'moneyManagement'|_ }}</span>
|
<span>{{ 'moneyManagement'|_ }}</span>
|
||||||
|
@ -126,7 +126,7 @@
|
|||||||
{{ ExpandedForm.text('tags') }}
|
{{ ExpandedForm.text('tags') }}
|
||||||
|
|
||||||
{# RELATE THIS TRANSFER TO A PIGGY BANK #}
|
{# RELATE THIS TRANSFER TO A PIGGY BANK #}
|
||||||
{{ ExpandedForm.select('piggy_bank_id', piggies, 0) }}
|
{{ ExpandedForm.piggyBankList('piggy_bank_id',0) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -200,6 +200,7 @@
|
|||||||
var transactionType = "{{ preFilled.transaction_type }}";
|
var transactionType = "{{ preFilled.transaction_type }}";
|
||||||
var suggestUri = "{{ route('recurring.suggest') }}";
|
var suggestUri = "{{ route('recurring.suggest') }}";
|
||||||
var eventsUri = "{{ route('recurring.events') }}";
|
var eventsUri = "{{ route('recurring.events') }}";
|
||||||
|
var oldRepetitionType= "{{ oldRepetitionType }}";
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="js/ff/recurring/create.js?v={{ FF_VERSION }}"></script>
|
<script type="text/javascript" src="js/ff/recurring/create.js?v={{ FF_VERSION }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
214
resources/views/recurring/edit.twig
Normal file
214
resources/views/recurring/edit.twig
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
{% extends "./layout/default" %}
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
{{ Breadcrumbs.render(Route.getCurrentRoute.getName, recurrence) }}
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<form action="{{ route('recurring.update') }}" method="post" id="store" class="form-horizontal">
|
||||||
|
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
|
||||||
|
{# row with recurrence information #}
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||||
|
{# mandatory recurrence stuff #}
|
||||||
|
<div class="box box-primary">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'mandatory_for_recurring'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
{{ ExpandedForm.text('title',recurrence.title) }}
|
||||||
|
{{ ExpandedForm.date('first_date',recurrence.first_date.format('Y-m-d'), {helpText: trans('firefly.help_first_date_no_past')}) }}
|
||||||
|
{{ ExpandedForm.select('repetition_type', [], null, {helpText: trans('firefly.change_date_other_options')}) }}
|
||||||
|
{{ ExpandedForm.number('skip', 0) }}
|
||||||
|
{{ ExpandedForm.select('repetition_end', []) }} {#typesOfRepetitions#}
|
||||||
|
{{ ExpandedForm.date('repeat_until',null) }}
|
||||||
|
{{ ExpandedForm.number('repetitions',null) }}
|
||||||
|
|
||||||
|
{# calendar in popup #}
|
||||||
|
<div class="form-group" id="calendar_holder">
|
||||||
|
<label for="ffInput_calendar" class="col-sm-4 control-label">{{ trans('form.calendar') }}</label>
|
||||||
|
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<p class="form-control-static" id="ffInput_calendar">
|
||||||
|
<a href="#" id="calendar-link">{{ 'click_for_calendar'|_ }}</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||||
|
{# optional recurrence stuff #}
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'optional_for_recurring'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
{{ ExpandedForm.textarea('recurring_description') }}
|
||||||
|
|
||||||
|
{{ ExpandedForm.checkbox('active',1) }}
|
||||||
|
|
||||||
|
{{ ExpandedForm.checkbox('apply_rules',1) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||||
|
{# mandatory transaction information #}
|
||||||
|
<div class="box box-primary">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'mandatory_for_transaction'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<p><em>{{ 'mandatory_fields_for_tranaction'|_ }}</em></p>
|
||||||
|
{# three buttons to distinguish type of transaction#}
|
||||||
|
<div class="form-group" id="name_holder">
|
||||||
|
<label for="ffInput_type" class="col-sm-4 control-label">
|
||||||
|
{{ trans('form.transaction_type') }}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<div class="btn-group btn-group-sm">
|
||||||
|
<a href="#" class="btn btn-default switch-button" data-value="withdrawal">{{ 'withdrawal'|_ }}</a>
|
||||||
|
<a href="#" class="btn btn-default switch-button" data-value="deposit">{{ 'deposit'|_ }}</a>
|
||||||
|
<a href="#" class="btn btn-default switch-button" data-value="transfer">{{ 'transfer'|_ }}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="transaction_type" value="">
|
||||||
|
{# end of three buttons#}
|
||||||
|
|
||||||
|
{{ ExpandedForm.text('transaction_description') }}
|
||||||
|
{# transaction information (mandatory) #}
|
||||||
|
{{ ExpandedForm.currencyList('transaction_currency_id', defaultCurrency.id) }}
|
||||||
|
{{ ExpandedForm.amountNoCurrency('amount', []) }}
|
||||||
|
|
||||||
|
{# source account if withdrawal, or if transfer: #}
|
||||||
|
{{ ExpandedForm.assetAccountList('source_account_id', null, {label: trans('form.asset_source_account')}) }}
|
||||||
|
|
||||||
|
{# source account name for deposits: #}
|
||||||
|
{{ ExpandedForm.text('source_account_name', null, {label: trans('form.revenue_account')}) }}
|
||||||
|
|
||||||
|
{# destination if deposit or transfer: #}
|
||||||
|
{{ ExpandedForm.assetAccountList('destination_account_id', null, {label: trans('form.asset_destination_account')} ) }}
|
||||||
|
|
||||||
|
{# destination account name for withdrawals #}
|
||||||
|
{{ ExpandedForm.text('destination_account_name', null, {label: trans('form.expense_account')}) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||||
|
{# optional transaction information #}
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'optional_for_transaction'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
{# transaction information (optional) #}
|
||||||
|
{{ ExpandedForm.currencyList('foreign_currency_id', defaultCurrency.id) }}
|
||||||
|
{{ ExpandedForm.amountNoCurrency('foreign_amount', []) }}
|
||||||
|
|
||||||
|
{# BUDGET ONLY WHEN CREATING A WITHDRAWAL #}
|
||||||
|
{% if budgets|length > 1 %}
|
||||||
|
{{ ExpandedForm.select('budget_id', [], null) }} {#budgets#}
|
||||||
|
{% else %}
|
||||||
|
{{ ExpandedForm.select('budget_id', [], null, {helpText: trans('firefly.no_budget_pointer')}) }}
|
||||||
|
{#budgets#}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{# CATEGORY ALWAYS #}
|
||||||
|
{{ ExpandedForm.text('category') }}
|
||||||
|
|
||||||
|
{# TAGS #}
|
||||||
|
{{ ExpandedForm.text('tags') }}
|
||||||
|
|
||||||
|
{# RELATE THIS TRANSFER TO A PIGGY BANK #}
|
||||||
|
{{ ExpandedForm.select('piggy_bank_id', [], 0) }} {#piggies#}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# row with submit stuff. #}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6 col-md-6 col-sm-12 col-lg-offset-6 lg-md-offset-6">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'options'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
{{ ExpandedForm.optionsList('create','recurrence') }}
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
<button type="submit" class="btn pull-right btn-success">
|
||||||
|
{{ ('store_new_recurrence')|_ }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{#
|
||||||
|
<div class="row">
|
||||||
|
<div class="box box-primary">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ 'expected_repetitions'|_ }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
Here.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
#}
|
||||||
|
</form>
|
||||||
|
|
||||||
|
{# calendar modal #}
|
||||||
|
<div class="modal fade" id="calendarModal" tabindex="-1" role="dialog">
|
||||||
|
<div class="modal-dialog modal-lg">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">Calendar view yay</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="recurring_calendar" style="max-width: 400px;margin: 0 auto;">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
{% block scripts %}
|
||||||
|
<script type="text/javascript" src="js/lib/modernizr-custom.js?v={{ FF_VERSION }}"></script>
|
||||||
|
<script type="text/javascript" src="js/lib/bootstrap3-typeahead.min.js?v={{ FF_VERSION }}"></script>
|
||||||
|
<script type="text/javascript" src="js/lib/bootstrap-tagsinput.min.js?v={{ FF_VERSION }}"></script>
|
||||||
|
<script type="text/javascript" src="js/lib/jquery-ui.min.js?v={{ FF_VERSION }}"></script>
|
||||||
|
<script type="text/javascript" src="lib/fc/fullcalendar.min.js?v={{ FF_VERSION }}"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var transactionType = "{{ preFilled.transaction_type }}";
|
||||||
|
var suggestUri = "{{ route('recurring.suggest') }}";
|
||||||
|
var eventsUri = "{{ route('recurring.events') }}";
|
||||||
|
var currentRepetitionType= "{{ currentRepetitionType }}";
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript" src="js/ff/recurring/edit.js?v={{ FF_VERSION }}"></script>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block styles %}
|
||||||
|
<link href="css/bootstrap-tagsinput.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all">
|
||||||
|
<link href="css/jquery-ui/jquery-ui.structure.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all">
|
||||||
|
<link href="css/jquery-ui/jquery-ui.theme.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all">
|
||||||
|
<link href="lib/fc/fullcalendar.min.css?v={{ FF_VERSION }}" type="text/css" rel="stylesheet" media="all">
|
||||||
|
{% endblock %}
|
@ -49,8 +49,7 @@
|
|||||||
<td class="hidden-sm hidden-xs">
|
<td class="hidden-sm hidden-xs">
|
||||||
<div class="btn-group btn-group-xs edit_tr_buttons">
|
<div class="btn-group btn-group-xs edit_tr_buttons">
|
||||||
<a class="btn btn-default btn-xs" title="{{ 'edit'|_ }}" href="{{ route('recurring.edit',rt.id) }}"><i
|
<a class="btn btn-default btn-xs" title="{{ 'edit'|_ }}" href="{{ route('recurring.edit',rt.id) }}"><i
|
||||||
class="fa fa-fw fa-pencil"></i></a>
|
class="fa fa-fw fa-pencil"></i></a><a class="btn btn-danger btn-xs" title="{{ 'delete'|_ }}" href="{{ route('recurring.delete',rt.id) }}"><i
|
||||||
<a class="btn btn-danger btn-xs" title="{{ 'delete'|_ }}" href="{{ route('recurring.delete',rt.id) }}"><i
|
|
||||||
class="fa fa-fw fa-trash-o"></i></a>
|
class="fa fa-fw fa-trash-o"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
@ -86,8 +86,7 @@
|
|||||||
{{ ExpandedForm.text('tags') }}
|
{{ ExpandedForm.text('tags') }}
|
||||||
|
|
||||||
{# RELATE THIS TRANSFER TO A PIGGY BANK #}
|
{# RELATE THIS TRANSFER TO A PIGGY BANK #}
|
||||||
{{ ExpandedForm.select('piggy_bank_id', piggies, '0') }}
|
{{ ExpandedForm.piggyBankList('piggy_bank_id',0) }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -211,7 +210,6 @@
|
|||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var what = "{{ what }}";
|
var what = "{{ what }}";
|
||||||
var piggiesLength = {{ piggies|length }};
|
|
||||||
|
|
||||||
// some titles and names:
|
// some titles and names:
|
||||||
var txt = [];
|
var txt = [];
|
||||||
|
@ -778,6 +778,14 @@ try {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Breadcrumbs::register(
|
||||||
|
'recurring.edit',
|
||||||
|
function (BreadCrumbsGenerator $breadcrumbs, Recurrence $recurrence) {
|
||||||
|
$breadcrumbs->parent('recurring.index');
|
||||||
|
$breadcrumbs->push(trans('firefly.edit_recurrence', ['title' => $recurrence->title]), route('recurring.edit', [$recurrence->id]));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
Breadcrumbs::register(
|
Breadcrumbs::register(
|
||||||
'recurring.create',
|
'recurring.create',
|
||||||
function (BreadCrumbsGenerator $breadcrumbs) {
|
function (BreadCrumbsGenerator $breadcrumbs) {
|
||||||
|
@ -625,6 +625,7 @@ Route::group(
|
|||||||
Route::get('delete/{recurrence}', ['uses' => 'DeleteController@delete', 'as' => 'delete']);
|
Route::get('delete/{recurrence}', ['uses' => 'DeleteController@delete', 'as' => 'delete']);
|
||||||
|
|
||||||
Route::post('store', ['uses' => 'CreateController@store', 'as' => 'store']);
|
Route::post('store', ['uses' => 'CreateController@store', 'as' => 'store']);
|
||||||
|
Route::post('update', ['uses' => 'EditController@update', 'as' => 'update']);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user