Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions app/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,24 @@ class DeleteForm(FlaskForm):
class LoginForm(FlaskForm):
openid = StringField('openid', validators=[DataRequired()])
remember_me = BooleanField('remember_me', default=False)

class AdminBeerEditForm(ModelForm, FlaskForm):
class Meta:
model = Beer

name = StringField('För- och efternamn', validators=[DataRequired()])
nickname = StringField('Kårnamn')
email = StringField('epost@din.com', validators=[Email()])
person_number = StringField(
'Personnummer',
validators=[
DataRequired(),
Regexp(
"^[12]{1}[90]{1}[0-9]{6}-[0-9]{4}$",
message="Skriv personnummer på formatet ååååmmdd-xxxx"
),
validate_age
]
)
mobile_number = StringField('Mobilnummer', validators=[DataRequired()])
has_payed = BooleanField('Betalat')
101 changes: 79 additions & 22 deletions app/mail_ohlreise.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
# -*- coding: utf-8 -*-
from app import app
import smtplib
import os
import json
import base64
from email.mime.text import MIMEText

from app import app
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build

SCOPES = ['https://www.googleapis.com/auth/gmail.send']

FROM_ADDRESS = 'info.brutalakademien'
SUBJECT = "Bokningskonfirmation"
BODY = """
Tack för din anmälan!
Expand All @@ -20,28 +26,79 @@
"""


def send(to_address="andreas.cederstrom@gmail.com", price=1337,
team_name="Aporna"):
def send(to_address="andreas.cederstrom@gmail.com", price=1337, team_name="Aporna"):
bank = app.config['ÖHLREISE']['payment']['bank']
account_number = app.config['ÖHLREISE']['payment']['account_number']
last_payment_date = app.config['ÖHLREISE']['payment']['last_payment_date']
mail = _build_mail(to_address, price, bank, account_number, last_payment_date, team_name)
_do_send(mail)

subject, body = _build_mail_content(
price,
bank,
account_number,
last_payment_date,
team_name
)
return _do_send(to_address, subject, body)

def _build_mail(to_address, price, bank, account_number, last_payment_date , team_name):

def _build_mail_content(price, bank, account_number, last_payment_date, team_name):
body = BODY % (price, bank, account_number, last_payment_date, team_name)
mail = MIMEText(body)
mail['Subject'] = SUBJECT
mail['From'] = FROM_ADDRESS
mail['To'] = to_address
return mail


def _do_send(mail):
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login(app.config['GMAIL_USERNAME'], app.config['GMAIL_PASSWORD'])
server.sendmail(mail['From'], mail['To'], mail.as_string())
server.quit()
return SUBJECT, body


def _load_credentials():
token_path = app.config['GOOGLE_OAUTH_TOKEN_FILE']

if not os.path.exists(token_path):
raise RuntimeError(
"Gmail OAuth token.json is missing. Connect Gmail via the admin OAuth route first."
)

with open(token_path, 'r') as f:
token_data = json.load(f)

creds = Credentials.from_authorized_user_info(token_data, SCOPES)

if creds.expired and creds.refresh_token:
creds.refresh(Request())
_save_credentials(creds)

if not creds.valid:
raise RuntimeError("Gmail OAuth credentials are invalid. Reconnect Gmail.")

return creds


def _save_credentials(creds):
token_path = app.config['GOOGLE_OAUTH_TOKEN_FILE']
with open(token_path, 'w') as f:
f.write(creds.to_json())


def _build_gmail_service():
creds = _load_credentials()
return build('gmail', 'v1', credentials=creds)


def _create_message(to_address, subject, body):
from_address = app.config['GMAIL_FROM_ADDRESS']

message = MIMEText(body, _charset='utf-8')
message['To'] = to_address
message['From'] = from_address
message['Reply-To'] = from_address
message['Subject'] = subject

raw = base64.urlsafe_b64encode(message.as_bytes()).decode('utf-8')
return {'raw': raw}


def _do_send(to_address, subject, body):
service = _build_gmail_service()
message = _create_message(to_address, subject, body)

service.users().messages().send(
userId='me',
body=message
).execute()

2 changes: 1 addition & 1 deletion app/templates/ohlreise/countdown.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{% block title %}Anmälan{% endblock %}
{% block content %}
<script>
var offsetToStart = {{ milliseconds }};
var offsetToStart = "{{ milliseconds }}";
var openAt = new Date();
openAt.setTime(openAt.getTime() + offsetToStart);

