Für ein Event kann man eine andere Organisation fragen, ob sie dieses Event referenzieren/empfehlen möchten.

This commit is contained in:
Daniel Grams 2020-10-01 21:23:52 +02:00
parent ac818fae9c
commit 0c7f6a4dc8
29 changed files with 781 additions and 439 deletions

5
app.py
View File

@ -2,7 +2,6 @@ import os
from base64 import b64decode
from flask import jsonify, Flask, render_template, request, url_for, redirect, abort, flash, current_app
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.orm import joinedload
from sqlalchemy.sql import asc, func
from sqlalchemy import and_, or_, not_
@ -13,7 +12,6 @@ from flask_principal import Permission
from flask_cors import CORS
import pytz
import json
from urllib.parse import quote_plus
from flask_qrcode import QRcode
from flask_mail import Mail, Message
@ -40,8 +38,6 @@ app.config['BABEL_DEFAULT_LOCALE'] = 'de'
app.config['BABEL_DEFAULT_TIMEZONE'] = 'Europe/Berlin'
babel = Babel(app)
app.jinja_env.filters['quote_plus'] = lambda u: quote_plus(u)
# cors
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
@ -100,6 +96,7 @@ from views import (
organizer,
reference,
reference_request,
reference_request_review,
root,
user,
widget

View File

@ -3,6 +3,7 @@ from flask_wtf import FlaskForm
from wtforms import SelectField, StringField, SubmitField
from wtforms.validators import DataRequired
from .common import event_rating_choices
from models import EventReferenceRequestRejectionReason, EventReferenceRequestReviewStatus
class CreateEventReferenceRequestForm(FlaskForm):
admin_unit_id = SelectField(lazy_gettext('Admin unit'), validators=[DataRequired()], coerce=int)
@ -10,4 +11,20 @@ class CreateEventReferenceRequestForm(FlaskForm):
class DeleteReferenceRequestForm(FlaskForm):
submit = SubmitField(lazy_gettext("Delete request"))
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
class ReferenceRequestReviewForm(FlaskForm):
review_status = SelectField(lazy_gettext('Review status'), coerce=int, choices=[
(int(EventReferenceRequestReviewStatus.inbox), lazy_gettext('EventReferenceRequestReviewStatus.inbox')),
(int(EventReferenceRequestReviewStatus.verified), lazy_gettext('EventReferenceRequestReviewStatus.verified')),
(int(EventReferenceRequestReviewStatus.rejected), lazy_gettext('EventReferenceRequestReviewStatus.rejected'))])
rejection_reason = SelectField(lazy_gettext('Rejection reason'), coerce=int, choices=[
(0, ''),
(int(EventReferenceRequestRejectionReason.duplicate), lazy_gettext('EventReferenceRequestRejectionReason.duplicate')),
(int(EventReferenceRequestRejectionReason.untrustworthy), lazy_gettext('EventReferenceRequestRejectionReason.untrustworthy')),
(int(EventReferenceRequestRejectionReason.irrelevant), lazy_gettext('EventReferenceRequestRejectionReason.irrelevant')),
(int(EventReferenceRequestRejectionReason.illegal), lazy_gettext('EventReferenceRequestRejectionReason.illegal'))])
rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices)
submit = SubmitField(lazy_gettext("Save review"))

View File

@ -1,5 +1,6 @@
from app import app
from utils import get_event_category_name, get_localized_enum_name
from urllib.parse import quote_plus
import os
def env_override(value, key):
@ -7,4 +8,5 @@ def env_override(value, key):
app.jinja_env.filters['event_category_name'] = lambda u: get_event_category_name(u)
app.jinja_env.filters['loc_enum'] = lambda u: get_localized_enum_name(u)
app.jinja_env.filters['env_override'] = env_override
app.jinja_env.filters['env_override'] = env_override
app.jinja_env.filters['quote_plus'] = lambda u: quote_plus(u)

14
services/reference.py Normal file
View File

