Adjust organization choice when creating reference request #497

This commit is contained in:
Daniel Grams 2023-06-17 15:06:32 +02:00
parent d2b6a080bb
commit f9faf45297
7 changed files with 172 additions and 71 deletions

View File

@ -4,9 +4,9 @@ from flask_login import login_user
from flask_principal import Permission, RoleNeed
from flask_security import current_user
from flask_security.utils import FsPermNeed
from sqlalchemy import and_
from sqlalchemy import and_, exists
from project import app
from project import app, db
from project.models import AdminUnit, AdminUnitMember, Event, PublicStatus, User
from project.models.admin_unit import AdminUnitMemberRole
from project.services.admin_unit import get_member_for_admin_unit_by_user_id
@ -145,16 +145,16 @@ def can_request_event_reference(event):
if event.public_status != PublicStatus.published:
return False
return len(get_admin_units_for_event_reference_request(event)) > 0
def get_admin_units_for_event_reference_request(event):
return AdminUnit.query.filter(
and_(
AdminUnit.id != event.admin_unit_id,
AdminUnit.incoming_reference_requests_allowed,
return db.session.scalar(
exists()
.where(
and_(
AdminUnit.id != event.admin_unit_id,
AdminUnit.incoming_reference_requests_allowed,
)
)
).all()
.select()
)
def admin_units_the_current_user_is_member_of():

View File

@ -93,7 +93,7 @@ from project.services.reference import (
get_reference_outgoing_query,
get_relation_outgoing_query,
)
from project.views.utils import send_mail
from project.views.utils import get_current_admin_unit_for_api, send_mail
class OrganizationResource(BaseResource):
@ -224,8 +224,19 @@ class OrganizationListResource(BaseResource):
login_api_user()
include_unverified = can_verify_admin_unit()
reference_request_for_admin_unit_id = None
pagination = get_admin_unit_query(keyword, include_unverified).paginate()
if "for_reference_request" in request.args:
admin_unit = get_current_admin_unit_for_api()
if admin_unit:
reference_request_for_admin_unit_id = admin_unit.id
pagination = get_admin_unit_query(
keyword,
include_unverified,
reference_request_for_admin_unit_id=reference_request_for_admin_unit_id,
).paginate()
return pagination

View File

@ -20,6 +20,10 @@ from project.models import (
)
from project.services.image import upsert_image_with_data
from project.services.location import assign_location_values
from project.services.reference import (
get_newest_reference_requests,
get_newest_references,
)
def insert_admin_unit_for_user(admin_unit, user, invitation=None):
@ -175,6 +179,7 @@ def get_admin_unit_query(
keyword=None,
include_unverified=False,
only_verifier=False,
reference_request_for_admin_unit_id=None,
):
query = AdminUnit.query
@ -187,6 +192,13 @@ def get_admin_unit_query(
)
query = query.filter(only_verifier_filter)
if reference_request_for_admin_unit_id:
request_filter = and_(
AdminUnit.id != reference_request_for_admin_unit_id,
AdminUnit.incoming_reference_requests_allowed,
)
query = query.filter(request_filter)
if keyword:
like_keyword = "%" + keyword + "%"
order_keyword = keyword + "%"
@ -384,3 +396,49 @@ def get_admin_units_with_due_delete_request():
def delete_admin_unit(admin_unit: AdminUnit):
db.session.delete(admin_unit)
db.session.commit()
def get_admin_unit_suggestions_for_reference_requests(admin_unit, max_choices=5):
admin_unit_ids = []
admin_unit_choices = []
selected_ids = []
def add_admin_units(admin_units, selected=True):
for admin_unit in admin_units:
if admin_unit.id in admin_unit_ids:
continue
admin_unit_ids.append(admin_unit.id)
admin_unit_choices.append(admin_unit)
if selected:
selected_ids.append(admin_unit.id)
# Neuste ausgehende Empfehlungsanfragen
limit = max_choices - len(admin_unit_ids)
reference_requests = get_newest_reference_requests(admin_unit.id, limit)
add_admin_units([r.admin_unit for r in reference_requests])
# Neuste ausgehende Empfehlungen
limit = max_choices - len(admin_unit_ids)
if limit > 0:
references = get_newest_references(admin_unit.id, limit)
add_admin_units([r.admin_unit for r in references])
# Eingehende Beziehungen, die Organisation oder Events automatisch verifizieren
limit = max_choices - len(admin_unit_ids)
if limit > 0:
relations = get_admin_unit_relations_for_reference_requests(
admin_unit.id, limit
)
add_admin_units([r.source_admin_unit for r in relations])
# Organisationen, die eingehende Empfehlungsanfragen erlauben
limit = max_choices - len(admin_unit_ids)
if limit > 0:
admin_units_for_reference = get_admin_units_for_reference_requests(
admin_unit.id, limit
)
add_admin_units(admin_units_for_reference, False)
return (admin_unit_choices, selected_ids)

View File

@ -1,8 +1,57 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_field_with_errors, render_field %}
{% from "_macros.html" import render_field_with_errors, render_field, render_form_styles, render_form_scripts %}
{%- block title -%}
{{ event.name }}
{%- endblock -%}
{% block styles %}
{{ render_form_styles() }}
{% endblock %}
{% block header_before_site_js %}
{{ render_form_scripts() }}
{%- endblock -%}
{% block header %}
<script>
$(function() {
$('#admin_unit_id').select2({
width: '100%',
theme: 'bootstrap4',
ajax: {
url: function (params) {
return '/api/v1/organizations?for_reference_request=1';
},
dataType: 'json',
headers: {"X-OrganizationId": "{{ current_admin_unit.id }}"},
delay: 250,
cache: true,
data: function (params) {
return {
name: params.term,
per_page: 5,
page: params.page || 1
};
},
processResults: function (data) {
return {
results: data.items.map(p => ({"id": p.id, "text": p.name})),
pagination: {
more: data.has_next
}
};
}
},
placeholder: "{{ _('Enter organization') }}",
allowClear: false
});
});
</script>
{% endblock %}
{% block content %}
<h1>{{ _('Request reference for event "%(name)s"', name=event.name) }}</h1>