Expand Down
26 changes: 13 additions & 13 deletions app/templates/ohlreise/edit_member.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,30 @@ <h3>{{ title }}</h3>
<form method="post">
<div class="row uniform 50%">
<div class="4u 12u(mobilep)">
<th>Namn</th>
{{ form.name(placeholder="Namn *") }}
<label for="name">Namn</label>
{{ form.name(id="name", placeholder="Namn *") }}
</div>
<div class="4u 12u(mobilep)">
<th>Kårnamn</th>
{{ form.nickname(placeholder="Kårnamn") }}
<label for="nickname">Kårnamn</label>
{{ form.nickname(id="nickname", placeholder="Kårnamn") }}
</div>
<div class="4u 12u(mobilep)">
<th>Personnummer</th>
{{ form.person_number(placeholder="Personnummer * (ååååmmdd-xxxx)") }}
<label for="person_number">Personnummer</label>
{{ form.person_number(id="person_number", placeholder="Personnummer * (ååååmmdd-xxxx)") }}
{% for error in form.person_number.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</div>
<div class="4u 12u(mobilep)">
<th>Allergier</th>
{{ form.allergies(placeholder="Allergier") }}
{% for error in form.allergies.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
<label for="email">Email</label>
{{ form.email(id="email", placeholder="Email *") }}
</div>
<div class="4u 12u(mobilep)">
<th>Email</th>
{{ form.email(placeholder="Email *") }}
<label for="mobile_number">Mobilnummer</label>
{{ form.mobile_number(id="mobile_number", placeholder="Mobilnummer *") }}
{% for error in form.mobile_number.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</div>
</div>
<div class="row uniform 50%">
Expand Down
74 changes: 61 additions & 13 deletions app/templates/ohlreise/members.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@
{% block title %}Alla anmälda bussresenärer{% endblock %}
{% block content %}

{% set is_admin = current_user.is_authenticated %}
{% set is_admin = current_user.is_authenticated and current_user.is_admin %}

<script src="/static/js/jquery.tablesorter.min.js"></script>
<script>
$(function() {
$(".tablesorter").tablesorter();

$("#select_has_payed").change(function() {
var url = [location.protocol, '//', location.host, location.pathname].join('');
var has_payed = this.options[this.selectedIndex].value;
var query = '';

if (has_payed !== '-') {
query = '?has_payed=' + has_payed;
}

$("#export_beer_csv_link").attr("href", "{{ url_for('ohlreise_export_csv') }}" + query);

window.location = url + query;
});
});
</script>

Expand All @@ -18,7 +32,36 @@ <h3>Alla anmälda bussresenärer</h3>
<p>
Totalt har vi <strong>{{ beer|length }}</strong> anmälda bussresenärer.
</p>

{% if is_admin %}
<p>
Antal som har betalat: <strong>{{ beer|selectattr("has_payed")|list|length }}</strong><br/>
Antal som inte har betalat: <strong>{{ beer|rejectattr("has_payed")|list|length }}</strong>
</p>

<div class="select-wrapper">
<select id="select_has_payed" name="has_payed">
<option value="-">- Inget filter -</option>
<option value="True" {% if has_payed == "True" %}selected{% endif %}>Har betalat</option>
<option value="False" {% if has_payed == "False" %}selected{% endif %}>Har EJ betalat</option>
</select>
</div>

<div class="export-links">
<a id="export_beer_csv_link" href="{{ url_for('ohlreise_export_csv', has_payed=has_payed if has_payed else '-') }}">
Ladda ner bussresenärer till CSV
</a>
<p>
<form method="post" action="{{ url_for('ohlreise_remove_all_members') }}"
onsubmit="return confirm('Är du säker på att du vill ta bort alla dess resenärer?');" class="inline-action-form">
<button type="submit" class="text-link-button-danger">
Ta bort alla resenärer
</button>
</form>
</p>
{% endif %}
</section>

<section class="box">
<div class="table-wrapper">
<table class="tablesorter">
Expand All @@ -28,26 +71,31 @@ <h3>Alla anmälda bussresenärer</h3>
<th>Kårnamn</th>
{% if is_admin %}
<th>Personnummer</th>
<th>Allergier</th>
<th>Email</th>
<th>Har betalat</th>
{% endif %}
</tr>
</thead>
<tbody>
{% for beer in beer %}
{% for member in beer %}
<tr>
<td>{{ beer.name }}</td>
<td>{{ beer.nickname }}</td>
<td>{{ member.name }}</td>
<td>{{ member.nickname }}</td>
{% if is_admin %}
<td>{{ beer.person_number }}</td>
<td>{{ beer.allergies }}</td>
<td>{{ beer.email }} </td>
<td>{{ 'Ja' if beer.has_payed else 'Nej' }}</td>
<td><a href="{{ url_for('ohlreise_edit_member', id=beer.id)}}">Edit</a></td>
<form method="post" action="{{ url_for('ohlreise_delete_member', id=beer.id)}}">
<td><button type="submit" name="Ta bort" value="submit_value" class="link-button">Ta bort</button></td>
</form>
<td>{{ member.person_number }}</td>
<td>{{ member.email }}</td>
<td>{{ 'Ja' if member.has_payed else 'Nej' }}</td>
<td>
<a href="{{ url_for('ohlreise_edit_member', id=member.id) }}">Justera</a>
</td>
<td>
<form method="post"
action="{{ url_for('ohlreise_delete_member', id=member.id) }}"
onsubmit="return confirm('Är du säker på att du vill ta bort medlemmen?');"
class="inline-action-form">
<button type="submit" class="text-link-button-danger">Ta bort</button>
</form>
</td>
{% endif %}
</tr>
{% endfor %}
Expand Down
Loading