@ -0,0 +1,14 @@
from app import db
from models import EventReference, EventReferenceRequest
from sqlalchemy import and_, or_, not_
def create_event_reference_for_request(request):
result = EventReference.query.filter(and_(EventReference.event_id == request.event_id,
EventReference.admin_unit_id == request.admin_unit_id)).first()
if result is None:
result = EventReference(event_id = request.event_id,
admin_unit_id = request.admin_unit_id)
db.session.add(result)
return result

View File

@ -218,9 +218,9 @@
{% endif %}
{% endmacro %}
{% macro render_reference_review_status_pill(reference) %}
{% if reference.review_status and reference.review_status != 2 %}
<span class="badge badge-pill {% if reference.review_status == 1 %}badge-info{% else %}badge-danger{% endif %}">{{ reference.review_status | loc_enum }}</span>
{% macro render_reference_request_review_status_pill(reference_request) %}
{% if reference_request.review_status %}
<span class="badge badge-pill {% if reference_request.review_status == 1 %}badge-info{% elif reference_request.review_status == 2 %}badge-success{% else %}badge-danger{% endif %}">{{ reference_request.review_status | loc_enum }}</span>
{% endif %}
{% endmacro %}
@ -265,6 +265,11 @@
{{ render_enum_prop(event.rejection_resaon, 'fa-search-minus', 'Rejection reason') }}
{% endmacro %}
{% macro render_reference_request_review_status(reference_request) %}
{{ render_enum_prop(reference_request.review_status, 'fa-certificate', 'Review status') }}
{{ render_enum_prop(reference_request.rejection_reason, 'fa-search-minus', 'Rejection reason') }}
{% endmacro %}
{% macro render_event_props(event, start, end, dates = None, show_rating = False) %}
<div class="card mb-3">
<div class="card-header">
@ -476,8 +481,10 @@
<ul class="nav nav-pills">
{{ render_tab('reviews', _('Reviews'), url_for('manage_admin_unit_event_reviews', id=admin_unit.id), active_id) }}
{{ render_tab('events', _('Events'), url_for('manage_admin_unit_events', id=admin_unit.id), active_id) }}
{{ render_tab('references', _('References'), url_for('manage_admin_unit_references', id=admin_unit.id), active_id) }}
{{ render_tab('reference_requests', _('Reference requests'), url_for('manage_admin_unit_reference_requests', id=admin_unit.id), active_id) }}
{{ render_tab('references_incoming', _('Incoming references'), url_for('manage_admin_unit_references_incoming', id=admin_unit.id), active_id) }}
{{ render_tab('references_outgoing', _('Outgoing references'), url_for('manage_admin_unit_references_outgoing', id=admin_unit.id), active_id) }}
{{ render_tab('reference_requests_incoming', _('Incoming reference requests'), url_for('manage_admin_unit_reference_requests_incoming', id=admin_unit.id), active_id) }}
{{ render_tab('reference_requests_outgoing', _('Outgoing reference requests'), url_for('manage_admin_unit_reference_requests_outgoing', id=admin_unit.id), active_id) }}
{{ render_tab('organizers', _('Organizers'), url_for('manage_admin_unit_organizers', id=admin_unit.id), active_id) }}
{{ render_tab('places', _('Places'), url_for('manage_admin_unit_event_places', id=admin_unit.id), active_id) }}
{{ render_tab('members', _('Members'), url_for('manage_admin_unit_members', id=admin_unit.id), active_id) }}

View File

@ -0,0 +1,6 @@
{% extends "email/layout.html" %}
{% from "_macros.html" import render_email_button %}
{% block content %}
<p>{{ _('There is a new event reference request that needs to be reviewed.') }}</p>
{{ render_email_button(url_for('event_reference_request_review', id=request.id, _external=True), _('Click here to review the request')) }}
{% endblock %}

View File

@ -0,0 +1,3 @@
{{ _('There is a new event reference request that needs to be reviewed.') }}
{{ _('Click the link below to review the request') }}
{{ url_for('event_reference_request_review', id=request.id, _external=True) }}

View File

@ -0,0 +1,6 @@
{% extends "email/layout.html" %}
{% from "_macros.html" import render_email_button %}
{% block content %}
<p>{{ _('The review status of your event reference request has been updated.') }}</p>
{{ render_email_button(url_for('event_review_status', event_id=event.id, _external=True), _('Click here to view the status')) }}
{% endblock %}