View File

@ -31,8 +31,7 @@ from project.models import (
)
from project.models.event_reference_request import EventReferenceRequest
from project.services.admin_unit import (
get_admin_unit_relations_for_reference_requests,
get_admin_units_for_reference_requests,
get_admin_unit_suggestions_for_reference_requests,
)
from project.services.event import (
create_ical_events_for_event,
@ -44,10 +43,6 @@ from project.services.event import (
update_event,
upsert_event_category,
)
from project.services.reference import (
get_newest_reference_requests,
get_newest_references,
)
from project.utils import get_event_category_name, get_place_str
from project.views.event_suggestion import send_event_suggestion_review_status_mail
from project.views.reference_request import handle_request_according_to_relation
@ -119,48 +114,10 @@ def prepare_form_reference_requests(form, admin_unit):
form.reference_request_admin_unit_id.choices = []
return
max_choices = 5
admin_unit_ids = []
admin_unit_choices = []
selected_ids = []
def add_admin_units(admin_units, selected=True):
for admin_unit in admin_units:
if admin_unit.id in admin_unit_ids:
continue
admin_unit_ids.append(admin_unit.id)
admin_unit_choices.append(admin_unit)
if selected:
selected_ids.append(admin_unit.id)
# Neuste ausgehende Empfehlungsanfragen
limit = max_choices - len(admin_unit_ids)
reference_requests = get_newest_reference_requests(admin_unit.id, limit)
add_admin_units([r.admin_unit for r in reference_requests])
# Neuste ausgehende Empfehlungen
limit = max_choices - len(admin_unit_ids)
if limit > 0:
references = get_newest_references(admin_unit.id, limit)
add_admin_units([r.admin_unit for r in references])
# Eingehende Beziehungen, die Organisation oder Events automatisch verifizieren
limit = max_choices - len(admin_unit_ids)
if limit > 0:
relations = get_admin_unit_relations_for_reference_requests(
admin_unit.id, limit
)
add_admin_units([r.source_admin_unit for r in relations])
# Organisationen, die eingehende Empfehlungsanfragen erlauben
limit = max_choices - len(admin_unit_ids)
if limit > 0:
admin_units_for_reference = get_admin_units_for_reference_requests(
admin_unit.id, limit
)
add_admin_units(admin_units_for_reference, False)
(
admin_unit_choices,
selected_ids,
) = get_admin_unit_suggestions_for_reference_requests(admin_unit)
form.reference_request_admin_unit_id.choices = sorted(
[(a.id, a.name) for a in admin_unit_choices],

View File

@ -9,7 +9,6 @@ from project.access import (
can_request_event_reference,
get_admin_unit_for_manage_or_404,
get_admin_unit_members_with_permission,
get_admin_units_for_event_reference_request,
)
from project.forms.reference_request import CreateEventReferenceRequestForm
from project.models import (
@ -17,7 +16,11 @@ from project.models import (
EventReferenceRequest,
EventReferenceRequestReviewStatus,
)
from project.services.admin_unit import get_admin_unit_by_id, get_admin_unit_relation
from project.services.admin_unit import (
get_admin_unit_by_id,
get_admin_unit_relation,
get_admin_unit_suggestions_for_reference_requests,
)
from project.services.reference import (
create_event_reference_for_request,
get_reference_requests_incoming_query,
@ -76,13 +79,24 @@ def event_reference_request_create(event_id):
abort(401)
form = CreateEventReferenceRequestForm()
form.admin_unit_id.choices = sorted(
[
(admin_unit.id, admin_unit.name)
for admin_unit in get_admin_units_for_event_reference_request(event)
],
key=lambda admin_unit: admin_unit[1],
)
if form.admin_unit_id.data and form.admin_unit_id.data > 0:
admin_unit = get_admin_unit_by_id(form.admin_unit_id.data)
if admin_unit:
form.admin_unit_id.choices = [(admin_unit.id, admin_unit.name)]
if not form.admin_unit_id.choices:
(
admin_unit_choices,
selected_ids,
) = get_admin_unit_suggestions_for_reference_requests(
event.admin_unit, max_choices=1
)
form.admin_unit_id.choices = [(a.id, a.name) for a in admin_unit_choices]
form.admin_unit_id.data = (
admin_unit_choices[0].id if len(admin_unit_choices) > 0 else None
)
if form.validate_on_submit():
request = EventReferenceRequest()

View File

@ -23,6 +23,18 @@ def test_list(client, seeder: Seeder, utils: UtilActions):
utils.get_json_ok(url)
def test_list_for_reference_request(client, seeder: Seeder, utils: UtilActions):
user_id, admin_unit_id = seeder.setup_api_access()
other_user_id = seeder.create_user("other@test.de")
other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew")
url = utils.get_url("api_v1_organization_list", for_reference_request="1")
response = utils.get_json_ok(url, headers={"X-OrganizationId": str(admin_unit_id)})
assert len(response.json["items"]) == 2
assert response.json["items"][1]["id"] == other_admin_unit_id
def test_list_unverified(client, app, seeder: Seeder, utils: UtilActions):
user_id, verified_admin_unit_id = seeder.setup_base(
email="verified@test.de",