feat: replace action row with a FAB

This commit is contained in:
Herculino Trotta
2025-06-15 23:12:22 -03:00
parent 02f6bb0c29
commit 1d3dc3f5a2
9 changed files with 1358 additions and 501 deletions

View File

@@ -11,33 +11,60 @@ from django.utils import timezone
from apps.accounts.models import Account, AccountGroup
from apps.currencies.models import Currency
from apps.transactions.models import Transaction, TransactionCategory, TransactionTag, TransactionEntity
from apps.export_app.resources.transactions import TransactionResource, TransactionTagResource
from apps.transactions.models import (
Transaction,
TransactionCategory,
TransactionTag,
TransactionEntity,
)
from apps.export_app.resources.transactions import (
TransactionResource,
TransactionTagResource,
)
from apps.export_app.resources.accounts import AccountResource
from apps.export_app.forms import ExportForm, RestoreForm # Added RestoreForm
from apps.export_app.forms import ExportForm, RestoreForm # Added RestoreForm
User = get_user_model()
class BaseExportAppTest(TestCase):
@classmethod
def setUpTestData(cls):
cls.superuser = User.objects.create_superuser(
email="exportadmin@example.com", password="password"
)
cls.currency_usd = Currency.objects.create(code="USD", name="US Dollar", decimal_places=2)
cls.currency_eur = Currency.objects.create(code="EUR", name="Euro", decimal_places=2)
cls.currency_usd = Currency.objects.create(
code="USD", name="US Dollar", decimal_places=2
)
cls.currency_eur = Currency.objects.create(
code="EUR", name="Euro", decimal_places=2
)
cls.user_group = AccountGroup.objects.create(name="User Group", owner=cls.superuser)
cls.user_group = AccountGroup.objects.create(
name="User Group", owner=cls.superuser
)
cls.account_usd = Account.objects.create(
name="Checking USD", currency=cls.currency_usd, owner=cls.superuser, group=cls.user_group
name="Checking USD",
currency=cls.currency_usd,
owner=cls.superuser,
group=cls.user_group,
)
cls.account_eur = Account.objects.create(
name="Savings EUR", currency=cls.currency_eur, owner=cls.superuser, group=cls.user_group
name="Savings EUR",
currency=cls.currency_eur,
owner=cls.superuser,
group=cls.user_group,
)
cls.category_food = TransactionCategory.objects.create(name="Food", owner=cls.superuser)
cls.tag_urgent = TransactionTag.objects.create(name="Urgent", owner=cls.superuser)
cls.entity_store = TransactionEntity.objects.create(name="SuperStore", owner=cls.superuser)
cls.category_food = TransactionCategory.objects.create(
name="Food", owner=cls.superuser
)
cls.tag_urgent = TransactionTag.objects.create(
name="Urgent", owner=cls.superuser
)
cls.entity_store = TransactionEntity.objects.create(
name="SuperStore", owner=cls.superuser
)
cls.transaction1 = Transaction.objects.create(
account=cls.account_usd,
@@ -48,7 +75,7 @@ class BaseExportAppTest(TestCase):
amount=Decimal("50.00"),
description="Groceries",
category=cls.category_food,
is_paid=True
is_paid=True,
)
cls.transaction1.tags.add(cls.tag_urgent)
cls.transaction1.entities.add(cls.entity_store)
@@ -61,7 +88,7 @@ class BaseExportAppTest(TestCase):
reference_date=date(2023, 1, 1),
amount=Decimal("1200.00"),
description="Salary",
is_paid=True
is_paid=True,
)
def setUp(self):
@@ -72,7 +99,9 @@ class BaseExportAppTest(TestCase):
class ResourceExportTests(BaseExportAppTest):
def test_transaction_resource_export(self):
resource = TransactionResource()
queryset = Transaction.objects.filter(owner=self.superuser).order_by('pk') # Ensure consistent order
queryset = Transaction.objects.filter(owner=self.superuser).order_by(
"pk"
) # Ensure consistent order
dataset = resource.export(queryset=queryset)
self.assertEqual(len(dataset), 2)
@@ -90,14 +119,17 @@ class ResourceExportTests(BaseExportAppTest):
self.assertEqual(exported_row1_dict["description"], "Groceries")
self.assertEqual(exported_row1_dict["category"], self.category_food.name)
# M2M fields order might vary, so check for presence
self.assertIn(self.tag_urgent.name, exported_row1_dict["tags"].split(','))
self.assertIn(self.entity_store.name, exported_row1_dict["entities"].split(','))
self.assertEqual(Decimal(exported_row1_dict["amount"]), self.transaction1.amount)
self.assertIn(self.tag_urgent.name, exported_row1_dict["tags"].split(","))
self.assertIn(self.entity_store.name, exported_row1_dict["entities"].split(","))
self.assertEqual(
Decimal(exported_row1_dict["amount"]), self.transaction1.amount
)
def test_account_resource_export(self):
resource = AccountResource()
queryset = Account.objects.filter(owner=self.superuser).order_by('name') # Ensure consistent order
queryset = Account.objects.filter(owner=self.superuser).order_by(
"name"
) # Ensure consistent order
dataset = resource.export(queryset=queryset)
self.assertEqual(len(dataset), 2)
@@ -125,9 +157,13 @@ class ExportViewTests(BaseExportAppTest):
self.assertEqual(response.status_code, 200)
self.assertEqual(response["Content-Type"], "text/csv")
self.assertTrue(response["Content-Disposition"].endswith("_WYGIWYH_export_transactions.csv\""))
self.assertTrue(
response["Content-Disposition"].endswith(
'_WYGIWYH_export_transactions.csv"'
)
)
content = response.content.decode('utf-8')
content = response.content.decode("utf-8")
reader = csv.reader(io.StringIO(content))
headers = next(reader)
self.assertIn("id", headers)
@@ -136,7 +172,6 @@ class ExportViewTests(BaseExportAppTest):
self.assertIn(self.transaction1.description, content)
self.assertIn(self.transaction2.description, content)
def test_export_multiple_to_zip(self):
data = {
"transactions": "on",
@@ -146,7 +181,9 @@ class ExportViewTests(BaseExportAppTest):
self.assertEqual(response.status_code, 200)
self.assertEqual(response["Content-Type"], "application/zip")
self.assertTrue(response["Content-Disposition"].endswith("_WYGIWYH_export.zip\""))
self.assertTrue(
response["Content-Disposition"].endswith('_WYGIWYH_export.zip"')
)
zip_buffer = io.BytesIO(response.content)
with zipfile.ZipFile(zip_buffer, "r") as zf:
@@ -155,19 +192,22 @@ class ExportViewTests(BaseExportAppTest):
self.assertIn("accounts.csv", filenames)
with zf.open("transactions.csv") as csv_file:
content = csv_file.read().decode('utf-8')
content = csv_file.read().decode("utf-8")
self.assertIn("id,type,date", content)
self.assertIn(self.transaction1.description, content)
def test_export_no_selection(self):
data = {}
response = self.client.post(reverse("export_form"), data)
self.assertEqual(response.status_code, 200)
self.assertIn("You have to select at least one export", response.content.decode())
self.assertIn(
"You have to select at least one export", response.content.decode()
)
def test_export_access_non_superuser(self):
normal_user = User.objects.create_user(email="normal@example.com", password="password")
normal_user = User.objects.create_user(
email="normal@example.com", password="password"
)
self.client.logout()
self.client.login(email="normal@example.com", password="password")
@@ -201,4 +241,3 @@ class RestoreViewTests(BaseExportAppTest):
# mock_process_imports.assert_called_once()
# # Further checks on how mock_process_imports was called could be added here.
pass
```