View File

@ -0,0 +1,3 @@
{{ _('The review status of your event reference request has been updated.') }}
{{ _('Click the link below to view the status') }}
{{ url_for('event_review_status', event_id=event.id, _external=True) }}

View File

@ -18,7 +18,7 @@
<a class="btn btn-outline-primary my-1" href="{{ url_for('event_reference', event_id=event.id) }}" role="button"><i class="fa fa-link"></i> {{ _('Reference event') }}</a>
{% endif %}
{% if user_can_create_reference_request %}
<a class="btn btn-outline-primary my-1" href="{{ url_for('event_reference_request', event_id=event.id) }}" role="button"><i class="fa fa-link"></i> {{ _('Empfehlung anfragen') }}</a>
<a class="btn btn-outline-primary my-1" href="{{ url_for('event_reference_request_create', event_id=event.id) }}" role="button"><i class="fa fa-link"></i> {{ _('Empfehlung anfragen') }}</a>
{% endif %}
</div>
{% endif %}

View File

@ -1,5 +1,5 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_request_review_status_pill, render_event_status_pill, render_event_date, render_pagination, render_event_organizer, render_manage_menu %}
{% from "_macros.html" import render_reference_request_review_status_pill, render_event_status_pill, render_event_date, render_pagination, render_event_organizer, render_manage_menu %}
{% block title %}
{{ _('Reference requests') }}
{% endblock %}
@ -7,7 +7,7 @@
<h1>{{ admin_unit.name }}</h1>
{{ render_manage_menu(admin_unit, 'reference_requests') }}
{{ render_manage_menu(admin_unit, 'reference_requests_incoming') }}
<ul class="list-group mt-4">
{% for request in requests %}
@ -16,10 +16,10 @@
<div class="dropdown d-inline-block">
<button class="btn btn-link dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ request.event.name }}</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="url_for('event_reference_request_review', event_id=event.id)">{{ _('Review request') }}...</a>
<a class="dropdown-item" href="{{ url_for('event_reference_request_review', id=request.id) }}">{{ _('Review request') }}...</a>
</div>
</div>
{{ render_event_status_pill(request.event) }}
{{ render_reference_request_review_status_pill(request) }}
<small>{{ request.event.admin_unit.name }}</small>
</li>
{% endfor %}

View File

@ -0,0 +1,30 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_reference_request_review_status_pill, render_event_status_pill, render_event_date, render_pagination, render_event_organizer, render_manage_menu %}
{% block title %}
{{ _('Reference requests') }}
{% endblock %}
{% block content %}
<h1>{{ admin_unit.name }}</h1>
{{ render_manage_menu(admin_unit, 'reference_requests_outgoing') }}
<ul class="list-group mt-4">
{% for request in requests %}
<li class="list-group-item">
{{ render_event_date(request.event) }}
<div class="dropdown d-inline-block">
<button class="btn btn-link dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ request.event.name }}</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="{{ url_for('event_reference_request_review_status', id=request.id) }}">{{ _('Show review status') }}</a>
</div>
</div>
{{ render_reference_request_review_status_pill(request) }}
<small>{{ request.admin_unit.name }}</small>
</li>
{% endfor %}
</ul>
<div class="my-4">{{ render_pagination(pagination) }}</div>
{% endblock %}

View File

@ -1,5 +1,5 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_reference_review_status_pill, render_event_status_pill, render_event_date, render_pagination, render_event_organizer, render_manage_menu %}
{% from "_macros.html" import render_event_status_pill, render_event_date, render_pagination, render_event_organizer, render_manage_menu %}
{% block title %}
{{ _('References') }}
{% endblock %}
@ -7,7 +7,7 @@
<h1>{{ admin_unit.name }}</h1>
{{ render_manage_menu(admin_unit, 'references') }}
{{ render_manage_menu(admin_unit, 'references_incoming') }}
<ul class="list-group mt-4">
{% for reference in references %}

View File

