From d207760ae936c66f4bceb6bdec7615a8e310ee19 Mon Sep 17 00:00:00 2001 From: Herculino Trotta Date: Wed, 5 Feb 2025 10:16:04 -0300 Subject: [PATCH 1/2] feat(currencies): add automatic exchange rate fetching Closes #123 --- app/apps/currencies/exchange_rates/fetcher.py | 14 +- .../currencies/exchange_rates/providers.py | 16 +- app/apps/currencies/forms.py | 50 ++- app/apps/currencies/models.py | 3 +- app/apps/currencies/tasks.py | 3 +- app/apps/currencies/urls.py | 30 ++ app/apps/currencies/views/__init__.py | 1 + .../views/exchange_rates_services.py | 122 ++++++ app/locale/de/LC_MESSAGES/django.po | 351 +++++++++++----- app/locale/nl/LC_MESSAGES/django.po | 386 +++++++++++++----- app/locale/pt_BR/LC_MESSAGES/django.po | 364 ++++++++++++----- .../fragments/add.html | 11 + .../fragments/edit.html | 11 + .../fragments/list.html | 81 ++++ .../fragments/table.html | 132 ++++++ .../exchange_rates_services/pages/index.html | 8 + app/templates/includes/navbar.html | 2 + app/templates/includes/toasts.html | 2 +- 18 files changed, 1244 insertions(+), 343 deletions(-) create mode 100644 app/apps/currencies/views/exchange_rates_services.py create mode 100644 app/templates/exchange_rates_services/fragments/add.html create mode 100644 app/templates/exchange_rates_services/fragments/edit.html create mode 100644 app/templates/exchange_rates_services/fragments/list.html create mode 100644 app/templates/exchange_rates_services/fragments/table.html create mode 100644 app/templates/exchange_rates_services/pages/index.html diff --git a/app/apps/currencies/exchange_rates/fetcher.py b/app/apps/currencies/exchange_rates/fetcher.py index d347e68..3e763c3 100644 --- a/app/apps/currencies/exchange_rates/fetcher.py +++ b/app/apps/currencies/exchange_rates/fetcher.py @@ -6,7 +6,8 @@ from django.utils import timezone from apps.currencies.exchange_rates.providers import ( SynthFinanceProvider, - CoinGeckoProvider, + CoinGeckoFreeProvider, + CoinGeckoProProvider, ) from apps.currencies.models import ExchangeRateService, ExchangeRate, Currency @@ -16,7 +17,8 @@ logger = logging.getLogger(__name__) # Map service types to provider classes PROVIDER_MAPPING = { "synth_finance": SynthFinanceProvider, - "coingecko": CoinGeckoProvider, + "coingecko_free": CoinGeckoFreeProvider, + "coingecko_pro": CoinGeckoProProvider, } @@ -31,7 +33,7 @@ class ExchangeRateFetcher: If False, only fetches services that are due according to their interval. """ services = ExchangeRateService.objects.filter(is_active=True) - current_time = timezone.now() + current_time = timezone.now().replace(minute=0, second=0, microsecond=0) for service in services: try: @@ -47,9 +49,9 @@ class ExchangeRateFetcher: continue # Calculate when the next fetch should occur - next_fetch_due = service.last_fetch + timedelta( - hours=service.fetch_interval_hours - ) + next_fetch_due = ( + service.last_fetch + timedelta(hours=service.fetch_interval_hours) + ).replace(minute=0, second=0, microsecond=0) # Check if it's time for the next fetch if current_time >= next_fetch_due: diff --git a/app/apps/currencies/exchange_rates/providers.py b/app/apps/currencies/exchange_rates/providers.py index eeccf76..fb61aa7 100644 --- a/app/apps/currencies/exchange_rates/providers.py +++ b/app/apps/currencies/exchange_rates/providers.py @@ -77,8 +77,8 @@ class SynthFinanceProvider(ExchangeRateProvider): return results -class CoinGeckoProvider(ExchangeRateProvider): - """Implementation for CoinGecko API""" +class CoinGeckoFreeProvider(ExchangeRateProvider): + """Implementation for CoinGecko Free API""" BASE_URL = "https://api.coingecko.com/api/v3" rates_inverted = True @@ -138,3 +138,15 @@ class CoinGeckoProvider(ExchangeRateProvider): logger.error(f"Error fetching rates from CoinGecko API: {e}") return results + + +class CoinGeckoProProvider(CoinGeckoFreeProvider): + """Implementation for CoinGecko Pro API""" + + BASE_URL = "https://pro-api.coingecko.com/api/v3/simple/price" + rates_inverted = True + + def __init__(self, api_key: str): + super().__init__(api_key) + self.session = requests.Session() + self.session.headers.update({"x-cg-pro-api-key": api_key}) diff --git a/app/apps/currencies/forms.py b/app/apps/currencies/forms.py index 22fa04f..f34e605 100644 --- a/app/apps/currencies/forms.py +++ b/app/apps/currencies/forms.py @@ -1,3 +1,4 @@ +from crispy_bootstrap5.bootstrap5 import Switch from crispy_forms.bootstrap import FormActions from crispy_forms.helper import FormHelper from crispy_forms.layout import Layout @@ -9,7 +10,7 @@ from apps.common.widgets.crispy.submit import NoClassSubmit from apps.common.widgets.datepicker import AirDateTimePickerInput from apps.common.widgets.decimal import ArbitraryDecimalDisplayNumberInput from apps.common.widgets.tom_select import TomSelect -from apps.currencies.models import Currency, ExchangeRate +from apps.currencies.models import Currency, ExchangeRate, ExchangeRateService class CurrencyForm(forms.ModelForm): @@ -99,3 +100,50 @@ class ExchangeRateForm(forms.ModelForm): ), ), ) + + +class ExchangeRateServiceForm(forms.ModelForm): + class Meta: + model = ExchangeRateService + fields = [ + "name", + "service_type", + "is_active", + "api_key", + "fetch_interval_hours", + "target_currencies", + "target_accounts", + ] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.helper = FormHelper() + self.helper.form_tag = False + self.helper.form_method = "post" + self.helper.layout = Layout( + "name", + "service_type", + Switch("is_active"), + "api_key", + "fetch_interval_hours", + "target_currencies", + "target_accounts", + ) + + if self.instance and self.instance.pk: + self.helper.layout.append( + FormActions( + NoClassSubmit( + "submit", _("Update"), css_class="btn btn-outline-primary w-100" + ), + ), + ) + else: + self.helper.layout.append( + FormActions( + NoClassSubmit( + "submit", _("Add"), css_class="btn btn-outline-primary w-100" + ), + ), + ) diff --git a/app/apps/currencies/models.py b/app/apps/currencies/models.py index eceef31..698745a 100644 --- a/app/apps/currencies/models.py +++ b/app/apps/currencies/models.py @@ -91,7 +91,8 @@ class ExchangeRateService(models.Model): class ServiceType(models.TextChoices): SYNTH_FINANCE = "synth_finance", "Synth Finance" - COINGECKO = "coingecko", "CoinGecko" + COINGECKO_FREE = "coingecko_free", "CoinGecko (Demo/Free)" + COINGECKO_PRO = "coingecko_pro", "CoinGecko (Pro)" name = models.CharField(max_length=255, unique=True, verbose_name=_("Service Name")) service_type = models.CharField( diff --git a/app/apps/currencies/tasks.py b/app/apps/currencies/tasks.py index c94941c..974ac02 100644 --- a/app/apps/currencies/tasks.py +++ b/app/apps/currencies/tasks.py @@ -1,9 +1,8 @@ import logging from procrastinate.contrib.django import app + from apps.currencies.exchange_rates.fetcher import ExchangeRateFetcher -from apps.currencies.models import ExchangeRateService -from django.utils import timezone logger = logging.getLogger(__name__) diff --git a/app/apps/currencies/urls.py b/app/apps/currencies/urls.py index f05d3fe..a65e72b 100644 --- a/app/apps/currencies/urls.py +++ b/app/apps/currencies/urls.py @@ -34,4 +34,34 @@ urlpatterns = [ views.exchange_rate_delete, name="exchange_rate_delete", ), + path( + "automatic-exchange-rates/", + views.exchange_rates_services_index, + name="automatic_exchange_rates_index", + ), + path( + "automatic-exchange-rates/list/", + views.exchange_rates_services_list, + name="automatic_exchange_rates_list", + ), + path( + "automatic-exchange-rates/add/", + views.exchange_rate_service_add, + name="automatic_exchange_rate_add", + ), + path( + "automatic-exchange-rates/force-fetch/", + views.exchange_rate_service_force_fetch, + name="automatic_exchange_rate_force_fetch", + ), + path( + "automatic-exchange-rates//edit/", + views.exchange_rate_service_edit, + name="automatic_exchange_rate_edit", + ), + path( + "automatic-exchange-rates//delete/", + views.exchange_rate_service_delete, + name="automatic_exchange_rate_delete", + ), ] diff --git a/app/apps/currencies/views/__init__.py b/app/apps/currencies/views/__init__.py index 6b013c5..c0b5222 100644 --- a/app/apps/currencies/views/__init__.py +++ b/app/apps/currencies/views/__init__.py @@ -1,2 +1,3 @@ from .currencies import * from .exchange_rates import * +from .exchange_rates_services import * diff --git a/app/apps/currencies/views/exchange_rates_services.py b/app/apps/currencies/views/exchange_rates_services.py new file mode 100644 index 0000000..c572f3b --- /dev/null +++ b/app/apps/currencies/views/exchange_rates_services.py @@ -0,0 +1,122 @@ +from django.contrib import messages +from django.contrib.auth.decorators import login_required +from django.db.models import CharField, Value +from django.db.models.functions import Concat +from django.http import HttpResponse +from django.shortcuts import render, get_object_or_404 +from django.utils.translation import gettext_lazy as _ +from django.views.decorators.http import require_http_methods + +from apps.common.decorators.htmx import only_htmx +from apps.currencies.forms import ExchangeRateForm, ExchangeRateServiceForm +from apps.currencies.models import ExchangeRate, ExchangeRateService +from apps.currencies.tasks import manual_fetch_exchange_rates + + +@login_required +@require_http_methods(["GET"]) +def exchange_rates_services_index(request): + return render( + request, + "exchange_rates_services/pages/index.html", + ) + + +@only_htmx +@login_required +@require_http_methods(["GET"]) +def exchange_rates_services_list(request): + services = ExchangeRateService.objects.all() + + return render( + request, + "exchange_rates_services/fragments/list.html", + {"services": services}, + ) + + +@only_htmx +@login_required +@require_http_methods(["GET", "POST"]) +def exchange_rate_service_add(request): + if request.method == "POST": + form = ExchangeRateServiceForm(request.POST) + if form.is_valid(): + form.save() + messages.success(request, _("Service added successfully")) + + return HttpResponse( + status=204, + headers={ + "HX-Trigger": "updated, hide_offcanvas", + }, + ) + else: + form = ExchangeRateServiceForm() + + return render( + request, + "exchange_rates_services/fragments/add.html", + {"form": form}, + ) + + +@only_htmx +@login_required +@require_http_methods(["GET", "POST"]) +def exchange_rate_service_edit(request, pk): + service = get_object_or_404(ExchangeRateService, id=pk) + + if request.method == "POST": + form = ExchangeRateServiceForm(request.POST, instance=service) + if form.is_valid(): + form.save() + messages.success(request, _("Service updated successfully")) + + return HttpResponse( + status=204, + headers={ + "HX-Trigger": "updated, hide_offcanvas", + }, + ) + else: + form = ExchangeRateServiceForm(instance=service) + + return render( + request, + "exchange_rates_services/fragments/edit.html", + {"form": form, "service": service}, + ) + + +@only_htmx +@login_required +@require_http_methods(["DELETE"]) +def exchange_rate_service_delete(request, pk): + service = get_object_or_404(ExchangeRateService, id=pk) + + service.delete() + + messages.success(request, _("Service deleted successfully")) + + return HttpResponse( + status=204, + headers={ + "HX-Trigger": "updated, hide_offcanvas", + }, + ) + + +@only_htmx +@login_required +@require_http_methods(["GET"]) +def exchange_rate_service_force_fetch(request): + manual_fetch_exchange_rates.defer() + messages.success(request, _("Services queued successfully")) + + return HttpResponse( + status=204, + headers={ + "HX-Trigger": "toasts", + }, + ) diff --git a/app/locale/de/LC_MESSAGES/django.po b/app/locale/de/LC_MESSAGES/django.po index 7911a66..d77ecb0 100644 --- a/app/locale/de/LC_MESSAGES/django.po +++ b/app/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-02-01 22:04+0000\n" +"POT-Creation-Date: 2025-02-04 03:20+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -23,23 +23,24 @@ msgid "Group name" msgstr "" #: apps/accounts/forms.py:40 apps/accounts/forms.py:96 -#: apps/currencies/forms.py:52 apps/currencies/forms.py:90 apps/dca/forms.py:41 -#: apps/dca/forms.py:93 apps/import_app/forms.py:34 apps/rules/forms.py:45 -#: apps/rules/forms.py:87 apps/transactions/forms.py:190 -#: apps/transactions/forms.py:257 apps/transactions/forms.py:581 -#: apps/transactions/forms.py:624 apps/transactions/forms.py:656 -#: apps/transactions/forms.py:691 apps/transactions/forms.py:827 +#: apps/currencies/forms.py:53 apps/currencies/forms.py:91 +#: apps/currencies/forms.py:138 apps/dca/forms.py:41 apps/dca/forms.py:93 +#: apps/import_app/forms.py:34 apps/rules/forms.py:45 apps/rules/forms.py:87 +#: apps/transactions/forms.py:190 apps/transactions/forms.py:257 +#: apps/transactions/forms.py:581 apps/transactions/forms.py:624 +#: apps/transactions/forms.py:656 apps/transactions/forms.py:691 +#: apps/transactions/forms.py:827 msgid "Update" msgstr "" #: apps/accounts/forms.py:48 apps/accounts/forms.py:104 -#: apps/common/widgets/tom_select.py:12 apps/currencies/forms.py:60 -#: apps/currencies/forms.py:98 apps/dca/forms.py:49 apps/dca/forms.py:102 -#: apps/import_app/forms.py:42 apps/rules/forms.py:53 apps/rules/forms.py:95 -#: apps/transactions/forms.py:174 apps/transactions/forms.py:199 -#: apps/transactions/forms.py:589 apps/transactions/forms.py:632 -#: apps/transactions/forms.py:664 apps/transactions/forms.py:699 -#: apps/transactions/forms.py:835 +#: apps/common/widgets/tom_select.py:12 apps/currencies/forms.py:61 +#: apps/currencies/forms.py:99 apps/currencies/forms.py:146 +#: apps/dca/forms.py:49 apps/dca/forms.py:102 apps/import_app/forms.py:42 +#: apps/rules/forms.py:53 apps/rules/forms.py:95 apps/transactions/forms.py:174 +#: apps/transactions/forms.py:199 apps/transactions/forms.py:589 +#: apps/transactions/forms.py:632 apps/transactions/forms.py:664 +#: apps/transactions/forms.py:699 apps/transactions/forms.py:835 #: templates/account_groups/fragments/list.html:9 #: templates/accounts/fragments/list.html:9 #: templates/categories/fragments/list.html:9 @@ -48,6 +49,7 @@ msgstr "" #: templates/dca/fragments/strategy/list.html:9 #: templates/entities/fragments/list.html:9 #: templates/exchange_rates/fragments/list.html:10 +#: templates/exchange_rates_services/fragments/list.html:10 #: templates/import_app/fragments/profiles/list.html:7 #: templates/import_app/fragments/profiles/list.html:10 #: templates/installment_plans/fragments/list.html:9 @@ -69,7 +71,7 @@ msgstr "" #: apps/transactions/forms.py:39 apps/transactions/forms.py:291 #: apps/transactions/forms.py:298 apps/transactions/forms.py:478 #: apps/transactions/forms.py:723 apps/transactions/models.py:159 -#: apps/transactions/models.py:314 apps/transactions/models.py:494 +#: apps/transactions/models.py:328 apps/transactions/models.py:508 msgid "Category" msgstr "" @@ -77,8 +79,8 @@ msgstr "" #: apps/transactions/filters.py:74 apps/transactions/forms.py:47 #: apps/transactions/forms.py:307 apps/transactions/forms.py:315 #: apps/transactions/forms.py:471 apps/transactions/forms.py:716 -#: apps/transactions/models.py:165 apps/transactions/models.py:316 -#: apps/transactions/models.py:498 templates/includes/navbar.html:105 +#: apps/transactions/models.py:165 apps/transactions/models.py:330 +#: apps/transactions/models.py:512 templates/includes/navbar.html:105 #: templates/tags/fragments/list.html:5 templates/tags/pages/index.html:4 msgid "Tags" msgstr "" @@ -92,6 +94,7 @@ msgstr "" #: templates/categories/fragments/table.html:16 #: templates/currencies/fragments/list.html:26 #: templates/entities/fragments/table.html:16 +#: templates/exchange_rates_services/fragments/list.html:32 #: templates/import_app/fragments/profiles/list.html:36 #: templates/installment_plans/fragments/table.html:16 #: templates/recurring_transactions/fragments/table.html:18 @@ -110,17 +113,17 @@ msgstr "" msgid "Account Groups" msgstr "" -#: apps/accounts/models.py:31 apps/currencies/models.py:32 +#: apps/accounts/models.py:31 apps/currencies/models.py:38 #: templates/accounts/fragments/list.html:27 msgid "Currency" msgstr "" -#: apps/accounts/models.py:37 apps/currencies/models.py:20 +#: apps/accounts/models.py:37 apps/currencies/models.py:26 #: templates/accounts/fragments/list.html:28 msgid "Exchange Currency" msgstr "" -#: apps/accounts/models.py:42 apps/currencies/models.py:25 +#: apps/accounts/models.py:42 apps/currencies/models.py:31 msgid "Default currency for exchange calculations" msgstr "" @@ -147,7 +150,7 @@ msgstr "" #: apps/accounts/models.py:59 apps/rules/models.py:19 #: apps/transactions/forms.py:59 apps/transactions/forms.py:463 #: apps/transactions/forms.py:708 apps/transactions/models.py:132 -#: apps/transactions/models.py:274 apps/transactions/models.py:476 +#: apps/transactions/models.py:288 apps/transactions/models.py:490 msgid "Account" msgstr "" @@ -345,35 +348,36 @@ msgstr "" msgid "No results..." msgstr "" -#: apps/currencies/forms.py:16 apps/currencies/models.py:15 +#: apps/currencies/forms.py:17 apps/currencies/models.py:21 msgid "Prefix" msgstr "" -#: apps/currencies/forms.py:17 apps/currencies/models.py:16 +#: apps/currencies/forms.py:18 apps/currencies/models.py:22 msgid "Suffix" msgstr "" -#: apps/currencies/forms.py:68 apps/dca/models.py:156 apps/rules/models.py:22 +#: apps/currencies/forms.py:69 apps/dca/models.py:156 apps/rules/models.py:22 #: apps/transactions/forms.py:63 apps/transactions/forms.py:319 #: apps/transactions/models.py:142 #: templates/dca/fragments/strategy/details.html:52 #: templates/exchange_rates/fragments/table.html:10 +#: templates/exchange_rates_services/fragments/table.html:10 msgid "Date" msgstr "" -#: apps/currencies/models.py:8 +#: apps/currencies/models.py:13 msgid "Currency Code" msgstr "" -#: apps/currencies/models.py:9 +#: apps/currencies/models.py:15 msgid "Currency Name" msgstr "" -#: apps/currencies/models.py:13 +#: apps/currencies/models.py:19 msgid "Decimal Places" msgstr "" -#: apps/currencies/models.py:33 apps/transactions/filters.py:60 +#: apps/currencies/models.py:39 apps/transactions/filters.py:60 #: templates/currencies/fragments/list.html:5 #: templates/currencies/pages/index.html:4 templates/includes/navbar.html:119 #: templates/includes/navbar.html:121 @@ -383,36 +387,97 @@ msgstr "" msgid "Currencies" msgstr "" -#: apps/currencies/models.py:41 +#: apps/currencies/models.py:47 msgid "Currency cannot have itself as exchange currency." msgstr "" -#: apps/currencies/models.py:52 +#: apps/currencies/models.py:58 msgid "From Currency" msgstr "" -#: apps/currencies/models.py:58 +#: apps/currencies/models.py:64 msgid "To Currency" msgstr "" -#: apps/currencies/models.py:61 apps/currencies/models.py:66 +#: apps/currencies/models.py:67 apps/currencies/models.py:72 msgid "Exchange Rate" msgstr "" -#: apps/currencies/models.py:63 +#: apps/currencies/models.py:69 msgid "Date and Time" msgstr "" -#: apps/currencies/models.py:67 templates/exchange_rates/fragments/list.html:6 +#: apps/currencies/models.py:73 templates/exchange_rates/fragments/list.html:6 #: templates/exchange_rates/pages/index.html:4 #: templates/includes/navbar.html:123 msgid "Exchange Rates" msgstr "" -#: apps/currencies/models.py:79 +#: apps/currencies/models.py:85 msgid "From and To currencies cannot be the same." msgstr "" +#: apps/currencies/models.py:97 +msgid "Service Name" +msgstr "" + +#: apps/currencies/models.py:99 +msgid "Service Type" +msgstr "" + +#: apps/currencies/models.py:101 apps/transactions/models.py:71 +#: apps/transactions/models.py:90 apps/transactions/models.py:109 +#: templates/categories/fragments/list.html:21 +#: templates/entities/fragments/list.html:21 +#: templates/recurring_transactions/fragments/list.html:21 +#: templates/tags/fragments/list.html:21 +msgid "Active" +msgstr "" + +#: apps/currencies/models.py:106 +msgid "API Key" +msgstr "" + +#: apps/currencies/models.py:107 +msgid "API key for the service (if required)" +msgstr "" + +#: apps/currencies/models.py:112 +msgid "Fetch Interval (hours)" +msgstr "" + +#: apps/currencies/models.py:115 +msgid "Last Successful Fetch" +msgstr "" + +#: apps/currencies/models.py:120 +msgid "Target Currencies" +msgstr "" + +#: apps/currencies/models.py:122 +msgid "" +"Select currencies to fetch exchange rates for. Rates will be fetched for " +"each currency against their set exchange currency." +msgstr "" + +#: apps/currencies/models.py:130 +msgid "Target Accounts" +msgstr "" + +#: apps/currencies/models.py:132 +msgid "" +"Select accounts to fetch exchange rates for. Rates will be fetched for each " +"account's currency against their set exchange currency." +msgstr "" + +#: apps/currencies/models.py:139 +msgid "Exchange Rate Service" +msgstr "" + +#: apps/currencies/models.py:140 +msgid "Exchange Rate Services" +msgstr "" + #: apps/currencies/views/currencies.py:42 msgid "Currency added successfully" msgstr "" @@ -437,6 +502,22 @@ msgstr "" msgid "Exchange rate deleted successfully" msgstr "" +#: apps/currencies/views/exchange_rates_services.py:46 +msgid "Service added successfully" +msgstr "" + +#: apps/currencies/views/exchange_rates_services.py:74 +msgid "Service updated successfully" +msgstr "" + +#: apps/currencies/views/exchange_rates_services.py:100 +msgid "Service deleted successfully" +msgstr "" + +#: apps/currencies/views/exchange_rates_services.py:115 +msgid "Services queued successfully" +msgstr "" + #: apps/dca/models.py:17 msgid "Target Currency" msgstr "" @@ -447,7 +528,7 @@ msgstr "" #: apps/dca/models.py:27 apps/dca/models.py:179 apps/rules/models.py:26 #: apps/transactions/forms.py:333 apps/transactions/models.py:155 -#: apps/transactions/models.py:323 apps/transactions/models.py:504 +#: apps/transactions/models.py:337 apps/transactions/models.py:518 msgid "Notes" msgstr "" @@ -611,7 +692,7 @@ msgstr "" #: apps/rules/models.py:10 apps/rules/models.py:25 #: apps/transactions/forms.py:325 apps/transactions/models.py:153 -#: apps/transactions/models.py:281 apps/transactions/models.py:490 +#: apps/transactions/models.py:295 apps/transactions/models.py:504 msgid "Description" msgstr "" @@ -620,7 +701,7 @@ msgid "Trigger" msgstr "" #: apps/rules/models.py:20 apps/transactions/models.py:139 -#: apps/transactions/models.py:279 apps/transactions/models.py:482 +#: apps/transactions/models.py:293 apps/transactions/models.py:496 msgid "Type" msgstr "" @@ -634,21 +715,21 @@ msgstr "" #: apps/rules/models.py:23 apps/transactions/forms.py:66 #: apps/transactions/forms.py:322 apps/transactions/forms.py:492 -#: apps/transactions/models.py:143 apps/transactions/models.py:297 -#: apps/transactions/models.py:506 +#: apps/transactions/models.py:143 apps/transactions/models.py:311 +#: apps/transactions/models.py:520 msgid "Reference Date" msgstr "" #: apps/rules/models.py:24 apps/transactions/models.py:148 -#: apps/transactions/models.py:487 +#: apps/transactions/models.py:501 msgid "Amount" msgstr "" #: apps/rules/models.py:29 apps/transactions/filters.py:81 #: apps/transactions/forms.py:55 apps/transactions/forms.py:486 #: apps/transactions/forms.py:731 apps/transactions/models.py:117 -#: apps/transactions/models.py:170 apps/transactions/models.py:319 -#: apps/transactions/models.py:501 templates/entities/fragments/list.html:5 +#: apps/transactions/models.py:170 apps/transactions/models.py:333 +#: apps/transactions/models.py:515 templates/entities/fragments/list.html:5 #: templates/entities/pages/index.html:4 templates/includes/navbar.html:107 msgid "Entities" msgstr "" @@ -786,14 +867,6 @@ msgstr "" msgid "Mute" msgstr "" -#: apps/transactions/models.py:71 apps/transactions/models.py:90 -#: apps/transactions/models.py:109 templates/categories/fragments/list.html:21 -#: templates/entities/fragments/list.html:21 -#: templates/recurring_transactions/fragments/list.html:21 -#: templates/tags/fragments/list.html:21 -msgid "Active" -msgstr "" - #: apps/transactions/models.py:73 msgid "" "Deactivated categories won't be able to be selected when creating new " @@ -846,11 +919,11 @@ msgstr "" msgid "Expense" msgstr "" -#: apps/transactions/models.py:181 apps/transactions/models.py:326 +#: apps/transactions/models.py:181 apps/transactions/models.py:340 msgid "Installment Plan" msgstr "" -#: apps/transactions/models.py:190 apps/transactions/models.py:527 +#: apps/transactions/models.py:190 apps/transactions/models.py:541 msgid "Recurring Transaction" msgstr "" @@ -882,95 +955,95 @@ msgstr "" msgid "Transactions" msgstr "" -#: apps/transactions/models.py:268 +#: apps/transactions/models.py:282 msgid "Yearly" msgstr "" -#: apps/transactions/models.py:269 apps/users/models.py:26 +#: apps/transactions/models.py:283 apps/users/models.py:26 #: templates/includes/navbar.html:26 msgid "Monthly" msgstr "" -#: apps/transactions/models.py:270 +#: apps/transactions/models.py:284 msgid "Weekly" msgstr "" -#: apps/transactions/models.py:271 +#: apps/transactions/models.py:285 msgid "Daily" msgstr "" -#: apps/transactions/models.py:284 +#: apps/transactions/models.py:298 msgid "Number of Installments" msgstr "" -#: apps/transactions/models.py:289 +#: apps/transactions/models.py:303 msgid "Installment Start" msgstr "" -#: apps/transactions/models.py:290 +#: apps/transactions/models.py:304 msgid "The installment number to start counting from" msgstr "" -#: apps/transactions/models.py:295 apps/transactions/models.py:510 +#: apps/transactions/models.py:309 apps/transactions/models.py:524 msgid "Start Date" msgstr "" -#: apps/transactions/models.py:299 apps/transactions/models.py:511 +#: apps/transactions/models.py:313 apps/transactions/models.py:525 msgid "End Date" msgstr "" -#: apps/transactions/models.py:304 +#: apps/transactions/models.py:318 msgid "Recurrence" msgstr "" -#: apps/transactions/models.py:307 +#: apps/transactions/models.py:321 msgid "Installment Amount" msgstr "" -#: apps/transactions/models.py:327 templates/includes/navbar.html:69 +#: apps/transactions/models.py:341 templates/includes/navbar.html:69 #: templates/installment_plans/fragments/list.html:5 #: templates/installment_plans/pages/index.html:4 msgid "Installment Plans" msgstr "" -#: apps/transactions/models.py:469 +#: apps/transactions/models.py:483 msgid "day(s)" msgstr "" -#: apps/transactions/models.py:470 +#: apps/transactions/models.py:484 msgid "week(s)" msgstr "" -#: apps/transactions/models.py:471 +#: apps/transactions/models.py:485 msgid "month(s)" msgstr "" -#: apps/transactions/models.py:472 +#: apps/transactions/models.py:486 msgid "year(s)" msgstr "" -#: apps/transactions/models.py:474 +#: apps/transactions/models.py:488 #: templates/recurring_transactions/fragments/list.html:24 msgid "Paused" msgstr "" -#: apps/transactions/models.py:513 +#: apps/transactions/models.py:527 msgid "Recurrence Type" msgstr "" -#: apps/transactions/models.py:516 +#: apps/transactions/models.py:530 msgid "Recurrence Interval" msgstr "" -#: apps/transactions/models.py:520 +#: apps/transactions/models.py:534 msgid "Last Generated Date" msgstr "" -#: apps/transactions/models.py:523 +#: apps/transactions/models.py:537 msgid "Last Generated Reference Date" msgstr "" -#: apps/transactions/models.py:528 templates/includes/navbar.html:71 +#: apps/transactions/models.py:542 templates/includes/navbar.html:71 #: templates/recurring_transactions/fragments/list.html:5 #: templates/recurring_transactions/pages/index.html:4 msgid "Recurring Transactions" @@ -1171,15 +1244,15 @@ msgstr "" msgid "Default" msgstr "" -#: apps/users/forms.py:91 apps/users/models.py:40 +#: apps/users/forms.py:91 apps/users/models.py:41 msgid "Date Format" msgstr "" -#: apps/users/forms.py:96 apps/users/models.py:45 +#: apps/users/forms.py:96 apps/users/models.py:46 msgid "Datetime Format" msgstr "" -#: apps/users/forms.py:102 apps/users/models.py:48 +#: apps/users/forms.py:102 apps/users/models.py:49 msgid "Number Format" msgstr "" @@ -1195,51 +1268,55 @@ msgstr "" msgid "Yearly by account" msgstr "" -#: apps/users/models.py:29 templates/includes/navbar.html:40 -msgid "Net Worth" +#: apps/users/models.py:29 templates/net_worth/net_worth.html:9 +msgid "Current Net Worth" msgstr "" -#: apps/users/models.py:30 +#: apps/users/models.py:30 templates/net_worth/net_worth.html:9 +msgid "Projected Net Worth" +msgstr "" + +#: apps/users/models.py:31 msgid "All Transactions" msgstr "" -#: apps/users/models.py:31 templates/includes/navbar.html:32 +#: apps/users/models.py:32 templates/includes/navbar.html:32 msgid "Calendar" msgstr "" -#: apps/users/models.py:53 apps/users/models.py:59 +#: apps/users/models.py:54 apps/users/models.py:60 msgid "Auto" msgstr "" -#: apps/users/models.py:55 +#: apps/users/models.py:56 msgid "Language" msgstr "" -#: apps/users/models.py:61 +#: apps/users/models.py:62 msgid "Time Zone" msgstr "" -#: apps/users/models.py:67 +#: apps/users/models.py:68 msgid "Start page" msgstr "" -#: apps/users/views.py:60 +#: apps/users/views.py:62 msgid "Transaction amounts are now hidden" msgstr "" -#: apps/users/views.py:63 +#: apps/users/views.py:65 msgid "Transaction amounts are now displayed" msgstr "" -#: apps/users/views.py:81 +#: apps/users/views.py:83 msgid "Sounds are now muted" msgstr "" -#: apps/users/views.py:84 +#: apps/users/views.py:86 msgid "Sounds will now play" msgstr "" -#: apps/users/views.py:100 +#: apps/users/views.py:102 msgid "Your settings have been updated" msgstr "" @@ -1258,6 +1335,8 @@ msgstr "" #: templates/dca/fragments/strategy/details.html:63 #: templates/entities/fragments/table.html:23 #: templates/exchange_rates/fragments/table.html:19 +#: templates/exchange_rates_services/fragments/list.html:43 +#: templates/exchange_rates_services/fragments/table.html:19 #: templates/import_app/fragments/profiles/list.html:44 #: templates/installment_plans/fragments/table.html:23 #: templates/recurring_transactions/fragments/table.html:25 @@ -1276,6 +1355,8 @@ msgstr "" #: templates/dca/fragments/strategy/list.html:34 #: templates/entities/fragments/table.html:28 #: templates/exchange_rates/fragments/table.html:23 +#: templates/exchange_rates_services/fragments/list.html:47 +#: templates/exchange_rates_services/fragments/table.html:23 #: templates/import_app/fragments/profiles/list.html:48 #: templates/installment_plans/fragments/table.html:27 #: templates/recurring_transactions/fragments/table.html:29 @@ -1297,6 +1378,8 @@ msgstr "" #: templates/dca/fragments/strategy/list.html:42 #: templates/entities/fragments/table.html:36 #: templates/exchange_rates/fragments/table.html:31 +#: templates/exchange_rates_services/fragments/list.html:54 +#: templates/exchange_rates_services/fragments/table.html:31 #: templates/import_app/fragments/profiles/list.html:69 #: templates/import_app/fragments/runs/list.html:102 #: templates/installment_plans/fragments/table.html:56 @@ -1320,6 +1403,8 @@ msgstr "" #: templates/dca/fragments/strategy/list.html:46 #: templates/entities/fragments/table.html:40 #: templates/exchange_rates/fragments/table.html:36 +#: templates/exchange_rates_services/fragments/list.html:58 +#: templates/exchange_rates_services/fragments/table.html:36 #: templates/import_app/fragments/profiles/list.html:73 #: templates/import_app/fragments/runs/list.html:106 #: templates/installment_plans/fragments/table.html:48 @@ -1346,6 +1431,8 @@ msgstr "" #: templates/dca/fragments/strategy/list.html:47 #: templates/entities/fragments/table.html:41 #: templates/exchange_rates/fragments/table.html:37 +#: templates/exchange_rates_services/fragments/list.html:59 +#: templates/exchange_rates_services/fragments/table.html:37 #: templates/import_app/fragments/profiles/list.html:74 #: templates/rules/fragments/list.html:49 #: templates/rules/fragments/transaction_rule/view.html:61 @@ -1363,6 +1450,8 @@ msgstr "" #: templates/dca/fragments/strategy/list.html:48 #: templates/entities/fragments/table.html:42 #: templates/exchange_rates/fragments/table.html:38 +#: templates/exchange_rates_services/fragments/list.html:60 +#: templates/exchange_rates_services/fragments/table.html:38 #: templates/import_app/fragments/profiles/list.html:75 #: templates/import_app/fragments/runs/list.html:108 #: templates/installment_plans/fragments/table.html:62 @@ -1494,37 +1583,37 @@ msgid "Restore" msgstr "" #: templates/cotton/ui/account_card.html:15 -#: templates/cotton/ui/currency_card.html:13 +#: templates/cotton/ui/currency_card.html:10 msgid "projected income" msgstr "" #: templates/cotton/ui/account_card.html:37 -#: templates/cotton/ui/currency_card.html:35 +#: templates/cotton/ui/currency_card.html:32 msgid "projected expenses" msgstr "" #: templates/cotton/ui/account_card.html:61 -#: templates/cotton/ui/currency_card.html:59 +#: templates/cotton/ui/currency_card.html:56 msgid "projected total" msgstr "" #: templates/cotton/ui/account_card.html:86 -#: templates/cotton/ui/currency_card.html:84 +#: templates/cotton/ui/currency_card.html:81 msgid "current income" msgstr "" #: templates/cotton/ui/account_card.html:108 -#: templates/cotton/ui/currency_card.html:106 +#: templates/cotton/ui/currency_card.html:103 msgid "current expenses" msgstr "" #: templates/cotton/ui/account_card.html:130 -#: templates/cotton/ui/currency_card.html:128 +#: templates/cotton/ui/currency_card.html:125 msgid "current total" msgstr "" #: templates/cotton/ui/account_card.html:156 -#: templates/cotton/ui/currency_card.html:154 +#: templates/cotton/ui/currency_card.html:151 msgid "final total" msgstr "" @@ -1778,10 +1867,12 @@ msgid "No entities" msgstr "" #: templates/exchange_rates/fragments/add.html:5 +#: templates/exchange_rates_services/fragments/add.html:5 msgid "Add exchange rate" msgstr "" #: templates/exchange_rates/fragments/edit.html:5 +#: templates/exchange_rates_services/fragments/edit.html:5 msgid "Edit exchange rate" msgstr "" @@ -1794,22 +1885,68 @@ msgid "All" msgstr "" #: templates/exchange_rates/fragments/table.html:11 +#: templates/exchange_rates_services/fragments/table.html:11 msgid "Pairing" msgstr "" #: templates/exchange_rates/fragments/table.html:12 +#: templates/exchange_rates_services/fragments/table.html:12 msgid "Rate" msgstr "" #: templates/exchange_rates/fragments/table.html:51 +#: templates/exchange_rates_services/fragments/table.html:51 msgid "No exchange rates" msgstr "" #: templates/exchange_rates/fragments/table.html:58 +#: templates/exchange_rates_services/fragments/table.html:58 #: templates/transactions/fragments/list_all.html:47 msgid "Page navigation" msgstr "" +#: templates/exchange_rates_services/fragments/list.html:6 +#: templates/exchange_rates_services/pages/index.html:4 +#: templates/includes/navbar.html:133 +msgid "Automatic Exchange Rates" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:21 +msgid "Fetch all" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:33 +msgid "Service" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:34 +msgid "Targeting" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:35 +msgid "Fetch every" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:36 +msgid "Last fetch" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:68 +msgid "currencies" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:68 +msgid "accounts" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:69 +msgid "hours" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:77 +msgid "No services configured" +msgstr "" + #: templates/import_app/fragments/profiles/add.html:6 msgid "Add new import profile" msgstr "" @@ -1907,6 +2044,10 @@ msgstr "" msgid "Overview" msgstr "" +#: templates/includes/navbar.html:40 +msgid "Net Worth" +msgstr "" + #: templates/includes/navbar.html:44 msgid "Current" msgstr "" @@ -1948,15 +2089,15 @@ msgstr "" msgid "Rules" msgstr "" -#: templates/includes/navbar.html:141 +#: templates/includes/navbar.html:143 msgid "Only use this if you know what you're doing" msgstr "" -#: templates/includes/navbar.html:142 +#: templates/includes/navbar.html:144 msgid "Django Admin" msgstr "" -#: templates/includes/navbar.html:151 +#: templates/includes/navbar.html:153 msgid "Calculator" msgstr "" @@ -2121,14 +2262,6 @@ msgstr "" msgid "Newest first" msgstr "" -#: templates/net_worth/net_worth.html:9 -msgid "Current Net Worth" -msgstr "" - -#: templates/net_worth/net_worth.html:9 -msgid "Projected Net Worth" -msgstr "" - #: templates/net_worth/net_worth.html:17 #: templates/yearly_overview/pages/overview_by_currency.html:9 msgid "By currency" diff --git a/app/locale/nl/LC_MESSAGES/django.po b/app/locale/nl/LC_MESSAGES/django.po index dc96215..21ac403 100644 --- a/app/locale/nl/LC_MESSAGES/django.po +++ b/app/locale/nl/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-02-01 22:04+0000\n" +"POT-Creation-Date: 2025-02-04 03:20+0000\n" "PO-Revision-Date: 2025-01-29 06:12+0100\n" "Last-Translator: Dimitri Decrock \n" "Language-Team: \n" @@ -24,23 +24,24 @@ msgid "Group name" msgstr "Groepsnaam" #: apps/accounts/forms.py:40 apps/accounts/forms.py:96 -#: apps/currencies/forms.py:52 apps/currencies/forms.py:90 apps/dca/forms.py:41 -#: apps/dca/forms.py:93 apps/import_app/forms.py:34 apps/rules/forms.py:45 -#: apps/rules/forms.py:87 apps/transactions/forms.py:190 -#: apps/transactions/forms.py:257 apps/transactions/forms.py:581 -#: apps/transactions/forms.py:624 apps/transactions/forms.py:656 -#: apps/transactions/forms.py:691 apps/transactions/forms.py:827 +#: apps/currencies/forms.py:53 apps/currencies/forms.py:91 +#: apps/currencies/forms.py:138 apps/dca/forms.py:41 apps/dca/forms.py:93 +#: apps/import_app/forms.py:34 apps/rules/forms.py:45 apps/rules/forms.py:87 +#: apps/transactions/forms.py:190 apps/transactions/forms.py:257 +#: apps/transactions/forms.py:581 apps/transactions/forms.py:624 +#: apps/transactions/forms.py:656 apps/transactions/forms.py:691 +#: apps/transactions/forms.py:827 msgid "Update" msgstr "Bijwerken" #: apps/accounts/forms.py:48 apps/accounts/forms.py:104 -#: apps/common/widgets/tom_select.py:12 apps/currencies/forms.py:60 -#: apps/currencies/forms.py:98 apps/dca/forms.py:49 apps/dca/forms.py:102 -#: apps/import_app/forms.py:42 apps/rules/forms.py:53 apps/rules/forms.py:95 -#: apps/transactions/forms.py:174 apps/transactions/forms.py:199 -#: apps/transactions/forms.py:589 apps/transactions/forms.py:632 -#: apps/transactions/forms.py:664 apps/transactions/forms.py:699 -#: apps/transactions/forms.py:835 +#: apps/common/widgets/tom_select.py:12 apps/currencies/forms.py:61 +#: apps/currencies/forms.py:99 apps/currencies/forms.py:146 +#: apps/dca/forms.py:49 apps/dca/forms.py:102 apps/import_app/forms.py:42 +#: apps/rules/forms.py:53 apps/rules/forms.py:95 apps/transactions/forms.py:174 +#: apps/transactions/forms.py:199 apps/transactions/forms.py:589 +#: apps/transactions/forms.py:632 apps/transactions/forms.py:664 +#: apps/transactions/forms.py:699 apps/transactions/forms.py:835 #: templates/account_groups/fragments/list.html:9 #: templates/accounts/fragments/list.html:9 #: templates/categories/fragments/list.html:9 @@ -49,6 +50,7 @@ msgstr "Bijwerken" #: templates/dca/fragments/strategy/list.html:9 #: templates/entities/fragments/list.html:9 #: templates/exchange_rates/fragments/list.html:10 +#: templates/exchange_rates_services/fragments/list.html:10 #: templates/import_app/fragments/profiles/list.html:7 #: templates/import_app/fragments/profiles/list.html:10 #: templates/installment_plans/fragments/list.html:9 @@ -70,7 +72,7 @@ msgstr "Nieuw saldo" #: apps/transactions/forms.py:39 apps/transactions/forms.py:291 #: apps/transactions/forms.py:298 apps/transactions/forms.py:478 #: apps/transactions/forms.py:723 apps/transactions/models.py:159 -#: apps/transactions/models.py:314 apps/transactions/models.py:494 +#: apps/transactions/models.py:328 apps/transactions/models.py:508 msgid "Category" msgstr "Categorie" @@ -78,8 +80,8 @@ msgstr "Categorie" #: apps/transactions/filters.py:74 apps/transactions/forms.py:47 #: apps/transactions/forms.py:307 apps/transactions/forms.py:315 #: apps/transactions/forms.py:471 apps/transactions/forms.py:716 -#: apps/transactions/models.py:165 apps/transactions/models.py:316 -#: apps/transactions/models.py:498 templates/includes/navbar.html:105 +#: apps/transactions/models.py:165 apps/transactions/models.py:330 +#: apps/transactions/models.py:512 templates/includes/navbar.html:105 #: templates/tags/fragments/list.html:5 templates/tags/pages/index.html:4 msgid "Tags" msgstr "Labels" @@ -93,6 +95,7 @@ msgstr "Labels" #: templates/categories/fragments/table.html:16 #: templates/currencies/fragments/list.html:26 #: templates/entities/fragments/table.html:16 +#: templates/exchange_rates_services/fragments/list.html:32 #: templates/import_app/fragments/profiles/list.html:36 #: templates/installment_plans/fragments/table.html:16 #: templates/recurring_transactions/fragments/table.html:18 @@ -111,17 +114,17 @@ msgstr "Accountgroep" msgid "Account Groups" msgstr "Accountgroepen" -#: apps/accounts/models.py:31 apps/currencies/models.py:32 +#: apps/accounts/models.py:31 apps/currencies/models.py:38 #: templates/accounts/fragments/list.html:27 msgid "Currency" msgstr "Munteenheid" -#: apps/accounts/models.py:37 apps/currencies/models.py:20 +#: apps/accounts/models.py:37 apps/currencies/models.py:26 #: templates/accounts/fragments/list.html:28 msgid "Exchange Currency" msgstr "Eenheid Wisselgeld" -#: apps/accounts/models.py:42 apps/currencies/models.py:25 +#: apps/accounts/models.py:42 apps/currencies/models.py:31 msgid "Default currency for exchange calculations" msgstr "Standaard munteenheid voor wisselberekeningen" @@ -152,7 +155,7 @@ msgstr "" #: apps/accounts/models.py:59 apps/rules/models.py:19 #: apps/transactions/forms.py:59 apps/transactions/forms.py:463 #: apps/transactions/forms.py:708 apps/transactions/models.py:132 -#: apps/transactions/models.py:274 apps/transactions/models.py:476 +#: apps/transactions/models.py:288 apps/transactions/models.py:490 msgid "Account" msgstr "Rekening" @@ -351,35 +354,36 @@ msgstr "Leegmaken" msgid "No results..." msgstr "Geen resultaten..." -#: apps/currencies/forms.py:16 apps/currencies/models.py:15 +#: apps/currencies/forms.py:17 apps/currencies/models.py:21 msgid "Prefix" msgstr "Voorvoegsel" -#: apps/currencies/forms.py:17 apps/currencies/models.py:16 +#: apps/currencies/forms.py:18 apps/currencies/models.py:22 msgid "Suffix" msgstr "Achtervoegsel" -#: apps/currencies/forms.py:68 apps/dca/models.py:156 apps/rules/models.py:22 +#: apps/currencies/forms.py:69 apps/dca/models.py:156 apps/rules/models.py:22 #: apps/transactions/forms.py:63 apps/transactions/forms.py:319 #: apps/transactions/models.py:142 #: templates/dca/fragments/strategy/details.html:52 #: templates/exchange_rates/fragments/table.html:10 +#: templates/exchange_rates_services/fragments/table.html:10 msgid "Date" msgstr "Datum" -#: apps/currencies/models.py:8 +#: apps/currencies/models.py:13 msgid "Currency Code" msgstr "Munteenheids Code" -#: apps/currencies/models.py:9 +#: apps/currencies/models.py:15 msgid "Currency Name" msgstr "Munteenheids Naam" -#: apps/currencies/models.py:13 +#: apps/currencies/models.py:19 msgid "Decimal Places" msgstr "Cijfers na de komma" -#: apps/currencies/models.py:33 apps/transactions/filters.py:60 +#: apps/currencies/models.py:39 apps/transactions/filters.py:60 #: templates/currencies/fragments/list.html:5 #: templates/currencies/pages/index.html:4 templates/includes/navbar.html:119 #: templates/includes/navbar.html:121 @@ -389,36 +393,109 @@ msgstr "Cijfers na de komma" msgid "Currencies" msgstr "Munteenheden" -#: apps/currencies/models.py:41 +#: apps/currencies/models.py:47 msgid "Currency cannot have itself as exchange currency." msgstr "Munteenheid kan zichzelf niet als ruilmiddel hebben." -#: apps/currencies/models.py:52 +#: apps/currencies/models.py:58 msgid "From Currency" msgstr "Van Munteenheid" -#: apps/currencies/models.py:58 +#: apps/currencies/models.py:64 msgid "To Currency" msgstr "Naar Munteenheid" -#: apps/currencies/models.py:61 apps/currencies/models.py:66 +#: apps/currencies/models.py:67 apps/currencies/models.py:72 msgid "Exchange Rate" msgstr "Wisselkoers" -#: apps/currencies/models.py:63 +#: apps/currencies/models.py:69 msgid "Date and Time" msgstr "Datum en Tijd" -#: apps/currencies/models.py:67 templates/exchange_rates/fragments/list.html:6 +#: apps/currencies/models.py:73 templates/exchange_rates/fragments/list.html:6 #: templates/exchange_rates/pages/index.html:4 #: templates/includes/navbar.html:123 msgid "Exchange Rates" msgstr "Wisselkoersen" -#: apps/currencies/models.py:79 +#: apps/currencies/models.py:85 msgid "From and To currencies cannot be the same." msgstr "Van en Naar munteenheid kunnen niet dezelfde zijn." +#: apps/currencies/models.py:97 +msgid "Service Name" +msgstr "" + +#: apps/currencies/models.py:99 +#, fuzzy +#| msgid "Recurrence Type" +msgid "Service Type" +msgstr "Type Terugkeerpatroon" + +#: apps/currencies/models.py:101 apps/transactions/models.py:71 +#: apps/transactions/models.py:90 apps/transactions/models.py:109 +#: templates/categories/fragments/list.html:21 +#: templates/entities/fragments/list.html:21 +#: templates/recurring_transactions/fragments/list.html:21 +#: templates/tags/fragments/list.html:21 +msgid "Active" +msgstr "Actief" + +#: apps/currencies/models.py:106 +msgid "API Key" +msgstr "" + +#: apps/currencies/models.py:107 +msgid "API key for the service (if required)" +msgstr "" + +#: apps/currencies/models.py:112 +msgid "Fetch Interval (hours)" +msgstr "" + +#: apps/currencies/models.py:115 +#, fuzzy +#| msgid "Successful Items" +msgid "Last Successful Fetch" +msgstr "Succesvolle Artikelen" + +#: apps/currencies/models.py:120 +#, fuzzy +#| msgid "Target Currency" +msgid "Target Currencies" +msgstr "Doel Munteenheid" + +#: apps/currencies/models.py:122 +msgid "" +"Select currencies to fetch exchange rates for. Rates will be fetched for " +"each currency against their set exchange currency." +msgstr "" + +#: apps/currencies/models.py:130 +#, fuzzy +#| msgid "To Account" +msgid "Target Accounts" +msgstr "Naar rekening" + +#: apps/currencies/models.py:132 +msgid "" +"Select accounts to fetch exchange rates for. Rates will be fetched for each " +"account's currency against their set exchange currency." +msgstr "" + +#: apps/currencies/models.py:139 +#, fuzzy +#| msgid "Exchange Rate" +msgid "Exchange Rate Service" +msgstr "Wisselkoers" + +#: apps/currencies/models.py:140 +#, fuzzy +#| msgid "Exchange Rates" +msgid "Exchange Rate Services" +msgstr "Wisselkoersen" + #: apps/currencies/views/currencies.py:42 msgid "Currency added successfully" msgstr "Munteenheid succesvol toegevoegd" @@ -443,6 +520,30 @@ msgstr "Wisselkoers succesvol bijgewerkt" msgid "Exchange rate deleted successfully" msgstr "Wisselkoers succesvol verwijderd" +#: apps/currencies/views/exchange_rates_services.py:46 +#, fuzzy +#| msgid "Rule added successfully" +msgid "Service added successfully" +msgstr "Regel succesvol toegevoegd" + +#: apps/currencies/views/exchange_rates_services.py:74 +#, fuzzy +#| msgid "Rule updated successfully" +msgid "Service updated successfully" +msgstr "Regel succesvol bijgewerkt" + +#: apps/currencies/views/exchange_rates_services.py:100 +#, fuzzy +#| msgid "Rule deleted successfully" +msgid "Service deleted successfully" +msgstr "Regel succesvol verwijderd" + +#: apps/currencies/views/exchange_rates_services.py:115 +#, fuzzy +#| msgid "Rule updated successfully" +msgid "Services queued successfully" +msgstr "Regel succesvol bijgewerkt" + #: apps/dca/models.py:17 msgid "Target Currency" msgstr "Doel Munteenheid" @@ -453,7 +554,7 @@ msgstr "Betaal Munteenheid" #: apps/dca/models.py:27 apps/dca/models.py:179 apps/rules/models.py:26 #: apps/transactions/forms.py:333 apps/transactions/models.py:155 -#: apps/transactions/models.py:323 apps/transactions/models.py:504 +#: apps/transactions/models.py:337 apps/transactions/models.py:518 msgid "Notes" msgstr "Opmerkingen" @@ -617,7 +718,7 @@ msgstr "Een waarde voor dit veld bestaat al in de regel." #: apps/rules/models.py:10 apps/rules/models.py:25 #: apps/transactions/forms.py:325 apps/transactions/models.py:153 -#: apps/transactions/models.py:281 apps/transactions/models.py:490 +#: apps/transactions/models.py:295 apps/transactions/models.py:504 msgid "Description" msgstr "Beschrijving" @@ -626,7 +727,7 @@ msgid "Trigger" msgstr "Trigger" #: apps/rules/models.py:20 apps/transactions/models.py:139 -#: apps/transactions/models.py:279 apps/transactions/models.py:482 +#: apps/transactions/models.py:293 apps/transactions/models.py:496 msgid "Type" msgstr "Soort" @@ -640,21 +741,21 @@ msgstr "Betaald" #: apps/rules/models.py:23 apps/transactions/forms.py:66 #: apps/transactions/forms.py:322 apps/transactions/forms.py:492 -#: apps/transactions/models.py:143 apps/transactions/models.py:297 -#: apps/transactions/models.py:506 +#: apps/transactions/models.py:143 apps/transactions/models.py:311 +#: apps/transactions/models.py:520 msgid "Reference Date" msgstr "Referentiedatum" #: apps/rules/models.py:24 apps/transactions/models.py:148 -#: apps/transactions/models.py:487 +#: apps/transactions/models.py:501 msgid "Amount" msgstr "Bedrag" #: apps/rules/models.py:29 apps/transactions/filters.py:81 #: apps/transactions/forms.py:55 apps/transactions/forms.py:486 #: apps/transactions/forms.py:731 apps/transactions/models.py:117 -#: apps/transactions/models.py:170 apps/transactions/models.py:319 -#: apps/transactions/models.py:501 templates/entities/fragments/list.html:5 +#: apps/transactions/models.py:170 apps/transactions/models.py:333 +#: apps/transactions/models.py:515 templates/entities/fragments/list.html:5 #: templates/entities/pages/index.html:4 templates/includes/navbar.html:107 msgid "Entities" msgstr "Bedrijven" @@ -792,14 +893,6 @@ msgstr "De einddatum moet na de begindatum vallen" msgid "Mute" msgstr "Gedempt" -#: apps/transactions/models.py:71 apps/transactions/models.py:90 -#: apps/transactions/models.py:109 templates/categories/fragments/list.html:21 -#: templates/entities/fragments/list.html:21 -#: templates/recurring_transactions/fragments/list.html:21 -#: templates/tags/fragments/list.html:21 -msgid "Active" -msgstr "Actief" - #: apps/transactions/models.py:73 msgid "" "Deactivated categories won't be able to be selected when creating new " @@ -858,11 +951,11 @@ msgstr "Ontvangsten Transactie" msgid "Expense" msgstr "Uitgave Transactie" -#: apps/transactions/models.py:181 apps/transactions/models.py:326 +#: apps/transactions/models.py:181 apps/transactions/models.py:340 msgid "Installment Plan" msgstr "Afbetalingsplan" -#: apps/transactions/models.py:190 apps/transactions/models.py:527 +#: apps/transactions/models.py:190 apps/transactions/models.py:541 msgid "Recurring Transaction" msgstr "Terugkerende verrichting" @@ -894,95 +987,95 @@ msgstr "Verrichting" msgid "Transactions" msgstr "Verrichtingen" -#: apps/transactions/models.py:268 +#: apps/transactions/models.py:282 msgid "Yearly" msgstr "Jaarlijks" -#: apps/transactions/models.py:269 apps/users/models.py:26 +#: apps/transactions/models.py:283 apps/users/models.py:26 #: templates/includes/navbar.html:26 msgid "Monthly" msgstr "Maandelijks" -#: apps/transactions/models.py:270 +#: apps/transactions/models.py:284 msgid "Weekly" msgstr "Wekelijks" -#: apps/transactions/models.py:271 +#: apps/transactions/models.py:285 msgid "Daily" msgstr "Dagelijks" -#: apps/transactions/models.py:284 +#: apps/transactions/models.py:298 msgid "Number of Installments" msgstr "Aantal aflossingen" -#: apps/transactions/models.py:289 +#: apps/transactions/models.py:303 msgid "Installment Start" msgstr "Begin afbetaling" -#: apps/transactions/models.py:290 +#: apps/transactions/models.py:304 msgid "The installment number to start counting from" msgstr "Het nummer van de aflevering om mee te beginnen" -#: apps/transactions/models.py:295 apps/transactions/models.py:510 +#: apps/transactions/models.py:309 apps/transactions/models.py:524 msgid "Start Date" msgstr "Startdatum" -#: apps/transactions/models.py:299 apps/transactions/models.py:511 +#: apps/transactions/models.py:313 apps/transactions/models.py:525 msgid "End Date" msgstr "Einddatum" -#: apps/transactions/models.py:304 +#: apps/transactions/models.py:318 msgid "Recurrence" msgstr "Terugkeerpatroon" -#: apps/transactions/models.py:307 +#: apps/transactions/models.py:321 msgid "Installment Amount" msgstr "Termijnbedrag" -#: apps/transactions/models.py:327 templates/includes/navbar.html:69 +#: apps/transactions/models.py:341 templates/includes/navbar.html:69 #: templates/installment_plans/fragments/list.html:5 #: templates/installment_plans/pages/index.html:4 msgid "Installment Plans" msgstr "Afbetalingsplannen" -#: apps/transactions/models.py:469 +#: apps/transactions/models.py:483 msgid "day(s)" msgstr "dag(en)" -#: apps/transactions/models.py:470 +#: apps/transactions/models.py:484 msgid "week(s)" msgstr "we(e)k(en)" -#: apps/transactions/models.py:471 +#: apps/transactions/models.py:485 msgid "month(s)" msgstr "maand(en)" -#: apps/transactions/models.py:472 +#: apps/transactions/models.py:486 msgid "year(s)" msgstr "ja(a)r(en)" -#: apps/transactions/models.py:474 +#: apps/transactions/models.py:488 #: templates/recurring_transactions/fragments/list.html:24 msgid "Paused" msgstr "Gepauzeerd" -#: apps/transactions/models.py:513 +#: apps/transactions/models.py:527 msgid "Recurrence Type" msgstr "Type Terugkeerpatroon" -#: apps/transactions/models.py:516 +#: apps/transactions/models.py:530 msgid "Recurrence Interval" msgstr "Terugkeer Interval" -#: apps/transactions/models.py:520 +#: apps/transactions/models.py:534 msgid "Last Generated Date" msgstr "Laatste Gegenereerde Datum" -#: apps/transactions/models.py:523 +#: apps/transactions/models.py:537 msgid "Last Generated Reference Date" msgstr "Laatste Gegenereerde Referentiedatum" -#: apps/transactions/models.py:528 templates/includes/navbar.html:71 +#: apps/transactions/models.py:542 templates/includes/navbar.html:71 #: templates/recurring_transactions/fragments/list.html:5 #: templates/recurring_transactions/pages/index.html:4 msgid "Recurring Transactions" @@ -1187,15 +1280,15 @@ msgstr "Deze gebruiker is gedeactiveerd" msgid "Default" msgstr "Standaard" -#: apps/users/forms.py:91 apps/users/models.py:40 +#: apps/users/forms.py:91 apps/users/models.py:41 msgid "Date Format" msgstr "Datumnotatie" -#: apps/users/forms.py:96 apps/users/models.py:45 +#: apps/users/forms.py:96 apps/users/models.py:46 msgid "Datetime Format" msgstr "Tijdsnotatie" -#: apps/users/forms.py:102 apps/users/models.py:48 +#: apps/users/forms.py:102 apps/users/models.py:49 msgid "Number Format" msgstr "Schrijfwijze Nummers" @@ -1211,51 +1304,55 @@ msgstr "Jaarlijks per munteenheid" msgid "Yearly by account" msgstr "Jaarlijks per rekening" -#: apps/users/models.py:29 templates/includes/navbar.html:40 -msgid "Net Worth" -msgstr "Netto Waarde" +#: apps/users/models.py:29 templates/net_worth/net_worth.html:9 +msgid "Current Net Worth" +msgstr "Huidige Nettowaarde" -#: apps/users/models.py:30 +#: apps/users/models.py:30 templates/net_worth/net_worth.html:9 +msgid "Projected Net Worth" +msgstr "Verwachte Nettowaarde" + +#: apps/users/models.py:31 msgid "All Transactions" msgstr "Alle Verrichtingen" -#: apps/users/models.py:31 templates/includes/navbar.html:32 +#: apps/users/models.py:32 templates/includes/navbar.html:32 msgid "Calendar" msgstr "Kalender" -#: apps/users/models.py:53 apps/users/models.py:59 +#: apps/users/models.py:54 apps/users/models.py:60 msgid "Auto" msgstr "Automatisch" -#: apps/users/models.py:55 +#: apps/users/models.py:56 msgid "Language" msgstr "Taal" -#: apps/users/models.py:61 +#: apps/users/models.py:62 msgid "Time Zone" msgstr "Tijdszone" -#: apps/users/models.py:67 +#: apps/users/models.py:68 msgid "Start page" msgstr "Startpagina" -#: apps/users/views.py:60 +#: apps/users/views.py:62 msgid "Transaction amounts are now hidden" msgstr "Verrichtingsbedragen worden nu verborgen" -#: apps/users/views.py:63 +#: apps/users/views.py:65 msgid "Transaction amounts are now displayed" msgstr "Verrichtingsbedragen worden nu weergegeven" -#: apps/users/views.py:81 +#: apps/users/views.py:83 msgid "Sounds are now muted" msgstr "De Geluiden zijn nu gedempt" -#: apps/users/views.py:84 +#: apps/users/views.py:86 msgid "Sounds will now play" msgstr "De geluiden worden nu afgespeeld" -#: apps/users/views.py:100 +#: apps/users/views.py:102 msgid "Your settings have been updated" msgstr "Jouw instellingen zijn bijgewerkt" @@ -1274,6 +1371,8 @@ msgstr "Rekeningsgroep bewerken" #: templates/dca/fragments/strategy/details.html:63 #: templates/entities/fragments/table.html:23 #: templates/exchange_rates/fragments/table.html:19 +#: templates/exchange_rates_services/fragments/list.html:43 +#: templates/exchange_rates_services/fragments/table.html:19 #: templates/import_app/fragments/profiles/list.html:44 #: templates/installment_plans/fragments/table.html:23 #: templates/recurring_transactions/fragments/table.html:25 @@ -1292,6 +1391,8 @@ msgstr "Acties" #: templates/dca/fragments/strategy/list.html:34 #: templates/entities/fragments/table.html:28 #: templates/exchange_rates/fragments/table.html:23 +#: templates/exchange_rates_services/fragments/list.html:47 +#: templates/exchange_rates_services/fragments/table.html:23 #: templates/import_app/fragments/profiles/list.html:48 #: templates/installment_plans/fragments/table.html:27 #: templates/recurring_transactions/fragments/table.html:29 @@ -1313,6 +1414,8 @@ msgstr "Bijwerken" #: templates/dca/fragments/strategy/list.html:42 #: templates/entities/fragments/table.html:36 #: templates/exchange_rates/fragments/table.html:31 +#: templates/exchange_rates_services/fragments/list.html:54 +#: templates/exchange_rates_services/fragments/table.html:31 #: templates/import_app/fragments/profiles/list.html:69 #: templates/import_app/fragments/runs/list.html:102 #: templates/installment_plans/fragments/table.html:56 @@ -1336,6 +1439,8 @@ msgstr "Verwijderen" #: templates/dca/fragments/strategy/list.html:46 #: templates/entities/fragments/table.html:40 #: templates/exchange_rates/fragments/table.html:36 +#: templates/exchange_rates_services/fragments/list.html:58 +#: templates/exchange_rates_services/fragments/table.html:36 #: templates/import_app/fragments/profiles/list.html:73 #: templates/import_app/fragments/runs/list.html:106 #: templates/installment_plans/fragments/table.html:48 @@ -1362,6 +1467,8 @@ msgstr "Weet je het zeker?" #: templates/dca/fragments/strategy/list.html:47 #: templates/entities/fragments/table.html:41 #: templates/exchange_rates/fragments/table.html:37 +#: templates/exchange_rates_services/fragments/list.html:59 +#: templates/exchange_rates_services/fragments/table.html:37 #: templates/import_app/fragments/profiles/list.html:74 #: templates/rules/fragments/list.html:49 #: templates/rules/fragments/transaction_rule/view.html:61 @@ -1379,6 +1486,8 @@ msgstr "Je kunt dit niet meer terugdraaien!" #: templates/dca/fragments/strategy/list.html:48 #: templates/entities/fragments/table.html:42 #: templates/exchange_rates/fragments/table.html:38 +#: templates/exchange_rates_services/fragments/list.html:60 +#: templates/exchange_rates_services/fragments/table.html:38 #: templates/import_app/fragments/profiles/list.html:75 #: templates/import_app/fragments/runs/list.html:108 #: templates/installment_plans/fragments/table.html:62 @@ -1510,37 +1619,37 @@ msgid "Restore" msgstr "" #: templates/cotton/ui/account_card.html:15 -#: templates/cotton/ui/currency_card.html:13 +#: templates/cotton/ui/currency_card.html:10 msgid "projected income" msgstr "verwachte inkomsten" #: templates/cotton/ui/account_card.html:37 -#: templates/cotton/ui/currency_card.html:35 +#: templates/cotton/ui/currency_card.html:32 msgid "projected expenses" msgstr "verwachte uitgaven" #: templates/cotton/ui/account_card.html:61 -#: templates/cotton/ui/currency_card.html:59 +#: templates/cotton/ui/currency_card.html:56 msgid "projected total" msgstr "verwachte totaal" #: templates/cotton/ui/account_card.html:86 -#: templates/cotton/ui/currency_card.html:84 +#: templates/cotton/ui/currency_card.html:81 msgid "current income" msgstr "huidige inkomsten" #: templates/cotton/ui/account_card.html:108 -#: templates/cotton/ui/currency_card.html:106 +#: templates/cotton/ui/currency_card.html:103 msgid "current expenses" msgstr "huidige uitgaven" #: templates/cotton/ui/account_card.html:130 -#: templates/cotton/ui/currency_card.html:128 +#: templates/cotton/ui/currency_card.html:125 msgid "current total" msgstr "huidige totaal" #: templates/cotton/ui/account_card.html:156 -#: templates/cotton/ui/currency_card.html:154 +#: templates/cotton/ui/currency_card.html:151 msgid "final total" msgstr "eindtotaal" @@ -1794,10 +1903,12 @@ msgid "No entities" msgstr "Geen bedrijven" #: templates/exchange_rates/fragments/add.html:5 +#: templates/exchange_rates_services/fragments/add.html:5 msgid "Add exchange rate" msgstr "Wisselkoers toevoegen" #: templates/exchange_rates/fragments/edit.html:5 +#: templates/exchange_rates_services/fragments/edit.html:5 msgid "Edit exchange rate" msgstr "Wisselkoers bewerken" @@ -1810,22 +1921,76 @@ msgid "All" msgstr "Allemaal" #: templates/exchange_rates/fragments/table.html:11 +#: templates/exchange_rates_services/fragments/table.html:11 msgid "Pairing" msgstr "Koppelen" #: templates/exchange_rates/fragments/table.html:12 +#: templates/exchange_rates_services/fragments/table.html:12 msgid "Rate" msgstr "Tarief" #: templates/exchange_rates/fragments/table.html:51 +#: templates/exchange_rates_services/fragments/table.html:51 msgid "No exchange rates" msgstr "Geen wisselkoersen" #: templates/exchange_rates/fragments/table.html:58 +#: templates/exchange_rates_services/fragments/table.html:58 #: templates/transactions/fragments/list_all.html:47 msgid "Page navigation" msgstr "Paginanavigatie" +#: templates/exchange_rates_services/fragments/list.html:6 +#: templates/exchange_rates_services/pages/index.html:4 +#: templates/includes/navbar.html:133 +#, fuzzy +#| msgid "Exchange Rates" +msgid "Automatic Exchange Rates" +msgstr "Wisselkoersen" + +#: templates/exchange_rates_services/fragments/list.html:21 +msgid "Fetch all" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:33 +#, fuzzy +#| msgid "Overview" +msgid "Service" +msgstr "Overzicht" + +#: templates/exchange_rates_services/fragments/list.html:34 +msgid "Targeting" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:35 +msgid "Fetch every" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:36 +msgid "Last fetch" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:68 +#, fuzzy +#| msgid "Currencies" +msgid "currencies" +msgstr "Munteenheden" + +#: templates/exchange_rates_services/fragments/list.html:68 +#, fuzzy +#| msgid "Accounts" +msgid "accounts" +msgstr "Rekeningen" + +#: templates/exchange_rates_services/fragments/list.html:69 +msgid "hours" +msgstr "" + +#: templates/exchange_rates_services/fragments/list.html:77 +msgid "No services configured" +msgstr "" + #: templates/import_app/fragments/profiles/add.html:6 msgid "Add new import profile" msgstr "Nieuw importprofiel toevoegen" @@ -1924,6 +2089,10 @@ msgstr "Navigatie Knop" msgid "Overview" msgstr "Overzicht" +#: templates/includes/navbar.html:40 +msgid "Net Worth" +msgstr "Netto Waarde" + #: templates/includes/navbar.html:44 msgid "Current" msgstr "Huidige" @@ -1965,15 +2134,15 @@ msgstr "Automatisatie" msgid "Rules" msgstr "Regels" -#: templates/includes/navbar.html:141 +#: templates/includes/navbar.html:143 msgid "Only use this if you know what you're doing" msgstr "Gebruik dit alleen als je weet wat je doet" -#: templates/includes/navbar.html:142 +#: templates/includes/navbar.html:144 msgid "Django Admin" msgstr "Django Beheerder" -#: templates/includes/navbar.html:151 +#: templates/includes/navbar.html:153 msgid "Calculator" msgstr "Rekenmachine" @@ -2142,14 +2311,6 @@ msgstr "Oudste eerst" msgid "Newest first" msgstr "Nieuwste eerst" -#: templates/net_worth/net_worth.html:9 -msgid "Current Net Worth" -msgstr "Huidige Nettowaarde" - -#: templates/net_worth/net_worth.html:9 -msgid "Projected Net Worth" -msgstr "Verwachte Nettowaarde" - #: templates/net_worth/net_worth.html:17 #: templates/yearly_overview/pages/overview_by_currency.html:9 msgid "By currency" @@ -2385,3 +2546,8 @@ msgstr "Jaaroverzicht" #: templates/yearly_overview/pages/overview_by_currency.html:63 msgid "Year" msgstr "Jaar" + +#, fuzzy +#~| msgid "Exchange rate deleted successfully" +#~ msgid "Exchange rates queued to be fetched successfully" +#~ msgstr "Wisselkoers succesvol verwijderd" diff --git a/app/locale/pt_BR/LC_MESSAGES/django.po b/app/locale/pt_BR/LC_MESSAGES/django.po index 20b11ea..2822f3d 100644 --- a/app/locale/pt_BR/LC_MESSAGES/django.po +++ b/app/locale/pt_BR/LC_MESSAGES/django.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-02-01 22:04+0000\n" -"PO-Revision-Date: 2025-02-01 19:04-0300\n" +"POT-Creation-Date: 2025-02-04 03:20+0000\n" +"PO-Revision-Date: 2025-02-04 00:22-0300\n" "Last-Translator: Herculino Trotta\n" "Language-Team: \n" "Language: pt_BR\n" @@ -24,23 +24,24 @@ msgid "Group name" msgstr "Nome do grupo" #: apps/accounts/forms.py:40 apps/accounts/forms.py:96 -#: apps/currencies/forms.py:52 apps/currencies/forms.py:90 apps/dca/forms.py:41 -#: apps/dca/forms.py:93 apps/import_app/forms.py:34 apps/rules/forms.py:45 -#: apps/rules/forms.py:87 apps/transactions/forms.py:190 -#: apps/transactions/forms.py:257 apps/transactions/forms.py:581 -#: apps/transactions/forms.py:624 apps/transactions/forms.py:656 -#: apps/transactions/forms.py:691 apps/transactions/forms.py:827 +#: apps/currencies/forms.py:53 apps/currencies/forms.py:91 +#: apps/currencies/forms.py:138 apps/dca/forms.py:41 apps/dca/forms.py:93 +#: apps/import_app/forms.py:34 apps/rules/forms.py:45 apps/rules/forms.py:87 +#: apps/transactions/forms.py:190 apps/transactions/forms.py:257 +#: apps/transactions/forms.py:581 apps/transactions/forms.py:624 +#: apps/transactions/forms.py:656 apps/transactions/forms.py:691 +#: apps/transactions/forms.py:827 msgid "Update" msgstr "Atualizar" #: apps/accounts/forms.py:48 apps/accounts/forms.py:104 -#: apps/common/widgets/tom_select.py:12 apps/currencies/forms.py:60 -#: apps/currencies/forms.py:98 apps/dca/forms.py:49 apps/dca/forms.py:102 -#: apps/import_app/forms.py:42 apps/rules/forms.py:53 apps/rules/forms.py:95 -#: apps/transactions/forms.py:174 apps/transactions/forms.py:199 -#: apps/transactions/forms.py:589 apps/transactions/forms.py:632 -#: apps/transactions/forms.py:664 apps/transactions/forms.py:699 -#: apps/transactions/forms.py:835 +#: apps/common/widgets/tom_select.py:12 apps/currencies/forms.py:61 +#: apps/currencies/forms.py:99 apps/currencies/forms.py:146 +#: apps/dca/forms.py:49 apps/dca/forms.py:102 apps/import_app/forms.py:42 +#: apps/rules/forms.py:53 apps/rules/forms.py:95 apps/transactions/forms.py:174 +#: apps/transactions/forms.py:199 apps/transactions/forms.py:589 +#: apps/transactions/forms.py:632 apps/transactions/forms.py:664 +#: apps/transactions/forms.py:699 apps/transactions/forms.py:835 #: templates/account_groups/fragments/list.html:9 #: templates/accounts/fragments/list.html:9 #: templates/categories/fragments/list.html:9 @@ -49,6 +50,7 @@ msgstr "Atualizar" #: templates/dca/fragments/strategy/list.html:9 #: templates/entities/fragments/list.html:9 #: templates/exchange_rates/fragments/list.html:10 +#: templates/exchange_rates_services/fragments/list.html:10 #: templates/import_app/fragments/profiles/list.html:7 #: templates/import_app/fragments/profiles/list.html:10 #: templates/installment_plans/fragments/list.html:9 @@ -70,7 +72,7 @@ msgstr "Novo saldo" #: apps/transactions/forms.py:39 apps/transactions/forms.py:291 #: apps/transactions/forms.py:298 apps/transactions/forms.py:478 #: apps/transactions/forms.py:723 apps/transactions/models.py:159 -#: apps/transactions/models.py:314 apps/transactions/models.py:494 +#: apps/transactions/models.py:328 apps/transactions/models.py:508 msgid "Category" msgstr "Categoria" @@ -78,8 +80,8 @@ msgstr "Categoria" #: apps/transactions/filters.py:74 apps/transactions/forms.py:47 #: apps/transactions/forms.py:307 apps/transactions/forms.py:315 #: apps/transactions/forms.py:471 apps/transactions/forms.py:716 -#: apps/transactions/models.py:165 apps/transactions/models.py:316 -#: apps/transactions/models.py:498 templates/includes/navbar.html:105 +#: apps/transactions/models.py:165 apps/transactions/models.py:330 +#: apps/transactions/models.py:512 templates/includes/navbar.html:105 #: templates/tags/fragments/list.html:5 templates/tags/pages/index.html:4 msgid "Tags" msgstr "Tags" @@ -93,6 +95,7 @@ msgstr "Tags" #: templates/categories/fragments/table.html:16 #: templates/currencies/fragments/list.html:26 #: templates/entities/fragments/table.html:16 +#: templates/exchange_rates_services/fragments/list.html:32 #: templates/import_app/fragments/profiles/list.html:36 #: templates/installment_plans/fragments/table.html:16 #: templates/recurring_transactions/fragments/table.html:18 @@ -111,17 +114,17 @@ msgstr "Grupo da Conta" msgid "Account Groups" msgstr "Grupos da Conta" -#: apps/accounts/models.py:31 apps/currencies/models.py:32 +#: apps/accounts/models.py:31 apps/currencies/models.py:38 #: templates/accounts/fragments/list.html:27 msgid "Currency" msgstr "Moeda" -#: apps/accounts/models.py:37 apps/currencies/models.py:20 +#: apps/accounts/models.py:37 apps/currencies/models.py:26 #: templates/accounts/fragments/list.html:28 msgid "Exchange Currency" msgstr "Moeda de Câmbio" -#: apps/accounts/models.py:42 apps/currencies/models.py:25 +#: apps/accounts/models.py:42 apps/currencies/models.py:31 msgid "Default currency for exchange calculations" msgstr "Moeda padrão para os cálculos de câmbio" @@ -151,7 +154,7 @@ msgstr "" #: apps/accounts/models.py:59 apps/rules/models.py:19 #: apps/transactions/forms.py:59 apps/transactions/forms.py:463 #: apps/transactions/forms.py:708 apps/transactions/models.py:132 -#: apps/transactions/models.py:274 apps/transactions/models.py:476 +#: apps/transactions/models.py:288 apps/transactions/models.py:490 msgid "Account" msgstr "Conta" @@ -349,35 +352,36 @@ msgstr "Limpar" msgid "No results..." msgstr "Sem resultados..." -#: apps/currencies/forms.py:16 apps/currencies/models.py:15 +#: apps/currencies/forms.py:17 apps/currencies/models.py:21 msgid "Prefix" msgstr "Prefixo" -#: apps/currencies/forms.py:17 apps/currencies/models.py:16 +#: apps/currencies/forms.py:18 apps/currencies/models.py:22 msgid "Suffix" msgstr "Sufixo" -#: apps/currencies/forms.py:68 apps/dca/models.py:156 apps/rules/models.py:22 +#: apps/currencies/forms.py:69 apps/dca/models.py:156 apps/rules/models.py:22 #: apps/transactions/forms.py:63 apps/transactions/forms.py:319 #: apps/transactions/models.py:142 #: templates/dca/fragments/strategy/details.html:52 #: templates/exchange_rates/fragments/table.html:10 +#: templates/exchange_rates_services/fragments/table.html:10 msgid "Date" msgstr "Data" -#: apps/currencies/models.py:8 +#: apps/currencies/models.py:13 msgid "Currency Code" msgstr "Código da Moeda" -#: apps/currencies/models.py:9 +#: apps/currencies/models.py:15 msgid "Currency Name" msgstr "Nome da Moeda" -#: apps/currencies/models.py:13 +#: apps/currencies/models.py:19 msgid "Decimal Places" msgstr "Casas Decimais" -#: apps/currencies/models.py:33 apps/transactions/filters.py:60 +#: apps/currencies/models.py:39 apps/transactions/filters.py:60 #: templates/currencies/fragments/list.html:5 #: templates/currencies/pages/index.html:4 templates/includes/navbar.html:119 #: templates/includes/navbar.html:121 @@ -387,36 +391,102 @@ msgstr "Casas Decimais" msgid "Currencies" msgstr "Moedas" -#: apps/currencies/models.py:41 +#: apps/currencies/models.py:47 msgid "Currency cannot have itself as exchange currency." msgstr "A moeda não pode ter a si mesma como moeda de câmbio." -#: apps/currencies/models.py:52 +#: apps/currencies/models.py:58 msgid "From Currency" msgstr "Moeda de origem" -#: apps/currencies/models.py:58 +#: apps/currencies/models.py:64 msgid "To Currency" msgstr "Moeda de destino" -#: apps/currencies/models.py:61 apps/currencies/models.py:66 +#: apps/currencies/models.py:67 apps/currencies/models.py:72 msgid "Exchange Rate" msgstr "Taxa de Câmbio" -#: apps/currencies/models.py:63 +#: apps/currencies/models.py:69 msgid "Date and Time" msgstr "Data e Tempo" -#: apps/currencies/models.py:67 templates/exchange_rates/fragments/list.html:6 +#: apps/currencies/models.py:73 templates/exchange_rates/fragments/list.html:6 #: templates/exchange_rates/pages/index.html:4 #: templates/includes/navbar.html:123 msgid "Exchange Rates" msgstr "Taxas de Câmbio" -#: apps/currencies/models.py:79 +#: apps/currencies/models.py:85 msgid "From and To currencies cannot be the same." msgstr "As moedas De e Para não podem ser as mesmas." +#: apps/currencies/models.py:97 +msgid "Service Name" +msgstr "Nome do Serviço" + +#: apps/currencies/models.py:99 +msgid "Service Type" +msgstr "Tipo de Serviço" + +#: apps/currencies/models.py:101 apps/transactions/models.py:71 +#: apps/transactions/models.py:90 apps/transactions/models.py:109 +#: templates/categories/fragments/list.html:21 +#: templates/entities/fragments/list.html:21 +#: templates/recurring_transactions/fragments/list.html:21 +#: templates/tags/fragments/list.html:21 +msgid "Active" +msgstr "Ativo" + +#: apps/currencies/models.py:106 +msgid "API Key" +msgstr "Chave de API" + +#: apps/currencies/models.py:107 +msgid "API key for the service (if required)" +msgstr "Chave de API para o serviço (se necessário)" + +#: apps/currencies/models.py:112 +msgid "Fetch Interval (hours)" +msgstr "Intervalo de busca (horas)" + +#: apps/currencies/models.py:115 +msgid "Last Successful Fetch" +msgstr "Última execução bem-sucedida" + +#: apps/currencies/models.py:120 +msgid "Target Currencies" +msgstr "Moedas-alvo" + +#: apps/currencies/models.py:122 +msgid "" +"Select currencies to fetch exchange rates for. Rates will be fetched for " +"each currency against their set exchange currency." +msgstr "" +"Selecione as moedas para as quais deseja obter as taxas de câmbio. As taxas " +"serão obtidas para cada moeda em relação à moeda de câmbio definida." + +#: apps/currencies/models.py:130 +msgid "Target Accounts" +msgstr "Contas-alvo" + +#: apps/currencies/models.py:132 +msgid "" +"Select accounts to fetch exchange rates for. Rates will be fetched for each " +"account's currency against their set exchange currency." +msgstr "" +"Selecione as contas para as quais deseja obter taxas de câmbio. As taxas " +"serão obtidas para a moeda de cada conta em relação à moeda de câmbio " +"definida." + +#: apps/currencies/models.py:139 +msgid "Exchange Rate Service" +msgstr "Serviço de Taxa de Câmbio" + +#: apps/currencies/models.py:140 +msgid "Exchange Rate Services" +msgstr "Serviços de Taxa de Câmbio" + #: apps/currencies/views/currencies.py:42 msgid "Currency added successfully" msgstr "Moeda adicionada com sucesso" @@ -441,6 +511,22 @@ msgstr "Taxa de câmbio atualizada com sucesso" msgid "Exchange rate deleted successfully" msgstr "Taxa de câmbio apagada com sucesso" +#: apps/currencies/views/exchange_rates_services.py:46 +msgid "Service added successfully" +msgstr "Serviço adicionado com sucesso" + +#: apps/currencies/views/exchange_rates_services.py:74 +msgid "Service updated successfully" +msgstr "Serviço atualizado com sucesso" + +#: apps/currencies/views/exchange_rates_services.py:100 +msgid "Service deleted successfully" +msgstr "Serviço apagado com sucesso" + +#: apps/currencies/views/exchange_rates_services.py:115 +msgid "Services queued successfully" +msgstr "Serviços marcados para execução com sucesso" + #: apps/dca/models.py:17 msgid "Target Currency" msgstr "Moeda de destino" @@ -451,7 +537,7 @@ msgstr "Moeda de pagamento" #: apps/dca/models.py:27 apps/dca/models.py:179 apps/rules/models.py:26 #: apps/transactions/forms.py:333 apps/transactions/models.py:155 -#: apps/transactions/models.py:323 apps/transactions/models.py:504 +#: apps/transactions/models.py:337 apps/transactions/models.py:518 msgid "Notes" msgstr "Notas" @@ -615,7 +701,7 @@ msgstr "Já existe um valor para esse campo na regra." #: apps/rules/models.py:10 apps/rules/models.py:25 #: apps/transactions/forms.py:325 apps/transactions/models.py:153 -#: apps/transactions/models.py:281 apps/transactions/models.py:490 +#: apps/transactions/models.py:295 apps/transactions/models.py:504 msgid "Description" msgstr "Descrição" @@ -624,7 +710,7 @@ msgid "Trigger" msgstr "Gatilho" #: apps/rules/models.py:20 apps/transactions/models.py:139 -#: apps/transactions/models.py:279 apps/transactions/models.py:482 +#: apps/transactions/models.py:293 apps/transactions/models.py:496 msgid "Type" msgstr "Tipo" @@ -638,21 +724,21 @@ msgstr "Pago" #: apps/rules/models.py:23 apps/transactions/forms.py:66 #: apps/transactions/forms.py:322 apps/transactions/forms.py:492 -#: apps/transactions/models.py:143 apps/transactions/models.py:297 -#: apps/transactions/models.py:506 +#: apps/transactions/models.py:143 apps/transactions/models.py:311 +#: apps/transactions/models.py:520 msgid "Reference Date" msgstr "Data de Referência" #: apps/rules/models.py:24 apps/transactions/models.py:148 -#: apps/transactions/models.py:487 +#: apps/transactions/models.py:501 msgid "Amount" msgstr "Quantia" #: apps/rules/models.py:29 apps/transactions/filters.py:81 #: apps/transactions/forms.py:55 apps/transactions/forms.py:486 #: apps/transactions/forms.py:731 apps/transactions/models.py:117 -#: apps/transactions/models.py:170 apps/transactions/models.py:319 -#: apps/transactions/models.py:501 templates/entities/fragments/list.html:5 +#: apps/transactions/models.py:170 apps/transactions/models.py:333 +#: apps/transactions/models.py:515 templates/entities/fragments/list.html:5 #: templates/entities/pages/index.html:4 templates/includes/navbar.html:107 msgid "Entities" msgstr "Entidades" @@ -790,14 +876,6 @@ msgstr "Data final deve ser após data inicial" msgid "Mute" msgstr "Silenciada" -#: apps/transactions/models.py:71 apps/transactions/models.py:90 -#: apps/transactions/models.py:109 templates/categories/fragments/list.html:21 -#: templates/entities/fragments/list.html:21 -#: templates/recurring_transactions/fragments/list.html:21 -#: templates/tags/fragments/list.html:21 -msgid "Active" -msgstr "Ativo" - #: apps/transactions/models.py:73 msgid "" "Deactivated categories won't be able to be selected when creating new " @@ -855,11 +933,11 @@ msgstr "Renda" msgid "Expense" msgstr "Despesa" -#: apps/transactions/models.py:181 apps/transactions/models.py:326 +#: apps/transactions/models.py:181 apps/transactions/models.py:340 msgid "Installment Plan" msgstr "Parcelamento" -#: apps/transactions/models.py:190 apps/transactions/models.py:527 +#: apps/transactions/models.py:190 apps/transactions/models.py:541 msgid "Recurring Transaction" msgstr "Transação Recorrente" @@ -891,95 +969,95 @@ msgstr "Transação" msgid "Transactions" msgstr "Transações" -#: apps/transactions/models.py:268 +#: apps/transactions/models.py:282 msgid "Yearly" msgstr "Anual" -#: apps/transactions/models.py:269 apps/users/models.py:26 +#: apps/transactions/models.py:283 apps/users/models.py:26 #: templates/includes/navbar.html:26 msgid "Monthly" msgstr "Mensal" -#: apps/transactions/models.py:270 +#: apps/transactions/models.py:284 msgid "Weekly" msgstr "Semanal" -#: apps/transactions/models.py:271 +#: apps/transactions/models.py:285 msgid "Daily" msgstr "Diária" -#: apps/transactions/models.py:284 +#: apps/transactions/models.py:298 msgid "Number of Installments" msgstr "Número de Parcelas" -#: apps/transactions/models.py:289 +#: apps/transactions/models.py:303 msgid "Installment Start" msgstr "Parcela inicial" -#: apps/transactions/models.py:290 +#: apps/transactions/models.py:304 msgid "The installment number to start counting from" msgstr "O número da parcela a partir do qual se inicia a contagem" -#: apps/transactions/models.py:295 apps/transactions/models.py:510 +#: apps/transactions/models.py:309 apps/transactions/models.py:524 msgid "Start Date" msgstr "Data de Início" -#: apps/transactions/models.py:299 apps/transactions/models.py:511 +#: apps/transactions/models.py:313 apps/transactions/models.py:525 msgid "End Date" msgstr "Data Final" -#: apps/transactions/models.py:304 +#: apps/transactions/models.py:318 msgid "Recurrence" msgstr "Recorrência" -#: apps/transactions/models.py:307 +#: apps/transactions/models.py:321 msgid "Installment Amount" msgstr "Valor da Parcela" -#: apps/transactions/models.py:327 templates/includes/navbar.html:69 +#: apps/transactions/models.py:341 templates/includes/navbar.html:69 #: templates/installment_plans/fragments/list.html:5 #: templates/installment_plans/pages/index.html:4 msgid "Installment Plans" msgstr "Parcelamentos" -#: apps/transactions/models.py:469 +#: apps/transactions/models.py:483 msgid "day(s)" msgstr "dia(s)" -#: apps/transactions/models.py:470 +#: apps/transactions/models.py:484 msgid "week(s)" msgstr "semana(s)" -#: apps/transactions/models.py:471 +#: apps/transactions/models.py:485 msgid "month(s)" msgstr "mês(es)" -#: apps/transactions/models.py:472 +#: apps/transactions/models.py:486 msgid "year(s)" msgstr "ano(s)" -#: apps/transactions/models.py:474 +#: apps/transactions/models.py:488 #: templates/recurring_transactions/fragments/list.html:24 msgid "Paused" msgstr "Pausado" -#: apps/transactions/models.py:513 +#: apps/transactions/models.py:527 msgid "Recurrence Type" msgstr "Tipo de recorrência" -#: apps/transactions/models.py:516 +#: apps/transactions/models.py:530 msgid "Recurrence Interval" msgstr "Intervalo de recorrência" -#: apps/transactions/models.py:520 +#: apps/transactions/models.py:534 msgid "Last Generated Date" msgstr "Última data gerada" -#: apps/transactions/models.py:523 +#: apps/transactions/models.py:537 msgid "Last Generated Reference Date" msgstr "Última data de referência gerada" -#: apps/transactions/models.py:528 templates/includes/navbar.html:71 +#: apps/transactions/models.py:542 templates/includes/navbar.html:71 #: templates/recurring_transactions/fragments/list.html:5 #: templates/recurring_transactions/pages/index.html:4 msgid "Recurring Transactions" @@ -1180,15 +1258,15 @@ msgstr "Essa conta está desativada" msgid "Default" msgstr "Padrão" -#: apps/users/forms.py:91 apps/users/models.py:40 +#: apps/users/forms.py:91 apps/users/models.py:41 msgid "Date Format" msgstr "Formato de Data" -#: apps/users/forms.py:96 apps/users/models.py:45 +#: apps/users/forms.py:96 apps/users/models.py:46 msgid "Datetime Format" msgstr "Formato de Data e Hora" -#: apps/users/forms.py:102 apps/users/models.py:48 +#: apps/users/forms.py:102 apps/users/models.py:49 msgid "Number Format" msgstr "Formato de Número" @@ -1204,51 +1282,55 @@ msgstr "Anual por moeda" msgid "Yearly by account" msgstr "Anual por conta" -#: apps/users/models.py:29 templates/includes/navbar.html:40 -msgid "Net Worth" -msgstr "Patrimônio" +#: apps/users/models.py:29 templates/net_worth/net_worth.html:9 +msgid "Current Net Worth" +msgstr "Patrimônio Atual" -#: apps/users/models.py:30 +#: apps/users/models.py:30 templates/net_worth/net_worth.html:9 +msgid "Projected Net Worth" +msgstr "Patrimônio Previsto" + +#: apps/users/models.py:31 msgid "All Transactions" msgstr "Todas as transações" -#: apps/users/models.py:31 templates/includes/navbar.html:32 +#: apps/users/models.py:32 templates/includes/navbar.html:32 msgid "Calendar" msgstr "Calendário" -#: apps/users/models.py:53 apps/users/models.py:59 +#: apps/users/models.py:54 apps/users/models.py:60 msgid "Auto" msgstr "Automático" -#: apps/users/models.py:55 +#: apps/users/models.py:56 msgid "Language" msgstr "Linguagem" -#: apps/users/models.py:61 +#: apps/users/models.py:62 msgid "Time Zone" msgstr "Fuso horário" -#: apps/users/models.py:67 +#: apps/users/models.py:68 msgid "Start page" msgstr "Página inicial" -#: apps/users/views.py:60 +#: apps/users/views.py:62 msgid "Transaction amounts are now hidden" msgstr "Os valores das transações agora estão ocultos" -#: apps/users/views.py:63 +#: apps/users/views.py:65 msgid "Transaction amounts are now displayed" msgstr "Os valores das transações agora estão sendo exibidos" -#: apps/users/views.py:81 +#: apps/users/views.py:83 msgid "Sounds are now muted" msgstr "Os sons agora estão silenciados" -#: apps/users/views.py:84 +#: apps/users/views.py:86 msgid "Sounds will now play" msgstr "Os sons agora serão reproduzidos" -#: apps/users/views.py:100 +#: apps/users/views.py:102 msgid "Your settings have been updated" msgstr "Suas configurações foram atualizadas" @@ -1267,6 +1349,8 @@ msgstr "Editar grupo de conta" #: templates/dca/fragments/strategy/details.html:63 #: templates/entities/fragments/table.html:23 #: templates/exchange_rates/fragments/table.html:19 +#: templates/exchange_rates_services/fragments/list.html:43 +#: templates/exchange_rates_services/fragments/table.html:19 #: templates/import_app/fragments/profiles/list.html:44 #: templates/installment_plans/fragments/table.html:23 #: templates/recurring_transactions/fragments/table.html:25 @@ -1285,6 +1369,8 @@ msgstr "Ações" #: templates/dca/fragments/strategy/list.html:34 #: templates/entities/fragments/table.html:28 #: templates/exchange_rates/fragments/table.html:23 +#: templates/exchange_rates_services/fragments/list.html:47 +#: templates/exchange_rates_services/fragments/table.html:23 #: templates/import_app/fragments/profiles/list.html:48 #: templates/installment_plans/fragments/table.html:27 #: templates/recurring_transactions/fragments/table.html:29 @@ -1306,6 +1392,8 @@ msgstr "Editar" #: templates/dca/fragments/strategy/list.html:42 #: templates/entities/fragments/table.html:36 #: templates/exchange_rates/fragments/table.html:31 +#: templates/exchange_rates_services/fragments/list.html:54 +#: templates/exchange_rates_services/fragments/table.html:31 #: templates/import_app/fragments/profiles/list.html:69 #: templates/import_app/fragments/runs/list.html:102 #: templates/installment_plans/fragments/table.html:56 @@ -1329,6 +1417,8 @@ msgstr "Apagar" #: templates/dca/fragments/strategy/list.html:46 #: templates/entities/fragments/table.html:40 #: templates/exchange_rates/fragments/table.html:36 +#: templates/exchange_rates_services/fragments/list.html:58 +#: templates/exchange_rates_services/fragments/table.html:36 #: templates/import_app/fragments/profiles/list.html:73 #: templates/import_app/fragments/runs/list.html:106 #: templates/installment_plans/fragments/table.html:48 @@ -1355,6 +1445,8 @@ msgstr "Tem certeza?" #: templates/dca/fragments/strategy/list.html:47 #: templates/entities/fragments/table.html:41 #: templates/exchange_rates/fragments/table.html:37 +#: templates/exchange_rates_services/fragments/list.html:59 +#: templates/exchange_rates_services/fragments/table.html:37 #: templates/import_app/fragments/profiles/list.html:74 #: templates/rules/fragments/list.html:49 #: templates/rules/fragments/transaction_rule/view.html:61 @@ -1372,6 +1464,8 @@ msgstr "Você não será capaz de reverter isso!" #: templates/dca/fragments/strategy/list.html:48 #: templates/entities/fragments/table.html:42 #: templates/exchange_rates/fragments/table.html:38 +#: templates/exchange_rates_services/fragments/list.html:60 +#: templates/exchange_rates_services/fragments/table.html:38 #: templates/import_app/fragments/profiles/list.html:75 #: templates/import_app/fragments/runs/list.html:108 #: templates/installment_plans/fragments/table.html:62 @@ -1503,37 +1597,37 @@ msgid "Restore" msgstr "Restaurar" #: templates/cotton/ui/account_card.html:15 -#: templates/cotton/ui/currency_card.html:13 +#: templates/cotton/ui/currency_card.html:10 msgid "projected income" msgstr "renda prevista" #: templates/cotton/ui/account_card.html:37 -#: templates/cotton/ui/currency_card.html:35 +#: templates/cotton/ui/currency_card.html:32 msgid "projected expenses" msgstr "despesas previstas" #: templates/cotton/ui/account_card.html:61 -#: templates/cotton/ui/currency_card.html:59 +#: templates/cotton/ui/currency_card.html:56 msgid "projected total" msgstr "total previsto" #: templates/cotton/ui/account_card.html:86 -#: templates/cotton/ui/currency_card.html:84 +#: templates/cotton/ui/currency_card.html:81 msgid "current income" msgstr "renda atual" #: templates/cotton/ui/account_card.html:108 -#: templates/cotton/ui/currency_card.html:106 +#: templates/cotton/ui/currency_card.html:103 msgid "current expenses" msgstr "despesas atuais" #: templates/cotton/ui/account_card.html:130 -#: templates/cotton/ui/currency_card.html:128 +#: templates/cotton/ui/currency_card.html:125 msgid "current total" msgstr "total atual" #: templates/cotton/ui/account_card.html:156 -#: templates/cotton/ui/currency_card.html:154 +#: templates/cotton/ui/currency_card.html:151 msgid "final total" msgstr "total final" @@ -1788,10 +1882,12 @@ msgid "No entities" msgstr "Sem entidades" #: templates/exchange_rates/fragments/add.html:5 +#: templates/exchange_rates_services/fragments/add.html:5 msgid "Add exchange rate" msgstr "Adicionar taxa de câmbio" #: templates/exchange_rates/fragments/edit.html:5 +#: templates/exchange_rates_services/fragments/edit.html:5 msgid "Edit exchange rate" msgstr "Editar taxa de câmbio" @@ -1804,22 +1900,68 @@ msgid "All" msgstr "Todas" #: templates/exchange_rates/fragments/table.html:11 +#: templates/exchange_rates_services/fragments/table.html:11 msgid "Pairing" msgstr "Pares" #: templates/exchange_rates/fragments/table.html:12 +#: templates/exchange_rates_services/fragments/table.html:12 msgid "Rate" msgstr "Taxa de Câmbio" #: templates/exchange_rates/fragments/table.html:51 +#: templates/exchange_rates_services/fragments/table.html:51 msgid "No exchange rates" msgstr "Nenhuma taxa de câmbio" #: templates/exchange_rates/fragments/table.html:58 +#: templates/exchange_rates_services/fragments/table.html:58 #: templates/transactions/fragments/list_all.html:47 msgid "Page navigation" msgstr "Navegação por página" +#: templates/exchange_rates_services/fragments/list.html:6 +#: templates/exchange_rates_services/pages/index.html:4 +#: templates/includes/navbar.html:133 +msgid "Automatic Exchange Rates" +msgstr "Taxas de Câmbio Automáticas" + +#: templates/exchange_rates_services/fragments/list.html:21 +msgid "Fetch all" +msgstr "Executar todos" + +#: templates/exchange_rates_services/fragments/list.html:33 +msgid "Service" +msgstr "Serviço" + +#: templates/exchange_rates_services/fragments/list.html:34 +msgid "Targeting" +msgstr "Alvos" + +#: templates/exchange_rates_services/fragments/list.html:35 +msgid "Fetch every" +msgstr "Buscar a cada" + +#: templates/exchange_rates_services/fragments/list.html:36 +msgid "Last fetch" +msgstr "Última execução" + +#: templates/exchange_rates_services/fragments/list.html:68 +msgid "currencies" +msgstr "moedas" + +#: templates/exchange_rates_services/fragments/list.html:68 +msgid "accounts" +msgstr "contas" + +#: templates/exchange_rates_services/fragments/list.html:69 +msgid "hours" +msgstr "horas" + +#: templates/exchange_rates_services/fragments/list.html:77 +msgid "No services configured" +msgstr "Nenhum serviço configurado" + #: templates/import_app/fragments/profiles/add.html:6 msgid "Add new import profile" msgstr "Adicionar novo perfil de importação" @@ -1919,6 +2061,10 @@ msgstr "Alternar navegação" msgid "Overview" msgstr "Visão Geral" +#: templates/includes/navbar.html:40 +msgid "Net Worth" +msgstr "Patrimônio" + #: templates/includes/navbar.html:44 msgid "Current" msgstr "Atual" @@ -1960,15 +2106,15 @@ msgstr "Automação" msgid "Rules" msgstr "Regras" -#: templates/includes/navbar.html:141 +#: templates/includes/navbar.html:143 msgid "Only use this if you know what you're doing" msgstr "Só use isso se você souber o que está fazendo" -#: templates/includes/navbar.html:142 +#: templates/includes/navbar.html:144 msgid "Django Admin" msgstr "Django Admin" -#: templates/includes/navbar.html:151 +#: templates/includes/navbar.html:153 msgid "Calculator" msgstr "Calculadora" @@ -2136,14 +2282,6 @@ msgstr "Mais antigas primeiro" msgid "Newest first" msgstr "Mais novas primeiro" -#: templates/net_worth/net_worth.html:9 -msgid "Current Net Worth" -msgstr "Patrimônio Atual" - -#: templates/net_worth/net_worth.html:9 -msgid "Projected Net Worth" -msgstr "Patrimônio Previsto" - #: templates/net_worth/net_worth.html:17 #: templates/yearly_overview/pages/overview_by_currency.html:9 msgid "By currency" @@ -2373,6 +2511,10 @@ msgstr "Visão Anual" msgid "Year" msgstr "Ano" +#, fuzzy +#~ msgid "Exchange rates queued to be fetched successfully" +#~ msgstr "Taxas de câmbio com sucesso" + #, fuzzy #~| msgid "Transaction updated successfully" #~ msgid "{count} transactions updated successfully" diff --git a/app/templates/exchange_rates_services/fragments/add.html b/app/templates/exchange_rates_services/fragments/add.html new file mode 100644 index 0000000..ec2dae0 --- /dev/null +++ b/app/templates/exchange_rates_services/fragments/add.html @@ -0,0 +1,11 @@ +{% extends 'extends/offcanvas.html' %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block title %}{% translate 'Add exchange rate' %}{% endblock %} + +{% block body %} +
+ {% crispy form %} +
+{% endblock %} diff --git a/app/templates/exchange_rates_services/fragments/edit.html b/app/templates/exchange_rates_services/fragments/edit.html new file mode 100644 index 0000000..516ccb7 --- /dev/null +++ b/app/templates/exchange_rates_services/fragments/edit.html @@ -0,0 +1,11 @@ +{% extends 'extends/offcanvas.html' %} +{% load i18n %} +{% load crispy_forms_tags %} + +{% block title %}{% translate 'Edit exchange rate' %}{% endblock %} + +{% block body %} +
+ {% crispy form %} +
+{% endblock %} diff --git a/app/templates/exchange_rates_services/fragments/list.html b/app/templates/exchange_rates_services/fragments/list.html new file mode 100644 index 0000000..fca5aa8 --- /dev/null +++ b/app/templates/exchange_rates_services/fragments/list.html @@ -0,0 +1,81 @@ +{% load currency_display %} +{% load i18n %} +
+
+ {% spaceless %} +
{% translate 'Automatic Exchange Rates' %} + + +
+ {% endspaceless %} +
+ +
+
+ +
+
+ {% if services %} + +
+ + + + + + + + + + + + + + {% for service in services %} + + + + + + + + + + {% endfor %} + +
{% translate 'Name' %}{% translate 'Service' %}{% translate 'Targeting' %}{% translate 'Fetch every' %}{% translate 'Last fetch' %}
+
+ + + +
+
{% if service.is_active %}{% else %} + {% endif %}{{ service.name }}{{ service.get_service_type_display }}{{ service.target_currencies.count }} {% trans 'currencies' %}, {{ service.target_accounts.count }} {% trans 'accounts' %}{{ service.fetch_interval_hours }} {% trans 'hours' %}{{ service.last_fetch|date:"SHORT_DATETIME_FORMAT" }}
+
+ {% else %} + + {% endif %} +
+
+
diff --git a/app/templates/exchange_rates_services/fragments/table.html b/app/templates/exchange_rates_services/fragments/table.html new file mode 100644 index 0000000..25250a8 --- /dev/null +++ b/app/templates/exchange_rates_services/fragments/table.html @@ -0,0 +1,132 @@ +{% load currency_display %} +{% load i18n %} +
+ {% if page_obj %} +
+ + + + + + + + + + + {% for exchange_rate in page_obj %} + + + + + + + {% endfor %} + +
{% translate 'Date' %}{% translate 'Pairing' %}{% translate 'Rate' %}
+
+ + + +
+
{{ exchange_rate.date|date:"SHORT_DATETIME_FORMAT" }}{{ exchange_rate.from_currency.name }} x {{ exchange_rate.to_currency.name }}1 {{ exchange_rate.from_currency.name }} ≅ {% currency_display amount=exchange_rate.rate prefix=exchange_rate.to_currency.prefix suffix=exchange_rate.to_currency.suffix decimal_places=exchange_rate.to_currency.decimal_places%}
+
+ {% else %} + + {% endif %} + + {% if page_obj.has_other_pages %} +
+ + + +
+ {% endif %} +
diff --git a/app/templates/exchange_rates_services/pages/index.html b/app/templates/exchange_rates_services/pages/index.html new file mode 100644 index 0000000..9a6e678 --- /dev/null +++ b/app/templates/exchange_rates_services/pages/index.html @@ -0,0 +1,8 @@ +{% extends "layouts/base.html" %} +{% load i18n %} + +{% block title %}{% translate 'Automatic Exchange Rates' %}{% endblock %} + +{% block content %} +
+{% endblock %} diff --git a/app/templates/includes/navbar.html b/app/templates/includes/navbar.html index fdd803d..c8e4c72 100644 --- a/app/templates/includes/navbar.html +++ b/app/templates/includes/navbar.html @@ -129,6 +129,8 @@ href="{% url 'rules_index' %}">{% translate 'Rules' %}
  • {% translate 'Import' %} beta
  • +
  • {% translate 'Automatic Exchange Rates' %}
  • diff --git a/app/templates/includes/toasts.html b/app/templates/includes/toasts.html index 010ad5b..27349d0 100644 --- a/app/templates/includes/toasts.html +++ b/app/templates/includes/toasts.html @@ -1,5 +1,5 @@
    -
    +
    From 93bb34166ee47bc7c1b5ecba1d475f32bf16594c Mon Sep 17 00:00:00 2001 From: Herculino Trotta Date: Thu, 6 Feb 2025 21:40:04 -0300 Subject: [PATCH 2/2] feat(ui): auto-resize textareas when typing --- app/templates/includes/scripts.html | 2 + .../scripts/hyperscript/autosize.html | 7 +++ frontend/src/application/autosize.js | 53 +------------------ 3 files changed, 10 insertions(+), 52 deletions(-) create mode 100644 app/templates/includes/scripts/hyperscript/autosize.html diff --git a/app/templates/includes/scripts.html b/app/templates/includes/scripts.html index ddedee4..f87f912 100644 --- a/app/templates/includes/scripts.html +++ b/app/templates/includes/scripts.html @@ -4,11 +4,13 @@ {% javascript_pack 'sweetalert2' attrs="defer" %} {% javascript_pack 'select' attrs="defer" %} {% javascript_pack 'datepicker' %} +{% javascript_pack 'autosize' attrs="defer" %} {% include 'includes/scripts/hyperscript/init_tom_select.html' %} {% include 'includes/scripts/hyperscript/init_date_picker.html' %} {% include 'includes/scripts/hyperscript/hide_amount.html' %} {% include 'includes/scripts/hyperscript/tooltip.html' %} +{% include 'includes/scripts/hyperscript/autosize.html' %} {% include 'includes/scripts/hyperscript/htmx_error_handler.html' %} {% include 'includes/scripts/hyperscript/sounds.html' %} {% include 'includes/scripts/hyperscript/swal.html' %} diff --git a/app/templates/includes/scripts/hyperscript/autosize.html b/app/templates/includes/scripts/hyperscript/autosize.html new file mode 100644 index 0000000..a5d0c03 --- /dev/null +++ b/app/templates/includes/scripts/hyperscript/autosize.html @@ -0,0 +1,7 @@ + diff --git a/frontend/src/application/autosize.js b/frontend/src/application/autosize.js index 05967f0..f544961 100644 --- a/frontend/src/application/autosize.js +++ b/frontend/src/application/autosize.js @@ -1,54 +1,3 @@ import autosize from "autosize/dist/autosize"; -let autosize_textareas = document.querySelectorAll('textarea[autosize]'); - -autosize(autosize_textareas); - -document.addEventListener('shown.bs.collapse', function () { - autosize.update(autosize_textareas); -}); - -// UPDATE AUTOSIZE TEXT AREAS FOR FORMS INSIDE HTMX MODALS -document.addEventListener('updated.bs.modal', function () { - let new_autosize_textareas = document.querySelectorAll('textarea[autosize]'); - autosize(new_autosize_textareas); -}); - -let charcount_textareas = document.querySelectorAll('textarea[countchars], input[countchars]'); -charcount_textareas.forEach(formElement => { - countTextArea(formElement); - formElement.addEventListener('input', () => countTextArea(formElement)); -}); - -function countTextArea(formElement) { - let name = formElement.name; - - let max_chars = null; - if (formElement.dataset.maxChars) { - max_chars = formElement.dataset.maxChars; - } else if (formElement.hasAttribute("maxlength")) { - max_chars = formElement.getAttribute("maxlength"); - } - - let cur_chars = formElement.value.length; - - let wrapper = document.querySelector(`#charcount-${name}`); - let char_counter = document.querySelector(`#char-counter-${name}`); - let max_counter = document.querySelector(`#max-counter-${name}`); - - char_counter.textContent = cur_chars; - if (max_counter) { - max_counter.textContent = max_chars; - wrapper.classList.remove("text-bg-warning", "text-bg-normal", "text-bg-success", "text-bg-danger"); - - if (cur_chars === 0) { - wrapper.classList.add("text-bg-secondary"); - } else if (cur_chars > max_chars - 1) { - wrapper.classList.add("text-bg-danger"); - } else if (cur_chars < max_chars && cur_chars > max_chars * (90 / 100)) { - wrapper.classList.add("text-bg-warning"); - } else if (cur_chars < max_chars - ((max_chars * (10 / 100)) - 1)) { - wrapper.classList.add("text-bg-success"); - } - } -} \ No newline at end of file +window.autosize = autosize;