feat: export (WIP)

This commit is contained in:
Herculino Trotta
2025-02-19 08:51:33 -03:00
parent 3080df9b66
commit 069f1b450c
7 changed files with 268 additions and 4 deletions

View File

@@ -0,0 +1,80 @@
from crispy_forms.bootstrap import FormActions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout
from django import forms
from django.utils.translation import gettext_lazy as _
from apps.common.widgets.crispy.submit import NoClassSubmit
class ExportForm(forms.Form):
accounts = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(),
label=_("Accounts"),
initial=True,
)
currencies = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(),
label=_("Currencies"),
initial=True,
)
transactions = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(),
label=_("Transactions"),
initial=True,
)
categories = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(),
label=_("Categories"),
initial=True,
)
tags = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(),
label=_("Tags"),
initial=False,
)
entities = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(),
label=_("Entities"),
initial=False,
)
exchange_rates = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(),
label=_("Exchange Rates"),
initial=False,
)
exchange_rates_services = forms.BooleanField(
required=False,
widget=forms.CheckboxInput(),
label=_("Automatic Exchange Rates"),
initial=False,
)
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(
"accounts",
"currencies",
"transactions",
"categories",
"entities",
"tags",
"exchange_rates_services",
"exchange_rates",
FormActions(
NoClassSubmit(
"submit", _("Export"), css_class="btn btn-outline-primary w-100"
),
),
)

View File

@@ -0,0 +1,25 @@
from import_export import fields, resources, widgets
from apps.accounts.models import Account
from apps.export_app.widgets.foreign_key import AutoCreateForeignKeyWidget
class AccountResource(resources.ModelResource):
group = fields.Field(
attribute="group",
column_name="group",
widget=AutoCreateForeignKeyWidget("accounts.AccountGroup", "name"),
)
currency = fields.Field(
attribute="currency",
column_name="currency",
widget=widgets.ForeignKeyWidget("currencies.Currency", "name"),
)
exchange_currency = fields.Field(
attribute="exchange_currency",
column_name="exchange_currency",
widget=widgets.ForeignKeyWidget("currencies.Currency", "name"),
)
class Meta:
model = Account

View File

@@ -0,0 +1,46 @@
from import_export import fields, resources, widgets
from apps.currencies.models import Currency, ExchangeRate, ExchangeRateService
class CurrencyResource(resources.ModelResource):
exchange_currency = fields.Field(
attribute="exchange_currency",
column_name="exchange_currency",
widget=widgets.ForeignKeyWidget("currencies.Currency", "name"),
)
class Meta:
model = Currency
class ExchangeRateResource(resources.ModelResource):
from_currency = fields.Field(
attribute="from_currency",
column_name="from_currency",
widget=widgets.ForeignKeyWidget("currencies.Currency", "name"),
)
to_currency = fields.Field(
attribute="to_currency",
column_name="to_currency",
widget=widgets.ForeignKeyWidget("currencies.Currency", "name"),
)
class Meta:
model = ExchangeRate
class ExchangeRateServiceResource(resources.ModelResource):
target_currencies = fields.Field(
attribute="target_currencies",
column_name="target_currencies",
widget=widgets.ManyToManyWidget("currencies.Currency", field="name"),
)
target_accounts = fields.Field(
attribute="target_accounts",
column_name="target_accounts",
widget=widgets.ForeignKeyWidget("accounts.Account", field="name"),
)
class Meta:
model = ExchangeRateService

View File