@ -0,0 +1,30 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_event_status_pill, render_event_date, render_pagination, render_event_organizer, render_manage_menu %}
{% block title %}
{{ _('References') }}
{% endblock %}
{% block content %}
<h1>{{ admin_unit.name }}</h1>
{{ render_manage_menu(admin_unit, 'references_outgoing') }}
<ul class="list-group mt-4">
{% for reference in references %}
<li class="list-group-item">
{{ render_event_date(reference.event) }}
<div class="dropdown d-inline-block">
<button class="btn btn-link dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{ reference.event.name }}</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="{{ url_for('event', event_id=reference.event.id) }}">{{ _('View') }}</a>
</div>
</div>
{{ render_event_status_pill(reference.event) }}
<small>{{ reference.admin_unit.name }}</small>
</li>
{% endfor %}
</ul>
<div class="my-4">{{ render_pagination(pagination) }}</div>
{% endblock %}

View File

@ -0,0 +1,42 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_radio_buttons, render_phone_prop, render_email_prop, render_string_prop, render_field_with_errors, render_field, render_event_props, render_image_with_link, render_place, render_link_prop %}
{% block title %}
{{ event.name }}
{% endblock %}
{% block content %}
<h1>{{ _('Review event reference request') }}</h1>
<form action="" method="POST">
{{ form.hidden_tag() }}
{{ render_field_with_errors(form.review_status) }}
{{ render_field_with_errors(form.rejection_reason) }}
{% if form.rating.choices|length > 1 %}
{{ render_field_with_errors(form.rating) }}
{% endif %}
{{ render_field(form.submit) }}
</form>
<div class="mt-3" style="max-width: 768px;">
{{ render_event_props(event, event.start, event.end, dates) }}
{% if dates|length > 0 %}
<div class="card mt-4">
<div class="card-header">
<a name="event-dates">{{ _('Event Dates') }}</a>
</div>
<div class="list-group list-group-flush">
{% for date in dates %}
<a href="#" class="list-group-item">{{ date.start | datetimeformat('short') }}</a>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -0,0 +1,22 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_reference_request_review_status, render_event_props, render_image_with_link, render_place, render_link_prop %}
{% block title %}
{{ event.name }}
{% endblock %}
{% block content %}
<h1>{{ event.name }}</h1>
<div class="card mb-3">
<div class="card-header">
{{ _('Review status') }}
</div>
<div class="card-body">
{{ render_reference_request_review_status(reference_request) }}
{% if event.verified %}
<a href="{{ url_for('event', event_id=event.id) }}">{{ _('View event') }}</a>
{% endif %}
</div>
</div>
{% endblock %}

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@ from app import app
from flask import url_for, render_template, request, redirect
from flask_security import auth_required
from models import AdminUnitMemberInvitation
from sqlalchemy.exc import SQLAlchemyError
def update_admin_unit_with_form(admin_unit, form):
form.populate_obj(admin_unit)

View File

@ -7,6 +7,7 @@ from forms.admin_unit_member import DeleteAdminUnitMemberForm, UpdateAdminUnitMe
from .utils import permission_missing, send_mail, handleSqlError, flash_errors
from access import get_admin_unit_for_manage_or_404, has_access
from services.admin_unit import add_roles_to_admin_unit_member
from sqlalchemy.exc import SQLAlchemyError
@app.route('/manage/member/<int:id>/update', methods=('GET', 'POST'))
@auth_required()

View File

@ -7,6 +7,7 @@ from forms.admin_unit_member import NegotiateAdminUnitMemberInvitationForm, Invi
from .utils import permission_missing, send_mail, handleSqlError, flash_errors
from access import get_admin_unit_for_manage_or_404, has_access
from services.admin_unit import add_user_to_admin_unit_with_roles
from sqlalchemy.exc import SQLAlchemyError
@app.route('/invitations/<int:id>', methods=('GET', 'POST'))
@auth_required()

View File

@ -12,6 +12,7 @@ from utils import get_event_category_name
from services.event import upsert_event_category, update_event_dates_with_recurrence_rule
from services.organizer import get_event_places
from sqlalchemy.sql import asc, func
from sqlalchemy.exc import SQLAlchemyError
@app.route('/event/<int:event_id>')
def event(event_id):

View File

