mirror of
https://github.com/eitchtee/WYGIWYH.git
synced 2026-06-06 22:52:51 +02:00
Compare commits
114 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6987b54dba | |||
| b44563b09b | |||
| e839f31104 | |||
| 2282625790 | |||
| aa8b559152 | |||
| e1862b8241 | |||
| eb6be8548c | |||
| 6ee4e21939 | |||
| bdd8aed891 | |||
| 801b2a9edd | |||
| 968499f1ab | |||
| 5b351821b1 | |||
| 7b49072848 | |||
| 0ee32724f1 | |||
| 6a19381672 | |||
| 248fec8b4c | |||
| b34c0557fa | |||
| 2af4066aab | |||
| d72ff3cdf5 | |||
| 63c69e5c6a | |||
| 78171183cc | |||
| 34a2b6bfd4 | |||
| 1dc24f855e | |||
| 1390aff07d | |||
| 8fc11b0acf | |||
| 9a30a0d3c0 | |||
| 10eecd09ff | |||
| 2cfb3fb12e | |||
| 47af8b135b | |||
| 39d0e63375 | |||
| 792154eba2 | |||
| dc76ed3156 | |||
| e627dd50be | |||
| 5527389196 | |||
| be24ca014e | |||
| 7c7056536e | |||
| 66d5d7a83b | |||
| 4d3ce087d6 | |||
| aeaf9fac43 | |||
| dcedf53b83 | |||
| 549648bd6b | |||
| 79149abdd2 | |||
| d66d1530bb | |||
| 4b9b6484d3 | |||
| a02944bdae | |||
| 3ede5304f1 | |||
| 27041695b8 | |||
| 0c927a2fe9 | |||
| c52db80c64 | |||
| 330ce8069c | |||
| 2989f11b01 | |||
| 738bb7fb74 | |||
| 79e50cd853 | |||
| 0a23c3ad5b | |||
| 43c7749102 | |||
| c1c4ccda8c | |||
| 615a689c61 | |||
| c5ccc42f99 | |||
| 2baa8b21e8 | |||
| 2e554141ba | |||
| 73ec6dc0fe | |||
| e19449ff99 | |||
| e81651119c | |||
| 55e9ef1b3f | |||
| c414179135 | |||
| 14c507de0f | |||
| 4722690fe9 | |||
| 493619a4ff | |||
| fb4aec88f1 | |||
| 4a35e770a4 | |||
| 83b81edbae | |||
| a7dc2c955e | |||
| ce2ae562c6 | |||
| de2881ffd4 | |||
| 838bf22498 | |||
| d3797ae4a5 | |||
| 0532397afd | |||
| 8106dc58e5 | |||
| 5986cf675b | |||
| 80da9142f1 | |||
| 766516d248 | |||
| 3fd0fba1b8 | |||
| c787565c04 | |||
| 0413921dbe | |||
| 9ecf8279b4 | |||
| 86cf625158 | |||
| ea097ab6f0 | |||
| b1201b51bb | |||
| 4c1d20215c | |||
| 27e85c4776 | |||
| 5a73cd20da | |||
| e305fab300 | |||
| c11f525373 | |||
| ea5d86dbf8 | |||
| a1d3539e3c | |||
| 1028a11c8b | |||
| e387a5e2a8 | |||
| 624dc382cf | |||
| f88699b333 | |||
| ca98dc073b | |||
| 63ba7af3c8 | |||
| 2d0dee4a9b | |||
| 0000a9ee03 | |||
| 41adb37fdb | |||
| 496651173e | |||
| 8836f06b80 | |||
| e98a48b3a7 | |||
| f9bc9f449b | |||
| 26eb1ae813 | |||
| 29a2cb9813 | |||
| be79e1b25a | |||
| 3fd08466a7 | |||
| 6896cdcdca | |||
| 2532930a64 |
@@ -165,3 +165,6 @@ cython_debug/
|
||||
node_modules/
|
||||
postgres_data/
|
||||
.prod.env
|
||||
|
||||
# Private local uploads
|
||||
app/attachments/
|
||||
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Docker: Dev",
|
||||
"type": "node-terminal",
|
||||
"request": "launch",
|
||||
"command": "docker compose --env-file .env -f docker-compose.dev.yml up --build",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"postDebugTask": "Docker: Dev Down"
|
||||
},
|
||||
{
|
||||
"name": "Docker: Dev (no rebuild)",
|
||||
"type": "node-terminal",
|
||||
"request": "launch",
|
||||
"command": "docker compose --env-file .env -f docker-compose.dev.yml up",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"postDebugTask": "Docker: Dev Down"
|
||||
},
|
||||
{
|
||||
"name": "Docker: Prod",
|
||||
"type": "node-terminal",
|
||||
"request": "launch",
|
||||
"command": "docker compose --env-file .prod.env -f docker-compose.prod.yml up --build",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"postDebugTask": "Docker: Prod Down"
|
||||
}
|
||||
]
|
||||
}
|
||||
Vendored
+119
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Docker: Dev",
|
||||
"type": "shell",
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"compose",
|
||||
"--env-file",
|
||||
".env",
|
||||
"-f",
|
||||
"docker-compose.dev.yml",
|
||||
"up",
|
||||
"--build"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"group": "build",
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Docker: Dev (no rebuild)",
|
||||
"type": "shell",
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"compose",
|
||||
"--env-file",
|
||||
".env",
|
||||
"-f",
|
||||
"docker-compose.dev.yml",
|
||||
"up"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Docker: Dev Refresh Vite Deps",
|
||||
"type": "shell",
|
||||
"command": "docker compose --env-file .env -f docker-compose.dev.yml rm -sfv vite; docker compose --env-file .env -f docker-compose.dev.yml up --build",
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Docker: Dev Down",
|
||||
"type": "shell",
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"compose",
|
||||
"--env-file",
|
||||
".env",
|
||||
"-f",
|
||||
"docker-compose.dev.yml",
|
||||
"down"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Docker: Prod",
|
||||
"type": "shell",
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"compose",
|
||||
"--env-file",
|
||||
".prod.env",
|
||||
"-f",
|
||||
"docker-compose.prod.yml",
|
||||
"up",
|
||||
"--build"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Docker: Prod Down",
|
||||
"type": "shell",
|
||||
"command": "docker",
|
||||
"args": [
|
||||
"compose",
|
||||
"--env-file",
|
||||
".prod.env",
|
||||
"-f",
|
||||
"docker-compose.prod.yml",
|
||||
"down"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}"
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Django: Runserver localhost:8000",
|
||||
"type": "shell",
|
||||
"command": "${command:python.interpreterPath}",
|
||||
"args": [
|
||||
"manage.py",
|
||||
"runserver",
|
||||
"localhost:8000"
|
||||
],
|
||||
"options": {
|
||||
"cwd": "${workspaceFolder}/app",
|
||||
"env": {
|
||||
"PYTHONUNBUFFERED": "1"
|
||||
}
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -157,6 +157,13 @@ WYGIWYH supports login via OpenID Connect (OIDC) through `django-allauth`. This
|
||||
> [!NOTE]
|
||||
> Currently only OpenID Connect is supported as a provider, open an issue if you need something else.
|
||||
|
||||
> [!Caution]
|
||||
> WYGIWYH automatically connects OIDC accounts to existing local accounts with matching email addresses.
|
||||
> This means if a user already exists with email `user@example.com` and someone logs in via OIDC with the same email, the OIDC account will be automatically linked to the existing account without requiring user confirmation.
|
||||
> This is only recommended for trusted OIDC providers that verify email addresses and where you control who can create accounts.
|
||||
|
||||
### Configuration
|
||||
|
||||
To configure OIDC, you need to set the following environment variables:
|
||||
|
||||
| Variable | Description |
|
||||
|
||||
+28
-27
@@ -311,6 +311,7 @@ LOCALE_PATHS = [BASE_DIR / "locale"]
|
||||
|
||||
STATIC_URL = "static/"
|
||||
STATIC_ROOT = BASE_DIR / "static_files"
|
||||
ATTACHMENT_MEDIA_ROOT = BASE_DIR / "attachments"
|
||||
|
||||
STATICFILES_DIRS = [
|
||||
ROOT_DIR / "frontend" / "build",
|
||||
@@ -376,8 +377,10 @@ ACCOUNT_EMAIL_VERIFICATION = "none"
|
||||
SOCIALACCOUNT_LOGIN_ON_GET = True
|
||||
SOCIALACCOUNT_ONLY = True
|
||||
SOCIALACCOUNT_AUTO_SIGNUP = os.getenv("OIDC_ALLOW_SIGNUP", "true").lower() == "true"
|
||||
SOCIALACCOUNT_EMAIL_AUTHENTICATION = True
|
||||
SOCIALACCOUNT_EMAIL_AUTHENTICATION_AUTO_CONNECT = True
|
||||
ACCOUNT_ADAPTER = "allauth.account.adapter.DefaultAccountAdapter"
|
||||
SOCIALACCOUNT_ADAPTER = "allauth.socialaccount.adapter.DefaultSocialAccountAdapter"
|
||||
SOCIALACCOUNT_ADAPTER = "apps.users.adapters.AutoConnectSocialAccountAdapter"
|
||||
|
||||
# CRISPY FORMS
|
||||
CRISPY_ALLOWED_TEMPLATE_PACKS = [
|
||||
@@ -390,6 +393,10 @@ SESSION_EXPIRE_AT_BROWSER_CLOSE = False
|
||||
SESSION_COOKIE_AGE = int(os.getenv("SESSION_EXPIRY_TIME", 2678400)) # 31 days
|
||||
SESSION_COOKIE_SECURE = os.getenv("HTTPS_ENABLED", "false").lower() == "true"
|
||||
|
||||
HTTPS_ENABLED = os.getenv("HTTPS_ENABLED", "false").lower() == "true"
|
||||
ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https" if HTTPS_ENABLED else "http"
|
||||
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") if HTTPS_ENABLED else None
|
||||
|
||||
DEBUG_TOOLBAR_CONFIG = {
|
||||
"ROOT_TAG_EXTRA_ATTRS": "hx-preserve",
|
||||
# "SHOW_TOOLBAR_CALLBACK": lambda r: False, # disables it
|
||||
@@ -434,14 +441,14 @@ REST_FRAMEWORK = {
|
||||
"apps.api.permissions.NotInDemoMode",
|
||||
"rest_framework.permissions.DjangoModelPermissions",
|
||||
],
|
||||
'DEFAULT_FILTER_BACKENDS': [
|
||||
'django_filters.rest_framework.DjangoFilterBackend',
|
||||
'rest_framework.filters.OrderingFilter',
|
||||
"DEFAULT_FILTER_BACKENDS": [
|
||||
"django_filters.rest_framework.DjangoFilterBackend",
|
||||
"rest_framework.filters.OrderingFilter",
|
||||
],
|
||||
'DEFAULT_AUTHENTICATION_CLASSES': [
|
||||
'rest_framework.authentication.BasicAuthentication',
|
||||
'rest_framework.authentication.SessionAuthentication',
|
||||
'rest_framework.authentication.TokenAuthentication',
|
||||
"DEFAULT_AUTHENTICATION_CLASSES": [
|
||||
"rest_framework.authentication.BasicAuthentication",
|
||||
"rest_framework.authentication.SessionAuthentication",
|
||||
"rest_framework.authentication.TokenAuthentication",
|
||||
],
|
||||
"DEFAULT_PAGINATION_CLASS": "apps.api.custom.pagination.CustomPageNumberPagination",
|
||||
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
|
||||
@@ -458,7 +465,7 @@ SPECTACULAR_SETTINGS = {
|
||||
if "procrastinate" in sys.argv:
|
||||
LOGGING = {
|
||||
"version": 1,
|
||||
"disable_existing_loggers": False,
|
||||
"disable_existing_loggers": True,
|
||||
"formatters": {
|
||||
"standard": {
|
||||
"format": "[%(asctime)s] - %(levelname)s - %(name)s - %(message)s",
|
||||
@@ -466,26 +473,19 @@ if "procrastinate" in sys.argv:
|
||||
},
|
||||
},
|
||||
"handlers": {
|
||||
"procrastinate": {
|
||||
"level": "INFO",
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "standard",
|
||||
},
|
||||
"console": {
|
||||
"class": "logging.StreamHandler",
|
||||
"formatter": "standard",
|
||||
"level": "INFO",
|
||||
},
|
||||
},
|
||||
"root": {
|
||||
"handlers": ["console"],
|
||||
"level": "INFO",
|
||||
},
|
||||
"loggers": {
|
||||
"procrastinate": {
|
||||
"handlers": ["procrastinate"],
|
||||
"propagate": False,
|
||||
},
|
||||
"root": {
|
||||
"handlers": ["console"],
|
||||
"level": "INFO",
|
||||
"propagate": False,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -505,19 +505,20 @@ else:
|
||||
"formatter": "standard",
|
||||
"level": "INFO",
|
||||
},
|
||||
"procrastinate": {
|
||||
"level": "INFO",
|
||||
"class": "logging.StreamHandler",
|
||||
},
|
||||
},
|
||||
"root": {
|
||||
"handlers": ["console"],
|
||||
"level": "INFO",
|
||||
},
|
||||
"loggers": {
|
||||
"procrastinate": {
|
||||
"handlers": None,
|
||||
"handlers": [],
|
||||
"propagate": False,
|
||||
},
|
||||
"root": {
|
||||
"allauth": {
|
||||
"handlers": ["console"],
|
||||
"level": "INFO",
|
||||
"level": "DEBUG",
|
||||
"propagate": False,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -90,10 +90,10 @@ class AccountBalanceAPITests(TestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
def test_get_balance_unauthenticated(self):
|
||||
"""Test unauthenticated request returns 403"""
|
||||
"""Test unauthenticated request returns 401"""
|
||||
unauthenticated_client = APIClient()
|
||||
response = unauthenticated_client.get(
|
||||
f"/api/accounts/{self.account.id}/balance/"
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
@@ -159,7 +159,7 @@ column_mapping:
|
||||
self.assertIn("import_run_id", response.data)
|
||||
|
||||
def test_unauthenticated_request(self):
|
||||
"""Test unauthenticated request returns 403"""
|
||||
"""Test unauthenticated request returns 401"""
|
||||
unauthenticated_client = APIClient()
|
||||
|
||||
csv_content = b"date,description,amount\n2025-01-01,Test,100"
|
||||
@@ -173,7 +173,7 @@ column_mapping:
|
||||
format="multipart",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
|
||||
@override_settings(
|
||||
@@ -266,11 +266,11 @@ column_mapping:
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
def test_profiles_unauthenticated(self):
|
||||
"""Test unauthenticated request returns 403"""
|
||||
"""Test unauthenticated request returns 401"""
|
||||
unauthenticated_client = APIClient()
|
||||
response = unauthenticated_client.get("/api/import/profiles/")
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
|
||||
@override_settings(
|
||||
@@ -397,8 +397,8 @@ column_mapping:
|
||||
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
|
||||
|
||||
def test_runs_unauthenticated(self):
|
||||
"""Test unauthenticated request returns 403"""
|
||||
"""Test unauthenticated request returns 401"""
|
||||
unauthenticated_client = APIClient()
|
||||
response = unauthenticated_client.get("/api/import/runs/")
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
|
||||
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
@@ -1,6 +1,47 @@
|
||||
import functools
|
||||
import inspect
|
||||
|
||||
import procrastinate
|
||||
from django.db import close_old_connections
|
||||
|
||||
|
||||
_CONNECTION_CLEANUP_WRAPPED = "_wygiwyh_connection_cleanup_wrapped"
|
||||
|
||||
|
||||
def _wrap_task_with_django_connection_cleanup(task):
|
||||
if getattr(task.func, _CONNECTION_CLEANUP_WRAPPED, False):
|
||||
return
|
||||
|
||||
func = task.func
|
||||
|
||||
if inspect.iscoroutinefunction(func):
|
||||
|
||||
@functools.wraps(func)
|
||||
async def async_wrapped(*args, **kwargs):
|
||||
close_old_connections()
|
||||
try:
|
||||
return await func(*args, **kwargs)
|
||||
finally:
|
||||
close_old_connections()
|
||||
|
||||
wrapped = async_wrapped
|
||||
else:
|
||||
|
||||
@functools.wraps(func)
|
||||
def sync_wrapped(*args, **kwargs):
|
||||
close_old_connections()
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
finally:
|
||||
close_old_connections()
|
||||
|
||||
wrapped = sync_wrapped
|
||||
|
||||
setattr(wrapped, _CONNECTION_CLEANUP_WRAPPED, True)
|
||||
task.func = wrapped
|
||||
|
||||
|
||||
def on_app_ready(app: procrastinate.App):
|
||||
"""This function is ran upon procrastinate initialization."""
|
||||
...
|
||||
for task in set(app.tasks.values()):
|
||||
_wrap_task_with_django_connection_cleanup(task)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
from unittest.mock import patch
|
||||
|
||||
import procrastinate
|
||||
from django.db import connection
|
||||
from django.test import SimpleTestCase, TransactionTestCase
|
||||
from procrastinate.testing import InMemoryConnector
|
||||
|
||||
from apps.common.procrastinate import on_app_ready
|
||||
|
||||
|
||||
def make_app_with_task(func):
|
||||
app = procrastinate.App(connector=InMemoryConnector())
|
||||
task = app.task(name="sample_task")(func)
|
||||
|
||||
return app, task
|
||||
|
||||
|
||||
class ProcrastinateConnectionCleanupTests(SimpleTestCase):
|
||||
def test_app_ready_closes_old_connections_around_sync_tasks(self):
|
||||
calls = []
|
||||
|
||||
def sample_task(value):
|
||||
calls.append(("task", value))
|
||||
return value * 2
|
||||
|
||||
app, task = make_app_with_task(sample_task)
|
||||
|
||||
with patch(
|
||||
"apps.common.procrastinate.close_old_connections",
|
||||
create=True,
|
||||
side_effect=lambda: calls.append(("cleanup", None)),
|
||||
):
|
||||
on_app_ready(app)
|
||||
|
||||
result = task.func(3)
|
||||
|
||||
self.assertEqual(result, 6)
|
||||
self.assertEqual(
|
||||
calls,
|
||||
[
|
||||
("cleanup", None),
|
||||
("task", 3),
|
||||
("cleanup", None),
|
||||
],
|
||||
)
|
||||
|
||||
def test_app_ready_closes_old_connections_when_sync_task_raises(self):
|
||||
calls = []
|
||||
|
||||
def sample_task():
|
||||
calls.append(("task", None))
|
||||
raise RuntimeError("boom")
|
||||
|
||||
app, task = make_app_with_task(sample_task)
|
||||
|
||||
with patch(
|
||||
"apps.common.procrastinate.close_old_connections",
|
||||
create=True,
|
||||
side_effect=lambda: calls.append(("cleanup", None)),
|
||||
):
|
||||
on_app_ready(app)
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
task.func()
|
||||
|
||||
self.assertEqual(
|
||||
calls,
|
||||
[
|
||||
("cleanup", None),
|
||||
("task", None),
|
||||
("cleanup", None),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
class ProcrastinateConnectionRecoveryTests(TransactionTestCase):
|
||||
def test_wrapped_task_recovers_from_closed_django_connection(self):
|
||||
def sample_task():
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("SELECT 1")
|
||||
return cursor.fetchone()[0]
|
||||
|
||||
app, task = make_app_with_task(sample_task)
|
||||
on_app_ready(app)
|
||||
|
||||
connection.ensure_connection()
|
||||
connection.connection.close()
|
||||
|
||||
self.assertEqual(task.func(), 1)
|
||||
@@ -13,6 +13,7 @@ import openpyxl
|
||||
import xlrd
|
||||
import yaml
|
||||
from cachalot.api import cachalot_disabled
|
||||
from django.core.exceptions import FieldDoesNotExist
|
||||
from django.utils import timezone
|
||||
from openpyxl.utils.exceptions import InvalidFileException
|
||||
|
||||
@@ -365,7 +366,7 @@ class ImportService:
|
||||
try:
|
||||
if entities_mapping:
|
||||
if entities_mapping.type == "id":
|
||||
entity = TransactionTag.objects.filter(
|
||||
entity = TransactionEntity.objects.filter(
|
||||
id=entity_name
|
||||
).first()
|
||||
else: # name
|
||||
@@ -462,12 +463,12 @@ class ImportService:
|
||||
for field in rule.fields:
|
||||
if field in transaction_data:
|
||||
value = transaction_data[field]
|
||||
# Use __iexact only for string fields; non-string types
|
||||
# (date, Decimal, bool, int, etc.) don't support UPPER()
|
||||
if rule.match_type == "strict" or not isinstance(value, str):
|
||||
query = query.filter(**{field: value})
|
||||
else: # lax matching for strings only
|
||||
query = query.filter(**{f"{field}__iexact": value})
|
||||
query = self._apply_deduplication_filter(
|
||||
query=query,
|
||||
field=field,
|
||||
value=value,
|
||||
match_type=rule.match_type,
|
||||
)
|
||||
|
||||
# If we found any matching transaction, it's a duplicate
|
||||
if query.exists():
|
||||
@@ -475,6 +476,71 @@ class ImportService:
|
||||
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def _is_int_like(value: Any) -> bool:
|
||||
try:
|
||||
int(value)
|
||||
except (TypeError, ValueError):
|
||||
return False
|
||||
return True
|
||||
|
||||
def _apply_deduplication_filter(
|
||||
self,
|
||||
query,
|
||||
field: str,
|
||||
value: Any,
|
||||
match_type: Literal["lax", "strict"],
|
||||
):
|
||||
if isinstance(value, list):
|
||||
return self._apply_list_deduplication_filter(
|
||||
query=query,
|
||||
field=field,
|
||||
values=value,
|
||||
match_type=match_type,
|
||||
)
|
||||
|
||||
# Use __iexact only for string fields; non-string types
|
||||
# (date, Decimal, bool, int, etc.) don't support UPPER()
|
||||
if match_type == "strict" or not isinstance(value, str):
|
||||
return query.filter(**{field: value})
|
||||
|
||||
return query.filter(**{f"{field}__iexact": value})
|
||||
|
||||
def _apply_list_deduplication_filter(
|
||||
self,
|
||||
query,
|
||||
field: str,
|
||||
values: list[Any],
|
||||
match_type: Literal["lax", "strict"],
|
||||
):
|
||||
clean_values = [v for v in values if v not in (None, "")]
|
||||
if not clean_values:
|
||||
return query
|
||||
|
||||
try:
|
||||
model_field = Transaction._meta.get_field(field)
|
||||
except FieldDoesNotExist:
|
||||
return query.filter(**{f"{field}__in": clean_values})
|
||||
|
||||
if getattr(model_field, "many_to_many", False):
|
||||
# For m2m fields (e.g., entities/tags), apply one filter per value so
|
||||
# all provided values must be present in the matched transaction.
|
||||
if all(self._is_int_like(v) for v in clean_values):
|
||||
for value in clean_values:
|
||||
query = query.filter(**{f"{field}__id": int(value)})
|
||||
else:
|
||||
for value in clean_values:
|
||||
lookup = (
|
||||
f"{field}__name"
|
||||
if match_type == "strict"
|
||||
else f"{field}__name__iexact"
|
||||
)
|
||||
query = query.filter(**{lookup: str(value).strip()})
|
||||
|
||||
return query.distinct()
|
||||
|
||||
return query.filter(**{f"{field}__in": clean_values})
|
||||
|
||||
def _coerce_type(
|
||||
self, value: str, mapping: version_1.ColumnMapping
|
||||
) -> Union[str, int, bool, Decimal, datetime, list, None]:
|
||||
|
||||
@@ -15,7 +15,7 @@ from apps.accounts.models import Account, AccountGroup
|
||||
from apps.currencies.models import Currency
|
||||
from apps.import_app.models import ImportProfile, ImportRun
|
||||
from apps.import_app.services.v1 import ImportService
|
||||
from apps.transactions.models import Transaction
|
||||
from apps.transactions.models import Transaction, TransactionEntity
|
||||
|
||||
|
||||
class DeduplicationTests(TestCase):
|
||||
@@ -273,3 +273,39 @@ deduplication:
|
||||
}
|
||||
)
|
||||
self.assertTrue(is_duplicate)
|
||||
|
||||
def test_deduplication_with_entities_list_value(self):
|
||||
"""Test that list values for m2m entities deduplicate correctly."""
|
||||
entity = TransactionEntity.objects.create(name="DB Vertrieb GmbH")
|
||||
self.existing_transaction.entities.add(entity)
|
||||
|
||||
service = self._create_import_service_with_deduplication(
|
||||
fields=["date", "amount", "entities"], match_type="strict"
|
||||
)
|
||||
|
||||
is_duplicate = service._check_duplicate_transaction(
|
||||
{
|
||||
"date": date(2024, 1, 15),
|
||||
"amount": Decimal("100.00"),
|
||||
"entities": ["DB Vertrieb GmbH"],
|
||||
}
|
||||
)
|
||||
self.assertTrue(is_duplicate)
|
||||
|
||||
def test_deduplication_with_entities_list_value_not_matching(self):
|
||||
"""Test that non-matching entity list values are not marked duplicate."""
|
||||
entity = TransactionEntity.objects.create(name="DB Vertrieb GmbH")
|
||||
self.existing_transaction.entities.add(entity)
|
||||
|
||||
service = self._create_import_service_with_deduplication(
|
||||
fields=["date", "amount", "entities"], match_type="strict"
|
||||
)
|
||||
|
||||
is_duplicate = service._check_duplicate_transaction(
|
||||
{
|
||||
"date": date(2024, 1, 15),
|
||||
"amount": Decimal("100.00"),
|
||||
"entities": ["Different Entity"],
|
||||
}
|
||||
)
|
||||
self.assertFalse(is_duplicate)
|
||||
|
||||
@@ -365,7 +365,9 @@ def check_for_transaction_rules(
|
||||
|
||||
if processed_action.set_category:
|
||||
value = simple.eval(processed_action.set_category)
|
||||
if isinstance(value, int):
|
||||
if value is None:
|
||||
transaction.category = None
|
||||
elif isinstance(value, int):
|
||||
transaction.category = TransactionCategory.objects.get(id=value)
|
||||
else:
|
||||
transaction.category = TransactionCategory.objects.get(name=value)
|
||||
@@ -458,7 +460,9 @@ def check_for_transaction_rules(
|
||||
transaction.account = account
|
||||
|
||||
elif field == TransactionRuleAction.Field.category:
|
||||
if isinstance(new_value, int):
|
||||
if new_value is None:
|
||||
transaction.category = None
|
||||
elif isinstance(new_value, int):
|
||||
category = TransactionCategory.objects.get(id=new_value)
|
||||
transaction.category = category
|
||||
elif isinstance(new_value, str):
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
from unittest.mock import patch
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.test import TransactionTestCase
|
||||
|
||||
from apps.accounts.models import Account
|
||||
from apps.currencies.models import Currency
|
||||
from apps.rules.models import TransactionRule, UpdateOrCreateTransactionRuleAction
|
||||
from apps.rules.tasks import check_for_transaction_rules
|
||||
from apps.transactions.models import Transaction
|
||||
|
||||
|
||||
def run_check_for_transaction_rules_without_worker_wrapper(**kwargs):
|
||||
task_func = check_for_transaction_rules.func
|
||||
task_func = getattr(task_func, "__wrapped__", task_func)
|
||||
|
||||
return task_func(**kwargs)
|
||||
|
||||
|
||||
class CheckForTransactionRulesTests(TransactionTestCase):
|
||||
def setUp(self):
|
||||
User = get_user_model()
|
||||
self.user = User.objects.create_user(
|
||||
email="rules@example.com",
|
||||
password="testpass123",
|
||||
)
|
||||
self.currency = Currency.objects.create(
|
||||
code="USD",
|
||||
name="US Dollar",
|
||||
decimal_places=2,
|
||||
)
|
||||
self.account = Account.objects.create(
|
||||
name="Main Account",
|
||||
currency=self.currency,
|
||||
owner=self.user,
|
||||
)
|
||||
|
||||
@patch("apps.rules.signals.check_for_transaction_rules.defer")
|
||||
def test_update_or_create_action_can_clear_category_from_none_expression(
|
||||
self, mock_defer
|
||||
):
|
||||
source_transaction = Transaction.objects.create(
|
||||
account=self.account,
|
||||
type=Transaction.Type.EXPENSE,
|
||||
amount=Decimal("10.00"),
|
||||
date=date(2026, 5, 4),
|
||||
reference_date=date(2026, 5, 1),
|
||||
description="Source without category",
|
||||
category=None,
|
||||
owner=self.user,
|
||||
)
|
||||
rule = TransactionRule.objects.create(
|
||||
active=True,
|
||||
on_create=False,
|
||||
on_update=True,
|
||||
name="Copy transaction",
|
||||
trigger="True",
|
||||
owner=self.user,
|
||||
)
|
||||
UpdateOrCreateTransactionRuleAction.objects.create(
|
||||
rule=rule,
|
||||
set_account="account_id",
|
||||
set_type="'EX'",
|
||||
set_date="date",
|
||||
set_reference_date="reference_date",
|
||||
set_amount="amount",
|
||||
set_description="'Generated transaction'",
|
||||
set_category="category_name",
|
||||
)
|
||||
|
||||
run_check_for_transaction_rules_without_worker_wrapper(
|
||||
instance_id=source_transaction.id,
|
||||
user_id=self.user.id,
|
||||
signal="transaction_updated",
|
||||
)
|
||||
|
||||
generated_transaction = Transaction.objects.get(
|
||||
description="Generated transaction"
|
||||
)
|
||||
self.assertIsNone(generated_transaction.category)
|
||||
@@ -5,6 +5,7 @@ from apps.common.fields.forms.dynamic_select import (
|
||||
DynamicModelChoiceField,
|
||||
DynamicModelMultipleChoiceField,
|
||||
)
|
||||
from apps.common.middleware.thread_local import get_current_user
|
||||
from apps.common.widgets.crispy.daisyui import Switch
|
||||
from apps.common.widgets.crispy.submit import NoClassSubmit
|
||||
from apps.common.widgets.datepicker import AirDatePickerInput, AirMonthYearPickerInput
|
||||
@@ -13,6 +14,7 @@ from apps.common.widgets.tom_select import TomSelect
|
||||
from apps.rules.signals import transaction_created, transaction_updated
|
||||
from apps.transactions.models import (
|
||||
InstallmentPlan,
|
||||
TransactionAttachment,
|
||||
QuickTransaction,
|
||||
RecurringTransaction,
|
||||
Transaction,
|
||||
@@ -35,6 +37,22 @@ from django.db.models import Q
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
|
||||
class MultipleFileInput(forms.ClearableFileInput):
|
||||
allow_multiple_selected = True
|
||||
|
||||
|
||||
class MultipleFileField(forms.FileField):
|
||||
widget = MultipleFileInput
|
||||
|
||||
def clean(self, data, initial=None):
|
||||
single_file_clean = super().clean
|
||||
if isinstance(data, (list, tuple)):
|
||||
return [single_file_clean(file, initial) for file in data]
|
||||
if data:
|
||||
return [single_file_clean(data, initial)]
|
||||
return []
|
||||
|
||||
|
||||
class TransactionForm(forms.ModelForm):
|
||||
category = DynamicModelChoiceField(
|
||||
create_field="name",
|
||||
@@ -116,6 +134,9 @@ class TransactionForm(forms.ModelForm):
|
||||
self.fields["account"].queryset = Account.objects.filter(
|
||||
is_archived=False,
|
||||
)
|
||||
user_settings = get_current_user().settings
|
||||
if user_settings.default_account:
|
||||
self.fields["account"].initial = user_settings.default_account
|
||||
|
||||
self.fields["category"].queryset = TransactionCategory.objects.filter(
|
||||
active=True
|
||||
@@ -243,6 +264,41 @@ class TransactionForm(forms.ModelForm):
|
||||
return instance
|
||||
|
||||
|
||||
class TransactionAttachmentForm(forms.Form):
|
||||
attachments = MultipleFileField(
|
||||
required=True,
|
||||
label=_("Attachments"),
|
||||
help_text=_("Files are private and only visible to users with access to this transaction."),
|
||||
)
|
||||
|
||||
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(
|
||||
"attachments",
|
||||
FormActions(
|
||||
NoClassSubmit("submit", _("Upload"), css_class="btn btn-primary"),
|
||||
),
|
||||
)
|
||||
|
||||
def save(self, transaction, uploaded_by):
|
||||
created = []
|
||||
for attachment in self.cleaned_data.get("attachments") or []:
|
||||
created.append(
|
||||
TransactionAttachment.objects.create(
|
||||
transaction=transaction,
|
||||
file=attachment,
|
||||
original_name=attachment.name,
|
||||
content_type=getattr(attachment, "content_type", ""),
|
||||
size=attachment.size,
|
||||
uploaded_by=uploaded_by,
|
||||
)
|
||||
)
|
||||
return created
|
||||
|
||||
|
||||
class QuickTransactionForm(forms.ModelForm):
|
||||
category = DynamicModelChoiceField(
|
||||
create_field="name",
|
||||
@@ -768,6 +824,9 @@ class InstallmentPlanForm(forms.ModelForm):
|
||||
).distinct()
|
||||
else:
|
||||
self.fields["account"].queryset = Account.objects.filter(is_archived=False)
|
||||
user_settings = get_current_user().settings
|
||||
if user_settings.default_account:
|
||||
self.fields["account"].initial = user_settings.default_account
|
||||
|
||||
self.fields["category"].queryset = TransactionCategory.objects.filter(
|
||||
active=True
|
||||
@@ -1010,6 +1069,10 @@ class RecurringTransactionForm(forms.ModelForm):
|
||||
).distinct()
|
||||
else:
|
||||
self.fields["account"].queryset = Account.objects.filter(is_archived=False)
|
||||
|
||||
user_settings = get_current_user().settings
|
||||
if user_settings.default_account:
|
||||
self.fields["account"].initial = user_settings.default_account
|
||||
|
||||
self.fields["category"].queryset = TransactionCategory.objects.filter(
|
||||
active=True
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# Generated by Django 5.2.13 on 2026-06-06 02:34
|
||||
|
||||
import apps.transactions.models
|
||||
import apps.transactions.storage
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('transactions', '0048_recurringtransaction_keep_at_most'),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='TransactionAttachment',
|
||||
fields=[
|
||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
|
||||
('file', models.FileField(storage=apps.transactions.storage.PrivateMediaStorage(), upload_to=apps.transactions.models.transaction_attachment_path, verbose_name='File')),
|
||||
('original_name', models.CharField(max_length=255, verbose_name='Original Name')),
|
||||
('content_type', models.CharField(blank=True, max_length=255, verbose_name='Content Type')),
|
||||
('size', models.PositiveBigIntegerField(default=0, verbose_name='Size')),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
('transaction', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attachments', to='transactions.transaction', verbose_name='Transaction')),
|
||||
('uploaded_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='transaction_attachments', to=settings.AUTH_USER_MODEL, verbose_name='Uploaded By')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Transaction Attachment',
|
||||
'verbose_name_plural': 'Transaction Attachments',
|
||||
'db_table': 'transaction_attachments',
|
||||
'ordering': ['-created_at', 'original_name'],
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -1,6 +1,8 @@
|
||||
import decimal
|
||||
import logging
|
||||
import uuid
|
||||
from copy import deepcopy
|
||||
from pathlib import Path
|
||||
|
||||
from apps.common.fields.month_year import MonthYearModelField
|
||||
from apps.common.functions.decimals import truncate_decimal
|
||||
@@ -13,13 +15,15 @@ from apps.common.models import (
|
||||
)
|
||||
from apps.common.templatetags.decimal import drop_trailing_zeros, localize_number
|
||||
from apps.currencies.utils.convert import convert
|
||||
from apps.transactions.storage import PrivateMediaStorage
|
||||
from apps.transactions.validators import validate_decimal_places, validate_non_negative
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from django.conf import settings
|
||||
from django.core.validators import MinValueValidator
|
||||
from django.db import models, transaction
|
||||
from django.db.models import Q
|
||||
from django.dispatch import Signal
|
||||
from django.db.models.signals import post_delete
|
||||
from django.dispatch import Signal, receiver
|
||||
from django.template.defaultfilters import date
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@@ -32,6 +36,11 @@ transaction_updated = Signal()
|
||||
transaction_deleted = Signal()
|
||||
|
||||
|
||||
def transaction_attachment_path(instance, filename):
|
||||
extension = Path(filename).suffix
|
||||
return f"transaction_attachments/{instance.transaction_id}/{instance.id}{extension}"
|
||||
|
||||
|
||||
class SoftDeleteQuerySet(models.QuerySet):
|
||||
@staticmethod
|
||||
def _emit_signals(instances, created=False, old_data=None):
|
||||
@@ -526,6 +535,60 @@ class Transaction(OwnedObject):
|
||||
|
||||
return new_obj
|
||||
|
||||
class TransactionAttachment(models.Model):
|
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
|
||||
transaction = models.ForeignKey(
|
||||
Transaction,
|
||||
on_delete=models.CASCADE,
|
||||
related_name="attachments",
|
||||
verbose_name=_("Transaction"),
|
||||
)
|
||||
file = models.FileField(
|
||||
upload_to=transaction_attachment_path,
|
||||
storage=PrivateMediaStorage(),
|
||||
verbose_name=_("File"),
|
||||
)
|
||||
original_name = models.CharField(max_length=255, verbose_name=_("Original Name"))
|
||||
content_type = models.CharField(
|
||||
max_length=255, blank=True, verbose_name=_("Content Type")
|
||||
)
|
||||
size = models.PositiveBigIntegerField(default=0, verbose_name=_("Size"))
|
||||
uploaded_by = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL,
|
||||
on_delete=models.PROTECT,
|
||||
related_name="transaction_attachments",
|
||||
verbose_name=_("Uploaded By"),
|
||||
)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Transaction Attachment")
|
||||
verbose_name_plural = _("Transaction Attachments")
|
||||
db_table = "transaction_attachments"
|
||||
ordering = ["-created_at", "original_name"]
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.file:
|
||||
if not self.original_name:
|
||||
self.original_name = Path(self.file.name).name
|
||||
if not self.size:
|
||||
self.size = self.file.size
|
||||
if not self.content_type:
|
||||
self.content_type = getattr(self.file.file, "content_type", "")
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return self.original_name
|
||||
|
||||
|
||||
@receiver(post_delete, sender=TransactionAttachment)
|
||||
def delete_transaction_attachment_file(sender, instance, **kwargs):
|
||||
if not instance.file.name:
|
||||
return
|
||||
|
||||
storage = instance.file.storage
|
||||
if storage.exists(instance.file.name):
|
||||
storage.delete(instance.file.name)
|
||||
|
||||
class InstallmentPlan(models.Model):
|
||||
class Recurrence(models.TextChoices):
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
from django.conf import settings
|
||||
from django.core.files.storage import FileSystemStorage
|
||||
|
||||
|
||||
class PrivateMediaStorage(FileSystemStorage):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault("location", settings.ATTACHMENT_MEDIA_ROOT)
|
||||
kwargs.setdefault("base_url", None)
|
||||
super().__init__(*args, **kwargs)
|
||||
@@ -0,0 +1,219 @@
|
||||
import shutil
|
||||
import tempfile
|
||||
from datetime import date
|
||||
from decimal import Decimal
|
||||
from pathlib import Path
|
||||
|
||||
from apps.accounts.models import Account
|
||||
from apps.common.middleware.thread_local import delete_current_user, write_current_user
|
||||
from apps.currencies.models import Currency
|
||||
from apps.transactions.models import Transaction, TransactionAttachment
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.test import TestCase, override_settings
|
||||
from django.urls import reverse
|
||||
|
||||
|
||||
@override_settings(
|
||||
STORAGES={
|
||||
"default": {"BACKEND": "django.core.files.storage.FileSystemStorage"},
|
||||
"staticfiles": {
|
||||
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"
|
||||
},
|
||||
},
|
||||
WHITENOISE_AUTOREFRESH=True,
|
||||
)
|
||||
class TransactionAttachmentTests(TestCase):
|
||||
def setUp(self):
|
||||
self.attachment_media_root = tempfile.mkdtemp()
|
||||
self.override_private_media = override_settings(
|
||||
ATTACHMENT_MEDIA_ROOT=self.attachment_media_root
|
||||
)
|
||||
self.override_private_media.enable()
|
||||
self.addCleanup(self.override_private_media.disable)
|
||||
self.addCleanup(shutil.rmtree, self.attachment_media_root, ignore_errors=True)
|
||||
|
||||
self.attachment_storage = TransactionAttachment._meta.get_field("file").storage
|
||||
self.original_storage_location = self.attachment_storage._location
|
||||
self.attachment_storage._location = self.attachment_media_root
|
||||
self.attachment_storage.__dict__.pop("base_location", None)
|
||||
self.attachment_storage.__dict__.pop("location", None)
|
||||
self.addCleanup(self.restore_attachment_storage)
|
||||
|
||||
User = get_user_model()
|
||||
self.user1 = User.objects.create_user(
|
||||
email="user1@test.com", password="testpass123"
|
||||
)
|
||||
self.user2 = User.objects.create_user(
|
||||
email="user2@test.com", password="testpass123"
|
||||
)
|
||||
|
||||
self.currency = Currency.objects.create(
|
||||
code="USD", name="US Dollar", decimal_places=2, prefix="$ "
|
||||
)
|
||||
self.user1_account = Account.all_objects.create(
|
||||
name="User1 Account", currency=self.currency, owner=self.user1
|
||||
)
|
||||
self.user2_account = Account.all_objects.create(
|
||||
name="User2 Account", currency=self.currency, owner=self.user2
|
||||
)
|
||||
self.transaction = Transaction.userless_all_objects.create(
|
||||
account=self.user1_account,
|
||||
type=Transaction.Type.EXPENSE,
|
||||
amount=Decimal("12.34"),
|
||||
is_paid=True,
|
||||
date=date(2026, 6, 5),
|
||||
description="Receipt transaction",
|
||||
owner=self.user1,
|
||||
)
|
||||
self.other_transaction = Transaction.userless_all_objects.create(
|
||||
account=self.user2_account,
|
||||
type=Transaction.Type.EXPENSE,
|
||||
amount=Decimal("56.78"),
|
||||
is_paid=True,
|
||||
date=date(2026, 6, 5),
|
||||
description="Other receipt transaction",
|
||||
owner=self.user2,
|
||||
)
|
||||
|
||||
def restore_attachment_storage(self):
|
||||
self.attachment_storage._location = self.original_storage_location
|
||||
self.attachment_storage.__dict__.pop("base_location", None)
|
||||
self.attachment_storage.__dict__.pop("location", None)
|
||||
|
||||
def test_attachment_uses_uuid_and_preserves_original_download_name(self):
|
||||
attachment = TransactionAttachment.objects.create(
|
||||
transaction=self.transaction,
|
||||
file=SimpleUploadedFile(
|
||||
"receipt June.pdf", b"receipt bytes", content_type="application/pdf"
|
||||
),
|
||||
uploaded_by=self.user1,
|
||||
)
|
||||
|
||||
self.assertEqual(attachment.original_name, "receipt June.pdf")
|
||||
self.assertNotIn("receipt June.pdf", attachment.file.name)
|
||||
|
||||
self.client.force_login(self.user1)
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"transaction_attachment_download",
|
||||
kwargs={"attachment_id": attachment.id},
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertEqual(b"".join(response.streaming_content), b"receipt bytes")
|
||||
self.assertIn('filename="receipt June.pdf"', response["Content-Disposition"])
|
||||
|
||||
def test_user_without_transaction_access_cannot_download_attachment(self):
|
||||
attachment = TransactionAttachment.objects.create(
|
||||
transaction=self.other_transaction,
|
||||
file=SimpleUploadedFile("private.txt", b"private"),
|
||||
uploaded_by=self.user2,
|
||||
)
|
||||
|
||||
self.client.force_login(self.user1)
|
||||
response = self.client.get(
|
||||
reverse(
|
||||
"transaction_attachment_download",
|
||||
kwargs={"attachment_id": attachment.id},
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
def test_attachment_button_lives_in_transaction_hover_toolbar(self):
|
||||
template = Path("templates/cotton/transaction/item.html").read_text()
|
||||
before_toolbar, toolbar = template.split("{# Item actions#}", 1)
|
||||
|
||||
self.assertNotIn("transaction_attachments", before_toolbar)
|
||||
self.assertLess(
|
||||
toolbar.index("transaction_edit"),
|
||||
toolbar.index("transaction_attachments"),
|
||||
)
|
||||
self.assertLess(
|
||||
toolbar.index("transaction_attachments"),
|
||||
toolbar.index("transaction_delete"),
|
||||
)
|
||||
|
||||
def test_transaction_edit_form_does_not_include_attachment_upload(self):
|
||||
self.client.force_login(self.user1)
|
||||
|
||||
response = self.client.get(
|
||||
reverse("transaction_edit", kwargs={"transaction_id": self.transaction.id}),
|
||||
HTTP_HX_REQUEST="true",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotContains(response, "multipart/form-data")
|
||||
self.assertNotContains(response, 'type="file"')
|
||||
|
||||
def test_attachment_management_uploads_multiple_attachments(self):
|
||||
self.client.force_login(self.user1)
|
||||
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"transaction_attachments",
|
||||
kwargs={"transaction_id": self.transaction.id},
|
||||
),
|
||||
{
|
||||
"attachments": [
|
||||
SimpleUploadedFile("first.txt", b"first"),
|
||||
SimpleUploadedFile("second.txt", b"second"),
|
||||
],
|
||||
},
|
||||
HTTP_HX_REQUEST="true",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "first.txt")
|
||||
self.assertContains(response, "second.txt")
|
||||
self.assertEqual(self.transaction.attachments.count(), 2)
|
||||
|
||||
def test_attachment_delete_returns_refreshed_attachment_list(self):
|
||||
attachment = TransactionAttachment.objects.create(
|
||||
transaction=self.transaction,
|
||||
file=SimpleUploadedFile("delete-me.txt", b"delete"),
|
||||
uploaded_by=self.user1,
|
||||
)
|
||||
|
||||
self.client.force_login(self.user1)
|
||||
response = self.client.delete(
|
||||
reverse(
|
||||
"transaction_attachment_delete",
|
||||
kwargs={"attachment_id": attachment.id},
|
||||
),
|
||||
HTTP_HX_REQUEST="true",
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertNotContains(response, "delete-me.txt")
|
||||
self.assertContains(response, "No attachments yet")
|
||||
self.assertFalse(
|
||||
TransactionAttachment.objects.filter(id=attachment.id).exists()
|
||||
)
|
||||
|
||||
def test_hard_deleting_transaction_deletes_attachment_files(self):
|
||||
attachment = TransactionAttachment.objects.create(
|
||||
transaction=self.transaction,
|
||||
file=SimpleUploadedFile("hard-delete.txt", b"delete with transaction"),
|
||||
uploaded_by=self.user1,
|
||||
)
|
||||
file_path = Path(attachment.file.path)
|
||||
|
||||
self.assertTrue(file_path.exists())
|
||||
|
||||
write_current_user(self.user1)
|
||||
self.addCleanup(delete_current_user)
|
||||
|
||||
self.transaction.delete()
|
||||
|
||||
self.assertTrue(file_path.exists())
|
||||
self.assertTrue(TransactionAttachment.objects.filter(id=attachment.id).exists())
|
||||
|
||||
self.transaction.delete()
|
||||
|
||||
self.assertFalse(file_path.exists())
|
||||
self.assertFalse(
|
||||
TransactionAttachment.objects.filter(id=attachment.id).exists()
|
||||
)
|
||||
@@ -81,6 +81,26 @@ urlpatterns = [
|
||||
views.transaction_move_to_today,
|
||||
name="transaction_move_to_today",
|
||||
),
|
||||
path(
|
||||
"transaction/<int:transaction_id>/attachments/",
|
||||
views.transaction_attachments,
|
||||
name="transaction_attachments",
|
||||
),
|
||||
path(
|
||||
"transaction/<int:transaction_id>/attachments/list/",
|
||||
views.transaction_attachments_list,
|
||||
name="transaction_attachments_list",
|
||||
),
|
||||
path(
|
||||
"transaction/attachments/<uuid:attachment_id>/download/",
|
||||
views.transaction_attachment_download,
|
||||
name="transaction_attachment_download",
|
||||
),
|
||||
path(
|
||||
"transaction/attachments/<uuid:attachment_id>/delete/",
|
||||
views.transaction_attachment_delete,
|
||||
name="transaction_attachment_delete",
|
||||
),
|
||||
path(
|
||||
"transaction/<int:transaction_id>/delete/",
|
||||
views.transaction_delete,
|
||||
|
||||
@@ -1,32 +1,120 @@
|
||||
import datetime
|
||||
from copy import deepcopy
|
||||
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models import Q, When, Case, Value, IntegerField
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _, ngettext_lazy
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
from apps.common.decorators.demo import disabled_on_demo
|
||||
from apps.common.decorators.htmx import only_htmx
|
||||
from apps.rules.signals import transaction_created, transaction_updated
|
||||
from apps.transactions.filters import TransactionsFilter
|
||||
from apps.transactions.forms import (
|
||||
BulkEditTransactionForm,
|
||||
TransactionAttachmentForm,
|
||||
TransactionForm,
|
||||
TransferForm,
|
||||
BulkEditTransactionForm,
|
||||
)
|
||||
from apps.transactions.models import Transaction
|
||||
from apps.transactions.models import Transaction, TransactionAttachment
|
||||
from apps.transactions.utils.calculations import (
|
||||
calculate_currency_totals,
|
||||
calculate_account_totals,
|
||||
calculate_currency_totals,
|
||||
calculate_percentage_distribution,
|
||||
)
|
||||
from apps.transactions.utils.default_ordering import default_order
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.core.paginator import Paginator
|
||||
from django.db.models import Case, IntegerField, Q, Value, When
|
||||
from django.http import FileResponse, Http404, HttpResponse, JsonResponse
|
||||
from django.shortcuts import get_object_or_404, render
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django.utils.translation import ngettext_lazy
|
||||
from django.views.decorators.http import require_http_methods
|
||||
|
||||
|
||||
def _get_accessible_transaction_or_404(transaction_id):
|
||||
return get_object_or_404(Transaction.objects, id=transaction_id)
|
||||
|
||||
|
||||
def _get_accessible_attachment_or_404(attachment_id):
|
||||
attachment = get_object_or_404(
|
||||
TransactionAttachment.objects.select_related("transaction"),
|
||||
id=attachment_id,
|
||||
)
|
||||
if not Transaction.objects.filter(id=attachment.transaction_id).exists():
|
||||
raise Http404()
|
||||
return attachment
|
||||
|
||||
|
||||
@only_htmx
|
||||
@login_required
|
||||
@disabled_on_demo
|
||||
@require_http_methods(["GET", "POST"])
|
||||
def transaction_attachments(request, transaction_id):
|
||||
transaction = _get_accessible_transaction_or_404(transaction_id)
|
||||
|
||||
if request.method == "POST":
|
||||
form = TransactionAttachmentForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
form.save(transaction=transaction, uploaded_by=request.user)
|
||||
messages.success(request, _("Attachment uploaded successfully"))
|
||||
form = TransactionAttachmentForm()
|
||||
else:
|
||||
form = TransactionAttachmentForm()
|
||||
|
||||
response = render(
|
||||
request,
|
||||
"transactions/fragments/attachments_manage.html",
|
||||
{"form": form, "transaction": transaction},
|
||||
)
|
||||
|
||||
response["HX-Trigger"] = "toasts, updated"
|
||||
|
||||
return response
|
||||
|
||||
|
||||
@only_htmx
|
||||
@login_required
|
||||
@disabled_on_demo
|
||||
@require_http_methods(["GET"])
|
||||
def transaction_attachments_list(request, transaction_id):
|
||||
transaction = _get_accessible_transaction_or_404(transaction_id)
|
||||
return render(
|
||||
request,
|
||||
"transactions/fragments/attachments.html",
|
||||
{"transaction": transaction},
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
@disabled_on_demo
|
||||
@require_http_methods(["GET"])
|
||||
def transaction_attachment_download(request, attachment_id):
|
||||
attachment = _get_accessible_attachment_or_404(attachment_id)
|
||||
return FileResponse(
|
||||
attachment.file.open("rb"),
|
||||
as_attachment=False,
|
||||
filename=attachment.original_name,
|
||||
content_type=attachment.content_type or "application/octet-stream",
|
||||
)
|
||||
|
||||
|
||||
@only_htmx
|
||||
@login_required
|
||||
@disabled_on_demo
|
||||
@require_http_methods(["DELETE"])
|
||||
def transaction_attachment_delete(request, attachment_id):
|
||||
attachment = _get_accessible_attachment_or_404(attachment_id)
|
||||
transaction = attachment.transaction
|
||||
attachment.file.delete(save=False)
|
||||
attachment.delete()
|
||||
messages.success(request, _("Attachment deleted successfully"))
|
||||
response = render(
|
||||
request,
|
||||
"transactions/fragments/attachments.html",
|
||||
{"transaction": transaction},
|
||||
)
|
||||
response["HX-Trigger"] = "toasts, updated"
|
||||
return response
|
||||
|
||||
|
||||
@only_htmx
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import logging
|
||||
from allauth.socialaccount.adapter import DefaultSocialAccountAdapter
|
||||
from django.contrib.auth import get_user_model
|
||||
|
||||
User = get_user_model()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AutoConnectSocialAccountAdapter(DefaultSocialAccountAdapter):
|
||||
"""
|
||||
Custom adapter to automatically connect social accounts to existing users
|
||||
with the same email address.
|
||||
|
||||
SECURITY WARNING:
|
||||
This adapter automatically connects OIDC accounts to existing local accounts
|
||||
based on email matching.
|
||||
|
||||
If your OIDC provider allows unverified emails, this could lead to
|
||||
ACCOUNT TAKEOVER attacks where an attacker creates an OIDC account
|
||||
with someone else's email and gains access to their account.
|
||||
"""
|
||||
|
||||
def pre_social_login(self, request, sociallogin):
|
||||
"""
|
||||
Invoked just after a user successfully authenticates via a
|
||||
social provider, but before the login is actually processed.
|
||||
|
||||
If a user with the same email already exists, connect the social
|
||||
account to that existing user instead of creating a new account.
|
||||
"""
|
||||
# If the social account is already connected to a user, do nothing
|
||||
if sociallogin.is_existing:
|
||||
return
|
||||
|
||||
# Check if we have an email from the social provider
|
||||
if not sociallogin.email_addresses:
|
||||
logger.warning(
|
||||
"OIDC login attempted without email address. "
|
||||
f"Provider: {sociallogin.account.provider}"
|
||||
)
|
||||
return
|
||||
|
||||
# Get the email from the social login
|
||||
email = sociallogin.email_addresses[0].email.lower()
|
||||
|
||||
# Try to find an existing user with this email
|
||||
try:
|
||||
user = User.objects.get(email__iexact=email)
|
||||
|
||||
# Log this connection for security audit trail
|
||||
logger.info(
|
||||
f"Auto-connecting OIDC account to existing user. "
|
||||
f"Email: {email}, Provider: {sociallogin.account.provider}, "
|
||||
f"User ID: {user.id}"
|
||||
)
|
||||
|
||||
# Connect the social account to the existing user
|
||||
sociallogin.connect(request, user)
|
||||
|
||||
except User.DoesNotExist:
|
||||
# No user with this email exists, proceed with normal signup flow
|
||||
logger.debug(
|
||||
f"No existing user found for email {email}. "
|
||||
"Proceeding with new account creation."
|
||||
)
|
||||
pass
|
||||
except User.MultipleObjectsReturned:
|
||||
# Multiple users with the same email (shouldn't happen with unique constraint)
|
||||
logger.error(
|
||||
f"Multiple users found with email {email}. "
|
||||
"This should not happen with unique constraint. "
|
||||
"Blocking auto-connect."
|
||||
)
|
||||
# Let the default behavior handle this
|
||||
pass
|
||||
@@ -1,6 +1,8 @@
|
||||
from apps.common.middleware.thread_local import get_current_user
|
||||
from apps.common.widgets.crispy.submit import NoClassSubmit
|
||||
from apps.common.widgets.tom_select import TomSelect
|
||||
from apps.users.models import UserSettings
|
||||
from apps.accounts.models import Account
|
||||
from crispy_forms.bootstrap import (
|
||||
FormActions,
|
||||
)
|
||||
@@ -116,6 +118,15 @@ class UserSettingsForm(forms.ModelForm):
|
||||
label=_("Number Format"),
|
||||
)
|
||||
|
||||
default_account = forms.ModelChoiceField(
|
||||
queryset=Account.objects.filter(
|
||||
is_archived=False,
|
||||
),
|
||||
label=_("Default Account"),
|
||||
widget=TomSelect(clear_button=False, group_by="group"),
|
||||
required=False,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = UserSettings
|
||||
fields = [
|
||||
@@ -126,11 +137,19 @@ class UserSettingsForm(forms.ModelForm):
|
||||
"datetime_format",
|
||||
"number_format",
|
||||
"volume",
|
||||
"default_account",
|
||||
]
|
||||
widgets = {
|
||||
"default_account": TomSelect(clear_button=False, group_by="group"),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
self.fields["default_account"].queryset = Account.objects.filter(
|
||||
is_archived=False,
|
||||
)
|
||||
|
||||
self.helper = FormHelper()
|
||||
self.helper.form_tag = False
|
||||
self.helper.form_method = "post"
|
||||
@@ -143,6 +162,7 @@ class UserSettingsForm(forms.ModelForm):
|
||||
"number_format",
|
||||
HTML('<hr class="hr my-3" />'),
|
||||
"start_page",
|
||||
"default_account",
|
||||
HTML('<hr class="hr my-3" />'),
|
||||
"volume",
|
||||
FormActions(
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 5.2.9 on 2026-02-15 21:35
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("accounts", "0016_account_untracked_by"),
|
||||
("users", "0023_alter_usersettings_timezone"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="usersettings",
|
||||
name="default_account",
|
||||
field=models.ForeignKey(
|
||||
blank=True,
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.SET_NULL,
|
||||
to="accounts.account",
|
||||
verbose_name="Default account",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
# Generated by Django 5.2.9 on 2026-02-16 01:32
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0016_account_untracked_by'),
|
||||
('users', '0024_usersettings_default_account'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='usersettings',
|
||||
name='default_account',
|
||||
field=models.ForeignKey(blank=True, help_text='Selects the account by default when creating new transactions', null=True, on_delete=django.db.models.deletion.SET_NULL, to='accounts.account', verbose_name='Default account'),
|
||||
),
|
||||
]
|
||||
@@ -510,6 +510,14 @@ class UserSettings(models.Model):
|
||||
default=StartPage.MONTHLY,
|
||||
verbose_name=_("Start page"),
|
||||
)
|
||||
default_account = models.ForeignKey(
|
||||
"accounts.Account",
|
||||
on_delete=models.SET_NULL,
|
||||
verbose_name=_("Default account"),
|
||||
help_text=_("Selects the account by default when creating new transactions"),
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.user.email}'s settings"
|
||||
|
||||
+319
-219
File diff suppressed because it is too large
Load Diff
+272
-177
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-10 20:50+0000\n"
|
||||
"POT-Creation-Date: 2026-06-06 07:41+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -26,12 +26,12 @@ msgstr ""
|
||||
#: apps/currencies/forms.py:53 apps/currencies/forms.py:87
|
||||
#: apps/currencies/forms.py:136 apps/dca/forms.py:46 apps/dca/forms.py:205
|
||||
#: apps/import_app/forms.py:32 apps/rules/forms.py:60 apps/rules/forms.py:100
|
||||
#: apps/rules/forms.py:385 apps/transactions/forms.py:197
|
||||
#: apps/transactions/forms.py:361 apps/transactions/forms.py:480
|
||||
#: apps/transactions/forms.py:821 apps/transactions/forms.py:860
|
||||
#: apps/transactions/forms.py:888 apps/transactions/forms.py:919
|
||||
#: apps/transactions/forms.py:1065 apps/users/forms.py:222
|
||||
#: apps/users/forms.py:380
|
||||
#: apps/rules/forms.py:385 apps/transactions/forms.py:218
|
||||
#: apps/transactions/forms.py:417 apps/transactions/forms.py:536
|
||||
#: apps/transactions/forms.py:880 apps/transactions/forms.py:919
|
||||
#: apps/transactions/forms.py:947 apps/transactions/forms.py:978
|
||||
#: apps/transactions/forms.py:1128 apps/users/forms.py:242
|
||||
#: apps/users/forms.py:400
|
||||
#: templates/rules/fragments/transaction_rule/dry_run/updated.html:5
|
||||
#: templates/rules/fragments/transaction_rule/view.html:128
|
||||
msgid "Update"
|
||||
@@ -42,11 +42,11 @@ msgstr ""
|
||||
#: apps/currencies/forms.py:93 apps/currencies/forms.py:142
|
||||
#: apps/dca/forms.py:52 apps/dca/forms.py:211 apps/import_app/forms.py:38
|
||||
#: apps/rules/forms.py:66 apps/rules/forms.py:106 apps/rules/forms.py:391
|
||||
#: apps/transactions/forms.py:184 apps/transactions/forms.py:204
|
||||
#: apps/transactions/forms.py:368 apps/transactions/forms.py:827
|
||||
#: apps/transactions/forms.py:866 apps/transactions/forms.py:894
|
||||
#: apps/transactions/forms.py:925 apps/transactions/forms.py:1071
|
||||
#: apps/users/forms.py:228 apps/users/forms.py:386
|
||||
#: apps/transactions/forms.py:205 apps/transactions/forms.py:225
|
||||
#: apps/transactions/forms.py:424 apps/transactions/forms.py:886
|
||||
#: apps/transactions/forms.py:925 apps/transactions/forms.py:953
|
||||
#: apps/transactions/forms.py:984 apps/transactions/forms.py:1134
|
||||
#: apps/users/forms.py:248 apps/users/forms.py:406
|
||||
#: templates/mini_tools/unit_price_calculator.html:168
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
@@ -62,12 +62,12 @@ msgstr ""
|
||||
#: apps/accounts/forms.py:125 apps/dca/forms.py:79 apps/dca/forms.py:86
|
||||
#: apps/insights/forms.py:117 apps/rules/forms.py:181 apps/rules/forms.py:197
|
||||
#: apps/rules/models.py:44 apps/rules/models.py:311
|
||||
#: apps/transactions/forms.py:43 apps/transactions/forms.py:251
|
||||
#: apps/transactions/forms.py:419 apps/transactions/forms.py:516
|
||||
#: apps/transactions/forms.py:523 apps/transactions/forms.py:707
|
||||
#: apps/transactions/forms.py:948 apps/transactions/models.py:322
|
||||
#: apps/transactions/models.py:578 apps/transactions/models.py:778
|
||||
#: apps/transactions/models.py:1026
|
||||
#: apps/transactions/forms.py:61 apps/transactions/forms.py:307
|
||||
#: apps/transactions/forms.py:475 apps/transactions/forms.py:572
|
||||
#: apps/transactions/forms.py:579 apps/transactions/forms.py:763
|
||||
#: apps/transactions/forms.py:1007 apps/transactions/models.py:331
|
||||
#: apps/transactions/models.py:641 apps/transactions/models.py:841
|
||||
#: apps/transactions/models.py:1089
|
||||
#: templates/insights/fragments/category_overview/index.html:86
|
||||
#: templates/insights/fragments/category_overview/index.html:542
|
||||
#: templates/insights/fragments/month_by_month.html:84
|
||||
@@ -79,12 +79,12 @@ msgstr ""
|
||||
#: apps/export_app/forms.py:43 apps/export_app/forms.py:132
|
||||
#: apps/rules/forms.py:184 apps/rules/forms.py:194 apps/rules/models.py:45
|
||||
#: apps/rules/models.py:315 apps/transactions/filters.py:73
|
||||
#: apps/transactions/forms.py:51 apps/transactions/forms.py:259
|
||||
#: apps/transactions/forms.py:427 apps/transactions/forms.py:532
|
||||
#: apps/transactions/forms.py:540 apps/transactions/forms.py:700
|
||||
#: apps/transactions/forms.py:941 apps/transactions/models.py:328
|
||||
#: apps/transactions/models.py:580 apps/transactions/models.py:782
|
||||
#: apps/transactions/models.py:1032 templates/includes/sidebar.html:150
|
||||
#: apps/transactions/forms.py:69 apps/transactions/forms.py:315
|
||||
#: apps/transactions/forms.py:483 apps/transactions/forms.py:588
|
||||
#: apps/transactions/forms.py:596 apps/transactions/forms.py:756
|
||||
#: apps/transactions/forms.py:1000 apps/transactions/models.py:337
|
||||
#: apps/transactions/models.py:643 apps/transactions/models.py:845
|
||||
#: apps/transactions/models.py:1095 templates/includes/sidebar.html:150
|
||||
#: templates/insights/fragments/category_overview/index.html:40
|
||||
#: templates/insights/fragments/month_by_month.html:29
|
||||
#: templates/insights/fragments/month_by_month.html:32
|
||||
@@ -96,8 +96,8 @@ msgstr ""
|
||||
|
||||
#: apps/accounts/models.py:12 apps/accounts/models.py:29 apps/dca/models.py:13
|
||||
#: apps/import_app/models.py:14 apps/rules/models.py:13
|
||||
#: apps/transactions/models.py:214 apps/transactions/models.py:239
|
||||
#: apps/transactions/models.py:263 apps/transactions/models.py:994
|
||||
#: apps/transactions/models.py:223 apps/transactions/models.py:248
|
||||
#: apps/transactions/models.py:272 apps/transactions/models.py:1057
|
||||
#: templates/account_groups/fragments/list.html:22
|
||||
#: templates/accounts/fragments/list.html:22
|
||||
#: templates/categories/fragments/table.html:17
|
||||
@@ -163,11 +163,11 @@ msgstr ""
|
||||
|
||||
#: apps/accounts/models.py:75 apps/rules/forms.py:173 apps/rules/forms.py:187
|
||||
#: apps/rules/models.py:35 apps/rules/models.py:267
|
||||
#: apps/transactions/forms.py:63 apps/transactions/forms.py:271
|
||||
#: apps/transactions/forms.py:386 apps/transactions/forms.py:692
|
||||
#: apps/transactions/forms.py:933 apps/transactions/models.py:294
|
||||
#: apps/transactions/models.py:538 apps/transactions/models.py:760
|
||||
#: apps/transactions/models.py:1000
|
||||
#: apps/transactions/forms.py:81 apps/transactions/forms.py:327
|
||||
#: apps/transactions/forms.py:442 apps/transactions/forms.py:748
|
||||
#: apps/transactions/forms.py:992 apps/transactions/models.py:303
|
||||
#: apps/transactions/models.py:601 apps/transactions/models.py:823
|
||||
#: apps/transactions/models.py:1063
|
||||
#: templates/installment_plans/fragments/table.html:17
|
||||
#: templates/quick_transactions/fragments/list.html:14
|
||||
#: templates/recurring_transactions/fragments/table.html:19
|
||||
@@ -344,7 +344,7 @@ msgid ""
|
||||
"owner.<br/>Public: Shown for all users. Only editable by the owner."
|
||||
msgstr ""
|
||||
|
||||
#: apps/common/forms.py:76 apps/users/forms.py:149
|
||||
#: apps/common/forms.py:76 apps/users/forms.py:169
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
@@ -480,8 +480,8 @@ msgstr ""
|
||||
|
||||
#: apps/currencies/forms.py:66 apps/dca/models.py:158 apps/rules/forms.py:176
|
||||
#: apps/rules/forms.py:190 apps/rules/models.py:38 apps/rules/models.py:279
|
||||
#: apps/transactions/forms.py:67 apps/transactions/forms.py:391
|
||||
#: apps/transactions/forms.py:544 apps/transactions/models.py:304
|
||||
#: apps/transactions/forms.py:85 apps/transactions/forms.py:447
|
||||
#: apps/transactions/forms.py:600 apps/transactions/models.py:313
|
||||
#: templates/dca/fragments/strategy/details.html:49
|
||||
#: templates/exchange_rates/fragments/table.html:10
|
||||
#: templates/exchange_rates_services/fragments/table.html:11
|
||||
@@ -567,8 +567,8 @@ msgid "Service Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/currencies/models.py:118 apps/transactions/filters.py:27
|
||||
#: apps/transactions/models.py:218 apps/transactions/models.py:242
|
||||
#: apps/transactions/models.py:266 templates/categories/fragments/list.html:16
|
||||
#: apps/transactions/models.py:227 apps/transactions/models.py:251
|
||||
#: apps/transactions/models.py:275 templates/categories/fragments/list.html:16
|
||||
#: templates/entities/fragments/list.html:16
|
||||
#: templates/installment_plans/fragments/list.html:16
|
||||
#: templates/recurring_transactions/fragments/list.html:16
|
||||
@@ -696,11 +696,11 @@ msgstr ""
|
||||
msgid "Create transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:64 apps/transactions/forms.py:491
|
||||
#: apps/dca/forms.py:64 apps/transactions/forms.py:547
|
||||
msgid "From Account"
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:70 apps/transactions/forms.py:496
|
||||
#: apps/dca/forms.py:70 apps/transactions/forms.py:552
|
||||
msgid "To Account"
|
||||
msgstr ""
|
||||
|
||||
@@ -725,7 +725,7 @@ msgstr ""
|
||||
msgid "You must provide an account."
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:290 apps/transactions/forms.py:638
|
||||
#: apps/dca/forms.py:290 apps/transactions/forms.py:694
|
||||
msgid "From and To accounts must be different."
|
||||
msgstr ""
|
||||
|
||||
@@ -744,9 +744,9 @@ msgstr ""
|
||||
|
||||
#: apps/dca/models.py:26 apps/dca/models.py:181 apps/rules/forms.py:180
|
||||
#: apps/rules/forms.py:196 apps/rules/models.py:43 apps/rules/models.py:295
|
||||
#: apps/transactions/forms.py:413 apps/transactions/forms.py:560
|
||||
#: apps/transactions/models.py:318 apps/transactions/models.py:587
|
||||
#: apps/transactions/models.py:788 apps/transactions/models.py:1022
|
||||
#: apps/transactions/forms.py:469 apps/transactions/forms.py:616
|
||||
#: apps/transactions/models.py:327 apps/transactions/models.py:650
|
||||
#: apps/transactions/models.py:851 apps/transactions/models.py:1085
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
@@ -809,7 +809,7 @@ msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:31 apps/export_app/forms.py:134
|
||||
#: apps/transactions/models.py:379 templates/includes/sidebar.html:81
|
||||
#: apps/transactions/models.py:388 templates/includes/sidebar.html:81
|
||||
#: templates/includes/sidebar.html:142
|
||||
#: templates/recurring_transactions/fragments/list_transactions.html:5
|
||||
#: templates/recurring_transactions/fragments/table.html:37
|
||||
@@ -830,11 +830,11 @@ msgstr ""
|
||||
#: apps/export_app/forms.py:49 apps/export_app/forms.py:133
|
||||
#: apps/rules/forms.py:185 apps/rules/forms.py:195 apps/rules/models.py:46
|
||||
#: apps/rules/models.py:307 apps/transactions/filters.py:78
|
||||
#: apps/transactions/forms.py:59 apps/transactions/forms.py:267
|
||||
#: apps/transactions/forms.py:435 apps/transactions/forms.py:715
|
||||
#: apps/transactions/forms.py:956 apps/transactions/models.py:277
|
||||
#: apps/transactions/models.py:333 apps/transactions/models.py:583
|
||||
#: apps/transactions/models.py:785 apps/transactions/models.py:1037
|
||||
#: apps/transactions/forms.py:77 apps/transactions/forms.py:323
|
||||
#: apps/transactions/forms.py:491 apps/transactions/forms.py:771
|
||||
#: apps/transactions/forms.py:1015 apps/transactions/models.py:286
|
||||
#: apps/transactions/models.py:342 apps/transactions/models.py:646
|
||||
#: apps/transactions/models.py:848 apps/transactions/models.py:1100
|
||||
#: templates/entities/fragments/list.html:9
|
||||
#: templates/entities/pages/index.html:4 templates/includes/sidebar.html:156
|
||||
#: templates/insights/fragments/category_overview/index.html:54
|
||||
@@ -846,14 +846,14 @@ msgid "Entities"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:55 apps/export_app/forms.py:137
|
||||
#: apps/transactions/models.py:825 templates/includes/sidebar.html:110
|
||||
#: apps/transactions/models.py:888 templates/includes/sidebar.html:110
|
||||
#: templates/recurring_transactions/fragments/list.html:9
|
||||
#: templates/recurring_transactions/pages/index.html:4
|
||||
msgid "Recurring Transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:61 apps/export_app/forms.py:135
|
||||
#: apps/transactions/models.py:601 templates/includes/sidebar.html:104
|
||||
#: apps/transactions/models.py:664 templates/includes/sidebar.html:104
|
||||
#: templates/installment_plans/fragments/list.html:9
|
||||
#: templates/installment_plans/pages/index.html:4
|
||||
msgid "Installment Plans"
|
||||
@@ -906,7 +906,7 @@ msgstr ""
|
||||
msgid "Update or create transaction actions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:181 templates/cotton/transaction/item.html:224
|
||||
#: apps/export_app/forms.py:181 templates/cotton/transaction/item.html:230
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:53
|
||||
#: templates/export_app/fragments/restore.html:5
|
||||
#: templates/export_app/pages/index.html:19
|
||||
@@ -1102,16 +1102,16 @@ msgid "Operator"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:174 apps/rules/forms.py:188 apps/rules/models.py:36
|
||||
#: apps/rules/models.py:271 apps/transactions/forms.py:377
|
||||
#: apps/transactions/models.py:301 apps/transactions/models.py:543
|
||||
#: apps/transactions/models.py:766 apps/transactions/models.py:1007
|
||||
#: apps/rules/models.py:271 apps/transactions/forms.py:433
|
||||
#: apps/transactions/models.py:310 apps/transactions/models.py:606
|
||||
#: apps/transactions/models.py:829 apps/transactions/models.py:1070
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:175 apps/rules/forms.py:189 apps/rules/models.py:37
|
||||
#: apps/rules/models.py:275 apps/transactions/filters.py:22
|
||||
#: apps/transactions/forms.py:381 apps/transactions/models.py:303
|
||||
#: apps/transactions/models.py:1009 templates/cotton/transaction/item.html:20
|
||||
#: apps/transactions/forms.py:437 apps/transactions/models.py:312
|
||||
#: apps/transactions/models.py:1072 templates/cotton/transaction/item.html:20
|
||||
#: templates/cotton/transaction/item.html:31
|
||||
#: templates/transactions/widgets/paid_toggle_button.html:10
|
||||
#: templates/transactions/widgets/unselectable_paid_toggle_button.html:13
|
||||
@@ -1119,17 +1119,17 @@ msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:177 apps/rules/forms.py:191 apps/rules/models.py:39
|
||||
#: apps/rules/models.py:283 apps/transactions/forms.py:71
|
||||
#: apps/transactions/forms.py:397 apps/transactions/forms.py:547
|
||||
#: apps/transactions/forms.py:721 apps/transactions/models.py:305
|
||||
#: apps/transactions/models.py:561 apps/transactions/models.py:790
|
||||
#: apps/rules/models.py:283 apps/transactions/forms.py:89
|
||||
#: apps/transactions/forms.py:453 apps/transactions/forms.py:603
|
||||
#: apps/transactions/forms.py:777 apps/transactions/models.py:314
|
||||
#: apps/transactions/models.py:624 apps/transactions/models.py:853
|
||||
msgid "Reference Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:178 apps/rules/forms.py:192 apps/rules/models.py:41
|
||||
#: apps/rules/models.py:287 apps/transactions/forms.py:404
|
||||
#: apps/transactions/models.py:311 apps/transactions/models.py:771
|
||||
#: apps/transactions/models.py:1015
|
||||
#: apps/rules/models.py:287 apps/transactions/forms.py:460
|
||||
#: apps/transactions/models.py:320 apps/transactions/models.py:834
|
||||
#: apps/transactions/models.py:1078
|
||||
#: templates/insights/fragments/sankey.html:102
|
||||
#: templates/installment_plans/fragments/table.html:18
|
||||
#: templates/quick_transactions/fragments/list.html:15
|
||||
@@ -1139,28 +1139,28 @@ msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:179 apps/rules/forms.py:193 apps/rules/models.py:14
|
||||
#: apps/rules/models.py:42 apps/rules/models.py:291
|
||||
#: apps/transactions/forms.py:408 apps/transactions/forms.py:551
|
||||
#: apps/transactions/models.py:316 apps/transactions/models.py:545
|
||||
#: apps/transactions/models.py:774 apps/transactions/models.py:1020
|
||||
#: apps/transactions/forms.py:464 apps/transactions/forms.py:607
|
||||
#: apps/transactions/models.py:325 apps/transactions/models.py:608
|
||||
#: apps/transactions/models.py:837 apps/transactions/models.py:1083
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:182 apps/rules/forms.py:198 apps/rules/models.py:47
|
||||
#: apps/rules/models.py:299 apps/transactions/models.py:355
|
||||
#: apps/transactions/models.py:1042
|
||||
#: apps/rules/models.py:299 apps/transactions/models.py:364
|
||||
#: apps/transactions/models.py:1105
|
||||
msgid "Internal Note"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:183 apps/rules/forms.py:199 apps/rules/models.py:48
|
||||
#: apps/rules/models.py:303 apps/transactions/models.py:357
|
||||
#: apps/transactions/models.py:1044
|
||||
#: apps/rules/models.py:303 apps/transactions/models.py:366
|
||||
#: apps/transactions/models.py:1107
|
||||
msgid "Internal ID"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:186 apps/rules/forms.py:200 apps/rules/models.py:40
|
||||
#: apps/rules/models.py:319 apps/transactions/forms.py:564
|
||||
#: apps/transactions/models.py:215 apps/transactions/models.py:306
|
||||
#: apps/transactions/models.py:1010
|
||||
#: apps/rules/models.py:319 apps/transactions/forms.py:620
|
||||
#: apps/transactions/models.py:224 apps/transactions/models.py:315
|
||||
#: apps/transactions/models.py:1073
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
@@ -1173,7 +1173,7 @@ msgid "Set Values"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:407 apps/rules/forms.py:442 apps/rules/forms.py:477
|
||||
#: apps/transactions/models.py:378
|
||||
#: apps/transactions/models.py:387 apps/transactions/models.py:544
|
||||
msgid "Transaction"
|
||||
msgstr ""
|
||||
|
||||
@@ -1378,96 +1378,110 @@ msgstr ""
|
||||
msgid "No entity"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:170
|
||||
#: apps/transactions/forms.py:191
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:207
|
||||
#: apps/transactions/forms.py:228
|
||||
msgid "Save and add similar"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:212
|
||||
#: apps/transactions/forms.py:233
|
||||
msgid "Save and add another"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:295 apps/transactions/forms.py:567
|
||||
#: apps/transactions/forms.py:270 templates/cotton/transaction/item.html:158
|
||||
#: templates/transactions/fragments/attachments.html:4
|
||||
msgid "Attachments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:271
|
||||
msgid ""
|
||||
"Files are private and only visible to users with access to this transaction."
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:282
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:351 apps/transactions/forms.py:623
|
||||
msgid "Muted transactions won't be displayed on monthly summaries"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:503
|
||||
#: apps/transactions/forms.py:559
|
||||
msgid "From Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:508
|
||||
#: apps/transactions/forms.py:564
|
||||
msgid "To Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:606
|
||||
#: apps/transactions/forms.py:662
|
||||
#: templates/cotton/ui/quick_transactions_buttons.html:40
|
||||
#: templates/cotton/ui/transactions_fab.html:44
|
||||
msgid "Transfer"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:847
|
||||
#: apps/transactions/forms.py:906
|
||||
msgid "Tag name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:875
|
||||
#: apps/transactions/forms.py:934
|
||||
msgid "Entity name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:903
|
||||
#: apps/transactions/forms.py:962
|
||||
msgid "Category name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:905
|
||||
#: apps/transactions/forms.py:964
|
||||
msgid "Muted categories won't be displayed on monthly summaries"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:1055
|
||||
#: apps/transactions/forms.py:1118
|
||||
msgid "future transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:1081
|
||||
#: apps/transactions/forms.py:1144
|
||||
msgid "End date should be after the start date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:220
|
||||
#: apps/transactions/models.py:229
|
||||
msgid ""
|
||||
"Deactivated categories won't be able to be selected when creating new "
|
||||
"transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:228
|
||||
#: apps/transactions/models.py:237
|
||||
msgid "Transaction Category"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:229
|
||||
#: apps/transactions/models.py:238
|
||||
msgid "Transaction Categories"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:244
|
||||
#: apps/transactions/models.py:253
|
||||
msgid ""
|
||||
"Deactivated tags won't be able to be selected when creating new transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:252 apps/transactions/models.py:253
|
||||
#: apps/transactions/models.py:261 apps/transactions/models.py:262
|
||||
msgid "Transaction Tags"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:268
|
||||
#: apps/transactions/models.py:277
|
||||
msgid ""
|
||||
"Deactivated entities won't be able to be selected when creating new "
|
||||
"transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:276
|
||||
#: apps/transactions/models.py:285
|
||||
#: templates/insights/fragments/month_by_month.html:88
|
||||
#: templates/insights/fragments/year_by_year.html:56
|
||||
msgid "Entity"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:288 apps/transactions/models.py:987
|
||||
#: apps/transactions/models.py:297 apps/transactions/models.py:1050
|
||||
#: templates/calendar_view/fragments/list.html:42
|
||||
#: templates/calendar_view/fragments/list.html:44
|
||||
#: templates/calendar_view/fragments/list.html:52
|
||||
@@ -1479,7 +1493,7 @@ msgstr ""
|
||||
msgid "Income"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:289 apps/transactions/models.py:988
|
||||
#: apps/transactions/models.py:298 apps/transactions/models.py:1051
|
||||
#: templates/calendar_view/fragments/list.html:46
|
||||
#: templates/calendar_view/fragments/list.html:48
|
||||
#: templates/calendar_view/fragments/list.html:56
|
||||
@@ -1490,129 +1504,157 @@ msgstr ""
|
||||
msgid "Expense"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:344 apps/transactions/models.py:600
|
||||
#: apps/transactions/models.py:353 apps/transactions/models.py:663
|
||||
msgid "Installment Plan"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:353 apps/transactions/models.py:824
|
||||
#: apps/transactions/models.py:362 apps/transactions/models.py:887
|
||||
msgid "Recurring Transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:361
|
||||
#: apps/transactions/models.py:370
|
||||
msgid "Deleted"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:366
|
||||
#: apps/transactions/models.py:375
|
||||
msgid "Deleted At"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:480 templates/tags/fragments/table.html:69
|
||||
#: apps/transactions/models.py:489 templates/tags/fragments/table.html:69
|
||||
msgid "No tags"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:482
|
||||
#: apps/transactions/models.py:491
|
||||
msgid "No category"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:484
|
||||
#: apps/transactions/models.py:493
|
||||
msgid "No description"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:532 templates/includes/sidebar.html:57
|
||||
#: apps/transactions/models.py:549
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:551
|
||||
msgid "Original Name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:553
|
||||
msgid "Content Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:555
|
||||
msgid "Size"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:560
|
||||
msgid "Uploaded By"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:565
|
||||
msgid "Transaction Attachment"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:566
|
||||
msgid "Transaction Attachments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:595 templates/includes/sidebar.html:57
|
||||
msgid "Yearly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:533 apps/users/models.py:464
|
||||
#: apps/transactions/models.py:596 apps/users/models.py:464
|
||||
#: templates/includes/sidebar.html:51
|
||||
msgid "Monthly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:534
|
||||
#: apps/transactions/models.py:597
|
||||
msgid "Weekly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:535
|
||||
#: apps/transactions/models.py:598
|
||||
msgid "Daily"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:548
|
||||
#: apps/transactions/models.py:611
|
||||
msgid "Number of Installments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:553
|
||||
#: apps/transactions/models.py:616
|
||||
msgid "Installment Start"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:554
|
||||
#: apps/transactions/models.py:617
|
||||
msgid "The installment number to start counting from"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:559 apps/transactions/models.py:794
|
||||
#: apps/transactions/models.py:622 apps/transactions/models.py:857
|
||||
msgid "Start Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:563 apps/transactions/models.py:795
|
||||
#: apps/transactions/models.py:626 apps/transactions/models.py:858
|
||||
msgid "End Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:568
|
||||
#: apps/transactions/models.py:631
|
||||
msgid "Recurrence"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:571
|
||||
#: apps/transactions/models.py:634
|
||||
msgid "Installment Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:590 apps/transactions/models.py:814
|
||||
#: apps/transactions/models.py:653 apps/transactions/models.py:877
|
||||
msgid "Add description to transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:593 apps/transactions/models.py:817
|
||||
#: apps/transactions/models.py:656 apps/transactions/models.py:880
|
||||
msgid "Add notes to transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:753
|
||||
#: apps/transactions/models.py:816
|
||||
msgid "day(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:754
|
||||
#: apps/transactions/models.py:817
|
||||
msgid "week(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:755
|
||||
#: apps/transactions/models.py:818
|
||||
msgid "month(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:756
|
||||
#: apps/transactions/models.py:819
|
||||
msgid "year(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:758
|
||||
#: apps/transactions/models.py:821
|
||||
#: templates/recurring_transactions/fragments/list.html:18
|
||||
msgid "Paused"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:797
|
||||
#: apps/transactions/models.py:860
|
||||
msgid "Recurrence Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:800
|
||||
#: apps/transactions/models.py:863
|
||||
msgid "Recurrence Interval"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:803
|
||||
#: apps/transactions/models.py:866
|
||||
msgid "Keep at most"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:807
|
||||
#: apps/transactions/models.py:870
|
||||
msgid "Last Generated Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:810
|
||||
#: apps/transactions/models.py:873
|
||||
msgid "Last Generated Reference Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:1054
|
||||
#: apps/transactions/models.py:1117
|
||||
#: apps/transactions/views/quick_transactions.py:178
|
||||
#: apps/transactions/views/quick_transactions.py:187
|
||||
#: apps/transactions/views/quick_transactions.py:189
|
||||
@@ -1621,7 +1663,7 @@ msgstr ""
|
||||
msgid "Quick Transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:1055 templates/includes/sidebar.html:98
|
||||
#: apps/transactions/models.py:1118 templates/includes/sidebar.html:98
|
||||
#: templates/quick_transactions/pages/index.html:5
|
||||
#: templates/quick_transactions/pages/index.html:15
|
||||
msgid "Quick Transactions"
|
||||
@@ -1726,8 +1768,8 @@ msgid "Item deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/quick_transactions.py:156
|
||||
#: apps/transactions/views/transactions.py:53
|
||||
#: apps/transactions/views/transactions.py:238
|
||||
#: apps/transactions/views/transactions.py:141
|
||||
#: apps/transactions/views/transactions.py:326
|
||||
msgid "Transaction added successfully"
|
||||
msgstr ""
|
||||
|
||||
@@ -1767,30 +1809,38 @@ msgstr ""
|
||||
msgid "Tag deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:262
|
||||
#: apps/transactions/views/transactions.py:59
|
||||
msgid "Attachment uploaded successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:110
|
||||
msgid "Attachment deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:350
|
||||
msgid "Transaction updated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:313
|
||||
#: apps/transactions/views/transactions.py:401
|
||||
#, python-format
|
||||
msgid "%(count)s transaction updated successfully"
|
||||
msgid_plural "%(count)s transactions updated successfully"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:349
|
||||
#: apps/transactions/views/transactions.py:437
|
||||
msgid "Transaction duplicated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:391
|
||||
#: apps/transactions/views/transactions.py:479
|
||||
msgid "Transaction deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:409
|
||||
#: apps/transactions/views/transactions.py:497
|
||||
msgid "Transaction restored successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:435
|
||||
#: apps/transactions/views/transactions.py:523
|
||||
msgid "Transfer added successfully"
|
||||
msgstr ""
|
||||
|
||||
@@ -1814,24 +1864,24 @@ msgstr ""
|
||||
msgid "Important dates"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:22 apps/users/forms.py:26 apps/users/models.py:451
|
||||
#: apps/users/forms.py:24 apps/users/forms.py:28 apps/users/models.py:451
|
||||
#: templates/users/login.html:18
|
||||
msgid "E-mail"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:33 apps/users/forms.py:38 templates/users/login.html:19
|
||||
#: apps/users/forms.py:35 apps/users/forms.py:40 templates/users/login.html:19
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:45
|
||||
#: apps/users/forms.py:47
|
||||
msgid "Invalid e-mail or password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:46
|
||||
#: apps/users/forms.py:48
|
||||
msgid "This account is deactivated"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:62 apps/users/forms.py:75 apps/users/forms.py:97
|
||||
#: apps/users/forms.py:64 apps/users/forms.py:77 apps/users/forms.py:99
|
||||
#: templates/monthly_overview/pages/overview.html:98
|
||||
#: templates/monthly_overview/pages/overview.html:245
|
||||
#: templates/transactions/pages/transactions.html:47
|
||||
@@ -1839,19 +1889,23 @@ msgstr ""
|
||||
msgid "Default"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:105 apps/users/models.py:484
|
||||
#: apps/users/forms.py:107 apps/users/models.py:484
|
||||
msgid "Date Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:110 apps/users/models.py:489
|
||||
#: apps/users/forms.py:112 apps/users/models.py:489
|
||||
msgid "Datetime Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:116 apps/users/models.py:492
|
||||
#: apps/users/forms.py:118 apps/users/models.py:492
|
||||
msgid "Number Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:154
|
||||
#: apps/users/forms.py:125
|
||||
msgid "Default Account"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:174
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This changes the language (if available) and how numbers and dates are "
|
||||
@@ -1859,59 +1913,59 @@ msgid ""
|
||||
"Consider helping translate WYGIWYH to your language at %(translation_link)s"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:163
|
||||
#: apps/users/forms.py:183
|
||||
msgid "New Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:166
|
||||
#: apps/users/forms.py:186
|
||||
msgid "Leave blank to keep the current password."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:169
|
||||
#: apps/users/forms.py:189
|
||||
msgid "Confirm New Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:181 apps/users/forms.py:338
|
||||
#: apps/users/forms.py:201 apps/users/forms.py:358
|
||||
msgid ""
|
||||
"Designates whether this user should be treated as active. Unselect this "
|
||||
"instead of deleting accounts."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:184 apps/users/forms.py:341
|
||||
#: apps/users/forms.py:204 apps/users/forms.py:361
|
||||
msgid ""
|
||||
"Designates that this user has all permissions without explicitly assigning "
|
||||
"them."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:251
|
||||
#: apps/users/forms.py:271
|
||||
msgid "This email address is already in use by another account."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:259
|
||||
#: apps/users/forms.py:279
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:261
|
||||
#: apps/users/forms.py:281
|
||||
msgid "Please confirm your new password."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:263
|
||||
#: apps/users/forms.py:283
|
||||
msgid "Please enter the new password first."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:283
|
||||
#: apps/users/forms.py:303
|
||||
msgid "You cannot deactivate your own account using this form."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:296
|
||||
#: apps/users/forms.py:316
|
||||
msgid "Cannot remove status from the last superuser."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:302
|
||||
#: apps/users/forms.py:322
|
||||
msgid "You cannot remove your own superuser status using this form."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:395
|
||||
#: apps/users/forms.py:415
|
||||
msgid "A user with this email address already exists."
|
||||
msgstr ""
|
||||
|
||||
@@ -1955,6 +2009,14 @@ msgstr ""
|
||||
msgid "Start page"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/models.py:516
|
||||
msgid "Default account"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/models.py:517
|
||||
msgid "Selects the account by default when creating new transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/views.py:67
|
||||
msgid "Transaction amounts are now hidden"
|
||||
msgstr ""
|
||||
@@ -2049,8 +2111,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:54
|
||||
#: templates/accounts/fragments/list.html:71
|
||||
#: templates/categories/fragments/table.html:51
|
||||
#: templates/cotton/transaction/item.html:158
|
||||
#: templates/cotton/transaction/item.html:230
|
||||
#: templates/cotton/transaction/item.html:164
|
||||
#: templates/cotton/transaction/item.html:236
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:57
|
||||
#: templates/cotton/ui/transactions_action_bar.html:82
|
||||
#: templates/currencies/fragments/list.html:40
|
||||
@@ -2078,8 +2140,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:58
|
||||
#: templates/accounts/fragments/list.html:75
|
||||
#: templates/categories/fragments/table.html:56
|
||||
#: templates/cotton/transaction/item.html:160
|
||||
#: templates/cotton/transaction/item.html:236
|
||||
#: templates/cotton/transaction/item.html:166
|
||||
#: templates/cotton/transaction/item.html:242
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:58
|
||||
#: templates/cotton/ui/transactions_action_bar.html:83
|
||||
#: templates/currencies/fragments/list.html:44
|
||||
@@ -2108,8 +2170,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:59
|
||||
#: templates/accounts/fragments/list.html:76
|
||||
#: templates/categories/fragments/table.html:57
|
||||
#: templates/cotton/transaction/item.html:161
|
||||
#: templates/cotton/transaction/item.html:237
|
||||
#: templates/cotton/transaction/item.html:167
|
||||
#: templates/cotton/transaction/item.html:243
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:58
|
||||
#: templates/cotton/ui/transactions_action_bar.html:83
|
||||
#: templates/currencies/fragments/list.html:45
|
||||
@@ -2130,8 +2192,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:60
|
||||
#: templates/accounts/fragments/list.html:77
|
||||
#: templates/categories/fragments/table.html:58
|
||||
#: templates/cotton/transaction/item.html:162
|
||||
#: templates/cotton/transaction/item.html:238
|
||||
#: templates/cotton/transaction/item.html:168
|
||||
#: templates/cotton/transaction/item.html:244
|
||||
#: templates/currencies/fragments/list.html:46
|
||||
#: templates/dca/fragments/strategy/details.html:77
|
||||
#: templates/dca/fragments/strategy/list.html:44
|
||||
@@ -2148,6 +2210,7 @@ msgstr ""
|
||||
#: templates/rules/fragments/transaction_rule/view.html:65
|
||||
#: templates/rules/fragments/transaction_rule/view.html:98
|
||||
#: templates/tags/fragments/table.html:57
|
||||
#: templates/transactions/fragments/attachments.html:22
|
||||
msgid "Yes, delete it!"
|
||||
msgstr ""
|
||||
|
||||
@@ -2283,41 +2346,41 @@ msgstr ""
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:175
|
||||
#: templates/cotton/transaction/item.html:186
|
||||
#: templates/cotton/transaction/item.html:196
|
||||
#: templates/cotton/transaction/item.html:181
|
||||
#: templates/cotton/transaction/item.html:192
|
||||
#: templates/cotton/transaction/item.html:202
|
||||
msgid "Show on summaries"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:177
|
||||
#: templates/cotton/transaction/item.html:183
|
||||
msgid "Controlled by account"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:188
|
||||
#: templates/cotton/transaction/item.html:194
|
||||
msgid "Controlled by category"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:201
|
||||
#: templates/cotton/transaction/item.html:207
|
||||
msgid "Hide from summaries"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:205
|
||||
#: templates/cotton/transaction/item.html:211
|
||||
msgid "Add as quick transaction"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:210
|
||||
#: templates/cotton/transaction/item.html:216
|
||||
msgid "Move to previous month"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:214
|
||||
#: templates/cotton/transaction/item.html:220
|
||||
msgid "Move to next month"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:217
|
||||
#: templates/cotton/transaction/item.html:223
|
||||
msgid "Move to today"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:221
|
||||
#: templates/cotton/transaction/item.html:227
|
||||
#: templates/cotton/ui/transactions_action_bar.html:78
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
@@ -2798,6 +2861,10 @@ msgstr ""
|
||||
msgid "Try reloading the page or check the console for more information."
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/hyperscript/htmx_error_handler.html:24
|
||||
msgid "Reload"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/hyperscript/swal.html:13
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
@@ -2806,6 +2873,18 @@ msgstr ""
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:4
|
||||
msgid "Pull down to refresh"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:5
|
||||
msgid "Release to refresh"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:6
|
||||
msgid "Refreshing"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/sidebar.html:69 templates/insights/pages/index.html:5
|
||||
msgid "Insights"
|
||||
msgstr ""
|
||||
@@ -3449,6 +3528,22 @@ msgstr ""
|
||||
msgid "Add Installment Plan"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:20
|
||||
msgid "Delete this attachment?"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:21
|
||||
msgid "This file will be removed from the transaction."
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:30
|
||||
msgid "No attachments yet"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments_manage.html:5
|
||||
msgid "Transaction attachments"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/bulk_edit.html:5
|
||||
msgid "Bulk Editing"
|
||||
msgstr ""
|
||||
|
||||
+294
-179
File diff suppressed because it is too large
Load Diff
+307
-182
File diff suppressed because it is too large
Load Diff
+290
-177
File diff suppressed because it is too large
Load Diff
+272
-177
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-10 20:50+0000\n"
|
||||
"POT-Creation-Date: 2026-06-06 07:41+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
@@ -25,12 +25,12 @@ msgstr ""
|
||||
#: apps/currencies/forms.py:53 apps/currencies/forms.py:87
|
||||
#: apps/currencies/forms.py:136 apps/dca/forms.py:46 apps/dca/forms.py:205
|
||||
#: apps/import_app/forms.py:32 apps/rules/forms.py:60 apps/rules/forms.py:100
|
||||
#: apps/rules/forms.py:385 apps/transactions/forms.py:197
|
||||
#: apps/transactions/forms.py:361 apps/transactions/forms.py:480
|
||||
#: apps/transactions/forms.py:821 apps/transactions/forms.py:860
|
||||
#: apps/transactions/forms.py:888 apps/transactions/forms.py:919
|
||||
#: apps/transactions/forms.py:1065 apps/users/forms.py:222
|
||||
#: apps/users/forms.py:380
|
||||
#: apps/rules/forms.py:385 apps/transactions/forms.py:218
|
||||
#: apps/transactions/forms.py:417 apps/transactions/forms.py:536
|
||||
#: apps/transactions/forms.py:880 apps/transactions/forms.py:919
|
||||
#: apps/transactions/forms.py:947 apps/transactions/forms.py:978
|
||||
#: apps/transactions/forms.py:1128 apps/users/forms.py:242
|
||||
#: apps/users/forms.py:400
|
||||
#: templates/rules/fragments/transaction_rule/dry_run/updated.html:5
|
||||
#: templates/rules/fragments/transaction_rule/view.html:128
|
||||
msgid "Update"
|
||||
@@ -41,11 +41,11 @@ msgstr ""
|
||||
#: apps/currencies/forms.py:93 apps/currencies/forms.py:142
|
||||
#: apps/dca/forms.py:52 apps/dca/forms.py:211 apps/import_app/forms.py:38
|
||||
#: apps/rules/forms.py:66 apps/rules/forms.py:106 apps/rules/forms.py:391
|
||||
#: apps/transactions/forms.py:184 apps/transactions/forms.py:204
|
||||
#: apps/transactions/forms.py:368 apps/transactions/forms.py:827
|
||||
#: apps/transactions/forms.py:866 apps/transactions/forms.py:894
|
||||
#: apps/transactions/forms.py:925 apps/transactions/forms.py:1071
|
||||
#: apps/users/forms.py:228 apps/users/forms.py:386
|
||||
#: apps/transactions/forms.py:205 apps/transactions/forms.py:225
|
||||
#: apps/transactions/forms.py:424 apps/transactions/forms.py:886
|
||||
#: apps/transactions/forms.py:925 apps/transactions/forms.py:953
|
||||
#: apps/transactions/forms.py:984 apps/transactions/forms.py:1134
|
||||
#: apps/users/forms.py:248 apps/users/forms.py:406
|
||||
#: templates/mini_tools/unit_price_calculator.html:168
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
@@ -61,12 +61,12 @@ msgstr ""
|
||||
#: apps/accounts/forms.py:125 apps/dca/forms.py:79 apps/dca/forms.py:86
|
||||
#: apps/insights/forms.py:117 apps/rules/forms.py:181 apps/rules/forms.py:197
|
||||
#: apps/rules/models.py:44 apps/rules/models.py:311
|
||||
#: apps/transactions/forms.py:43 apps/transactions/forms.py:251
|
||||
#: apps/transactions/forms.py:419 apps/transactions/forms.py:516
|
||||
#: apps/transactions/forms.py:523 apps/transactions/forms.py:707
|
||||
#: apps/transactions/forms.py:948 apps/transactions/models.py:322
|
||||
#: apps/transactions/models.py:578 apps/transactions/models.py:778
|
||||
#: apps/transactions/models.py:1026
|
||||
#: apps/transactions/forms.py:61 apps/transactions/forms.py:307
|
||||
#: apps/transactions/forms.py:475 apps/transactions/forms.py:572
|
||||
#: apps/transactions/forms.py:579 apps/transactions/forms.py:763
|
||||
#: apps/transactions/forms.py:1007 apps/transactions/models.py:331
|
||||
#: apps/transactions/models.py:641 apps/transactions/models.py:841
|
||||
#: apps/transactions/models.py:1089
|
||||
#: templates/insights/fragments/category_overview/index.html:86
|
||||
#: templates/insights/fragments/category_overview/index.html:542
|
||||
#: templates/insights/fragments/month_by_month.html:84
|
||||
@@ -78,12 +78,12 @@ msgstr ""
|
||||
#: apps/export_app/forms.py:43 apps/export_app/forms.py:132
|
||||
#: apps/rules/forms.py:184 apps/rules/forms.py:194 apps/rules/models.py:45
|
||||
#: apps/rules/models.py:315 apps/transactions/filters.py:73
|
||||
#: apps/transactions/forms.py:51 apps/transactions/forms.py:259
|
||||
#: apps/transactions/forms.py:427 apps/transactions/forms.py:532
|
||||
#: apps/transactions/forms.py:540 apps/transactions/forms.py:700
|
||||
#: apps/transactions/forms.py:941 apps/transactions/models.py:328
|
||||
#: apps/transactions/models.py:580 apps/transactions/models.py:782
|
||||
#: apps/transactions/models.py:1032 templates/includes/sidebar.html:150
|
||||
#: apps/transactions/forms.py:69 apps/transactions/forms.py:315
|
||||
#: apps/transactions/forms.py:483 apps/transactions/forms.py:588
|
||||
#: apps/transactions/forms.py:596 apps/transactions/forms.py:756
|
||||
#: apps/transactions/forms.py:1000 apps/transactions/models.py:337
|
||||
#: apps/transactions/models.py:643 apps/transactions/models.py:845
|
||||
#: apps/transactions/models.py:1095 templates/includes/sidebar.html:150
|
||||
#: templates/insights/fragments/category_overview/index.html:40
|
||||
#: templates/insights/fragments/month_by_month.html:29
|
||||
#: templates/insights/fragments/month_by_month.html:32
|
||||
@@ -95,8 +95,8 @@ msgstr ""
|
||||
|
||||
#: apps/accounts/models.py:12 apps/accounts/models.py:29 apps/dca/models.py:13
|
||||
#: apps/import_app/models.py:14 apps/rules/models.py:13
|
||||
#: apps/transactions/models.py:214 apps/transactions/models.py:239
|
||||
#: apps/transactions/models.py:263 apps/transactions/models.py:994
|
||||
#: apps/transactions/models.py:223 apps/transactions/models.py:248
|
||||
#: apps/transactions/models.py:272 apps/transactions/models.py:1057
|
||||
#: templates/account_groups/fragments/list.html:22
|
||||
#: templates/accounts/fragments/list.html:22
|
||||
#: templates/categories/fragments/table.html:17
|
||||
@@ -162,11 +162,11 @@ msgstr ""
|
||||
|
||||
#: apps/accounts/models.py:75 apps/rules/forms.py:173 apps/rules/forms.py:187
|
||||
#: apps/rules/models.py:35 apps/rules/models.py:267
|
||||
#: apps/transactions/forms.py:63 apps/transactions/forms.py:271
|
||||
#: apps/transactions/forms.py:386 apps/transactions/forms.py:692
|
||||
#: apps/transactions/forms.py:933 apps/transactions/models.py:294
|
||||
#: apps/transactions/models.py:538 apps/transactions/models.py:760
|
||||
#: apps/transactions/models.py:1000
|
||||
#: apps/transactions/forms.py:81 apps/transactions/forms.py:327
|
||||
#: apps/transactions/forms.py:442 apps/transactions/forms.py:748
|
||||
#: apps/transactions/forms.py:992 apps/transactions/models.py:303
|
||||
#: apps/transactions/models.py:601 apps/transactions/models.py:823
|
||||
#: apps/transactions/models.py:1063
|
||||
#: templates/installment_plans/fragments/table.html:17
|
||||
#: templates/quick_transactions/fragments/list.html:14
|
||||
#: templates/recurring_transactions/fragments/table.html:19
|
||||
@@ -343,7 +343,7 @@ msgid ""
|
||||
"owner.<br/>Public: Shown for all users. Only editable by the owner."
|
||||
msgstr ""
|
||||
|
||||
#: apps/common/forms.py:76 apps/users/forms.py:149
|
||||
#: apps/common/forms.py:76 apps/users/forms.py:169
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
@@ -479,8 +479,8 @@ msgstr ""
|
||||
|
||||
#: apps/currencies/forms.py:66 apps/dca/models.py:158 apps/rules/forms.py:176
|
||||
#: apps/rules/forms.py:190 apps/rules/models.py:38 apps/rules/models.py:279
|
||||
#: apps/transactions/forms.py:67 apps/transactions/forms.py:391
|
||||
#: apps/transactions/forms.py:544 apps/transactions/models.py:304
|
||||
#: apps/transactions/forms.py:85 apps/transactions/forms.py:447
|
||||
#: apps/transactions/forms.py:600 apps/transactions/models.py:313
|
||||
#: templates/dca/fragments/strategy/details.html:49
|
||||
#: templates/exchange_rates/fragments/table.html:10
|
||||
#: templates/exchange_rates_services/fragments/table.html:11
|
||||
@@ -566,8 +566,8 @@ msgid "Service Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/currencies/models.py:118 apps/transactions/filters.py:27
|
||||
#: apps/transactions/models.py:218 apps/transactions/models.py:242
|
||||
#: apps/transactions/models.py:266 templates/categories/fragments/list.html:16
|
||||
#: apps/transactions/models.py:227 apps/transactions/models.py:251
|
||||
#: apps/transactions/models.py:275 templates/categories/fragments/list.html:16
|
||||
#: templates/entities/fragments/list.html:16
|
||||
#: templates/installment_plans/fragments/list.html:16
|
||||
#: templates/recurring_transactions/fragments/list.html:16
|
||||
@@ -695,11 +695,11 @@ msgstr ""
|
||||
msgid "Create transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:64 apps/transactions/forms.py:491
|
||||
#: apps/dca/forms.py:64 apps/transactions/forms.py:547
|
||||
msgid "From Account"
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:70 apps/transactions/forms.py:496
|
||||
#: apps/dca/forms.py:70 apps/transactions/forms.py:552
|
||||
msgid "To Account"
|
||||
msgstr ""
|
||||
|
||||
@@ -724,7 +724,7 @@ msgstr ""
|
||||
msgid "You must provide an account."
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:290 apps/transactions/forms.py:638
|
||||
#: apps/dca/forms.py:290 apps/transactions/forms.py:694
|
||||
msgid "From and To accounts must be different."
|
||||
msgstr ""
|
||||
|
||||
@@ -743,9 +743,9 @@ msgstr ""
|
||||
|
||||
#: apps/dca/models.py:26 apps/dca/models.py:181 apps/rules/forms.py:180
|
||||
#: apps/rules/forms.py:196 apps/rules/models.py:43 apps/rules/models.py:295
|
||||
#: apps/transactions/forms.py:413 apps/transactions/forms.py:560
|
||||
#: apps/transactions/models.py:318 apps/transactions/models.py:587
|
||||
#: apps/transactions/models.py:788 apps/transactions/models.py:1022
|
||||
#: apps/transactions/forms.py:469 apps/transactions/forms.py:616
|
||||
#: apps/transactions/models.py:327 apps/transactions/models.py:650
|
||||
#: apps/transactions/models.py:851 apps/transactions/models.py:1085
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
@@ -808,7 +808,7 @@ msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:31 apps/export_app/forms.py:134
|
||||
#: apps/transactions/models.py:379 templates/includes/sidebar.html:81
|
||||
#: apps/transactions/models.py:388 templates/includes/sidebar.html:81
|
||||
#: templates/includes/sidebar.html:142
|
||||
#: templates/recurring_transactions/fragments/list_transactions.html:5
|
||||
#: templates/recurring_transactions/fragments/table.html:37
|
||||
@@ -829,11 +829,11 @@ msgstr ""
|
||||
#: apps/export_app/forms.py:49 apps/export_app/forms.py:133
|
||||
#: apps/rules/forms.py:185 apps/rules/forms.py:195 apps/rules/models.py:46
|
||||
#: apps/rules/models.py:307 apps/transactions/filters.py:78
|
||||
#: apps/transactions/forms.py:59 apps/transactions/forms.py:267
|
||||
#: apps/transactions/forms.py:435 apps/transactions/forms.py:715
|
||||
#: apps/transactions/forms.py:956 apps/transactions/models.py:277
|
||||
#: apps/transactions/models.py:333 apps/transactions/models.py:583
|
||||
#: apps/transactions/models.py:785 apps/transactions/models.py:1037
|
||||
#: apps/transactions/forms.py:77 apps/transactions/forms.py:323
|
||||
#: apps/transactions/forms.py:491 apps/transactions/forms.py:771
|
||||
#: apps/transactions/forms.py:1015 apps/transactions/models.py:286
|
||||
#: apps/transactions/models.py:342 apps/transactions/models.py:646
|
||||
#: apps/transactions/models.py:848 apps/transactions/models.py:1100
|
||||
#: templates/entities/fragments/list.html:9
|
||||
#: templates/entities/pages/index.html:4 templates/includes/sidebar.html:156
|
||||
#: templates/insights/fragments/category_overview/index.html:54
|
||||
@@ -845,14 +845,14 @@ msgid "Entities"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:55 apps/export_app/forms.py:137
|
||||
#: apps/transactions/models.py:825 templates/includes/sidebar.html:110
|
||||
#: apps/transactions/models.py:888 templates/includes/sidebar.html:110
|
||||
#: templates/recurring_transactions/fragments/list.html:9
|
||||
#: templates/recurring_transactions/pages/index.html:4
|
||||
msgid "Recurring Transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:61 apps/export_app/forms.py:135
|
||||
#: apps/transactions/models.py:601 templates/includes/sidebar.html:104
|
||||
#: apps/transactions/models.py:664 templates/includes/sidebar.html:104
|
||||
#: templates/installment_plans/fragments/list.html:9
|
||||
#: templates/installment_plans/pages/index.html:4
|
||||
msgid "Installment Plans"
|
||||
@@ -905,7 +905,7 @@ msgstr ""
|
||||
msgid "Update or create transaction actions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:181 templates/cotton/transaction/item.html:224
|
||||
#: apps/export_app/forms.py:181 templates/cotton/transaction/item.html:230
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:53
|
||||
#: templates/export_app/fragments/restore.html:5
|
||||
#: templates/export_app/pages/index.html:19
|
||||
@@ -1101,16 +1101,16 @@ msgid "Operator"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:174 apps/rules/forms.py:188 apps/rules/models.py:36
|
||||
#: apps/rules/models.py:271 apps/transactions/forms.py:377
|
||||
#: apps/transactions/models.py:301 apps/transactions/models.py:543
|
||||
#: apps/transactions/models.py:766 apps/transactions/models.py:1007
|
||||
#: apps/rules/models.py:271 apps/transactions/forms.py:433
|
||||
#: apps/transactions/models.py:310 apps/transactions/models.py:606
|
||||
#: apps/transactions/models.py:829 apps/transactions/models.py:1070
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:175 apps/rules/forms.py:189 apps/rules/models.py:37
|
||||
#: apps/rules/models.py:275 apps/transactions/filters.py:22
|
||||
#: apps/transactions/forms.py:381 apps/transactions/models.py:303
|
||||
#: apps/transactions/models.py:1009 templates/cotton/transaction/item.html:20
|
||||
#: apps/transactions/forms.py:437 apps/transactions/models.py:312
|
||||
#: apps/transactions/models.py:1072 templates/cotton/transaction/item.html:20
|
||||
#: templates/cotton/transaction/item.html:31
|
||||
#: templates/transactions/widgets/paid_toggle_button.html:10
|
||||
#: templates/transactions/widgets/unselectable_paid_toggle_button.html:13
|
||||
@@ -1118,17 +1118,17 @@ msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:177 apps/rules/forms.py:191 apps/rules/models.py:39
|
||||
#: apps/rules/models.py:283 apps/transactions/forms.py:71
|
||||
#: apps/transactions/forms.py:397 apps/transactions/forms.py:547
|
||||
#: apps/transactions/forms.py:721 apps/transactions/models.py:305
|
||||
#: apps/transactions/models.py:561 apps/transactions/models.py:790
|
||||
#: apps/rules/models.py:283 apps/transactions/forms.py:89
|
||||
#: apps/transactions/forms.py:453 apps/transactions/forms.py:603
|
||||
#: apps/transactions/forms.py:777 apps/transactions/models.py:314
|
||||
#: apps/transactions/models.py:624 apps/transactions/models.py:853
|
||||
msgid "Reference Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:178 apps/rules/forms.py:192 apps/rules/models.py:41
|
||||
#: apps/rules/models.py:287 apps/transactions/forms.py:404
|
||||
#: apps/transactions/models.py:311 apps/transactions/models.py:771
|
||||
#: apps/transactions/models.py:1015
|
||||
#: apps/rules/models.py:287 apps/transactions/forms.py:460
|
||||
#: apps/transactions/models.py:320 apps/transactions/models.py:834
|
||||
#: apps/transactions/models.py:1078
|
||||
#: templates/insights/fragments/sankey.html:102
|
||||
#: templates/installment_plans/fragments/table.html:18
|
||||
#: templates/quick_transactions/fragments/list.html:15
|
||||
@@ -1138,28 +1138,28 @@ msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:179 apps/rules/forms.py:193 apps/rules/models.py:14
|
||||
#: apps/rules/models.py:42 apps/rules/models.py:291
|
||||
#: apps/transactions/forms.py:408 apps/transactions/forms.py:551
|
||||
#: apps/transactions/models.py:316 apps/transactions/models.py:545
|
||||
#: apps/transactions/models.py:774 apps/transactions/models.py:1020
|
||||
#: apps/transactions/forms.py:464 apps/transactions/forms.py:607
|
||||
#: apps/transactions/models.py:325 apps/transactions/models.py:608
|
||||
#: apps/transactions/models.py:837 apps/transactions/models.py:1083
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:182 apps/rules/forms.py:198 apps/rules/models.py:47
|
||||
#: apps/rules/models.py:299 apps/transactions/models.py:355
|
||||
#: apps/transactions/models.py:1042
|
||||
#: apps/rules/models.py:299 apps/transactions/models.py:364
|
||||
#: apps/transactions/models.py:1105
|
||||
msgid "Internal Note"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:183 apps/rules/forms.py:199 apps/rules/models.py:48
|
||||
#: apps/rules/models.py:303 apps/transactions/models.py:357
|
||||
#: apps/transactions/models.py:1044
|
||||
#: apps/rules/models.py:303 apps/transactions/models.py:366
|
||||
#: apps/transactions/models.py:1107
|
||||
msgid "Internal ID"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:186 apps/rules/forms.py:200 apps/rules/models.py:40
|
||||
#: apps/rules/models.py:319 apps/transactions/forms.py:564
|
||||
#: apps/transactions/models.py:215 apps/transactions/models.py:306
|
||||
#: apps/transactions/models.py:1010
|
||||
#: apps/rules/models.py:319 apps/transactions/forms.py:620
|
||||
#: apps/transactions/models.py:224 apps/transactions/models.py:315
|
||||
#: apps/transactions/models.py:1073
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
@@ -1172,7 +1172,7 @@ msgid "Set Values"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:407 apps/rules/forms.py:442 apps/rules/forms.py:477
|
||||
#: apps/transactions/models.py:378
|
||||
#: apps/transactions/models.py:387 apps/transactions/models.py:544
|
||||
msgid "Transaction"
|
||||
msgstr ""
|
||||
|
||||
@@ -1377,96 +1377,110 @@ msgstr ""
|
||||
msgid "No entity"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:170
|
||||
#: apps/transactions/forms.py:191
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:207
|
||||
#: apps/transactions/forms.py:228
|
||||
msgid "Save and add similar"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:212
|
||||
#: apps/transactions/forms.py:233
|
||||
msgid "Save and add another"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:295 apps/transactions/forms.py:567
|
||||
#: apps/transactions/forms.py:270 templates/cotton/transaction/item.html:158
|
||||
#: templates/transactions/fragments/attachments.html:4
|
||||
msgid "Attachments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:271
|
||||
msgid ""
|
||||
"Files are private and only visible to users with access to this transaction."
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:282
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:351 apps/transactions/forms.py:623
|
||||
msgid "Muted transactions won't be displayed on monthly summaries"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:503
|
||||
#: apps/transactions/forms.py:559
|
||||
msgid "From Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:508
|
||||
#: apps/transactions/forms.py:564
|
||||
msgid "To Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:606
|
||||
#: apps/transactions/forms.py:662
|
||||
#: templates/cotton/ui/quick_transactions_buttons.html:40
|
||||
#: templates/cotton/ui/transactions_fab.html:44
|
||||
msgid "Transfer"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:847
|
||||
#: apps/transactions/forms.py:906
|
||||
msgid "Tag name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:875
|
||||
#: apps/transactions/forms.py:934
|
||||
msgid "Entity name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:903
|
||||
#: apps/transactions/forms.py:962
|
||||
msgid "Category name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:905
|
||||
#: apps/transactions/forms.py:964
|
||||
msgid "Muted categories won't be displayed on monthly summaries"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:1055
|
||||
#: apps/transactions/forms.py:1118
|
||||
msgid "future transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:1081
|
||||
#: apps/transactions/forms.py:1144
|
||||
msgid "End date should be after the start date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:220
|
||||
#: apps/transactions/models.py:229
|
||||
msgid ""
|
||||
"Deactivated categories won't be able to be selected when creating new "
|
||||
"transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:228
|
||||
#: apps/transactions/models.py:237
|
||||
msgid "Transaction Category"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:229
|
||||
#: apps/transactions/models.py:238
|
||||
msgid "Transaction Categories"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:244
|
||||
#: apps/transactions/models.py:253
|
||||
msgid ""
|
||||
"Deactivated tags won't be able to be selected when creating new transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:252 apps/transactions/models.py:253
|
||||
#: apps/transactions/models.py:261 apps/transactions/models.py:262
|
||||
msgid "Transaction Tags"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:268
|
||||
#: apps/transactions/models.py:277
|
||||
msgid ""
|
||||
"Deactivated entities won't be able to be selected when creating new "
|
||||
"transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:276
|
||||
#: apps/transactions/models.py:285
|
||||
#: templates/insights/fragments/month_by_month.html:88
|
||||
#: templates/insights/fragments/year_by_year.html:56
|
||||
msgid "Entity"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:288 apps/transactions/models.py:987
|
||||
#: apps/transactions/models.py:297 apps/transactions/models.py:1050
|
||||
#: templates/calendar_view/fragments/list.html:42
|
||||
#: templates/calendar_view/fragments/list.html:44
|
||||
#: templates/calendar_view/fragments/list.html:52
|
||||
@@ -1478,7 +1492,7 @@ msgstr ""
|
||||
msgid "Income"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:289 apps/transactions/models.py:988
|
||||
#: apps/transactions/models.py:298 apps/transactions/models.py:1051
|
||||
#: templates/calendar_view/fragments/list.html:46
|
||||
#: templates/calendar_view/fragments/list.html:48
|
||||
#: templates/calendar_view/fragments/list.html:56
|
||||
@@ -1489,129 +1503,157 @@ msgstr ""
|
||||
msgid "Expense"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:344 apps/transactions/models.py:600
|
||||
#: apps/transactions/models.py:353 apps/transactions/models.py:663
|
||||
msgid "Installment Plan"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:353 apps/transactions/models.py:824
|
||||
#: apps/transactions/models.py:362 apps/transactions/models.py:887
|
||||
msgid "Recurring Transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:361
|
||||
#: apps/transactions/models.py:370
|
||||
msgid "Deleted"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:366
|
||||
#: apps/transactions/models.py:375
|
||||
msgid "Deleted At"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:480 templates/tags/fragments/table.html:69
|
||||
#: apps/transactions/models.py:489 templates/tags/fragments/table.html:69
|
||||
msgid "No tags"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:482
|
||||
#: apps/transactions/models.py:491
|
||||
msgid "No category"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:484
|
||||
#: apps/transactions/models.py:493
|
||||
msgid "No description"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:532 templates/includes/sidebar.html:57
|
||||
#: apps/transactions/models.py:549
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:551
|
||||
msgid "Original Name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:553
|
||||
msgid "Content Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:555
|
||||
msgid "Size"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:560
|
||||
msgid "Uploaded By"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:565
|
||||
msgid "Transaction Attachment"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:566
|
||||
msgid "Transaction Attachments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:595 templates/includes/sidebar.html:57
|
||||
msgid "Yearly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:533 apps/users/models.py:464
|
||||
#: apps/transactions/models.py:596 apps/users/models.py:464
|
||||
#: templates/includes/sidebar.html:51
|
||||
msgid "Monthly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:534
|
||||
#: apps/transactions/models.py:597
|
||||
msgid "Weekly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:535
|
||||
#: apps/transactions/models.py:598
|
||||
msgid "Daily"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:548
|
||||
#: apps/transactions/models.py:611
|
||||
msgid "Number of Installments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:553
|
||||
#: apps/transactions/models.py:616
|
||||
msgid "Installment Start"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:554
|
||||
#: apps/transactions/models.py:617
|
||||
msgid "The installment number to start counting from"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:559 apps/transactions/models.py:794
|
||||
#: apps/transactions/models.py:622 apps/transactions/models.py:857
|
||||
msgid "Start Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:563 apps/transactions/models.py:795
|
||||
#: apps/transactions/models.py:626 apps/transactions/models.py:858
|
||||
msgid "End Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:568
|
||||
#: apps/transactions/models.py:631
|
||||
msgid "Recurrence"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:571
|
||||
#: apps/transactions/models.py:634
|
||||
msgid "Installment Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:590 apps/transactions/models.py:814
|
||||
#: apps/transactions/models.py:653 apps/transactions/models.py:877
|
||||
msgid "Add description to transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:593 apps/transactions/models.py:817
|
||||
#: apps/transactions/models.py:656 apps/transactions/models.py:880
|
||||
msgid "Add notes to transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:753
|
||||
#: apps/transactions/models.py:816
|
||||
msgid "day(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:754
|
||||
#: apps/transactions/models.py:817
|
||||
msgid "week(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:755
|
||||
#: apps/transactions/models.py:818
|
||||
msgid "month(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:756
|
||||
#: apps/transactions/models.py:819
|
||||
msgid "year(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:758
|
||||
#: apps/transactions/models.py:821
|
||||
#: templates/recurring_transactions/fragments/list.html:18
|
||||
msgid "Paused"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:797
|
||||
#: apps/transactions/models.py:860
|
||||
msgid "Recurrence Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:800
|
||||
#: apps/transactions/models.py:863
|
||||
msgid "Recurrence Interval"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:803
|
||||
#: apps/transactions/models.py:866
|
||||
msgid "Keep at most"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:807
|
||||
#: apps/transactions/models.py:870
|
||||
msgid "Last Generated Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:810
|
||||
#: apps/transactions/models.py:873
|
||||
msgid "Last Generated Reference Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:1054
|
||||
#: apps/transactions/models.py:1117
|
||||
#: apps/transactions/views/quick_transactions.py:178
|
||||
#: apps/transactions/views/quick_transactions.py:187
|
||||
#: apps/transactions/views/quick_transactions.py:189
|
||||
@@ -1620,7 +1662,7 @@ msgstr ""
|
||||
msgid "Quick Transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:1055 templates/includes/sidebar.html:98
|
||||
#: apps/transactions/models.py:1118 templates/includes/sidebar.html:98
|
||||
#: templates/quick_transactions/pages/index.html:5
|
||||
#: templates/quick_transactions/pages/index.html:15
|
||||
msgid "Quick Transactions"
|
||||
@@ -1725,8 +1767,8 @@ msgid "Item deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/quick_transactions.py:156
|
||||
#: apps/transactions/views/transactions.py:53
|
||||
#: apps/transactions/views/transactions.py:238
|
||||
#: apps/transactions/views/transactions.py:141
|
||||
#: apps/transactions/views/transactions.py:326
|
||||
msgid "Transaction added successfully"
|
||||
msgstr ""
|
||||
|
||||
@@ -1766,30 +1808,38 @@ msgstr ""
|
||||
msgid "Tag deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:262
|
||||
#: apps/transactions/views/transactions.py:59
|
||||
msgid "Attachment uploaded successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:110
|
||||
msgid "Attachment deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:350
|
||||
msgid "Transaction updated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:313
|
||||
#: apps/transactions/views/transactions.py:401
|
||||
#, python-format
|
||||
msgid "%(count)s transaction updated successfully"
|
||||
msgid_plural "%(count)s transactions updated successfully"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:349
|
||||
#: apps/transactions/views/transactions.py:437
|
||||
msgid "Transaction duplicated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:391
|
||||
#: apps/transactions/views/transactions.py:479
|
||||
msgid "Transaction deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:409
|
||||
#: apps/transactions/views/transactions.py:497
|
||||
msgid "Transaction restored successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:435
|
||||
#: apps/transactions/views/transactions.py:523
|
||||
msgid "Transfer added successfully"
|
||||
msgstr ""
|
||||
|
||||
@@ -1813,24 +1863,24 @@ msgstr ""
|
||||
msgid "Important dates"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:22 apps/users/forms.py:26 apps/users/models.py:451
|
||||
#: apps/users/forms.py:24 apps/users/forms.py:28 apps/users/models.py:451
|
||||
#: templates/users/login.html:18
|
||||
msgid "E-mail"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:33 apps/users/forms.py:38 templates/users/login.html:19
|
||||
#: apps/users/forms.py:35 apps/users/forms.py:40 templates/users/login.html:19
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:45
|
||||
#: apps/users/forms.py:47
|
||||
msgid "Invalid e-mail or password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:46
|
||||
#: apps/users/forms.py:48
|
||||
msgid "This account is deactivated"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:62 apps/users/forms.py:75 apps/users/forms.py:97
|
||||
#: apps/users/forms.py:64 apps/users/forms.py:77 apps/users/forms.py:99
|
||||
#: templates/monthly_overview/pages/overview.html:98
|
||||
#: templates/monthly_overview/pages/overview.html:245
|
||||
#: templates/transactions/pages/transactions.html:47
|
||||
@@ -1838,19 +1888,23 @@ msgstr ""
|
||||
msgid "Default"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:105 apps/users/models.py:484
|
||||
#: apps/users/forms.py:107 apps/users/models.py:484
|
||||
msgid "Date Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:110 apps/users/models.py:489
|
||||
#: apps/users/forms.py:112 apps/users/models.py:489
|
||||
msgid "Datetime Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:116 apps/users/models.py:492
|
||||
#: apps/users/forms.py:118 apps/users/models.py:492
|
||||
msgid "Number Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:154
|
||||
#: apps/users/forms.py:125
|
||||
msgid "Default Account"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:174
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This changes the language (if available) and how numbers and dates are "
|
||||
@@ -1858,59 +1912,59 @@ msgid ""
|
||||
"Consider helping translate WYGIWYH to your language at %(translation_link)s"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:163
|
||||
#: apps/users/forms.py:183
|
||||
msgid "New Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:166
|
||||
#: apps/users/forms.py:186
|
||||
msgid "Leave blank to keep the current password."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:169
|
||||
#: apps/users/forms.py:189
|
||||
msgid "Confirm New Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:181 apps/users/forms.py:338
|
||||
#: apps/users/forms.py:201 apps/users/forms.py:358
|
||||
msgid ""
|
||||
"Designates whether this user should be treated as active. Unselect this "
|
||||
"instead of deleting accounts."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:184 apps/users/forms.py:341
|
||||
#: apps/users/forms.py:204 apps/users/forms.py:361
|
||||
msgid ""
|
||||
"Designates that this user has all permissions without explicitly assigning "
|
||||
"them."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:251
|
||||
#: apps/users/forms.py:271
|
||||
msgid "This email address is already in use by another account."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:259
|
||||
#: apps/users/forms.py:279
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:261
|
||||
#: apps/users/forms.py:281
|
||||
msgid "Please confirm your new password."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:263
|
||||
#: apps/users/forms.py:283
|
||||
msgid "Please enter the new password first."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:283
|
||||
#: apps/users/forms.py:303
|
||||
msgid "You cannot deactivate your own account using this form."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:296
|
||||
#: apps/users/forms.py:316
|
||||
msgid "Cannot remove status from the last superuser."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:302
|
||||
#: apps/users/forms.py:322
|
||||
msgid "You cannot remove your own superuser status using this form."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:395
|
||||
#: apps/users/forms.py:415
|
||||
msgid "A user with this email address already exists."
|
||||
msgstr ""
|
||||
|
||||
@@ -1954,6 +2008,14 @@ msgstr ""
|
||||
msgid "Start page"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/models.py:516
|
||||
msgid "Default account"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/models.py:517
|
||||
msgid "Selects the account by default when creating new transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/views.py:67
|
||||
msgid "Transaction amounts are now hidden"
|
||||
msgstr ""
|
||||
@@ -2048,8 +2110,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:54
|
||||
#: templates/accounts/fragments/list.html:71
|
||||
#: templates/categories/fragments/table.html:51
|
||||
#: templates/cotton/transaction/item.html:158
|
||||
#: templates/cotton/transaction/item.html:230
|
||||
#: templates/cotton/transaction/item.html:164
|
||||
#: templates/cotton/transaction/item.html:236
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:57
|
||||
#: templates/cotton/ui/transactions_action_bar.html:82
|
||||
#: templates/currencies/fragments/list.html:40
|
||||
@@ -2077,8 +2139,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:58
|
||||
#: templates/accounts/fragments/list.html:75
|
||||
#: templates/categories/fragments/table.html:56
|
||||
#: templates/cotton/transaction/item.html:160
|
||||
#: templates/cotton/transaction/item.html:236
|
||||
#: templates/cotton/transaction/item.html:166
|
||||
#: templates/cotton/transaction/item.html:242
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:58
|
||||
#: templates/cotton/ui/transactions_action_bar.html:83
|
||||
#: templates/currencies/fragments/list.html:44
|
||||
@@ -2107,8 +2169,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:59
|
||||
#: templates/accounts/fragments/list.html:76
|
||||
#: templates/categories/fragments/table.html:57
|
||||
#: templates/cotton/transaction/item.html:161
|
||||
#: templates/cotton/transaction/item.html:237
|
||||
#: templates/cotton/transaction/item.html:167
|
||||
#: templates/cotton/transaction/item.html:243
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:58
|
||||
#: templates/cotton/ui/transactions_action_bar.html:83
|
||||
#: templates/currencies/fragments/list.html:45
|
||||
@@ -2129,8 +2191,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:60
|
||||
#: templates/accounts/fragments/list.html:77
|
||||
#: templates/categories/fragments/table.html:58
|
||||
#: templates/cotton/transaction/item.html:162
|
||||
#: templates/cotton/transaction/item.html:238
|
||||
#: templates/cotton/transaction/item.html:168
|
||||
#: templates/cotton/transaction/item.html:244
|
||||
#: templates/currencies/fragments/list.html:46
|
||||
#: templates/dca/fragments/strategy/details.html:77
|
||||
#: templates/dca/fragments/strategy/list.html:44
|
||||
@@ -2147,6 +2209,7 @@ msgstr ""
|
||||
#: templates/rules/fragments/transaction_rule/view.html:65
|
||||
#: templates/rules/fragments/transaction_rule/view.html:98
|
||||
#: templates/tags/fragments/table.html:57
|
||||
#: templates/transactions/fragments/attachments.html:22
|
||||
msgid "Yes, delete it!"
|
||||
msgstr ""
|
||||
|
||||
@@ -2282,41 +2345,41 @@ msgstr ""
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:175
|
||||
#: templates/cotton/transaction/item.html:186
|
||||
#: templates/cotton/transaction/item.html:196
|
||||
#: templates/cotton/transaction/item.html:181
|
||||
#: templates/cotton/transaction/item.html:192
|
||||
#: templates/cotton/transaction/item.html:202
|
||||
msgid "Show on summaries"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:177
|
||||
#: templates/cotton/transaction/item.html:183
|
||||
msgid "Controlled by account"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:188
|
||||
#: templates/cotton/transaction/item.html:194
|
||||
msgid "Controlled by category"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:201
|
||||
#: templates/cotton/transaction/item.html:207
|
||||
msgid "Hide from summaries"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:205
|
||||
#: templates/cotton/transaction/item.html:211
|
||||
msgid "Add as quick transaction"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:210
|
||||
#: templates/cotton/transaction/item.html:216
|
||||
msgid "Move to previous month"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:214
|
||||
#: templates/cotton/transaction/item.html:220
|
||||
msgid "Move to next month"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:217
|
||||
#: templates/cotton/transaction/item.html:223
|
||||
msgid "Move to today"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:221
|
||||
#: templates/cotton/transaction/item.html:227
|
||||
#: templates/cotton/ui/transactions_action_bar.html:78
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
@@ -2796,6 +2859,10 @@ msgstr ""
|
||||
msgid "Try reloading the page or check the console for more information."
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/hyperscript/htmx_error_handler.html:24
|
||||
msgid "Reload"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/hyperscript/swal.html:13
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
@@ -2804,6 +2871,18 @@ msgstr ""
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:4
|
||||
msgid "Pull down to refresh"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:5
|
||||
msgid "Release to refresh"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:6
|
||||
msgid "Refreshing"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/sidebar.html:69 templates/insights/pages/index.html:5
|
||||
msgid "Insights"
|
||||
msgstr ""
|
||||
@@ -3447,6 +3526,22 @@ msgstr ""
|
||||
msgid "Add Installment Plan"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:20
|
||||
msgid "Delete this attachment?"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:21
|
||||
msgid "This file will be removed from the transaction."
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:30
|
||||
msgid "No attachments yet"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments_manage.html:5
|
||||
msgid "Transaction attachments"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/bulk_edit.html:5
|
||||
msgid "Bulk Editing"
|
||||
msgstr ""
|
||||
|
||||
+302
-177
File diff suppressed because it is too large
Load Diff
+295
-184
File diff suppressed because it is too large
Load Diff
+857
-694
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+683
-545
File diff suppressed because it is too large
Load Diff
+272
-177
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-10 20:50+0000\n"
|
||||
"POT-Creation-Date: 2026-06-06 07:41+0000\n"
|
||||
"PO-Revision-Date: 2025-04-14 06:16+0000\n"
|
||||
"Last-Translator: Emil <emil.bjorkroth@gmail.com>\n"
|
||||
"Language-Team: Swedish <https://translations.herculino.com/projects/wygiwyh/"
|
||||
@@ -27,12 +27,12 @@ msgstr ""
|
||||
#: apps/currencies/forms.py:53 apps/currencies/forms.py:87
|
||||
#: apps/currencies/forms.py:136 apps/dca/forms.py:46 apps/dca/forms.py:205
|
||||
#: apps/import_app/forms.py:32 apps/rules/forms.py:60 apps/rules/forms.py:100
|
||||
#: apps/rules/forms.py:385 apps/transactions/forms.py:197
|
||||
#: apps/transactions/forms.py:361 apps/transactions/forms.py:480
|
||||
#: apps/transactions/forms.py:821 apps/transactions/forms.py:860
|
||||
#: apps/transactions/forms.py:888 apps/transactions/forms.py:919
|
||||
#: apps/transactions/forms.py:1065 apps/users/forms.py:222
|
||||
#: apps/users/forms.py:380
|
||||
#: apps/rules/forms.py:385 apps/transactions/forms.py:218
|
||||
#: apps/transactions/forms.py:417 apps/transactions/forms.py:536
|
||||
#: apps/transactions/forms.py:880 apps/transactions/forms.py:919
|
||||
#: apps/transactions/forms.py:947 apps/transactions/forms.py:978
|
||||
#: apps/transactions/forms.py:1128 apps/users/forms.py:242
|
||||
#: apps/users/forms.py:400
|
||||
#: templates/rules/fragments/transaction_rule/dry_run/updated.html:5
|
||||
#: templates/rules/fragments/transaction_rule/view.html:128
|
||||
msgid "Update"
|
||||
@@ -43,11 +43,11 @@ msgstr "Uppdatera"
|
||||
#: apps/currencies/forms.py:93 apps/currencies/forms.py:142
|
||||
#: apps/dca/forms.py:52 apps/dca/forms.py:211 apps/import_app/forms.py:38
|
||||
#: apps/rules/forms.py:66 apps/rules/forms.py:106 apps/rules/forms.py:391
|
||||
#: apps/transactions/forms.py:184 apps/transactions/forms.py:204
|
||||
#: apps/transactions/forms.py:368 apps/transactions/forms.py:827
|
||||
#: apps/transactions/forms.py:866 apps/transactions/forms.py:894
|
||||
#: apps/transactions/forms.py:925 apps/transactions/forms.py:1071
|
||||
#: apps/users/forms.py:228 apps/users/forms.py:386
|
||||
#: apps/transactions/forms.py:205 apps/transactions/forms.py:225
|
||||
#: apps/transactions/forms.py:424 apps/transactions/forms.py:886
|
||||
#: apps/transactions/forms.py:925 apps/transactions/forms.py:953
|
||||
#: apps/transactions/forms.py:984 apps/transactions/forms.py:1134
|
||||
#: apps/users/forms.py:248 apps/users/forms.py:406
|
||||
#: templates/mini_tools/unit_price_calculator.html:168
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
@@ -63,12 +63,12 @@ msgstr ""
|
||||
#: apps/accounts/forms.py:125 apps/dca/forms.py:79 apps/dca/forms.py:86
|
||||
#: apps/insights/forms.py:117 apps/rules/forms.py:181 apps/rules/forms.py:197
|
||||
#: apps/rules/models.py:44 apps/rules/models.py:311
|
||||
#: apps/transactions/forms.py:43 apps/transactions/forms.py:251
|
||||
#: apps/transactions/forms.py:419 apps/transactions/forms.py:516
|
||||
#: apps/transactions/forms.py:523 apps/transactions/forms.py:707
|
||||
#: apps/transactions/forms.py:948 apps/transactions/models.py:322
|
||||
#: apps/transactions/models.py:578 apps/transactions/models.py:778
|
||||
#: apps/transactions/models.py:1026
|
||||
#: apps/transactions/forms.py:61 apps/transactions/forms.py:307
|
||||
#: apps/transactions/forms.py:475 apps/transactions/forms.py:572
|
||||
#: apps/transactions/forms.py:579 apps/transactions/forms.py:763
|
||||
#: apps/transactions/forms.py:1007 apps/transactions/models.py:331
|
||||
#: apps/transactions/models.py:641 apps/transactions/models.py:841
|
||||
#: apps/transactions/models.py:1089
|
||||
#: templates/insights/fragments/category_overview/index.html:86
|
||||
#: templates/insights/fragments/category_overview/index.html:542
|
||||
#: templates/insights/fragments/month_by_month.html:84
|
||||
@@ -80,12 +80,12 @@ msgstr ""
|
||||
#: apps/export_app/forms.py:43 apps/export_app/forms.py:132
|
||||
#: apps/rules/forms.py:184 apps/rules/forms.py:194 apps/rules/models.py:45
|
||||
#: apps/rules/models.py:315 apps/transactions/filters.py:73
|
||||
#: apps/transactions/forms.py:51 apps/transactions/forms.py:259
|
||||
#: apps/transactions/forms.py:427 apps/transactions/forms.py:532
|
||||
#: apps/transactions/forms.py:540 apps/transactions/forms.py:700
|
||||
#: apps/transactions/forms.py:941 apps/transactions/models.py:328
|
||||
#: apps/transactions/models.py:580 apps/transactions/models.py:782
|
||||
#: apps/transactions/models.py:1032 templates/includes/sidebar.html:150
|
||||
#: apps/transactions/forms.py:69 apps/transactions/forms.py:315
|
||||
#: apps/transactions/forms.py:483 apps/transactions/forms.py:588
|
||||
#: apps/transactions/forms.py:596 apps/transactions/forms.py:756
|
||||
#: apps/transactions/forms.py:1000 apps/transactions/models.py:337
|
||||
#: apps/transactions/models.py:643 apps/transactions/models.py:845
|
||||
#: apps/transactions/models.py:1095 templates/includes/sidebar.html:150
|
||||
#: templates/insights/fragments/category_overview/index.html:40
|
||||
#: templates/insights/fragments/month_by_month.html:29
|
||||
#: templates/insights/fragments/month_by_month.html:32
|
||||
@@ -97,8 +97,8 @@ msgstr ""
|
||||
|
||||
#: apps/accounts/models.py:12 apps/accounts/models.py:29 apps/dca/models.py:13
|
||||
#: apps/import_app/models.py:14 apps/rules/models.py:13
|
||||
#: apps/transactions/models.py:214 apps/transactions/models.py:239
|
||||
#: apps/transactions/models.py:263 apps/transactions/models.py:994
|
||||
#: apps/transactions/models.py:223 apps/transactions/models.py:248
|
||||
#: apps/transactions/models.py:272 apps/transactions/models.py:1057
|
||||
#: templates/account_groups/fragments/list.html:22
|
||||
#: templates/accounts/fragments/list.html:22
|
||||
#: templates/categories/fragments/table.html:17
|
||||
@@ -164,11 +164,11 @@ msgstr ""
|
||||
|
||||
#: apps/accounts/models.py:75 apps/rules/forms.py:173 apps/rules/forms.py:187
|
||||
#: apps/rules/models.py:35 apps/rules/models.py:267
|
||||
#: apps/transactions/forms.py:63 apps/transactions/forms.py:271
|
||||
#: apps/transactions/forms.py:386 apps/transactions/forms.py:692
|
||||
#: apps/transactions/forms.py:933 apps/transactions/models.py:294
|
||||
#: apps/transactions/models.py:538 apps/transactions/models.py:760
|
||||
#: apps/transactions/models.py:1000
|
||||
#: apps/transactions/forms.py:81 apps/transactions/forms.py:327
|
||||
#: apps/transactions/forms.py:442 apps/transactions/forms.py:748
|
||||
#: apps/transactions/forms.py:992 apps/transactions/models.py:303
|
||||
#: apps/transactions/models.py:601 apps/transactions/models.py:823
|
||||
#: apps/transactions/models.py:1063
|
||||
#: templates/installment_plans/fragments/table.html:17
|
||||
#: templates/quick_transactions/fragments/list.html:14
|
||||
#: templates/recurring_transactions/fragments/table.html:19
|
||||
@@ -345,7 +345,7 @@ msgid ""
|
||||
"owner.<br/>Public: Shown for all users. Only editable by the owner."
|
||||
msgstr ""
|
||||
|
||||
#: apps/common/forms.py:76 apps/users/forms.py:149
|
||||
#: apps/common/forms.py:76 apps/users/forms.py:169
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
@@ -481,8 +481,8 @@ msgstr ""
|
||||
|
||||
#: apps/currencies/forms.py:66 apps/dca/models.py:158 apps/rules/forms.py:176
|
||||
#: apps/rules/forms.py:190 apps/rules/models.py:38 apps/rules/models.py:279
|
||||
#: apps/transactions/forms.py:67 apps/transactions/forms.py:391
|
||||
#: apps/transactions/forms.py:544 apps/transactions/models.py:304
|
||||
#: apps/transactions/forms.py:85 apps/transactions/forms.py:447
|
||||
#: apps/transactions/forms.py:600 apps/transactions/models.py:313
|
||||
#: templates/dca/fragments/strategy/details.html:49
|
||||
#: templates/exchange_rates/fragments/table.html:10
|
||||
#: templates/exchange_rates_services/fragments/table.html:11
|
||||
@@ -568,8 +568,8 @@ msgid "Service Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/currencies/models.py:118 apps/transactions/filters.py:27
|
||||
#: apps/transactions/models.py:218 apps/transactions/models.py:242
|
||||
#: apps/transactions/models.py:266 templates/categories/fragments/list.html:16
|
||||
#: apps/transactions/models.py:227 apps/transactions/models.py:251
|
||||
#: apps/transactions/models.py:275 templates/categories/fragments/list.html:16
|
||||
#: templates/entities/fragments/list.html:16
|
||||
#: templates/installment_plans/fragments/list.html:16
|
||||
#: templates/recurring_transactions/fragments/list.html:16
|
||||
@@ -697,11 +697,11 @@ msgstr ""
|
||||
msgid "Create transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:64 apps/transactions/forms.py:491
|
||||
#: apps/dca/forms.py:64 apps/transactions/forms.py:547
|
||||
msgid "From Account"
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:70 apps/transactions/forms.py:496
|
||||
#: apps/dca/forms.py:70 apps/transactions/forms.py:552
|
||||
msgid "To Account"
|
||||
msgstr ""
|
||||
|
||||
@@ -726,7 +726,7 @@ msgstr ""
|
||||
msgid "You must provide an account."
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:290 apps/transactions/forms.py:638
|
||||
#: apps/dca/forms.py:290 apps/transactions/forms.py:694
|
||||
msgid "From and To accounts must be different."
|
||||
msgstr ""
|
||||
|
||||
@@ -745,9 +745,9 @@ msgstr ""
|
||||
|
||||
#: apps/dca/models.py:26 apps/dca/models.py:181 apps/rules/forms.py:180
|
||||
#: apps/rules/forms.py:196 apps/rules/models.py:43 apps/rules/models.py:295
|
||||
#: apps/transactions/forms.py:413 apps/transactions/forms.py:560
|
||||
#: apps/transactions/models.py:318 apps/transactions/models.py:587
|
||||
#: apps/transactions/models.py:788 apps/transactions/models.py:1022
|
||||
#: apps/transactions/forms.py:469 apps/transactions/forms.py:616
|
||||
#: apps/transactions/models.py:327 apps/transactions/models.py:650
|
||||
#: apps/transactions/models.py:851 apps/transactions/models.py:1085
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
@@ -810,7 +810,7 @@ msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:31 apps/export_app/forms.py:134
|
||||
#: apps/transactions/models.py:379 templates/includes/sidebar.html:81
|
||||
#: apps/transactions/models.py:388 templates/includes/sidebar.html:81
|
||||
#: templates/includes/sidebar.html:142
|
||||
#: templates/recurring_transactions/fragments/list_transactions.html:5
|
||||
#: templates/recurring_transactions/fragments/table.html:37
|
||||
@@ -831,11 +831,11 @@ msgstr ""
|
||||
#: apps/export_app/forms.py:49 apps/export_app/forms.py:133
|
||||
#: apps/rules/forms.py:185 apps/rules/forms.py:195 apps/rules/models.py:46
|
||||
#: apps/rules/models.py:307 apps/transactions/filters.py:78
|
||||
#: apps/transactions/forms.py:59 apps/transactions/forms.py:267
|
||||
#: apps/transactions/forms.py:435 apps/transactions/forms.py:715
|
||||
#: apps/transactions/forms.py:956 apps/transactions/models.py:277
|
||||
#: apps/transactions/models.py:333 apps/transactions/models.py:583
|
||||
#: apps/transactions/models.py:785 apps/transactions/models.py:1037
|
||||
#: apps/transactions/forms.py:77 apps/transactions/forms.py:323
|
||||
#: apps/transactions/forms.py:491 apps/transactions/forms.py:771
|
||||
#: apps/transactions/forms.py:1015 apps/transactions/models.py:286
|
||||
#: apps/transactions/models.py:342 apps/transactions/models.py:646
|
||||
#: apps/transactions/models.py:848 apps/transactions/models.py:1100
|
||||
#: templates/entities/fragments/list.html:9
|
||||
#: templates/entities/pages/index.html:4 templates/includes/sidebar.html:156
|
||||
#: templates/insights/fragments/category_overview/index.html:54
|
||||
@@ -847,14 +847,14 @@ msgid "Entities"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:55 apps/export_app/forms.py:137
|
||||
#: apps/transactions/models.py:825 templates/includes/sidebar.html:110
|
||||
#: apps/transactions/models.py:888 templates/includes/sidebar.html:110
|
||||
#: templates/recurring_transactions/fragments/list.html:9
|
||||
#: templates/recurring_transactions/pages/index.html:4
|
||||
msgid "Recurring Transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:61 apps/export_app/forms.py:135
|
||||
#: apps/transactions/models.py:601 templates/includes/sidebar.html:104
|
||||
#: apps/transactions/models.py:664 templates/includes/sidebar.html:104
|
||||
#: templates/installment_plans/fragments/list.html:9
|
||||
#: templates/installment_plans/pages/index.html:4
|
||||
msgid "Installment Plans"
|
||||
@@ -907,7 +907,7 @@ msgstr ""
|
||||
msgid "Update or create transaction actions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:181 templates/cotton/transaction/item.html:224
|
||||
#: apps/export_app/forms.py:181 templates/cotton/transaction/item.html:230
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:53
|
||||
#: templates/export_app/fragments/restore.html:5
|
||||
#: templates/export_app/pages/index.html:19
|
||||
@@ -1103,16 +1103,16 @@ msgid "Operator"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:174 apps/rules/forms.py:188 apps/rules/models.py:36
|
||||
#: apps/rules/models.py:271 apps/transactions/forms.py:377
|
||||
#: apps/transactions/models.py:301 apps/transactions/models.py:543
|
||||
#: apps/transactions/models.py:766 apps/transactions/models.py:1007
|
||||
#: apps/rules/models.py:271 apps/transactions/forms.py:433
|
||||
#: apps/transactions/models.py:310 apps/transactions/models.py:606
|
||||
#: apps/transactions/models.py:829 apps/transactions/models.py:1070
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:175 apps/rules/forms.py:189 apps/rules/models.py:37
|
||||
#: apps/rules/models.py:275 apps/transactions/filters.py:22
|
||||
#: apps/transactions/forms.py:381 apps/transactions/models.py:303
|
||||
#: apps/transactions/models.py:1009 templates/cotton/transaction/item.html:20
|
||||
#: apps/transactions/forms.py:437 apps/transactions/models.py:312
|
||||
#: apps/transactions/models.py:1072 templates/cotton/transaction/item.html:20
|
||||
#: templates/cotton/transaction/item.html:31
|
||||
#: templates/transactions/widgets/paid_toggle_button.html:10
|
||||
#: templates/transactions/widgets/unselectable_paid_toggle_button.html:13
|
||||
@@ -1120,17 +1120,17 @@ msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:177 apps/rules/forms.py:191 apps/rules/models.py:39
|
||||
#: apps/rules/models.py:283 apps/transactions/forms.py:71
|
||||
#: apps/transactions/forms.py:397 apps/transactions/forms.py:547
|
||||
#: apps/transactions/forms.py:721 apps/transactions/models.py:305
|
||||
#: apps/transactions/models.py:561 apps/transactions/models.py:790
|
||||
#: apps/rules/models.py:283 apps/transactions/forms.py:89
|
||||
#: apps/transactions/forms.py:453 apps/transactions/forms.py:603
|
||||
#: apps/transactions/forms.py:777 apps/transactions/models.py:314
|
||||
#: apps/transactions/models.py:624 apps/transactions/models.py:853
|
||||
msgid "Reference Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:178 apps/rules/forms.py:192 apps/rules/models.py:41
|
||||
#: apps/rules/models.py:287 apps/transactions/forms.py:404
|
||||
#: apps/transactions/models.py:311 apps/transactions/models.py:771
|
||||
#: apps/transactions/models.py:1015
|
||||
#: apps/rules/models.py:287 apps/transactions/forms.py:460
|
||||
#: apps/transactions/models.py:320 apps/transactions/models.py:834
|
||||
#: apps/transactions/models.py:1078
|
||||
#: templates/insights/fragments/sankey.html:102
|
||||
#: templates/installment_plans/fragments/table.html:18
|
||||
#: templates/quick_transactions/fragments/list.html:15
|
||||
@@ -1140,28 +1140,28 @@ msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:179 apps/rules/forms.py:193 apps/rules/models.py:14
|
||||
#: apps/rules/models.py:42 apps/rules/models.py:291
|
||||
#: apps/transactions/forms.py:408 apps/transactions/forms.py:551
|
||||
#: apps/transactions/models.py:316 apps/transactions/models.py:545
|
||||
#: apps/transactions/models.py:774 apps/transactions/models.py:1020
|
||||
#: apps/transactions/forms.py:464 apps/transactions/forms.py:607
|
||||
#: apps/transactions/models.py:325 apps/transactions/models.py:608
|
||||
#: apps/transactions/models.py:837 apps/transactions/models.py:1083
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:182 apps/rules/forms.py:198 apps/rules/models.py:47
|
||||
#: apps/rules/models.py:299 apps/transactions/models.py:355
|
||||
#: apps/transactions/models.py:1042
|
||||
#: apps/rules/models.py:299 apps/transactions/models.py:364
|
||||
#: apps/transactions/models.py:1105
|
||||
msgid "Internal Note"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:183 apps/rules/forms.py:199 apps/rules/models.py:48
|
||||
#: apps/rules/models.py:303 apps/transactions/models.py:357
|
||||
#: apps/transactions/models.py:1044
|
||||
#: apps/rules/models.py:303 apps/transactions/models.py:366
|
||||
#: apps/transactions/models.py:1107
|
||||
msgid "Internal ID"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:186 apps/rules/forms.py:200 apps/rules/models.py:40
|
||||
#: apps/rules/models.py:319 apps/transactions/forms.py:564
|
||||
#: apps/transactions/models.py:215 apps/transactions/models.py:306
|
||||
#: apps/transactions/models.py:1010
|
||||
#: apps/rules/models.py:319 apps/transactions/forms.py:620
|
||||
#: apps/transactions/models.py:224 apps/transactions/models.py:315
|
||||
#: apps/transactions/models.py:1073
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
@@ -1174,7 +1174,7 @@ msgid "Set Values"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:407 apps/rules/forms.py:442 apps/rules/forms.py:477
|
||||
#: apps/transactions/models.py:378
|
||||
#: apps/transactions/models.py:387 apps/transactions/models.py:544
|
||||
msgid "Transaction"
|
||||
msgstr ""
|
||||
|
||||
@@ -1379,96 +1379,110 @@ msgstr ""
|
||||
msgid "No entity"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:170
|
||||
#: apps/transactions/forms.py:191
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:207
|
||||
#: apps/transactions/forms.py:228
|
||||
msgid "Save and add similar"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:212
|
||||
#: apps/transactions/forms.py:233
|
||||
msgid "Save and add another"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:295 apps/transactions/forms.py:567
|
||||
#: apps/transactions/forms.py:270 templates/cotton/transaction/item.html:158
|
||||
#: templates/transactions/fragments/attachments.html:4
|
||||
msgid "Attachments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:271
|
||||
msgid ""
|
||||
"Files are private and only visible to users with access to this transaction."
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:282
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:351 apps/transactions/forms.py:623
|
||||
msgid "Muted transactions won't be displayed on monthly summaries"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:503
|
||||
#: apps/transactions/forms.py:559
|
||||
msgid "From Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:508
|
||||
#: apps/transactions/forms.py:564
|
||||
msgid "To Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:606
|
||||
#: apps/transactions/forms.py:662
|
||||
#: templates/cotton/ui/quick_transactions_buttons.html:40
|
||||
#: templates/cotton/ui/transactions_fab.html:44
|
||||
msgid "Transfer"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:847
|
||||
#: apps/transactions/forms.py:906
|
||||
msgid "Tag name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:875
|
||||
#: apps/transactions/forms.py:934
|
||||
msgid "Entity name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:903
|
||||
#: apps/transactions/forms.py:962
|
||||
msgid "Category name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:905
|
||||
#: apps/transactions/forms.py:964
|
||||
msgid "Muted categories won't be displayed on monthly summaries"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:1055
|
||||
#: apps/transactions/forms.py:1118
|
||||
msgid "future transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:1081
|
||||
#: apps/transactions/forms.py:1144
|
||||
msgid "End date should be after the start date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:220
|
||||
#: apps/transactions/models.py:229
|
||||
msgid ""
|
||||
"Deactivated categories won't be able to be selected when creating new "
|
||||
"transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:228
|
||||
#: apps/transactions/models.py:237
|
||||
msgid "Transaction Category"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:229
|
||||
#: apps/transactions/models.py:238
|
||||
msgid "Transaction Categories"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:244
|
||||
#: apps/transactions/models.py:253
|
||||
msgid ""
|
||||
"Deactivated tags won't be able to be selected when creating new transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:252 apps/transactions/models.py:253
|
||||
#: apps/transactions/models.py:261 apps/transactions/models.py:262
|
||||
msgid "Transaction Tags"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:268
|
||||
#: apps/transactions/models.py:277
|
||||
msgid ""
|
||||
"Deactivated entities won't be able to be selected when creating new "
|
||||
"transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:276
|
||||
#: apps/transactions/models.py:285
|
||||
#: templates/insights/fragments/month_by_month.html:88
|
||||
#: templates/insights/fragments/year_by_year.html:56
|
||||
msgid "Entity"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:288 apps/transactions/models.py:987
|
||||
#: apps/transactions/models.py:297 apps/transactions/models.py:1050
|
||||
#: templates/calendar_view/fragments/list.html:42
|
||||
#: templates/calendar_view/fragments/list.html:44
|
||||
#: templates/calendar_view/fragments/list.html:52
|
||||
@@ -1480,7 +1494,7 @@ msgstr ""
|
||||
msgid "Income"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:289 apps/transactions/models.py:988
|
||||
#: apps/transactions/models.py:298 apps/transactions/models.py:1051
|
||||
#: templates/calendar_view/fragments/list.html:46
|
||||
#: templates/calendar_view/fragments/list.html:48
|
||||
#: templates/calendar_view/fragments/list.html:56
|
||||
@@ -1491,129 +1505,157 @@ msgstr ""
|
||||
msgid "Expense"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:344 apps/transactions/models.py:600
|
||||
#: apps/transactions/models.py:353 apps/transactions/models.py:663
|
||||
msgid "Installment Plan"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:353 apps/transactions/models.py:824
|
||||
#: apps/transactions/models.py:362 apps/transactions/models.py:887
|
||||
msgid "Recurring Transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:361
|
||||
#: apps/transactions/models.py:370
|
||||
msgid "Deleted"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:366
|
||||
#: apps/transactions/models.py:375
|
||||
msgid "Deleted At"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:480 templates/tags/fragments/table.html:69
|
||||
#: apps/transactions/models.py:489 templates/tags/fragments/table.html:69
|
||||
msgid "No tags"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:482
|
||||
#: apps/transactions/models.py:491
|
||||
msgid "No category"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:484
|
||||
#: apps/transactions/models.py:493
|
||||
msgid "No description"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:532 templates/includes/sidebar.html:57
|
||||
#: apps/transactions/models.py:549
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:551
|
||||
msgid "Original Name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:553
|
||||
msgid "Content Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:555
|
||||
msgid "Size"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:560
|
||||
msgid "Uploaded By"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:565
|
||||
msgid "Transaction Attachment"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:566
|
||||
msgid "Transaction Attachments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:595 templates/includes/sidebar.html:57
|
||||
msgid "Yearly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:533 apps/users/models.py:464
|
||||
#: apps/transactions/models.py:596 apps/users/models.py:464
|
||||
#: templates/includes/sidebar.html:51
|
||||
msgid "Monthly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:534
|
||||
#: apps/transactions/models.py:597
|
||||
msgid "Weekly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:535
|
||||
#: apps/transactions/models.py:598
|
||||
msgid "Daily"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:548
|
||||
#: apps/transactions/models.py:611
|
||||
msgid "Number of Installments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:553
|
||||
#: apps/transactions/models.py:616
|
||||
msgid "Installment Start"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:554
|
||||
#: apps/transactions/models.py:617
|
||||
msgid "The installment number to start counting from"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:559 apps/transactions/models.py:794
|
||||
#: apps/transactions/models.py:622 apps/transactions/models.py:857
|
||||
msgid "Start Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:563 apps/transactions/models.py:795
|
||||
#: apps/transactions/models.py:626 apps/transactions/models.py:858
|
||||
msgid "End Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:568
|
||||
#: apps/transactions/models.py:631
|
||||
msgid "Recurrence"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:571
|
||||
#: apps/transactions/models.py:634
|
||||
msgid "Installment Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:590 apps/transactions/models.py:814
|
||||
#: apps/transactions/models.py:653 apps/transactions/models.py:877
|
||||
msgid "Add description to transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:593 apps/transactions/models.py:817
|
||||
#: apps/transactions/models.py:656 apps/transactions/models.py:880
|
||||
msgid "Add notes to transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:753
|
||||
#: apps/transactions/models.py:816
|
||||
msgid "day(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:754
|
||||
#: apps/transactions/models.py:817
|
||||
msgid "week(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:755
|
||||
#: apps/transactions/models.py:818
|
||||
msgid "month(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:756
|
||||
#: apps/transactions/models.py:819
|
||||
msgid "year(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:758
|
||||
#: apps/transactions/models.py:821
|
||||
#: templates/recurring_transactions/fragments/list.html:18
|
||||
msgid "Paused"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:797
|
||||
#: apps/transactions/models.py:860
|
||||
msgid "Recurrence Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:800
|
||||
#: apps/transactions/models.py:863
|
||||
msgid "Recurrence Interval"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:803
|
||||
#: apps/transactions/models.py:866
|
||||
msgid "Keep at most"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:807
|
||||
#: apps/transactions/models.py:870
|
||||
msgid "Last Generated Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:810
|
||||
#: apps/transactions/models.py:873
|
||||
msgid "Last Generated Reference Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:1054
|
||||
#: apps/transactions/models.py:1117
|
||||
#: apps/transactions/views/quick_transactions.py:178
|
||||
#: apps/transactions/views/quick_transactions.py:187
|
||||
#: apps/transactions/views/quick_transactions.py:189
|
||||
@@ -1622,7 +1664,7 @@ msgstr ""
|
||||
msgid "Quick Transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:1055 templates/includes/sidebar.html:98
|
||||
#: apps/transactions/models.py:1118 templates/includes/sidebar.html:98
|
||||
#: templates/quick_transactions/pages/index.html:5
|
||||
#: templates/quick_transactions/pages/index.html:15
|
||||
msgid "Quick Transactions"
|
||||
@@ -1727,8 +1769,8 @@ msgid "Item deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/quick_transactions.py:156
|
||||
#: apps/transactions/views/transactions.py:53
|
||||
#: apps/transactions/views/transactions.py:238
|
||||
#: apps/transactions/views/transactions.py:141
|
||||
#: apps/transactions/views/transactions.py:326
|
||||
msgid "Transaction added successfully"
|
||||
msgstr ""
|
||||
|
||||
@@ -1768,30 +1810,38 @@ msgstr ""
|
||||
msgid "Tag deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:262
|
||||
#: apps/transactions/views/transactions.py:59
|
||||
msgid "Attachment uploaded successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:110
|
||||
msgid "Attachment deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:350
|
||||
msgid "Transaction updated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:313
|
||||
#: apps/transactions/views/transactions.py:401
|
||||
#, python-format
|
||||
msgid "%(count)s transaction updated successfully"
|
||||
msgid_plural "%(count)s transactions updated successfully"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:349
|
||||
#: apps/transactions/views/transactions.py:437
|
||||
msgid "Transaction duplicated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:391
|
||||
#: apps/transactions/views/transactions.py:479
|
||||
msgid "Transaction deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:409
|
||||
#: apps/transactions/views/transactions.py:497
|
||||
msgid "Transaction restored successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:435
|
||||
#: apps/transactions/views/transactions.py:523
|
||||
msgid "Transfer added successfully"
|
||||
msgstr ""
|
||||
|
||||
@@ -1815,24 +1865,24 @@ msgstr ""
|
||||
msgid "Important dates"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:22 apps/users/forms.py:26 apps/users/models.py:451
|
||||
#: apps/users/forms.py:24 apps/users/forms.py:28 apps/users/models.py:451
|
||||
#: templates/users/login.html:18
|
||||
msgid "E-mail"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:33 apps/users/forms.py:38 templates/users/login.html:19
|
||||
#: apps/users/forms.py:35 apps/users/forms.py:40 templates/users/login.html:19
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:45
|
||||
#: apps/users/forms.py:47
|
||||
msgid "Invalid e-mail or password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:46
|
||||
#: apps/users/forms.py:48
|
||||
msgid "This account is deactivated"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:62 apps/users/forms.py:75 apps/users/forms.py:97
|
||||
#: apps/users/forms.py:64 apps/users/forms.py:77 apps/users/forms.py:99
|
||||
#: templates/monthly_overview/pages/overview.html:98
|
||||
#: templates/monthly_overview/pages/overview.html:245
|
||||
#: templates/transactions/pages/transactions.html:47
|
||||
@@ -1840,19 +1890,23 @@ msgstr ""
|
||||
msgid "Default"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:105 apps/users/models.py:484
|
||||
#: apps/users/forms.py:107 apps/users/models.py:484
|
||||
msgid "Date Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:110 apps/users/models.py:489
|
||||
#: apps/users/forms.py:112 apps/users/models.py:489
|
||||
msgid "Datetime Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:116 apps/users/models.py:492
|
||||
#: apps/users/forms.py:118 apps/users/models.py:492
|
||||
msgid "Number Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:154
|
||||
#: apps/users/forms.py:125
|
||||
msgid "Default Account"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:174
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This changes the language (if available) and how numbers and dates are "
|
||||
@@ -1860,59 +1914,59 @@ msgid ""
|
||||
"Consider helping translate WYGIWYH to your language at %(translation_link)s"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:163
|
||||
#: apps/users/forms.py:183
|
||||
msgid "New Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:166
|
||||
#: apps/users/forms.py:186
|
||||
msgid "Leave blank to keep the current password."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:169
|
||||
#: apps/users/forms.py:189
|
||||
msgid "Confirm New Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:181 apps/users/forms.py:338
|
||||
#: apps/users/forms.py:201 apps/users/forms.py:358
|
||||
msgid ""
|
||||
"Designates whether this user should be treated as active. Unselect this "
|
||||
"instead of deleting accounts."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:184 apps/users/forms.py:341
|
||||
#: apps/users/forms.py:204 apps/users/forms.py:361
|
||||
msgid ""
|
||||
"Designates that this user has all permissions without explicitly assigning "
|
||||
"them."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:251
|
||||
#: apps/users/forms.py:271
|
||||
msgid "This email address is already in use by another account."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:259
|
||||
#: apps/users/forms.py:279
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:261
|
||||
#: apps/users/forms.py:281
|
||||
msgid "Please confirm your new password."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:263
|
||||
#: apps/users/forms.py:283
|
||||
msgid "Please enter the new password first."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:283
|
||||
#: apps/users/forms.py:303
|
||||
msgid "You cannot deactivate your own account using this form."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:296
|
||||
#: apps/users/forms.py:316
|
||||
msgid "Cannot remove status from the last superuser."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:302
|
||||
#: apps/users/forms.py:322
|
||||
msgid "You cannot remove your own superuser status using this form."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:395
|
||||
#: apps/users/forms.py:415
|
||||
msgid "A user with this email address already exists."
|
||||
msgstr ""
|
||||
|
||||
@@ -1956,6 +2010,14 @@ msgstr ""
|
||||
msgid "Start page"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/models.py:516
|
||||
msgid "Default account"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/models.py:517
|
||||
msgid "Selects the account by default when creating new transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/views.py:67
|
||||
msgid "Transaction amounts are now hidden"
|
||||
msgstr ""
|
||||
@@ -2050,8 +2112,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:54
|
||||
#: templates/accounts/fragments/list.html:71
|
||||
#: templates/categories/fragments/table.html:51
|
||||
#: templates/cotton/transaction/item.html:158
|
||||
#: templates/cotton/transaction/item.html:230
|
||||
#: templates/cotton/transaction/item.html:164
|
||||
#: templates/cotton/transaction/item.html:236
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:57
|
||||
#: templates/cotton/ui/transactions_action_bar.html:82
|
||||
#: templates/currencies/fragments/list.html:40
|
||||
@@ -2079,8 +2141,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:58
|
||||
#: templates/accounts/fragments/list.html:75
|
||||
#: templates/categories/fragments/table.html:56
|
||||
#: templates/cotton/transaction/item.html:160
|
||||
#: templates/cotton/transaction/item.html:236
|
||||
#: templates/cotton/transaction/item.html:166
|
||||
#: templates/cotton/transaction/item.html:242
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:58
|
||||
#: templates/cotton/ui/transactions_action_bar.html:83
|
||||
#: templates/currencies/fragments/list.html:44
|
||||
@@ -2109,8 +2171,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:59
|
||||
#: templates/accounts/fragments/list.html:76
|
||||
#: templates/categories/fragments/table.html:57
|
||||
#: templates/cotton/transaction/item.html:161
|
||||
#: templates/cotton/transaction/item.html:237
|
||||
#: templates/cotton/transaction/item.html:167
|
||||
#: templates/cotton/transaction/item.html:243
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:58
|
||||
#: templates/cotton/ui/transactions_action_bar.html:83
|
||||
#: templates/currencies/fragments/list.html:45
|
||||
@@ -2131,8 +2193,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:60
|
||||
#: templates/accounts/fragments/list.html:77
|
||||
#: templates/categories/fragments/table.html:58
|
||||
#: templates/cotton/transaction/item.html:162
|
||||
#: templates/cotton/transaction/item.html:238
|
||||
#: templates/cotton/transaction/item.html:168
|
||||
#: templates/cotton/transaction/item.html:244
|
||||
#: templates/currencies/fragments/list.html:46
|
||||
#: templates/dca/fragments/strategy/details.html:77
|
||||
#: templates/dca/fragments/strategy/list.html:44
|
||||
@@ -2149,6 +2211,7 @@ msgstr ""
|
||||
#: templates/rules/fragments/transaction_rule/view.html:65
|
||||
#: templates/rules/fragments/transaction_rule/view.html:98
|
||||
#: templates/tags/fragments/table.html:57
|
||||
#: templates/transactions/fragments/attachments.html:22
|
||||
msgid "Yes, delete it!"
|
||||
msgstr ""
|
||||
|
||||
@@ -2284,41 +2347,41 @@ msgstr ""
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:175
|
||||
#: templates/cotton/transaction/item.html:186
|
||||
#: templates/cotton/transaction/item.html:196
|
||||
#: templates/cotton/transaction/item.html:181
|
||||
#: templates/cotton/transaction/item.html:192
|
||||
#: templates/cotton/transaction/item.html:202
|
||||
msgid "Show on summaries"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:177
|
||||
#: templates/cotton/transaction/item.html:183
|
||||
msgid "Controlled by account"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:188
|
||||
#: templates/cotton/transaction/item.html:194
|
||||
msgid "Controlled by category"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:201
|
||||
#: templates/cotton/transaction/item.html:207
|
||||
msgid "Hide from summaries"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:205
|
||||
#: templates/cotton/transaction/item.html:211
|
||||
msgid "Add as quick transaction"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:210
|
||||
#: templates/cotton/transaction/item.html:216
|
||||
msgid "Move to previous month"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:214
|
||||
#: templates/cotton/transaction/item.html:220
|
||||
msgid "Move to next month"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:217
|
||||
#: templates/cotton/transaction/item.html:223
|
||||
msgid "Move to today"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:221
|
||||
#: templates/cotton/transaction/item.html:227
|
||||
#: templates/cotton/ui/transactions_action_bar.html:78
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
@@ -2799,6 +2862,10 @@ msgstr ""
|
||||
msgid "Try reloading the page or check the console for more information."
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/hyperscript/htmx_error_handler.html:24
|
||||
msgid "Reload"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/hyperscript/swal.html:13
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
@@ -2807,6 +2874,18 @@ msgstr ""
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:4
|
||||
msgid "Pull down to refresh"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:5
|
||||
msgid "Release to refresh"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:6
|
||||
msgid "Refreshing"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/sidebar.html:69 templates/insights/pages/index.html:5
|
||||
msgid "Insights"
|
||||
msgstr ""
|
||||
@@ -3450,6 +3529,22 @@ msgstr ""
|
||||
msgid "Add Installment Plan"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:20
|
||||
msgid "Delete this attachment?"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:21
|
||||
msgid "This file will be removed from the transaction."
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:30
|
||||
msgid "No attachments yet"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments_manage.html:5
|
||||
msgid "Transaction attachments"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/bulk_edit.html:5
|
||||
msgid "Bulk Editing"
|
||||
msgstr ""
|
||||
|
||||
+276
-177
@@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-10 20:50+0000\n"
|
||||
"POT-Creation-Date: 2026-06-06 07:41+0000\n"
|
||||
"PO-Revision-Date: 2026-01-18 19:24+0000\n"
|
||||
"Last-Translator: Ebrahim Tayabali <ebrahimhakimuddin@gmail.com>\n"
|
||||
"Language-Team: Swahili <https://translations.herculino.com/projects/wygiwyh/"
|
||||
@@ -27,12 +27,12 @@ msgstr "Jina La Kundi"
|
||||
#: apps/currencies/forms.py:53 apps/currencies/forms.py:87
|
||||
#: apps/currencies/forms.py:136 apps/dca/forms.py:46 apps/dca/forms.py:205
|
||||
#: apps/import_app/forms.py:32 apps/rules/forms.py:60 apps/rules/forms.py:100
|
||||
#: apps/rules/forms.py:385 apps/transactions/forms.py:197
|
||||
#: apps/transactions/forms.py:361 apps/transactions/forms.py:480
|
||||
#: apps/transactions/forms.py:821 apps/transactions/forms.py:860
|
||||
#: apps/transactions/forms.py:888 apps/transactions/forms.py:919
|
||||
#: apps/transactions/forms.py:1065 apps/users/forms.py:222
|
||||
#: apps/users/forms.py:380
|
||||
#: apps/rules/forms.py:385 apps/transactions/forms.py:218
|
||||
#: apps/transactions/forms.py:417 apps/transactions/forms.py:536
|
||||
#: apps/transactions/forms.py:880 apps/transactions/forms.py:919
|
||||
#: apps/transactions/forms.py:947 apps/transactions/forms.py:978
|
||||
#: apps/transactions/forms.py:1128 apps/users/forms.py:242
|
||||
#: apps/users/forms.py:400
|
||||
#: templates/rules/fragments/transaction_rule/dry_run/updated.html:5
|
||||
#: templates/rules/fragments/transaction_rule/view.html:128
|
||||
msgid "Update"
|
||||
@@ -43,11 +43,11 @@ msgstr ""
|
||||
#: apps/currencies/forms.py:93 apps/currencies/forms.py:142
|
||||
#: apps/dca/forms.py:52 apps/dca/forms.py:211 apps/import_app/forms.py:38
|
||||
#: apps/rules/forms.py:66 apps/rules/forms.py:106 apps/rules/forms.py:391
|
||||
#: apps/transactions/forms.py:184 apps/transactions/forms.py:204
|
||||
#: apps/transactions/forms.py:368 apps/transactions/forms.py:827
|
||||
#: apps/transactions/forms.py:866 apps/transactions/forms.py:894
|
||||
#: apps/transactions/forms.py:925 apps/transactions/forms.py:1071
|
||||
#: apps/users/forms.py:228 apps/users/forms.py:386
|
||||
#: apps/transactions/forms.py:205 apps/transactions/forms.py:225
|
||||
#: apps/transactions/forms.py:424 apps/transactions/forms.py:886
|
||||
#: apps/transactions/forms.py:925 apps/transactions/forms.py:953
|
||||
#: apps/transactions/forms.py:984 apps/transactions/forms.py:1134
|
||||
#: apps/users/forms.py:248 apps/users/forms.py:406
|
||||
#: templates/mini_tools/unit_price_calculator.html:168
|
||||
#, fuzzy
|
||||
msgid "Add"
|
||||
@@ -64,12 +64,12 @@ msgstr "Salio Mpya"
|
||||
#: apps/accounts/forms.py:125 apps/dca/forms.py:79 apps/dca/forms.py:86
|
||||
#: apps/insights/forms.py:117 apps/rules/forms.py:181 apps/rules/forms.py:197
|
||||
#: apps/rules/models.py:44 apps/rules/models.py:311
|
||||
#: apps/transactions/forms.py:43 apps/transactions/forms.py:251
|
||||
#: apps/transactions/forms.py:419 apps/transactions/forms.py:516
|
||||
#: apps/transactions/forms.py:523 apps/transactions/forms.py:707
|
||||
#: apps/transactions/forms.py:948 apps/transactions/models.py:322
|
||||
#: apps/transactions/models.py:578 apps/transactions/models.py:778
|
||||
#: apps/transactions/models.py:1026
|
||||
#: apps/transactions/forms.py:61 apps/transactions/forms.py:307
|
||||
#: apps/transactions/forms.py:475 apps/transactions/forms.py:572
|
||||
#: apps/transactions/forms.py:579 apps/transactions/forms.py:763
|
||||
#: apps/transactions/forms.py:1007 apps/transactions/models.py:331
|
||||
#: apps/transactions/models.py:641 apps/transactions/models.py:841
|
||||
#: apps/transactions/models.py:1089
|
||||
#: templates/insights/fragments/category_overview/index.html:86
|
||||
#: templates/insights/fragments/category_overview/index.html:542
|
||||
#: templates/insights/fragments/month_by_month.html:84
|
||||
@@ -81,12 +81,12 @@ msgstr ""
|
||||
#: apps/export_app/forms.py:43 apps/export_app/forms.py:132
|
||||
#: apps/rules/forms.py:184 apps/rules/forms.py:194 apps/rules/models.py:45
|
||||
#: apps/rules/models.py:315 apps/transactions/filters.py:73
|
||||
#: apps/transactions/forms.py:51 apps/transactions/forms.py:259
|
||||
#: apps/transactions/forms.py:427 apps/transactions/forms.py:532
|
||||
#: apps/transactions/forms.py:540 apps/transactions/forms.py:700
|
||||
#: apps/transactions/forms.py:941 apps/transactions/models.py:328
|
||||
#: apps/transactions/models.py:580 apps/transactions/models.py:782
|
||||
#: apps/transactions/models.py:1032 templates/includes/sidebar.html:150
|
||||
#: apps/transactions/forms.py:69 apps/transactions/forms.py:315
|
||||
#: apps/transactions/forms.py:483 apps/transactions/forms.py:588
|
||||
#: apps/transactions/forms.py:596 apps/transactions/forms.py:756
|
||||
#: apps/transactions/forms.py:1000 apps/transactions/models.py:337
|
||||
#: apps/transactions/models.py:643 apps/transactions/models.py:845
|
||||
#: apps/transactions/models.py:1095 templates/includes/sidebar.html:150
|
||||
#: templates/insights/fragments/category_overview/index.html:40
|
||||
#: templates/insights/fragments/month_by_month.html:29
|
||||
#: templates/insights/fragments/month_by_month.html:32
|
||||
@@ -98,8 +98,8 @@ msgstr ""
|
||||
|
||||
#: apps/accounts/models.py:12 apps/accounts/models.py:29 apps/dca/models.py:13
|
||||
#: apps/import_app/models.py:14 apps/rules/models.py:13
|
||||
#: apps/transactions/models.py:214 apps/transactions/models.py:239
|
||||
#: apps/transactions/models.py:263 apps/transactions/models.py:994
|
||||
#: apps/transactions/models.py:223 apps/transactions/models.py:248
|
||||
#: apps/transactions/models.py:272 apps/transactions/models.py:1057
|
||||
#: templates/account_groups/fragments/list.html:22
|
||||
#: templates/accounts/fragments/list.html:22
|
||||
#: templates/categories/fragments/table.html:17
|
||||
@@ -168,11 +168,11 @@ msgstr ""
|
||||
|
||||
#: apps/accounts/models.py:75 apps/rules/forms.py:173 apps/rules/forms.py:187
|
||||
#: apps/rules/models.py:35 apps/rules/models.py:267
|
||||
#: apps/transactions/forms.py:63 apps/transactions/forms.py:271
|
||||
#: apps/transactions/forms.py:386 apps/transactions/forms.py:692
|
||||
#: apps/transactions/forms.py:933 apps/transactions/models.py:294
|
||||
#: apps/transactions/models.py:538 apps/transactions/models.py:760
|
||||
#: apps/transactions/models.py:1000
|
||||
#: apps/transactions/forms.py:81 apps/transactions/forms.py:327
|
||||
#: apps/transactions/forms.py:442 apps/transactions/forms.py:748
|
||||
#: apps/transactions/forms.py:992 apps/transactions/models.py:303
|
||||
#: apps/transactions/models.py:601 apps/transactions/models.py:823
|
||||
#: apps/transactions/models.py:1063
|
||||
#: templates/installment_plans/fragments/table.html:17
|
||||
#: templates/quick_transactions/fragments/list.html:14
|
||||
#: templates/recurring_transactions/fragments/table.html:19
|
||||
@@ -349,7 +349,7 @@ msgid ""
|
||||
"owner.<br/>Public: Shown for all users. Only editable by the owner."
|
||||
msgstr ""
|
||||
|
||||
#: apps/common/forms.py:76 apps/users/forms.py:149
|
||||
#: apps/common/forms.py:76 apps/users/forms.py:169
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
@@ -485,8 +485,8 @@ msgstr ""
|
||||
|
||||
#: apps/currencies/forms.py:66 apps/dca/models.py:158 apps/rules/forms.py:176
|
||||
#: apps/rules/forms.py:190 apps/rules/models.py:38 apps/rules/models.py:279
|
||||
#: apps/transactions/forms.py:67 apps/transactions/forms.py:391
|
||||
#: apps/transactions/forms.py:544 apps/transactions/models.py:304
|
||||
#: apps/transactions/forms.py:85 apps/transactions/forms.py:447
|
||||
#: apps/transactions/forms.py:600 apps/transactions/models.py:313
|
||||
#: templates/dca/fragments/strategy/details.html:49
|
||||
#: templates/exchange_rates/fragments/table.html:10
|
||||
#: templates/exchange_rates_services/fragments/table.html:11
|
||||
@@ -572,8 +572,8 @@ msgid "Service Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/currencies/models.py:118 apps/transactions/filters.py:27
|
||||
#: apps/transactions/models.py:218 apps/transactions/models.py:242
|
||||
#: apps/transactions/models.py:266 templates/categories/fragments/list.html:16
|
||||
#: apps/transactions/models.py:227 apps/transactions/models.py:251
|
||||
#: apps/transactions/models.py:275 templates/categories/fragments/list.html:16
|
||||
#: templates/entities/fragments/list.html:16
|
||||
#: templates/installment_plans/fragments/list.html:16
|
||||
#: templates/recurring_transactions/fragments/list.html:16
|
||||
@@ -701,11 +701,11 @@ msgstr ""
|
||||
msgid "Create transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:64 apps/transactions/forms.py:491
|
||||
#: apps/dca/forms.py:64 apps/transactions/forms.py:547
|
||||
msgid "From Account"
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:70 apps/transactions/forms.py:496
|
||||
#: apps/dca/forms.py:70 apps/transactions/forms.py:552
|
||||
msgid "To Account"
|
||||
msgstr ""
|
||||
|
||||
@@ -730,7 +730,7 @@ msgstr ""
|
||||
msgid "You must provide an account."
|
||||
msgstr ""
|
||||
|
||||
#: apps/dca/forms.py:290 apps/transactions/forms.py:638
|
||||
#: apps/dca/forms.py:290 apps/transactions/forms.py:694
|
||||
msgid "From and To accounts must be different."
|
||||
msgstr ""
|
||||
|
||||
@@ -749,9 +749,9 @@ msgstr ""
|
||||
|
||||
#: apps/dca/models.py:26 apps/dca/models.py:181 apps/rules/forms.py:180
|
||||
#: apps/rules/forms.py:196 apps/rules/models.py:43 apps/rules/models.py:295
|
||||
#: apps/transactions/forms.py:413 apps/transactions/forms.py:560
|
||||
#: apps/transactions/models.py:318 apps/transactions/models.py:587
|
||||
#: apps/transactions/models.py:788 apps/transactions/models.py:1022
|
||||
#: apps/transactions/forms.py:469 apps/transactions/forms.py:616
|
||||
#: apps/transactions/models.py:327 apps/transactions/models.py:650
|
||||
#: apps/transactions/models.py:851 apps/transactions/models.py:1085
|
||||
msgid "Notes"
|
||||
msgstr ""
|
||||
|
||||
@@ -814,7 +814,7 @@ msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:31 apps/export_app/forms.py:134
|
||||
#: apps/transactions/models.py:379 templates/includes/sidebar.html:81
|
||||
#: apps/transactions/models.py:388 templates/includes/sidebar.html:81
|
||||
#: templates/includes/sidebar.html:142
|
||||
#: templates/recurring_transactions/fragments/list_transactions.html:5
|
||||
#: templates/recurring_transactions/fragments/table.html:37
|
||||
@@ -835,11 +835,11 @@ msgstr ""
|
||||
#: apps/export_app/forms.py:49 apps/export_app/forms.py:133
|
||||
#: apps/rules/forms.py:185 apps/rules/forms.py:195 apps/rules/models.py:46
|
||||
#: apps/rules/models.py:307 apps/transactions/filters.py:78
|
||||
#: apps/transactions/forms.py:59 apps/transactions/forms.py:267
|
||||
#: apps/transactions/forms.py:435 apps/transactions/forms.py:715
|
||||
#: apps/transactions/forms.py:956 apps/transactions/models.py:277
|
||||
#: apps/transactions/models.py:333 apps/transactions/models.py:583
|
||||
#: apps/transactions/models.py:785 apps/transactions/models.py:1037
|
||||
#: apps/transactions/forms.py:77 apps/transactions/forms.py:323
|
||||
#: apps/transactions/forms.py:491 apps/transactions/forms.py:771
|
||||
#: apps/transactions/forms.py:1015 apps/transactions/models.py:286
|
||||
#: apps/transactions/models.py:342 apps/transactions/models.py:646
|
||||
#: apps/transactions/models.py:848 apps/transactions/models.py:1100
|
||||
#: templates/entities/fragments/list.html:9
|
||||
#: templates/entities/pages/index.html:4 templates/includes/sidebar.html:156
|
||||
#: templates/insights/fragments/category_overview/index.html:54
|
||||
@@ -851,14 +851,14 @@ msgid "Entities"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:55 apps/export_app/forms.py:137
|
||||
#: apps/transactions/models.py:825 templates/includes/sidebar.html:110
|
||||
#: apps/transactions/models.py:888 templates/includes/sidebar.html:110
|
||||
#: templates/recurring_transactions/fragments/list.html:9
|
||||
#: templates/recurring_transactions/pages/index.html:4
|
||||
msgid "Recurring Transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:61 apps/export_app/forms.py:135
|
||||
#: apps/transactions/models.py:601 templates/includes/sidebar.html:104
|
||||
#: apps/transactions/models.py:664 templates/includes/sidebar.html:104
|
||||
#: templates/installment_plans/fragments/list.html:9
|
||||
#: templates/installment_plans/pages/index.html:4
|
||||
msgid "Installment Plans"
|
||||
@@ -911,7 +911,7 @@ msgstr ""
|
||||
msgid "Update or create transaction actions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/export_app/forms.py:181 templates/cotton/transaction/item.html:224
|
||||
#: apps/export_app/forms.py:181 templates/cotton/transaction/item.html:230
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:53
|
||||
#: templates/export_app/fragments/restore.html:5
|
||||
#: templates/export_app/pages/index.html:19
|
||||
@@ -1107,16 +1107,16 @@ msgid "Operator"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:174 apps/rules/forms.py:188 apps/rules/models.py:36
|
||||
#: apps/rules/models.py:271 apps/transactions/forms.py:377
|
||||
#: apps/transactions/models.py:301 apps/transactions/models.py:543
|
||||
#: apps/transactions/models.py:766 apps/transactions/models.py:1007
|
||||
#: apps/rules/models.py:271 apps/transactions/forms.py:433
|
||||
#: apps/transactions/models.py:310 apps/transactions/models.py:606
|
||||
#: apps/transactions/models.py:829 apps/transactions/models.py:1070
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:175 apps/rules/forms.py:189 apps/rules/models.py:37
|
||||
#: apps/rules/models.py:275 apps/transactions/filters.py:22
|
||||
#: apps/transactions/forms.py:381 apps/transactions/models.py:303
|
||||
#: apps/transactions/models.py:1009 templates/cotton/transaction/item.html:20
|
||||
#: apps/transactions/forms.py:437 apps/transactions/models.py:312
|
||||
#: apps/transactions/models.py:1072 templates/cotton/transaction/item.html:20
|
||||
#: templates/cotton/transaction/item.html:31
|
||||
#: templates/transactions/widgets/paid_toggle_button.html:10
|
||||
#: templates/transactions/widgets/unselectable_paid_toggle_button.html:13
|
||||
@@ -1124,17 +1124,17 @@ msgid "Paid"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:177 apps/rules/forms.py:191 apps/rules/models.py:39
|
||||
#: apps/rules/models.py:283 apps/transactions/forms.py:71
|
||||
#: apps/transactions/forms.py:397 apps/transactions/forms.py:547
|
||||
#: apps/transactions/forms.py:721 apps/transactions/models.py:305
|
||||
#: apps/transactions/models.py:561 apps/transactions/models.py:790
|
||||
#: apps/rules/models.py:283 apps/transactions/forms.py:89
|
||||
#: apps/transactions/forms.py:453 apps/transactions/forms.py:603
|
||||
#: apps/transactions/forms.py:777 apps/transactions/models.py:314
|
||||
#: apps/transactions/models.py:624 apps/transactions/models.py:853
|
||||
msgid "Reference Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:178 apps/rules/forms.py:192 apps/rules/models.py:41
|
||||
#: apps/rules/models.py:287 apps/transactions/forms.py:404
|
||||
#: apps/transactions/models.py:311 apps/transactions/models.py:771
|
||||
#: apps/transactions/models.py:1015
|
||||
#: apps/rules/models.py:287 apps/transactions/forms.py:460
|
||||
#: apps/transactions/models.py:320 apps/transactions/models.py:834
|
||||
#: apps/transactions/models.py:1078
|
||||
#: templates/insights/fragments/sankey.html:102
|
||||
#: templates/installment_plans/fragments/table.html:18
|
||||
#: templates/quick_transactions/fragments/list.html:15
|
||||
@@ -1144,28 +1144,28 @@ msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:179 apps/rules/forms.py:193 apps/rules/models.py:14
|
||||
#: apps/rules/models.py:42 apps/rules/models.py:291
|
||||
#: apps/transactions/forms.py:408 apps/transactions/forms.py:551
|
||||
#: apps/transactions/models.py:316 apps/transactions/models.py:545
|
||||
#: apps/transactions/models.py:774 apps/transactions/models.py:1020
|
||||
#: apps/transactions/forms.py:464 apps/transactions/forms.py:607
|
||||
#: apps/transactions/models.py:325 apps/transactions/models.py:608
|
||||
#: apps/transactions/models.py:837 apps/transactions/models.py:1083
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:182 apps/rules/forms.py:198 apps/rules/models.py:47
|
||||
#: apps/rules/models.py:299 apps/transactions/models.py:355
|
||||
#: apps/transactions/models.py:1042
|
||||
#: apps/rules/models.py:299 apps/transactions/models.py:364
|
||||
#: apps/transactions/models.py:1105
|
||||
msgid "Internal Note"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:183 apps/rules/forms.py:199 apps/rules/models.py:48
|
||||
#: apps/rules/models.py:303 apps/transactions/models.py:357
|
||||
#: apps/transactions/models.py:1044
|
||||
#: apps/rules/models.py:303 apps/transactions/models.py:366
|
||||
#: apps/transactions/models.py:1107
|
||||
msgid "Internal ID"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:186 apps/rules/forms.py:200 apps/rules/models.py:40
|
||||
#: apps/rules/models.py:319 apps/transactions/forms.py:564
|
||||
#: apps/transactions/models.py:215 apps/transactions/models.py:306
|
||||
#: apps/transactions/models.py:1010
|
||||
#: apps/rules/models.py:319 apps/transactions/forms.py:620
|
||||
#: apps/transactions/models.py:224 apps/transactions/models.py:315
|
||||
#: apps/transactions/models.py:1073
|
||||
msgid "Mute"
|
||||
msgstr ""
|
||||
|
||||
@@ -1178,7 +1178,7 @@ msgid "Set Values"
|
||||
msgstr ""
|
||||
|
||||
#: apps/rules/forms.py:407 apps/rules/forms.py:442 apps/rules/forms.py:477
|
||||
#: apps/transactions/models.py:378
|
||||
#: apps/transactions/models.py:387 apps/transactions/models.py:544
|
||||
msgid "Transaction"
|
||||
msgstr ""
|
||||
|
||||
@@ -1383,96 +1383,110 @@ msgstr ""
|
||||
msgid "No entity"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:170
|
||||
#: apps/transactions/forms.py:191
|
||||
msgid "More"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:207
|
||||
#: apps/transactions/forms.py:228
|
||||
msgid "Save and add similar"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:212
|
||||
#: apps/transactions/forms.py:233
|
||||
msgid "Save and add another"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:295 apps/transactions/forms.py:567
|
||||
#: apps/transactions/forms.py:270 templates/cotton/transaction/item.html:158
|
||||
#: templates/transactions/fragments/attachments.html:4
|
||||
msgid "Attachments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:271
|
||||
msgid ""
|
||||
"Files are private and only visible to users with access to this transaction."
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:282
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:351 apps/transactions/forms.py:623
|
||||
msgid "Muted transactions won't be displayed on monthly summaries"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:503
|
||||
#: apps/transactions/forms.py:559
|
||||
msgid "From Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:508
|
||||
#: apps/transactions/forms.py:564
|
||||
msgid "To Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:606
|
||||
#: apps/transactions/forms.py:662
|
||||
#: templates/cotton/ui/quick_transactions_buttons.html:40
|
||||
#: templates/cotton/ui/transactions_fab.html:44
|
||||
msgid "Transfer"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:847
|
||||
#: apps/transactions/forms.py:906
|
||||
msgid "Tag name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:875
|
||||
#: apps/transactions/forms.py:934
|
||||
msgid "Entity name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:903
|
||||
#: apps/transactions/forms.py:962
|
||||
msgid "Category name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:905
|
||||
#: apps/transactions/forms.py:964
|
||||
msgid "Muted categories won't be displayed on monthly summaries"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:1055
|
||||
#: apps/transactions/forms.py:1118
|
||||
msgid "future transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/forms.py:1081
|
||||
#: apps/transactions/forms.py:1144
|
||||
msgid "End date should be after the start date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:220
|
||||
#: apps/transactions/models.py:229
|
||||
msgid ""
|
||||
"Deactivated categories won't be able to be selected when creating new "
|
||||
"transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:228
|
||||
#: apps/transactions/models.py:237
|
||||
msgid "Transaction Category"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:229
|
||||
#: apps/transactions/models.py:238
|
||||
msgid "Transaction Categories"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:244
|
||||
#: apps/transactions/models.py:253
|
||||
msgid ""
|
||||
"Deactivated tags won't be able to be selected when creating new transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:252 apps/transactions/models.py:253
|
||||
#: apps/transactions/models.py:261 apps/transactions/models.py:262
|
||||
msgid "Transaction Tags"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:268
|
||||
#: apps/transactions/models.py:277
|
||||
msgid ""
|
||||
"Deactivated entities won't be able to be selected when creating new "
|
||||
"transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:276
|
||||
#: apps/transactions/models.py:285
|
||||
#: templates/insights/fragments/month_by_month.html:88
|
||||
#: templates/insights/fragments/year_by_year.html:56
|
||||
msgid "Entity"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:288 apps/transactions/models.py:987
|
||||
#: apps/transactions/models.py:297 apps/transactions/models.py:1050
|
||||
#: templates/calendar_view/fragments/list.html:42
|
||||
#: templates/calendar_view/fragments/list.html:44
|
||||
#: templates/calendar_view/fragments/list.html:52
|
||||
@@ -1484,7 +1498,7 @@ msgstr ""
|
||||
msgid "Income"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:289 apps/transactions/models.py:988
|
||||
#: apps/transactions/models.py:298 apps/transactions/models.py:1051
|
||||
#: templates/calendar_view/fragments/list.html:46
|
||||
#: templates/calendar_view/fragments/list.html:48
|
||||
#: templates/calendar_view/fragments/list.html:56
|
||||
@@ -1495,129 +1509,157 @@ msgstr ""
|
||||
msgid "Expense"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:344 apps/transactions/models.py:600
|
||||
#: apps/transactions/models.py:353 apps/transactions/models.py:663
|
||||
msgid "Installment Plan"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:353 apps/transactions/models.py:824
|
||||
#: apps/transactions/models.py:362 apps/transactions/models.py:887
|
||||
msgid "Recurring Transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:361
|
||||
#: apps/transactions/models.py:370
|
||||
msgid "Deleted"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:366
|
||||
#: apps/transactions/models.py:375
|
||||
msgid "Deleted At"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:480 templates/tags/fragments/table.html:69
|
||||
#: apps/transactions/models.py:489 templates/tags/fragments/table.html:69
|
||||
msgid "No tags"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:482
|
||||
#: apps/transactions/models.py:491
|
||||
msgid "No category"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:484
|
||||
#: apps/transactions/models.py:493
|
||||
msgid "No description"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:532 templates/includes/sidebar.html:57
|
||||
#: apps/transactions/models.py:549
|
||||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:551
|
||||
msgid "Original Name"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:553
|
||||
msgid "Content Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:555
|
||||
msgid "Size"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:560
|
||||
msgid "Uploaded By"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:565
|
||||
msgid "Transaction Attachment"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:566
|
||||
msgid "Transaction Attachments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:595 templates/includes/sidebar.html:57
|
||||
msgid "Yearly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:533 apps/users/models.py:464
|
||||
#: apps/transactions/models.py:596 apps/users/models.py:464
|
||||
#: templates/includes/sidebar.html:51
|
||||
msgid "Monthly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:534
|
||||
#: apps/transactions/models.py:597
|
||||
msgid "Weekly"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:535
|
||||
#: apps/transactions/models.py:598
|
||||
msgid "Daily"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:548
|
||||
#: apps/transactions/models.py:611
|
||||
msgid "Number of Installments"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:553
|
||||
#: apps/transactions/models.py:616
|
||||
msgid "Installment Start"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:554
|
||||
#: apps/transactions/models.py:617
|
||||
msgid "The installment number to start counting from"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:559 apps/transactions/models.py:794
|
||||
#: apps/transactions/models.py:622 apps/transactions/models.py:857
|
||||
msgid "Start Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:563 apps/transactions/models.py:795
|
||||
#: apps/transactions/models.py:626 apps/transactions/models.py:858
|
||||
msgid "End Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:568
|
||||
#: apps/transactions/models.py:631
|
||||
msgid "Recurrence"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:571
|
||||
#: apps/transactions/models.py:634
|
||||
msgid "Installment Amount"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:590 apps/transactions/models.py:814
|
||||
#: apps/transactions/models.py:653 apps/transactions/models.py:877
|
||||
msgid "Add description to transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:593 apps/transactions/models.py:817
|
||||
#: apps/transactions/models.py:656 apps/transactions/models.py:880
|
||||
msgid "Add notes to transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:753
|
||||
#: apps/transactions/models.py:816
|
||||
msgid "day(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:754
|
||||
#: apps/transactions/models.py:817
|
||||
msgid "week(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:755
|
||||
#: apps/transactions/models.py:818
|
||||
msgid "month(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:756
|
||||
#: apps/transactions/models.py:819
|
||||
msgid "year(s)"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:758
|
||||
#: apps/transactions/models.py:821
|
||||
#: templates/recurring_transactions/fragments/list.html:18
|
||||
msgid "Paused"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:797
|
||||
#: apps/transactions/models.py:860
|
||||
msgid "Recurrence Type"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:800
|
||||
#: apps/transactions/models.py:863
|
||||
msgid "Recurrence Interval"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:803
|
||||
#: apps/transactions/models.py:866
|
||||
msgid "Keep at most"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:807
|
||||
#: apps/transactions/models.py:870
|
||||
msgid "Last Generated Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:810
|
||||
#: apps/transactions/models.py:873
|
||||
msgid "Last Generated Reference Date"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:1054
|
||||
#: apps/transactions/models.py:1117
|
||||
#: apps/transactions/views/quick_transactions.py:178
|
||||
#: apps/transactions/views/quick_transactions.py:187
|
||||
#: apps/transactions/views/quick_transactions.py:189
|
||||
@@ -1626,7 +1668,7 @@ msgstr ""
|
||||
msgid "Quick Transaction"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/models.py:1055 templates/includes/sidebar.html:98
|
||||
#: apps/transactions/models.py:1118 templates/includes/sidebar.html:98
|
||||
#: templates/quick_transactions/pages/index.html:5
|
||||
#: templates/quick_transactions/pages/index.html:15
|
||||
msgid "Quick Transactions"
|
||||
@@ -1731,8 +1773,8 @@ msgid "Item deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/quick_transactions.py:156
|
||||
#: apps/transactions/views/transactions.py:53
|
||||
#: apps/transactions/views/transactions.py:238
|
||||
#: apps/transactions/views/transactions.py:141
|
||||
#: apps/transactions/views/transactions.py:326
|
||||
msgid "Transaction added successfully"
|
||||
msgstr ""
|
||||
|
||||
@@ -1772,30 +1814,38 @@ msgstr ""
|
||||
msgid "Tag deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:262
|
||||
#: apps/transactions/views/transactions.py:59
|
||||
msgid "Attachment uploaded successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:110
|
||||
msgid "Attachment deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:350
|
||||
msgid "Transaction updated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:313
|
||||
#: apps/transactions/views/transactions.py:401
|
||||
#, python-format
|
||||
msgid "%(count)s transaction updated successfully"
|
||||
msgid_plural "%(count)s transactions updated successfully"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:349
|
||||
#: apps/transactions/views/transactions.py:437
|
||||
msgid "Transaction duplicated successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:391
|
||||
#: apps/transactions/views/transactions.py:479
|
||||
msgid "Transaction deleted successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:409
|
||||
#: apps/transactions/views/transactions.py:497
|
||||
msgid "Transaction restored successfully"
|
||||
msgstr ""
|
||||
|
||||
#: apps/transactions/views/transactions.py:435
|
||||
#: apps/transactions/views/transactions.py:523
|
||||
msgid "Transfer added successfully"
|
||||
msgstr ""
|
||||
|
||||
@@ -1819,24 +1869,24 @@ msgstr ""
|
||||
msgid "Important dates"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:22 apps/users/forms.py:26 apps/users/models.py:451
|
||||
#: apps/users/forms.py:24 apps/users/forms.py:28 apps/users/models.py:451
|
||||
#: templates/users/login.html:18
|
||||
msgid "E-mail"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:33 apps/users/forms.py:38 templates/users/login.html:19
|
||||
#: apps/users/forms.py:35 apps/users/forms.py:40 templates/users/login.html:19
|
||||
msgid "Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:45
|
||||
#: apps/users/forms.py:47
|
||||
msgid "Invalid e-mail or password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:46
|
||||
#: apps/users/forms.py:48
|
||||
msgid "This account is deactivated"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:62 apps/users/forms.py:75 apps/users/forms.py:97
|
||||
#: apps/users/forms.py:64 apps/users/forms.py:77 apps/users/forms.py:99
|
||||
#: templates/monthly_overview/pages/overview.html:98
|
||||
#: templates/monthly_overview/pages/overview.html:245
|
||||
#: templates/transactions/pages/transactions.html:47
|
||||
@@ -1844,19 +1894,25 @@ msgstr ""
|
||||
msgid "Default"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:105 apps/users/models.py:484
|
||||
#: apps/users/forms.py:107 apps/users/models.py:484
|
||||
msgid "Date Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:110 apps/users/models.py:489
|
||||
#: apps/users/forms.py:112 apps/users/models.py:489
|
||||
msgid "Datetime Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:116 apps/users/models.py:492
|
||||
#: apps/users/forms.py:118 apps/users/models.py:492
|
||||
msgid "Number Format"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:154
|
||||
#: apps/users/forms.py:125
|
||||
#, fuzzy
|
||||
#| msgid "Asset account"
|
||||
msgid "Default Account"
|
||||
msgstr "Akaunti ya Mali"
|
||||
|
||||
#: apps/users/forms.py:174
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This changes the language (if available) and how numbers and dates are "
|
||||
@@ -1864,59 +1920,59 @@ msgid ""
|
||||
"Consider helping translate WYGIWYH to your language at %(translation_link)s"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:163
|
||||
#: apps/users/forms.py:183
|
||||
msgid "New Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:166
|
||||
#: apps/users/forms.py:186
|
||||
msgid "Leave blank to keep the current password."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:169
|
||||
#: apps/users/forms.py:189
|
||||
msgid "Confirm New Password"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:181 apps/users/forms.py:338
|
||||
#: apps/users/forms.py:201 apps/users/forms.py:358
|
||||
msgid ""
|
||||
"Designates whether this user should be treated as active. Unselect this "
|
||||
"instead of deleting accounts."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:184 apps/users/forms.py:341
|
||||
#: apps/users/forms.py:204 apps/users/forms.py:361
|
||||
msgid ""
|
||||
"Designates that this user has all permissions without explicitly assigning "
|
||||
"them."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:251
|
||||
#: apps/users/forms.py:271
|
||||
msgid "This email address is already in use by another account."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:259
|
||||
#: apps/users/forms.py:279
|
||||
msgid "The two password fields didn't match."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:261
|
||||
#: apps/users/forms.py:281
|
||||
msgid "Please confirm your new password."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:263
|
||||
#: apps/users/forms.py:283
|
||||
msgid "Please enter the new password first."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:283
|
||||
#: apps/users/forms.py:303
|
||||
msgid "You cannot deactivate your own account using this form."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:296
|
||||
#: apps/users/forms.py:316
|
||||
msgid "Cannot remove status from the last superuser."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:302
|
||||
#: apps/users/forms.py:322
|
||||
msgid "You cannot remove your own superuser status using this form."
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/forms.py:395
|
||||
#: apps/users/forms.py:415
|
||||
msgid "A user with this email address already exists."
|
||||
msgstr ""
|
||||
|
||||
@@ -1960,6 +2016,16 @@ msgstr ""
|
||||
msgid "Start page"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/models.py:516
|
||||
#, fuzzy
|
||||
#| msgid "Asset account"
|
||||
msgid "Default account"
|
||||
msgstr "Akaunti ya Mali"
|
||||
|
||||
#: apps/users/models.py:517
|
||||
msgid "Selects the account by default when creating new transactions"
|
||||
msgstr ""
|
||||
|
||||
#: apps/users/views.py:67
|
||||
msgid "Transaction amounts are now hidden"
|
||||
msgstr ""
|
||||
@@ -2054,8 +2120,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:54
|
||||
#: templates/accounts/fragments/list.html:71
|
||||
#: templates/categories/fragments/table.html:51
|
||||
#: templates/cotton/transaction/item.html:158
|
||||
#: templates/cotton/transaction/item.html:230
|
||||
#: templates/cotton/transaction/item.html:164
|
||||
#: templates/cotton/transaction/item.html:236
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:57
|
||||
#: templates/cotton/ui/transactions_action_bar.html:82
|
||||
#: templates/currencies/fragments/list.html:40
|
||||
@@ -2083,8 +2149,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:58
|
||||
#: templates/accounts/fragments/list.html:75
|
||||
#: templates/categories/fragments/table.html:56
|
||||
#: templates/cotton/transaction/item.html:160
|
||||
#: templates/cotton/transaction/item.html:236
|
||||
#: templates/cotton/transaction/item.html:166
|
||||
#: templates/cotton/transaction/item.html:242
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:58
|
||||
#: templates/cotton/ui/transactions_action_bar.html:83
|
||||
#: templates/currencies/fragments/list.html:44
|
||||
@@ -2113,8 +2179,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:59
|
||||
#: templates/accounts/fragments/list.html:76
|
||||
#: templates/categories/fragments/table.html:57
|
||||
#: templates/cotton/transaction/item.html:161
|
||||
#: templates/cotton/transaction/item.html:237
|
||||
#: templates/cotton/transaction/item.html:167
|
||||
#: templates/cotton/transaction/item.html:243
|
||||
#: templates/cotton/ui/deleted_transactions_action_bar.html:58
|
||||
#: templates/cotton/ui/transactions_action_bar.html:83
|
||||
#: templates/currencies/fragments/list.html:45
|
||||
@@ -2135,8 +2201,8 @@ msgstr ""
|
||||
#: templates/account_groups/fragments/list.html:60
|
||||
#: templates/accounts/fragments/list.html:77
|
||||
#: templates/categories/fragments/table.html:58
|
||||
#: templates/cotton/transaction/item.html:162
|
||||
#: templates/cotton/transaction/item.html:238
|
||||
#: templates/cotton/transaction/item.html:168
|
||||
#: templates/cotton/transaction/item.html:244
|
||||
#: templates/currencies/fragments/list.html:46
|
||||
#: templates/dca/fragments/strategy/details.html:77
|
||||
#: templates/dca/fragments/strategy/list.html:44
|
||||
@@ -2153,6 +2219,7 @@ msgstr ""
|
||||
#: templates/rules/fragments/transaction_rule/view.html:65
|
||||
#: templates/rules/fragments/transaction_rule/view.html:98
|
||||
#: templates/tags/fragments/table.html:57
|
||||
#: templates/transactions/fragments/attachments.html:22
|
||||
msgid "Yes, delete it!"
|
||||
msgstr ""
|
||||
|
||||
@@ -2288,41 +2355,41 @@ msgstr ""
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:175
|
||||
#: templates/cotton/transaction/item.html:186
|
||||
#: templates/cotton/transaction/item.html:196
|
||||
#: templates/cotton/transaction/item.html:181
|
||||
#: templates/cotton/transaction/item.html:192
|
||||
#: templates/cotton/transaction/item.html:202
|
||||
msgid "Show on summaries"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:177
|
||||
#: templates/cotton/transaction/item.html:183
|
||||
msgid "Controlled by account"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:188
|
||||
#: templates/cotton/transaction/item.html:194
|
||||
msgid "Controlled by category"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:201
|
||||
#: templates/cotton/transaction/item.html:207
|
||||
msgid "Hide from summaries"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:205
|
||||
#: templates/cotton/transaction/item.html:211
|
||||
msgid "Add as quick transaction"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:210
|
||||
#: templates/cotton/transaction/item.html:216
|
||||
msgid "Move to previous month"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:214
|
||||
#: templates/cotton/transaction/item.html:220
|
||||
msgid "Move to next month"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:217
|
||||
#: templates/cotton/transaction/item.html:223
|
||||
msgid "Move to today"
|
||||
msgstr ""
|
||||
|
||||
#: templates/cotton/transaction/item.html:221
|
||||
#: templates/cotton/transaction/item.html:227
|
||||
#: templates/cotton/ui/transactions_action_bar.html:78
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
@@ -2803,6 +2870,10 @@ msgstr ""
|
||||
msgid "Try reloading the page or check the console for more information."
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/hyperscript/htmx_error_handler.html:24
|
||||
msgid "Reload"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/hyperscript/swal.html:13
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
@@ -2811,6 +2882,18 @@ msgstr ""
|
||||
msgid "Confirm"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:4
|
||||
msgid "Pull down to refresh"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:5
|
||||
msgid "Release to refresh"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/scripts/pull_to_refresh_i18n.html:6
|
||||
msgid "Refreshing"
|
||||
msgstr ""
|
||||
|
||||
#: templates/includes/sidebar.html:69 templates/insights/pages/index.html:5
|
||||
msgid "Insights"
|
||||
msgstr ""
|
||||
@@ -3454,6 +3537,22 @@ msgstr ""
|
||||
msgid "Add Installment Plan"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:20
|
||||
msgid "Delete this attachment?"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:21
|
||||
msgid "This file will be removed from the transaction."
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments.html:30
|
||||
msgid "No attachments yet"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/attachments_manage.html:5
|
||||
msgid "Transaction attachments"
|
||||
msgstr ""
|
||||
|
||||
#: templates/transactions/fragments/bulk_edit.html:5
|
||||
msgid "Bulk Editing"
|
||||
msgstr ""
|
||||
|
||||
+289
-177
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -147,6 +147,12 @@
|
||||
hx-target="#generic-offcanvas" hx-swap="innerHTML"
|
||||
data-tippy-content="{% translate "Edit" %}">
|
||||
<i class="fa-solid fa-pencil fa-fw"></i></a>
|
||||
<a class="btn btn-soft btn-sm transaction-action gap-1"
|
||||
role="button"
|
||||
hx-get="{% url 'transaction_attachments' transaction_id=transaction.id %}"
|
||||
hx-target="#generic-offcanvas" hx-swap="innerHTML"
|
||||
data-tippy-content="{% translate "Attachments" %}">
|
||||
<i class="fa-solid fa-paperclip fa-fw"></i><span>{{ transaction.attachments.count }}</span></a>
|
||||
<a class="btn btn-error btn-soft btn-sm transaction-action"
|
||||
role="button"
|
||||
hx-delete="{% url 'transaction_delete' transaction_id=transaction.id %}"
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
{% include 'includes/scripts/hyperscript/sounds.html' %}
|
||||
{% include 'includes/scripts/hyperscript/swal.html' %}
|
||||
{% include 'includes/scripts/hyperscript/autosize.html' %}
|
||||
{% include 'includes/scripts/pull_to_refresh_i18n.html' %}
|
||||
|
||||
<script defer>
|
||||
let tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
var tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
||||
if (!tz) {
|
||||
tz = "UTC"
|
||||
}
|
||||
|
||||
@@ -20,11 +20,16 @@ behavior htmx_error_handler
|
||||
text: '{% trans "Try reloading the page or check the console for more information." %}',
|
||||
icon: 'error',
|
||||
timer: 60000,
|
||||
showDenyButton: true,
|
||||
denyButtonText: '{% trans "Reload" %}',
|
||||
customClass: {
|
||||
confirmButton: 'btn btn-primary'
|
||||
confirmButton: 'btn btn-primary',
|
||||
denyButton: 'btn btn-error',
|
||||
actions: 'gap-2'
|
||||
},
|
||||
buttonsStyling: false
|
||||
})
|
||||
buttonsStyling: false,
|
||||
reverseButtons: true
|
||||
}) then if it.isDenied call location.reload()
|
||||
end
|
||||
then log event
|
||||
then halt the event
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{% load i18n %}
|
||||
<span id="ptr-i18n"
|
||||
class="hidden"
|
||||
data-pull="{% translate 'Pull down to refresh' %}"
|
||||
data-release="{% translate 'Release to refresh' %}"
|
||||
data-refreshing="{% translate 'Refreshing' %}"></span>
|
||||
@@ -268,7 +268,7 @@
|
||||
</div>
|
||||
|
||||
{# Filter transactions form #}
|
||||
<div class="z-1" x-show="filterOpen" x-collapse>
|
||||
<div class="z-1" x-show="filterOpen" x-collapse x-cloak>
|
||||
<div class="card card-body bg-base-200 mt-2">
|
||||
<div class="text-right">
|
||||
<button class="btn btn-outline btn-error btn-sm w-fit"
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
{% load i18n %}
|
||||
|
||||
<div id="transaction-attachments-list" class="mt-4">
|
||||
<h3 class="font-semibold mb-2">{% translate 'Attachments' %}</h3>
|
||||
{% if transaction.attachments.exists %}
|
||||
<ul class="flex flex-col gap-2">
|
||||
{% for attachment in transaction.attachments.all %}
|
||||
<li class="flex items-center justify-between gap-3 rounded-box border border-base-content/20 p-3">
|
||||
<a class="link link-primary truncate"
|
||||
target="_blank"
|
||||
href="{% url 'transaction_attachment_download' attachment_id=attachment.id %}">
|
||||
{{ attachment.original_name }}
|
||||
</a>
|
||||
<button class="btn btn-error btn-sm btn-soft"
|
||||
type="button"
|
||||
hx-delete="{% url 'transaction_attachment_delete' attachment_id=attachment.id %}"
|
||||
hx-trigger="confirmed"
|
||||
hx-target="#transaction-attachments-list"
|
||||
hx-swap="outerHTML"
|
||||
data-title="{% translate 'Delete this attachment?' %}"
|
||||
data-text="{% translate 'This file will be removed from the transaction.' %}"
|
||||
data-confirm-text="{% translate 'Yes, delete it!' %}"
|
||||
_="install prompt_swal">
|
||||
<i class="fa-solid fa-trash fa-fw"></i>
|
||||
</button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<p class="text-base-content/60">{% translate 'No attachments yet' %}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -0,0 +1,17 @@
|
||||
{% extends 'extends/offcanvas.html' %}
|
||||
{% load i18n %}
|
||||
{% load crispy_forms_tags %}
|
||||
|
||||
{% block title %}{% translate 'Transaction attachments' %}{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<form hx-post="{% url 'transaction_attachments' transaction_id=transaction.id %}"
|
||||
hx-target="#generic-offcanvas"
|
||||
hx-swap="innerHTML"
|
||||
enctype="multipart/form-data"
|
||||
novalidate>
|
||||
{% crispy form %}
|
||||
</form>
|
||||
|
||||
{% include 'transactions/fragments/attachments.html' %}
|
||||
{% endblock %}
|
||||
@@ -218,7 +218,7 @@
|
||||
</div>
|
||||
|
||||
{# Filter transactions form #}
|
||||
<div class="z-1" x-show="filterOpen" x-collapse>
|
||||
<div class="z-1" x-show="filterOpen" x-collapse x-cloak>
|
||||
<div class="card card-body bg-base-200 mt-2">
|
||||
<div class="text-right">
|
||||
<button class="btn btn-outline btn-error btn-sm w-fit"
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
volumes:
|
||||
wygiwyh_dev_postgres_data: {}
|
||||
wygiwyh_temp:
|
||||
wygiwyh_attachments:
|
||||
|
||||
|
||||
services:
|
||||
@@ -14,6 +15,7 @@ services:
|
||||
- ./app/:/usr/src/app/:z
|
||||
- ./frontend/:/usr/src/frontend:z
|
||||
- wygiwyh_temp:/usr/src/app/temp/
|
||||
- wygiwyh_attachments:/usr/src/app/attachments/
|
||||
ports:
|
||||
- "${OUTBOUND_PORT:-8000}:${INTERNAL_PORT:-8000}"
|
||||
env_file:
|
||||
|
||||
@@ -6,6 +6,8 @@ services:
|
||||
- "${OUTBOUND_PORT:-8000}:${INTERNAL_PORT:-8000}"
|
||||
env_file:
|
||||
- .env
|
||||
volumes:
|
||||
- ./media:/usr/src/app/attachments/
|
||||
depends_on:
|
||||
- db
|
||||
restart: unless-stopped
|
||||
|
||||
@@ -2,9 +2,9 @@ FROM node:lts-alpine
|
||||
|
||||
WORKDIR /usr/src/frontend
|
||||
|
||||
COPY ./frontend/package.json .
|
||||
COPY ./frontend/package.json ./frontend/package-lock.json ./
|
||||
|
||||
RUN npm install --verbose && npm cache clean --force
|
||||
RUN npm ci --verbose && npm cache clean --force
|
||||
|
||||
ENV PATH ./node_modules/.bin/:$PATH
|
||||
|
||||
|
||||
Generated
+802
-735
File diff suppressed because it is too large
Load Diff
+21
-20
@@ -16,34 +16,35 @@
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@alpinejs/collapse": "^3.15.1",
|
||||
"@alpinejs/mask": "^3.15.1",
|
||||
"@alpinejs/collapse": "^3.15.12",
|
||||
"@alpinejs/mask": "^3.15.12",
|
||||
"@fontsource-variable/jetbrains-mono": "^5.2.8",
|
||||
"@fortawesome/fontawesome-free": "^7.1.0",
|
||||
"@fortawesome/fontawesome-free": "^7.2.0",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@rollup/plugin-commonjs": "^29.0.0",
|
||||
"@tailwindcss/vite": "^4.1.17",
|
||||
"@rollup/plugin-commonjs": "^29.0.3",
|
||||
"@tailwindcss/vite": "^4.3.0",
|
||||
"air-datepicker": "^3.6.0",
|
||||
"alpinejs": "^3.15.1",
|
||||
"autoprefixer": "^10.4.22",
|
||||
"alpinejs": "^3.15.12",
|
||||
"autoprefixer": "^10.5.0",
|
||||
"autosize": "^6.0.1",
|
||||
"bootstrap": "^5.3.8",
|
||||
"chart.js": "^4.5.1",
|
||||
"chartjs-chart-sankey": "^0.14.0",
|
||||
"daisyui": "^5.5.5",
|
||||
"htmx.org": "^2.0.8",
|
||||
"hyperscript.org": "^0.9.14",
|
||||
"mathjs": "^15.1.0",
|
||||
"postcss": "^8.5.6",
|
||||
"sass": "^1.94.0",
|
||||
"sweetalert2": "^11.26.3",
|
||||
"tailwindcss": "^4.1.17",
|
||||
"chartjs-chart-sankey": "^0.14.3",
|
||||
"daisyui": "5.5.20",
|
||||
"htmx.org": "^2.0.10",
|
||||
"hyperscript.org": "^0.9.91",
|
||||
"mathjs": "^15.2.0",
|
||||
"postcss": "^8.5.15",
|
||||
"pulltorefreshjs": "^0.1.22",
|
||||
"sass": "^1.100.0",
|
||||
"sweetalert2": "^11.26.25",
|
||||
"tailwindcss": "^4.3.0",
|
||||
"tippy.js": "^6.3.7",
|
||||
"tom-select": "^2.4.3",
|
||||
"tw-bootstrap-grid": "^1.3.2",
|
||||
"vite": "7.2.2"
|
||||
"tom-select": "^2.6.1",
|
||||
"tw-bootstrap-grid": "^1.4.0",
|
||||
"vite": "7.3.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"rollup": "npm:@rollup/wasm-node"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import _hyperscript from 'hyperscript.org/dist/_hyperscript.min';
|
||||
import 'hyperscript.org';
|
||||
import './_htmx.js';
|
||||
import Alpine from "alpinejs";
|
||||
import mask from '@alpinejs/mask';
|
||||
@@ -6,7 +6,6 @@ import collapse from '@alpinejs/collapse'
|
||||
import { create, all } from 'mathjs';
|
||||
|
||||
window.Alpine = Alpine;
|
||||
window._hyperscript = _hyperscript;
|
||||
window.math = create(all, {
|
||||
number: 'BigNumber',
|
||||
});
|
||||
@@ -15,8 +14,6 @@ Alpine.plugin(mask);
|
||||
Alpine.plugin(collapse);
|
||||
Alpine.start();
|
||||
|
||||
_hyperscript.browserInit();
|
||||
|
||||
const successAudio = new Audio("/static/sounds/success.mp3");
|
||||
const popAudio = new Audio("/static/sounds/pop.mp3");
|
||||
window.paidSound = successAudio;
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
import PullToRefresh from 'pulltorefreshjs';
|
||||
|
||||
const isOverlayOpen = () => !!document.querySelector('.offcanvas.show, .swal2-container');
|
||||
|
||||
const isIosPwa = () => {
|
||||
const ua = window.navigator.userAgent.toLowerCase();
|
||||
const isIos = /iphone|ipad|ipod/.test(ua) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1);
|
||||
const isStandalone = window.navigator.standalone === true || window.matchMedia('(display-mode: standalone)').matches;
|
||||
return isIos && isStandalone;
|
||||
};
|
||||
|
||||
const ptrMarkup = `
|
||||
<div class="__PREFIX__box">
|
||||
<div class="__PREFIX__content">
|
||||
<div class="__PREFIX__icon"></div>
|
||||
<div class="__PREFIX__text"></div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const ptrStyles = `
|
||||
.__PREFIX__ptr {
|
||||
box-shadow: inset 0 -3px 5px rgba(0, 0, 0, 0.12);
|
||||
pointer-events: none;
|
||||
font-size: 0.85em;
|
||||
font-weight: bold;
|
||||
top: 0;
|
||||
height: 0;
|
||||
transition: height 0.3s, min-height 0.3s;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
align-content: stretch;
|
||||
}
|
||||
|
||||
.__PREFIX__box {
|
||||
padding: 10px;
|
||||
flex-basis: 100%;
|
||||
}
|
||||
|
||||
.__PREFIX__pull {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.__PREFIX__text {
|
||||
margin-top: .33em;
|
||||
color: var(--color-base-content);
|
||||
}
|
||||
|
||||
.__PREFIX__icon {
|
||||
color: var(--color-base-content);
|
||||
transition: transform .3s;
|
||||
}
|
||||
|
||||
/*
|
||||
When at the top of the page, disable vertical overscroll so passive touch
|
||||
listeners can take over.
|
||||
*/
|
||||
.__PREFIX__top {
|
||||
touch-action: pan-x pan-down pinch-zoom;
|
||||
}
|
||||
|
||||
.__PREFIX__release .__PREFIX__icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
`;
|
||||
|
||||
const getPtrStrings = () => {
|
||||
const ptrStringsEl = document.querySelector('#ptr-i18n');
|
||||
return {
|
||||
pull: ptrStringsEl?.dataset.pull,
|
||||
release: ptrStringsEl?.dataset.release,
|
||||
refreshing: ptrStringsEl?.dataset.refreshing
|
||||
};
|
||||
};
|
||||
|
||||
const initPullToRefresh = () => {
|
||||
const ptrStrings = getPtrStrings();
|
||||
|
||||
PullToRefresh.destroyAll();
|
||||
let ptr = PullToRefresh.init({
|
||||
mainElement: 'body',
|
||||
triggerElement: '#content',
|
||||
getMarkup() {
|
||||
return ptrMarkup;
|
||||
},
|
||||
getStyles() {
|
||||
return ptrStyles;
|
||||
},
|
||||
instructionsPullToRefresh: ptrStrings.pull || 'Pull down to refresh',
|
||||
instructionsReleaseToRefresh: ptrStrings.release || 'Release to refresh',
|
||||
instructionsRefreshing: ptrStrings.refreshing || 'Refreshing',
|
||||
shouldPullToRefresh() {
|
||||
return isIosPwa() && !isOverlayOpen() && window.scrollY === 0;
|
||||
},
|
||||
onRefresh() {
|
||||
window.location.reload();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if (isIosPwa()) {
|
||||
initPullToRefresh();
|
||||
|
||||
document.body.addEventListener('htmx:afterSwap', (event) => {
|
||||
if (event.detail.target === document.body) {
|
||||
initPullToRefresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -4,6 +4,15 @@ import '../styles/_tom-select.scss'
|
||||
|
||||
|
||||
window.TomSelect = function createDynamicTomSelect(element) {
|
||||
const schedulePopperUpdate = function (instance) {
|
||||
// Wait for TomSelect DOM updates before recalculating dropdown position.
|
||||
requestAnimationFrame(() => {
|
||||
if (instance.popper) {
|
||||
instance.popper.update();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Basic configuration
|
||||
const config = {
|
||||
plugins: {},
|
||||
@@ -27,10 +36,16 @@ window.TomSelect = function createDynamicTomSelect(element) {
|
||||
this.popper = Popper.createPopper(this.control, this.dropdown, {
|
||||
placement: "bottom-start",
|
||||
modifiers: [
|
||||
{
|
||||
name: "offset",
|
||||
options: {
|
||||
offset: [0, 4],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sameWidth",
|
||||
enabled: true,
|
||||
fn: ({state}) => {
|
||||
fn: ({ state }) => {
|
||||
state.styles.popper.width = `${state.rects.reference.width}px`;
|
||||
},
|
||||
phase: "beforeWrite",
|
||||
@@ -48,8 +63,17 @@ window.TomSelect = function createDynamicTomSelect(element) {
|
||||
|
||||
},
|
||||
onDropdownOpen: function () {
|
||||
this.popper.update();
|
||||
}
|
||||
schedulePopperUpdate(this);
|
||||
},
|
||||
onItemAdd: function () {
|
||||
schedulePopperUpdate(this);
|
||||
},
|
||||
onItemRemove: function () {
|
||||
schedulePopperUpdate(this);
|
||||
},
|
||||
onClear: function () {
|
||||
schedulePopperUpdate(this);
|
||||
},
|
||||
};
|
||||
|
||||
if (element.dataset.checkboxes === 'true') {
|
||||
|
||||
@@ -10,3 +10,4 @@ import './js/sweetalert2.js';
|
||||
import './js/style.js';
|
||||
import './js/_utils.js';
|
||||
import './js/hide_amounts.js';
|
||||
import './js/pulltorefresh.js';
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import twBootstrapGrid from "tw-bootstrap-grid";
|
||||
|
||||
export default twBootstrapGrid;
|
||||
@@ -49,6 +49,10 @@ div:where(.swal2-container) {
|
||||
z-index: 1101 !important;
|
||||
}
|
||||
|
||||
#toasts .toast-container {
|
||||
z-index: 1100;
|
||||
}
|
||||
|
||||
.logo {
|
||||
/* Set the background-color to DaisyUI CSS variable */
|
||||
background-color: var(--color-primary);
|
||||
@@ -77,4 +81,4 @@ div:where(.swal2-container) {
|
||||
|
||||
[x-cloak] {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
themes: wygiwyh_dark --default, wygiwyh_light;
|
||||
logs: true;
|
||||
}
|
||||
@plugin "tw-bootstrap-grid";
|
||||
@plugin "../plugins/tw-bootstrap-grid-plugin.js";
|
||||
|
||||
@plugin "daisyui/theme" {
|
||||
name: "wygiwyh_light";
|
||||
|
||||
@@ -51,10 +51,44 @@ export default defineConfig({
|
||||
manifest: 'manifest.json',
|
||||
emptyOutDir: true,
|
||||
target: 'es2017',
|
||||
chunkSizeWarningLimit: 800,
|
||||
rollupOptions: {
|
||||
input: rollupInputs,
|
||||
output: {
|
||||
chunkFileNames: undefined,
|
||||
manualChunks(id) {
|
||||
if (!id.includes('node_modules')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (id.includes('/chart.js/') || id.includes('/chartjs-chart-sankey/')) {
|
||||
return 'vendor-chart';
|
||||
}
|
||||
|
||||
if (id.includes('/mathjs/')) {
|
||||
return 'vendor-math';
|
||||
}
|
||||
|
||||
if (
|
||||
id.includes('/alpinejs/') ||
|
||||
id.includes('/@alpinejs/') ||
|
||||
id.includes('/htmx.org/') ||
|
||||
id.includes('/hyperscript.org/')
|
||||
) {
|
||||
return 'vendor-interaction';
|
||||
}
|
||||
|
||||
if (
|
||||
id.includes('/bootstrap/') ||
|
||||
id.includes('/@popperjs/') ||
|
||||
id.includes('/sweetalert2/') ||
|
||||
id.includes('/tippy.js/') ||
|
||||
id.includes('/tom-select/') ||
|
||||
id.includes('/air-datepicker/')
|
||||
) {
|
||||
return 'vendor-ui';
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+18
-18
@@ -5,34 +5,34 @@ description = "An opinionated and powerful finance tracker."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
"crispy-bootstrap5==2025.6",
|
||||
"django~=5.2.9",
|
||||
"django-allauth[socialaccount]~=65.13.1",
|
||||
"crispy-bootstrap5==2026.3",
|
||||
"django~=5.2.15",
|
||||
"django-allauth[socialaccount]~=65.18.0",
|
||||
"django-browser-reload==1.21.0",
|
||||
"django-cachalot~=2.8.0",
|
||||
"django-cotton<2.3.0",
|
||||
"django-crispy-forms==2.5",
|
||||
"django-debug-toolbar==6.1.0",
|
||||
"django-cachalot~=2.9.0",
|
||||
"django-cotton~=2.7.2",
|
||||
"django-crispy-forms==2.6",
|
||||
"django-debug-toolbar==6.3.0",
|
||||
"django-filter==25.2",
|
||||
"django-hijack==3.7.4",
|
||||
"django-import-export~=4.3.9",
|
||||
"django-hijack==3.7.8",
|
||||
"django-import-export~=4.4.1",
|
||||
"django-pwa~=2.0.1",
|
||||
"django-vite==3.1.0",
|
||||
"djangorestframework~=3.16.0",
|
||||
"djangorestframework~=3.17.1",
|
||||
"drf-spectacular~=0.29.0",
|
||||
"gunicorn==23.0.0",
|
||||
"mistune~=3.1.3",
|
||||
"gunicorn==26.0.0",
|
||||
"mistune~=3.2.1",
|
||||
"openpyxl~=3.1.5",
|
||||
"procrastinate[django]~=3.5.3",
|
||||
"psycopg[binary,pool]==3.2.9",
|
||||
"pydantic~=2.12.3",
|
||||
"procrastinate[django]~=3.8.1",
|
||||
"psycopg[binary,pool]==3.3.4",
|
||||
"pydantic~=2.13.4",
|
||||
"python-dateutil~=2.9.0.post0",
|
||||
"pytz>=2025.2",
|
||||
"pyyaml~=6.0.2",
|
||||
"requests~=2.32.5",
|
||||
"requests~=2.34.2",
|
||||
"simpleeval~=1.0.3",
|
||||
"watchfiles==1.1.1",
|
||||
"whitenoise[brotli]==6.11.0",
|
||||
"watchfiles==1.2.0",
|
||||
"whitenoise[brotli]==6.12.0",
|
||||
"xlrd~=2.0.1",
|
||||
]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user