Compare commits

..

38 Commits

Author SHA1 Message Date
Herculino Trotta
992c518dab Merge pull request #222
fix(net-worth): non-used currencies showing up on charts
2025-03-23 01:35:14 -03:00
Herculino Trotta
29aa1c9d2b fix(net-worth): non-used currencies showing up on charts 2025-03-23 01:34:53 -03:00
Herculino Trotta
1b3b7a583d Merge pull request #220 from eitchtee/dependabot/pip/gunicorn-23.0.0
chore(deps): bump gunicorn from 22.0.0 to 23.0.0
2025-03-22 01:02:43 -03:00
dependabot[bot]
2d22f961ad chore(deps): bump gunicorn from 22.0.0 to 23.0.0
Bumps [gunicorn](https://github.com/benoitc/gunicorn) from 22.0.0 to 23.0.0.
- [Release notes](https://github.com/benoitc/gunicorn/releases)
- [Commits](https://github.com/benoitc/gunicorn/compare/22.0.0...23.0.0)

---
updated-dependencies:
- dependency-name: gunicorn
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-22 04:01:48 +00:00
Herculino Trotta
71551d7651 Merge pull request #219
fix(insights:category-explorer): category field not loading available categories correctly
2025-03-15 11:37:46 -03:00
Herculino Trotta
62d58d1be3 fix(insights:category-explorer): category field not loading available categories correctly 2025-03-15 11:37:28 -03:00
Herculino Trotta
21917437f2 Merge pull request #218
fix(tools:currency-converter): currency list displaying oldest result instead of newest
2025-03-13 22:18:21 -03:00
Herculino Trotta
59acb14d05 fix(tools:currency-converter): currency list displaying oldest result instead of newest 2025-03-13 22:18:02 -03:00
Dimitri Decrock
050f794f2b locale(Dutch): update translation
Currently translated at 100.0% (611 of 611 strings)

Translation: WYGIWYH/App
Translate-URL: https://translations.herculino.com/projects/wygiwyh/app/nl/
2025-03-13 07:05:35 +00:00
Schmitz Schmitz
a5958c0937 locale(German): update translation
Currently translated at 99.6% (609 of 611 strings)

Translation: WYGIWYH/App
Translate-URL: https://translations.herculino.com/projects/wygiwyh/app/de/
2025-03-10 09:05:35 +00:00
Herculino Trotta
ee73ada5ae Merge pull request #215
fix: missing selection when updating transactions in a transaction list
2025-03-09 20:22:18 -03:00
Herculino Trotta
736a116685 fix: missing selection when updating transactions in a transaction list 2025-03-09 20:21:48 -03:00
Herculino Trotta
6c03c7b4eb locale(Portuguese (Brazil)): update translation
Currently translated at 100.0% (611 of 611 strings)

Translation: WYGIWYH/App
Translate-URL: https://translations.herculino.com/projects/wygiwyh/app/pt_BR/
2025-03-09 23:10:59 +00:00
eitchtee
960e537709 chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2025-03-09 21:56:43 +00:00
Herculino Trotta
e32285ce75 Merge pull request #214
feat: alphabetically order most models by default
2025-03-09 18:56:10 -03:00
Herculino Trotta
73e8fdbf04 feat: alphabetically order most models by default
#207
2025-03-09 18:55:29 -03:00
Herculino Trotta
d4c15da051 Merge pull request #212
feat(monthly_overview): preserve filter between month changes
2025-03-09 18:46:38 -03:00
Herculino Trotta
187b3174d2 feat(monthly_overview): preserve filter between month changes
#208
2025-03-09 18:45:55 -03:00
eitchtee
c90ea7ef16 chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2025-03-09 20:55:47 +00:00
Herculino Trotta
54713ecfe2 Merge pull request #211
fix(transactions:transfer): remove required description field
2025-03-09 17:55:15 -03:00
Herculino Trotta
cf693aa0c3 fix(transactions:transfer): remove required description field
#209
2025-03-09 17:54:16 -03:00
eitchtee
3580f1b132 chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2025-03-09 20:51:39 +00:00
Herculino Trotta
febd9a8ae7 Merge pull request #210
feat(transactions): add option for removing Recurring/Installment descriptions and notes from generated transactions
2025-03-09 17:50:59 -03:00
Herculino Trotta
3809f82b60 feat(transactions): add option for removing Recurring/Installment descriptions and notes from generated transactions
#209
2025-03-09 17:50:27 -03:00
Dimitri Decrock
3c6b52462a locale(Dutch): update translation
Currently translated at 100.0% (609 of 609 strings)

Translation: WYGIWYH/App
Translate-URL: https://translations.herculino.com/projects/wygiwyh/app/nl/
2025-03-09 12:05:35 +00:00
Herculino Trotta
cc8a4c97a9 locale(Portuguese (Brazil)): update translation
Currently translated at 100.0% (609 of 609 strings)

Translation: WYGIWYH/App
Translate-URL: https://translations.herculino.com/projects/wygiwyh/app/pt_BR/
2025-03-09 04:56:21 +00:00
eitchtee
99fbb5f7db chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2025-03-09 04:55:05 +00:00
Herculino Trotta
3d61068ecf Merge pull request #206
feat(rules): trigger transaction rules on delete
2025-03-09 01:54:28 -03:00
Herculino Trotta
f6f06f4d65 feat(rules): trigger transaction rules on delete 2025-03-09 01:54:03 -03:00
eitchtee
56346c26ee chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2025-03-09 04:27:30 +00:00
Herculino Trotta
23b74d73e5 Merge pull request #205
fix(rules): unable to save
2025-03-09 01:26:57 -03:00
Herculino Trotta
17697dc565 fix(rules): unable to save 2025-03-09 01:26:42 -03:00
Herculino Trotta
e9bc35d9b2 Merge pull request #204
fix(api): re-order transactions from newest to oldest
2025-03-08 23:23:25 -03:00
Herculino Trotta
d6fbb71f41 fix(api): re-order transactions from newest to oldest 2025-03-08 23:23:07 -03:00
eitchtee
9a9cf75bcd chore(locale): update translation files
[skip ci] Automatically generated by Django makemessages workflow
2025-03-09 01:10:53 +00:00
Herculino Trotta
d6a8658fe1 Merge pull request #203
fix(api): unable to create transaction
2025-03-08 22:09:40 -03:00
Herculino Trotta
211963ea7d fix(api): unable to create transaction 2025-03-08 22:09:24 -03:00
Herculino Trotta
776068a438 locale(Portuguese (Brazil)): update translation
Currently translated at 100.0% (608 of 608 strings)

Translation: WYGIWYH/App
Translate-URL: https://translations.herculino.com/projects/wygiwyh/app/pt_BR/
2025-03-08 18:05:35 +00:00
29 changed files with 1287 additions and 926 deletions

View File

@@ -0,0 +1,21 @@
# Generated by Django 5.1.7 on 2025-03-09 21:54
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('accounts', '0013_alter_account_visibility_and_more'),
]
operations = [
migrations.AlterModelOptions(
name='account',
options={'ordering': ['name', 'id'], 'verbose_name': 'Account', 'verbose_name_plural': 'Accounts'},
),
migrations.AlterModelOptions(
name='accountgroup',
options={'ordering': ['name', 'id'], 'verbose_name': 'Account Group', 'verbose_name_plural': 'Account Groups'},
),
]

View File

@@ -19,6 +19,7 @@ class AccountGroup(SharedObject):
verbose_name_plural = _("Account Groups")
db_table = "account_groups"
unique_together = (("owner", "name"),)
ordering = ["name", "id"]
def __str__(self):
return self.name
@@ -69,6 +70,7 @@ class Account(SharedObject):
verbose_name = _("Account")
verbose_name_plural = _("Accounts")
unique_together = (("owner", "name"),)
ordering = ["name", "id"]
def __str__(self):
return self.name

View File

@@ -23,6 +23,7 @@ from apps.transactions.models import (
TransactionEntity,
RecurringTransaction,
)
from apps.common.middleware.thread_local import get_current_user
class TransactionCategorySerializer(serializers.ModelSerializer):
@@ -31,6 +32,10 @@ class TransactionCategorySerializer(serializers.ModelSerializer):
class Meta:
model = TransactionCategory
fields = "__all__"
read_only_fields = [
"id",
"owner",
]
class TransactionTagSerializer(serializers.ModelSerializer):
@@ -39,6 +44,10 @@ class TransactionTagSerializer(serializers.ModelSerializer):
class Meta:
model = TransactionTag
fields = "__all__"
read_only_fields = [
"id",
"owner",
]
class TransactionEntitySerializer(serializers.ModelSerializer):
@@ -47,6 +56,10 @@ class TransactionEntitySerializer(serializers.ModelSerializer):
class Meta:
model = TransactionEntity
fields = "__all__"
read_only_fields = [
"id",
"owner",
]
class InstallmentPlanSerializer(serializers.ModelSerializer):
@@ -157,8 +170,16 @@ class TransactionSerializer(serializers.ModelSerializer):
"installment_plan",
"recurring_transaction",
"installment_id",
"owner",
"deleted_at",
"deleted",
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["account_id"].queryset = Account.objects.all()
def validate(self, data):
if not self.partial:
if "date" in data and "reference_date" not in data:

View File

@@ -20,6 +20,8 @@ class AccountViewSet(viewsets.ModelViewSet):
pagination_class = CustomPageNumberPagination
def get_queryset(self):
return Account.objects.all().select_related(
"group", "currency", "exchange_currency"
return (
Account.objects.all()
.order_by("id")
.select_related("group", "currency", "exchange_currency")
)

View File

@@ -38,7 +38,7 @@ class TransactionViewSet(viewsets.ModelViewSet):
return self.update(request, *args, **kwargs)
def get_queryset(self):
return Transaction.objects.all().order_by("id")
return Transaction.objects.all().order_by("-id")
class TransactionCategoryViewSet(viewsets.ModelViewSet):
@@ -51,7 +51,7 @@ class TransactionCategoryViewSet(viewsets.ModelViewSet):
class TransactionTagViewSet(viewsets.ModelViewSet):
queryset = TransactionTag.objects.all().order_by("id")
queryset = TransactionTag.objects.all()
serializer_class = TransactionTagSerializer
pagination_class = CustomPageNumberPagination
@@ -60,7 +60,7 @@ class TransactionTagViewSet(viewsets.ModelViewSet):
class TransactionEntityViewSet(viewsets.ModelViewSet):
queryset = TransactionEntity.objects.all().order_by("id")
queryset = TransactionEntity.objects.all()
serializer_class = TransactionEntitySerializer
pagination_class = CustomPageNumberPagination
@@ -69,18 +69,18 @@ class TransactionEntityViewSet(viewsets.ModelViewSet):
class InstallmentPlanViewSet(viewsets.ModelViewSet):
queryset = InstallmentPlan.objects.all().order_by("id")
queryset = InstallmentPlan.objects.all()
serializer_class = InstallmentPlanSerializer
pagination_class = CustomPageNumberPagination
def get_queryset(self):
return InstallmentPlan.objects.all().order_by("id")
return InstallmentPlan.objects.all().order_by("-id")
class RecurringTransactionViewSet(viewsets.ModelViewSet):
queryset = RecurringTransaction.objects.all().order_by("id")
queryset = RecurringTransaction.objects.all()
serializer_class = RecurringTransactionSerializer
pagination_class = CustomPageNumberPagination
def get_queryset(self):
return RecurringTransaction.objects.all().order_by("id")
return RecurringTransaction.objects.all().order_by("-id")

View File

@@ -0,0 +1,17 @@
# Generated by Django 5.1.7 on 2025-03-09 21:54
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('currencies', '0013_alter_exchangerateservice_service_type'),
]
operations = [
migrations.AlterModelOptions(
name='currency',
options={'ordering': ['name', 'id'], 'verbose_name': 'Currency', 'verbose_name_plural': 'Currencies'},
),
]

View File

@@ -38,6 +38,7 @@ class Currency(models.Model):
class Meta:
verbose_name = _("Currency")
verbose_name_plural = _("Currencies")
ordering = ["name", "id"]
def clean(self):
super().clean()

View File

@@ -117,13 +117,15 @@ class CategoryForm(forms.Form):
required=False,
label=_("Category"),
empty_label=_("Uncategorized"),
queryset=TransactionCategory.objects.filter(active=True),
queryset=TransactionCategory.objects.all(),
widget=TomSelect(clear_button=True),
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields["category"].queryset = TransactionCategory.objects.all()
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.disable_csrf = True

View File

@@ -40,8 +40,8 @@ def get_currency_exchange_map(date=None) -> Dict[str, dict]:
date_diff=Func(Extract(F("date") - Value(date), "epoch"), function="ABS"),
effective_rate=F("rate"),
)
.order_by("from_currency", "to_currency", "date_diff")
.distinct("from_currency", "to_currency")
.order_by("from_currency", "to_currency", "-date_diff")
.distinct()
)
# Initialize the result dictionary

View File