@ -7,6 +7,7 @@ from access import has_access, access_or_401, get_admin_unit_for_manage_or_404
from forms.event_place import UpdateEventPlaceForm, CreateEventPlaceForm
from .utils import flash_errors, upsert_image_with_data, send_mail
from sqlalchemy.sql import asc, func
from sqlalchemy.exc import SQLAlchemyError
@app.route('/manage/organizer/<int:id>/places/create', methods=('GET', 'POST'))
@auth_required()

View File

@ -7,6 +7,7 @@ from access import has_access, access_or_401, can_reference_event
from dateutils import today
from forms.event import ReviewEventForm
from .utils import flash_errors, send_mail
from sqlalchemy.exc import SQLAlchemyError
@app.route('/event/<int:event_id>/review', methods=('GET', 'POST'))
def event_review(event_id):

View File

@ -7,6 +7,7 @@ from access import has_access, access_or_401, get_admin_unit_for_manage_or_404
from forms.organizer import CreateOrganizerForm, UpdateOrganizerForm, DeleteOrganizerForm
from .utils import flash_errors, upsert_image_with_data, send_mail
from sqlalchemy.sql import asc, func
from sqlalchemy.exc import SQLAlchemyError
@app.route('/manage/admin_unit/<int:id>/organizers/create', methods=('GET', 'POST'))
@auth_required()

View File

