mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-04-20 07:41:28 +02:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8de340b68b | ||
|
|
ef15b85386 | ||
|
|
45d939237d | ||
|
|
6bf262e514 | ||
|
|
f9d9137336 | ||
|
|
b532521f27 | ||
|
|
1e06e2d34d | ||
|
|
a33fa5e184 | ||
|
|
a2453695d8 | ||
|
|
3e929d0433 | ||
|
|
185fc464a5 | ||
|
|
647c009525 | ||
|
|
ba75492dcc | ||
|
|
8312baaf45 | ||
|
|
4d346dc278 | ||
|
|
70ff7fab38 | ||
|
|
6947c6affd | ||
|
|
dcab83f936 | ||
|
|
b228e4ec26 | ||
|
|
4071a1301f | ||
|
|
5c9db10710 | ||
|
|
19c92e0014 | ||
|
|
6459f2eb46 |
@@ -163,6 +163,7 @@ AUTH_USER_MODEL = "users.User"
|
|||||||
|
|
||||||
LANGUAGE_CODE = "en"
|
LANGUAGE_CODE = "en"
|
||||||
LANGUAGES = (
|
LANGUAGES = (
|
||||||
|
("de", "Deutsch"),
|
||||||
("en", "English"),
|
("en", "English"),
|
||||||
("nl", "Nederlands"),
|
("nl", "Nederlands"),
|
||||||
("pt-br", "Português (Brasil)"),
|
("pt-br", "Português (Brasil)"),
|
||||||
|
|||||||
@@ -2,13 +2,15 @@ from import_export import fields, resources, widgets
|
|||||||
|
|
||||||
from apps.accounts.models import Account
|
from apps.accounts.models import Account
|
||||||
from apps.currencies.models import Currency, ExchangeRate, ExchangeRateService
|
from apps.currencies.models import Currency, ExchangeRate, ExchangeRateService
|
||||||
|
from apps.export_app.widgets.foreign_key import SkipMissingForeignKeyWidget
|
||||||
|
from apps.export_app.widgets.numbers import UniversalDecimalWidget
|
||||||
|
|
||||||
|
|
||||||
class CurrencyResource(resources.ModelResource):
|
class CurrencyResource(resources.ModelResource):
|
||||||
exchange_currency = fields.Field(
|
exchange_currency = fields.Field(
|
||||||
attribute="exchange_currency",
|
attribute="exchange_currency",
|
||||||
column_name="exchange_currency",
|
column_name="exchange_currency",
|
||||||
widget=widgets.ForeignKeyWidget(Currency, "name"),
|
widget=SkipMissingForeignKeyWidget(Currency, "name"),
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -26,6 +28,9 @@ class ExchangeRateResource(resources.ModelResource):
|
|||||||
column_name="to_currency",
|
column_name="to_currency",
|
||||||
widget=widgets.ForeignKeyWidget(Currency, "name"),
|
widget=widgets.ForeignKeyWidget(Currency, "name"),
|
||||||
)
|
)
|
||||||
|
rate = fields.Field(
|
||||||
|
attribute="rate", column_name="rate", widget=UniversalDecimalWidget()
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ExchangeRate
|
model = ExchangeRate
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ from import_export.widgets import ForeignKeyWidget
|
|||||||
|
|
||||||
from apps.dca.models import DCAStrategy, DCAEntry
|
from apps.dca.models import DCAStrategy, DCAEntry
|
||||||
from apps.currencies.models import Currency
|
from apps.currencies.models import Currency
|
||||||
|
from apps.export_app.widgets.numbers import UniversalDecimalWidget
|
||||||
|
|
||||||
|
|
||||||
class DCAStrategyResource(resources.ModelResource):
|
class DCAStrategyResource(resources.ModelResource):
|
||||||
@@ -22,5 +23,16 @@ class DCAStrategyResource(resources.ModelResource):
|
|||||||
|
|
||||||
|
|
||||||
class DCAEntryResource(resources.ModelResource):
|
class DCAEntryResource(resources.ModelResource):
|
||||||
|
amount_paid = fields.Field(
|
||||||
|
attribute="amount_paid",
|
||||||
|
column_name="amount_paid",
|
||||||
|
widget=UniversalDecimalWidget(),
|
||||||
|
)
|
||||||
|
amount_received = fields.Field(
|
||||||
|
attribute="amount_received",
|
||||||
|
column_name="amount_received",
|
||||||
|
widget=UniversalDecimalWidget(),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = DCAEntry
|
model = DCAEntry
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ from apps.transactions.models import (
|
|||||||
RecurringTransaction,
|
RecurringTransaction,
|
||||||
InstallmentPlan,
|
InstallmentPlan,
|
||||||
)
|
)
|
||||||
|
from apps.export_app.widgets.numbers import UniversalDecimalWidget
|
||||||
|
|
||||||
|
|
||||||
class TransactionResource(resources.ModelResource):
|
class TransactionResource(resources.ModelResource):
|
||||||
@@ -44,6 +45,12 @@ class TransactionResource(resources.ModelResource):
|
|||||||
column_name="internal_id", attribute="internal_id"
|
column_name="internal_id", attribute="internal_id"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
amount = fields.Field(
|
||||||
|
attribute="amount",
|
||||||
|
column_name="amount",
|
||||||
|
widget=UniversalDecimalWidget(),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Transaction
|
model = Transaction
|
||||||
|
|
||||||
@@ -91,6 +98,12 @@ class RecurringTransactionResource(resources.ModelResource):
|
|||||||
widget=AutoCreateManyToManyWidget(TransactionEntity, field="name"),
|
widget=AutoCreateManyToManyWidget(TransactionEntity, field="name"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
amount = fields.Field(
|
||||||
|
attribute="amount",
|
||||||
|
column_name="amount",
|
||||||
|
widget=UniversalDecimalWidget(),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RecurringTransaction
|
model = RecurringTransaction
|
||||||
|
|
||||||
@@ -120,5 +133,11 @@ class InstallmentPlanResource(resources.ModelResource):
|
|||||||
widget=AutoCreateManyToManyWidget(TransactionEntity, field="name"),
|
widget=AutoCreateManyToManyWidget(TransactionEntity, field="name"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
installment_amount = fields.Field(
|
||||||
|
attribute="installment_amount",
|
||||||
|
column_name="installment_amount",
|
||||||
|
widget=UniversalDecimalWidget(),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = InstallmentPlan
|
model = InstallmentPlan
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ def export_index(request):
|
|||||||
return render(request, "export_app/pages/index.html")
|
return render(request, "export_app/pages/index.html")
|
||||||
|
|
||||||
|
|
||||||
@only_htmx
|
|
||||||
@login_required
|
@login_required
|
||||||
@require_http_methods(["GET", "POST"])
|
@require_http_methods(["GET", "POST"])
|
||||||
def export_form(request):
|
def export_form(request):
|
||||||
@@ -241,11 +240,6 @@ def process_imports(request, cleaned_data):
|
|||||||
dataset = Dataset()
|
dataset = Dataset()
|
||||||
dataset.load(content, format="csv")
|
dataset.load(content, format="csv")
|
||||||
|
|
||||||
# Debug logging
|
|
||||||
logger.debug(f"Importing {field_name}")
|
|
||||||
logger.debug(f"Headers: {dataset.headers}")
|
|
||||||
logger.debug(f"First row: {dataset[0] if len(dataset) > 0 else 'No data'}")
|
|
||||||
|
|
||||||
# Perform the import
|
# Perform the import
|
||||||
result = resource.import_data(
|
result = resource.import_data(
|
||||||
dataset,
|
dataset,
|
||||||
@@ -266,6 +260,8 @@ def process_imports(request, cleaned_data):
|
|||||||
raise ImportError(f"Error importing {field_name}: {str(e)}")
|
raise ImportError(f"Error importing {field_name}: {str(e)}")
|
||||||
|
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
|
files = {}
|
||||||
|
|
||||||
if zip_file := cleaned_data.get("zip_file"):
|
if zip_file := cleaned_data.get("zip_file"):
|
||||||
# Process ZIP file
|
# Process ZIP file
|
||||||
with zipfile.ZipFile(zip_file) as z:
|
with zipfile.ZipFile(zip_file) as z:
|
||||||
@@ -274,10 +270,12 @@ def process_imports(request, cleaned_data):
|
|||||||
with z.open(filename) as f:
|
with z.open(filename) as f:
|
||||||
content = f.read().decode("utf-8")
|
content = f.read().decode("utf-8")
|
||||||
|
|
||||||
for field_name, resource_class in import_order:
|
files[name] = content
|
||||||
if name == field_name:
|
|
||||||
import_dataset(content, resource_class, field_name)
|
for field_name, resource_class in import_order:
|
||||||
break
|
if field_name in files.keys():
|
||||||
|
content = files[field_name]
|
||||||
|
import_dataset(content, resource_class, field_name)
|
||||||
else:
|
else:
|
||||||
# Process individual files
|
# Process individual files
|
||||||
for field_name, resource_class in import_order:
|
for field_name, resource_class in import_order:
|
||||||
|
|||||||
@@ -9,3 +9,14 @@ class AutoCreateForeignKeyWidget(ForeignKeyWidget):
|
|||||||
except self.model.DoesNotExist:
|
except self.model.DoesNotExist:
|
||||||
return self.model.objects.create(name=value)
|
return self.model.objects.create(name=value)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class SkipMissingForeignKeyWidget(ForeignKeyWidget):
|
||||||
|
def clean(self, value, row=None, *args, **kwargs):
|
||||||
|
if not value:
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
return super().clean(value, row, *args, **kwargs)
|
||||||
|
except self.model.DoesNotExist:
|
||||||
|
return None
|
||||||
|
|||||||
18
app/apps/export_app/widgets/numbers.py
Normal file
18
app/apps/export_app/widgets/numbers.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
|
from import_export.widgets import NumberWidget
|
||||||
|
|
||||||
|
|
||||||
|
class UniversalDecimalWidget(NumberWidget):
|
||||||
|
def clean(self, value, row=None, *args, **kwargs):
|
||||||
|
if self.is_empty(value):
|
||||||
|
return None
|
||||||
|
# Replace comma with dot if present
|
||||||
|
if isinstance(value, str):
|
||||||
|
value = value.replace(",", ".")
|
||||||
|
return Decimal(str(value))
|
||||||
|
|
||||||
|
def render(self, value, obj=None, **kwargs):
|
||||||
|
if value is None:
|
||||||
|
return ""
|
||||||
|
return str(value).replace(",", ".")
|
||||||
@@ -29,4 +29,14 @@ urlpatterns = [
|
|||||||
views.category_sum_by_currency,
|
views.category_sum_by_currency,
|
||||||
name="category_sum_by_currency",
|
name="category_sum_by_currency",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"insights/late-transactions/",
|
||||||
|
views.late_transactions,
|
||||||
|
name="insights_late_transactions",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"insights/latest-transactions/",
|
||||||
|
views.latest_transactions,
|
||||||
|
name="insights_latest_transactions",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -14,8 +14,7 @@ def get_category_sums_by_account(queryset, category=None):
|
|||||||
current_income=Coalesce(
|
current_income=Coalesce(
|
||||||
Sum(
|
Sum(
|
||||||
Case(
|
Case(
|
||||||
When(type="IN", then="amount"),
|
When(type="IN", is_paid=True, then="amount"),
|
||||||
When(is_paid=True, then="amount"),
|
|
||||||
default=Value(0),
|
default=Value(0),
|
||||||
output_field=DecimalField(max_digits=42, decimal_places=30),
|
output_field=DecimalField(max_digits=42, decimal_places=30),
|
||||||
)
|
)
|
||||||
@@ -26,8 +25,7 @@ def get_category_sums_by_account(queryset, category=None):
|
|||||||
current_expense=Coalesce(
|
current_expense=Coalesce(
|
||||||
Sum(
|
Sum(
|
||||||
Case(
|
Case(
|
||||||
When(type="EX", then=-F("amount")),
|
When(type="EX", is_paid=True, then=-F("amount")),
|
||||||
When(is_paid=True, then="amount"),
|
|
||||||
default=Value(0),
|
default=Value(0),
|
||||||
output_field=DecimalField(max_digits=42, decimal_places=30),
|
output_field=DecimalField(max_digits=42, decimal_places=30),
|
||||||
)
|
)
|
||||||
@@ -38,8 +36,7 @@ def get_category_sums_by_account(queryset, category=None):
|
|||||||
projected_income=Coalesce(
|
projected_income=Coalesce(
|
||||||
Sum(
|
Sum(
|
||||||
Case(
|
Case(
|
||||||
When(type="IN", then="amount"),
|
When(type="IN", is_paid=False, then="amount"),
|
||||||
When(is_paid=False, then="amount"),
|
|
||||||
default=Value(0),
|
default=Value(0),
|
||||||
output_field=DecimalField(max_digits=42, decimal_places=30),
|
output_field=DecimalField(max_digits=42, decimal_places=30),
|
||||||
)
|
)
|
||||||
@@ -50,8 +47,7 @@ def get_category_sums_by_account(queryset, category=None):
|
|||||||
projected_expense=Coalesce(
|
projected_expense=Coalesce(
|
||||||
Sum(
|
Sum(
|
||||||
Case(
|
Case(
|
||||||
When(type="EX", then=-F("amount")),
|
When(type="EX", is_paid=False, then=-F("amount")),
|
||||||
When(is_paid=False, then="amount"),
|
|
||||||
default=Value(0),
|
default=Value(0),
|
||||||
output_field=DecimalField(max_digits=42, decimal_places=30),
|
output_field=DecimalField(max_digits=42, decimal_places=30),
|
||||||
)
|
)
|
||||||
@@ -97,8 +93,7 @@ def get_category_sums_by_currency(queryset, category=None):
|
|||||||
current_income=Coalesce(
|
current_income=Coalesce(
|
||||||
Sum(
|
Sum(
|
||||||
Case(
|
Case(
|
||||||
When(type="IN", then="amount"),
|
When(type="IN", is_paid=True, then="amount"),
|
||||||
When(is_paid=True, then="amount"),
|
|
||||||
default=Value(0),
|
default=Value(0),
|
||||||
output_field=DecimalField(max_digits=42, decimal_places=30),
|
output_field=DecimalField(max_digits=42, decimal_places=30),
|
||||||
)
|
)
|
||||||
@@ -109,8 +104,7 @@ def get_category_sums_by_currency(queryset, category=None):
|
|||||||
current_expense=Coalesce(
|
current_expense=Coalesce(
|
||||||
Sum(
|
Sum(
|
||||||
Case(
|
Case(
|
||||||
When(type="EX", then=-F("amount")),
|
When(type="EX", is_paid=True, then=-F("amount")),
|
||||||
When(is_paid=True, then="amount"),
|
|
||||||
default=Value(0),
|
default=Value(0),
|
||||||
output_field=DecimalField(max_digits=42, decimal_places=30),
|
output_field=DecimalField(max_digits=42, decimal_places=30),
|
||||||
)
|
)
|
||||||
@@ -121,8 +115,7 @@ def get_category_sums_by_currency(queryset, category=None):
|
|||||||
projected_income=Coalesce(
|
projected_income=Coalesce(
|
||||||
Sum(
|
Sum(
|
||||||
Case(
|
Case(
|
||||||
When(type="IN", then="amount"),
|
When(type="IN", is_paid=False, then="amount"),
|
||||||
When(is_paid=False, then="amount"),
|
|
||||||
default=Value(0),
|
default=Value(0),
|
||||||
output_field=DecimalField(max_digits=42, decimal_places=30),
|
output_field=DecimalField(max_digits=42, decimal_places=30),
|
||||||
)
|
)
|
||||||
@@ -133,8 +126,7 @@ def get_category_sums_by_currency(queryset, category=None):
|
|||||||
projected_expense=Coalesce(
|
projected_expense=Coalesce(
|
||||||
Sum(
|
Sum(
|
||||||
Case(
|
Case(
|
||||||
When(type="EX", then=-F("amount")),
|
When(type="EX", is_paid=False, then=-F("amount")),
|
||||||
When(is_paid=False, then="amount"),
|
|
||||||
default=Value(0),
|
default=Value(0),
|
||||||
output_field=DecimalField(max_digits=42, decimal_places=30),
|
output_field=DecimalField(max_digits=42, decimal_places=30),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ from apps.insights.utils.sankey import (
|
|||||||
generate_sankey_data_by_currency,
|
generate_sankey_data_by_currency,
|
||||||
)
|
)
|
||||||
from apps.insights.utils.transactions import get_transactions
|
from apps.insights.utils.transactions import get_transactions
|
||||||
from apps.transactions.models import TransactionCategory
|
from apps.transactions.models import TransactionCategory, Transaction
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -157,3 +157,33 @@ def category_sum_by_currency(request):
|
|||||||
"insights/fragments/category_explorer/charts/currency.html",
|
"insights/fragments/category_explorer/charts/currency.html",
|
||||||
{"currency_data": currency_data},
|
{"currency_data": currency_data},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@only_htmx
|
||||||
|
@login_required
|
||||||
|
@require_http_methods(["GET"])
|
||||||
|
def latest_transactions(request):
|
||||||
|
limit = timezone.now() - relativedelta(days=3)
|
||||||
|
transactions = Transaction.objects.filter(created_at__gte=limit).order_by("-id")[
|
||||||
|
:30
|
||||||
|
]
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"insights/fragments/latest_transactions.html",
|
||||||
|
{"transactions": transactions},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@only_htmx
|
||||||
|
@login_required
|
||||||
|
@require_http_methods(["GET"])
|
||||||
|
def late_transactions(request):
|
||||||
|
now = timezone.localdate(timezone.now())
|
||||||
|
transactions = Transaction.objects.filter(is_paid=False, date__lt=now)
|
||||||
|
|
||||||
|
return render(
|
||||||
|
request,
|
||||||
|
"insights/fragments/late_transactions.html",
|
||||||
|
{"transactions": transactions},
|
||||||
|
)
|
||||||
|
|||||||
0
app/apps/mini_tools/utils/__init__.py
Normal file
0
app/apps/mini_tools/utils/__init__.py
Normal file
85
app/apps/mini_tools/utils/exchange_rate_map.py
Normal file
85
app/apps/mini_tools/utils/exchange_rate_map.py
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
from typing import Dict
|
||||||
|
|
||||||
|
from django.db.models import Func, F, Value
|
||||||
|
from django.db.models.functions import Extract
|
||||||
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from apps.currencies.models import ExchangeRate
|
||||||
|
|
||||||
|
|
||||||
|
def get_currency_exchange_map(date=None) -> Dict[str, dict]:
|
||||||
|
"""
|
||||||
|
Creates a nested dictionary of exchange rates and currency information.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
{
|
||||||
|
'BTC': {
|
||||||
|
'decimal_places': 8,
|
||||||
|
'prefix': '₿',
|
||||||
|
'suffix': '',
|
||||||
|
'rates': {'USD': Decimal('34000.00'), 'EUR': Decimal('31000.00')}
|
||||||
|
},
|
||||||
|
'USD': {
|
||||||
|
'decimal_places': 2,
|
||||||
|
'prefix': '$',
|
||||||
|
'suffix': '',
|
||||||
|
'rates': {'BTC': Decimal('0.0000294'), 'EUR': Decimal('0.91')}
|
||||||
|
},
|
||||||
|
...
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
if date is None:
|
||||||
|
date = timezone.localtime(timezone.now())
|
||||||
|
|
||||||
|
# Get all exchange rates for the closest date
|
||||||
|
exchange_rates = (
|
||||||
|
ExchangeRate.objects.select_related(
|
||||||
|
"from_currency", "to_currency"
|
||||||
|
) # Optimize currency queries
|
||||||
|
.annotate(
|
||||||
|
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")
|
||||||
|
)
|
||||||
|
|
||||||
|
# Initialize the result dictionary
|
||||||
|
rate_map = {}
|
||||||
|
|
||||||
|
# Build the exchange rate mapping with currency info
|
||||||
|
for rate in exchange_rates:
|
||||||
|
# Add from_currency info if not exists
|
||||||
|
if rate.from_currency.name not in rate_map:
|
||||||
|
rate_map[rate.from_currency.name] = {
|
||||||
|
"decimal_places": rate.from_currency.decimal_places,
|
||||||
|
"prefix": rate.from_currency.prefix,
|
||||||
|
"suffix": rate.from_currency.suffix,
|
||||||
|
"rates": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add to_currency info if not exists
|
||||||
|
if rate.to_currency.name not in rate_map:
|
||||||
|
rate_map[rate.to_currency.name] = {
|
||||||
|
"decimal_places": rate.to_currency.decimal_places,
|
||||||
|
"prefix": rate.to_currency.prefix,
|
||||||
|
"suffix": rate.to_currency.suffix,
|
||||||
|
"rates": {},
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add direct rate
|
||||||
|
rate_map[rate.from_currency.name]["rates"][rate.to_currency.name] = {
|
||||||
|
"rate": rate.rate,
|
||||||
|
"decimal_places": rate.to_currency.decimal_places,
|
||||||
|
"prefix": rate.to_currency.prefix,
|
||||||
|
"suffix": rate.to_currency.suffix,
|
||||||
|
}
|
||||||
|
# Add inverse rate
|
||||||
|
rate_map[rate.to_currency.name]["rates"][rate.from_currency.name] = {
|
||||||
|
"rate": 1 / rate.rate,
|
||||||
|
"decimal_places": rate.from_currency.decimal_places,
|
||||||
|
"prefix": rate.from_currency.prefix,
|
||||||
|
"suffix": rate.from_currency.suffix,
|
||||||
|
}
|
||||||
|
|
||||||
|
return rate_map
|
||||||
@@ -5,6 +5,7 @@ from apps.common.widgets.decimal import convert_to_decimal
|
|||||||
from apps.currencies.models import Currency
|
from apps.currencies.models import Currency
|
||||||
from apps.currencies.utils.convert import convert
|
from apps.currencies.utils.convert import convert
|
||||||
from apps.mini_tools.forms import CurrencyConverterForm
|
from apps.mini_tools.forms import CurrencyConverterForm
|
||||||
|
from apps.mini_tools.utils.exchange_rate_map import get_currency_exchange_map
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
@@ -14,11 +15,13 @@ def unit_price_calculator(request):
|
|||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def currency_converter(request):
|
def currency_converter(request):
|
||||||
|
rate_map = get_currency_exchange_map()
|
||||||
|
|
||||||
form = CurrencyConverterForm()
|
form = CurrencyConverterForm()
|
||||||
return render(
|
return render(
|
||||||
request,
|
request,
|
||||||
"mini_tools/currency_converter/currency_converter.html",
|
"mini_tools/currency_converter/currency_converter.html",
|
||||||
context={"form": form},
|
context={"form": form, "rate_map": rate_map},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 5.1.6 on 2025-02-24 19:32
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('users', '0018_alter_usersettings_start_page'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='usersettings',
|
||||||
|
name='language',
|
||||||
|
field=models.CharField(choices=[('auto', 'Auto'), ('de', 'Deutsch'), ('en', 'English'), ('nl', 'Nederlands'), ('pt-br', 'Português (Brasil)')], default='auto', max_length=10, verbose_name='Language'),
|
||||||
|
),
|
||||||
|
]
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-02-19 13:44-0300\n"
|
"POT-Creation-Date: 2025-02-24 16:30-0300\n"
|
||||||
"PO-Revision-Date: 2025-02-12 06:58+0100\n"
|
"PO-Revision-Date: 2025-02-22 15:03+0100\n"
|
||||||
"Last-Translator: Dimitri Decrock <dimitri@fam-decrock.eu>\n"
|
"Last-Translator: Dimitri Decrock <dimitri@fam-decrock.eu>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: nl\n"
|
"Language: nl\n"
|
||||||
@@ -582,10 +582,8 @@ msgid "Services queued successfully"
|
|||||||
msgstr "Diensten succesvol in de wachtrij geplaatst"
|
msgstr "Diensten succesvol in de wachtrij geplaatst"
|
||||||
|
|
||||||
#: apps/dca/forms.py:65 apps/dca/forms.py:164
|
#: apps/dca/forms.py:65 apps/dca/forms.py:164
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Deleted transactions"
|
|
||||||
msgid "Create transaction"
|
msgid "Create transaction"
|
||||||
msgstr "Verwijderde verrichtingen"
|
msgstr "Maak verrichtingen"
|
||||||
|
|
||||||
#: apps/dca/forms.py:70 apps/transactions/forms.py:267
|
#: apps/dca/forms.py:70 apps/transactions/forms.py:267
|
||||||
msgid "From Account"
|
msgid "From Account"
|
||||||
@@ -602,31 +600,29 @@ msgstr "Uitgave Transactie"
|
|||||||
#: apps/dca/forms.py:120 apps/dca/forms.py:130
|
#: apps/dca/forms.py:120 apps/dca/forms.py:130
|
||||||
msgid "Type to search for a transaction to link to this entry"
|
msgid "Type to search for a transaction to link to this entry"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Type om een transactie te zoeken die aan dit item moet worden gekoppeld"
|
||||||
|
|
||||||
#: apps/dca/forms.py:126 apps/dca/models.py:177
|
#: apps/dca/forms.py:126 apps/dca/models.py:177
|
||||||
msgid "Income Transaction"
|
msgid "Income Transaction"
|
||||||
msgstr "Ontvangsten Transactie"
|
msgstr "Ontvangsten Transactie"
|
||||||
|
|
||||||
#: apps/dca/forms.py:210
|
#: apps/dca/forms.py:210
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Edit transaction"
|
|
||||||
msgid "Link transaction"
|
msgid "Link transaction"
|
||||||
msgstr "Bewerk verrichting"
|
msgstr "Koppel verrichting"
|
||||||
|
|
||||||
#: apps/dca/forms.py:279 apps/dca/forms.py:280 apps/dca/forms.py:285
|
#: apps/dca/forms.py:279 apps/dca/forms.py:280 apps/dca/forms.py:285
|
||||||
#: apps/dca/forms.py:289
|
#: apps/dca/forms.py:289
|
||||||
msgid "You must provide an account."
|
msgid "You must provide an account."
|
||||||
msgstr ""
|
msgstr "Je moet een account opgeven."
|
||||||
|
|
||||||
#: apps/dca/forms.py:294 apps/transactions/forms.py:414
|
#: apps/dca/forms.py:294 apps/transactions/forms.py:414
|
||||||
msgid "From and To accounts must be different."
|
msgid "From and To accounts must be different."
|
||||||
msgstr "Van en Naar rekening moeten verschillend zijn."
|
msgstr "Van en Naar rekening moeten verschillend zijn."
|
||||||
|
|
||||||
#: apps/dca/forms.py:308
|
#: apps/dca/forms.py:308
|
||||||
#, fuzzy, python-format
|
#, python-format
|
||||||
#| msgid "DCA Strategies"
|
|
||||||
msgid "DCA for %(strategy_name)s"
|
msgid "DCA for %(strategy_name)s"
|
||||||
msgstr "DCA Strategieën"
|
msgstr "DCA voor %(strategy_name)s"
|
||||||
|
|
||||||
#: apps/dca/models.py:17
|
#: apps/dca/models.py:17
|
||||||
msgid "Target Currency"
|
msgid "Target Currency"
|
||||||
@@ -749,7 +745,7 @@ msgstr "Regels"
|
|||||||
|
|
||||||
#: apps/export_app/forms.py:80 templates/cotton/transaction/item.html:56
|
#: apps/export_app/forms.py:80 templates/cotton/transaction/item.html:56
|
||||||
msgid "DCA"
|
msgid "DCA"
|
||||||
msgstr ""
|
msgstr "DCA"
|
||||||
|
|
||||||
#: apps/export_app/forms.py:86 apps/export_app/forms.py:147
|
#: apps/export_app/forms.py:86 apps/export_app/forms.py:147
|
||||||
#: templates/import_app/fragments/profiles/list.html:5
|
#: templates/import_app/fragments/profiles/list.html:5
|
||||||
@@ -759,18 +755,16 @@ msgstr "Profielen importeren"
|
|||||||
|
|
||||||
#: apps/export_app/forms.py:112 templates/export_app/fragments/export.html:5
|
#: apps/export_app/forms.py:112 templates/export_app/fragments/export.html:5
|
||||||
#: templates/export_app/pages/index.html:15
|
#: templates/export_app/pages/index.html:15
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Import"
|
|
||||||
msgid "Export"
|
msgid "Export"
|
||||||
msgstr "Importeer"
|
msgstr "Exporteer"
|
||||||
|
|
||||||
#: apps/export_app/forms.py:121
|
#: apps/export_app/forms.py:121
|
||||||
msgid "Import a ZIP file exported from WYGIWYH"
|
msgid "Import a ZIP file exported from WYGIWYH"
|
||||||
msgstr ""
|
msgstr "Importeer een ZIP-bestand geëxporteerd vanuit WYGIWYH"
|
||||||
|
|
||||||
#: apps/export_app/forms.py:122
|
#: apps/export_app/forms.py:122
|
||||||
msgid "ZIP File"
|
msgid "ZIP File"
|
||||||
msgstr ""
|
msgstr "ZIP-bestand"
|
||||||
|
|
||||||
#: apps/export_app/forms.py:138 apps/rules/models.py:16
|
#: apps/export_app/forms.py:138 apps/rules/models.py:16
|
||||||
msgid "Transaction rules"
|
msgid "Transaction rules"
|
||||||
@@ -793,22 +787,22 @@ msgstr "Herstel"
|
|||||||
|
|
||||||
#: apps/export_app/forms.py:187
|
#: apps/export_app/forms.py:187
|
||||||
msgid "Please upload either a ZIP file or at least one CSV file"
|
msgid "Please upload either a ZIP file or at least one CSV file"
|
||||||
msgstr ""
|
msgstr "Upload een ZIP-bestand of ten minste één CSV-bestand"
|
||||||
|
|
||||||
#: apps/export_app/views.py:169
|
#: apps/export_app/views.py:168
|
||||||
msgid "You have to select at least one export"
|
msgid "You have to select at least one export"
|
||||||
msgstr ""
|
msgstr "U moet ten minste één export selecteren"
|
||||||
|
|
||||||
#: apps/export_app/views.py:187
|
#: apps/export_app/views.py:186
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Tag updated successfully"
|
|
||||||
msgid "Data restored successfully"
|
msgid "Data restored successfully"
|
||||||
msgstr "Label succesvol bijgewerkt"
|
msgstr "Gegevens succesvol hersteld"
|
||||||
|
|
||||||
#: apps/export_app/views.py:199
|
#: apps/export_app/views.py:198
|
||||||
msgid ""
|
msgid ""
|
||||||
"There was an error restoring your data. Check the logs for more details."
|
"There was an error restoring your data. Check the logs for more details."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"Er is een fout opgetreden bij het herstellen van uw gegevens. Controleer de "
|
||||||
|
"logboeken voor meer details."
|
||||||
|
|
||||||
#: apps/import_app/forms.py:49
|
#: apps/import_app/forms.py:49
|
||||||
msgid "Select a file"
|
msgid "Select a file"
|
||||||
@@ -886,22 +880,20 @@ msgstr "Run met succes verwijderd"
|
|||||||
|
|
||||||
#: apps/insights/forms.py:119 apps/insights/utils/sankey.py:36
|
#: apps/insights/forms.py:119 apps/insights/utils/sankey.py:36
|
||||||
#: apps/insights/utils/sankey.py:167
|
#: apps/insights/utils/sankey.py:167
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Categories"
|
|
||||||
msgid "Uncategorized"
|
msgid "Uncategorized"
|
||||||
msgstr "Categorieën"
|
msgstr "Ongecategoriseerd"
|
||||||
|
|
||||||
#: apps/insights/utils/category_explorer.py:70
|
#: apps/insights/utils/category_explorer.py:66
|
||||||
#: apps/insights/utils/category_explorer.py:153
|
#: apps/insights/utils/category_explorer.py:145
|
||||||
#: templates/cotton/ui/percentage_distribution.html:10
|
#: templates/cotton/ui/percentage_distribution.html:10
|
||||||
#: templates/cotton/ui/percentage_distribution.html:14
|
#: templates/cotton/ui/percentage_distribution.html:14
|
||||||
#: templates/insights/fragments/category_explorer/charts/account.html:60
|
#: templates/insights/fragments/category_explorer/charts/account.html:72
|
||||||
#: templates/insights/fragments/category_explorer/charts/currency.html:60
|
#: templates/insights/fragments/category_explorer/charts/currency.html:72
|
||||||
msgid "Current Income"
|
msgid "Current Income"
|
||||||
msgstr "Huidige inkomsten"
|
msgstr "Huidige inkomsten"
|
||||||
|
|
||||||
#: apps/insights/utils/category_explorer.py:74
|
#: apps/insights/utils/category_explorer.py:70
|
||||||
#: apps/insights/utils/category_explorer.py:157
|
#: apps/insights/utils/category_explorer.py:149
|
||||||
#: templates/cotton/ui/percentage_distribution.html:24
|
#: templates/cotton/ui/percentage_distribution.html:24
|
||||||
#: templates/cotton/ui/percentage_distribution.html:28
|
#: templates/cotton/ui/percentage_distribution.html:28
|
||||||
#: templates/insights/fragments/category_explorer/charts/account.html:66
|
#: templates/insights/fragments/category_explorer/charts/account.html:66
|
||||||
@@ -909,30 +901,28 @@ msgstr "Huidige inkomsten"
|
|||||||
msgid "Current Expenses"
|
msgid "Current Expenses"
|
||||||
msgstr "Huidige uitgaven"
|
msgstr "Huidige uitgaven"
|
||||||
|
|
||||||
#: apps/insights/utils/category_explorer.py:78
|
#: apps/insights/utils/category_explorer.py:74
|
||||||
#: apps/insights/utils/category_explorer.py:161
|
#: apps/insights/utils/category_explorer.py:153
|
||||||
#: templates/cotton/ui/percentage_distribution.html:3
|
#: templates/cotton/ui/percentage_distribution.html:3
|
||||||
#: templates/cotton/ui/percentage_distribution.html:7
|
#: templates/cotton/ui/percentage_distribution.html:7
|
||||||
#: templates/insights/fragments/category_explorer/charts/account.html:72
|
#: templates/insights/fragments/category_explorer/charts/account.html:78
|
||||||
#: templates/insights/fragments/category_explorer/charts/currency.html:72
|
#: templates/insights/fragments/category_explorer/charts/currency.html:78
|
||||||
msgid "Projected Income"
|
msgid "Projected Income"
|
||||||
msgstr "Verwachte inkomsten"
|
msgstr "Verwachte inkomsten"
|
||||||
|
|
||||||
#: apps/insights/utils/category_explorer.py:82
|
#: apps/insights/utils/category_explorer.py:78
|
||||||
#: apps/insights/utils/category_explorer.py:165
|
#: apps/insights/utils/category_explorer.py:157
|
||||||
#: templates/cotton/ui/percentage_distribution.html:17
|
#: templates/cotton/ui/percentage_distribution.html:17
|
||||||
#: templates/cotton/ui/percentage_distribution.html:21
|
#: templates/cotton/ui/percentage_distribution.html:21
|
||||||
#: templates/insights/fragments/category_explorer/charts/account.html:78
|
#: templates/insights/fragments/category_explorer/charts/account.html:60
|
||||||
#: templates/insights/fragments/category_explorer/charts/currency.html:78
|
#: templates/insights/fragments/category_explorer/charts/currency.html:60
|
||||||
msgid "Projected Expenses"
|
msgid "Projected Expenses"
|
||||||
msgstr "Verwachte uitgaven"
|
msgstr "Verwachte uitgaven"
|
||||||
|
|
||||||
#: apps/insights/utils/sankey.py:133 apps/insights/utils/sankey.py:134
|
#: apps/insights/utils/sankey.py:133 apps/insights/utils/sankey.py:134
|
||||||
#: apps/insights/utils/sankey.py:263 apps/insights/utils/sankey.py:264
|
#: apps/insights/utils/sankey.py:263 apps/insights/utils/sankey.py:264
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Save"
|
|
||||||
msgid "Saved"
|
msgid "Saved"
|
||||||
msgstr "Opslaan"
|
msgstr "Opgeslagen"
|
||||||
|
|
||||||
#: apps/rules/forms.py:20
|
#: apps/rules/forms.py:20
|
||||||
msgid "Run on creation"
|
msgid "Run on creation"
|
||||||
@@ -1085,13 +1075,12 @@ msgid "Filter"
|
|||||||
msgstr "Filter"
|
msgstr "Filter"
|
||||||
|
|
||||||
#: apps/rules/models.py:85
|
#: apps/rules/models.py:85
|
||||||
#, fuzzy
|
|
||||||
msgid ""
|
msgid ""
|
||||||
"Generic expression to enable or disable execution. Should evaluate to True "
|
"Generic expression to enable or disable execution. Should evaluate to True "
|
||||||
"or False"
|
"or False"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Generieke expressie om uitvoering in of uit te schakelen. Moet evalueren "
|
"Generieke expressie om uitvoering in of uit te schakelen. Moet evalueren "
|
||||||
"naar True of False"
|
"naar Waar of Onwaar"
|
||||||
|
|
||||||
#: apps/rules/models.py:289
|
#: apps/rules/models.py:289
|
||||||
msgid "Update or create transaction action"
|
msgid "Update or create transaction action"
|
||||||
@@ -1296,16 +1285,12 @@ msgid "No tags"
|
|||||||
msgstr "Geen labels"
|
msgstr "Geen labels"
|
||||||
|
|
||||||
#: apps/transactions/models.py:324
|
#: apps/transactions/models.py:324
|
||||||
#, fuzzy
|
|
||||||
#| msgid "No categories"
|
|
||||||
msgid "No category"
|
msgid "No category"
|
||||||
msgstr "Geen categorieën"
|
msgstr "Geen categorie"
|
||||||
|
|
||||||
#: apps/transactions/models.py:326
|
#: apps/transactions/models.py:326
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Description"
|
|
||||||
msgid "No description"
|
msgid "No description"
|
||||||
msgstr "Beschrijving"
|
msgstr "Geen Beschrijving"
|
||||||
|
|
||||||
#: apps/transactions/models.py:332
|
#: apps/transactions/models.py:332
|
||||||
msgid "Yearly"
|
msgid "Yearly"
|
||||||
@@ -1910,6 +1895,7 @@ msgstr "Sluiten"
|
|||||||
|
|
||||||
#: templates/cotton/config/search.html:6
|
#: templates/cotton/config/search.html:6
|
||||||
#: templates/import_app/fragments/profiles/list_presets.html:13
|
#: templates/import_app/fragments/profiles/list_presets.html:13
|
||||||
|
#: templates/monthly_overview/pages/overview.html:177
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Zoeken"
|
msgstr "Zoeken"
|
||||||
|
|
||||||
@@ -2255,7 +2241,7 @@ msgstr "Geen diensten ingesteld"
|
|||||||
|
|
||||||
#: templates/export_app/pages/index.html:4 templates/includes/navbar.html:136
|
#: templates/export_app/pages/index.html:4 templates/includes/navbar.html:136
|
||||||
msgid "Export and Restore"
|
msgid "Export and Restore"
|
||||||
msgstr ""
|
msgstr "Exporteren en Herstellen"
|
||||||
|
|
||||||
#: templates/import_app/fragments/profiles/add.html:6
|
#: templates/import_app/fragments/profiles/add.html:6
|
||||||
msgid "Add new import profile"
|
msgid "Add new import profile"
|
||||||
@@ -2360,7 +2346,7 @@ msgstr "Huidige"
|
|||||||
|
|
||||||
#: templates/includes/navbar.html:50
|
#: templates/includes/navbar.html:50
|
||||||
msgid "Insights"
|
msgid "Insights"
|
||||||
msgstr ""
|
msgstr "Inzichten"
|
||||||
|
|
||||||
#: templates/includes/navbar.html:66
|
#: templates/includes/navbar.html:66
|
||||||
msgid "Trash Can"
|
msgid "Trash Can"
|
||||||
@@ -2436,8 +2422,8 @@ msgstr "Annuleer"
|
|||||||
msgid "Confirm"
|
msgid "Confirm"
|
||||||
msgstr "Bevestig"
|
msgstr "Bevestig"
|
||||||
|
|
||||||
#: templates/insights/fragments/category_explorer/charts/account.html:99
|
#: templates/insights/fragments/category_explorer/charts/account.html:100
|
||||||
#: templates/insights/fragments/category_explorer/charts/currency.html:91
|
#: templates/insights/fragments/category_explorer/charts/currency.html:92
|
||||||
#: templates/monthly_overview/fragments/monthly_account_summary.html:14
|
#: templates/monthly_overview/fragments/monthly_account_summary.html:14
|
||||||
#: templates/monthly_overview/fragments/monthly_currency_summary.html:13
|
#: templates/monthly_overview/fragments/monthly_currency_summary.html:13
|
||||||
#: templates/transactions/fragments/all_account_summary.html:14
|
#: templates/transactions/fragments/all_account_summary.html:14
|
||||||
@@ -2451,27 +2437,35 @@ msgstr "Geen informatie om weer te geven"
|
|||||||
|
|
||||||
#: templates/insights/fragments/category_explorer/index.html:14
|
#: templates/insights/fragments/category_explorer/index.html:14
|
||||||
msgid "Income/Expense by Account"
|
msgid "Income/Expense by Account"
|
||||||
msgstr ""
|
msgstr "Inkomsten/uitgaven per rekening"
|
||||||
|
|
||||||
#: templates/insights/fragments/category_explorer/index.html:26
|
#: templates/insights/fragments/category_explorer/index.html:26
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Exchange Currency"
|
|
||||||
msgid "Income/Expense by Currency"
|
msgid "Income/Expense by Currency"
|
||||||
msgstr "Eenheid Wisselgeld"
|
msgstr "Inkomsten/uitgaven per Munteenheid"
|
||||||
|
|
||||||
|
#: templates/insights/fragments/late_transactions.html:15
|
||||||
|
msgid "All good!"
|
||||||
|
msgstr "Allemaal goed!"
|
||||||
|
|
||||||
|
#: templates/insights/fragments/late_transactions.html:16
|
||||||
|
msgid "No late transactions"
|
||||||
|
msgstr "Geen betalingsachterstanden"
|
||||||
|
|
||||||
|
#: templates/insights/fragments/latest_transactions.html:14
|
||||||
|
msgid "No recent transactions"
|
||||||
|
msgstr "Geen recente betalingen"
|
||||||
|
|
||||||
#: templates/insights/fragments/sankey.html:93
|
#: templates/insights/fragments/sankey.html:93
|
||||||
msgid "From"
|
msgid "From"
|
||||||
msgstr ""
|
msgstr "Van"
|
||||||
|
|
||||||
#: templates/insights/fragments/sankey.html:96
|
#: templates/insights/fragments/sankey.html:96
|
||||||
msgid "Percentage"
|
msgid "Percentage"
|
||||||
msgstr ""
|
msgstr "Percentage"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:35
|
#: templates/insights/pages/index.html:35
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Monthly"
|
|
||||||
msgid "Month"
|
msgid "Month"
|
||||||
msgstr "Maandelijks"
|
msgstr "Maand"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:38
|
#: templates/insights/pages/index.html:38
|
||||||
#: templates/yearly_overview/pages/overview_by_account.html:61
|
#: templates/yearly_overview/pages/overview_by_account.html:61
|
||||||
@@ -2480,38 +2474,36 @@ msgid "Year"
|
|||||||
msgstr "Jaar"
|
msgstr "Jaar"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:43
|
#: templates/insights/pages/index.html:43
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Unchanged"
|
|
||||||
msgid "Month Range"
|
msgid "Month Range"
|
||||||
msgstr "Ongewijzigd"
|
msgstr "Maand Bereik"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:48
|
#: templates/insights/pages/index.html:48
|
||||||
msgid "Year Range"
|
msgid "Year Range"
|
||||||
msgstr ""
|
msgstr "Jaar Bereik"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:53
|
#: templates/insights/pages/index.html:53
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Date and Time"
|
|
||||||
msgid "Date Range"
|
msgid "Date Range"
|
||||||
msgstr "Datum en Tijd"
|
msgstr "Datum Bereik"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:82
|
#: templates/insights/pages/index.html:81
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Account"
|
|
||||||
msgid "Account Flow"
|
msgid "Account Flow"
|
||||||
msgstr "Rekening"
|
msgstr "Rekeningstroom"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:89
|
#: templates/insights/pages/index.html:88
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Currency Code"
|
|
||||||
msgid "Currency Flow"
|
msgid "Currency Flow"
|
||||||
msgstr "Munteenheids Code"
|
msgstr "Geldstroom"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:96
|
#: templates/insights/pages/index.html:95
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Category name"
|
|
||||||
msgid "Category Explorer"
|
msgid "Category Explorer"
|
||||||
msgstr "Naam van categorie"
|
msgstr "Categorie Verkenner"
|
||||||
|
|
||||||
|
#: templates/insights/pages/index.html:102
|
||||||
|
msgid "Late Transactions"
|
||||||
|
msgstr "Betalingsachterstanden"
|
||||||
|
|
||||||
|
#: templates/insights/pages/index.html:108
|
||||||
|
msgid "Latest Transactions"
|
||||||
|
msgstr "Laatste Verrichtingen"
|
||||||
|
|
||||||
#: templates/installment_plans/fragments/add.html:5
|
#: templates/installment_plans/fragments/add.html:5
|
||||||
msgid "Add installment plan"
|
msgid "Add installment plan"
|
||||||
@@ -2875,6 +2867,26 @@ msgstr "Bedragen tonen"
|
|||||||
msgid "Yearly Overview"
|
msgid "Yearly Overview"
|
||||||
msgstr "Jaaroverzicht"
|
msgstr "Jaaroverzicht"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "From Amount"
|
||||||
|
#~ msgid "Principal Amount"
|
||||||
|
#~ msgstr "Van Bedrag"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Interval"
|
||||||
|
#~ msgid "Interest"
|
||||||
|
#~ msgstr "Interval"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Management"
|
||||||
|
#~ msgid "Loan Payment"
|
||||||
|
#~ msgstr "Beheer"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Management"
|
||||||
|
#~ msgid "Loan Payments"
|
||||||
|
#~ msgstr "Beheer"
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#~| msgid "Installment Plans"
|
#~| msgid "Installment Plans"
|
||||||
#~ msgid "Installment Planss"
|
#~ msgid "Installment Planss"
|
||||||
@@ -2935,11 +2947,6 @@ msgstr "Jaaroverzicht"
|
|||||||
#~ msgid "Reference Date Operator"
|
#~ msgid "Reference Date Operator"
|
||||||
#~ msgstr "Referentiedatum vanaf"
|
#~ msgstr "Referentiedatum vanaf"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
#~| msgid "From Amount"
|
|
||||||
#~ msgid "Search Amount"
|
|
||||||
#~ msgstr "Van Bedrag"
|
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#~| msgid "Amount max"
|
#~| msgid "Amount max"
|
||||||
#~ msgid "Amount Operator"
|
#~ msgid "Amount Operator"
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-02-19 13:44-0300\n"
|
"POT-Creation-Date: 2025-02-24 16:30-0300\n"
|
||||||
"PO-Revision-Date: 2025-02-19 13:50-0300\n"
|
"PO-Revision-Date: 2025-02-19 23:06-0300\n"
|
||||||
"Last-Translator: Herculino Trotta\n"
|
"Last-Translator: Herculino Trotta\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: pt_BR\n"
|
"Language: pt_BR\n"
|
||||||
@@ -774,7 +774,7 @@ msgstr "Ação de editar de transação"
|
|||||||
|
|
||||||
#: apps/export_app/forms.py:143 apps/rules/models.py:290
|
#: apps/export_app/forms.py:143 apps/rules/models.py:290
|
||||||
msgid "Update or create transaction actions"
|
msgid "Update or create transaction actions"
|
||||||
msgstr "Ações de atualizar ou criar transação "
|
msgstr "Ações de atualizar ou criar transação"
|
||||||
|
|
||||||
#: apps/export_app/forms.py:176 templates/cotton/transaction/item.html:158
|
#: apps/export_app/forms.py:176 templates/cotton/transaction/item.html:158
|
||||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:47
|
#: templates/cotton/ui/deleted_transactions_action_bar.html:47
|
||||||
@@ -787,15 +787,15 @@ msgstr "Restaurar"
|
|||||||
msgid "Please upload either a ZIP file or at least one CSV file"
|
msgid "Please upload either a ZIP file or at least one CSV file"
|
||||||
msgstr "Carregue um arquivo ZIP ou pelo menos um arquivo CSV"
|
msgstr "Carregue um arquivo ZIP ou pelo menos um arquivo CSV"
|
||||||
|
|
||||||
#: apps/export_app/views.py:169
|
#: apps/export_app/views.py:168
|
||||||
msgid "You have to select at least one export"
|
msgid "You have to select at least one export"
|
||||||
msgstr "É necessário selecionar pelo menos uma exportação"
|
msgstr "É necessário selecionar pelo menos uma exportação"
|
||||||
|
|
||||||
#: apps/export_app/views.py:187
|
#: apps/export_app/views.py:186
|
||||||
msgid "Data restored successfully"
|
msgid "Data restored successfully"
|
||||||
msgstr "Dados restaurados com sucesso"
|
msgstr "Dados restaurados com sucesso"
|
||||||
|
|
||||||
#: apps/export_app/views.py:199
|
#: apps/export_app/views.py:198
|
||||||
msgid ""
|
msgid ""
|
||||||
"There was an error restoring your data. Check the logs for more details."
|
"There was an error restoring your data. Check the logs for more details."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -881,17 +881,17 @@ msgstr "Importação apagada com sucesso"
|
|||||||
msgid "Uncategorized"
|
msgid "Uncategorized"
|
||||||
msgstr "Sem categoria"
|
msgstr "Sem categoria"
|
||||||
|
|
||||||
#: apps/insights/utils/category_explorer.py:70
|
#: apps/insights/utils/category_explorer.py:66
|
||||||
#: apps/insights/utils/category_explorer.py:153
|
#: apps/insights/utils/category_explorer.py:145
|
||||||
#: templates/cotton/ui/percentage_distribution.html:10
|
#: templates/cotton/ui/percentage_distribution.html:10
|
||||||
#: templates/cotton/ui/percentage_distribution.html:14
|
#: templates/cotton/ui/percentage_distribution.html:14
|
||||||
#: templates/insights/fragments/category_explorer/charts/account.html:60
|
#: templates/insights/fragments/category_explorer/charts/account.html:72
|
||||||
#: templates/insights/fragments/category_explorer/charts/currency.html:60
|
#: templates/insights/fragments/category_explorer/charts/currency.html:72
|
||||||
msgid "Current Income"
|
msgid "Current Income"
|
||||||
msgstr "Renda Atual"
|
msgstr "Renda Atual"
|
||||||
|
|
||||||
#: apps/insights/utils/category_explorer.py:74
|
#: apps/insights/utils/category_explorer.py:70
|
||||||
#: apps/insights/utils/category_explorer.py:157
|
#: apps/insights/utils/category_explorer.py:149
|
||||||
#: templates/cotton/ui/percentage_distribution.html:24
|
#: templates/cotton/ui/percentage_distribution.html:24
|
||||||
#: templates/cotton/ui/percentage_distribution.html:28
|
#: templates/cotton/ui/percentage_distribution.html:28
|
||||||
#: templates/insights/fragments/category_explorer/charts/account.html:66
|
#: templates/insights/fragments/category_explorer/charts/account.html:66
|
||||||
@@ -899,21 +899,21 @@ msgstr "Renda Atual"
|
|||||||
msgid "Current Expenses"
|
msgid "Current Expenses"
|
||||||
msgstr "Despesas Atuais"
|
msgstr "Despesas Atuais"
|
||||||
|
|
||||||
#: apps/insights/utils/category_explorer.py:78
|
#: apps/insights/utils/category_explorer.py:74
|
||||||
#: apps/insights/utils/category_explorer.py:161
|
#: apps/insights/utils/category_explorer.py:153
|
||||||
#: templates/cotton/ui/percentage_distribution.html:3
|
#: templates/cotton/ui/percentage_distribution.html:3
|
||||||
#: templates/cotton/ui/percentage_distribution.html:7
|
#: templates/cotton/ui/percentage_distribution.html:7
|
||||||
#: templates/insights/fragments/category_explorer/charts/account.html:72
|
#: templates/insights/fragments/category_explorer/charts/account.html:78
|
||||||
#: templates/insights/fragments/category_explorer/charts/currency.html:72
|
#: templates/insights/fragments/category_explorer/charts/currency.html:78
|
||||||
msgid "Projected Income"
|
msgid "Projected Income"
|
||||||
msgstr "Renda Prevista"
|
msgstr "Renda Prevista"
|
||||||
|
|
||||||
#: apps/insights/utils/category_explorer.py:82
|
#: apps/insights/utils/category_explorer.py:78
|
||||||
#: apps/insights/utils/category_explorer.py:165
|
#: apps/insights/utils/category_explorer.py:157
|
||||||
#: templates/cotton/ui/percentage_distribution.html:17
|
#: templates/cotton/ui/percentage_distribution.html:17
|
||||||
#: templates/cotton/ui/percentage_distribution.html:21
|
#: templates/cotton/ui/percentage_distribution.html:21
|
||||||
#: templates/insights/fragments/category_explorer/charts/account.html:78
|
#: templates/insights/fragments/category_explorer/charts/account.html:60
|
||||||
#: templates/insights/fragments/category_explorer/charts/currency.html:78
|
#: templates/insights/fragments/category_explorer/charts/currency.html:60
|
||||||
msgid "Projected Expenses"
|
msgid "Projected Expenses"
|
||||||
msgstr "Despesas Previstas"
|
msgstr "Despesas Previstas"
|
||||||
|
|
||||||
@@ -1082,7 +1082,7 @@ msgstr ""
|
|||||||
|
|
||||||
#: apps/rules/models.py:289
|
#: apps/rules/models.py:289
|
||||||
msgid "Update or create transaction action"
|
msgid "Update or create transaction action"
|
||||||
msgstr " Ação de atualizar ou criar transação"
|
msgstr "Ação de atualizar ou criar transação"
|
||||||
|
|
||||||
#: apps/rules/views.py:52
|
#: apps/rules/views.py:52
|
||||||
msgid "Rule deactivated successfully"
|
msgid "Rule deactivated successfully"
|
||||||
@@ -1892,6 +1892,7 @@ msgstr "Fechar"
|
|||||||
|
|
||||||
#: templates/cotton/config/search.html:6
|
#: templates/cotton/config/search.html:6
|
||||||
#: templates/import_app/fragments/profiles/list_presets.html:13
|
#: templates/import_app/fragments/profiles/list_presets.html:13
|
||||||
|
#: templates/monthly_overview/pages/overview.html:177
|
||||||
msgid "Search"
|
msgid "Search"
|
||||||
msgstr "Buscar"
|
msgstr "Buscar"
|
||||||
|
|
||||||
@@ -2419,8 +2420,8 @@ msgstr "Cancelar"
|
|||||||
msgid "Confirm"
|
msgid "Confirm"
|
||||||
msgstr "Confirmar"
|
msgstr "Confirmar"
|
||||||
|
|
||||||
#: templates/insights/fragments/category_explorer/charts/account.html:99
|
#: templates/insights/fragments/category_explorer/charts/account.html:100
|
||||||
#: templates/insights/fragments/category_explorer/charts/currency.html:91
|
#: templates/insights/fragments/category_explorer/charts/currency.html:92
|
||||||
#: templates/monthly_overview/fragments/monthly_account_summary.html:14
|
#: templates/monthly_overview/fragments/monthly_account_summary.html:14
|
||||||
#: templates/monthly_overview/fragments/monthly_currency_summary.html:13
|
#: templates/monthly_overview/fragments/monthly_currency_summary.html:13
|
||||||
#: templates/transactions/fragments/all_account_summary.html:14
|
#: templates/transactions/fragments/all_account_summary.html:14
|
||||||
@@ -2440,6 +2441,18 @@ msgstr "Gasto/Despesa por Conta"
|
|||||||
msgid "Income/Expense by Currency"
|
msgid "Income/Expense by Currency"
|
||||||
msgstr "Gasto/Despesa por Moeda"
|
msgstr "Gasto/Despesa por Moeda"
|
||||||
|
|
||||||
|
#: templates/insights/fragments/late_transactions.html:15
|
||||||
|
msgid "All good!"
|
||||||
|
msgstr "Tudo certo!"
|
||||||
|
|
||||||
|
#: templates/insights/fragments/late_transactions.html:16
|
||||||
|
msgid "No late transactions"
|
||||||
|
msgstr "Nenhuma transação atrasada"
|
||||||
|
|
||||||
|
#: templates/insights/fragments/latest_transactions.html:14
|
||||||
|
msgid "No recent transactions"
|
||||||
|
msgstr "Nenhuma transação recente"
|
||||||
|
|
||||||
#: templates/insights/fragments/sankey.html:93
|
#: templates/insights/fragments/sankey.html:93
|
||||||
msgid "From"
|
msgid "From"
|
||||||
msgstr "De"
|
msgstr "De"
|
||||||
@@ -2470,18 +2483,26 @@ msgstr "Intervalo de Ano"
|
|||||||
msgid "Date Range"
|
msgid "Date Range"
|
||||||
msgstr "Intervalo de Data"
|
msgstr "Intervalo de Data"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:82
|
#: templates/insights/pages/index.html:81
|
||||||
msgid "Account Flow"
|
msgid "Account Flow"
|
||||||
msgstr "Fluxo de Conta"
|
msgstr "Fluxo de Conta"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:89
|
#: templates/insights/pages/index.html:88
|
||||||
msgid "Currency Flow"
|
msgid "Currency Flow"
|
||||||
msgstr "Fluxo de Moeda"
|
msgstr "Fluxo de Moeda"
|
||||||
|
|
||||||
#: templates/insights/pages/index.html:96
|
#: templates/insights/pages/index.html:95
|
||||||
msgid "Category Explorer"
|
msgid "Category Explorer"
|
||||||
msgstr "Explorador de Categoria"
|
msgstr "Explorador de Categoria"
|
||||||
|
|
||||||
|
#: templates/insights/pages/index.html:102
|
||||||
|
msgid "Late Transactions"
|
||||||
|
msgstr "Transações Atrasadas"
|
||||||
|
|
||||||
|
#: templates/insights/pages/index.html:108
|
||||||
|
msgid "Latest Transactions"
|
||||||
|
msgstr "Últimas Transações"
|
||||||
|
|
||||||
#: templates/installment_plans/fragments/add.html:5
|
#: templates/installment_plans/fragments/add.html:5
|
||||||
msgid "Add installment plan"
|
msgid "Add installment plan"
|
||||||
msgstr "Adicionar parcelamento"
|
msgstr "Adicionar parcelamento"
|
||||||
@@ -2841,6 +2862,26 @@ msgstr "Mostrar valores"
|
|||||||
msgid "Yearly Overview"
|
msgid "Yearly Overview"
|
||||||
msgstr "Visão Anual"
|
msgstr "Visão Anual"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "From Amount"
|
||||||
|
#~ msgid "Principal Amount"
|
||||||
|
#~ msgstr "Quantia de origem"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Interval"
|
||||||
|
#~ msgid "Interest"
|
||||||
|
#~ msgstr "Intervalo"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Management"
|
||||||
|
#~ msgid "Loan Payment"
|
||||||
|
#~ msgstr "Gerenciar"
|
||||||
|
|
||||||
|
#, fuzzy
|
||||||
|
#~| msgid "Management"
|
||||||
|
#~ msgid "Loan Payments"
|
||||||
|
#~ msgstr "Gerenciar"
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#~| msgid "Installment Plans"
|
#~| msgid "Installment Plans"
|
||||||
#~ msgid "Installment Planss"
|
#~ msgid "Installment Planss"
|
||||||
@@ -2906,11 +2947,6 @@ msgstr "Visão Anual"
|
|||||||
#~ msgid "Reference Date Operator"
|
#~ msgid "Reference Date Operator"
|
||||||
#~ msgstr "Data de Referência de"
|
#~ msgstr "Data de Referência de"
|
||||||
|
|
||||||
#, fuzzy
|
|
||||||
#~| msgid "From Amount"
|
|
||||||
#~ msgid "Search Amount"
|
|
||||||
#~ msgstr "Quantia de origem"
|
|
||||||
|
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
#~| msgid "Amount max"
|
#~| msgid "Amount max"
|
||||||
#~ msgid "Amount Operator"
|
#~ msgid "Amount Operator"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<div class="row {% if not remove_padding %}p-5{% endif %}">
|
<div class="row {% if not remove_padding %}p-5{% endif %}">
|
||||||
<div class="col {% if not remove_padding %}p-5{% endif %}">
|
<div class="col {% if not remove_padding %}p-5{% endif %}">
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<i class="fa-solid fa-circle-xmark tw-text-6xl"></i>
|
<i class="{% if icon %}{{ icon }}{% else %}fa-solid fa-circle-xmark{% endif %} tw-text-6xl"></i>
|
||||||
<p class="lead mt-4 mb-0">{{ title }}</p>
|
<p class="lead mt-4 mb-0">{{ title }}</p>
|
||||||
<p class="tw-text-gray-500">{{ subtitle }}</p>
|
<p class="tw-text-gray-500">{{ subtitle }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -15,9 +15,9 @@
|
|||||||
_="on mouseover remove .tw-invisible from the first .transaction-actions in me end
|
_="on mouseover remove .tw-invisible from the first .transaction-actions in me end
|
||||||
on mouseout add .tw-invisible to the first .transaction-actions in me end">
|
on mouseout add .tw-invisible to the first .transaction-actions in me end">
|
||||||
<div class="row font-monospace tw-text-sm align-items-center">
|
<div class="row font-monospace tw-text-sm align-items-center">
|
||||||
<div class="col-lg-1 col-12 d-flex align-items-center tw-text-2xl lg:tw-text-xl text-lg-center text-center">
|
<div class="col-lg-auto col-12 d-flex align-items-center tw-text-2xl lg:tw-text-xl text-lg-center text-center p-0 ps-1">
|
||||||
{% if not transaction.deleted %}
|
{% if not transaction.deleted %}
|
||||||
<a class="text-decoration-none my-lg-3 mx-lg-3 mx-2 my-2 tw-text-gray-500"
|
<a class="text-decoration-none p-3 tw-text-gray-500"
|
||||||
title="{% if transaction.is_paid %}{% trans 'Paid' %}{% else %}{% trans 'Projected' %}{% endif %}"
|
title="{% if transaction.is_paid %}{% trans 'Paid' %}{% else %}{% trans 'Projected' %}{% endif %}"
|
||||||
role="button"
|
role="button"
|
||||||
hx-get="{% url 'transaction_pay' transaction_id=transaction.id %}"
|
hx-get="{% url 'transaction_pay' transaction_id=transaction.id %}"
|
||||||
@@ -27,14 +27,14 @@
|
|||||||
class="fa-regular fa-circle"></i>{% endif %}
|
class="fa-regular fa-circle"></i>{% endif %}
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="text-decoration-none my-lg-3 mx-lg-3 mx-2 my-2 tw-text-gray-500"
|
<div class="text-decoration-none p-3 tw-text-gray-500"
|
||||||
title="{% if transaction.is_paid %}{% trans 'Paid' %}{% else %}{% trans 'Projected' %}{% endif %}">
|
title="{% if transaction.is_paid %}{% trans 'Paid' %}{% else %}{% trans 'Projected' %}{% endif %}">
|
||||||
{% if transaction.is_paid %}<i class="fa-regular fa-circle-check"></i>{% else %}<i
|
{% if transaction.is_paid %}<i class="fa-regular fa-circle-check"></i>{% else %}<i
|
||||||
class="fa-regular fa-circle"></i>{% endif %}
|
class="fa-regular fa-circle"></i>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-8 col-12">
|
<div class="col-lg col-12">
|
||||||
{# Date#}
|
{# Date#}
|
||||||
<div class="row mb-2 mb-lg-1 tw-text-gray-400">
|
<div class="row mb-2 mb-lg-1 tw-text-gray-400">
|
||||||
<div class="col-auto pe-1"><i class="fa-solid fa-calendar fa-fw me-1 fa-xs"></i></div>
|
<div class="col-auto pe-1"><i class="fa-solid fa-calendar fa-fw me-1 fa-xs"></i></div>
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
{% endwith %}
|
{% endwith %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3 col-12 text-lg-end align-self-end">
|
<div class="col-lg-auto col-12 text-lg-end align-self-end">
|
||||||
<div class="main-amount mb-2 mb-lg-0">
|
<div class="main-amount mb-2 mb-lg-0">
|
||||||
<c-amount.display
|
<c-amount.display
|
||||||
:amount="transaction.amount"
|
:amount="transaction.amount"
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<div class="card tw-relative h-100 shadow">
|
<div class="card tw-relative h-100 shadow">
|
||||||
<div class="tw-absolute tw-h-8 tw-w-8 tw-right-2 tw-top-2 tw-bg-{{ color }}-300 tw-text-{{ color }}-800 text-center align-items-center d-flex justify-content-center rounded-2">
|
<div class="tw-absolute tw-h-8 tw-w-8 tw-right-2 tw-top-2 tw-bg-{{ color }}-300 tw-text-{{ color }}-800 text-center align-items-center d-flex justify-content-center rounded-2">
|
||||||
<i class="{{ icon }}"></i>
|
{% if icon %}<i class="{{ icon }}"></i>{% else %}<span class="fw-bold">{{ title.0 }}</span>{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="tw-text-{{ color }}-400 fw-bold tw-mr-[50px]" {{ attrs }}>{{ title }}{% if help_text %}{% include 'includes/help_icon.html' with content=help_text %}{% endif %}</h5>
|
<h5 class="tw-text-{{ color }}-400 fw-bold tw-mr-[50px]" {{ attrs }}>{{ title }}{% if help_text %}{% include 'includes/help_icon.html' with content=help_text %}{% endif %}</h5>
|
||||||
{{ slot }}
|
{{ slot }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -57,9 +57,9 @@
|
|||||||
labels: accountData.labels,
|
labels: accountData.labels,
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: "{% trans 'Current Income' %}",
|
label: "{% trans 'Projected Expenses' %}",
|
||||||
data: accountData.datasets[0].data,
|
data: accountData.datasets[3].data,
|
||||||
backgroundColor: '#4dde80',
|
backgroundColor: '#f8717180', // Added transparency
|
||||||
stack: 'stack0'
|
stack: 'stack0'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -68,18 +68,19 @@
|
|||||||
backgroundColor: '#f87171',
|
backgroundColor: '#f87171',
|
||||||
stack: 'stack0'
|
stack: 'stack0'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "{% trans 'Current Income' %}",
|
||||||
|
data: accountData.datasets[0].data,
|
||||||
|
backgroundColor: '#4dde80',
|
||||||
|
stack: 'stack0'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "{% trans 'Projected Income' %}",
|
label: "{% trans 'Projected Income' %}",
|
||||||
data: accountData.datasets[2].data,
|
data: accountData.datasets[2].data,
|
||||||
backgroundColor: '#4dde8080', // Added transparency
|
backgroundColor: '#4dde8080', // Added transparency
|
||||||
stack: 'stack0'
|
stack: 'stack0'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: "{% trans 'Projected Expenses' %}",
|
|
||||||
data: accountData.datasets[3].data,
|
|
||||||
backgroundColor: '#f8717180', // Added transparency
|
|
||||||
stack: 'stack0'
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
|
|||||||
@@ -57,9 +57,9 @@
|
|||||||
labels: currencyData.labels,
|
labels: currencyData.labels,
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: "{% trans 'Current Income' %}",
|
label: "{% trans 'Projected Expenses' %}",
|
||||||
data: currencyData.datasets[0].data,
|
data: currencyData.datasets[3].data,
|
||||||
backgroundColor: '#4dde80',
|
backgroundColor: '#f8717180', // Added transparency
|
||||||
stack: 'stack0'
|
stack: 'stack0'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -68,18 +68,19 @@
|
|||||||
backgroundColor: '#f87171',
|
backgroundColor: '#f87171',
|
||||||
stack: 'stack0'
|
stack: 'stack0'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "{% trans 'Current Income' %}",
|
||||||
|
data: currencyData.datasets[0].data,
|
||||||
|
backgroundColor: '#4dde80',
|
||||||
|
stack: 'stack0'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "{% trans 'Projected Income' %}",
|
label: "{% trans 'Projected Income' %}",
|
||||||
data: currencyData.datasets[2].data,
|
data: currencyData.datasets[2].data,
|
||||||
backgroundColor: '#4dde8080', // Added transparency
|
backgroundColor: '#4dde8080', // Added transparency
|
||||||
stack: 'stack0'
|
stack: 'stack0'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: "{% trans 'Projected Expenses' %}",
|
|
||||||
data: currencyData.datasets[3].data,
|
|
||||||
backgroundColor: '#f8717180', // Added transparency
|
|
||||||
stack: 'stack0'
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
options: chartOptions
|
options: chartOptions
|
||||||
|
|||||||
18
app/templates/insights/fragments/late_transactions.html
Normal file
18
app/templates/insights/fragments/late_transactions.html
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
||||||
|
<div hx-get="{% url 'insights_late_transactions' %}" hx-trigger="updated from:window" class="show-loading"
|
||||||
|
id="transactions-list" hx-swap="outerHTML">
|
||||||
|
{% if transactions %}
|
||||||
|
{% for transaction in transactions %}
|
||||||
|
<c-transaction.item :transaction="transaction"></c-transaction.item>
|
||||||
|
{% endfor %}
|
||||||
|
{# Floating bar #}
|
||||||
|
<c-ui.transactions-action-bar></c-ui.transactions-action-bar>
|
||||||
|
{% else %}
|
||||||
|
<c-msg.empty
|
||||||
|
icon="fa-regular fa-hourglass"
|
||||||
|
title="{% translate 'All good!' %}"
|
||||||
|
subtitle="{% translate "No late transactions" %}"></c-msg.empty>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
16
app/templates/insights/fragments/latest_transactions.html
Normal file
16
app/templates/insights/fragments/latest_transactions.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
|
||||||
|
<div hx-get="{% url 'insights_late_transactions' %}" hx-trigger="updated from:window" class="show-loading"
|
||||||
|
id="transactions-list" hx-swap="outerHTML">
|
||||||
|
{% if transactions %}
|
||||||
|
{% for transaction in transactions %}
|
||||||
|
<c-transaction.item :transaction="transaction"></c-transaction.item>
|
||||||
|
{% endfor %}
|
||||||
|
{# Floating bar #}
|
||||||
|
<c-ui.transactions-action-bar></c-ui.transactions-action-bar>
|
||||||
|
{% else %}
|
||||||
|
<c-msg.empty
|
||||||
|
title="{% translate 'No recent transactions' %}"></c-msg.empty>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
@@ -72,7 +72,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<hr class="mt-0">
|
|
||||||
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist"
|
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist"
|
||||||
aria-orientation="vertical">
|
aria-orientation="vertical">
|
||||||
<button class="nav-link" id="v-pills-tab" data-bs-toggle="pill" data-bs-target="#v-pills-content"
|
<button class="nav-link" id="v-pills-tab" data-bs-toggle="pill" data-bs-target="#v-pills-content"
|
||||||
@@ -95,6 +94,19 @@
|
|||||||
hx-indicator="#tab-content"
|
hx-indicator="#tab-content"
|
||||||
hx-target="#tab-content">{% trans 'Category Explorer' %}
|
hx-target="#tab-content">{% trans 'Category Explorer' %}
|
||||||
</button>
|
</button>
|
||||||
|
<hr>
|
||||||
|
<button class="nav-link" id="v-pills-tab" data-bs-toggle="pill" data-bs-target="#v-pills-content"
|
||||||
|
type="button" role="tab" aria-controls="v-pills-content" aria-selected="false"
|
||||||
|
hx-get="{% url 'insights_late_transactions' %}"
|
||||||
|
hx-indicator="#tab-content"
|
||||||
|
hx-target="#tab-content">{% trans 'Late Transactions' %}
|
||||||
|
</button>
|
||||||
|
<button class="nav-link" id="v-pills-tab" data-bs-toggle="pill" data-bs-target="#v-pills-content"
|
||||||
|
type="button" role="tab" aria-controls="v-pills-content" aria-selected="false"
|
||||||
|
hx-get="{% url 'insights_latest_transactions' %}"
|
||||||
|
hx-indicator="#tab-content"
|
||||||
|
hx-target="#tab-content">{% trans 'Latest Transactions' %}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="tw-cursor-pointer text-primary text-end"
|
<div class="tw-cursor-pointer text-primary text-end"
|
||||||
_="on click
|
_="on click
|
||||||
set from_value to #id_from_currency's value
|
set from_value to #id_from_currency's value
|
||||||
set to_value to #id_to_currency's value
|
set to_value to #id_to_currency's value
|
||||||
@@ -58,5 +58,39 @@
|
|||||||
<i class="fa-solid fa-rotate me-2"></i><span>{% trans 'Invert' %}</span>
|
<i class="fa-solid fa-rotate me-2"></i><span>{% trans 'Invert' %}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<hr>
|
||||||
|
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
|
||||||
|
{% for currency, data in rate_map.items %}
|
||||||
|
<div class="col">
|
||||||
|
<c-ui.info-card color="yellow" title="{{ currency }}">
|
||||||
|
{% for rate in data.rates.values %}
|
||||||
|
<div class="d-flex justify-content-between align-items-baseline mt-2">
|
||||||
|
<div class="text-end font-monospace">
|
||||||
|
<div class="tw-text-gray-400">
|
||||||
|
{# <c-amount.display#}
|
||||||
|
{# :amount="1"#}
|
||||||
|
{# :prefix="data.prefix"#}
|
||||||
|
{# :suffix="data.suffix"#}
|
||||||
|
{# :decimal_places="data.decimal_places"></c-amount.display>#}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="dotted-line flex-grow-1"></div>
|
||||||
|
{% if currency.income_projected != 0 %}
|
||||||
|
<div class="text-end font-monospace tw-text-green-400">
|
||||||
|
<c-amount.display
|
||||||
|
:amount="rate.rate"
|
||||||
|
:prefix="rate.prefix"
|
||||||
|
:suffix="rate.suffix"
|
||||||
|
:decimal_places="rate.decimal_places"></c-amount.display>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="text-end font-monospace">-</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</c-ui.info-card>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
@@ -174,7 +174,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="search" class="my-3">
|
<div id="search" class="my-3">
|
||||||
<label class="w-100">
|
<label class="w-100">
|
||||||
<input type="search" class="form-control" placeholder="Buscar" hx-preserve id="quick-search"
|
<input type="search" class="form-control" placeholder="{% translate 'Search' %}" hx-preserve id="quick-search"
|
||||||
_="on input or search or htmx:afterSwap from window
|
_="on input or search or htmx:afterSwap from window
|
||||||
if my value is empty
|
if my value is empty
|
||||||
trigger toggle on <.transactions-divider-collapse/>
|
trigger toggle on <.transactions-divider-collapse/>
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ import AirDatepicker from 'air-datepicker';
|
|||||||
import en from 'air-datepicker/locale/en';
|
import en from 'air-datepicker/locale/en';
|
||||||
import ptBr from 'air-datepicker/locale/pt-BR';
|
import ptBr from 'air-datepicker/locale/pt-BR';
|
||||||
import nl from 'air-datepicker/locale/nl';
|
import nl from 'air-datepicker/locale/nl';
|
||||||
|
import de from 'air-datepicker/locale/de';
|
||||||
import {createPopper} from '@popperjs/core';
|
import {createPopper} from '@popperjs/core';
|
||||||
|
|
||||||
const locales = {
|
const locales = {
|
||||||
'pt': ptBr,
|
'pt': ptBr,
|
||||||
'en': en,
|
'en': en,
|
||||||
'nl': nl
|
'nl': nl,
|
||||||
|
'de': de
|
||||||
};
|
};
|
||||||
|
|
||||||
function isMobileDevice() {
|
function isMobileDevice() {
|
||||||
@@ -43,7 +45,7 @@ window.DatePicker = function createDynamicDatePicker(element) {
|
|||||||
toggleSelected: element.dataset.toggleSelected === 'true',
|
toggleSelected: element.dataset.toggleSelected === 'true',
|
||||||
autoClose: element.dataset.autoClose === 'true',
|
autoClose: element.dataset.autoClose === 'true',
|
||||||
buttons: element.dataset.clearButton === 'true' ? ['clear', todayButton] : [todayButton],
|
buttons: element.dataset.clearButton === 'true' ? ['clear', todayButton] : [todayButton],
|
||||||
locale: locales[element.dataset.language],
|
locale: locales[element.dataset.language] || locales['en'],
|
||||||
onSelect: ({date, formattedDate, datepicker}) => {
|
onSelect: ({date, formattedDate, datepicker}) => {
|
||||||
const _event = new CustomEvent("change", {
|
const _event = new CustomEvent("change", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
@@ -117,7 +119,7 @@ window.MonthYearPicker = function createDynamicDatePicker(element) {
|
|||||||
toggleSelected: element.dataset.toggleSelected === 'true',
|
toggleSelected: element.dataset.toggleSelected === 'true',
|
||||||
autoClose: element.dataset.autoClose === 'true',
|
autoClose: element.dataset.autoClose === 'true',
|
||||||
buttons: element.dataset.clearButton === 'true' ? ['clear', todayButton] : [todayButton],
|
buttons: element.dataset.clearButton === 'true' ? ['clear', todayButton] : [todayButton],
|
||||||
locale: locales[element.dataset.language],
|
locale: locales[element.dataset.language] || locales['en'],
|
||||||
onSelect: ({date, formattedDate, datepicker}) => {
|
onSelect: ({date, formattedDate, datepicker}) => {
|
||||||
const _event = new CustomEvent("change", {
|
const _event = new CustomEvent("change", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
@@ -190,7 +192,7 @@ window.YearPicker = function createDynamicDatePicker(element) {
|
|||||||
toggleSelected: element.dataset.toggleSelected === 'true',
|
toggleSelected: element.dataset.toggleSelected === 'true',
|
||||||
autoClose: element.dataset.autoClose === 'true',
|
autoClose: element.dataset.autoClose === 'true',
|
||||||
buttons: element.dataset.clearButton === 'true' ? ['clear', todayButton] : [todayButton],
|
buttons: element.dataset.clearButton === 'true' ? ['clear', todayButton] : [todayButton],
|
||||||
locale: locales[element.dataset.language],
|
locale: locales[element.dataset.language] || locales['en'],
|
||||||
onSelect: ({date, formattedDate, datepicker}) => {
|
onSelect: ({date, formattedDate, datepicker}) => {
|
||||||
const _event = new CustomEvent("change", {
|
const _event = new CustomEvent("change", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user