refactor: move some fields and widgets around

This commit is contained in:
Herculino Trotta
2024-10-10 22:37:10 -03:00
parent d2cd115751
commit 5b66ac7fac
8 changed files with 110 additions and 69 deletions

View File

@@ -14,7 +14,7 @@ from apps.common.fields.forms.dynamic_select import (
from apps.common.widgets.crispy.submit import NoClassSubmit
from apps.common.widgets.tom_select import TomSelect
from apps.transactions.models import TransactionCategory, TransactionTag
from apps.transactions.widgets import ArbitraryDecimalDisplayNumberInput
from apps.common.widgets.decimal import ArbitraryDecimalDisplayNumberInput
class AccountGroupForm(forms.ModelForm):

View File

@@ -4,10 +4,10 @@ from django import forms
from django.db import models
from django.core.exceptions import ValidationError
from apps.transactions.widgets import MonthYearWidget
from apps.common.widgets.month_year import MonthYearWidget
class MonthYearField(models.DateField):
class MonthYearModelField(models.DateField):
def to_python(self, value):
if value is None or isinstance(value, datetime.date):
return value
@@ -27,6 +27,8 @@ class MonthYearField(models.DateField):
class MonthYearFormField(forms.DateField):
widget = MonthYearWidget
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.input_formats = ["%Y-%m"]
@@ -34,11 +36,13 @@ class MonthYearFormField(forms.DateField):
def to_python(self, value):
if value in self.empty_values:
return None
if isinstance(value, datetime.datetime):
return value.date()
try:
date = datetime.datetime.strptime(value, "%Y-%m")
return date.replace(day=1).date()
except ValueError:
raise ValidationError("Invalid date format. Use YYYY-MM.")
raise ValidationError(_("Invalid date format. Use YYYY-MM."))
def prepare_value(self, value):
if isinstance(value, datetime.date):

View File

@@ -1,9 +1,6 @@
from datetime import datetime, date
from django import forms
from decimal import Decimal, InvalidOperation
from django.template.defaultfilters import floatformat
from django import forms
from django.utils.formats import get_format, number_format
@@ -25,19 +22,6 @@ def convert_to_decimal(value: str):
return None
class MonthYearWidget(forms.DateInput):
"""
Custom widget to display a month-year picker.
"""
input_type = "month" # Set the input type to 'month'
def format_value(self, value):
if isinstance(value, (datetime, date)):
return value.strftime("%Y-%m")
return value
class ArbitraryDecimalDisplayNumberInput(forms.TextInput):
"""A widget for displaying and inputing decimal numbers with the least amount of trailing zeros possible. You
must set this on your Form's __init__ method."""

View File

@@ -0,0 +1,16 @@
from datetime import datetime, date
from django import forms
class MonthYearWidget(forms.DateInput):
"""
Custom widget to display a month-year picker.
"""
input_type = "month" # Set the input type to 'month'
def format_value(self, value):
if isinstance(value, (datetime, date)):
return value.strftime("%Y-%m")
return value

View File

@@ -1,11 +1,10 @@
from crispy_bootstrap5.bootstrap5 import Switch
from crispy_forms.bootstrap import FormActions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Field, Fieldset
from crispy_forms.layout import Layout, Row, Column, Field
from dateutil.relativedelta import relativedelta
from django import forms
from django.db import transaction
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from apps.accounts.models import Account
@@ -14,17 +13,15 @@ from apps.common.fields.forms.dynamic_select import (
DynamicModelMultipleChoiceField,
)
from apps.common.widgets.crispy.submit import NoClassSubmit
from apps.common.widgets.tom_select import TomSelect, TomSelectMultiple
from apps.common.widgets.tom_select import TomSelect
from apps.transactions.models import (
Transaction,
TransactionCategory,
TransactionTag,
InstallmentPlan,
)
from apps.transactions.widgets import (
ArbitraryDecimalDisplayNumberInput,
MonthYearWidget,
)
from apps.common.widgets.decimal import ArbitraryDecimalDisplayNumberInput
from apps.common.fields.month_year import MonthYearFormField
class TransactionForm(forms.ModelForm):
@@ -40,6 +37,7 @@ class TransactionForm(forms.ModelForm):
required=False,
label=_("Tags"),
)
reference_date = MonthYearFormField(label=_("Reference Date"), required=False)
class Meta:
model = Transaction
@@ -190,7 +188,7 @@ class TransferForm(forms.Form):
date = forms.DateField(
label="Date", widget=forms.DateInput(attrs={"type": "date"}, format="%Y-%m-%d")
)
reference_date = forms.CharField(label="Reference Date", widget=MonthYearWidget())
reference_date = MonthYearFormField(label=_("Reference Date"), required=False)
description = forms.CharField(max_length=500, label="Description")
def __init__(self, *args, **kwargs):
@@ -324,6 +322,7 @@ class InstallmentPlanForm(forms.Form):
label=_("Start Date"),
widget=forms.DateInput(attrs={"type": "date"}, format="%Y-%m-%d"),
)
reference_date = MonthYearFormField(label=_("Reference Date"), required=False)
description = forms.CharField(max_length=500, label=_("Description"))
number_of_installments = forms.IntegerField(
min_value=1, label=_("Number of Installments")
@@ -372,9 +371,13 @@ class InstallmentPlanForm(forms.Form):
"account",
"description",
Row(
Column("start_date", css_class="form-group col-md-4 mb-0"),
Column("number_of_installments", css_class="form-group col-md-4 mb-0"),
Column("recurrence", css_class="form-group col-md-4 mb-0"),
Column("number_of_installments", css_class="form-group col-md-6 mb-0"),
Column("recurrence", css_class="form-group col-md-6 mb-0"),
css_class="form-row",
),
Row(
Column("start_date", css_class="form-group col-md-6 mb-0"),
Column("reference_date", css_class="form-group col-md-6 mb-0"),
css_class="form-row",
),
"installment_amount",
@@ -396,12 +399,16 @@ class InstallmentPlanForm(forms.Form):
number_of_installments = self.cleaned_data["number_of_installments"]
transaction_type = self.cleaned_data["type"]
start_date = self.cleaned_data["start_date"]
reference_date = self.cleaned_data["reference_date"] or start_date
recurrence = self.cleaned_data["recurrence"]
account = self.cleaned_data["account"]
description = self.cleaned_data["description"]
installment_amount = self.cleaned_data["installment_amount"]
category = self.cleaned_data["category"]
print(reference_date, type(reference_date))
print(start_date, type(start_date))
with transaction.atomic():
installment_plan = InstallmentPlan.objects.create(
account=account,
@@ -421,11 +428,13 @@ class InstallmentPlanForm(forms.Form):
delta = relativedelta(days=i)
transaction_date = start_date + delta
transaction_reference_date = (reference_date + delta).replace(day=1)
new_transaction = Transaction.objects.create(
account=account,
type=transaction_type,
date=transaction_date,
reference_date=transaction_date.replace(day=1),
is_paid=False,
reference_date=transaction_reference_date,
amount=installment_amount,
description=description,
notes=f"{i + 1}/{number_of_installments}",

View File

@@ -1,6 +1,6 @@
# Generated by Django 5.1.1 on 2024-09-19 02:11
import apps.transactions.fields
import apps.common.fields.month_year
from django.db import migrations, models
@@ -8,19 +8,31 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
]
dependencies = []
operations = [
migrations.CreateModel(
name='Transaction',
name="Transaction",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_paid', models.BooleanField(default=True)),
('date', models.DateField()),
('reference_date', apps.transactions.fields.MonthYearField(help_text='Please enter a month and year in the format MM/YYYY.')),
('description', models.CharField(max_length=500)),
('notes', models.TextField(blank=True)),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("is_paid", models.BooleanField(default=True)),
("date", models.DateField()),
(
"reference_date",
apps.common.fields.month_year.MonthYearModelField(
help_text="Please enter a month and year in the format MM/YYYY."
),
),
("description", models.CharField(max_length=500)),
("notes", models.TextField(blank=True)),
],
),
]

View File

@@ -1,6 +1,6 @@
# Generated by Django 5.1.1 on 2024-09-19 13:35
import apps.transactions.fields
import apps.common.fields.month_year
import apps.transactions.validators
import django.db.models.deletion
from django.db import migrations, models
@@ -9,46 +9,62 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0001_initial'),
('transactions', '0001_initial'),
("accounts", "0001_initial"),
("transactions", "0001_initial"),
]
operations = [
migrations.AddField(
model_name='transaction',
name='account',
field=models.ForeignKey(default=0, on_delete=django.db.models.deletion.PROTECT, to='accounts.account', verbose_name='Account'),
model_name="transaction",
name="account",
field=models.ForeignKey(
default=0,
on_delete=django.db.models.deletion.PROTECT,
to="accounts.account",
verbose_name="Account",
),
preserve_default=False,
),
migrations.AddField(
model_name='transaction',
name='amount',
field=models.DecimalField(decimal_places=18, default=0, max_digits=30, validators=[apps.transactions.validators.validate_non_negative, apps.transactions.validators.validate_decimal_places], verbose_name='Amount'),
model_name="transaction",
name="amount",
field=models.DecimalField(
decimal_places=18,
default=0,
max_digits=30,
validators=[
apps.transactions.validators.validate_non_negative,
apps.transactions.validators.validate_decimal_places,
],
verbose_name="Amount",
),
preserve_default=False,
),
migrations.AlterField(
model_name='transaction',
name='date',
field=models.DateField(verbose_name='Date'),
model_name="transaction",
name="date",
field=models.DateField(verbose_name="Date"),
),
migrations.AlterField(
model_name='transaction',
name='description',
field=models.CharField(max_length=500, verbose_name='Description'),
model_name="transaction",
name="description",
field=models.CharField(max_length=500, verbose_name="Description"),
),
migrations.AlterField(
model_name='transaction',
name='is_paid',
field=models.BooleanField(default=True, verbose_name='Paid'),
model_name="transaction",
name="is_paid",
field=models.BooleanField(default=True, verbose_name="Paid"),
),
migrations.AlterField(
model_name='transaction',
name='notes',
field=models.TextField(blank=True, verbose_name='Notes'),
model_name="transaction",
name="notes",
field=models.TextField(blank=True, verbose_name="Notes"),
),
migrations.AlterField(
model_name='transaction',
name='reference_date',
field=apps.transactions.fields.MonthYearField(verbose_name='Reference Date'),
model_name="transaction",
name="reference_date",
field=apps.common.fields.month_year.MonthYearModelField(
verbose_name="Reference Date"
),
),
]

View File

@@ -6,9 +6,9 @@ from django.utils.functional import cached_property
from django.utils.translation import gettext_lazy as _
from apps.common.functions.decimals import truncate_decimal
from apps.transactions.fields import MonthYearField
from apps.transactions.validators import validate_decimal_places, validate_non_negative
from apps.currencies.utils.convert import convert
from apps.common.fields.month_year import MonthYearModelField
class TransactionCategory(models.Model):
@@ -76,7 +76,7 @@ class Transaction(models.Model):
)
is_paid = models.BooleanField(default=True, verbose_name=_("Paid"))
date = models.DateField(verbose_name=_("Date"))
reference_date = MonthYearField(verbose_name=_("Reference Date"))
reference_date = MonthYearModelField(verbose_name=_("Reference Date"))
amount = models.DecimalField(
max_digits=42,