@ -7,6 +7,8 @@ from flask_babelex import gettext
from flask_security import auth_required
from models import EventReference, Event
from access import access_or_401, can_reference_event
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.sql import desc
@app.route('/event/<int:event_id>/reference', methods=('GET', 'POST'))
def event_reference(event_id):
@ -52,7 +54,7 @@ def event_reference_update(id):
try:
db.session.commit()
flash(gettext('Reference successfully updated'), 'success')
return redirect(url_for('manage_admin_unit_references', id=reference.admin_unit_id))
return redirect(url_for('manage_admin_unit_references_incoming', id=reference.admin_unit_id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
@ -63,13 +65,24 @@ def event_reference_update(id):
form=form,
reference=reference)
@app.route('/manage/admin_unit/<int:id>/references')
@app.route('/manage/admin_unit/<int:id>/references/incoming')
@auth_required()
def manage_admin_unit_references(id):
def manage_admin_unit_references_incoming(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
references = EventReference.query.filter(EventReference.admin_unit_id == admin_unit.id).order_by(EventReference.created_at).paginate()
references = EventReference.query.filter(EventReference.admin_unit_id == admin_unit.id).order_by(desc(EventReference.created_at)).paginate()
return render_template('manage/references.html',
return render_template('manage/references_incoming.html',
admin_unit=admin_unit,
references=references.items,
pagination=get_pagination_urls(references, id=id))
@app.route('/manage/admin_unit/<int:id>/references/outgoing')
@auth_required()
def manage_admin_unit_references_outgoing(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
references = EventReference.query.join(Event).filter(Event.admin_unit_id == admin_unit.id).order_by(desc(EventReference.created_at)).paginate()
return render_template('manage/references_outgoing.html',
admin_unit=admin_unit,
references=references.items,
pagination=get_pagination_urls(references, id=id))
@ -89,7 +102,7 @@ def reference_delete(id):
db.session.delete(reference)
db.session.commit()
flash(gettext('Reference successfully deleted'), 'success')
return redirect(url_for('manage_admin_unit_references', id=reference.admin_unit_id))
return redirect(url_for('manage_admin_unit_references_incoming', id=reference.admin_unit_id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')

View File

@ -1,14 +1,39 @@
from app import app, db
from .utils import get_pagination_urls, flash_errors, handleSqlError
from .utils import get_pagination_urls, flash_errors, handleSqlError, send_mail
from forms.reference_request import CreateEventReferenceRequestForm, DeleteReferenceRequestForm
from flask import render_template, flash, redirect, url_for
from flask_babelex import gettext
from flask_security import auth_required
from models import EventReferenceRequest, Event, AdminUnit
from access import access_or_401, get_admin_unit_for_manage_or_404
from models import EventReferenceRequest, Event, AdminUnit, AdminUnitMember, User, EventReferenceRequestReviewStatus
from access import access_or_401, get_admin_unit_for_manage_or_404, has_admin_unit_member_permission
from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy import and_, or_, not_
from sqlalchemy.sql import desc
@app.route('/event/<int:event_id>/reference_request', methods=('GET', 'POST'))
def event_reference_request(event_id):
@app.route('/manage/admin_unit/<int:id>/reference_requests/incoming')
@auth_required()
def manage_admin_unit_reference_requests_incoming(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
requests = EventReferenceRequest.query.filter(and_(EventReferenceRequest.review_status != EventReferenceRequestReviewStatus.verified, EventReferenceRequest.admin_unit_id == admin_unit.id)).order_by(desc(EventReferenceRequest.created_at)).paginate()
return render_template('manage/reference_requests_incoming.html',
admin_unit=admin_unit,
requests=requests.items,
pagination=get_pagination_urls(requests, id=id))
@app.route('/manage/admin_unit/<int:id>/reference_requests/outgoing')
@auth_required()
def manage_admin_unit_reference_requests_outgoing(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
requests = EventReferenceRequest.query.join(Event).filter(Event.admin_unit_id == admin_unit.id).order_by(desc(EventReferenceRequest.created_at)).paginate()
return render_template('manage/reference_requests_outgoing.html',
admin_unit=admin_unit,
requests=requests.items,
pagination=get_pagination_urls(requests, id=id))
@app.route('/event/<int:event_id>/reference_request/create', methods=('GET', 'POST'))
def event_reference_request_create(event_id):
event = Event.query.get_or_404(event_id)
access_or_401(event.admin_unit, 'reference_request:create')
@ -17,12 +42,14 @@ def event_reference_request(event_id):
if form.validate_on_submit():
request = EventReferenceRequest()
request.review_status = EventReferenceRequestReviewStatus.inbox
form.populate_obj(request)
request.event = event
try:
db.session.add(request)
db.session.commit()
send_reference_request_inbox_mails(request)
flash(gettext('Request successfully created'), 'success')
return redirect(url_for('event', event_id=event.id))
except SQLAlchemyError as e:
@ -35,78 +62,13 @@ def event_reference_request(event_id):
form=form,
event=event)
@app.route('/manage/admin_unit/<int:id>/reference_requests')
@auth_required()
def manage_admin_unit_reference_requests(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
requests = EventReferenceRequest.query.filter(EventReferenceRequest.admin_unit_id == admin_unit.id).order_by(EventReferenceRequest.created_at).paginate()
def send_reference_request_inbox_mails(request):
# Benachrichtige alle Mitglieder der AdminUnit, die diesen Request verifizieren können
members = AdminUnitMember.query.join(User).filter(AdminUnitMember.admin_unit_id == request.admin_unit_id).all()
return render_template('manage/reference_requests.html',
admin_unit=admin_unit,
requests=requests.items,
pagination=get_pagination_urls(requests, id=id))
# @app.route('/reference_request/<int:id>/review', methods=('GET', 'POST'))
# def event_reference_request_review(id):
# request = EventReferenceRequest.query.get_or_404(id)
# event = Event.query.get_or_404(request.event_id)
# dates = EventDate.query.with_parent(event).filter(EventDate.start >= today).order_by(EventDate.start).all()
# user_can_verify_event = can_verify_event(event)
# if not user_can_verify_event:
# abort(401)
# form = ReviewEventForm(obj=event)
# if form.validate_on_submit():
# form.populate_obj(event)
# if event.review_status != EventReviewStatus.rejected:
# event.rejection_resaon = None
# if event.rejection_resaon == 0:
# event.rejection_resaon = None
# try:
# db.session.commit()
# send_event_review_status_mail(event)
# flash(gettext('Event successfully updated'), 'success')
# return redirect(url_for('manage_admin_unit_event_reviews', id=event.admin_unit_id))
# except SQLAlchemyError as e:
# db.session.rollback()
# flash(handleSqlError(e), 'danger')
# else:
# flash_errors(form)
# return render_template('event/review.html',
# form=form,
# dates=dates,
# event=event)
# @app.route('/reference/<int:id>/delete', methods=('GET', 'POST'))
# def reference_delete(id):
# reference = EventReference.query.get_or_404(id)
# if not can_delete_reference(reference):
# abort(401)
# form = DeleteReferenceForm()
# if form.validate_on_submit():
# if form.name.data != reference.event.name:
# flash(gettext('Entered name does not match event name'), 'danger')
# else:
# try:
# db.session.delete(reference)
# db.session.commit()
# flash(gettext('Reference successfully deleted'), 'success')
# return redirect(url_for('manage_admin_unit_references', id=reference.admin_unit_id))
# except SQLAlchemyError as e:
# db.session.rollback()
# flash(handleSqlError(e), 'danger')
# else:
# flash_errors(form)
# return render_template('reference/delete.html',
# form=form,
# reference=reference)
for member in members:
if has_admin_unit_member_permission(member, 'reference_request:verify'):
send_mail(member.user.email,
gettext('New reference request'),
'reference_request_notice',
request=request)

View File

@ -0,0 +1,78 @@
from app import app, db
from models import Event, EventDate, EventReferenceRequest, EventReferenceRequestReviewStatus, AdminUnitMember, User
from flask import render_template, flash, url_for, redirect
from flask_babelex import gettext
from flask_security import auth_required
from access import has_access, access_or_401, can_reference_event
from dateutils import today
from forms.reference_request import ReferenceRequestReviewForm
from .utils import flash_errors, send_mail
from services.reference import create_event_reference_for_request
from sqlalchemy.exc import SQLAlchemyError
@app.route('/reference_request/<int:id>/review', methods=('GET', 'POST'))
def event_reference_request_review(id):
request = EventReferenceRequest.query.get_or_404(id)
access_or_401(request.admin_unit, 'reference_request:verify')
if request.review_status == EventReferenceRequestReviewStatus.verified:
flash(gettext('Request already verified'), 'danger')
return redirect(url_for('manage_admin_unit_reference_requests_incoming', id=request.admin_unit_id))
form = ReferenceRequestReviewForm(obj=request)
if form.validate_on_submit():
form.populate_obj(request)
if request.review_status != EventReferenceRequestReviewStatus.rejected:
request.rejection_reason = None
if request.rejection_reason == 0:
request.rejection_reason = None
try:
if request.review_status == EventReferenceRequestReviewStatus.verified:
reference = create_event_reference_for_request(request)
reference.rating = form.rating.data
msg = gettext('Request successfully updated')
else:
msg = gettext('Reference successfully created')
db.session.commit()
send_reference_request_review_status_mails(request)
flash(msg, 'success')
return redirect(url_for('manage_admin_unit_reference_requests_incoming', id=request.admin_unit_id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
else:
flash_errors(form)
dates = EventDate.query.with_parent(request.event).filter(EventDate.start >= today).order_by(EventDate.start).all()
return render_template('reference_request/review.html',
form=form,
dates=dates,
request=request,
event=request.event)
@app.route('/reference_request/<int:id>/review_status')
def event_reference_request_review_status(id):
request = EventReferenceRequest.query.get_or_404(id)
if not has_access(request.admin_unit, 'reference_request:verify') and not has_access(request.event.admin_unit, 'reference_request:create'):
abort(401)
return render_template('reference_request/review_status.html',
reference_request=request,
event=request.event)
def send_reference_request_review_status_mails(request):
# Benachrichtige alle Mitglieder der AdminUnit, die diesen Request erstellt hatte
members = AdminUnitMember.query.join(User).filter(AdminUnitMember.admin_unit_id == request.event.admin_unit_id).all()
for member in members:
if has_admin_unit_member_permission(member, 'reference_request:create'):
send_mail(member.user.email,
gettext('Event review status updated'),
'reference_request_review_status_notice',
request=request)

View File

@ -67,4 +67,10 @@ def send_mails(recipients, subject, template, **context):
msg.recipients = recipients
msg.body = render_template("email/%s.txt" % template, **context)
msg.html = render_template("email/%s.html" % template, **context)
if not mail.default_sender:
print(msg.subject)
print(msg.body)
return
mail.send(msg)