@@ -1,4 +1,5 @@
from import_export import fields, resources
from import_export.widgets import ForeignKeyWidget
from apps.export_app.widgets.foreign_key import AutoCreateForeignKeyWidget
from apps.export_app.widgets.many_to_many import AutoCreateManyToManyWidget
@@ -14,7 +15,7 @@ class TransactionResource(resources.ModelResource):
account = fields.Field(
attribute="account",
column_name="account",
widget=AutoCreateForeignKeyWidget("accounts.Account", "name"),
widget=ForeignKeyWidget("accounts.Account", "name"),
)
category = fields.Field(
@@ -37,3 +38,18 @@ class TransactionResource(resources.ModelResource):
class Meta:
model = Transaction
class TransactionTagResource(resources.ModelResource):
class Meta:
model = TransactionTag
class TransactionEntityResource(resources.ModelResource):
class Meta:
model = TransactionEntity
class TransactionCategoyResource(resources.ModelResource):
class Meta:
model = TransactionCategory

View File

@@ -2,5 +2,6 @@ from django.urls import path
import apps.export_app.views as views
urlpatterns = [
path("export/", views.export, name="export"),
path("export/", views.export_index, name="export_index"),
path("export/export/", views.export_form, name="export_form"),
]

View File

@@ -1,9 +1,92 @@
import zipfile
from io import BytesIO
from django.http import HttpResponse
from django.shortcuts import render
from apps.export_app.resources.transactions import TransactionResource
from apps.export_app.forms import ExportForm
from apps.export_app.resources.accounts import AccountResource
from apps.export_app.resources.transactions import (
TransactionResource,
TransactionTagResource,
TransactionEntityResource,
TransactionCategoyResource,
)
from apps.export_app.resources.currencies import (
CurrencyResource,
ExchangeRateResource,
ExchangeRateServiceResource,
)
# Create your views here.
def export(request):
def export_index(request):
dataset = TransactionResource().export()
print(dataset.csv)
def export_form(request):
if request.method == "POST":
form = ExportForm(request.POST)
if form.is_valid():
zip_buffer = BytesIO()
export_accounts = form.cleaned_data.get("accounts", False)
export_currencies = form.cleaned_data.get("currencies", False)
export_transactions = form.cleaned_data.get("transactions", False)
export_categories = form.cleaned_data.get("categories", False)
export_tags = form.cleaned_data.get("tags", False)
export_entities = form.cleaned_data.get("entities", False)
export_exchange_rates_services = form.cleaned_data.get(
"exchange_rates_services", False
)
export_exchange_rates = form.cleaned_data.get("exchange_rates", False)
exports = []
if export_accounts:
exports.append((AccountResource().export(), "accounts"))
if export_currencies:
exports.append((CurrencyResource().export(), "currencies"))
if export_transactions:
exports.append((TransactionResource().export(), "transactions"))
if export_tags:
exports.append((TransactionTagResource().export(), "transactions_tags"))
if export_entities:
exports.append(
(TransactionEntityResource().export(), "transactions_entities")
)
if export_categories:
exports.append(
(TransactionCategoyResource().export(), "transactions_categories")
)
if export_exchange_rates_services:
exports.append(
(ExchangeRateServiceResource().export(), "automatic_exchange_rates")
)
if export_exchange_rates:
exports.append((ExchangeRateResource().export(), "exchange_rates"))
if len(exports) >= 2:
with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
for dataset, name in exports:
zip_file.writestr(f"{name}.csv", dataset.csv)
response = HttpResponse(
zip_buffer.getvalue(), content_type="application/zip"
)
response["Content-Disposition"] = f'attachment; filename="export.zip"'
return response
else:
dataset, name = exports[0]
response = HttpResponse(
dataset.csv,
content_type="text/csv",
)
response["Content-Disposition"] = f'attachment; filename="{name}.csv"'
return response
else:
form = ExportForm()
return render(request, "export_app/pages/form.html", context={"form": form})

View File

@@ -0,0 +1,13 @@
{% extends "layouts/base.html" %}
{% load crispy_forms_tags %}
{% load i18n %}
{% block title %}{% translate 'Import Profiles' %}{% endblock %}
{% block content %}
<div class="container p-3">
<form method="post" action="{% url 'export_form' %}" id="export-form">
{% crispy form %}
</form>
</div>
{% endblock %}