mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-09-19 19:01:58 +00:00
New cron job for bills.
This commit is contained in:
@@ -28,6 +28,7 @@ use Carbon\Carbon;
|
|||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Support\Cronjobs\AutoBudgetCronjob;
|
use FireflyIII\Support\Cronjobs\AutoBudgetCronjob;
|
||||||
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
use FireflyIII\Support\Cronjobs\RecurringCronjob;
|
||||||
|
use FireflyIII\Support\Cronjobs\BillWarningCronjob;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
use Log;
|
use Log;
|
||||||
@@ -90,6 +91,17 @@ class Cron extends Command
|
|||||||
$this->error($e->getMessage());
|
$this->error($e->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fire bill warning cron job
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
$this->billWarningCronJob($force, $date);
|
||||||
|
} catch (FireflyException $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
Log::error($e->getTraceAsString());
|
||||||
|
$this->error($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
$this->info('More feedback on the cron jobs can be found in the log files.');
|
$this->info('More feedback on the cron jobs can be found in the log files.');
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -150,4 +162,32 @@ class Cron extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $force
|
||||||
|
* @param Carbon|null $date
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function billWarningCronJob(bool $force, ?Carbon $date): void
|
||||||
|
{
|
||||||
|
$autoBudget = new BillWarningCronjob;
|
||||||
|
$autoBudget->setForce($force);
|
||||||
|
// set date in cron job:
|
||||||
|
if (null !== $date) {
|
||||||
|
$autoBudget->setDate($date);
|
||||||
|
}
|
||||||
|
|
||||||
|
$autoBudget->fire();
|
||||||
|
|
||||||
|
if ($autoBudget->jobErrored) {
|
||||||
|
$this->error(sprintf('Error in "bill warnings" cron: %s', $autoBudget->message));
|
||||||
|
}
|
||||||
|
if ($autoBudget->jobFired) {
|
||||||
|
$this->error(sprintf('"Send bill warnings" cron fired: %s', $autoBudget->message));
|
||||||
|
}
|
||||||
|
if ($autoBudget->jobSucceeded) {
|
||||||
|
$this->error(sprintf('"Send bill warnings" cron ran with success: %s', $autoBudget->message));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
54
app/Events/WarnUserAboutBill.php
Normal file
54
app/Events/WarnUserAboutBill.php
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DestroyedTransactionGroup.php
|
||||||
|
* Copyright (c) 2019 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Events;
|
||||||
|
|
||||||
|
use FireflyIII\Models\Bill;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WarnUserAboutBill.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
class WarnUserAboutBill extends Event
|
||||||
|
{
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
public Bill $bill;
|
||||||
|
public string $field;
|
||||||
|
public int $diff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
* @param string $field
|
||||||
|
* @param int $diff
|
||||||
|
*/
|
||||||
|
public function __construct(Bill $bill, string $field, int $diff)
|
||||||
|
{
|
||||||
|
$this->bill = $bill;
|
||||||
|
$this->field = $field;
|
||||||
|
$this->diff = $diff;
|
||||||
|
}
|
||||||
|
}
|
41
app/Handlers/Events/BillEventHandler.php
Normal file
41
app/Handlers/Events/BillEventHandler.php
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FireflyIII\Handlers\Events;
|
||||||
|
|
||||||
|
use FireflyIII\Events\WarnUserAboutBill;
|
||||||
|
use FireflyIII\Mail\BillWarningMail;
|
||||||
|
use Log;
|
||||||
|
use Mail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BillEventHandler
|
||||||
|
*/
|
||||||
|
class BillEventHandler
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param WarnUserAboutBill $event
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function warnAboutBill(WarnUserAboutBill $event): void
|
||||||
|
{
|
||||||
|
$bill = $event->bill;
|
||||||
|
$field = $event->field;
|
||||||
|
$diff = $event->diff;
|
||||||
|
$user = $bill->user;
|
||||||
|
$address = $user->email;
|
||||||
|
$ipAddress = request()?->ip();
|
||||||
|
|
||||||
|
// see if user has alternative email address:
|
||||||
|
$pref = app('preferences')->getForUser($user, 'remote_guard_alt_email');
|
||||||
|
if (null !== $pref) {
|
||||||
|
$address = $pref->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// send message:
|
||||||
|
Mail::to($address)->send(new BillWarningMail($bill, $field, $diff, $ipAddress));
|
||||||
|
|
||||||
|
|
||||||
|
Log::debug('warnAboutBill');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -102,6 +102,7 @@ class CreateController extends Controller
|
|||||||
public function store(BillStoreRequest $request): RedirectResponse
|
public function store(BillStoreRequest $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$billData = $request->getBillData();
|
$billData = $request->getBillData();
|
||||||
|
|
||||||
$billData['active'] = true;
|
$billData['active'] = true;
|
||||||
try {
|
try {
|
||||||
$bill = $this->repository->store($billData);
|
$bill = $this->repository->store($billData);
|
||||||
|
@@ -98,6 +98,8 @@ class EditController extends Controller
|
|||||||
$hasOldInput = null !== $request->old('_token');
|
$hasOldInput = null !== $request->old('_token');
|
||||||
|
|
||||||
$preFilled = [
|
$preFilled = [
|
||||||
|
'bill_end_date' => $bill->end_date,
|
||||||
|
'extension_date' => $bill->extension_date,
|
||||||
'notes' => $this->repository->getNoteText($bill),
|
'notes' => $this->repository->getNoteText($bill),
|
||||||
'transaction_currency_id' => $bill->transaction_currency_id,
|
'transaction_currency_id' => $bill->transaction_currency_id,
|
||||||
'active' => $hasOldInput ? (bool) $request->old('active') : $bill->active,
|
'active' => $hasOldInput ? (bool) $request->old('active') : $bill->active,
|
||||||
|
@@ -136,8 +136,9 @@ class IndexController extends Controller
|
|||||||
// summarise per currency / per group.
|
// summarise per currency / per group.
|
||||||
$sums = $this->getSums($bills);
|
$sums = $this->getSums($bills);
|
||||||
$totals = $this->getTotals($sums);
|
$totals = $this->getTotals($sums);
|
||||||
|
$today = now()->startOfDay();
|
||||||
|
|
||||||
return view('bills.index', compact('bills', 'sums', 'total', 'totals'));
|
return view('bills.index', compact('bills', 'sums', 'total', 'totals','today'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -47,6 +47,8 @@ class BillStoreRequest extends FormRequest
|
|||||||
'currency_code' => '',
|
'currency_code' => '',
|
||||||
'amount_max' => $this->string('amount_max'),
|
'amount_max' => $this->string('amount_max'),
|
||||||
'date' => $this->getCarbonDate('date'),
|
'date' => $this->getCarbonDate('date'),
|
||||||
|
'end_date' => $this->getCarbonDate('bill_end_date'),
|
||||||
|
'extension_date' => $this->getCarbonDate('extension_date'),
|
||||||
'repeat_freq' => $this->string('repeat_freq'),
|
'repeat_freq' => $this->string('repeat_freq'),
|
||||||
'skip' => $this->integer('skip'),
|
'skip' => $this->integer('skip'),
|
||||||
'notes' => $this->stringWithNewlines('notes'),
|
'notes' => $this->stringWithNewlines('notes'),
|
||||||
@@ -68,6 +70,8 @@ class BillStoreRequest extends FormRequest
|
|||||||
'amount_max' => 'required|numeric|gt:0|max:1000000000',
|
'amount_max' => 'required|numeric|gt:0|max:1000000000',
|
||||||
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
|
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
|
||||||
'date' => 'required|date',
|
'date' => 'required|date',
|
||||||
|
'bill_end_date' => 'nullable|date',
|
||||||
|
'extension_date' => 'nullable|date',
|
||||||
'repeat_freq' => sprintf('required|in:%s', join(',', config('firefly.bill_periods'))),
|
'repeat_freq' => sprintf('required|in:%s', join(',', config('firefly.bill_periods'))),
|
||||||
'skip' => 'required|integer|gte:0|lte:31',
|
'skip' => 'required|integer|gte:0|lte:31',
|
||||||
'active' => 'boolean',
|
'active' => 'boolean',
|
||||||
|
@@ -48,6 +48,8 @@ class BillUpdateRequest extends FormRequest
|
|||||||
'currency_code' => '',
|
'currency_code' => '',
|
||||||
'amount_max' => $this->string('amount_max'),
|
'amount_max' => $this->string('amount_max'),
|
||||||
'date' => $this->getCarbonDate('date'),
|
'date' => $this->getCarbonDate('date'),
|
||||||
|
'end_date' => $this->getCarbonDate('bill_end_date'),
|
||||||
|
'extension_date' => $this->getCarbonDate('extension_date'),
|
||||||
'repeat_freq' => $this->string('repeat_freq'),
|
'repeat_freq' => $this->string('repeat_freq'),
|
||||||
'skip' => $this->integer('skip'),
|
'skip' => $this->integer('skip'),
|
||||||
'notes' => $this->stringWithNewlines('notes'),
|
'notes' => $this->stringWithNewlines('notes'),
|
||||||
@@ -72,6 +74,8 @@ class BillUpdateRequest extends FormRequest
|
|||||||
'amount_max' => 'required|numeric|gt:0|max:1000000000',
|
'amount_max' => 'required|numeric|gt:0|max:1000000000',
|
||||||
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
|
'transaction_currency_id' => 'required|exists:transaction_currencies,id',
|
||||||
'date' => 'required|date',
|
'date' => 'required|date',
|
||||||
|
'bill_end_date' => 'nullable|date',
|
||||||
|
'extension_date' => 'nullable|date',
|
||||||
'repeat_freq' => sprintf('required|in:%s', join(',', config('firefly.bill_periods'))),
|
'repeat_freq' => sprintf('required|in:%s', join(',', config('firefly.bill_periods'))),
|
||||||
'skip' => 'required|integer|gte:0|lte:31',
|
'skip' => 'required|integer|gte:0|lte:31',
|
||||||
'active' => 'boolean',
|
'active' => 'boolean',
|
||||||
|
@@ -24,7 +24,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Jobs;
|
namespace FireflyIII\Jobs;
|
||||||
|
|
||||||
use Log;
|
|
||||||
use FireflyIII\Models\WebhookMessage;
|
use FireflyIII\Models\WebhookMessage;
|
||||||
use FireflyIII\Services\Webhook\WebhookSenderInterface;
|
use FireflyIII\Services\Webhook\WebhookSenderInterface;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
@@ -32,6 +31,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
|
|||||||
use Illuminate\Foundation\Bus\Dispatchable;
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
use Illuminate\Queue\InteractsWithQueue;
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class SendWebhookMessage
|
* Class SendWebhookMessage
|
||||||
|
153
app/Jobs/WarnAboutBills.php
Normal file
153
app/Jobs/WarnAboutBills.php
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FireflyIII\Jobs;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Events\RequestedReportOnJournals;
|
||||||
|
use FireflyIII\Events\WarnUserAboutBill;
|
||||||
|
use FireflyIII\Models\Bill;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
|
use Illuminate\Foundation\Bus\Dispatchable;
|
||||||
|
use Illuminate\Queue\InteractsWithQueue;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class WarnAboutBills
|
||||||
|
*/
|
||||||
|
class WarnAboutBills implements ShouldQueue
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
|
private Carbon $date;
|
||||||
|
private bool $force;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new job instance.
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
|
* @param Carbon|null $date
|
||||||
|
*/
|
||||||
|
public function __construct(?Carbon $date)
|
||||||
|
{
|
||||||
|
if (null !== $date) {
|
||||||
|
$newDate = clone $date;
|
||||||
|
$newDate->startOfDay();
|
||||||
|
$this->date = $newDate;
|
||||||
|
}
|
||||||
|
if (null === $date) {
|
||||||
|
$newDate = new Carbon;
|
||||||
|
$newDate->startOfDay();
|
||||||
|
$this->date = $newDate;
|
||||||
|
}
|
||||||
|
$this->force = false;
|
||||||
|
|
||||||
|
Log::debug(sprintf('Created new WarnAboutBills("%s")', $this->date->format('Y-m-d')));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the job.
|
||||||
|
*/
|
||||||
|
public function handle(): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now at start of WarnAboutBills() job for %s.', $this->date->format('D d M Y')));
|
||||||
|
$bills = Bill::all();
|
||||||
|
/** @var Bill $bill */
|
||||||
|
foreach ($bills as $bill) {
|
||||||
|
Log::debug(sprintf('Now checking bill #%d ("%s")', $bill->id, $bill->name));
|
||||||
|
if ($this->hasDateFields($bill)) {
|
||||||
|
if ($this->needsWarning($bill, 'end_date')) {
|
||||||
|
$this->sendWarning($bill, 'end_date');
|
||||||
|
}
|
||||||
|
if ($this->needsWarning($bill, 'extension_date')) {
|
||||||
|
$this->sendWarning($bill, 'extension_date');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log::debug('Done with handle()');
|
||||||
|
|
||||||
|
// clear cache:
|
||||||
|
app('preferences')->mark();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function hasDateFields(Bill $bill): bool
|
||||||
|
{
|
||||||
|
if (false === $bill->active) {
|
||||||
|
Log::debug('Bill is not active.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (null === $bill->end_date && null === $bill->extension_date) {
|
||||||
|
Log::debug('Bill has no date fields.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
* @param string $field
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function needsWarning(Bill $bill, string $field): bool
|
||||||
|
{
|
||||||
|
if (null === $bill->$field) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$diff = $this->getDiff($bill, $field);
|
||||||
|
$list = config('firefly.bill_reminder_periods');
|
||||||
|
Log::debug(sprintf('Difference in days for field "%s" ("%s") is %d day(s)', $field, $bill->$field->format('Y-m-d'), $diff));
|
||||||
|
if (in_array($diff, $list, true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
* @param string $field
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function getDiff(Bill $bill, string $field): int
|
||||||
|
{
|
||||||
|
$today = clone $this->date;
|
||||||
|
$carbon = clone $bill->$field;
|
||||||
|
return $today->diffInDays($carbon, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Bill $bill
|
||||||
|
* @param string $field
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function sendWarning(Bill $bill, string $field): void
|
||||||
|
{
|
||||||
|
$diff = $this->getDiff($bill, $field);
|
||||||
|
Log::debug('Will now send warning!');
|
||||||
|
event(new WarnUserAboutBill($bill, $field, $diff));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Carbon $date
|
||||||
|
*/
|
||||||
|
public function setDate(Carbon $date): void
|
||||||
|
{
|
||||||
|
$newDate = clone $date;
|
||||||
|
$newDate->startOfDay();
|
||||||
|
$this->date = $newDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $force
|
||||||
|
*/
|
||||||
|
public function setForce(bool $force): void
|
||||||
|
{
|
||||||
|
$this->force = $force;
|
||||||
|
}
|
||||||
|
}
|
@@ -37,10 +37,8 @@ class AdminTestMail extends Mailable
|
|||||||
{
|
{
|
||||||
use Queueable, SerializesModels;
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
/** @var string Email address of admin */
|
public string $email;
|
||||||
public $email;
|
public string $ipAddress;
|
||||||
/** @var string IP address of admin */
|
|
||||||
public $ipAddress;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConfirmEmailChangeMail constructor.
|
* ConfirmEmailChangeMail constructor.
|
||||||
|
52
app/Mail/BillWarningMail.php
Normal file
52
app/Mail/BillWarningMail.php
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace FireflyIII\Mail;
|
||||||
|
|
||||||
|
use FireflyIII\Models\Bill;
|
||||||
|
use Illuminate\Bus\Queueable;
|
||||||
|
use Illuminate\Mail\Mailable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class BillWarningMail extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
public Bill $bill;
|
||||||
|
public string $field;
|
||||||
|
public int $diff;
|
||||||
|
public string $ipAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ConfirmEmailChangeMail constructor.
|
||||||
|
*
|
||||||
|
* @param Bill $bill
|
||||||
|
* @param string $field
|
||||||
|
* @param int $diff
|
||||||
|
* @param string $ipAddress
|
||||||
|
*/
|
||||||
|
public function __construct(Bill $bill, string $field, int $diff, string $ipAddress)
|
||||||
|
{
|
||||||
|
$this->bill = $bill;
|
||||||
|
$this->field = $field;
|
||||||
|
$this->diff = $diff;
|
||||||
|
$this->ipAddress = $ipAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build the message.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function build(): self
|
||||||
|
{
|
||||||
|
$subject = (string) trans(sprintf('email.bill_warning_subject_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]);
|
||||||
|
if (0 === $this->diff) {
|
||||||
|
$subject = (string) trans(sprintf('email.bill_warning_subject_now_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this
|
||||||
|
->view('emails.bill-warning-html')
|
||||||
|
->text('emails.bill-warning-text')
|
||||||
|
->subject($subject);
|
||||||
|
}
|
||||||
|
}
|
@@ -37,14 +37,10 @@ class ConfirmEmailChangeMail extends Mailable
|
|||||||
{
|
{
|
||||||
use Queueable, SerializesModels;
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
/** @var string IP address of user */
|
public string $ipAddress;
|
||||||
public $ipAddress;
|
public string $newEmail;
|
||||||
/** @var string New email address */
|
public string $oldEmail;
|
||||||
public $newEmail;
|
public string $uri;
|
||||||
/** @var string Old email address */
|
|
||||||
public $oldEmail;
|
|
||||||
/** @var string Confirmation link */
|
|
||||||
public $uri;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConfirmEmailChangeMail constructor.
|
* ConfirmEmailChangeMail constructor.
|
||||||
|
@@ -37,6 +37,7 @@ use FireflyIII\Events\StoredTransactionGroup;
|
|||||||
use FireflyIII\Events\UpdatedAccount;
|
use FireflyIII\Events\UpdatedAccount;
|
||||||
use FireflyIII\Events\UpdatedTransactionGroup;
|
use FireflyIII\Events\UpdatedTransactionGroup;
|
||||||
use FireflyIII\Events\UserChangedEmail;
|
use FireflyIII\Events\UserChangedEmail;
|
||||||
|
use FireflyIII\Events\WarnUserAboutBill;
|
||||||
use FireflyIII\Mail\OAuthTokenCreatedMail;
|
use FireflyIII\Mail\OAuthTokenCreatedMail;
|
||||||
use FireflyIII\Models\PiggyBank;
|
use FireflyIII\Models\PiggyBank;
|
||||||
use FireflyIII\Models\PiggyBankRepetition;
|
use FireflyIII\Models\PiggyBankRepetition;
|
||||||
@@ -134,6 +135,11 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
UpdatedAccount::class => [
|
UpdatedAccount::class => [
|
||||||
'FireflyIII\Handlers\Events\UpdatedAccountEventHandler@recalculateCredit',
|
'FireflyIII\Handlers\Events\UpdatedAccountEventHandler@recalculateCredit',
|
||||||
],
|
],
|
||||||
|
|
||||||
|
// bill related events:
|
||||||
|
WarnUserAboutBill::class => [
|
||||||
|
'FireflyIII\Handlers\Events\BillEventHandler@warnAboutBill',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -166,6 +166,12 @@ class BillUpdateService
|
|||||||
if (array_key_exists('active', $data)) {
|
if (array_key_exists('active', $data)) {
|
||||||
$bill->active = $data['active'];
|
$bill->active = $data['active'];
|
||||||
}
|
}
|
||||||
|
if(array_key_exists('end_date', $data)) {
|
||||||
|
$bill->end_date = $data['end_date'];
|
||||||
|
}
|
||||||
|
if(array_key_exists('extension_date', $data)) {
|
||||||
|
$bill->extension_date = $data['extension_date'];
|
||||||
|
}
|
||||||
|
|
||||||
$bill->match = 'EMPTY';
|
$bill->match = 'EMPTY';
|
||||||
$bill->automatch = true;
|
$bill->automatch = true;
|
||||||
|
102
app/Support/Cronjobs/BillWarningCronjob.php
Normal file
102
app/Support/Cronjobs/BillWarningCronjob.php
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* RecurringCronjob.php
|
||||||
|
* Copyright (c) 2019 james@firefly-iii.org
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III (https://github.com/firefly-iii).
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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 Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Support\Cronjobs;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Jobs\WarnAboutBills;
|
||||||
|
use FireflyIII\Models\Configuration;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class BillWarningCronjob
|
||||||
|
*/
|
||||||
|
class BillWarningCronjob extends AbstractCronjob
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function fire(): void
|
||||||
|
{
|
||||||
|
Log::debug(sprintf('Now in %s', __METHOD__));
|
||||||
|
/** @var Configuration $config */
|
||||||
|
$config = app('fireflyconfig')->get('last_bw_job', 0);
|
||||||
|
$lastTime = (int)$config->data;
|
||||||
|
$diff = time() - $lastTime;
|
||||||
|
$diffForHumans = Carbon::now()->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true);
|
||||||
|
|
||||||
|
if (0 === $lastTime) {
|
||||||
|
Log::info('The bill warning cron-job has never fired before.');
|
||||||
|
}
|
||||||
|
// less than half a day ago:
|
||||||
|
if ($lastTime > 0 && $diff <= 43200) {
|
||||||
|
Log::info(sprintf('It has been %s since the bill warning cron-job has fired.', $diffForHumans));
|
||||||
|
if (false === $this->force) {
|
||||||
|
Log::info('The cron-job will not fire now.');
|
||||||
|
$this->message = sprintf('It has been %s since the bill warning cron-job has fired. It will not fire now.', $diffForHumans);
|
||||||
|
$this->jobFired = false;
|
||||||
|
$this->jobErrored = false;
|
||||||
|
$this->jobSucceeded = false;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fire job regardless.
|
||||||
|
if (true === $this->force) {
|
||||||
|
Log::info('Execution of the bill warning cron-job has been FORCED.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($lastTime > 0 && $diff > 43200) {
|
||||||
|
Log::info(sprintf('It has been %s since the bill warning cron-job has fired. It will fire now!', $diffForHumans));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->fireWarnings();
|
||||||
|
|
||||||
|
app('preferences')->mark();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private function fireWarnings(): void
|
||||||
|
{
|
||||||
|
Log::info(sprintf('Will now fire bill warning job task for date "%s".', $this->date->format('Y-m-d H:i:s')));
|
||||||
|
/** @var WarnAboutBills $job */
|
||||||
|
$job = app(WarnAboutBills::class);
|
||||||
|
$job->setDate($this->date);
|
||||||
|
$job->setForce($this->force);
|
||||||
|
$job->handle();
|
||||||
|
|
||||||
|
// get stuff from job:
|
||||||
|
$this->jobFired = true;
|
||||||
|
$this->jobErrored = false;
|
||||||
|
$this->jobSucceeded = true;
|
||||||
|
$this->message = 'Bill warning cron job fired successfully.';
|
||||||
|
|
||||||
|
app('fireflyconfig')->set('last_bw_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 bill warning cron job task.');
|
||||||
|
}
|
||||||
|
}
|
@@ -68,6 +68,7 @@ class General extends AbstractExtension
|
|||||||
$this->getMetaField(),
|
$this->getMetaField(),
|
||||||
$this->hasRole(),
|
$this->hasRole(),
|
||||||
$this->getRootSearchOperator(),
|
$this->getRootSearchOperator(),
|
||||||
|
$this->carbonize()
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -395,6 +396,19 @@ class General extends AbstractExtension
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return TwigFunction
|
||||||
|
*/
|
||||||
|
protected function carbonize(): TwigFunction
|
||||||
|
{
|
||||||
|
return new TwigFunction(
|
||||||
|
'carbonize',
|
||||||
|
static function (string $date): Carbon {
|
||||||
|
return new Carbon($date);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will return true if the user is of role X.
|
* Will return true if the user is of role X.
|
||||||
*
|
*
|
||||||
|
@@ -221,6 +221,7 @@ return [
|
|||||||
TransactionJournal::class,
|
TransactionJournal::class,
|
||||||
Recurrence::class,
|
Recurrence::class,
|
||||||
],
|
],
|
||||||
|
'bill_reminder_periods' => [90, 30, 14, 7, 0],
|
||||||
'valid_view_ranges' => ['1D', '1W', '1M', '3M', '6M', '1Y',],
|
'valid_view_ranges' => ['1D', '1W', '1M', '3M', '6M', '1Y',],
|
||||||
'allowedMimes' => [
|
'allowedMimes' => [
|
||||||
/* plain files */
|
/* plain files */
|
||||||
@@ -708,7 +709,7 @@ return [
|
|||||||
'import_hash', 'import_hash_v2', 'external_id', 'original_source',
|
'import_hash', 'import_hash_v2', 'external_id', 'original_source',
|
||||||
|
|
||||||
// recurring transactions
|
// recurring transactions
|
||||||
'recurrence_total', 'recurrence_count'
|
'recurrence_total', 'recurrence_count',
|
||||||
],
|
],
|
||||||
'webhooks' => [
|
'webhooks' => [
|
||||||
'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3),
|
'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3),
|
||||||
|
@@ -102,4 +102,19 @@ return [
|
|||||||
// report new journals
|
// report new journals
|
||||||
'new_journals_subject' => 'Firefly III has created a new transaction|Firefly III has created :count new transactions',
|
'new_journals_subject' => 'Firefly III has created a new transaction|Firefly III has created :count new transactions',
|
||||||
'new_journals_header' => 'Firefly III has created a transaction for you. You can find it in your Firefly III installation:|Firefly III has created :count transactions for you. You can find them in your Firefly III installation:',
|
'new_journals_header' => 'Firefly III has created a transaction for you. You can find it in your Firefly III installation:|Firefly III has created :count transactions for you. You can find them in your Firefly III installation:',
|
||||||
|
|
||||||
|
// bill warning
|
||||||
|
'bill_warning_subject_end_date' => 'Your bill ":name" is due to end in :diff days',
|
||||||
|
'bill_warning_subject_now_end_date' => 'Your bill ":name" is due to end TODAY',
|
||||||
|
'bill_warning_subject_extension_date' => 'Your bill ":name" is due to be extended or cancelled in :diff days',
|
||||||
|
'bill_warning_subject_now_extension_date' => 'Your bill ":name" is due to be extended or cancelled TODAY',
|
||||||
|
'bill_warning_end_date_text' => 'Your bill ":name" is due to end on :date. This moment will pass in about :diff days.',
|
||||||
|
'bill_warning_extension_date_text' => 'Your bill ":name" is due to be extended or cancelled on :date. This moment will pass in about :diff days.',
|
||||||
|
'bill_warning_end_date_text_zero' => 'Your bill ":name" is due to end on :date. This moment will pass TODAY!',
|
||||||
|
'bill_warning_extension_date_text_zero' => 'Your bill ":name" is due to be extended or cancelled on :date. This moment will pass TODAY!',
|
||||||
|
'bill_warning_please_action' => 'Please take the appropriate action.',
|
||||||
|
'bill_warning_end_date_html' => 'Your bill <strong>":name"</strong> is due to end on :date. This moment will pass in about <strong>:diff days</strong>.',
|
||||||
|
'bill_warning_extension_date_html' => 'Your bill <strong>":name"</strong> is due to be extended or cancelled on :date. This moment will pass in about <strong>:diff days</strong>.',
|
||||||
|
'bill_warning_end_date_html_zero' => 'Your bill <strong>":name"</strong> is due to end on :date. This moment will pass <strong>TODAY!</strong>',
|
||||||
|
'bill_warning_extension_date_html_zero' => 'Your bill <strong>":name"</strong> is due to be extended or cancelled on :date. This moment will pass <strong>TODAY!</strong>',
|
||||||
];
|
];
|
||||||
|
@@ -1309,6 +1309,10 @@ return [
|
|||||||
'running_again_loss' => 'Previously linked transactions to this bill may lose their connection, if they (no longer) match the rule(s).',
|
'running_again_loss' => 'Previously linked transactions to this bill may lose their connection, if they (no longer) match the rule(s).',
|
||||||
'bill_related_rules' => 'Rules related to this bill',
|
'bill_related_rules' => 'Rules related to this bill',
|
||||||
'repeats' => 'Repeats',
|
'repeats' => 'Repeats',
|
||||||
|
'bill_end_date_help' => 'Optional field. The bill is expected to end on this date.',
|
||||||
|
'bill_extension_date_help' => 'Optional field. The bill must be extended (or cancelled) on or before this date.',
|
||||||
|
'bill_end_index_line' => 'This bill ends on :date',
|
||||||
|
'bill_extension_index_line' => 'This bill must be extended or cancelled on :date',
|
||||||
'connected_journals' => 'Connected transactions',
|
'connected_journals' => 'Connected transactions',
|
||||||
'auto_match_on' => 'Automatically matched by Firefly III',
|
'auto_match_on' => 'Automatically matched by Firefly III',
|
||||||
'auto_match_off' => 'Not automatically matched by Firefly III',
|
'auto_match_off' => 'Not automatically matched by Firefly III',
|
||||||
|
@@ -181,6 +181,7 @@ return [
|
|||||||
'login_name' => 'Login',
|
'login_name' => 'Login',
|
||||||
'is_owner' => 'Is admin?',
|
'is_owner' => 'Is admin?',
|
||||||
'url' => 'URL',
|
'url' => 'URL',
|
||||||
|
'bill_end_date' => 'End date',
|
||||||
|
|
||||||
// import
|
// import
|
||||||
'apply_rules' => 'Apply rules',
|
'apply_rules' => 'Apply rules',
|
||||||
|
@@ -22,6 +22,7 @@
|
|||||||
{{ ExpandedForm.amountNoCurrency('amount_max') }}
|
{{ ExpandedForm.amountNoCurrency('amount_max') }}
|
||||||
{{ ExpandedForm.date('date',phpdate('Y-m-d')) }}
|
{{ ExpandedForm.date('date',phpdate('Y-m-d')) }}
|
||||||
{{ ExpandedForm.select('repeat_freq',periods,'monthly') }}
|
{{ ExpandedForm.select('repeat_freq',periods,'monthly') }}
|
||||||
|
{{ ExpandedForm.integer('skip',0) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -32,9 +33,12 @@
|
|||||||
<h3 class="box-title">{{ 'optionalFields'|_ }}</h3>
|
<h3 class="box-title">{{ 'optionalFields'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
|
{{ ExpandedForm.date('bill_end_date',null, {'helpText': trans('firefly.bill_end_date_help')}) }}
|
||||||
|
{{ ExpandedForm.date('extension_date',null,{'helpText': trans('firefly.bill_extension_date_help')} ) }}
|
||||||
|
|
||||||
|
|
||||||
{{ ExpandedForm.textarea('notes',null,{helpText: trans('firefly.field_supports_markdown')}) }}
|
{{ ExpandedForm.textarea('notes',null,{helpText: trans('firefly.field_supports_markdown')}) }}
|
||||||
{{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }}
|
{{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }}
|
||||||
{{ ExpandedForm.integer('skip',0) }}
|
|
||||||
{{ ExpandedForm.objectGroup() }}
|
{{ ExpandedForm.objectGroup() }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -27,6 +27,8 @@
|
|||||||
{{ ExpandedForm.amountNoCurrency('amount_max') }}
|
{{ ExpandedForm.amountNoCurrency('amount_max') }}
|
||||||
{{ ExpandedForm.date('date',bill.date.format('Y-m-d')) }}
|
{{ ExpandedForm.date('date',bill.date.format('Y-m-d')) }}
|
||||||
{{ ExpandedForm.select('repeat_freq',periods) }}
|
{{ ExpandedForm.select('repeat_freq',periods) }}
|
||||||
|
{{ ExpandedForm.integer('skip') }}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -38,9 +40,11 @@
|
|||||||
<h3 class="box-title">{{ 'optionalFields'|_ }}</h3>
|
<h3 class="box-title">{{ 'optionalFields'|_ }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
|
{{ ExpandedForm.date('bill_end_date',null, {'helpText': trans('firefly.bill_end_date_help')}) }}
|
||||||
|
{{ ExpandedForm.date('extension_date',null,{'helpText': trans('firefly.bill_extension_date_help')} ) }}
|
||||||
|
|
||||||
{{ ExpandedForm.textarea('notes',null,{helpText: trans('firefly.field_supports_markdown')}) }}
|
{{ ExpandedForm.textarea('notes',null,{helpText: trans('firefly.field_supports_markdown')}) }}
|
||||||
{{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }}
|
{{ ExpandedForm.file('attachments[]', {'multiple': 'multiple','helpText': trans('firefly.upload_max_file_size', {'size': uploadSize|filesize}) }) }}
|
||||||
{{ ExpandedForm.integer('skip') }}
|
|
||||||
{{ ExpandedForm.objectGroup() }}
|
{{ ExpandedForm.objectGroup() }}
|
||||||
{# only correct way to do active checkbox #}
|
{# only correct way to do active checkbox #}
|
||||||
{{ ExpandedForm.checkbox('active', 1) }}
|
{{ ExpandedForm.checkbox('active', 1) }}
|
||||||
|
25
resources/views/emails/bill-warning-html.twig
Normal file
25
resources/views/emails/bill-warning-html.twig
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{% include 'emails.header-html' %}
|
||||||
|
|
||||||
|
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
|
||||||
|
|
||||||
|
{% if field == 'end_date' and diff != 0 %}
|
||||||
|
{{ trans('email.bill_warning_end_date_html', {name: bill.name|escape, date: bill.end_date.isoFormat(trans('config.month_and_day_js')), diff: diff})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
{% if field == 'extension_date' and diff != 0 %}
|
||||||
|
{{ trans('email.bill_warning_extension_date_html', {name: bill.name|escape, date: bill.extension_date.isoFormat(trans('config.month_and_day_js')), diff: diff})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
{% if field == 'end_date' and diff == 0 %}
|
||||||
|
{{ trans('email.bill_warning_end_date_html_zero', {name: bill.name|escape, date: bill.end_date.isoFormat(trans('config.month_and_day_js'))})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
{% if field == 'extension_date' and diff == 0 %}
|
||||||
|
{{ trans('email.bill_warning_extension_date_html_zero', {name: bill.name|escape, date: bill.end_date.isoFormat(trans('config.month_and_day_js'))})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
|
||||||
|
Please take the appropriate action.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
{% include 'emails.footer-html' %}
|
17
resources/views/emails/bill-warning-text.twig
Normal file
17
resources/views/emails/bill-warning-text.twig
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{% include 'emails.header-text' %}
|
||||||
|
{% if field == 'end_date' and diff != 0 %}
|
||||||
|
{{ trans('email.bill_warning_end_date_text', {name: bill.name, date: bill.end_date.isoFormat(trans('config.month_and_day_js')), diff: diff})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
{% if field == 'extension_date' and diff != 0 %}
|
||||||
|
{{ trans('email.bill_warning_extension_date_text', {name: bill.name|escape, date: bill.extension_date.isoFormat(trans('config.month_and_day_js')), diff: diff})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
{% if field == 'end_date' and diff == 0 %}
|
||||||
|
{{ trans('email.bill_warning_end_date_text_zero', {name: bill.name|escape, date: bill.end_date.isoFormat(trans('config.month_and_day_js'))})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
{% if field == 'extension_date' and diff == 0 %}
|
||||||
|
{{ trans('email.bill_warning_extension_date_text_zero', {name: bill.name|escape, date: bill.end_date.isoFormat(trans('config.month_and_day_js'))})|raw }}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{{ trans('email.bill_warning_please_action') }}
|
||||||
|
|
||||||
|
{% include 'emails.footer-text' %}
|
@@ -16,20 +16,25 @@
|
|||||||
</thead>
|
</thead>
|
||||||
{% for objectGroupOrder, objectGroup in bills %}
|
{% for objectGroupOrder, objectGroup in bills %}
|
||||||
{% if objectGroup.bills|length > 0 %}
|
{% if objectGroup.bills|length > 0 %}
|
||||||
<tbody class="bill-connected-list" {% if objectGroupOrder != 0 %}data-title="{{ objectGroup.object_group_title }}" {% else %}data-title=""{% endif %}>
|
<tbody class="bill-connected-list"
|
||||||
|
{% if objectGroupOrder != 0 %}data-title="{{ objectGroup.object_group_title }}"
|
||||||
|
{% else %}data-title=""{% endif %}>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="hidden-sm hidden-xs"> </td>
|
<td class="hidden-sm hidden-xs"> </td>
|
||||||
<td class="hidden-sm hidden-xs"> </td>
|
<td class="hidden-sm hidden-xs"> </td>
|
||||||
<td colspan="6"><small>{{ objectGroup.object_group_title }}</small></td>
|
<td colspan="6"><small>{{ objectGroup.object_group_title }}</small></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% for entry in objectGroup.bills %}
|
{% for entry in objectGroup.bills %}
|
||||||
<tr class="bill-sortable" data-id="{{ entry.id }}" data-name="{{ entry.name }}" data-order="{{ entry.order }}" data-position="{{ loop.index0 }}">
|
<tr class="bill-sortable" data-id="{{ entry.id }}" data-name="{{ entry.name }}"
|
||||||
|
data-order="{{ entry.order }}" data-position="{{ loop.index0 }}">
|
||||||
<td class="hidden-sm hidden-xs">
|
<td class="hidden-sm hidden-xs">
|
||||||
<span class="fa fa-fw fa-bars bill-handle"></span>
|
<span class="fa fa-fw fa-bars bill-handle"></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="hidden-sm hidden-xs">
|
<td class="hidden-sm hidden-xs">
|
||||||
<div class="btn-group btn-group-xs edit_tr_buttons"><a href="{{ route('bills.edit',entry.id) }}" class="btn btn-default btn-xs"><span
|
<div class="btn-group btn-group-xs edit_tr_buttons"><a href="{{ route('bills.edit',entry.id) }}"
|
||||||
class="fa fa-fw fa-pencil"></span></a><a href="{{ route('bills.delete',entry.id) }}" class="btn btn-danger btn-xs"><span
|
class="btn btn-default btn-xs"><span
|
||||||
|
class="fa fa-fw fa-pencil"></span></a><a
|
||||||
|
href="{{ route('bills.delete',entry.id) }}" class="btn btn-danger btn-xs"><span
|
||||||
class="fa fa-fw fa-trash-o"></span></a></div>
|
class="fa fa-fw fa-trash-o"></span></a></div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
@@ -126,6 +131,26 @@
|
|||||||
{% if entry.skip > 0 %}
|
{% if entry.skip > 0 %}
|
||||||
{{ 'skips_over'|_ }} {{ entry.skip }}
|
{{ 'skips_over'|_ }} {{ entry.skip }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if entry.end_date %}
|
||||||
|
<br>
|
||||||
|
{% if carbonize(entry.end_date).lte(today) %}
|
||||||
|
<span class="text-danger">
|
||||||
|
{{ trans('firefly.bill_end_index_line', {date: carbonize(entry.end_date).isoFormat(monthAndDayFormat) }) }}
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
{{ trans('firefly.bill_end_index_line', {date: carbonize(entry.end_date).isoFormat(monthAndDayFormat) }) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if entry.extension_date %}
|
||||||
|
<br>
|
||||||
|
{% if carbonize(entry.extension_date).lte(today) %}
|
||||||
|
<span class="text-danger">
|
||||||
|
{{ trans('firefly.bill_extension_index_line', {date: carbonize(entry.extension_date).isoFormat(monthAndDayFormat) }) }}
|
||||||
|
</span>
|
||||||
|
{% else %}
|
||||||
|
{{ trans('firefly.bill_extension_index_line', {date: carbonize(entry.extension_date).isoFormat(monthAndDayFormat) }) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -150,7 +175,8 @@
|
|||||||
<td class="hidden-sm hidden-xs"> </td> <!-- handle -->
|
<td class="hidden-sm hidden-xs"> </td> <!-- handle -->
|
||||||
<td class="hidden-sm hidden-xs"> </td> <!-- buttons -->
|
<td class="hidden-sm hidden-xs"> </td> <!-- buttons -->
|
||||||
<td colspan="2" style="text-align: right;"> <!-- title -->
|
<td colspan="2" style="text-align: right;"> <!-- title -->
|
||||||
<small>{{ ('per_period_sum_'~sum.period)|_ }} ({{ sum.currency_name }}) ({{ 'active_bills_only'|_ }})</small>
|
<small>{{ ('per_period_sum_'~sum.period)|_ }} ({{ sum.currency_name }})
|
||||||
|
({{ 'active_bills_only'|_ }})</small>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: right;"> <!-- amount -->
|
<td style="text-align: right;"> <!-- amount -->
|
||||||
{{ formatAmountBySymbol(sum.per_period, sum.currency_symbol, sum.currency_decimal_places) }}
|
{{ formatAmountBySymbol(sum.per_period, sum.currency_symbol, sum.currency_decimal_places) }}
|
||||||
@@ -190,7 +216,8 @@
|
|||||||
<td class="hidden-sm hidden-xs"> </td> <!-- handle -->
|
<td class="hidden-sm hidden-xs"> </td> <!-- handle -->
|
||||||
<td class="hidden-sm hidden-xs"> </td> <!-- buttons -->
|
<td class="hidden-sm hidden-xs"> </td> <!-- buttons -->
|
||||||
<td colspan="2" style="text-align: right;"> <!-- title -->
|
<td colspan="2" style="text-align: right;"> <!-- title -->
|
||||||
<small>{{ ('per_period_sum_'~sum.period)|_ }} ({{ sum.currency_name }}) ({{ 'active_bills_only_total'|_ }})</small>
|
<small>{{ ('per_period_sum_'~sum.period)|_ }} ({{ sum.currency_name }})
|
||||||
|
({{ 'active_bills_only_total'|_ }})</small>
|
||||||
</td>
|
</td>
|
||||||
<td style="text-align: right;"> <!-- amount -->
|
<td style="text-align: right;"> <!-- amount -->
|
||||||
{{ formatAmountBySymbol(sum.per_period, sum.currency_symbol, sum.currency_decimal_places) }}
|
{{ formatAmountBySymbol(sum.per_period, sum.currency_symbol, sum.currency_decimal_places) }}
|
||||||
|
Reference in New Issue
Block a user