@@ -2,25 +2,38 @@ from collections import OrderedDict, defaultdict
from decimal import Decimal
from dateutil.relativedelta import relativedelta
from django.db.models import Sum, Min, Max, Case, When, F, Value, DecimalField
from django.db.models import Sum, Min, Max, Case, When, F, Value, DecimalField, Q
from django.db.models.functions import TruncMonth
from django.template.defaultfilters import date as date_filter
from django.utils import timezone
from apps.accounts.models import Account
from apps.common.middleware.thread_local import get_current_user
from apps.currencies.models import Currency
from apps.transactions.models import Transaction
def calculate_historical_currency_net_worth(is_paid=True):
transactions_params = {**{k: v for k, v in [("is_paid", True)] if is_paid}}
def calculate_historical_currency_net_worth(queryset):
# Get all currencies and date range in a single query
aggregates = Transaction.objects.aggregate(
aggregates = queryset.aggregate(
min_date=Min("reference_date"),
max_date=Max("reference_date"),
)
currencies = list(Currency.objects.values_list("name", flat=True))
user = get_current_user()
currencies = list(
Currency.objects.filter(
Q(accounts__visibility="public")
| Q(accounts__owner=user)
| Q(accounts__shared_with=user)
| Q(accounts__visibility="private", accounts__owner=None),
accounts__is_archived=False,
accounts__isnull=False,
)
.values_list("name", flat=True)
.distinct()
)
if not aggregates.get("min_date"):
start_date = timezone.localdate(timezone.now())
@@ -34,8 +47,7 @@ def calculate_historical_currency_net_worth(is_paid=True):
# Calculate cumulative balances for each account, currency, and month
cumulative_balances = (
Transaction.objects.filter(**transactions_params)
.annotate(month=TruncMonth("reference_date"))
queryset.annotate(month=TruncMonth("reference_date"))
.values("account__currency__name", "month")
.annotate(
balance=Sum(
@@ -94,15 +106,14 @@ def calculate_historical_currency_net_worth(is_paid=True):
return historical_net_worth
def calculate_historical_account_balance(is_paid=True):
transactions_params = {**{k: v for k, v in [("is_paid", True)] if is_paid}}
def calculate_historical_account_balance(queryset):
# Get all accounts
accounts = Account.objects.filter(
is_archived=False,
)
# Get the date range
date_range = Transaction.objects.filter(**transactions_params).aggregate(
date_range = queryset.aggregate(
min_date=Min("reference_date"), max_date=Max("reference_date")
)
@@ -118,8 +129,7 @@ def calculate_historical_account_balance(is_paid=True):
# Calculate balances for each account and month
balances = (
Transaction.objects.filter(**transactions_params)
.annotate(month=TruncMonth("reference_date"))
queryset.annotate(month=TruncMonth("reference_date"))
.values("account", "month")
.annotate(
balance=Sum(

View File

@@ -38,7 +38,9 @@ def net_worth_current(request):
transactions_queryset=transactions_account_queryset
)
historical_currency_net_worth = calculate_historical_currency_net_worth()
historical_currency_net_worth = calculate_historical_currency_net_worth(
queryset=transactions_currency_queryset
)
labels = (
list(historical_currency_net_worth.keys())
@@ -71,7 +73,9 @@ def net_worth_current(request):
chart_data_currency_json = json.dumps(chart_data_currency, cls=DjangoJSONEncoder)
historical_account_balance = calculate_historical_account_balance()
historical_account_balance = calculate_historical_account_balance(
queryset=transactions_account_queryset
)
labels = (
list(historical_account_balance.keys()) if historical_account_balance else []
@@ -140,7 +144,7 @@ def net_worth_projected(request):
)
historical_currency_net_worth = calculate_historical_currency_net_worth(
is_paid=False
queryset=transactions_currency_queryset
)
labels = (
@@ -174,7 +178,9 @@ def net_worth_projected(request):
chart_data_currency_json = json.dumps(chart_data_currency, cls=DjangoJSONEncoder)
historical_account_balance = calculate_historical_account_balance(is_paid=False)
historical_account_balance = calculate_historical_account_balance(
queryset=transactions_account_queryset
)
labels = (
list(historical_account_balance.keys()) if historical_account_balance else []

View File

@@ -16,9 +16,11 @@ class TransactionRuleForm(forms.ModelForm):
class Meta:
model = TransactionRule
fields = "__all__"
exclude = ("owner", "shared_with", "visibility")
labels = {
"on_create": _("Run on creation"),
"on_update": _("Run on update"),
"on_delete": _("Run on delete"),
"trigger": _("If..."),
}
widgets = {"description": forms.widgets.TextInput}
@@ -33,7 +35,11 @@ class TransactionRuleForm(forms.ModelForm):
self.helper.layout = Layout(
Switch("active"),
"name",
Row(Column(Switch("on_update")), Column(Switch("on_create"))),
Row(
Column(Switch("on_update")),
Column(Switch("on_create")),
Column(Switch("on_delete")),
),
"description",
"trigger",
)

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.1.7 on 2025-03-09 03:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('rules', '0012_transactionrule_owner_transactionrule_shared_with_and_more'),
]
operations = [
migrations.AddField(
model_name='transactionrule',
name='on_delete',
field=models.BooleanField(default=False),
),
]

View File

@@ -9,6 +9,7 @@ class TransactionRule(SharedObject):
active = models.BooleanField(default=True)
on_update = models.BooleanField(default=False)
on_create = models.BooleanField(default=True)
on_delete = models.BooleanField(default=False)
name = models.CharField(max_length=100, verbose_name=_("Name"))
description = models.TextField(blank=True, null=True, verbose_name=_("Description"))
trigger = models.TextField(verbose_name=_("Trigger"))

View File

@@ -1,9 +1,11 @@
from django.conf import settings
from django.dispatch import receiver
from apps.transactions.models import (
Transaction,
transaction_created,
transaction_updated,
transaction_deleted,
)
from apps.rules.tasks import check_for_transaction_rules
from apps.common.middleware.thread_local import get_current_user
@@ -11,7 +13,45 @@ from apps.common.middleware.thread_local import get_current_user
@receiver(transaction_created)
@receiver(transaction_updated)
@receiver(transaction_deleted)
def transaction_changed_receiver(sender: Transaction, signal, **kwargs):
if signal is transaction_deleted:
# Serialize transaction data for processing
transaction_data = {
"id": sender.id,
"account": (sender.account.id, sender.account.name),
"account_group": (
sender.account.group.id if sender.account.group else None,
sender.account.group.name if sender.account.group else None,
),
"type": str(sender.type),
"is_paid": sender.is_paid,
"is_asset": sender.account.is_asset,
"is_archived": sender.account.is_archived,
"category": (
sender.category.id if sender.category else None,
sender.category.name if sender.category else None,
),
"date": sender.date.isoformat(),
"reference_date": sender.reference_date.isoformat(),
"amount": str(sender.amount),
"description": sender.description,
"notes": sender.notes,
"tags": list(sender.tags.values_list("id", "name")),
"entities": list(sender.entities.values_list("id", "name")),
"deleted": True,
"internal_note": sender.internal_note,
"internal_id": sender.internal_id,
}
check_for_transaction_rules.defer(
transaction_data=transaction_data,
user_id=get_current_user().id,
signal="transaction_deleted",
is_hard_deleted=kwargs.get("hard_delete", not settings.ENABLE_SOFT_DELETE),
)
return
for dca_entry in sender.dca_expense_entries.all():
dca_entry.amount_paid = sender.amount
dca_entry.save()

View File

@@ -1,6 +1,8 @@
import decimal
import logging
from datetime import datetime, date
from decimal import Decimal
from typing import Any
from cachalot.api import cachalot_disabled
from dateutil.relativedelta import relativedelta
@@ -26,16 +28,27 @@ logger = logging.getLogger(__name__)
@app.task(name="check_for_transaction_rules")
def check_for_transaction_rules(
instance_id: int,
user_id: int,
signal,
instance_id=None,
transaction_data=None,
user_id=None,
signal=None,
is_hard_deleted=False,
):
user = get_user_model().objects.get(id=user_id)
write_current_user(user)
try:
with cachalot_disabled():
instance = Transaction.objects.get(id=instance_id)
# For deleted transactions
if signal == "transaction_deleted" and transaction_data:
# Create a transaction-like object from the serialized data
if is_hard_deleted:
instance = transaction_data
else:
instance = Transaction.deleted_objects.get(id=instance_id)
else:
# Regular transaction processing for creates and updates
instance = Transaction.objects.get(id=instance_id)
functions = {
"relativedelta": relativedelta,
@@ -47,10 +60,11 @@ def check_for_transaction_rules(
"date": date,
}
simple = EvalWithCompoundTypes(
names=_get_names(instance), functions=functions
)
names = _get_names(instance)
simple = EvalWithCompoundTypes(names=names, functions=functions)
# Select rules based on the signal type
if signal == "transaction_created":
rules = TransactionRule.objects.filter(
active=True, on_create=True
@@ -59,39 +73,56 @@ def check_for_transaction_rules(
rules = TransactionRule.objects.filter(
active=True, on_update=True
).order_by("id")
elif signal == "transaction_deleted":
rules = TransactionRule.objects.filter(
active=True, on_delete=True
).order_by("id")
else:
rules = TransactionRule.objects.filter(active=True).order_by("id")
# Process the rules as before
for rule in rules:
if simple.eval(rule.trigger):
for action in rule.transaction_actions.all():
try:
instance = _process_edit_transaction_action(
instance=instance, action=action, simple_eval=simple
)
except Exception as e:
logger.error(
f"Error processing edit transaction action {action.id}",
exc_info=True,
)
# else:
# simple.names.update(_get_names(instance))
# instance.save()
# For deleted transactions, we might want to limit what actions can be performed
if signal == "transaction_deleted":
# Process only create/update actions, not edit actions
for action in rule.update_or_create_transaction_actions.all():
try:
_process_update_or_create_transaction_action(
action=action, simple_eval=simple
)
except Exception as e:
logger.error(
f"Error processing update or create transaction action {action.id} on deletion",
exc_info=True,
)
else:
# Normal processing for non-deleted transactions
for action in rule.transaction_actions.all():
try:
instance = _process_edit_transaction_action(
instance=instance, action=action, simple_eval=simple
)
except Exception as e:
logger.error(
f"Error processing edit transaction action {action.id}",
exc_info=True,
)
simple.names.update(_get_names(instance))
instance.save()
for action in rule.update_or_create_transaction_actions.all():
try:
_process_update_or_create_transaction_action(
action=action, simple_eval=simple
)
except Exception as e:
logger.error(
f"Error processing update or create transaction action {action.id}",
exc_info=True,
)
simple.names.update(_get_names(instance))
if signal != "transaction_deleted":
instance.save()
for action in rule.update_or_create_transaction_actions.all():
try:
_process_update_or_create_transaction_action(
action=action, simple_eval=simple
)
except Exception as e:
logger.error(
f"Error processing update or create transaction action {action.id}",
exc_info=True,
)
except Exception as e:
logger.error(
"Error while executing 'check_for_transaction_rules' task",
@@ -99,40 +130,68 @@ def check_for_transaction_rules(
)
delete_current_user()
raise e
delete_current_user()
def _get_names(instance):
return {
"id": instance.id,
"account_name": instance.account.name,
"account_id": instance.account.id,
"account_group_name": (
instance.account.group.name if instance.account.group else None
),
"account_group_id": (
instance.account.group.id if instance.account.group else None
),
"is_asset_account": instance.account.is_asset,
"is_archived_account": instance.account.is_archived,
"category_name": instance.category.name if instance.category else None,
"category_id": instance.category.id if instance.category else None,
"tag_names": [x.name for x in instance.tags.all()],
"tag_ids": [x.id for x in instance.tags.all()],
"entities_names": [x.name for x in instance.entities.all()],
"entities_ids": [x.id for x in instance.entities.all()],
"is_expense": instance.type == Transaction.Type.EXPENSE,
"is_income": instance.type == Transaction.Type.INCOME,
"is_paid": instance.is_paid,
"description": instance.description,
"amount": instance.amount,
"notes": instance.notes,
"date": instance.date,
"reference_date": instance.reference_date,
"internal_note": instance.internal_note,
"internal_id": instance.internal_id,
}
def _get_names(instance: Transaction | dict):
if isinstance(instance, Transaction):
return {
"id": instance.id,
"account_name": instance.account.name,
"account_id": instance.account.id,
"account_group_name": (
instance.account.group.name if instance.account.group else None
),
"account_group_id": (
instance.account.group.id if instance.account.group else None
),
"is_asset_account": instance.account.is_asset,
"is_archived_account": instance.account.is_archived,
"category_name": instance.category.name if instance.category else None,
"category_id": instance.category.id if instance.category else None,
"tag_names": [x.name for x in instance.tags.all()],
"tag_ids": [x.id for x in instance.tags.all()],
"entities_names": [x.name for x in instance.entities.all()],
"entities_ids": [x.id for x in instance.entities.all()],
"is_expense": instance.type == Transaction.Type.EXPENSE,
"is_income": instance.type == Transaction.Type.INCOME,
"is_paid": instance.is_paid,
"description": instance.description,
"amount": instance.amount,
"notes": instance.notes,
"date": instance.date,
"reference_date": instance.reference_date,
"internal_note": instance.internal_note,
"internal_id": instance.internal_id,
"is_deleted": instance.deleted,
}
else:
return {
"id": instance.get("id"),
"account_name": instance.get("account", (None, None))[1],
"account_id": instance.get("account", (None, None))[0],
"account_group_name": instance.get("account_group", (None, None))[1],
"account_group_id": instance.get("account_group", (None, None))[0],
"is_asset_account": instance.get("is_asset"),
"is_archived_account": instance.get("is_archived"),
"category_name": instance.get("category", (None, None))[1],
"category_id": instance.get("category", (None, None))[0],
"tag_names": [x[1] for x in instance.get("tags", [])],
"tag_ids": [x[0] for x in instance.get("tags", [])],
"entities_names": [x[1] for x in instance.get("entities", [])],
"entities_ids": [x[0] for x in instance.get("entities", [])],
"is_expense": instance.get("type") == Transaction.Type.EXPENSE,
"is_income": instance.get("type") == Transaction.Type.INCOME,
"is_paid": instance.get("is_paid"),
"description": instance.get("description", ""),
"amount": Decimal(instance.get("amount")),
"notes": instance.get("notes", ""),
"date": datetime.fromisoformat(instance.get("date")),
"reference_date": datetime.fromisoformat(instance.get("reference_date")),
"internal_note": instance.get("internal_note", ""),
"internal_id": instance.get("internal_id", ""),
"is_deleted": instance.get("deleted", True),
}
def _process_update_or_create_transaction_action(action, simple_eval):

View File

@@ -334,7 +334,9 @@ class TransferForm(forms.Form):
widget=AirMonthYearPickerInput(), label=_("Reference Date"), required=False
)
description = forms.CharField(max_length=500, label=_("Description"))
description = forms.CharField(
max_length=500, label=_("Description"), required=False
)
notes = forms.CharField(
required=False,
widget=forms.Textarea(
@@ -538,6 +540,8 @@ class InstallmentPlanForm(forms.ModelForm):
"notes",
"installment_start",
"entities",
"add_description_to_transaction",
"add_notes_to_transaction",
]
widgets = {
"account": TomSelect(),
@@ -593,7 +597,9 @@ class InstallmentPlanForm(forms.ModelForm):
css_class="form-row",
),
"description",
Switch("add_description_to_transaction"),
"notes",
Switch("add_notes_to_transaction"),
Row(
Column("number_of_installments", css_class="form-group col-md-6 mb-0"),
Column("installment_start", css_class="form-group col-md-6 mb-0"),
@@ -782,6 +788,7 @@ class RecurringTransactionForm(forms.ModelForm):
"type",
"amount",
"description",
"add_description_to_transaction",
"category",
"tags",
"start_date",
@@ -790,6 +797,7 @@ class RecurringTransactionForm(forms.ModelForm):
"recurrence_type",
"recurrence_interval",
"notes",
"add_notes_to_transaction",
"entities",
]
widgets = {
@@ -850,6 +858,7 @@ class RecurringTransactionForm(forms.ModelForm):
css_class="form-row",
),
"description",
Switch("add_description_to_transaction"),
"amount",
Row(
Column("category", css_class="form-group col-md-6 mb-0"),
@@ -857,6 +866,7 @@ class RecurringTransactionForm(forms.ModelForm):
css_class="form-row",
),
"notes",
Switch("add_notes_to_transaction"),
Row(
Column("start_date", css_class="form-group col-md-6 mb-0"),
Column("reference_date", css_class="form-group col-md-6 mb-0"),

View File

@@ -0,0 +1,33 @@
# Generated by Django 5.1.7 on 2025-03-09 20:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('transactions', '0040_alter_transaction_unique_together_and_more'),
]
operations = [
migrations.AddField(
model_name='installmentplan',
name='add_description_to_transaction',
field=models.BooleanField(default=True, verbose_name='Add description to transactions'),
),
migrations.AddField(
model_name='installmentplan',
name='add_notes_to_transaction',
field=models.BooleanField(default=True, verbose_name='Add notes to transactions'),
),
migrations.AddField(
model_name='recurringtransaction',
name='add_description_to_transaction',
field=models.BooleanField(default=True, verbose_name='Add description to transactions'),
),
migrations.AddField(
model_name='recurringtransaction',
name='add_notes_to_transaction',
field=models.BooleanField(default=True, verbose_name='Add notes to transactions'),
),
]

View File

@@ -0,0 +1,25 @@
# Generated by Django 5.1.7 on 2025-03-09 21:54
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('transactions', '0041_installmentplan_add_description_to_transaction_and_more'),
]
operations = [
migrations.AlterModelOptions(
name='transactioncategory',
options={'ordering': ['name', 'id'], 'verbose_name': 'Transaction Category', 'verbose_name_plural': 'Transaction Categories'},
),
migrations.AlterModelOptions(
name='transactionentity',
options={'ordering': ['name', 'id'], 'verbose_name': 'Entity', 'verbose_name_plural': 'Entities'},
),
migrations.AlterModelOptions(
name='transactiontag',
options={'ordering': ['name', 'id'], 'verbose_name': 'Transaction Tags', 'verbose_name_plural': 'Transaction Tags'},
),
]

View File

@@ -23,6 +23,7 @@ logger = logging.getLogger()
transaction_created = Signal()
transaction_updated = Signal()
transaction_deleted = Signal()
class SoftDeleteQuerySet(models.QuerySet):
@@ -65,8 +66,14 @@ class SoftDeleteQuerySet(models.QuerySet):
def delete(self):
if not settings.ENABLE_SOFT_DELETE:
# If soft deletion is disabled, perform a normal delete
return super().delete()
# Get instances before hard delete
instances = list(self)
# Send signals for each instance before deletion
for instance in instances:
transaction_deleted.send(sender=instance)
# Perform hard delete
result = super().delete()
return result
# Separate the queryset into already deleted and not deleted objects
already_deleted = self.filter(deleted=True)
@@ -74,14 +81,28 @@ class SoftDeleteQuerySet(models.QuerySet):
# Use a transaction to ensure atomicity
with transaction.atomic():
# Get instances for hard delete before they're gone
already_deleted_instances = list(already_deleted)
for instance in already_deleted_instances:
transaction_deleted.send(sender=instance)
# Perform hard delete on already deleted objects
hard_deleted_count = already_deleted._raw_delete(already_deleted.db)
# Get instances for soft delete
instances_to_soft_delete = list(not_deleted)
# Perform soft delete on not deleted objects
soft_deleted_count = not_deleted.update(
deleted=True, deleted_at=timezone.now()
)
# Send signals for soft deleted instances
for instance in instances_to_soft_delete:
instance.deleted = True
instance.deleted_at = timezone.now()
transaction_deleted.send(sender=instance)
# Return a tuple of counts as expected by Django's delete method
return (
hard_deleted_count + soft_deleted_count,
@@ -192,6 +213,7 @@ class TransactionCategory(SharedObject):
verbose_name_plural = _("Transaction Categories")
db_table = "t_categories"
unique_together = (("owner", "name"),)
ordering = ["name", "id"]
def __str__(self):
return self.name
@@ -215,6 +237,7 @@ class TransactionTag(SharedObject):
verbose_name_plural = _("Transaction Tags")
db_table = "tags"
unique_together = (("owner", "name"),)
ordering = ["name", "id"]
def __str__(self):
return self.name
@@ -238,6 +261,7 @@ class TransactionEntity(SharedObject):
verbose_name_plural = _("Entities")
db_table = "entities"
unique_together = (("owner", "name"),)
ordering = ["name", "id"]
def __str__(self):
return self.name
@@ -358,10 +382,14 @@ class Transaction(OwnedObject):
self.deleted = True
self.deleted_at = timezone.now()
self.save()
transaction_deleted.send(sender=self) # Emit signal for soft delete
else:
super().delete(*args, **kwargs)
result = super().delete(*args, **kwargs)
return result
else:
super().delete(*args, **kwargs)
# For hard delete mode
transaction_deleted.send(sender=self) # Emit signal before hard delete
return super().delete(*args, **kwargs)
def hard_delete(self, *args, **kwargs):
super().delete(*args, **kwargs)
@@ -468,6 +496,13 @@ class InstallmentPlan(models.Model):
notes = models.TextField(blank=True, verbose_name=_("Notes"))
add_description_to_transaction = models.BooleanField(
default=True, verbose_name=_("Add description to transactions")
)
add_notes_to_transaction = models.BooleanField(
default=True, verbose_name=_("Add notes to transactions")
)
all_objects = models.Manager() # Unfiltered manager
objects = GenericAccountOwnerManager() # Default filtered manager
@@ -532,11 +567,13 @@ class InstallmentPlan(models.Model):
is_paid=False,
reference_date=transaction_reference_date,
amount=self.installment_amount,
description=self.description,
description=(
self.description if self.add_description_to_transaction else ""
),
category=self.category,
installment_plan=self,
installment_id=i,
notes=self.notes,
notes=self.notes if self.add_notes_to_transaction else "",
)
new_transaction.tags.set(self.tags.all())
new_transaction.entities.set(self.entities.all())
@@ -569,9 +606,13 @@ class InstallmentPlan(models.Model):
existing_transaction.type = self.type
existing_transaction.date = transaction_date
existing_transaction.reference_date = transaction_reference_date
existing_transaction.description = self.description
existing_transaction.description = (
self.description if self.add_description_to_transaction else ""
)
existing_transaction.category = self.category
existing_transaction.notes = self.notes
existing_transaction.notes = (
self.notes if self.add_notes_to_transaction else ""
)
if (
not existing_transaction.is_paid
@@ -592,11 +633,13 @@ class InstallmentPlan(models.Model):
is_paid=False,
reference_date=transaction_reference_date,
amount=self.installment_amount,
description=self.description,
description=(
self.description if self.add_description_to_transaction else ""
),
category=self.category,
installment_plan=self,
installment_id=i,
notes=self.notes,
notes=self.notes if self.add_notes_to_transaction else "",
)
new_transaction.tags.set(self.tags.all())
new_transaction.entities.set(self.entities.all())
@@ -672,6 +715,13 @@ class RecurringTransaction(models.Model):
verbose_name=_("Last Generated Reference Date"), null=True, blank=True
)
add_description_to_transaction = models.BooleanField(
default=True, verbose_name=_("Add description to transactions")
)
add_notes_to_transaction = models.BooleanField(
default=True, verbose_name=_("Add notes to transactions")
)
all_objects = models.Manager() # Unfiltered manager
objects = GenericAccountOwnerManager() # Default filtered manager
@@ -718,11 +768,13 @@ class RecurringTransaction(models.Model):
date=date,
reference_date=reference_date.replace(day=1),
amount=self.amount,
description=self.description,
description=(
self.description if self.add_description_to_transaction else ""
),
category=self.category,
is_paid=False,
recurring_transaction=self,
notes=self.notes,
notes=self.notes if self.add_notes_to_transaction else "",
)
if self.tags.exists():
created_transaction.tags.set(self.tags.all())
@@ -796,9 +848,13 @@ class RecurringTransaction(models.Model):
for existing_transaction in unpaid_transactions:
# Update fields based on RecurringTransaction
existing_transaction.amount = self.amount
existing_transaction.description = self.description
existing_transaction.description = (
self.description if self.add_description_to_transaction else ""
)
existing_transaction.category = self.category
existing_transaction.notes = self.notes
existing_transaction.notes = (
self.notes if self.add_notes_to_transaction else ""
)
# Update many-to-many relationships
existing_transaction.tags.set(self.tags.all())

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-08 15:04+0000\n"
"POT-Creation-Date: 2025-03-09 21:56+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -25,11 +25,11 @@ msgstr ""
#: apps/accounts/forms.py:40 apps/accounts/forms.py:98
#: apps/currencies/forms.py:53 apps/currencies/forms.py:91
#: apps/currencies/forms.py:142 apps/dca/forms.py:49 apps/dca/forms.py:224
#: apps/import_app/forms.py:34 apps/rules/forms.py:45 apps/rules/forms.py:87
#: apps/rules/forms.py:359 apps/transactions/forms.py:202
#: apps/transactions/forms.py:269 apps/transactions/forms.py:623
#: apps/transactions/forms.py:666 apps/transactions/forms.py:698
#: apps/transactions/forms.py:733 apps/transactions/forms.py:881
#: apps/import_app/forms.py:34 apps/rules/forms.py:51 apps/rules/forms.py:93
#: apps/rules/forms.py:365 apps/transactions/forms.py:202
#: apps/transactions/forms.py:269 apps/transactions/forms.py:629
#: apps/transactions/forms.py:672 apps/transactions/forms.py:704
#: apps/transactions/forms.py:739 apps/transactions/forms.py:891
msgid "Update"
msgstr ""
@@ -37,11 +37,11 @@ msgstr ""
#: apps/common/widgets/tom_select.py:13 apps/currencies/forms.py:61
#: apps/currencies/forms.py:99 apps/currencies/forms.py:150
#: apps/dca/forms.py:57 apps/dca/forms.py:232 apps/import_app/forms.py:42
#: apps/rules/forms.py:53 apps/rules/forms.py:95 apps/rules/forms.py:367
#: apps/rules/forms.py:59 apps/rules/forms.py:101 apps/rules/forms.py:373
#: apps/transactions/forms.py:187 apps/transactions/forms.py:211
#: apps/transactions/forms.py:631 apps/transactions/forms.py:674
#: apps/transactions/forms.py:706 apps/transactions/forms.py:741
#: apps/transactions/forms.py:889
#: apps/transactions/forms.py:637 apps/transactions/forms.py:680
#: apps/transactions/forms.py:712 apps/transactions/forms.py:747
#: apps/transactions/forms.py:899
#: templates/account_groups/fragments/list.html:9
#: templates/accounts/fragments/list.html:9
#: templates/categories/fragments/list.html:9
@@ -69,33 +69,33 @@ msgid "New balance"
msgstr ""
#: apps/accounts/forms.py:121 apps/dca/forms.py:85 apps/dca/forms.py:92
#: apps/insights/forms.py:118 apps/rules/forms.py:168 apps/rules/forms.py:183
#: apps/rules/models.py:37 apps/rules/models.py:285
#: apps/insights/forms.py:118 apps/rules/forms.py:174 apps/rules/forms.py:189
#: apps/rules/models.py:38 apps/rules/models.py:286
#: apps/transactions/forms.py:40 apps/transactions/forms.py:303
#: apps/transactions/forms.py:310 apps/transactions/forms.py:508
#: apps/transactions/forms.py:765 apps/transactions/models.py:281
#: apps/transactions/models.py:460 apps/transactions/models.py:643
#: apps/transactions/forms.py:310 apps/transactions/forms.py:510
#: apps/transactions/forms.py:771 apps/transactions/models.py:305
#: apps/transactions/models.py:488 apps/transactions/models.py:686
#: templates/insights/fragments/category_overview/index.html:9
msgid "Category"
msgstr ""
#: apps/accounts/forms.py:128 apps/dca/forms.py:101 apps/dca/forms.py:109
#: apps/export_app/forms.py:44 apps/export_app/forms.py:135
#: apps/rules/forms.py:171 apps/rules/forms.py:180 apps/rules/models.py:38
#: apps/rules/models.py:289 apps/transactions/filters.py:74
#: apps/rules/forms.py:177 apps/rules/forms.py:186 apps/rules/models.py:39
#: apps/rules/models.py:290 apps/transactions/filters.py:74
#: apps/transactions/forms.py:48 apps/transactions/forms.py:319
#: apps/transactions/forms.py:327 apps/transactions/forms.py:501
#: apps/transactions/forms.py:758 apps/transactions/models.py:287
#: apps/transactions/models.py:462 apps/transactions/models.py:647
#: apps/transactions/forms.py:327 apps/transactions/forms.py:503
#: apps/transactions/forms.py:764 apps/transactions/models.py:311
#: apps/transactions/models.py:490 apps/transactions/models.py:690
#: templates/includes/navbar.html:108 templates/tags/fragments/list.html:5
#: templates/tags/pages/index.html:4
msgid "Tags"
msgstr ""
#: apps/accounts/models.py:12 apps/accounts/models.py:28 apps/dca/models.py:13
#: apps/import_app/models.py:14 apps/rules/models.py:12
#: apps/transactions/models.py:177 apps/transactions/models.py:201
#: apps/transactions/models.py:224
#: apps/accounts/models.py:12 apps/accounts/models.py:29 apps/dca/models.py:13
#: apps/import_app/models.py:14 apps/rules/models.py:13
#: apps/transactions/models.py:198 apps/transactions/models.py:223
#: apps/transactions/models.py:247
#: templates/account_groups/fragments/list.html:25
#: templates/accounts/fragments/list.html:25
#: templates/categories/fragments/table.html:16
@@ -110,7 +110,7 @@ msgstr ""
msgid "Name"
msgstr ""
#: apps/accounts/models.py:18 apps/accounts/models.py:32
#: apps/accounts/models.py:18 apps/accounts/models.py:33
msgid "Account Group"
msgstr ""
@@ -120,49 +120,49 @@ msgstr ""
msgid "Account Groups"
msgstr ""
#: apps/accounts/models.py:38 apps/currencies/models.py:39
#: apps/accounts/models.py:39 apps/currencies/models.py:39
#: templates/accounts/fragments/list.html:27
msgid "Currency"
msgstr ""
#: apps/accounts/models.py:44 apps/currencies/models.py:27
#: apps/accounts/models.py:45 apps/currencies/models.py:27
#: templates/accounts/fragments/list.html:28
msgid "Exchange Currency"
msgstr ""
#: apps/accounts/models.py:49 apps/currencies/models.py:32
#: apps/accounts/models.py:50 apps/currencies/models.py:32
msgid "Default currency for exchange calculations"
msgstr ""
#: apps/accounts/models.py:54
#: apps/accounts/models.py:55
msgid "Asset account"
msgstr ""
#: apps/accounts/models.py:56
#: apps/accounts/models.py:57
msgid ""
"Asset accounts count towards your Net Worth, but not towards your month."
msgstr ""
#: apps/accounts/models.py:61 templates/accounts/fragments/list.html:30
#: apps/accounts/models.py:62 templates/accounts/fragments/list.html:30
#: templates/categories/fragments/list.html:24
#: templates/entities/fragments/list.html:24
#: templates/tags/fragments/list.html:24
msgid "Archived"
msgstr ""
#: apps/accounts/models.py:62
#: apps/accounts/models.py:63
msgid "Archived accounts don't show up nor count towards your net worth"
msgstr ""
#: apps/accounts/models.py:69 apps/rules/forms.py:160 apps/rules/forms.py:173
#: apps/rules/models.py:29 apps/rules/models.py:241
#: apps/transactions/forms.py:60 apps/transactions/forms.py:493
#: apps/transactions/forms.py:750 apps/transactions/models.py:254
#: apps/transactions/models.py:420 apps/transactions/models.py:625
#: apps/accounts/models.py:70 apps/rules/forms.py:166 apps/rules/forms.py:179
#: apps/rules/models.py:30 apps/rules/models.py:242
#: apps/transactions/forms.py:60 apps/transactions/forms.py:495
#: apps/transactions/forms.py:756 apps/transactions/models.py:278
#: apps/transactions/models.py:448 apps/transactions/models.py:668
msgid "Account"
msgstr ""
#: apps/accounts/models.py:70 apps/export_app/forms.py:20
#: apps/accounts/models.py:71 apps/export_app/forms.py:20
#: apps/export_app/forms.py:132 apps/transactions/filters.py:53
#: templates/accounts/fragments/list.html:5
#: templates/accounts/pages/index.html:4 templates/includes/navbar.html:114
@@ -173,7 +173,7 @@ msgstr ""
msgid "Accounts"
msgstr ""
#: apps/accounts/models.py:82
#: apps/accounts/models.py:84
msgid "Exchange currency cannot be the same as the account's main currency."
msgstr ""
@@ -266,7 +266,7 @@ msgstr ""
msgid "Invalid entity data. Provide an ID or name."
msgstr ""
#: apps/api/serializers/transactions.py:170
#: apps/api/serializers/transactions.py:191
msgid "Either 'date' or 'reference_date' must be provided."
msgstr ""
@@ -439,10 +439,10 @@ msgstr ""
msgid "Suffix"
msgstr ""
#: apps/currencies/forms.py:69 apps/dca/models.py:158 apps/rules/forms.py:163
#: apps/rules/forms.py:176 apps/rules/models.py:32 apps/rules/models.py:253
#: apps/currencies/forms.py:69 apps/dca/models.py:158 apps/rules/forms.py:169
#: apps/rules/forms.py:182 apps/rules/models.py:33 apps/rules/models.py:254
#: apps/transactions/forms.py:64 apps/transactions/forms.py:331
#: apps/transactions/models.py:264
#: apps/transactions/models.py:288
#: templates/dca/fragments/strategy/details.html:52
#: templates/exchange_rates/fragments/table.html:10
#: templates/exchange_rates_services/fragments/table.html:10
@@ -472,59 +472,59 @@ msgstr ""
msgid "Currencies"
msgstr ""
#: apps/currencies/models.py:48
#: apps/currencies/models.py:49
msgid "Currency cannot have itself as exchange currency."
msgstr ""
#: apps/currencies/models.py:59
#: apps/currencies/models.py:60
msgid "From Currency"
msgstr ""
#: apps/currencies/models.py:65
#: apps/currencies/models.py:66
msgid "To Currency"
msgstr ""
#: apps/currencies/models.py:68 apps/currencies/models.py:73
#: apps/currencies/models.py:69 apps/currencies/models.py:74
msgid "Exchange Rate"
msgstr ""
#: apps/currencies/models.py:70
#: apps/currencies/models.py:71
msgid "Date and Time"
msgstr ""
#: apps/currencies/models.py:74 apps/export_app/forms.py:68
#: apps/currencies/models.py:75 apps/export_app/forms.py:68
#: apps/export_app/forms.py:145 templates/exchange_rates/fragments/list.html:6
#: templates/exchange_rates/pages/index.html:4
#: templates/includes/navbar.html:126
msgid "Exchange Rates"
msgstr ""
#: apps/currencies/models.py:86
#: apps/currencies/models.py:87
msgid "From and To currencies cannot be the same."
msgstr ""
#: apps/currencies/models.py:101
#: apps/currencies/models.py:102
msgid "On"
msgstr ""
#: apps/currencies/models.py:102
#: apps/currencies/models.py:103
msgid "Every X hours"
msgstr ""
#: apps/currencies/models.py:103
#: apps/currencies/models.py:104
msgid "Not on"
msgstr ""
#: apps/currencies/models.py:105
#: apps/currencies/models.py:106
msgid "Service Name"
msgstr ""
#: apps/currencies/models.py:107
#: apps/currencies/models.py:108
msgid "Service Type"
msgstr ""
#: apps/currencies/models.py:109 apps/transactions/models.py:181
#: apps/transactions/models.py:204 apps/transactions/models.py:227
#: apps/currencies/models.py:110 apps/transactions/models.py:202
#: apps/transactions/models.py:226 apps/transactions/models.py:250
#: templates/categories/fragments/list.html:21
#: templates/entities/fragments/list.html:21
#: templates/recurring_transactions/fragments/list.html:21
@@ -532,69 +532,69 @@ msgstr ""
msgid "Active"
msgstr ""
#: apps/currencies/models.py:114
#: apps/currencies/models.py:115
msgid "API Key"
msgstr ""
#: apps/currencies/models.py:115
#: apps/currencies/models.py:116
msgid "API key for the service (if required)"
msgstr ""
#: apps/currencies/models.py:120
#: apps/currencies/models.py:121
msgid "Interval Type"
msgstr ""
#: apps/currencies/models.py:124
#: apps/currencies/models.py:125
msgid "Interval"
msgstr ""
#: apps/currencies/models.py:127
#: apps/currencies/models.py:128
msgid "Last Successful Fetch"
msgstr ""
#: apps/currencies/models.py:132
#: apps/currencies/models.py:133
msgid "Target Currencies"
msgstr ""
#: apps/currencies/models.py:134
#: apps/currencies/models.py:135
msgid ""
"Select currencies to fetch exchange rates for. Rates will be fetched for "
"each currency against their set exchange currency."
msgstr ""
#: apps/currencies/models.py:142
#: apps/currencies/models.py:143
msgid "Target Accounts"
msgstr ""
#: apps/currencies/models.py:144
#: apps/currencies/models.py:145
msgid ""
"Select accounts to fetch exchange rates for. Rates will be fetched for each "
"account's currency against their set exchange currency."
msgstr ""
#: apps/currencies/models.py:151
#: apps/currencies/models.py:152
msgid "Exchange Rate Service"
msgstr ""
#: apps/currencies/models.py:152
#: apps/currencies/models.py:153
msgid "Exchange Rate Services"
msgstr ""
#: apps/currencies/models.py:204
#: apps/currencies/models.py:205
msgid "'Every X hours' interval type requires a positive integer."
msgstr ""
#: apps/currencies/models.py:213
#: apps/currencies/models.py:214
msgid "'Every X hours' interval must be between 1 and 24."
msgstr ""
#: apps/currencies/models.py:227
#: apps/currencies/models.py:228
msgid ""
"Invalid hour format. Use comma-separated hours (0-23) and/or ranges (e.g., "
"'1-5,8,10-12')."
msgstr ""
#: apps/currencies/models.py:238
#: apps/currencies/models.py:239
msgid ""
"Invalid format. Please check the requirements for your selected interval "
"type."
@@ -673,7 +673,7 @@ msgstr ""
msgid "You must provide an account."
msgstr ""
#: apps/dca/forms.py:312 apps/transactions/forms.py:443
#: apps/dca/forms.py:312 apps/transactions/forms.py:445
msgid "From and To accounts must be different."
msgstr ""
@@ -690,10 +690,10 @@ msgstr ""
msgid "Payment Currency"
msgstr ""
#: apps/dca/models.py:26 apps/dca/models.py:181 apps/rules/forms.py:167
#: apps/rules/forms.py:182 apps/rules/models.py:36 apps/rules/models.py:269
#: apps/transactions/forms.py:345 apps/transactions/models.py:277
#: apps/transactions/models.py:469 apps/transactions/models.py:653
#: apps/dca/models.py:26 apps/dca/models.py:181 apps/rules/forms.py:173
#: apps/rules/forms.py:188 apps/rules/models.py:37 apps/rules/models.py:270
#: apps/transactions/forms.py:347 apps/transactions/models.py:301
#: apps/transactions/models.py:497 apps/transactions/models.py:696
msgid "Notes"
msgstr ""
@@ -754,7 +754,7 @@ msgid "Users"
msgstr ""
#: apps/export_app/forms.py:32 apps/export_app/forms.py:137
#: apps/transactions/models.py:338 templates/includes/navbar.html:57
#: apps/transactions/models.py:362 templates/includes/navbar.html:57
#: templates/includes/navbar.html:104
#: templates/recurring_transactions/fragments/list_transactions.html:5
#: templates/recurring_transactions/fragments/table.html:37
@@ -769,25 +769,25 @@ msgid "Categories"
msgstr ""
#: apps/export_app/forms.py:50 apps/export_app/forms.py:136
#: apps/rules/forms.py:172 apps/rules/forms.py:181 apps/rules/models.py:39
#: apps/rules/models.py:281 apps/transactions/filters.py:81
#: apps/transactions/forms.py:56 apps/transactions/forms.py:516
#: apps/transactions/forms.py:773 apps/transactions/models.py:238
#: apps/transactions/models.py:292 apps/transactions/models.py:465
#: apps/transactions/models.py:650 templates/entities/fragments/list.html:5
#: apps/rules/forms.py:178 apps/rules/forms.py:187 apps/rules/models.py:40
#: apps/rules/models.py:282 apps/transactions/filters.py:81
#: apps/transactions/forms.py:56 apps/transactions/forms.py:518
#: apps/transactions/forms.py:779 apps/transactions/models.py:261
#: apps/transactions/models.py:316 apps/transactions/models.py:493
#: apps/transactions/models.py:693 templates/entities/fragments/list.html:5
#: templates/entities/pages/index.html:4 templates/includes/navbar.html:110
msgid "Entities"
msgstr ""
#: apps/export_app/forms.py:56 apps/export_app/forms.py:140
#: apps/transactions/models.py:680 templates/includes/navbar.html:74
#: apps/transactions/models.py:730 templates/includes/navbar.html:74
#: templates/recurring_transactions/fragments/list.html:5
#: templates/recurring_transactions/pages/index.html:4
msgid "Recurring Transactions"
msgstr ""
#: apps/export_app/forms.py:62 apps/export_app/forms.py:138
#: apps/transactions/models.py:476 templates/includes/navbar.html:72
#: apps/transactions/models.py:511 templates/includes/navbar.html:72
#: templates/installment_plans/fragments/list.html:5
#: templates/installment_plans/pages/index.html:4
msgid "Installment Plans"
@@ -828,15 +828,15 @@ msgstr ""
msgid "ZIP File"
msgstr ""
#: apps/export_app/forms.py:146 apps/rules/models.py:21
#: apps/export_app/forms.py:146 apps/rules/models.py:22
msgid "Transaction rules"
msgstr ""
#: apps/export_app/forms.py:148 apps/rules/models.py:58
#: apps/export_app/forms.py:148 apps/rules/models.py:59
msgid "Edit transaction action"
msgstr ""
#: apps/export_app/forms.py:151 apps/rules/models.py:295
#: apps/export_app/forms.py:151 apps/rules/models.py:296
msgid "Update or create transaction actions"
msgstr ""
@@ -985,163 +985,167 @@ msgstr ""
msgid "Saved"
msgstr ""
#: apps/rules/forms.py:20
#: apps/rules/forms.py:21
msgid "Run on creation"
msgstr ""
#: apps/rules/forms.py:21
#: apps/rules/forms.py:22
msgid "Run on update"
msgstr ""
#: apps/rules/forms.py:22
#: apps/rules/forms.py:23
msgid "Run on delete"
msgstr ""
#: apps/rules/forms.py:24
msgid "If..."
msgstr ""
#: apps/rules/forms.py:64
#: apps/rules/forms.py:70
msgid "Set field"
msgstr ""
#: apps/rules/forms.py:65 templates/insights/fragments/sankey.html:94
#: apps/rules/forms.py:71 templates/insights/fragments/sankey.html:94
msgid "To"
msgstr ""
#: apps/rules/forms.py:115
#: apps/rules/forms.py:121
msgid "A value for this field already exists in the rule."
msgstr ""
#: apps/rules/forms.py:147 apps/rules/forms.py:148 apps/rules/forms.py:149
#: apps/rules/forms.py:150 apps/rules/forms.py:151 apps/rules/forms.py:152
#: apps/rules/forms.py:153 apps/rules/forms.py:154 apps/rules/forms.py:155
#: apps/rules/forms.py:156 apps/rules/forms.py:157 apps/rules/forms.py:158
#: apps/rules/forms.py:159
#: apps/rules/forms.py:159 apps/rules/forms.py:160 apps/rules/forms.py:161
#: apps/rules/forms.py:162 apps/rules/forms.py:163 apps/rules/forms.py:164
#: apps/rules/forms.py:165
msgid "Operator"
msgstr ""
#: apps/rules/forms.py:161 apps/rules/forms.py:174 apps/rules/models.py:30
#: apps/rules/models.py:245 apps/transactions/models.py:261
#: apps/transactions/models.py:425 apps/transactions/models.py:631
#: apps/rules/forms.py:167 apps/rules/forms.py:180 apps/rules/models.py:31
#: apps/rules/models.py:246 apps/transactions/models.py:285
#: apps/transactions/models.py:453 apps/transactions/models.py:674
msgid "Type"
msgstr ""
#: apps/rules/forms.py:162 apps/rules/forms.py:175 apps/rules/models.py:31
#: apps/rules/models.py:249 apps/transactions/filters.py:23
#: apps/transactions/models.py:263 templates/cotton/transaction/item.html:21
#: apps/rules/forms.py:168 apps/rules/forms.py:181 apps/rules/models.py:32
#: apps/rules/models.py:250 apps/transactions/filters.py:23
#: apps/transactions/models.py:287 templates/cotton/transaction/item.html:21
#: templates/cotton/transaction/item.html:31
#: templates/transactions/widgets/paid_toggle_button.html:12
#: templates/transactions/widgets/unselectable_paid_toggle_button.html:16
msgid "Paid"
msgstr ""
#: apps/rules/forms.py:164 apps/rules/forms.py:177 apps/rules/models.py:33
#: apps/rules/models.py:257 apps/transactions/forms.py:68
#: apps/transactions/forms.py:334 apps/transactions/forms.py:522
#: apps/transactions/models.py:265 apps/transactions/models.py:443
#: apps/transactions/models.py:655
#: apps/rules/forms.py:170 apps/rules/forms.py:183 apps/rules/models.py:34
#: apps/rules/models.py:258 apps/transactions/forms.py:68
#: apps/transactions/forms.py:334 apps/transactions/forms.py:524
#: apps/transactions/models.py:289 apps/transactions/models.py:471
#: apps/transactions/models.py:698
msgid "Reference Date"
msgstr ""
#: apps/rules/forms.py:165 apps/rules/forms.py:178 apps/rules/models.py:34
#: apps/rules/models.py:261 apps/transactions/models.py:270
#: apps/transactions/models.py:636 templates/insights/fragments/sankey.html:95
#: apps/rules/forms.py:171 apps/rules/forms.py:184 apps/rules/models.py:35
#: apps/rules/models.py:262 apps/transactions/models.py:294
#: apps/transactions/models.py:679 templates/insights/fragments/sankey.html:95
msgid "Amount"
msgstr ""
#: apps/rules/forms.py:166 apps/rules/forms.py:179 apps/rules/models.py:13
#: apps/rules/models.py:35 apps/rules/models.py:265
#: apps/transactions/forms.py:337 apps/transactions/models.py:275
#: apps/transactions/models.py:427 apps/transactions/models.py:639
#: apps/rules/forms.py:172 apps/rules/forms.py:185 apps/rules/models.py:14
#: apps/rules/models.py:36 apps/rules/models.py:266
#: apps/transactions/forms.py:338 apps/transactions/models.py:299
#: apps/transactions/models.py:455 apps/transactions/models.py:682
msgid "Description"
msgstr ""
#: apps/rules/forms.py:169 apps/rules/forms.py:184 apps/rules/models.py:273
#: apps/transactions/models.py:314
#: apps/rules/forms.py:175 apps/rules/forms.py:190 apps/rules/models.py:274
#: apps/transactions/models.py:338
msgid "Internal Note"
msgstr ""
#: apps/rules/forms.py:170 apps/rules/forms.py:185 apps/rules/models.py:277
#: apps/transactions/models.py:316
#: apps/rules/forms.py:176 apps/rules/forms.py:191 apps/rules/models.py:278
#: apps/transactions/models.py:340
msgid "Internal ID"
msgstr ""
#: apps/rules/forms.py:199
#: apps/rules/forms.py:205
msgid "Search Criteria"
msgstr ""
#: apps/rules/forms.py:334
#: apps/rules/forms.py:340
msgid "Set Values"
msgstr ""
#: apps/rules/models.py:14
#: apps/rules/models.py:15
msgid "Trigger"
msgstr ""
#: apps/rules/models.py:20
#: apps/rules/models.py:21
msgid "Transaction rule"
msgstr ""
#: apps/rules/models.py:45 apps/rules/models.py:83
#: apps/rules/models.py:46 apps/rules/models.py:84
msgid "Rule"
msgstr ""
#: apps/rules/models.py:50
#: apps/rules/models.py:51
msgid "Field"
msgstr ""
#: apps/rules/models.py:52
#: apps/rules/models.py:53
msgid "Value"
msgstr ""
#: apps/rules/models.py:59
#: apps/rules/models.py:60
msgid "Edit transaction actions"
msgstr ""
#: apps/rules/models.py:69
#: apps/rules/models.py:70
msgid "is exactly"
msgstr ""
#: apps/rules/models.py:70
#: apps/rules/models.py:71
msgid "contains"
msgstr ""
#: apps/rules/models.py:71
#: apps/rules/models.py:72
msgid "starts with"
msgstr ""
#: apps/rules/models.py:72
#: apps/rules/models.py:73
msgid "ends with"
msgstr ""
#: apps/rules/models.py:73
#: apps/rules/models.py:74
msgid "equals"
msgstr ""
#: apps/rules/models.py:74
#: apps/rules/models.py:75
msgid "greater than"
msgstr ""
#: apps/rules/models.py:75
#: apps/rules/models.py:76
msgid "less than"
msgstr ""
#: apps/rules/models.py:76
#: apps/rules/models.py:77
msgid "greater than or equal"
msgstr ""
#: apps/rules/models.py:77
#: apps/rules/models.py:78
msgid "less than or equal"
msgstr ""
#: apps/rules/models.py:87 templates/transactions/pages/transactions.html:15
#: apps/rules/models.py:88 templates/transactions/pages/transactions.html:15
msgid "Filter"
msgstr ""
#: apps/rules/models.py:90
#: apps/rules/models.py:91
msgid ""
"Generic expression to enable or disable execution. Should evaluate to True "
"or False"
msgstr ""
#: apps/rules/models.py:294
#: apps/rules/models.py:295
msgid "Update or create transaction action"
msgstr ""
@@ -1232,69 +1236,69 @@ msgstr ""
msgid "To Amount"
msgstr ""
#: apps/transactions/forms.py:410
#: apps/transactions/forms.py:412
#: templates/cotton/ui/quick_transactions_buttons.html:40
msgid "Transfer"
msgstr ""
#: apps/transactions/forms.py:652
#: apps/transactions/forms.py:658
msgid "Tag name"
msgstr ""
#: apps/transactions/forms.py:684
#: apps/transactions/forms.py:690
msgid "Entity name"
msgstr ""
#: apps/transactions/forms.py:716
#: apps/transactions/forms.py:722
msgid "Category name"
msgstr ""
#: apps/transactions/forms.py:718
#: apps/transactions/forms.py:724
msgid "Muted categories won't count towards your monthly total"
msgstr ""
#: apps/transactions/forms.py:900
#: apps/transactions/forms.py:910
msgid "End date should be after the start date"
msgstr ""
#: apps/transactions/models.py:178
#: apps/transactions/models.py:199
msgid "Mute"
msgstr ""
#: apps/transactions/models.py:183
#: apps/transactions/models.py:204
msgid ""
"Deactivated categories won't be able to be selected when creating new "
"transactions"
msgstr ""
#: apps/transactions/models.py:191
#: apps/transactions/models.py:212
msgid "Transaction Category"
msgstr ""
#: apps/transactions/models.py:192
#: apps/transactions/models.py:213
msgid "Transaction Categories"
msgstr ""
#: apps/transactions/models.py:206
#: apps/transactions/models.py:228
msgid ""
"Deactivated tags won't be able to be selected when creating new transactions"
msgstr ""
#: apps/transactions/models.py:214 apps/transactions/models.py:215
#: apps/transactions/models.py:236 apps/transactions/models.py:237
msgid "Transaction Tags"
msgstr ""
#: apps/transactions/models.py:229
#: apps/transactions/models.py:252
msgid ""
"Deactivated entities won't be able to be selected when creating new "
"transactions"
msgstr ""
#: apps/transactions/models.py:237
#: apps/transactions/models.py:260
msgid "Entity"
msgstr ""
#: apps/transactions/models.py:248
#: apps/transactions/models.py:272
#: templates/calendar_view/fragments/list.html:42
#: templates/calendar_view/fragments/list.html:44
#: templates/calendar_view/fragments/list.html:52
@@ -1305,7 +1309,7 @@ msgstr ""
msgid "Income"
msgstr ""
#: apps/transactions/models.py:249
#: apps/transactions/models.py:273
#: templates/calendar_view/fragments/list.html:46
#: templates/calendar_view/fragments/list.html:48
#: templates/calendar_view/fragments/list.html:56
@@ -1315,117 +1319,125 @@ msgstr ""
msgid "Expense"
msgstr ""
#: apps/transactions/models.py:303 apps/transactions/models.py:475
#: apps/transactions/models.py:327 apps/transactions/models.py:510
msgid "Installment Plan"
msgstr ""
#: apps/transactions/models.py:312 apps/transactions/models.py:679
#: apps/transactions/models.py:336 apps/transactions/models.py:729
msgid "Recurring Transaction"
msgstr ""
#: apps/transactions/models.py:320
#: apps/transactions/models.py:344
msgid "Deleted"
msgstr ""
#: apps/transactions/models.py:325
#: apps/transactions/models.py:349
msgid "Deleted At"
msgstr ""
#: apps/transactions/models.py:337
#: apps/transactions/models.py:361
msgid "Transaction"
msgstr ""
#: apps/transactions/models.py:405 templates/tags/fragments/table.html:71
#: apps/transactions/models.py:433 templates/tags/fragments/table.html:71
msgid "No tags"
msgstr ""
#: apps/transactions/models.py:406
#: apps/transactions/models.py:434
msgid "No category"
msgstr ""
#: apps/transactions/models.py:408
#: apps/transactions/models.py:436
msgid "No description"
msgstr ""
#: apps/transactions/models.py:414
#: apps/transactions/models.py:442
msgid "Yearly"
msgstr ""
#: apps/transactions/models.py:415 apps/users/models.py:26
#: apps/transactions/models.py:443 apps/users/models.py:26
#: templates/includes/navbar.html:26
msgid "Monthly"
msgstr ""
#: apps/transactions/models.py:416
#: apps/transactions/models.py:444
msgid "Weekly"
msgstr ""
#: apps/transactions/models.py:417
#: apps/transactions/models.py:445
msgid "Daily"
msgstr ""
#: apps/transactions/models.py:430
#: apps/transactions/models.py:458
msgid "Number of Installments"
msgstr ""
#: apps/transactions/models.py:435
#: apps/transactions/models.py:463
msgid "Installment Start"
msgstr ""
#: apps/transactions/models.py:436
#: apps/transactions/models.py:464
msgid "The installment number to start counting from"
msgstr ""
#: apps/transactions/models.py:441 apps/transactions/models.py:659
#: apps/transactions/models.py:469 apps/transactions/models.py:702
msgid "Start Date"
msgstr ""
#: apps/transactions/models.py:445 apps/transactions/models.py:660
#: apps/transactions/models.py:473 apps/transactions/models.py:703
msgid "End Date"
msgstr ""
#: apps/transactions/models.py:450
#: apps/transactions/models.py:478
msgid "Recurrence"
msgstr ""
#: apps/transactions/models.py:453
#: apps/transactions/models.py:481
msgid "Installment Amount"
msgstr ""
#: apps/transactions/models.py:618
#: apps/transactions/models.py:500 apps/transactions/models.py:719
msgid "Add description to transactions"
msgstr ""
#: apps/transactions/models.py:503 apps/transactions/models.py:722
msgid "Add notes to transactions"
msgstr ""
#: apps/transactions/models.py:661
msgid "day(s)"
msgstr ""
#: apps/transactions/models.py:619
#: apps/transactions/models.py:662
msgid "week(s)"
msgstr ""
#: apps/transactions/models.py:620
#: apps/transactions/models.py:663
msgid "month(s)"
msgstr ""
#: apps/transactions/models.py:621
#: apps/transactions/models.py:664
msgid "year(s)"
msgstr ""
#: apps/transactions/models.py:623
#: apps/transactions/models.py:666
#: templates/recurring_transactions/fragments/list.html:24
msgid "Paused"
msgstr ""
#: apps/transactions/models.py:662
#: apps/transactions/models.py:705
msgid "Recurrence Type"
msgstr ""
#: apps/transactions/models.py:665
#: apps/transactions/models.py:708
msgid "Recurrence Interval"
msgstr ""
#: apps/transactions/models.py:669
#: apps/transactions/models.py:712
msgid "Last Generated Date"
msgstr ""
#: apps/transactions/models.py:672
#: apps/transactions/models.py:715
msgid "Last Generated Reference Date"
msgstr ""

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,8 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-03-08 15:04+0000\n"
"PO-Revision-Date: 2025-03-08 16:05+0000\n"
"POT-Creation-Date: 2025-03-09 21:56+0000\n"
"PO-Revision-Date: 2025-03-09 23:10+0000\n"
"Last-Translator: Herculino Trotta <netotrotta@gmail.com>\n"
"Language-Team: Portuguese (Brazil) <https://translations.herculino.com/"
"projects/wygiwyh/app/pt_BR/>\n"
@@ -26,11 +26,11 @@ msgstr "Nome do grupo"
#: apps/accounts/forms.py:40 apps/accounts/forms.py:98
#: apps/currencies/forms.py:53 apps/currencies/forms.py:91
#: apps/currencies/forms.py:142 apps/dca/forms.py:49 apps/dca/forms.py:224
#: apps/import_app/forms.py:34 apps/rules/forms.py:45 apps/rules/forms.py:87
#: apps/rules/forms.py:359 apps/transactions/forms.py:202
#: apps/transactions/forms.py:269 apps/transactions/forms.py:623
#: apps/transactions/forms.py:666 apps/transactions/forms.py:698
#: apps/transactions/forms.py:733 apps/transactions/forms.py:881
#: apps/import_app/forms.py:34 apps/rules/forms.py:51 apps/rules/forms.py:93
#: apps/rules/forms.py:365 apps/transactions/forms.py:202
#: apps/transactions/forms.py:269 apps/transactions/forms.py:629
#: apps/transactions/forms.py:672 apps/transactions/forms.py:704
#: apps/transactions/forms.py:739 apps/transactions/forms.py:891
msgid "Update"
msgstr "Atualizar"
@@ -38,11 +38,11 @@ msgstr "Atualizar"
#: apps/common/widgets/tom_select.py:13 apps/currencies/forms.py:61
#: apps/currencies/forms.py:99 apps/currencies/forms.py:150
#: apps/dca/forms.py:57 apps/dca/forms.py:232 apps/import_app/forms.py:42
#: apps/rules/forms.py:53 apps/rules/forms.py:95 apps/rules/forms.py:367
#: apps/rules/forms.py:59 apps/rules/forms.py:101 apps/rules/forms.py:373
#: apps/transactions/forms.py:187 apps/transactions/forms.py:211
#: apps/transactions/forms.py:631 apps/transactions/forms.py:674
#: apps/transactions/forms.py:706 apps/transactions/forms.py:741
#: apps/transactions/forms.py:889
#: apps/transactions/forms.py:637 apps/transactions/forms.py:680
#: apps/transactions/forms.py:712 apps/transactions/forms.py:747
#: apps/transactions/forms.py:899
#: templates/account_groups/fragments/list.html:9
#: templates/accounts/fragments/list.html:9
#: templates/categories/fragments/list.html:9
@@ -70,33 +70,33 @@ msgid "New balance"
msgstr "Novo saldo"
#: apps/accounts/forms.py:121 apps/dca/forms.py:85 apps/dca/forms.py:92
#: apps/insights/forms.py:118 apps/rules/forms.py:168 apps/rules/forms.py:183
#: apps/rules/models.py:37 apps/rules/models.py:285
#: apps/insights/forms.py:118 apps/rules/forms.py:174 apps/rules/forms.py:189
#: apps/rules/models.py:38 apps/rules/models.py:286
#: apps/transactions/forms.py:40 apps/transactions/forms.py:303
#: apps/transactions/forms.py:310 apps/transactions/forms.py:508
#: apps/transactions/forms.py:765 apps/transactions/models.py:281
#: apps/transactions/models.py:460 apps/transactions/models.py:643
#: apps/transactions/forms.py:310 apps/transactions/forms.py:510
#: apps/transactions/forms.py:771 apps/transactions/models.py:305
#: apps/transactions/models.py:488 apps/transactions/models.py:686
#: templates/insights/fragments/category_overview/index.html:9
msgid "Category"
msgstr "Categoria"
#: apps/accounts/forms.py:128 apps/dca/forms.py:101 apps/dca/forms.py:109
#: apps/export_app/forms.py:44 apps/export_app/forms.py:135
#: apps/rules/forms.py:171 apps/rules/forms.py:180 apps/rules/models.py:38
#: apps/rules/models.py:289 apps/transactions/filters.py:74
#: apps/rules/forms.py:177 apps/rules/forms.py:186 apps/rules/models.py:39
#: apps/rules/models.py:290 apps/transactions/filters.py:74
#: apps/transactions/forms.py:48 apps/transactions/forms.py:319
#: apps/transactions/forms.py:327 apps/transactions/forms.py:501
#: apps/transactions/forms.py:758 apps/transactions/models.py:287
#: apps/transactions/models.py:462 apps/transactions/models.py:647
#: apps/transactions/forms.py:327 apps/transactions/forms.py:503
#: apps/transactions/forms.py:764 apps/transactions/models.py:311
#: apps/transactions/models.py:490 apps/transactions/models.py:690
#: templates/includes/navbar.html:108 templates/tags/fragments/list.html:5
#: templates/tags/pages/index.html:4
msgid "Tags"
msgstr "Tags"
#: apps/accounts/models.py:12 apps/accounts/models.py:28 apps/dca/models.py:13
#: apps/import_app/models.py:14 apps/rules/models.py:12
#: apps/transactions/models.py:177 apps/transactions/models.py:201
#: apps/transactions/models.py:224
#: apps/accounts/models.py:12 apps/accounts/models.py:29 apps/dca/models.py:13
#: apps/import_app/models.py:14 apps/rules/models.py:13
#: apps/transactions/models.py:198 apps/transactions/models.py:223
#: apps/transactions/models.py:247
#: templates/account_groups/fragments/list.html:25
#: templates/accounts/fragments/list.html:25
#: templates/categories/fragments/table.html:16
@@ -111,7 +111,7 @@ msgstr "Tags"
msgid "Name"
msgstr "Nome"
#: apps/accounts/models.py:18 apps/accounts/models.py:32
#: apps/accounts/models.py:18 apps/accounts/models.py:33
msgid "Account Group"
msgstr "Grupo da Conta"
@@ -121,52 +121,52 @@ msgstr "Grupo da Conta"
msgid "Account Groups"
msgstr "Grupos da Conta"
#: apps/accounts/models.py:38 apps/currencies/models.py:39
#: apps/accounts/models.py:39 apps/currencies/models.py:39
#: templates/accounts/fragments/list.html:27
msgid "Currency"
msgstr "Moeda"
#: apps/accounts/models.py:44 apps/currencies/models.py:27
#: apps/accounts/models.py:45 apps/currencies/models.py:27
#: templates/accounts/fragments/list.html:28
msgid "Exchange Currency"
msgstr "Moeda de Câmbio"
#: apps/accounts/models.py:49 apps/currencies/models.py:32
#: apps/accounts/models.py:50 apps/currencies/models.py:32
msgid "Default currency for exchange calculations"
msgstr "Moeda padrão para os cálculos de câmbio"
#: apps/accounts/models.py:54
#: apps/accounts/models.py:55
msgid "Asset account"
msgstr "Conta de ativos"
#: apps/accounts/models.py:56
#: apps/accounts/models.py:57
msgid ""
"Asset accounts count towards your Net Worth, but not towards your month."
msgstr ""
"As contas de ativos contam para o seu patrimônio líquido, mas não para o seu "
"mês."
#: apps/accounts/models.py:61 templates/accounts/fragments/list.html:30
#: apps/accounts/models.py:62 templates/accounts/fragments/list.html:30
#: templates/categories/fragments/list.html:24
#: templates/entities/fragments/list.html:24
#: templates/tags/fragments/list.html:24
msgid "Archived"
msgstr "Arquivada"
#: apps/accounts/models.py:62
#: apps/accounts/models.py:63
msgid "Archived accounts don't show up nor count towards your net worth"
msgstr ""
"Contas arquivadas não aparecem nem contam para o seu patrimônio líquido"
#: apps/accounts/models.py:69 apps/rules/forms.py:160 apps/rules/forms.py:173
#: apps/rules/models.py:29 apps/rules/models.py:241
#: apps/transactions/forms.py:60 apps/transactions/forms.py:493
#: apps/transactions/forms.py:750 apps/transactions/models.py:254
#: apps/transactions/models.py:420 apps/transactions/models.py:625
#: apps/accounts/models.py:70 apps/rules/forms.py:166 apps/rules/forms.py:179
#: apps/rules/models.py:30 apps/rules/models.py:242
#: apps/transactions/forms.py:60 apps/transactions/forms.py:495
#: apps/transactions/forms.py:756 apps/transactions/models.py:278
#: apps/transactions/models.py:448 apps/transactions/models.py:668
msgid "Account"
msgstr "Conta"
#: apps/accounts/models.py:70 apps/export_app/forms.py:20
#: apps/accounts/models.py:71 apps/export_app/forms.py:20
#: apps/export_app/forms.py:132 apps/transactions/filters.py:53
#: templates/accounts/fragments/list.html:5
#: templates/accounts/pages/index.html:4 templates/includes/navbar.html:114
@@ -177,7 +177,7 @@ msgstr "Conta"
msgid "Accounts"
msgstr "Contas"
#: apps/accounts/models.py:82
#: apps/accounts/models.py:84
msgid "Exchange currency cannot be the same as the account's main currency."
msgstr "A moeda de câmbio não pode ser a mesma que a moeda principal da conta."
@@ -270,7 +270,7 @@ msgstr "Entidade com esse ID não existe."
msgid "Invalid entity data. Provide an ID or name."
msgstr "Dados da entidade inválidos. Forneça um ID ou nome."
#: apps/api/serializers/transactions.py:170
#: apps/api/serializers/transactions.py:191
msgid "Either 'date' or 'reference_date' must be provided."
msgstr "É necessário fornecer “date” ou “reference_date”."
@@ -448,10 +448,10 @@ msgstr "Prefixo"
msgid "Suffix"
msgstr "Sufixo"
#: apps/currencies/forms.py:69 apps/dca/models.py:158 apps/rules/forms.py:163
#: apps/rules/forms.py:176 apps/rules/models.py:32 apps/rules/models.py:253
#: apps/currencies/forms.py:69 apps/dca/models.py:158 apps/rules/forms.py:169
#: apps/rules/forms.py:182 apps/rules/models.py:33 apps/rules/models.py:254
#: apps/transactions/forms.py:64 apps/transactions/forms.py:331
#: apps/transactions/models.py:264
#: apps/transactions/models.py:288
#: templates/dca/fragments/strategy/details.html:52
#: templates/exchange_rates/fragments/table.html:10
#: templates/exchange_rates_services/fragments/table.html:10
@@ -481,59 +481,59 @@ msgstr "Casas Decimais"
msgid "Currencies"
msgstr "Moedas"
#: apps/currencies/models.py:48
#: apps/currencies/models.py:49
msgid "Currency cannot have itself as exchange currency."
msgstr "A moeda não pode ter a si mesma como moeda de câmbio."
#: apps/currencies/models.py:59
#: apps/currencies/models.py:60
msgid "From Currency"
msgstr "Moeda de origem"
#: apps/currencies/models.py:65
#: apps/currencies/models.py:66
msgid "To Currency"
msgstr "Moeda de destino"
#: apps/currencies/models.py:68 apps/currencies/models.py:73
#: apps/currencies/models.py:69 apps/currencies/models.py:74
msgid "Exchange Rate"
msgstr "Taxa de Câmbio"
#: apps/currencies/models.py:70
#: apps/currencies/models.py:71
msgid "Date and Time"
msgstr "Data e Tempo"
#: apps/currencies/models.py:74 apps/export_app/forms.py:68
#: apps/currencies/models.py:75 apps/export_app/forms.py:68
#: apps/export_app/forms.py:145 templates/exchange_rates/fragments/list.html:6
#: templates/exchange_rates/pages/index.html:4
#: templates/includes/navbar.html:126
msgid "Exchange Rates"
msgstr "Taxas de Câmbio"
#: apps/currencies/models.py:86
#: apps/currencies/models.py:87
msgid "From and To currencies cannot be the same."
msgstr "As moedas De e Para não podem ser as mesmas."
#: apps/currencies/models.py:101
#: apps/currencies/models.py:102
msgid "On"
msgstr "Em"
#: apps/currencies/models.py:102
#: apps/currencies/models.py:103
msgid "Every X hours"
msgstr "A cada X horas"
#: apps/currencies/models.py:103
#: apps/currencies/models.py:104
msgid "Not on"
msgstr "Não em"
#: apps/currencies/models.py:105
#: apps/currencies/models.py:106
msgid "Service Name"
msgstr "Nome do Serviço"
#: apps/currencies/models.py:107
#: apps/currencies/models.py:108
msgid "Service Type"
msgstr "Tipo de Serviço"
#: apps/currencies/models.py:109 apps/transactions/models.py:181
#: apps/transactions/models.py:204 apps/transactions/models.py:227
#: apps/currencies/models.py:110 apps/transactions/models.py:202
#: apps/transactions/models.py:226 apps/transactions/models.py:250
#: templates/categories/fragments/list.html:21
#: templates/entities/fragments/list.html:21
#: templates/recurring_transactions/fragments/list.html:21
@@ -541,31 +541,31 @@ msgstr "Tipo de Serviço"
msgid "Active"
msgstr "Ativo"
#: apps/currencies/models.py:114
#: apps/currencies/models.py:115
msgid "API Key"
msgstr "Chave de API"
#: apps/currencies/models.py:115
#: apps/currencies/models.py:116
msgid "API key for the service (if required)"
msgstr "Chave de API para o serviço (se necessário)"
#: apps/currencies/models.py:120
#: apps/currencies/models.py:121
msgid "Interval Type"
msgstr "Tipo de Intervalo"
#: apps/currencies/models.py:124
#: apps/currencies/models.py:125
msgid "Interval"
msgstr "Intervalo"
#: apps/currencies/models.py:127
#: apps/currencies/models.py:128
msgid "Last Successful Fetch"
msgstr "Última execução bem-sucedida"
#: apps/currencies/models.py:132
#: apps/currencies/models.py:133
msgid "Target Currencies"
msgstr "Moedas-alvo"
#: apps/currencies/models.py:134
#: apps/currencies/models.py:135
msgid ""
"Select currencies to fetch exchange rates for. Rates will be fetched for "
"each currency against their set exchange currency."
@@ -573,11 +573,11 @@ msgstr ""
"Selecione as moedas para as quais deseja obter as taxas de câmbio. As taxas "
"serão obtidas para cada moeda em relação à moeda de câmbio definida."
#: apps/currencies/models.py:142
#: apps/currencies/models.py:143
msgid "Target Accounts"
msgstr "Contas-alvo"
#: apps/currencies/models.py:144
#: apps/currencies/models.py:145
msgid ""
"Select accounts to fetch exchange rates for. Rates will be fetched for each "
"account's currency against their set exchange currency."
@@ -586,24 +586,24 @@ msgstr ""
"serão obtidas para a moeda de cada conta em relação à moeda de câmbio "
"definida."
#: apps/currencies/models.py:151
#: apps/currencies/models.py:152
msgid "Exchange Rate Service"
msgstr "Serviço de Taxa de Câmbio"
#: apps/currencies/models.py:152
#: apps/currencies/models.py:153
msgid "Exchange Rate Services"
msgstr "Serviços de Taxa de Câmbio"
#: apps/currencies/models.py:204
#: apps/currencies/models.py:205
msgid "'Every X hours' interval type requires a positive integer."
msgstr ""
"Intervalo do tipo 'A cada X horas' requerer um número inteiro positivo."
#: apps/currencies/models.py:213
#: apps/currencies/models.py:214
msgid "'Every X hours' interval must be between 1 and 24."
msgstr "Intervalo do tipo 'A cada X horas' requerer um número entre 1 e 24."
#: apps/currencies/models.py:227
#: apps/currencies/models.py:228
msgid ""
"Invalid hour format. Use comma-separated hours (0-23) and/or ranges (e.g., "
"'1-5,8,10-12')."
@@ -611,7 +611,7 @@ msgstr ""
"Formato inválido de hora. Use uma lista de horas separada por vírgulas "
"(0-23) e/ou uma faixa (ex.: '1-5,8,10-12')."
#: apps/currencies/models.py:238
#: apps/currencies/models.py:239
msgid ""
"Invalid format. Please check the requirements for your selected interval "
"type."
@@ -692,7 +692,7 @@ msgstr "Conectar transação"
msgid "You must provide an account."
msgstr "Você deve informar uma conta."
#: apps/dca/forms.py:312 apps/transactions/forms.py:443
#: apps/dca/forms.py:312 apps/transactions/forms.py:445
msgid "From and To accounts must be different."
msgstr "As contas De e Para devem ser diferentes."
@@ -709,10 +709,10 @@ msgstr "Moeda de destino"
msgid "Payment Currency"
msgstr "Moeda de pagamento"
#: apps/dca/models.py:26 apps/dca/models.py:181 apps/rules/forms.py:167
#: apps/rules/forms.py:182 apps/rules/models.py:36 apps/rules/models.py:269
#: apps/transactions/forms.py:345 apps/transactions/models.py:277
#: apps/transactions/models.py:469 apps/transactions/models.py:653
#: apps/dca/models.py:26 apps/dca/models.py:181 apps/rules/forms.py:173
#: apps/rules/forms.py:188 apps/rules/models.py:37 apps/rules/models.py:270
#: apps/transactions/forms.py:347 apps/transactions/models.py:301
#: apps/transactions/models.py:497 apps/transactions/models.py:696
msgid "Notes"
msgstr "Notas"
@@ -773,7 +773,7 @@ msgid "Users"
msgstr "Usuários"
#: apps/export_app/forms.py:32 apps/export_app/forms.py:137
#: apps/transactions/models.py:338 templates/includes/navbar.html:57
#: apps/transactions/models.py:362 templates/includes/navbar.html:57
#: templates/includes/navbar.html:104
#: templates/recurring_transactions/fragments/list_transactions.html:5
#: templates/recurring_transactions/fragments/table.html:37
@@ -788,25 +788,25 @@ msgid "Categories"
msgstr "Categorias"
#: apps/export_app/forms.py:50 apps/export_app/forms.py:136
#: apps/rules/forms.py:172 apps/rules/forms.py:181 apps/rules/models.py:39
#: apps/rules/models.py:281 apps/transactions/filters.py:81
#: apps/transactions/forms.py:56 apps/transactions/forms.py:516
#: apps/transactions/forms.py:773 apps/transactions/models.py:238
#: apps/transactions/models.py:292 apps/transactions/models.py:465
#: apps/transactions/models.py:650 templates/entities/fragments/list.html:5
#: apps/rules/forms.py:178 apps/rules/forms.py:187 apps/rules/models.py:40
#: apps/rules/models.py:282 apps/transactions/filters.py:81
#: apps/transactions/forms.py:56 apps/transactions/forms.py:518
#: apps/transactions/forms.py:779 apps/transactions/models.py:261
#: apps/transactions/models.py:316 apps/transactions/models.py:493
#: apps/transactions/models.py:693 templates/entities/fragments/list.html:5
#: templates/entities/pages/index.html:4 templates/includes/navbar.html:110
msgid "Entities"
msgstr "Entidades"
#: apps/export_app/forms.py:56 apps/export_app/forms.py:140
#: apps/transactions/models.py:680 templates/includes/navbar.html:74
#: apps/transactions/models.py:730 templates/includes/navbar.html:74
#: templates/recurring_transactions/fragments/list.html:5
#: templates/recurring_transactions/pages/index.html:4
msgid "Recurring Transactions"
msgstr "Transações Recorrentes"
#: apps/export_app/forms.py:62 apps/export_app/forms.py:138
#: apps/transactions/models.py:476 templates/includes/navbar.html:72
#: apps/transactions/models.py:511 templates/includes/navbar.html:72
#: templates/installment_plans/fragments/list.html:5
#: templates/installment_plans/pages/index.html:4
msgid "Installment Plans"
@@ -847,15 +847,15 @@ msgstr "Importe um arquivo ZIP exportado do WYGIWYH"
msgid "ZIP File"
msgstr "Arquivo ZIP"
#: apps/export_app/forms.py:146 apps/rules/models.py:21
#: apps/export_app/forms.py:146 apps/rules/models.py:22
msgid "Transaction rules"
msgstr "Regra da transação"
#: apps/export_app/forms.py:148 apps/rules/models.py:58
#: apps/export_app/forms.py:148 apps/rules/models.py:59
msgid "Edit transaction action"
msgstr "Ação de editar de transação"
#: apps/export_app/forms.py:151 apps/rules/models.py:295
#: apps/export_app/forms.py:151 apps/rules/models.py:296
msgid "Update or create transaction actions"
msgstr "Ações de atualizar ou criar transação"
@@ -1006,157 +1006,161 @@ msgstr "Despesas Previstas"
msgid "Saved"
msgstr "Salvo"
#: apps/rules/forms.py:20
msgid "Run on creation"
msgstr "Rodar na criação"
#: apps/rules/forms.py:21
msgid "Run on update"
msgstr "Rodar na atualização"
msgid "Run on creation"
msgstr "Rodar ao criar"
#: apps/rules/forms.py:22
msgid "Run on update"
msgstr "Rodar ao atualizar"
#: apps/rules/forms.py:23
msgid "Run on delete"
msgstr "Rodar ao apagar"
#: apps/rules/forms.py:24
msgid "If..."
msgstr "Se..."
#: apps/rules/forms.py:64
#: apps/rules/forms.py:70
msgid "Set field"
msgstr "Definir campo"
#: apps/rules/forms.py:65 templates/insights/fragments/sankey.html:94
#: apps/rules/forms.py:71 templates/insights/fragments/sankey.html:94
msgid "To"
msgstr "Para"
#: apps/rules/forms.py:115
#: apps/rules/forms.py:121
msgid "A value for this field already exists in the rule."
msgstr "Já existe um valor para esse campo na regra."
#: apps/rules/forms.py:147 apps/rules/forms.py:148 apps/rules/forms.py:149
#: apps/rules/forms.py:150 apps/rules/forms.py:151 apps/rules/forms.py:152
#: apps/rules/forms.py:153 apps/rules/forms.py:154 apps/rules/forms.py:155
#: apps/rules/forms.py:156 apps/rules/forms.py:157 apps/rules/forms.py:158
#: apps/rules/forms.py:159
#: apps/rules/forms.py:159 apps/rules/forms.py:160 apps/rules/forms.py:161
#: apps/rules/forms.py:162 apps/rules/forms.py:163 apps/rules/forms.py:164
#: apps/rules/forms.py:165
msgid "Operator"
msgstr "Operador"
#: apps/rules/forms.py:161 apps/rules/forms.py:174 apps/rules/models.py:30
#: apps/rules/models.py:245 apps/transactions/models.py:261
#: apps/transactions/models.py:425 apps/transactions/models.py:631
#: apps/rules/forms.py:167 apps/rules/forms.py:180 apps/rules/models.py:31
#: apps/rules/models.py:246 apps/transactions/models.py:285
#: apps/transactions/models.py:453 apps/transactions/models.py:674
msgid "Type"
msgstr "Tipo"
#: apps/rules/forms.py:162 apps/rules/forms.py:175 apps/rules/models.py:31
#: apps/rules/models.py:249 apps/transactions/filters.py:23
#: apps/transactions/models.py:263 templates/cotton/transaction/item.html:21
#: apps/rules/forms.py:168 apps/rules/forms.py:181 apps/rules/models.py:32
#: apps/rules/models.py:250 apps/transactions/filters.py:23
#: apps/transactions/models.py:287 templates/cotton/transaction/item.html:21
#: templates/cotton/transaction/item.html:31
#: templates/transactions/widgets/paid_toggle_button.html:12
#: templates/transactions/widgets/unselectable_paid_toggle_button.html:16
msgid "Paid"
msgstr "Pago"
#: apps/rules/forms.py:164 apps/rules/forms.py:177 apps/rules/models.py:33
#: apps/rules/models.py:257 apps/transactions/forms.py:68
#: apps/transactions/forms.py:334 apps/transactions/forms.py:522
#: apps/transactions/models.py:265 apps/transactions/models.py:443
#: apps/transactions/models.py:655
#: apps/rules/forms.py:170 apps/rules/forms.py:183 apps/rules/models.py:34
#: apps/rules/models.py:258 apps/transactions/forms.py:68
#: apps/transactions/forms.py:334 apps/transactions/forms.py:524
#: apps/transactions/models.py:289 apps/transactions/models.py:471
#: apps/transactions/models.py:698
msgid "Reference Date"
msgstr "Data de Referência"
#: apps/rules/forms.py:165 apps/rules/forms.py:178 apps/rules/models.py:34
#: apps/rules/models.py:261 apps/transactions/models.py:270
#: apps/transactions/models.py:636 templates/insights/fragments/sankey.html:95
#: apps/rules/forms.py:171 apps/rules/forms.py:184 apps/rules/models.py:35
#: apps/rules/models.py:262 apps/transactions/models.py:294
#: apps/transactions/models.py:679 templates/insights/fragments/sankey.html:95
msgid "Amount"
msgstr "Quantia"
#: apps/rules/forms.py:166 apps/rules/forms.py:179 apps/rules/models.py:13
#: apps/rules/models.py:35 apps/rules/models.py:265
#: apps/transactions/forms.py:337 apps/transactions/models.py:275
#: apps/transactions/models.py:427 apps/transactions/models.py:639
#: apps/rules/forms.py:172 apps/rules/forms.py:185 apps/rules/models.py:14
#: apps/rules/models.py:36 apps/rules/models.py:266
#: apps/transactions/forms.py:338 apps/transactions/models.py:299
#: apps/transactions/models.py:455 apps/transactions/models.py:682
msgid "Description"
msgstr "Descrição"
#: apps/rules/forms.py:169 apps/rules/forms.py:184 apps/rules/models.py:273
#: apps/transactions/models.py:314
#: apps/rules/forms.py:175 apps/rules/forms.py:190 apps/rules/models.py:274
#: apps/transactions/models.py:338
msgid "Internal Note"
msgstr "Nota Interna"
#: apps/rules/forms.py:170 apps/rules/forms.py:185 apps/rules/models.py:277
#: apps/transactions/models.py:316
#: apps/rules/forms.py:176 apps/rules/forms.py:191 apps/rules/models.py:278
#: apps/transactions/models.py:340
msgid "Internal ID"
msgstr "ID Interna"
#: apps/rules/forms.py:199
#: apps/rules/forms.py:205
msgid "Search Criteria"
msgstr "Critério de Busca"
#: apps/rules/forms.py:334
#: apps/rules/forms.py:340
msgid "Set Values"
msgstr "Definir valores"
#: apps/rules/models.py:14
#: apps/rules/models.py:15
msgid "Trigger"
msgstr "Gatilho"
#: apps/rules/models.py:20
#: apps/rules/models.py:21
msgid "Transaction rule"
msgstr "Regra da transação"
#: apps/rules/models.py:45 apps/rules/models.py:83
#: apps/rules/models.py:46 apps/rules/models.py:84
msgid "Rule"
msgstr "Regra"
#: apps/rules/models.py:50
#: apps/rules/models.py:51
msgid "Field"
msgstr "Campo"
#: apps/rules/models.py:52
#: apps/rules/models.py:53
msgid "Value"
msgstr "Valor"
#: apps/rules/models.py:59
#: apps/rules/models.py:60
msgid "Edit transaction actions"
msgstr "Ações de editar de transação"
#: apps/rules/models.py:69
#: apps/rules/models.py:70
msgid "is exactly"
msgstr "é exatamete"
#: apps/rules/models.py:70
#: apps/rules/models.py:71
msgid "contains"
msgstr "contém"
#: apps/rules/models.py:71
#: apps/rules/models.py:72
msgid "starts with"
msgstr "começa com"
#: apps/rules/models.py:72
#: apps/rules/models.py:73
msgid "ends with"
msgstr "termina em"
#: apps/rules/models.py:73
#: apps/rules/models.py:74
msgid "equals"
msgstr "igual"
#: apps/rules/models.py:74
#: apps/rules/models.py:75
msgid "greater than"
msgstr "maior que"
#: apps/rules/models.py:75
#: apps/rules/models.py:76
msgid "less than"
msgstr "menos de"
#: apps/rules/models.py:76
#: apps/rules/models.py:77
msgid "greater than or equal"
msgstr "maior ou igual"
#: apps/rules/models.py:77
#: apps/rules/models.py:78
msgid "less than or equal"
msgstr "menor ou igual"
#: apps/rules/models.py:87 templates/transactions/pages/transactions.html:15
#: apps/rules/models.py:88 templates/transactions/pages/transactions.html:15
msgid "Filter"
msgstr "Filtro"
#: apps/rules/models.py:90
#: apps/rules/models.py:91
msgid ""
"Generic expression to enable or disable execution. Should evaluate to True "
"or False"
@@ -1164,7 +1168,7 @@ msgstr ""
"Expressão genérica para ativar ou desativar a execução. Deve retornar True "
"ou False"
#: apps/rules/models.py:294
#: apps/rules/models.py:295
msgid "Update or create transaction action"
msgstr "Ação de atualizar ou criar transação"
@@ -1255,36 +1259,36 @@ msgstr "Quantia de origem"
msgid "To Amount"
msgstr "Quantia de destino"
#: apps/transactions/forms.py:410
#: apps/transactions/forms.py:412
#: templates/cotton/ui/quick_transactions_buttons.html:40
msgid "Transfer"
msgstr "Transferir"
#: apps/transactions/forms.py:652
#: apps/transactions/forms.py:658
msgid "Tag name"
msgstr "Nome da Tag"
#: apps/transactions/forms.py:684
#: apps/transactions/forms.py:690
msgid "Entity name"
msgstr "Nome da entidade"
#: apps/transactions/forms.py:716
#: apps/transactions/forms.py:722
msgid "Category name"
msgstr "Nome da Categoria"
#: apps/transactions/forms.py:718
#: apps/transactions/forms.py:724
msgid "Muted categories won't count towards your monthly total"
msgstr "As categorias silenciadas não serão contabilizadas em seu total mensal"
#: apps/transactions/forms.py:900
#: apps/transactions/forms.py:910
msgid "End date should be after the start date"
msgstr "Data final deve ser após data inicial"
#: apps/transactions/models.py:178
#: apps/transactions/models.py:199
msgid "Mute"
msgstr "Silenciada"
#: apps/transactions/models.py:183
#: apps/transactions/models.py:204
msgid ""
"Deactivated categories won't be able to be selected when creating new "
"transactions"
@@ -1292,25 +1296,25 @@ msgstr ""
"As categorias desativadas não poderão ser selecionadas ao criar novas "
"transações"
#: apps/transactions/models.py:191
#: apps/transactions/models.py:212
msgid "Transaction Category"
msgstr "Categoria da Transação"
#: apps/transactions/models.py:192
#: apps/transactions/models.py:213
msgid "Transaction Categories"
msgstr "Categorias da Trasanção"
#: apps/transactions/models.py:206
#: apps/transactions/models.py:228
msgid ""
"Deactivated tags won't be able to be selected when creating new transactions"
msgstr ""
"As tags desativadas não poderão ser selecionadas ao criar novas transações"
#: apps/transactions/models.py:214 apps/transactions/models.py:215
#: apps/transactions/models.py:236 apps/transactions/models.py:237
msgid "Transaction Tags"
msgstr "Tags da Transação"
#: apps/transactions/models.py:229
#: apps/transactions/models.py:252
msgid ""
"Deactivated entities won't be able to be selected when creating new "
"transactions"
@@ -1318,11 +1322,11 @@ msgstr ""
"As entidades desativadas não poderão ser selecionadas ao criar novas "
"transações"
#: apps/transactions/models.py:237
#: apps/transactions/models.py:260
msgid "Entity"
msgstr "Entidade"
#: apps/transactions/models.py:248
#: apps/transactions/models.py:272
#: templates/calendar_view/fragments/list.html:42
#: templates/calendar_view/fragments/list.html:44
#: templates/calendar_view/fragments/list.html:52
@@ -1333,7 +1337,7 @@ msgstr "Entidade"
msgid "Income"
msgstr "Renda"
#: apps/transactions/models.py:249
#: apps/transactions/models.py:273
#: templates/calendar_view/fragments/list.html:46
#: templates/calendar_view/fragments/list.html:48
#: templates/calendar_view/fragments/list.html:56
@@ -1343,117 +1347,125 @@ msgstr "Renda"
msgid "Expense"
msgstr "Despesa"
#: apps/transactions/models.py:303 apps/transactions/models.py:475
#: apps/transactions/models.py:327 apps/transactions/models.py:510
msgid "Installment Plan"
msgstr "Parcelamento"
#: apps/transactions/models.py:312 apps/transactions/models.py:679
#: apps/transactions/models.py:336 apps/transactions/models.py:729
msgid "Recurring Transaction"
msgstr "Transação Recorrente"
#: apps/transactions/models.py:320
#: apps/transactions/models.py:344
msgid "Deleted"
msgstr "Apagado"
#: apps/transactions/models.py:325
#: apps/transactions/models.py:349
msgid "Deleted At"
msgstr "Apagado Em"
#: apps/transactions/models.py:337
#: apps/transactions/models.py:361
msgid "Transaction"
msgstr "Transação"
#: apps/transactions/models.py:405 templates/tags/fragments/table.html:71
#: apps/transactions/models.py:433 templates/tags/fragments/table.html:71
msgid "No tags"
msgstr "Nenhuma tag"
#: apps/transactions/models.py:406
#: apps/transactions/models.py:434
msgid "No category"
msgstr "Sem categoria"
#: apps/transactions/models.py:408
#: apps/transactions/models.py:436
msgid "No description"
msgstr "Sem descrição"
#: apps/transactions/models.py:414
#: apps/transactions/models.py:442
msgid "Yearly"
msgstr "Anual"
#: apps/transactions/models.py:415 apps/users/models.py:26
#: apps/transactions/models.py:443 apps/users/models.py:26
#: templates/includes/navbar.html:26
msgid "Monthly"
msgstr "Mensal"
#: apps/transactions/models.py:416
#: apps/transactions/models.py:444
msgid "Weekly"
msgstr "Semanal"
#: apps/transactions/models.py:417
#: apps/transactions/models.py:445
msgid "Daily"
msgstr "Diária"
#: apps/transactions/models.py:430
#: apps/transactions/models.py:458
msgid "Number of Installments"
msgstr "Número de Parcelas"
#: apps/transactions/models.py:435
#: apps/transactions/models.py:463
msgid "Installment Start"
msgstr "Parcela inicial"
#: apps/transactions/models.py:436
#: apps/transactions/models.py:464
msgid "The installment number to start counting from"
msgstr "O número da parcela a partir do qual se inicia a contagem"
#: apps/transactions/models.py:441 apps/transactions/models.py:659
#: apps/transactions/models.py:469 apps/transactions/models.py:702
msgid "Start Date"
msgstr "Data de Início"
#: apps/transactions/models.py:445 apps/transactions/models.py:660
#: apps/transactions/models.py:473 apps/transactions/models.py:703
msgid "End Date"
msgstr "Data Final"
#: apps/transactions/models.py:450
#: apps/transactions/models.py:478
msgid "Recurrence"
msgstr "Recorrência"
#: apps/transactions/models.py:453
#: apps/transactions/models.py:481
msgid "Installment Amount"
msgstr "Valor da Parcela"
#: apps/transactions/models.py:618
#: apps/transactions/models.py:500 apps/transactions/models.py:719
msgid "Add description to transactions"
msgstr "Adicionar descrição às transações"
#: apps/transactions/models.py:503 apps/transactions/models.py:722
msgid "Add notes to transactions"
msgstr "Adicionar notas às transações"
#: apps/transactions/models.py:661
msgid "day(s)"
msgstr "dia(s)"
#: apps/transactions/models.py:619
#: apps/transactions/models.py:662
msgid "week(s)"
msgstr "semana(s)"
#: apps/transactions/models.py:620
#: apps/transactions/models.py:663
msgid "month(s)"
msgstr "mês(es)"
#: apps/transactions/models.py:621
#: apps/transactions/models.py:664
msgid "year(s)"
msgstr "ano(s)"
#: apps/transactions/models.py:623
#: apps/transactions/models.py:666
#: templates/recurring_transactions/fragments/list.html:24
msgid "Paused"
msgstr "Pausado"
#: apps/transactions/models.py:662
#: apps/transactions/models.py:705
msgid "Recurrence Type"
msgstr "Tipo de recorrência"
#: apps/transactions/models.py:665
#: apps/transactions/models.py:708
msgid "Recurrence Interval"
msgstr "Intervalo de recorrência"
#: apps/transactions/models.py:669
#: apps/transactions/models.py:712
msgid "Last Generated Date"
msgstr "Última data gerada"
#: apps/transactions/models.py:672
#: apps/transactions/models.py:715
msgid "Last Generated Reference Date"
msgstr "Última data de referência gerada"
@@ -2560,7 +2572,7 @@ msgstr "Total"
#: templates/insights/fragments/emergency_fund.html:15
msgid "You've spent an average of"
msgstr "Você gastou um total de"
msgstr "Você gastou em média"
#: templates/insights/fragments/emergency_fund.html:23
msgid "on the last 12 months, at this rate you could go by"

View File

@@ -5,7 +5,7 @@
{% block title %}{% translate 'Transactions on' %} {{ date|date:"SHORT_DATE_FORMAT" }}{% endblock %}
{% block body %}
<div hx-get="{% url 'calendar_transactions_list' day=date.day month=date.month year=date.year %}" hx-trigger="updated from:window" hx-vals='{"disable_selection": true}' hx-target="closest .offcanvas" class="show-loading" id="transactions-list">
<div hx-get="{% url 'calendar_transactions_list' day=date.day month=date.month year=date.year %}" hx-trigger="updated from:window" hx-target="closest .offcanvas" class="show-loading" id="transactions-list">
{% for transaction in transactions %}
<c-transaction.item :transaction="transaction"></c-transaction.item>
{% empty %}

View File

@@ -5,7 +5,7 @@
{% block title %}{% translate 'Installments' %}{% endblock %}
{% block body %}
<div hx-get="{% url 'installment_plan_transactions' installment_plan_id=installment_plan.id %}" hx-trigger="updated from:window" hx-vals='{"disable_selection": true}' hx-target="closest .offcanvas" class="show-loading" id="transactions-list">
<div hx-get="{% url 'installment_plan_transactions' installment_plan_id=installment_plan.id %}" hx-trigger="updated from:window" hx-target="closest .offcanvas" class="show-loading" id="transactions-list">
{% for transaction in transactions %}
<c-transaction.item :transaction="transaction"></c-transaction.item>
{% endfor %}

View File

@@ -160,7 +160,7 @@
</div>
</div>
{# Filter transactions form#}
<div class="collapse" id="collapse-filter">
<div class="collapse" id="collapse-filter" hx-preserve>
<div class="card card-body">
<form _="on change or submit or search trigger updated on window end
install init_tom_select

View File

@@ -5,7 +5,7 @@
{% block title %}{% translate 'Transactions' %}{% endblock %}
{% block body %}
<div hx-get="{% url 'recurring_transaction_transactions' recurring_transaction_id=recurring_transaction.id %}" hx-trigger="updated from:window" hx-vals='{"disable_selection": true}' hx-target="closest .offcanvas" class="show-loading" id="transactions-list">
<div hx-get="{% url 'recurring_transaction_transactions' recurring_transaction_id=recurring_transaction.id %}" hx-trigger="updated from:window" hx-target="closest .offcanvas" class="show-loading" id="transactions-list">
{% for transaction in transactions %}
<c-transaction.item :transaction="transaction"></c-transaction.item>
{% endfor %}

View File

@@ -14,7 +14,7 @@ djangorestframework~=3.15.2
drf-spectacular~=0.27.2
django-import-export~=4.3.5
gunicorn==22.0.0
gunicorn==23.0.0
whitenoise[brotli]==6.6.0
watchfiles==0.24.0 # https://github.com/samuelcolvin/watchfiles