Changeset - 52127f437376
[Not reviewed]
default
0 4 0
Dennis Fink - 4 years ago 2021-06-14 20:43:03
dennis.fink@c3l.lu
Split up membership plans into more fields.

Student and starving are now options that can be selected additionally to the
regular or supporting membership.
4 files changed with 44 insertions and 17 deletions:
0 comments (0 inline, 0 general)
c3l_membership/forms.py
Show inline comments
 
from datetime import date
 

	
 
from flask_wtf import Form
 
from wtforms import BooleanField, RadioField, StringField, SubmitField
 
from wtforms.fields.html5 import DateField
 
from wtforms.validators import Email, InputRequired, Length, Optional, Required
 

	
 

	
 
class MembershipForm(Form):
 

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

	
 
    membership = RadioField(
 
        "Membership Plan",
 
        validators=[InputRequired("Please select one of the options!")],
 
        choices=[
 
            ("regular", "Regular membership (120€/year)"),
 
            ("student", "Student membership (40€/year)"),
 
            (
 
                "regular",
 
                "Regular membership - Membership with voting rights on the general assembly.",
 
            ),
 
            (
 
                "supporting",
 
                "Supporting membership (40€/year) - Membership without voting rights",
 
                "Supporting membership - Membership without voting rights on the general assembly.",
 
            ),
 
            ("starving", "Starving Hacker - Get in touch with us at info@c3l.lu"),
 
        ],
 
    )
 

	
 
    student = BooleanField(
 
        ("I am a student and would like to have the reduced membership fees."),
 
    )
 

	
 
    starving = BooleanField(
 
        (
 
            "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(
 
        "Payment Options",
 
        validators=[InputRequired("Please select one of the options!")],
 
        choices=[
 
            ("cash", "by cash"),
 
            ("wire transfer", "by wire transfer"),
 
            ("digicash", "by DigiCash"),
 
            ("bitcoin", "by bitcoin"),
 
            ("ethereum", "by ethereum"),
 
        ],
 
    )
 

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

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

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

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

	
 
    gpg = StringField(
 
        "GPG-ID",
 
        validators=[Optional(), Length(max=18)],
 
    )
 
    jabber = StringField("Jabber Handle", validators=[Optional(), Email()])
 
    twitter = StringField("Twitter Handle", validators=[Optional()])
 

	
 
    terms = BooleanField(
 
        (
 
            "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>'
 
        ),
c3l_membership/templates/index.html
Show inline comments
 
@@ -15,96 +15,110 @@
 
<div class="pure-g">
 
  <div class="pure-u-md-1-3">
 
  </div>
 
  <div class="pure-u-1-1 pure-u-md-1-3">
 
    <img src="{{ url_for('static', filename='images/logo.png') }}" class="pure-img"></img>
 
    <h1>Membership Application</h1>
 
    <h2>How to use this form</h2>
 
    <p>Fill out this form and click on "Become a member". Afterwards you will be presented with a PDF,
 
      which you have to send to info@c3l.lu or bring it to one of our next events. Print it or save it
 
      to your local hardware, because we don't save a copy on our servers for data protection reasons!</p>
 
    {% if form.errors %}
 
    {% for fieldname, errors in form.errors.items() %}
 
    {% for error in errors %}
 
    <p>{{ fieldname }} - {{ error }}</p>
 
    {% endfor %}
 
    {% endfor %}
 
    {% endif %}
 
    <form class="pure-form pure-form-stacked" method="POST" action="/">
 
      <fieldset>
 
        {{ form.hidden_tag() }}
 
        <legend>Required information</legend>
 
        <div class="pure-g">
 
          <div class="pure-u-1-1">
 
            <b>{{ form.username.label }}</b>
 
            {{ form.username(required=True, class="pure-u-1-1") }}
 
          </div>
 
        </div>
 
        <div class="pure-g">
 
          <div class="pure-u-1-1">
 
            <b>{{ form.email.label }}</b>
 
            {{ form.email(required=True, class="pure-u-1-1") }}
 
          </div>
 
        </div>
 
        <div class="pure-g">
 
          <div class="pure-u-1-1">
 
            <b>{{ form.fullname.label }}</b>
 
            {{ form.fullname(required=True, class="pure-u-1-1") }}
 
          </div>
 
        </div>
 
        <div class="pure-g">
 
          <div class="pure-u-1-1">
 
            <b>{{ form.membership.label }}</b>
 
            {% for option in form.membership %}
 
            <label for="{{ option.id }}" class="pure-radio pure-u-1-1">
 
              {{ option() }}
 
              {{ option.label.text }}
 
            </label>
 
            {% endfor %}
 
            <div class="pure-g">
 
              <div class="pure-u-1-1">
 
                <label for="{{ form.student.id }}" class="pure-checkbox">
 
                {{ form.student }} {{ form.student.label.text|safe}}
 
                </label>
 
              </div>
 
            </div>
 
            <div class="pure-g">
 
              <div class="pure-u-1-1">
 
                <label for="{{ form.starving.id }}" class="pure-checkbox">
 
                  {{ form.starving }} {{ form.starving.label.text|safe}}
 
                </label>
 
              </div>
 
            </div>
 
            <h3>What's difference between the different membership options?</h3>
 
            <p>All the options include to following benefits:</p>
 
            <ul>
 
              <li>Access to the <a href="https://wiki.c3l.lu/doku.php?id=organization:membership#benefits">services</a> run by us</li>
 
              <li>Access to our <a href="https://wiki.c3l.lu/doku.php?id=chaosstuff:bootstrap">hackerspace: ChaosStuff</a></li>
 
            </ul>
 
            <p>Becoming a regular/student member gives you these additional benefits:</p>
 
            <ul>
 
              <li>Voting rights on general assemblys</li>
 
              <li>Access to our internal mailinglist</li>
 
            </ul>
 
            <p>You can read more on the membership <a href="https://wiki.c3l.lu/doku.php?id=organization:membership">here</a>.</p>
 
            <h3>I cannot afford the membership?</h3>
 
            <p>If you cannot afford the membership, please contact us via info@c3l.lu first, before filling out the membership form. We will try to find a solution together.</p>
 
          </div>
 
        </div>
 
        <div class="pure-g">
 
          <div class="pure-u-1-1">
 
            <b>{{ form.payment.label }}</b>
 
            {% for option in form.payment %}
 
            <label for="{{ option.id }}" class="pure-radio pure-u-1-1">
 
              {{ option() }}
 
              {{ option.label.text }}
 
            </label>
 
            {% endfor %}
 
          </div>
 
        </div>
 
        <legend>Additional information</legend>
 
        <div class="pure-g">
 
          <div class="pure-u-1-1">
 
            <b>{{ form.street.label }}</b>
 
            {{ form.street(class="pure-u-1-1") }}
 
          </div>
 
        </div>
 
        <div class="pure-g">
 
          <div class="pure-u-1-1">
 
            <b>{{ form.zip.label }}</b>
 
            {{ form.zip(class="pure-u-1-1") }}
 
          </div>
 
        </div>
 
        <div class="pure-g">
 
          <div class="pure-u-1-1">
 
            <b>{{ form.city.label }}</b>
 
            {{ form.city(class="pure-u-1-1") }}
 
          </div>
 
        </div>
 
        <div class="pure-g">
 
          <div class="pure-u-1-1">
c3l_membership/templates/member.html
Show inline comments
 
<!DOCTYPE html>
 
<html>
 
  <head>
 
   <title>Membership Application - {{ form.username.data }}</title>
 
   <link rel="stylesheet" href="{{ url_for('static', filename='pdf.css') }}" />
 
  </head>
 
  <body>
 
    <img src="{{ url_for('static', filename='images/logo.png') }}"></img>
 
    <h1>Membership Application</h1>
 
    <dl>
 
      <dt>Username:</dt>
 
      <dd>{{ form.username.data }}</dd>
 
      <dt>E-Mail:</dt>
 
      <dd>{{ form.email.data }}</dd>
 
      <dt>Full Name:</dt>
 
      <dd>{{ form.fullname.data }}</dd>
 
      <dt>Street:</dt>
 
      <dd>{{ form.street.data if form.street.data else "<i>Not specified</i>"|safe }}</dd>
 
      <dt>ZIP-Code:</dt>
 
      <dd>{{ form.zip.data if form.zip.data else "<i>Not specified</i>"|safe }}</dd>
 
      <dt>City:</dt>
 
      <dd>{{ form.city.data if form.city.data else "<i>Not specified</i>"|safe }}</dd>
 
      <dt>State/County/Province:</dt>
 
      <dd>{{ form.state.data if form.state.data else "<i>Not specified</i>"|safe }}</dd>
 
      <dt>Country:</dt>
 
      <dd>{{ form.country.data if form.country.data else "<i>Not specified</i>"|safe }}</dd>
 
      <dt>Membership Plan:</dt>
 
      <dd>{{ membership }}</dd>
 
      <dd>{{ form.membership.data }}</dd>
 
      <dt>Student:</dt>
 
      <dd>{{ "Yes" if form.student.data else "No" }}</dd>
 
      <dt>Starving:</dt>
 
      <dd>{{ "Yes" if form.starving.data else "No" }}</dd>
 
      <dt>Payment:</dt>
 
      <dd>{{ form.payment.data }}</dd>
 
      <dt>Agreed to Terms &amp; Conditions:</dt>
 
      <dd>{{ "Yes" if form.terms.data else "No" }}</dd>
 
      <dt>Minor Member:</dt>
 
      <dd>{{ "Yes" if form.minor_member.data else "No" }}</dd>
 
      <dt>GPG-ID:</dt>
 
      <dd>{{ form.gpg.data or "<i>Not specified</i>"|safe }}</dd>
 
      <dt>Jabber Handle:</dt>
 
      <dd>{{ form.jabber.data or "<i>Not specified</i>"|safe }}</dd>
 
      <dt>Twitter Handle:</dt>
 
      <dd>{{ form.twitter.data or "<i>Not specified</i>"|safe }}</dd>
 
    </dl>
 
    <p>Send this document to the Chaos Computer Club Lëtzebuerg!</p>
 
    {% if form.payment.data == 'wire transfer' %}
 
      <ul class="bank">
 
        <li>Account Holder: Chaos Computer Club Lëtzebuerg</li>
 
        <li>BIC/Swift: BCEELULLXXX</li>
 
        <li>IBAN: LU29 0019 2855 3890 4000</li>
 
        <li>Message: Membership fee {{ year }} {{ form.username.data }}</li>
 
        <li>Amount: {{ price }}€</li>
 
      </ul>
 
    {% elif form.payment.data == 'cash' %}
 
      <p>Please bring {{ price }}€ with you the next time you meet us!</p>
 
    {% elif form.payment.data == 'bitcoin' %}
 
      <div>
 
          <ul class='btctext'>
 
            <li><b>Address:</b> 3BV5UPToMUmXJiqUVndHjSSq2HqDW8npRd</li>
 
            <li><b>Label:</b> Membership Fee</li>
 
            <li><b>Message:</b> {{ year }} {{ form.username.data }}</li>
 
            <li><b>Amount:</b> {{ price }} BTC</li>
 
         </ul>
 
         {% set bitcoin_url= 'bitcoin:3BV5UPToMUmXJiqUVndHjSSq2HqDW8npRd?amount={amount}&label=Membership Fee {year} {username}&message=Membership Fee {year} {username}'.format(amount=price, year=year, username=form.username.data) %}
 
         <img class='btcqrcode' src="{{ qrcode(bitcoin_url) }}"></img>
 
      </div>
 
    {% elif form.payment.data == 'ethereum' %}
 
      <div>
 
        <ul class='btctext'>
 
          <li><b>Address:</b> 0x1C05b4C236914B218B57e0E25948d416B4885655</li>
 
          <li><b>Label:</b> Membership Fee</li>
 
          <li><b>Message:</b> {{ year }} {{ form.username.data }}</li>
 
          <li><b>Amount:</b> {{ price }} ETH</li>
 
        </ul>
 
        {% set ethereum_url= '0x1C05b4C236914B218B57e0E25948d416B4885655' %}
 
          <img class="btcqrcode" src="{{ qrcode(ethereum_url) }}"></img>
 
      </div>
 
    {% elif form.payment.data == 'digicash' %}
 
      <div>
c3l_membership/views.py
Show inline comments
 
import subprocess
 
from datetime import date
 

	
 
from flask import Blueprint, current_app, render_template, request
 
from flask_weasyprint import HTML, render_pdf
 

	
 
from .forms import MembershipForm
 

	
 
root_page = Blueprint("root", __name__)
 

	
 

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

	
 
        if form.minor_member.data and form.membership.data != "starving":
 
            membership = "student"
 
        else:
 
            membership = form.membership.data
 
        if (
 
            form.minor_member.data
 
            or form.student.data
 
            or form.membership.data == "supporting"
 
        ):
 
            price = 40
 
        elif form.membership.data == "regular":
 
            price = 120
 

	
 
        if membership in ["student", "supporting"]:
 
            price = 40
 
        elif membership == "starving":
 
        if form.starving.data:
 
            price = 1
 
        else:
 
            price = 120
 

	
 
        if form.payment.data == "bitcoin":
 
            price = subprocess.check_output(
 
                ["/usr/local/share/btc/BTC_Membership.pl", str(price)]
 
            ).decode("utf-8")
 
        elif form.payment.data == "ethereum":
 
            price = subprocess.check_output(
 
                ["/usr/local/share/eth/ETH_Membership.pl", str(price)]
 
            ).decode("utf-8")
 
        elif form.payment.data == "digicash":
 
            price = price * 100
 

	
 
        year = date.today().year
 

	
 
        html = render_template(
 
            "member.html", form=form, membership=membership, price=price, year=year
 
        )
 
        html = render_template("member.html", form=form, price=price, year=year)
 
        return render_pdf(HTML(string=html))
 
    return render_template("index.html", form=form)
0 comments (0 inline, 0 general)