Changeset - 262323080d4e
[Not reviewed]
default
0 2 0
Dennis Fink - 3 years ago 2022-01-19 21:08:16
dennis.fink@c3l.lu
Make student and starving mutually exclusive
2 files changed with 60 insertions and 3 deletions:
0 comments (0 inline, 0 general)
c3l_membership/forms.py
Show inline comments
 
from datetime import date
 

	
 
from flask_babel import lazy_gettext
 
from flask_wtf import FlaskForm
 
from wtforms import BooleanField, DateField, RadioField, StringField, SubmitField
 
from wtforms import (
 
    BooleanField,
 
    DateField,
 
    RadioField,
 
    StringField,
 
    SubmitField,
 
    ValidationError,
 
)
 
from wtforms.validators import Email, InputRequired, Length, Optional
 

	
 

	
 
class NotEqualTo:
 
    """
 
    Compares the values of two fields.
 
    :param fieldname:
 
        The name of the other field to compare to.
 
    :param message:
 
        Error message to raise in case of a validation error. Can be
 
        interpolated with `%(other_label)s` and `%(other_name)s` to provide a
 
        more helpful error.
 
    """
 

	
 
    def __init__(self, fieldname, message=None):
 
        self.fieldname = fieldname
 
        self.message = message
 

	
 
    def __call__(self, form, field):
 
        try:
 
            other = form[self.fieldname]
 
        except KeyError as exc:
 
            raise ValidationError(
 
                field.gettext("Invalid field name '%s'.") % self.fieldname
 
            ) from exc
 
        if field.data != other.data:
 
            return
 

	
 
        d = {
 
            "other_label": hasattr(other, "label")
 
            and other.label.text
 
            or self.fieldname,
 
            "other_name": self.fieldname,
 
        }
 
        message = self.message
 
        if message is None:
 
            message = field.gettext("Field must not be equal to %(other_name)s.")
 

	
 
        raise ValidationError(message % d)
 

	
 

	
 
class MembershipForm(FlaskForm):
 

	
 
    username = StringField(
 
        lazy_gettext("Username"),
 
        validators=[
 
            InputRequired(lazy_gettext("This field is required!")),
 
            Length(max=255),
 
        ],
 
    )
 
    email = StringField(
 
        lazy_gettext("E-Mail"),
 
        validators=[InputRequired(lazy_gettext("This field is required!")), Email()],
 
    )
 
    fullname = StringField(
 
        lazy_gettext("Full Name"),
 
        validators=[
 
            InputRequired(lazy_gettext("This field is required!")),
 
            Length(max=65536),
 
        ],
 
    )
 

	
 
    membership = RadioField(
 
        lazy_gettext("Membership Plan"),
 
        validators=[InputRequired(lazy_gettext("Please select one of the options!"))],
 
        choices=[
 
            (
 
                "regular",
 
                lazy_gettext(
 
                    "Regular membership - Membership with voting rights on the general assembly."
 
                ),
 
            ),
 
            (
 
                "supporting",
 
                lazy_gettext(
 
                    "Supporting membership - Membership without voting rights on the general assembly."
 
                ),
 
            ),
 
        ],
 
    )
 

	
 
    student = BooleanField(
 
        lazy_gettext(
 
            "I am a student and would like to have the reduced membership fees."
 
        ),
 
        validators=[
 
            Optional(),
 
            NotEqualTo(
 
                "starving",
 
                lazy_gettext(
 
                    "Student and Starving Hacker are mutually exclusive! Please select only one of them."
 
                ),
 
            ),
 
        ],
 
    )
 

	
 
    starving = BooleanField(
 
        lazy_gettext(
 
            "I am a starving hacker and cannot afford the membership! (Please get in touch with us at info@c3l.lu before filling out this membership form)"
 
        )
 
    )
 

	
 
    payment = RadioField(
 
        lazy_gettext("Payment Options"),
 
        validators=[InputRequired(lazy_gettext("Please select one of the options!"))],
 
    )
 

	
 
    birthday = DateField(lazy_gettext("Birthday"), validators=[Optional()])
 

	
 
    street = StringField(
 
        lazy_gettext("Nr., Street"),
 
        validators=[Optional(), Length(max=4000)],
 
    )
 
    zip = StringField(
 
        lazy_gettext("Postal Code"),
 
        validators=[Optional(), Length(max=30)],
 
    )
 

	
 
    city = StringField(
 
        lazy_gettext("City/Town"),
 
        validators=[Optional(), Length(max=500)],
 
    )
 

	
 
    state = StringField(
 
        lazy_gettext("State/County/Province"),
 
        validators=[Optional(), Length(max=500)],
 
    )
 

	
 
    country = StringField(
 
        lazy_gettext("Country"),
 
        validators=[Optional(), Length(max=500)],
 
    )
 

	
 
    terms = BooleanField(
 
        lazy_gettext(
 
            'By submitting this membership application, you agree to have read and understood the <a href="http://statutes.c3l.lu">statutes of the Chaos Computer Club Lëtzebuerg A.S.B.L.</a>.'
 
        ),
 
        validators=[InputRequired()],
 
    )
 

	
 
    minor_member = BooleanField(
 
        lazy_gettext(
 
            "I am under 18 years of age and have the approval of my legal representative."
 
        )
 
    )
 
    submit = SubmitField(lazy_gettext("Become a member"))
