diff --git a/src/accounting/forms.py b/src/accounting/forms.py index c749695..026130f 100644 --- a/src/accounting/forms.py +++ b/src/accounting/forms.py @@ -17,12 +17,15 @@ """The forms. """ +import re + +from flask_babel import LazyString from flask_wtf import FlaskForm from wtforms import StringField, ValidationError from accounting import db from accounting.locale import lazy_gettext -from accounting.models import Currency +from accounting.models import Currency, Account class CurrencyExists: @@ -34,3 +37,60 @@ class CurrencyExists: if db.session.get(Currency, field.data) is None: raise ValidationError(lazy_gettext( "The currency does not exist.")) + + +class AccountExists: + """The validator to check if the account exists.""" + + def __call__(self, form: FlaskForm, field: StringField) -> None: + if field.data is None: + return + if Account.find_by_code(field.data) is None: + raise ValidationError(lazy_gettext( + "The account does not exist.")) + + +class IsDebitAccount: + """The validator to check if the account is for debit line items.""" + + def __init__(self, message: str | LazyString | None = None): + """Constructs the validator. + + :param message: The optional custom error message. + """ + if message is None: + message = lazy_gettext( + "This account is not for debit line items.") + self.__message: str | LazyString = message + + def __call__(self, form: FlaskForm, field: StringField) -> None: + if field.data is None: + return + if re.match(r"^(?:[1235689]|7[5678])", field.data) \ + and not field.data.startswith("3351-") \ + and not field.data.startswith("3353-"): + return + raise ValidationError(self.__message) + + +class IsCreditAccount: + """The validator to check if the account is for credit line items.""" + + def __init__(self, message: str | LazyString | None = None): + """Constructs the validator. + + :param message: The optional custom error message. + """ + if message is None: + message = lazy_gettext( + "This account is not for credit line items.") + self.__message: str | LazyString = message + + def __call__(self, form: FlaskForm, field: StringField) -> None: + if field.data is None: + return + if re.match(r"^(?:[123489]|7[1234])", field.data) \ + and not field.data.startswith("3351-") \ + and not field.data.startswith("3353-"): + return + raise ValidationError(self.__message) diff --git a/src/accounting/journal_entry/forms/line_item.py b/src/accounting/journal_entry/forms/line_item.py index 2d14778..ddf198b 100644 --- a/src/accounting/journal_entry/forms/line_item.py +++ b/src/accounting/journal_entry/forms/line_item.py @@ -17,7 +17,6 @@ """The line item sub-forms for the journal entry management. """ -import re from datetime import date from decimal import Decimal @@ -29,6 +28,7 @@ from wtforms import StringField, ValidationError, DecimalField, IntegerField from wtforms.validators import DataRequired, Optional from accounting import db +from accounting.forms import AccountExists, IsDebitAccount, IsCreditAccount from accounting.locale import lazy_gettext from accounting.models import Account, JournalEntryLineItem from accounting.template_filters import format_amount @@ -105,45 +105,6 @@ class OriginalLineItemNotOffset: "The original line item cannot be an offset item.")) -class AccountExists: - """The validator to check if the account exists.""" - - def __call__(self, form: FlaskForm, field: StringField) -> None: - if field.data is None: - return - if Account.find_by_code(field.data) is None: - raise ValidationError(lazy_gettext( - "The account does not exist.")) - - -class IsDebitAccount: - """The validator to check if the account is for debit line items.""" - - def __call__(self, form: FlaskForm, field: StringField) -> None: - if field.data is None: - return - if re.match(r"^(?:[1235689]|7[5678])", field.data) \ - and not field.data.startswith("3351-") \ - and not field.data.startswith("3353-"): - return - raise ValidationError(lazy_gettext( - "This account is not for debit line items.")) - - -class IsCreditAccount: - """The validator to check if the account is for credit line items.""" - - def __call__(self, form: FlaskForm, field: StringField) -> None: - if field.data is None: - return - if re.match(r"^(?:[123489]|7[1234])", field.data) \ - and not field.data.startswith("3351-") \ - and not field.data.startswith("3353-"): - return - raise ValidationError(lazy_gettext( - "This account is not for credit line items.")) - - class SameAccountAsOriginalLineItem: """The validator to check if the account is the same as the original line item.""" diff --git a/src/accounting/option/forms.py b/src/accounting/option/forms.py index b8824e6..9e4906b 100644 --- a/src/accounting/option/forms.py +++ b/src/accounting/option/forms.py @@ -17,15 +17,14 @@ """The forms for the option management. """ -import re - from flask import render_template from flask_babel import LazyString from flask_wtf import FlaskForm from wtforms import StringField, FieldList, FormField, IntegerField from wtforms.validators import DataRequired, ValidationError -from accounting.forms import CurrencyExists +from accounting.forms import CurrencyExists, AccountExists, IsDebitAccount, \ + IsCreditAccount from accounting.locale import lazy_gettext from accounting.models import Account from accounting.utils.current_account import CurrentAccount, current_accounts @@ -33,45 +32,6 @@ from accounting.utils.options import Options from accounting.utils.strip_text import strip_text -class AccountExists: - """The validator to check if the account exists.""" - - def __call__(self, form: FlaskForm, field: StringField) -> None: - if field.data is None: - return - if Account.find_by_code(field.data) is None: - raise ValidationError(lazy_gettext( - "The account does not exist.")) - - -class IsExpenseAccount: - """The validator to check if the account is for expense.""" - - def __call__(self, form: FlaskForm, field: StringField) -> None: - if field.data is None: - return - if re.match(r"^(?:[1235689]|7[5678])", field.data) \ - and not field.data.startswith("3351-") \ - and not field.data.startswith("3353-"): - return - raise ValidationError(lazy_gettext( - "This account is not for expense.")) - - -class IsIncomeAccount: - """The validator to check if the account is for income.""" - - def __call__(self, form: FlaskForm, field: StringField) -> None: - if field.data is None: - return - if re.match(r"^(?:[123489]|7[1234])", field.data) \ - and not field.data.startswith("3351-") \ - and not field.data.startswith("3353-"): - return - raise ValidationError(lazy_gettext( - "This account is not for income.")) - - class NotStartPayableFromExpense: """The validator to check that a payable line item does not start from expense.""" @@ -143,9 +103,10 @@ class RecurringExpenseForm(RecurringItemForm): """The name of the recurring item.""" account_code = StringField( filters=[strip_text], - validators=[AccountExists(), - IsExpenseAccount(), - NotStartPayableFromExpense()]) + validators=[ + AccountExists(), + IsDebitAccount(lazy_gettext("This account is not for expense.")), + NotStartPayableFromExpense()]) """The account code.""" description_template = StringField( filters=[strip_text], @@ -165,9 +126,10 @@ class RecurringIncomeForm(RecurringItemForm): """The name of the recurring item.""" account_code = StringField( filters=[strip_text], - validators=[AccountExists(), - IsIncomeAccount(), - NotStartReceivableFromIncome()]) + validators=[ + AccountExists(), + IsCreditAccount(lazy_gettext("This account is not for income.")), + NotStartReceivableFromIncome()]) """The account code.""" description_template = StringField( filters=[strip_text],