mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-02-25 08:54:52 +01:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8312baaf45 | ||
|
|
4d346dc278 | ||
|
|
70ff7fab38 | ||
|
|
6947c6affd | ||
|
|
dcab83f936 | ||
|
|
b228e4ec26 | ||
|
|
4071a1301f | ||
|
|
5c9db10710 |
@@ -2,13 +2,15 @@ from import_export import fields, resources, widgets
|
||||
|
||||
from apps.accounts.models import Account
|
||||
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):
|
||||
exchange_currency = fields.Field(
|
||||
attribute="exchange_currency",
|
||||
column_name="exchange_currency",
|
||||
widget=widgets.ForeignKeyWidget(Currency, "name"),
|
||||
widget=SkipMissingForeignKeyWidget(Currency, "name"),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
@@ -26,6 +28,9 @@ class ExchangeRateResource(resources.ModelResource):
|
||||
column_name="to_currency",
|
||||
widget=widgets.ForeignKeyWidget(Currency, "name"),
|
||||
)
|
||||
rate = fields.Field(
|
||||
attribute="rate", column_name="rate", widget=UniversalDecimalWidget()
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = ExchangeRate
|
||||
|
||||
@@ -3,6 +3,7 @@ from import_export.widgets import ForeignKeyWidget
|
||||
|
||||
from apps.dca.models import DCAStrategy, DCAEntry
|
||||
from apps.currencies.models import Currency
|
||||
from apps.export_app.widgets.numbers import UniversalDecimalWidget
|
||||
|
||||
|
||||
class DCAStrategyResource(resources.ModelResource):
|
||||
@@ -22,5 +23,16 @@ class DCAStrategyResource(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:
|
||||
model = DCAEntry
|
||||
|
||||
@@ -13,6 +13,7 @@ from apps.transactions.models import (
|
||||
RecurringTransaction,
|
||||
InstallmentPlan,
|
||||
)
|
||||
from apps.export_app.widgets.numbers import UniversalDecimalWidget
|
||||
|
||||
|
||||
class TransactionResource(resources.ModelResource):
|
||||
@@ -44,6 +45,12 @@ class TransactionResource(resources.ModelResource):
|
||||
column_name="internal_id", attribute="internal_id"
|
||||
)
|
||||
|
||||
amount = fields.Field(
|
||||
attribute="amount",
|
||||
column_name="amount",
|
||||
widget=UniversalDecimalWidget(),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Transaction
|
||||
|
||||
@@ -91,6 +98,12 @@ class RecurringTransactionResource(resources.ModelResource):
|
||||
widget=AutoCreateManyToManyWidget(TransactionEntity, field="name"),
|
||||
)
|
||||
|
||||
amount = fields.Field(
|
||||
attribute="amount",
|
||||
column_name="amount",
|
||||
widget=UniversalDecimalWidget(),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = RecurringTransaction
|
||||
|
||||
@@ -120,5 +133,11 @@ class InstallmentPlanResource(resources.ModelResource):
|
||||
widget=AutoCreateManyToManyWidget(TransactionEntity, field="name"),
|
||||
)
|
||||
|
||||
installment_amount = fields.Field(
|
||||
attribute="installment_amount",
|
||||
column_name="installment_amount",
|
||||
widget=UniversalDecimalWidget(),
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = InstallmentPlan
|
||||
|
||||
@@ -240,11 +240,6 @@ def process_imports(request, cleaned_data):
|
||||
dataset = Dataset()
|
||||
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
|
||||
result = resource.import_data(
|
||||
dataset,
|
||||
@@ -265,6 +260,8 @@ def process_imports(request, cleaned_data):
|
||||
raise ImportError(f"Error importing {field_name}: {str(e)}")
|
||||
|
||||
with transaction.atomic():
|
||||
files = {}
|
||||
|
||||
if zip_file := cleaned_data.get("zip_file"):
|
||||
# Process ZIP file
|
||||
with zipfile.ZipFile(zip_file) as z:
|
||||
@@ -273,10 +270,12 @@ def process_imports(request, cleaned_data):
|
||||
with z.open(filename) as f:
|
||||
content = f.read().decode("utf-8")
|
||||
|
||||
for field_name, resource_class in import_order:
|
||||
if name == field_name:
|
||||
import_dataset(content, resource_class, field_name)
|
||||
break
|
||||
files[name] = content
|
||||
|
||||
for field_name, resource_class in import_order:
|
||||
if field_name in files.keys():
|
||||
content = files[field_name]
|
||||
import_dataset(content, resource_class, field_name)
|
||||
else:
|
||||
# Process individual files
|
||||
for field_name, resource_class in import_order:
|
||||
|
||||
@@ -9,3 +9,14 @@ class AutoCreateForeignKeyWidget(ForeignKeyWidget):
|
||||
except self.model.DoesNotExist:
|
||||
return self.model.objects.create(name=value)
|
||||
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,
|
||||
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(
|
||||
Sum(
|
||||
Case(
|
||||
When(type="IN", then="amount"),
|
||||
When(is_paid=True, then="amount"),
|
||||
When(type="IN", is_paid=True, then="amount"),
|
||||
default=Value(0),
|
||||
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(
|
||||
Sum(
|
||||
Case(
|
||||
When(type="EX", then=-F("amount")),
|
||||
When(is_paid=True, then="amount"),
|
||||
When(type="EX", is_paid=True, then=-F("amount")),
|
||||
default=Value(0),
|
||||
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(
|
||||
Sum(
|
||||
Case(
|
||||
When(type="IN", then="amount"),
|
||||
When(is_paid=False, then="amount"),
|
||||
When(type="IN", is_paid=False, then="amount"),
|
||||
default=Value(0),
|
||||
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(
|
||||
Sum(
|
||||
Case(
|
||||
When(type="EX", then=-F("amount")),
|
||||
When(is_paid=False, then="amount"),
|
||||
When(type="EX", is_paid=False, then=-F("amount")),
|
||||
default=Value(0),
|
||||
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(
|
||||
Sum(
|
||||
Case(
|
||||
When(type="IN", then="amount"),
|
||||
When(is_paid=True, then="amount"),
|
||||
When(type="IN", is_paid=True, then="amount"),
|
||||
default=Value(0),
|
||||
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(
|
||||
Sum(
|
||||
Case(
|
||||
When(type="EX", then=-F("amount")),
|
||||
When(is_paid=True, then="amount"),
|
||||
When(type="EX", is_paid=True, then=-F("amount")),
|
||||
default=Value(0),
|
||||
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(
|
||||
Sum(
|
||||
Case(
|
||||
When(type="IN", then="amount"),
|
||||
When(is_paid=False, then="amount"),
|
||||
When(type="IN", is_paid=False, then="amount"),
|
||||
default=Value(0),
|
||||
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(
|
||||
Sum(
|
||||
Case(
|
||||
When(type="EX", then=-F("amount")),
|
||||
When(is_paid=False, then="amount"),
|
||||
When(type="EX", is_paid=False, then=-F("amount")),
|
||||
default=Value(0),
|
||||
output_field=DecimalField(max_digits=42, decimal_places=30),
|
||||
)
|
||||
|
||||
@@ -22,7 +22,7 @@ from apps.insights.utils.sankey import (
|
||||
generate_sankey_data_by_currency,
|
||||
)
|
||||
from apps.insights.utils.transactions import get_transactions
|
||||
from apps.transactions.models import TransactionCategory
|
||||
from apps.transactions.models import TransactionCategory, Transaction
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -157,3 +157,31 @@ def category_sum_by_currency(request):
|
||||
"insights/fragments/category_explorer/charts/currency.html",
|
||||
{"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)[: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.utils.convert import convert
|
||||
from apps.mini_tools.forms import CurrencyConverterForm
|
||||
from apps.mini_tools.utils.exchange_rate_map import get_currency_exchange_map
|
||||
|
||||
|
||||
@login_required
|
||||
@@ -14,11 +15,13 @@ def unit_price_calculator(request):
|
||||
|
||||
@login_required
|
||||
def currency_converter(request):
|
||||
rate_map = get_currency_exchange_map()
|
||||
|
||||
form = CurrencyConverterForm()
|
||||
return render(
|
||||
request,
|
||||
"mini_tools/currency_converter/currency_converter.html",
|
||||
context={"form": form},
|
||||
context={"form": form, "rate_map": rate_map},
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-02-19 13:44-0300\n"
|
||||
"POT-Creation-Date: 2025-02-19 23:05-0300\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"
|
||||
@@ -773,15 +773,15 @@ msgstr ""
|
||||
msgid "Please upload either a ZIP file or at least one CSV file"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/views.py:169
|
||||
#: apps/export_app/views.py:168
|
||||
msgid "You have to select at least one export"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/views.py:187
|
||||
#: apps/export_app/views.py:186
|
||||
msgid "Data restored successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/views.py:199
|
||||
#: apps/export_app/views.py:198
|
||||
msgid ""
|
||||
"There was an error restoring your data. Check the logs for more details."
|
||||
msgstr ""
|
||||
@@ -865,17 +865,17 @@ msgstr ""
|
||||
msgid "Uncategorized"
|
||||
msgstr ""
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:70
|
||||
#: apps/insights/utils/category_explorer.py:153
|
||||
#: apps/insights/utils/category_explorer.py:66
|
||||
#: apps/insights/utils/category_explorer.py:145
|
||||
#: templates/cotton/ui/percentage_distribution.html:10
|
||||
#: templates/cotton/ui/percentage_distribution.html:14
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:60
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:60
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:72
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:72
|
||||
msgid "Current Income"
|
||||
msgstr ""
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:74
|
||||
#: apps/insights/utils/category_explorer.py:157
|
||||
#: apps/insights/utils/category_explorer.py:70
|
||||
#: apps/insights/utils/category_explorer.py:149
|
||||
#: templates/cotton/ui/percentage_distribution.html:24
|
||||
#: templates/cotton/ui/percentage_distribution.html:28
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:66
|
||||
@@ -883,21 +883,21 @@ msgstr ""
|
||||
msgid "Current Expenses"
|
||||
msgstr ""
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:78
|
||||
#: apps/insights/utils/category_explorer.py:161
|
||||
#: apps/insights/utils/category_explorer.py:74
|
||||
#: apps/insights/utils/category_explorer.py:153
|
||||
#: templates/cotton/ui/percentage_distribution.html:3
|
||||
#: templates/cotton/ui/percentage_distribution.html:7
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:72
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:72
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:78
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:78
|
||||
msgid "Projected Income"
|
||||
msgstr ""
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:82
|
||||
#: apps/insights/utils/category_explorer.py:165
|
||||
#: apps/insights/utils/category_explorer.py:78
|
||||
#: apps/insights/utils/category_explorer.py:157
|
||||
#: templates/cotton/ui/percentage_distribution.html:17
|
||||
#: templates/cotton/ui/percentage_distribution.html:21
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:78
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:78
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:60
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:60
|
||||
msgid "Projected Expenses"
|
||||
msgstr ""
|
||||
|
||||
@@ -2392,8 +2392,8 @@ msgstr ""
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:99
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:91
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:100
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:92
|
||||
#: templates/monthly_overview/fragments/monthly_account_summary.html:14
|
||||
#: templates/monthly_overview/fragments/monthly_currency_summary.html:13
|
||||
#: templates/transactions/fragments/all_account_summary.html:14
|
||||
@@ -2413,6 +2413,18 @@ msgstr ""
|
||||
msgid "Income/Expense by Currency"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/fragments/late_transactions.html:15
|
||||
msgid "All good!"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/fragments/late_transactions.html:16
|
||||
msgid "No late transactions"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/fragments/latest_transactions.html:14
|
||||
msgid "No recent transactions"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/fragments/sankey.html:93
|
||||
msgid "From"
|
||||
msgstr ""
|
||||
@@ -2443,18 +2455,26 @@ msgstr ""
|
||||
msgid "Date Range"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/pages/index.html:82
|
||||
#: templates/insights/pages/index.html:81
|
||||
msgid "Account Flow"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/pages/index.html:89
|
||||
#: templates/insights/pages/index.html:88
|
||||
msgid "Currency Flow"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/pages/index.html:96
|
||||
#: templates/insights/pages/index.html:95
|
||||
msgid "Category Explorer"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/pages/index.html:102
|
||||
msgid "Late Transactions"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/pages/index.html:108
|
||||
msgid "Latest Transactions"
|
||||
msgstr ""
|
||||
|
||||
#: templates/installment_plans/fragments/add.html:5
|
||||
msgid "Add installment plan"
|
||||
msgstr ""
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-02-19 13:44-0300\n"
|
||||
"POT-Creation-Date: 2025-02-19 23:05-0300\n"
|
||||
"PO-Revision-Date: 2025-02-12 06:58+0100\n"
|
||||
"Last-Translator: Dimitri Decrock <dimitri@fam-decrock.eu>\n"
|
||||
"Language-Team: \n"
|
||||
@@ -795,17 +795,17 @@ msgstr "Herstel"
|
||||
msgid "Please upload either a ZIP file or at least one CSV file"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/views.py:169
|
||||
#: apps/export_app/views.py:168
|
||||
msgid "You have to select at least one export"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/views.py:187
|
||||
#: apps/export_app/views.py:186
|
||||
#, fuzzy
|
||||
#| msgid "Tag updated successfully"
|
||||
msgid "Data restored successfully"
|
||||
msgstr "Label succesvol bijgewerkt"
|
||||
|
||||
#: apps/export_app/views.py:199
|
||||
#: apps/export_app/views.py:198
|
||||
msgid ""
|
||||
"There was an error restoring your data. Check the logs for more details."
|
||||
msgstr ""
|
||||
@@ -891,17 +891,17 @@ msgstr "Run met succes verwijderd"
|
||||
msgid "Uncategorized"
|
||||
msgstr "Categorieën"
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:70
|
||||
#: apps/insights/utils/category_explorer.py:153
|
||||
#: apps/insights/utils/category_explorer.py:66
|
||||
#: apps/insights/utils/category_explorer.py:145
|
||||
#: templates/cotton/ui/percentage_distribution.html:10
|
||||
#: templates/cotton/ui/percentage_distribution.html:14
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:60
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:60
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:72
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:72
|
||||
msgid "Current Income"
|
||||
msgstr "Huidige inkomsten"
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:74
|
||||
#: apps/insights/utils/category_explorer.py:157
|
||||
#: apps/insights/utils/category_explorer.py:70
|
||||
#: apps/insights/utils/category_explorer.py:149
|
||||
#: templates/cotton/ui/percentage_distribution.html:24
|
||||
#: templates/cotton/ui/percentage_distribution.html:28
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:66
|
||||
@@ -909,21 +909,21 @@ msgstr "Huidige inkomsten"
|
||||
msgid "Current Expenses"
|
||||
msgstr "Huidige uitgaven"
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:78
|
||||
#: apps/insights/utils/category_explorer.py:161
|
||||
#: apps/insights/utils/category_explorer.py:74
|
||||
#: apps/insights/utils/category_explorer.py:153
|
||||
#: templates/cotton/ui/percentage_distribution.html:3
|
||||
#: templates/cotton/ui/percentage_distribution.html:7
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:72
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:72
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:78
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:78
|
||||
msgid "Projected Income"
|
||||
msgstr "Verwachte inkomsten"
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:82
|
||||
#: apps/insights/utils/category_explorer.py:165
|
||||
#: apps/insights/utils/category_explorer.py:78
|
||||
#: apps/insights/utils/category_explorer.py:157
|
||||
#: templates/cotton/ui/percentage_distribution.html:17
|
||||
#: templates/cotton/ui/percentage_distribution.html:21
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:78
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:78
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:60
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:60
|
||||
msgid "Projected Expenses"
|
||||
msgstr "Verwachte uitgaven"
|
||||
|
||||
@@ -2436,8 +2436,8 @@ msgstr "Annuleer"
|
||||
msgid "Confirm"
|
||||
msgstr "Bevestig"
|
||||
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:99
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:91
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:100
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:92
|
||||
#: templates/monthly_overview/fragments/monthly_account_summary.html:14
|
||||
#: templates/monthly_overview/fragments/monthly_currency_summary.html:13
|
||||
#: templates/transactions/fragments/all_account_summary.html:14
|
||||
@@ -2459,6 +2459,22 @@ msgstr ""
|
||||
msgid "Income/Expense by Currency"
|
||||
msgstr "Eenheid Wisselgeld"
|
||||
|
||||
#: templates/insights/fragments/late_transactions.html:15
|
||||
msgid "All good!"
|
||||
msgstr ""
|
||||
|
||||
#: templates/insights/fragments/late_transactions.html:16
|
||||
#, fuzzy
|
||||
#| msgid "Filter transactions"
|
||||
msgid "No late transactions"
|
||||
msgstr "Filter verrichtingen"
|
||||
|
||||
#: templates/insights/fragments/latest_transactions.html:14
|
||||
#, fuzzy
|
||||
#| msgid "No recurring transactions"
|
||||
msgid "No recent transactions"
|
||||
msgstr "Geen terugkerende verrichtingen"
|
||||
|
||||
#: templates/insights/fragments/sankey.html:93
|
||||
msgid "From"
|
||||
msgstr ""
|
||||
@@ -2495,24 +2511,36 @@ msgstr ""
|
||||
msgid "Date Range"
|
||||
msgstr "Datum en Tijd"
|
||||
|
||||
#: templates/insights/pages/index.html:82
|
||||
#: templates/insights/pages/index.html:81
|
||||
#, fuzzy
|
||||
#| msgid "Account"
|
||||
msgid "Account Flow"
|
||||
msgstr "Rekening"
|
||||
|
||||
#: templates/insights/pages/index.html:89
|
||||
#: templates/insights/pages/index.html:88
|
||||
#, fuzzy
|
||||
#| msgid "Currency Code"
|
||||
msgid "Currency Flow"
|
||||
msgstr "Munteenheids Code"
|
||||
|
||||
#: templates/insights/pages/index.html:96
|
||||
#: templates/insights/pages/index.html:95
|
||||
#, fuzzy
|
||||
#| msgid "Category name"
|
||||
msgid "Category Explorer"
|
||||
msgstr "Naam van categorie"
|
||||
|
||||
#: templates/insights/pages/index.html:102
|
||||
#, fuzzy
|
||||
#| msgid "Transactions"
|
||||
msgid "Late Transactions"
|
||||
msgstr "Verrichtingen"
|
||||
|
||||
#: templates/insights/pages/index.html:108
|
||||
#, fuzzy
|
||||
#| msgid "Transactions"
|
||||
msgid "Latest Transactions"
|
||||
msgstr "Verrichtingen"
|
||||
|
||||
#: templates/installment_plans/fragments/add.html:5
|
||||
msgid "Add installment plan"
|
||||
msgstr "Afbetalingsplan toevoegen"
|
||||
|
||||
@@ -8,8 +8,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-02-19 13:44-0300\n"
|
||||
"PO-Revision-Date: 2025-02-19 13:50-0300\n"
|
||||
"POT-Creation-Date: 2025-02-19 23:05-0300\n"
|
||||
"PO-Revision-Date: 2025-02-19 23:06-0300\n"
|
||||
"Last-Translator: Herculino Trotta\n"
|
||||
"Language-Team: \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
|
||||
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
|
||||
#: 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"
|
||||
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"
|
||||
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"
|
||||
msgstr "Dados restaurados com sucesso"
|
||||
|
||||
#: apps/export_app/views.py:199
|
||||
#: apps/export_app/views.py:198
|
||||
msgid ""
|
||||
"There was an error restoring your data. Check the logs for more details."
|
||||
msgstr ""
|
||||
@@ -881,17 +881,17 @@ msgstr "Importação apagada com sucesso"
|
||||
msgid "Uncategorized"
|
||||
msgstr "Sem categoria"
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:70
|
||||
#: apps/insights/utils/category_explorer.py:153
|
||||
#: apps/insights/utils/category_explorer.py:66
|
||||
#: apps/insights/utils/category_explorer.py:145
|
||||
#: templates/cotton/ui/percentage_distribution.html:10
|
||||
#: templates/cotton/ui/percentage_distribution.html:14
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:60
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:60
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:72
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:72
|
||||
msgid "Current Income"
|
||||
msgstr "Renda Atual"
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:74
|
||||
#: apps/insights/utils/category_explorer.py:157
|
||||
#: apps/insights/utils/category_explorer.py:70
|
||||
#: apps/insights/utils/category_explorer.py:149
|
||||
#: templates/cotton/ui/percentage_distribution.html:24
|
||||
#: templates/cotton/ui/percentage_distribution.html:28
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:66
|
||||
@@ -899,21 +899,21 @@ msgstr "Renda Atual"
|
||||
msgid "Current Expenses"
|
||||
msgstr "Despesas Atuais"
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:78
|
||||
#: apps/insights/utils/category_explorer.py:161
|
||||
#: apps/insights/utils/category_explorer.py:74
|
||||
#: apps/insights/utils/category_explorer.py:153
|
||||
#: templates/cotton/ui/percentage_distribution.html:3
|
||||
#: templates/cotton/ui/percentage_distribution.html:7
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:72
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:72
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:78
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:78
|
||||
msgid "Projected Income"
|
||||
msgstr "Renda Prevista"
|
||||
|
||||
#: apps/insights/utils/category_explorer.py:82
|
||||
#: apps/insights/utils/category_explorer.py:165
|
||||
#: apps/insights/utils/category_explorer.py:78
|
||||
#: apps/insights/utils/category_explorer.py:157
|
||||
#: templates/cotton/ui/percentage_distribution.html:17
|
||||
#: templates/cotton/ui/percentage_distribution.html:21
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:78
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:78
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:60
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:60
|
||||
msgid "Projected Expenses"
|
||||
msgstr "Despesas Previstas"
|
||||
|
||||
@@ -1082,7 +1082,7 @@ msgstr ""
|
||||
|
||||
#: apps/rules/models.py:289
|
||||
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
|
||||
msgid "Rule deactivated successfully"
|
||||
@@ -2419,8 +2419,8 @@ msgstr "Cancelar"
|
||||
msgid "Confirm"
|
||||
msgstr "Confirmar"
|
||||
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:99
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:91
|
||||
#: templates/insights/fragments/category_explorer/charts/account.html:100
|
||||
#: templates/insights/fragments/category_explorer/charts/currency.html:92
|
||||
#: templates/monthly_overview/fragments/monthly_account_summary.html:14
|
||||
#: templates/monthly_overview/fragments/monthly_currency_summary.html:13
|
||||
#: templates/transactions/fragments/all_account_summary.html:14
|
||||
@@ -2440,6 +2440,18 @@ msgstr "Gasto/Despesa por Conta"
|
||||
msgid "Income/Expense by Currency"
|
||||
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
|
||||
msgid "From"
|
||||
msgstr "De"
|
||||
@@ -2470,18 +2482,26 @@ msgstr "Intervalo de Ano"
|
||||
msgid "Date Range"
|
||||
msgstr "Intervalo de Data"
|
||||
|
||||
#: templates/insights/pages/index.html:82
|
||||
#: templates/insights/pages/index.html:81
|
||||
msgid "Account Flow"
|
||||
msgstr "Fluxo de Conta"
|
||||
|
||||
#: templates/insights/pages/index.html:89
|
||||
#: templates/insights/pages/index.html:88
|
||||
msgid "Currency Flow"
|
||||
msgstr "Fluxo de Moeda"
|
||||
|
||||
#: templates/insights/pages/index.html:96
|
||||
#: templates/insights/pages/index.html:95
|
||||
msgid "Category Explorer"
|
||||
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
|
||||
msgid "Add installment plan"
|
||||
msgstr "Adicionar parcelamento"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="row {% if not remove_padding %}p-5{% endif %}">
|
||||
<div class="col {% if not remove_padding %}p-5{% endif %}">
|
||||
<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="tw-text-gray-500">{{ subtitle }}</p>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<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">
|
||||
<i class="{{ icon }}"></i>
|
||||
{% if icon %}<i class="{{ icon }}"></i>{% else %}<span class="fw-bold">{{ title.0 }}</span>{% endif %}
|
||||
</div>
|
||||
<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>
|
||||
{{ slot }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -57,9 +57,9 @@
|
||||
labels: accountData.labels,
|
||||
datasets: [
|
||||
{
|
||||
label: "{% trans 'Current Income' %}",
|
||||
data: accountData.datasets[0].data,
|
||||
backgroundColor: '#4dde80',
|
||||
label: "{% trans 'Projected Expenses' %}",
|
||||
data: accountData.datasets[3].data,
|
||||
backgroundColor: '#f8717180', // Added transparency
|
||||
stack: 'stack0'
|
||||
},
|
||||
{
|
||||
@@ -68,18 +68,19 @@
|
||||
backgroundColor: '#f87171',
|
||||
stack: 'stack0'
|
||||
},
|
||||
{
|
||||
label: "{% trans 'Current Income' %}",
|
||||
data: accountData.datasets[0].data,
|
||||
backgroundColor: '#4dde80',
|
||||
stack: 'stack0'
|
||||
},
|
||||
{
|
||||
label: "{% trans 'Projected Income' %}",
|
||||
data: accountData.datasets[2].data,
|
||||
backgroundColor: '#4dde8080', // Added transparency
|
||||
stack: 'stack0'
|
||||
},
|
||||
{
|
||||
label: "{% trans 'Projected Expenses' %}",
|
||||
data: accountData.datasets[3].data,
|
||||
backgroundColor: '#f8717180', // Added transparency
|
||||
stack: 'stack0'
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
options: {
|
||||
|
||||
@@ -57,9 +57,9 @@
|
||||
labels: currencyData.labels,
|
||||
datasets: [
|
||||
{
|
||||
label: "{% trans 'Current Income' %}",
|
||||
data: currencyData.datasets[0].data,
|
||||
backgroundColor: '#4dde80',
|
||||
label: "{% trans 'Projected Expenses' %}",
|
||||
data: currencyData.datasets[3].data,
|
||||
backgroundColor: '#f8717180', // Added transparency
|
||||
stack: 'stack0'
|
||||
},
|
||||
{
|
||||
@@ -68,18 +68,19 @@
|
||||
backgroundColor: '#f87171',
|
||||
stack: 'stack0'
|
||||
},
|
||||
{
|
||||
label: "{% trans 'Current Income' %}",
|
||||
data: currencyData.datasets[0].data,
|
||||
backgroundColor: '#4dde80',
|
||||
stack: 'stack0'
|
||||
},
|
||||
{
|
||||
label: "{% trans 'Projected Income' %}",
|
||||
data: currencyData.datasets[2].data,
|
||||
backgroundColor: '#4dde8080', // Added transparency
|
||||
stack: 'stack0'
|
||||
},
|
||||
{
|
||||
label: "{% trans 'Projected Expenses' %}",
|
||||
data: currencyData.datasets[3].data,
|
||||
backgroundColor: '#f8717180', // Added transparency
|
||||
stack: 'stack0'
|
||||
}
|
||||
|
||||
]
|
||||
},
|
||||
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>
|
||||
</form>
|
||||
</div>
|
||||
<hr class="mt-0">
|
||||
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist"
|
||||
aria-orientation="vertical">
|
||||
<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-target="#tab-content">{% trans 'Category Explorer' %}
|
||||
</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>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="tw-cursor-pointer text-primary text-end"
|
||||
<div class="tw-cursor-pointer text-primary text-end"
|
||||
_="on click
|
||||
set from_value to #id_from_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>
|
||||
</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>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user