c3l_membership/views.py
Show inline comments
 
@@ -4,120 +4,123 @@ from datetime import date
 

	
 
import requests
 
from flask import Blueprint, current_app, g, render_template, request
 
from flask_babel import gettext
 
from flask_weasyprint import HTML, render_pdf
 

	
 
from .forms import MembershipForm
 

	
 
root_page = Blueprint("root", __name__, url_prefix="/<lang_code>")
 

	
 
xml_template = "<member><numm>{name}</numm><gebuertsdag>{birthday:%d.%m.%Y}</gebuertsdag><address>{address}</address><nick>{username}</nick><email>{email}</email><status>{status}</status><stemmrecht>{voting}</stemmrecht></member>"
 

	
 

	
 
@root_page.url_defaults
 
def add_lang_code(endpoint, values):
 
    values.setdefault("lang_code", g.lang_code)
 

	
 

	
 
@root_page.url_value_preprocessor
 
def pull_lang_code(endpoint, values):
 
    lang_code = values.pop("lang_code")
 
    if lang_code != "favicon.ico":
 
        g.lang_code = lang_code
 

	
 

	
 
@root_page.route("/", methods=("GET", "POST"))
 
def index():
 
    form = MembershipForm()
 

	
 
    choices = [
 
        ("cash", gettext("by cash")),
 
        ("wire transfer", gettext("by wire transfer")),
 
    ]
 

	
 
    if current_app.config["DIGICASH_ENABLED"]:
 
        choices.append(("digicash", gettext("by DigiCash")))
 

	
 
    for cryptocurrency_label, options in current_app.config["CRYPTOCURRENCIES"].items():
 
        if options["ENABLED"]:
 
            choices.append(
 
                (
 
                    cryptocurrency_label,
 
                    " ".join((gettext("by"), cryptocurrency_label.title())),
 
                ),
 
            )
 

	
 
    form.payment.choices = choices
 

	
 
    if form.validate_on_submit():
 

	
 
        if (
 
            form.minor_member.data
 
            or form.student.data
 
            or form.membership.data == "supporting"
 
        ):
 
            price = current_app.config["SUPPORTING_FEE"]
 
        elif form.starving.data:
 
            price = 1
 
        else:
 
            price = current_app.config["REGULAR_FEE"]
 

	
 
        if form.starving.data:
 
            status = "Starving"
 
        elif form.minor_member.data or form.student.data:
 
            status = "Student"
 
        elif form.membership.data == "supporting":
 
            status = "Supporter"
 
        else:
 
            status = "Regular"
 

	
 
        if form.payment.data in current_app.config["CRYPTOCURRENCIES"]:
 
            try:
 
                current_conversion_r = requests.get(
 
                    current_app.config["CONVERSION_URL"], timeout=30
 
                )
 
                current_conversion_r.raise_for_status()
 
            except:
 
                return render_template("index.html", form=form, crypto_error=True), 503
 
            else:
 
                current_conversion = current_conversion_r.json()
 
                commodity = current_app.config["CRYPTOCURRENCIES"][form.payment.data][
 
                    "COMMODITY"
 
                ]
 
                price = current_conversion[commodity][status.upper()]
 
        elif form.payment.data == "digicash":
 
            price = price * 100
 

	
 
        now = date.today()
 
        xml_data = {
 
            "status": status,
 
            "name": form.fullname.data,
 
            "birthday": form.birthday.data
 
            if form.birthday.data is not None
 
            else date(9999, 12, 12),
 
            "username": form.username.data,
 
            "email": form.email.data,
 
            "address": " ".join(
 
            "address": re.sub(
 
                "\s+",
 
                " ",
 
                " ".join(
 
                (
 
                    form.street.data,
 
                    form.zip.data,
 
                    form.city.data,
 
                    form.state.data,
 
                    form.country.data,
 
                )
 
            ),
 
            "address": re.sub("\s+", " ", xml_data["address"]),
 
            ),
 
            "voting": 1 if form.membership.data == "regular" else 0,
 
            "date": now,
 
        }
 

	
 
        html = render_template(
 
            "member.html",
 
            form=form,
 
            price=price,
 
            year=now.year,
 
            xml=xml_template.format(**xml_data),
 
        )
 
        return render_pdf(HTML(string=html))
 

	
 
    return render_template("index.html", form=form, crypto_error=False)
0 comments (0 inline, 0 general)