mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-10-12 15:35:15 +00:00
Code for #3240
This commit is contained in:
@@ -56,12 +56,9 @@ class TransactionJournalFactory
|
|||||||
{
|
{
|
||||||
use JournalServiceTrait;
|
use JournalServiceTrait;
|
||||||
|
|
||||||
/** @var AccountRepositoryInterface */
|
private AccountRepositoryInterface $accountRepository;
|
||||||
private $accountRepository;
|
private AccountValidator $accountValidator;
|
||||||
/** @var AccountValidator */
|
private BillRepositoryInterface $billRepository;
|
||||||
private $accountValidator;
|
|
||||||
/** @var BillRepositoryInterface */
|
|
||||||
private $billRepository;
|
|
||||||
/** @var CurrencyRepositoryInterface */
|
/** @var CurrencyRepositoryInterface */
|
||||||
private $currencyRepository;
|
private $currencyRepository;
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
@@ -88,6 +85,7 @@ class TransactionJournalFactory
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->errorOnHash = false;
|
$this->errorOnHash = false;
|
||||||
|
// TODO move valid meta fields to config.
|
||||||
$this->fields = [
|
$this->fields = [
|
||||||
// sepa
|
// sepa
|
||||||
'sepa_cc', 'sepa_ct_op', 'sepa_ct_id',
|
'sepa_cc', 'sepa_ct_op', 'sepa_ct_id',
|
||||||
@@ -100,7 +98,11 @@ class TransactionJournalFactory
|
|||||||
|
|
||||||
// others
|
// others
|
||||||
'recurrence_id', 'internal_reference', 'bunq_payment_id',
|
'recurrence_id', 'internal_reference', 'bunq_payment_id',
|
||||||
'import_hash', 'import_hash_v2', 'external_id', 'original_source'];
|
'import_hash', 'import_hash_v2', 'external_id', 'original_source',
|
||||||
|
|
||||||
|
// recurring transactions
|
||||||
|
'recurrence_total', 'recurrence_count'
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
if ('testing' === config('app.env')) {
|
if ('testing' === config('app.env')) {
|
||||||
|
@@ -53,15 +53,15 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||||
|
|
||||||
/** @var int Transaction groups created */
|
/** @var int Transaction groups created */
|
||||||
public $created;
|
public int $created;
|
||||||
/** @var int Number of recurrences actually fired */
|
/** @var int Number of recurrences actually fired */
|
||||||
public $executed;
|
public int $executed;
|
||||||
/** @var int Number of recurrences submitted */
|
/** @var int Number of recurrences submitted */
|
||||||
public $submitted;
|
public int $submitted;
|
||||||
/** @var Carbon The current date */
|
/** @var Carbon The current date */
|
||||||
private $date;
|
private Carbon $date;
|
||||||
/** @var bool Force the transaction to be created no matter what. */
|
/** @var bool Force the transaction to be created no matter what. */
|
||||||
private $force;
|
private bool $force;
|
||||||
/** @var TransactionGroupRepositoryInterface */
|
/** @var TransactionGroupRepositoryInterface */
|
||||||
private $groupRepository;
|
private $groupRepository;
|
||||||
/** @var JournalRepositoryInterface Journal repository */
|
/** @var JournalRepositoryInterface Journal repository */
|
||||||
@@ -219,19 +219,23 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
/**
|
/**
|
||||||
* Get transaction information from a recurring transaction.
|
* Get transaction information from a recurring transaction.
|
||||||
*
|
*
|
||||||
* @param Recurrence $recurrence
|
* @param Recurrence $recurrence
|
||||||
* @param Carbon $date
|
* @param RecurrenceRepetition $repetition
|
||||||
|
* @param Carbon $date
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private function getTransactionData(Recurrence $recurrence, Carbon $date): array
|
private function getTransactionData(Recurrence $recurrence, RecurrenceRepetition $repetition, Carbon $date): array
|
||||||
{
|
{
|
||||||
|
// total transactions expected for this recurrence:
|
||||||
|
$total = $this->repository->totalTransactions($recurrence, $repetition);
|
||||||
|
$count = $this->repository->getJournalCount($recurrence) + 1;
|
||||||
$transactions = $recurrence->recurrenceTransactions()->get();
|
$transactions = $recurrence->recurrenceTransactions()->get();
|
||||||
$return = [];
|
$return = [];
|
||||||
/** @var RecurrenceTransaction $transaction */
|
/** @var RecurrenceTransaction $transaction */
|
||||||
foreach ($transactions as $index => $transaction) {
|
foreach ($transactions as $index => $transaction) {
|
||||||
$single = [
|
$single = [
|
||||||
'type' => strtolower($recurrence->transactionType->type),
|
'type' => strtolower($recurrence->transactionType->type),
|
||||||
'date' => $date,
|
'date' => $date,
|
||||||
'user' => $recurrence->user_id,
|
'user' => $recurrence->user_id,
|
||||||
@@ -260,6 +264,8 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
'piggy_bank_name' => null,
|
'piggy_bank_name' => null,
|
||||||
'bill_id' => null,
|
'bill_id' => null,
|
||||||
'bill_name' => null,
|
'bill_name' => null,
|
||||||
|
'recurrence_total' => $total,
|
||||||
|
'recurrence_count' => $count,
|
||||||
];
|
];
|
||||||
$return[] = $single;
|
$return[] = $single;
|
||||||
}
|
}
|
||||||
@@ -268,17 +274,18 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Recurrence $recurrence
|
* @param Recurrence $recurrence
|
||||||
* @param Carbon $date
|
* @param RecurrenceRepetition $repetition
|
||||||
|
* @param Carbon $date
|
||||||
*
|
*
|
||||||
* @return TransactionGroup|null
|
* @return TransactionGroup|null
|
||||||
*/
|
*/
|
||||||
private function handleOccurrence(Recurrence $recurrence, Carbon $date): ?TransactionGroup
|
private function handleOccurrence(Recurrence $recurrence, RecurrenceRepetition $repetition, Carbon $date): ?TransactionGroup
|
||||||
{
|
{
|
||||||
Log::debug(sprintf('Now at date %s.', $date->format('Y-m-d')));
|
#Log::debug(sprintf('Now at date %s.', $date->format('Y-m-d')));
|
||||||
$date->startOfDay();
|
$date->startOfDay();
|
||||||
if ($date->ne($this->date)) {
|
if ($date->ne($this->date)) {
|
||||||
Log::debug(sprintf('%s is not today (%s)', $date->format('Y-m-d'), $this->date->format('Y-m-d')));
|
#Log::debug(sprintf('%s is not today (%s)', $date->format('Y-m-d'), $this->date->format('Y-m-d')));
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -305,10 +312,11 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
$groupTitle = $first->description;
|
$groupTitle = $first->description;
|
||||||
// @codeCoverageIgnoreEnd
|
// @codeCoverageIgnoreEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
$array = [
|
$array = [
|
||||||
'user' => $recurrence->user_id,
|
'user' => $recurrence->user_id,
|
||||||
'group_title' => $groupTitle,
|
'group_title' => $groupTitle,
|
||||||
'transactions' => $this->getTransactionData($recurrence, $date),
|
'transactions' => $this->getTransactionData($recurrence, $repetition, $date),
|
||||||
];
|
];
|
||||||
/** @var TransactionGroup $group */
|
/** @var TransactionGroup $group */
|
||||||
$group = $this->groupRepository->store($array);
|
$group = $this->groupRepository->store($array);
|
||||||
@@ -328,17 +336,18 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
/**
|
/**
|
||||||
* Check if the occurences should be executed.
|
* Check if the occurences should be executed.
|
||||||
*
|
*
|
||||||
* @param Recurrence $recurrence
|
* @param Recurrence $recurrence
|
||||||
* @param array $occurrences
|
* @param RecurrenceRepetition $repetition
|
||||||
|
* @param array $occurrences
|
||||||
*
|
*
|
||||||
* @return Collection
|
* @return Collection
|
||||||
*/
|
*/
|
||||||
private function handleOccurrences(Recurrence $recurrence, array $occurrences): Collection
|
private function handleOccurrences(Recurrence $recurrence, RecurrenceRepetition $repetition, array $occurrences): Collection
|
||||||
{
|
{
|
||||||
$collection = new Collection;
|
$collection = new Collection;
|
||||||
/** @var Carbon $date */
|
/** @var Carbon $date */
|
||||||
foreach ($occurrences as $date) {
|
foreach ($occurrences as $date) {
|
||||||
$result = $this->handleOccurrence($recurrence, $date);
|
$result = $this->handleOccurrence($recurrence, $repetition, $date);
|
||||||
if (null !== $result) {
|
if (null !== $result) {
|
||||||
$collection->push($result);
|
$collection->push($result);
|
||||||
}
|
}
|
||||||
@@ -374,6 +383,7 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
$includeWeekend = clone $this->date;
|
$includeWeekend = clone $this->date;
|
||||||
$includeWeekend->addDays(2);
|
$includeWeekend->addDays(2);
|
||||||
$occurrences = $this->repository->getOccurrencesInRange($repetition, $recurrence->first_date, $includeWeekend);
|
$occurrences = $this->repository->getOccurrencesInRange($repetition, $recurrence->first_date, $includeWeekend);
|
||||||
|
/*
|
||||||
Log::debug(
|
Log::debug(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Calculated %d occurrences between %s and %s',
|
'Calculated %d occurrences between %s and %s',
|
||||||
@@ -383,9 +393,10 @@ class CreateRecurringTransactions implements ShouldQueue
|
|||||||
),
|
),
|
||||||
$this->debugArray($occurrences)
|
$this->debugArray($occurrences)
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
unset($includeWeekend);
|
unset($includeWeekend);
|
||||||
|
|
||||||
$result = $this->handleOccurrences($recurrence, $occurrences);
|
$result = $this->handleOccurrences($recurrence, $repetition, $occurrences);
|
||||||
$collection = $collection->merge($result);
|
$collection = $collection->merge($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -569,4 +569,28 @@ class RecurringRepository implements RecurringRepositoryInterface
|
|||||||
{
|
{
|
||||||
$this->user->recurrences()->delete();
|
$this->user->recurrences()->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function totalTransactions(Recurrence $recurrence, RecurrenceRepetition $repetition): int
|
||||||
|
{
|
||||||
|
// if repeat = null just return 0.
|
||||||
|
if (null === $recurrence->repeat_until && 0 === (int) $recurrence->repetitions) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
// expect X transactions then stop. Return that number
|
||||||
|
if (null === $recurrence->repeat_until && 0 !== (int) $recurrence->repetitions) {
|
||||||
|
return (int) $recurrence->repetitions;
|
||||||
|
}
|
||||||
|
|
||||||
|
// need to calculate, this depends on the repetition:
|
||||||
|
if (null !== $recurrence->repeat_until && 0 === (int) $recurrence->repetitions) {
|
||||||
|
$occurrences = $this->getOccurrencesInRange($repetition, $recurrence->first_date ?? today(), $recurrence->repeat_until);
|
||||||
|
|
||||||
|
return count($occurrences);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,15 @@ interface RecurringRepositoryInterface
|
|||||||
*/
|
*/
|
||||||
public function destroyAll(): void;
|
public function destroyAll(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate how many transactions are to be expected from this recurrence.
|
||||||
|
*
|
||||||
|
* @param Recurrence $recurrence
|
||||||
|
* @param RecurrenceRepetition $repetition
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function totalTransactions(Recurrence $recurrence, RecurrenceRepetition $repetition): int;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destroy a recurring transaction.
|
* Destroy a recurring transaction.
|
||||||
*
|
*
|
||||||
|
@@ -44,14 +44,10 @@ use Log;
|
|||||||
*/
|
*/
|
||||||
trait JournalServiceTrait
|
trait JournalServiceTrait
|
||||||
{
|
{
|
||||||
/** @var AccountRepositoryInterface */
|
private AccountRepositoryInterface $accountRepository;
|
||||||
private $accountRepository;
|
private BudgetRepositoryInterface $budgetRepository;
|
||||||
/** @var BudgetRepositoryInterface */
|
private CategoryRepositoryInterface $categoryRepository;
|
||||||
private $budgetRepository;
|
private TagFactory $tagFactory;
|
||||||
/** @var CategoryRepositoryInterface */
|
|
||||||
private $categoryRepository;
|
|
||||||
/** @var TagFactory */
|
|
||||||
private $tagFactory;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -46,11 +46,11 @@ trait CalculateRangeOccurrences
|
|||||||
{
|
{
|
||||||
$return = [];
|
$return = [];
|
||||||
$attempts = 0;
|
$attempts = 0;
|
||||||
Log::debug('Rep is daily. Start of loop.');
|
#Log::debug('Rep is daily. Start of loop.');
|
||||||
while ($start <= $end) {
|
while ($start <= $end) {
|
||||||
Log::debug(sprintf('Mutator is now: %s', $start->format('Y-m-d')));
|
#Log::debug(sprintf('Mutator is now: %s', $start->format('Y-m-d')));
|
||||||
if (0 === $attempts % $skipMod) {
|
if (0 === $attempts % $skipMod) {
|
||||||
Log::debug(sprintf('Attempts modulo skipmod is zero, include %s', $start->format('Y-m-d')));
|
#Log::debug(sprintf('Attempts modulo skipmod is zero, include %s', $start->format('Y-m-d')));
|
||||||
$return[] = clone $start;
|
$return[] = clone $start;
|
||||||
}
|
}
|
||||||
$start->addDay();
|
$start->addDay();
|
||||||
@@ -77,27 +77,27 @@ trait CalculateRangeOccurrences
|
|||||||
$return = [];
|
$return = [];
|
||||||
$attempts = 0;
|
$attempts = 0;
|
||||||
$dayOfMonth = (int)$moment;
|
$dayOfMonth = (int)$moment;
|
||||||
Log::debug(sprintf('Day of month in repetition is %d', $dayOfMonth));
|
#Log::debug(sprintf('Day of month in repetition is %d', $dayOfMonth));
|
||||||
Log::debug(sprintf('Start is %s.', $start->format('Y-m-d')));
|
#Log::debug(sprintf('Start is %s.', $start->format('Y-m-d')));
|
||||||
Log::debug(sprintf('End is %s.', $end->format('Y-m-d')));
|
#Log::debug(sprintf('End is %s.', $end->format('Y-m-d')));
|
||||||
if ($start->day > $dayOfMonth) {
|
if ($start->day > $dayOfMonth) {
|
||||||
Log::debug('Add a month.');
|
#Log::debug('Add a month.');
|
||||||
// day has passed already, add a month.
|
// day has passed already, add a month.
|
||||||
$start->addMonth();
|
$start->addMonth();
|
||||||
}
|
}
|
||||||
Log::debug(sprintf('Start is now %s.', $start->format('Y-m-d')));
|
#Log::debug(sprintf('Start is now %s.', $start->format('Y-m-d')));
|
||||||
Log::debug('Start loop.');
|
#Log::debug('Start loop.');
|
||||||
while ($start < $end) {
|
while ($start < $end) {
|
||||||
Log::debug(sprintf('Mutator is now %s.', $start->format('Y-m-d')));
|
#Log::debug(sprintf('Mutator is now %s.', $start->format('Y-m-d')));
|
||||||
$domCorrected = min($dayOfMonth, $start->daysInMonth);
|
$domCorrected = min($dayOfMonth, $start->daysInMonth);
|
||||||
Log::debug(sprintf('DoM corrected is %d', $domCorrected));
|
#Log::debug(sprintf('DoM corrected is %d', $domCorrected));
|
||||||
$start->day = $domCorrected;
|
$start->day = $domCorrected;
|
||||||
Log::debug(sprintf('Mutator is now %s.', $start->format('Y-m-d')));
|
#Log::debug(sprintf('Mutator is now %s.', $start->format('Y-m-d')));
|
||||||
Log::debug(sprintf('$attempts %% $skipMod === 0 is %s', var_export(0 === $attempts % $skipMod, true)));
|
#Log::debug(sprintf('$attempts %% $skipMod === 0 is %s', var_export(0 === $attempts % $skipMod, true)));
|
||||||
Log::debug(sprintf('$start->lte($mutator) is %s', var_export($start->lte($start), true)));
|
#Log::debug(sprintf('$start->lte($mutator) is %s', var_export($start->lte($start), true)));
|
||||||
Log::debug(sprintf('$end->gte($mutator) is %s', var_export($end->gte($start), true)));
|
#Log::debug(sprintf('$end->gte($mutator) is %s', var_export($end->gte($start), true)));
|
||||||
if (0 === $attempts % $skipMod && $start->lte($start) && $end->gte($start)) {
|
if (0 === $attempts % $skipMod && $start->lte($start) && $end->gte($start)) {
|
||||||
Log::debug(sprintf('ADD %s to return!', $start->format('Y-m-d')));
|
#Log::debug(sprintf('ADD %s to return!', $start->format('Y-m-d')));
|
||||||
$return[] = clone $start;
|
$return[] = clone $start;
|
||||||
}
|
}
|
||||||
$attempts++;
|
$attempts++;
|
||||||
|
@@ -60,7 +60,8 @@ class TransactionGroupTransformer extends AbstractTransformer
|
|||||||
$this->metaFields = [
|
$this->metaFields = [
|
||||||
'sepa_cc', 'sepa_ct_op', 'sepa_ct_id', 'sepa_db', 'sepa_country', 'sepa_ep',
|
'sepa_cc', 'sepa_ct_op', 'sepa_ct_id', 'sepa_db', 'sepa_country', 'sepa_ep',
|
||||||
'sepa_ci', 'sepa_batch_id', 'internal_reference', 'bunq_payment_id', 'import_hash_v2',
|
'sepa_ci', 'sepa_batch_id', 'internal_reference', 'bunq_payment_id', 'import_hash_v2',
|
||||||
'recurrence_id', 'external_id', 'original_source', 'external_uri'
|
'recurrence_id', 'external_id', 'original_source', 'external_uri',
|
||||||
|
'recurrence_count', 'recurrence_total',
|
||||||
];
|
];
|
||||||
$this->metaDateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
$this->metaDateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date'];
|
||||||
|
|
||||||
@@ -492,13 +493,15 @@ class TransactionGroupTransformer extends AbstractTransformer
|
|||||||
'bill_name' => $row['bill_name'],
|
'bill_name' => $row['bill_name'],
|
||||||
|
|
||||||
'reconciled' => $row['reconciled'],
|
'reconciled' => $row['reconciled'],
|
||||||
'notes' => $this->groupRepos->getNoteText((int)$row['transaction_journal_id']),
|
'notes' => $this->groupRepos->getNoteText((int) $row['transaction_journal_id']),
|
||||||
'tags' => $this->groupRepos->getTags((int)$row['transaction_journal_id']),
|
'tags' => $this->groupRepos->getTags((int) $row['transaction_journal_id']),
|
||||||
|
|
||||||
'internal_reference' => $metaFieldData['internal_reference'],
|
'internal_reference' => $metaFieldData['internal_reference'],
|
||||||
'external_id' => $metaFieldData['external_id'],
|
'external_id' => $metaFieldData['external_id'],
|
||||||
'original_source' => $metaFieldData['original_source'],
|
'original_source' => $metaFieldData['original_source'],
|
||||||
'recurrence_id' => $metaFieldData['recurrence_id'],
|
'recurrence_id' => null !== $metaFieldData['recurrence_id'] ? (int) $metaFieldData['recurrence_id'] : null,
|
||||||
|
'recurrence_total' => null !== $metaFieldData['recurrence_total'] ? (int) $metaFieldData['recurrence_total'] : null,
|
||||||
|
'recurrence_count' => null !== $metaFieldData['recurrence_count'] ? (int) $metaFieldData['recurrence_count'] : null,
|
||||||
'bunq_payment_id' => $metaFieldData['bunq_payment_id'],
|
'bunq_payment_id' => $metaFieldData['bunq_payment_id'],
|
||||||
'external_uri' => $metaFieldData['external_uri'],
|
'external_uri' => $metaFieldData['external_uri'],
|
||||||
'import_hash_v2' => $metaFieldData['import_hash_v2'],
|
'import_hash_v2' => $metaFieldData['import_hash_v2'],
|
||||||
@@ -520,7 +523,6 @@ class TransactionGroupTransformer extends AbstractTransformer
|
|||||||
'invoice_date' => $metaDateData['invoice_date'] ? $metaDateData['invoice_date']->toAtomString() : null,
|
'invoice_date' => $metaDateData['invoice_date'] ? $metaDateData['invoice_date']->toAtomString() : null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1637,6 +1637,7 @@ return [
|
|||||||
'created_withdrawals' => 'Created withdrawals',
|
'created_withdrawals' => 'Created withdrawals',
|
||||||
'created_deposits' => 'Created deposits',
|
'created_deposits' => 'Created deposits',
|
||||||
'created_transfers' => 'Created transfers',
|
'created_transfers' => 'Created transfers',
|
||||||
|
'recurring_info' => 'Recurring transaction :count / :total',
|
||||||
'created_from_recurrence' => 'Created from recurring transaction ":title" (#:id)',
|
'created_from_recurrence' => 'Created from recurring transaction ":title" (#:id)',
|
||||||
'recurring_never_cron' => 'It seems the cron job that is necessary to support recurring transactions has never run. This is of course normal when you have just installed Firefly III, but this should be something to set up as soon as possible. Please check out the help-pages using the (?)-icon in the top right corner of the page.',
|
'recurring_never_cron' => 'It seems the cron job that is necessary to support recurring transactions has never run. This is of course normal when you have just installed Firefly III, but this should be something to set up as soon as possible. Please check out the help-pages using the (?)-icon in the top right corner of the page.',
|
||||||
'recurring_cron_long_ago' => 'It looks like it has been more than 36 hours since the cron job to support recurring transactions has fired for the last time. Are you sure it has been set up correctly? Please check out the help-pages using the (?)-icon in the top right corner of the page.',
|
'recurring_cron_long_ago' => 'It looks like it has been more than 36 hours since the cron job to support recurring transactions has fired for the last time. Are you sure it has been set up correctly? Please check out the help-pages using the (?)-icon in the top right corner of the page.',
|
||||||
|
@@ -37,6 +37,7 @@ return [
|
|||||||
'linked_to_rules' => 'Relevant rules',
|
'linked_to_rules' => 'Relevant rules',
|
||||||
'active' => 'Is active?',
|
'active' => 'Is active?',
|
||||||
'percentage' => 'pct.',
|
'percentage' => 'pct.',
|
||||||
|
'recurring_transaction' => 'Recurring transaction',
|
||||||
'next_due' => 'Next due',
|
'next_due' => 'Next due',
|
||||||
'transaction_type' => 'Type',
|
'transaction_type' => 'Type',
|
||||||
'lastActivity' => 'Last activity',
|
'lastActivity' => 'Last activity',
|
||||||
|
@@ -276,6 +276,16 @@
|
|||||||
<td class="markdown">{{ journal.notes|markdown }}</td>
|
<td class="markdown">{{ journal.notes|markdown }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if journalHasMeta(journal.transaction_journal_id, 'recurring_total') and journalHasMeta(journal.transaction_journal_id, 'recurring_count') %}
|
||||||
|
{% set recurringTotal = journalGetMetaField(journal.transaction_journal_id, 'recurring_total') %}
|
||||||
|
{% if 0 == recurringTotal %}
|
||||||
|
{% set recurringTotal = '∞' %}
|
||||||
|
{% endif %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ trans('list.recurring_transaction') }}</td>
|
||||||
|
<td>{{ trans('firefly.recurring_info', {total: recurringTotal, count: journalGetMetaField(journal.transaction_journal_id, 'recurring_count') }) }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
{% if journal.tags|length > 0 %}
|
{% if journal.tags|length > 0 %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ 'tags'|_ }}</td>
|
<td>{{ 'tags'|_ }}</td>
|
||||||
|
Reference in New Issue
Block a user