mirror of
https://github.com/lucaspalomodevelop/eventcally.git
synced 2026-03-13 00:07:22 +00:00
API: event-reference-requests #520
This commit is contained in:
parent
5a60801a78
commit
ea17578890
@ -133,6 +133,8 @@ scope_list = [
|
||||
"eventlist:write",
|
||||
"customwidget:write",
|
||||
"eventreference:write",
|
||||
"eventreferencerequest:read",
|
||||
"eventreferencerequest:write",
|
||||
]
|
||||
scopes = {k: get_localized_scope(k) for v, k in enumerate(scope_list)}
|
||||
|
||||
@ -220,6 +222,7 @@ import project.api.event_category.resources
|
||||
import project.api.event_date.resources
|
||||
import project.api.event_list.resources
|
||||
import project.api.event_reference.resources
|
||||
import project.api.event_reference_request.resources
|
||||
import project.api.organization.resources
|
||||
import project.api.organization_invitation.resources
|
||||
import project.api.organization_relation.resources
|
||||
|
||||
0
project/api/event_reference_request/__init__.py
Normal file
0
project/api/event_reference_request/__init__.py
Normal file
127
project/api/event_reference_request/resources.py
Normal file
127
project/api/event_reference_request/resources.py
Normal file
@ -0,0 +1,127 @@
|
||||
from flask import abort, make_response
|
||||
from flask_apispec import doc, marshal_with, use_kwargs
|
||||
from marshmallow import ValidationError
|
||||
|
||||
from project import db
|
||||
from project.access import access_or_401, has_access, login_api_user_or_401
|
||||
from project.api import add_api_resource
|
||||
from project.api.event_reference.schemas import EventReferenceIdSchema
|
||||
from project.api.event_reference_request.schemas import (
|
||||
EventReferenceRequestRejectRequestSchema,
|
||||
EventReferenceRequestSchema,
|
||||
EventReferenceRequestVerifyRequestSchema,
|
||||
)
|
||||
from project.api.resources import BaseResource, require_api_access
|
||||
from project.models import EventReferenceRequest
|
||||
from project.models.event_reference_request import EventReferenceRequestReviewStatus
|
||||
from project.services.reference import create_event_reference_for_request
|
||||
from project.views.reference_request_review import (
|
||||
send_reference_request_review_status_mails,
|
||||
)
|
||||
|
||||
|
||||
class EventReferenceRequestResource(BaseResource):
|
||||
@doc(summary="Get event reference request", tags=["Event Reference Requests"])
|
||||
@marshal_with(EventReferenceRequestSchema)
|
||||
@require_api_access("eventreferencerequest:read")
|
||||
def get(self, id):
|
||||
login_api_user_or_401()
|
||||
reference_request = EventReferenceRequest.query.get_or_404(id)
|
||||
|
||||
if not has_access(
|
||||
reference_request.event.admin_unit, "reference_request:read"
|
||||
) and not has_access(reference_request.admin_unit, "reference_request:verify"):
|
||||
abort(401)
|
||||
|
||||
return reference_request
|
||||
|
||||
@doc(
|
||||
summary="Delete reference request",
|
||||
tags=["Event Reference Requests"],
|
||||
)
|
||||
@marshal_with(None, 204)
|
||||
@require_api_access("eventreferencerequest:write")
|
||||
def delete(self, id):
|
||||
login_api_user_or_401()
|
||||
reference_request = EventReferenceRequest.query.get_or_404(id)
|
||||
access_or_401(reference_request.event.admin_unit, "reference_request:delete")
|
||||
|
||||
db.session.delete(reference_request)
|
||||
db.session.commit()
|
||||
|
||||
return make_response("", 204)
|
||||
|
||||
|
||||
class EventReferenceRequestVerifyResource(BaseResource):
|
||||
@doc(
|
||||
summary="Verify event reference request. Returns reference id.",
|
||||
tags=["Event Reference Requests"],
|
||||
)
|
||||
@use_kwargs(EventReferenceRequestVerifyRequestSchema, location="json", apply=True)
|
||||
@marshal_with(EventReferenceIdSchema, 201)
|
||||
@require_api_access("eventreferencerequest:write")
|
||||
def post(self, id, **kwargs):
|
||||
login_api_user_or_401()
|
||||
reference_request = EventReferenceRequest.query.get_or_404(id)
|
||||
access_or_401(reference_request.admin_unit, "reference_request:verify")
|
||||
|
||||
if (
|
||||
reference_request.review_status
|
||||
== EventReferenceRequestReviewStatus.verified
|
||||
): # pragma: no cover
|
||||
raise ValidationError("Request already verified")
|
||||
|
||||
reference_request.review_status = EventReferenceRequestReviewStatus.verified
|
||||
|
||||
reference = create_event_reference_for_request(reference_request)
|
||||
reference.rating = kwargs.get("rating", reference.rating)
|
||||
db.session.commit()
|
||||
|
||||
send_reference_request_review_status_mails(reference_request)
|
||||
|
||||
return reference, 201
|
||||
|
||||
|
||||
class EventReferenceRequestRejectResource(BaseResource):
|
||||
@doc(
|
||||
summary="Reject event reference request",
|
||||
tags=["Event Reference Requests"],
|
||||
)
|
||||
@use_kwargs(EventReferenceRequestRejectRequestSchema, location="json", apply=False)
|
||||
@marshal_with(None, 204)
|
||||
@require_api_access("eventreferencerequest:write")
|
||||
def post(self, id):
|
||||
login_api_user_or_401()
|
||||
reference_request = EventReferenceRequest.query.get_or_404(id)
|
||||
access_or_401(reference_request.admin_unit, "reference_request:verify")
|
||||
|
||||
if (
|
||||
reference_request.review_status
|
||||
== EventReferenceRequestReviewStatus.verified
|
||||
): # pragma: no cover
|
||||
raise ValidationError("Request already verified")
|
||||
|
||||
reference_request = self.update_instance(
|
||||
EventReferenceRequestRejectRequestSchema, instance=reference_request
|
||||
)
|
||||
reference_request.review_status = EventReferenceRequestReviewStatus.rejected
|
||||
db.session.commit()
|
||||
|
||||
return make_response("", 204)
|
||||
|
||||
|
||||
add_api_resource(
|
||||
EventReferenceRequestResource,
|
||||
"/event-reference-requests/<int:id>",
|
||||
"api_v1_event_reference_request",
|
||||
)
|
||||
add_api_resource(
|
||||
EventReferenceRequestVerifyResource,
|
||||
"/event-reference-requests/<int:id>/verify",
|
||||
"api_v1_event_reference_request_verify",
|
||||
)
|
||||
add_api_resource(
|
||||
EventReferenceRequestRejectResource,
|
||||
"/event-reference-requests/<int:id>/reject",
|
||||
"api_v1_event_reference_request_reject",
|
||||
)
|
||||
126
project/api/event_reference_request/schemas.py
Normal file
126
project/api/event_reference_request/schemas.py
Normal file
@ -0,0 +1,126 @@
|
||||
from marshmallow import fields, validate
|
||||
from marshmallow_enum import EnumField
|
||||
|
||||
from project.api import marshmallow
|
||||
from project.api.event.schemas import EventRefSchema, EventWriteIdSchema
|
||||
from project.api.organization.schemas import (
|
||||
OrganizationRefSchema,
|
||||
OrganizationWriteIdSchema,
|
||||
)
|
||||
from project.api.schemas import (
|
||||
IdSchemaMixin,
|
||||
PaginationRequestSchema,
|
||||
PaginationResponseSchema,
|
||||
SQLAlchemyBaseSchema,
|
||||
TrackableRequestSchemaMixin,
|
||||
TrackableSchemaMixin,
|
||||
)
|
||||
from project.models import EventReferenceRequest
|
||||
from project.models.event_reference_request import (
|
||||
EventReferenceRequestRejectionReason,
|
||||
EventReferenceRequestReviewStatus,
|
||||
)
|
||||
|
||||
|
||||
class EventReferenceRequestModelSchema(SQLAlchemyBaseSchema):
|
||||
class Meta:
|
||||
model = EventReferenceRequest
|
||||
load_instance = True
|
||||
|
||||
|
||||
class EventReferenceRequestIdSchema(EventReferenceRequestModelSchema, IdSchemaMixin):
|
||||
pass
|
||||
|
||||
|
||||
class EventReferenceRequestBaseSchemaMixin(TrackableSchemaMixin):
|
||||
review_status = EnumField(
|
||||
EventReferenceRequestReviewStatus,
|
||||
load_default=EventReferenceRequestReviewStatus.inbox,
|
||||
)
|
||||
rejection_reason = EnumField(
|
||||
EventReferenceRequestRejectionReason,
|
||||
)
|
||||
|
||||
|
||||
class EventReferenceRequestRefSchema(
|
||||
EventReferenceRequestIdSchema, TrackableSchemaMixin
|
||||
):
|
||||
event = fields.Nested(EventRefSchema)
|
||||
|
||||
|
||||
class EventReferenceRequestSchema(
|
||||
EventReferenceRequestIdSchema, EventReferenceRequestBaseSchemaMixin
|
||||
):
|
||||
event = fields.Nested(EventRefSchema)
|
||||
organization = fields.Nested(OrganizationRefSchema, attribute="admin_unit")
|
||||
|
||||
|
||||
class EventReferenceRequestDumpSchema(EventReferenceRequestIdSchema):
|
||||
event_id = marshmallow.auto_field()
|
||||
organization_id = fields.Int(attribute="admin_unit_id")
|
||||
|
||||
|
||||
class EventReferenceRequestListRequestSchema(
|
||||
PaginationRequestSchema, TrackableRequestSchemaMixin
|
||||
):
|
||||
sort = fields.Str(
|
||||
metadata={"description": "Sort result items."},
|
||||
validate=validate.OneOf(["-created_at", "-updated_at", "-last_modified_at"]),
|
||||
)
|
||||
|
||||
|
||||
class EventReferenceRequestListResponseSchema(PaginationResponseSchema):
|
||||
items = fields.List(
|
||||
fields.Nested(EventReferenceRequestRefSchema),
|
||||
metadata={"description": "Event reference requests"},
|
||||
)
|
||||
|
||||
|
||||
class EventReferenceRequestWriteSchemaMixin(object):
|
||||
event = fields.Nested(
|
||||
EventWriteIdSchema,
|
||||
required=True,
|
||||
metadata={"description": "Event to reference"},
|
||||
)
|
||||
target_organization = fields.Nested(
|
||||
OrganizationWriteIdSchema,
|
||||
attribute="admin_unit",
|
||||
required=True,
|
||||
metadata={"description": "Target organization."},
|
||||
)
|
||||
|
||||
|
||||
class EventReferenceRequestPostRequestSchema(
|
||||
EventReferenceRequestModelSchema,
|
||||
EventReferenceRequestWriteSchemaMixin,
|
||||
):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.make_post_schema()
|
||||
|
||||
|
||||
class EventReferenceRequestVerifyRequestSchema(SQLAlchemyBaseSchema):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.make_post_schema()
|
||||
|
||||
rating = fields.Int(
|
||||
load_default=50,
|
||||
dump_default=50,
|
||||
validate=validate.OneOf([0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]),
|
||||
metadata={
|
||||
"description": "How relevant the event is to your organization. 0 (Little relevant), 50 (Default), 100 (Highlight)."
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class EventReferenceRequestRejectRequestSchema(
|
||||
EventReferenceRequestModelSchema,
|
||||
):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.make_post_schema()
|
||||
|
||||
rejection_reason = EnumField(
|
||||
EventReferenceRequestRejectionReason,
|
||||
)
|
||||
@ -6,6 +6,7 @@ from sqlalchemy import and_
|
||||
from project import db
|
||||
from project.access import (
|
||||
access_or_401,
|
||||
can_request_event_reference,
|
||||
can_verify_admin_unit,
|
||||
get_admin_unit_for_manage_or_404,
|
||||
login_api_user,
|
||||
@ -45,6 +46,12 @@ from project.api.event_reference.schemas import (
|
||||
EventReferenceListRequestSchema,
|
||||
EventReferenceListResponseSchema,
|
||||
)
|
||||
from project.api.event_reference_request.schemas import (
|
||||
EventReferenceRequestIdSchema,
|
||||
EventReferenceRequestListRequestSchema,
|
||||
EventReferenceRequestListResponseSchema,
|
||||
EventReferenceRequestPostRequestSchema,
|
||||
)
|
||||
from project.api.organization.schemas import (
|
||||
OrganizationListRequestSchema,
|
||||
OrganizationListResponseSchema,
|
||||
@ -92,16 +99,23 @@ from project.services.importer.event_importer import EventImporter
|
||||
from project.services.reference import (
|
||||
get_reference_incoming_query,
|
||||
get_reference_outgoing_query,
|
||||
get_reference_requests_incoming_query,
|
||||
get_reference_requests_outgoing_query,
|
||||
get_relation_outgoing_query,
|
||||
)
|
||||
from project.services.search_params import (
|
||||
AdminUnitSearchParams,
|
||||
EventPlaceSearchParams,
|
||||
EventReferenceRequestSearchParams,
|
||||
EventReferenceSearchParams,
|
||||
EventSearchParams,
|
||||
OrganizerSearchParams,
|
||||
TrackableSearchParams,
|
||||
)
|
||||
from project.views.reference_request import (
|
||||
handle_request_according_to_relation,
|
||||
send_reference_request_mails,
|
||||
)
|
||||
from project.views.utils import get_current_admin_unit_for_api, send_mail_async
|
||||
|
||||
|
||||
@ -375,10 +389,78 @@ class OrganizationOutgoingEventReferenceListResource(BaseResource):
|
||||
def get(self, id, **kwargs):
|
||||
admin_unit = AdminUnit.query.get_or_404(id)
|
||||
|
||||
pagination = get_reference_outgoing_query(admin_unit).paginate()
|
||||
params = EventReferenceSearchParams()
|
||||
params.load_from_request(**kwargs)
|
||||
params.admin_unit_id = admin_unit.id
|
||||
pagination = get_reference_outgoing_query(params).paginate()
|
||||
return pagination
|
||||
|
||||
|
||||
class OrganizationIncomingEventReferenceRequestListResource(BaseResource):
|
||||
@doc(
|
||||
summary="List incoming event reference requests of organization",
|
||||
tags=["Organizations", "Event Reference Requests"],
|
||||
)
|
||||
@use_kwargs(EventReferenceRequestListRequestSchema, location=("query"))
|
||||
@marshal_with(EventReferenceRequestListResponseSchema)
|
||||
@require_api_access("eventreferencerequest:read")
|
||||
def get(self, id, **kwargs):
|
||||
login_api_user_or_401()
|
||||
admin_unit = get_admin_unit_for_manage_or_404(id)
|
||||
|
||||
params = EventReferenceRequestSearchParams()
|
||||
params.load_from_request(**kwargs)
|
||||
params.admin_unit_id = admin_unit.id
|
||||
pagination = get_reference_requests_incoming_query(params).paginate()
|
||||
return pagination
|
||||
|
||||
|
||||
class OrganizationOutgoingEventReferenceRequestListResource(BaseResource):
|
||||
@doc(
|
||||
summary="List outgoing event reference requests of organization",
|
||||
tags=["Organizations", "Event Reference Requests"],
|
||||
)
|
||||
@use_kwargs(EventReferenceRequestListRequestSchema, location=("query"))
|
||||
@marshal_with(EventReferenceRequestListResponseSchema)
|
||||
@require_api_access("eventreferencerequest:read")
|
||||
def get(self, id, **kwargs):
|
||||
login_api_user_or_401()
|
||||
admin_unit = get_admin_unit_for_manage_or_404(id)
|
||||
|
||||
params = EventReferenceRequestSearchParams()
|
||||
params.load_from_request(**kwargs)
|
||||
params.admin_unit_id = admin_unit.id
|
||||
pagination = get_reference_requests_outgoing_query(params).paginate()
|
||||
return pagination
|
||||
|
||||
@doc(
|
||||
summary="Add reference request",
|
||||
tags=["Organizations", "Event Reference Requests"],
|
||||
)
|
||||
@use_kwargs(EventReferenceRequestPostRequestSchema, location="json", apply=False)
|
||||
@marshal_with(EventReferenceRequestIdSchema, 201)
|
||||
@require_api_access("eventreferencerequest:write")
|
||||
def post(self, id):
|
||||
login_api_user_or_401()
|
||||
admin_unit = get_admin_unit_for_manage_or_404(id)
|
||||
|
||||
reference_request = self.create_instance(EventReferenceRequestPostRequestSchema)
|
||||
event = reference_request.event
|
||||
|
||||
if event.admin_unit_id != admin_unit.id:
|
||||
abort(404)
|
||||
|
||||
if not can_request_event_reference(event):
|
||||
abort(401)
|
||||
|
||||
db.session.add(reference_request)
|
||||
reference, _ = handle_request_according_to_relation(reference_request, event)
|
||||
db.session.commit()
|
||||
send_reference_request_mails(reference_request, reference)
|
||||
|
||||
return reference_request, 201
|
||||
|
||||
|
||||
class OrganizationOutgoingRelationListResource(BaseResource):
|
||||
@doc(
|
||||
summary="List outgoing relations of organization",
|
||||
@ -626,6 +708,18 @@ add_api_resource(
|
||||
"/organizations/<int:id>/event-references/outgoing",
|
||||
"api_v1_organization_outgoing_event_reference_list",
|
||||
)
|
||||
|
||||
add_api_resource(
|
||||
OrganizationIncomingEventReferenceRequestListResource,
|
||||
"/organizations/<int:id>/event-reference-requests/incoming",
|
||||
"api_v1_organization_incoming_event_reference_request_list",
|
||||
)
|
||||
add_api_resource(
|
||||
OrganizationOutgoingEventReferenceRequestListResource,
|
||||
"/organizations/<int:id>/event-reference-requests/outgoing",
|
||||
"api_v1_organization_outgoing_event_reference_request_list",
|
||||
)
|
||||
|
||||
add_api_resource(
|
||||
OrganizationOutgoingRelationListResource,
|
||||
"/organizations/<int:id>/relations/outgoing",
|
||||
|
||||
@ -66,4 +66,10 @@ class AdminUnitVerificationRequest(db.Model, TrackableMixin):
|
||||
@listens_for(AdminUnitVerificationRequest, "before_insert")
|
||||
@listens_for(AdminUnitVerificationRequest, "before_update")
|
||||
def before_saving_admin_unit_verification_request(mapper, connect, self):
|
||||
if self.review_status != AdminUnitVerificationRequestReviewStatus.rejected:
|
||||
self.rejection_reason = None
|
||||
|
||||
if self.rejection_reason == 0:
|
||||
self.rejection_reason = None
|
||||
|
||||
self.validate()
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
from enum import IntEnum
|
||||
|
||||
from sqlalchemy import Column, Integer, UniqueConstraint
|
||||
from sqlalchemy.event import listens_for
|
||||
from sqlalchemy.ext.hybrid import hybrid_property
|
||||
|
||||
from project import db
|
||||
@ -38,3 +39,13 @@ class EventReferenceRequest(db.Model, TrackableMixin):
|
||||
@hybrid_property
|
||||
def verified(self):
|
||||
return self.review_status == EventReferenceRequestReviewStatus.verified
|
||||
|
||||
|
||||
@listens_for(EventReferenceRequest, "before_insert")
|
||||
@listens_for(EventReferenceRequest, "before_update")
|
||||
def before_saving_event_reference_request(mapper, connect, self):
|
||||
if self.review_status != EventReferenceRequestReviewStatus.rejected:
|
||||
self.rejection_reason = None
|
||||
|
||||
if self.rejection_reason == 0:
|
||||
self.rejection_reason = None
|
||||
|
||||
@ -10,7 +10,10 @@ from project.models import (
|
||||
EventReferenceRequestReviewStatus,
|
||||
)
|
||||
from project.models.admin_unit import AdminUnit
|
||||
from project.services.search_params import EventReferenceSearchParams
|
||||
from project.services.search_params import (
|
||||
EventReferenceRequestSearchParams,
|
||||
EventReferenceSearchParams,
|
||||
)
|
||||
|
||||
|
||||
def create_event_reference_for_request(request):
|
||||
@ -49,22 +52,42 @@ def get_reference_incoming_query(params: EventReferenceSearchParams):
|
||||
return result
|
||||
|
||||
|
||||
def get_reference_outgoing_query(admin_unit):
|
||||
return (
|
||||
EventReference.query.join(Event)
|
||||
.filter(Event.admin_unit_id == admin_unit.id)
|
||||
.order_by(EventReference.created_at.desc())
|
||||
)
|
||||
def get_reference_outgoing_query(params: EventReferenceSearchParams):
|
||||
result = EventReference.query.join(Event)
|
||||
|
||||
if params.admin_unit_id:
|
||||
result = result.filter(Event.admin_unit_id == params.admin_unit_id)
|
||||
|
||||
result = params.get_trackable_query(result, EventReference)
|
||||
result = params.get_trackable_order_by(result, EventReference)
|
||||
result = result.order_by(EventReference.created_at.desc())
|
||||
return result
|
||||
|
||||
|
||||
def get_reference_requests_incoming_query(admin_unit):
|
||||
return EventReferenceRequest.query.filter(
|
||||
and_(
|
||||
EventReferenceRequest.review_status
|
||||
!= EventReferenceRequestReviewStatus.verified,
|
||||
EventReferenceRequest.admin_unit_id == admin_unit.id,
|
||||
def get_reference_requests_incoming_query(params: EventReferenceRequestSearchParams):
|
||||
result = EventReferenceRequest.query
|
||||
|
||||
if params.admin_unit_id:
|
||||
result = result.filter(
|
||||
EventReferenceRequest.admin_unit_id == params.admin_unit_id
|
||||
)
|
||||
)
|
||||
|
||||
result = params.get_trackable_query(result, EventReferenceRequest)
|
||||
result = params.get_trackable_order_by(result, EventReferenceRequest)
|
||||
result = result.order_by(EventReferenceRequest.created_at.desc())
|
||||
return result
|
||||
|
||||
|
||||
def get_reference_requests_outgoing_query(params: EventReferenceRequestSearchParams):
|
||||
result = EventReferenceRequest.query.join(Event)
|
||||
|
||||
if params.admin_unit_id:
|
||||
result = result.filter(Event.admin_unit_id == params.admin_unit_id)
|
||||
|
||||
result = params.get_trackable_query(result, EventReferenceRequest)
|
||||
result = params.get_trackable_order_by(result, EventReferenceRequest)
|
||||
result = result.order_by(EventReferenceRequest.created_at.desc())
|
||||
return result
|
||||
|
||||
|
||||
def get_reference_requests_incoming_badge_query(admin_unit):
|
||||
|
||||
@ -63,6 +63,13 @@ class EventReferenceSearchParams(TrackableSearchParams):
|
||||
self.admin_unit_id = None
|
||||
|
||||
|
||||
class EventReferenceRequestSearchParams(TrackableSearchParams):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.admin_unit_id = None
|
||||
self.review_status = None
|
||||
|
||||
|
||||
class AdminUnitSearchParams(TrackableSearchParams):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
@ -45,7 +45,10 @@ from project.services.event import (
|
||||
)
|
||||
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
|
||||
from project.views.reference_request import (
|
||||
handle_request_according_to_relation,
|
||||
send_reference_request_mails,
|
||||
)
|
||||
from project.views.utils import (
|
||||
flash_errors,
|
||||
flash_message,
|
||||
@ -222,8 +225,11 @@ def event_create_for_admin_unit_id(id):
|
||||
reference_request.event_id = event.id
|
||||
reference_request.admin_unit_id = target_admin_unit_id
|
||||
db.session.add(reference_request)
|
||||
msg = handle_request_according_to_relation(reference_request, event)
|
||||
reference, msg = handle_request_according_to_relation(
|
||||
reference_request, event
|
||||
)
|
||||
db.session.commit()
|
||||
send_reference_request_mails(reference_request, reference)
|
||||
flash(msg, "success")
|
||||
|
||||
return redirect(url_for("event_actions", event_id=event.id))
|
||||
|
||||
@ -128,7 +128,10 @@ def manage_admin_unit_references_incoming(id):
|
||||
@auth_required()
|
||||
def manage_admin_unit_references_outgoing(id):
|
||||
admin_unit = get_admin_unit_for_manage_or_404(id)
|
||||
references = get_reference_outgoing_query(admin_unit).paginate()
|
||||
|
||||
params = EventReferenceSearchParams()
|
||||
params.admin_unit_id = admin_unit.id
|
||||
references = get_reference_outgoing_query(params).paginate()
|
||||
|
||||
return render_template(
|
||||
"manage/references_outgoing.html",
|
||||
|
||||
@ -2,7 +2,6 @@ from flask import abort, flash, redirect, render_template, url_for
|
||||
from flask_babel import gettext
|
||||
from flask_security import auth_required
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.sql import desc
|
||||
|
||||
from project import app, db
|
||||
from project.access import (
|
||||
@ -16,6 +15,7 @@ from project.models import (
|
||||
EventReferenceRequest,
|
||||
EventReferenceRequestReviewStatus,
|
||||
)
|
||||
from project.models.event_reference import EventReference
|
||||
from project.services.admin_unit import (
|
||||
get_admin_unit_by_id,
|
||||
get_admin_unit_relation,
|
||||
@ -24,7 +24,9 @@ from project.services.admin_unit import (
|
||||
from project.services.reference import (
|
||||
create_event_reference_for_request,
|
||||
get_reference_requests_incoming_query,
|
||||
get_reference_requests_outgoing_query,
|
||||
)
|
||||
from project.services.search_params import EventReferenceRequestSearchParams
|
||||
from project.views.utils import (
|
||||
flash_errors,
|
||||
get_pagination_urls,
|
||||
@ -37,11 +39,10 @@ from project.views.utils import (
|
||||
@auth_required()
|
||||
def manage_admin_unit_reference_requests_incoming(id):
|
||||
admin_unit = get_admin_unit_for_manage_or_404(id)
|
||||
requests = (
|
||||
get_reference_requests_incoming_query(admin_unit)
|
||||
.order_by(desc(EventReferenceRequest.created_at))
|
||||
.paginate()
|
||||
)
|
||||
|
||||
params = EventReferenceRequestSearchParams()
|
||||
params.admin_unit_id = admin_unit.id
|
||||
requests = get_reference_requests_incoming_query(params).paginate()
|
||||
|
||||
return render_template(
|
||||
"manage/reference_requests_incoming.html",
|
||||
@ -55,12 +56,10 @@ def manage_admin_unit_reference_requests_incoming(id):
|
||||
@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()
|
||||
)
|
||||
|
||||
params = EventReferenceRequestSearchParams()
|
||||
params.admin_unit_id = admin_unit.id
|
||||
requests = get_reference_requests_outgoing_query(params).paginate()
|
||||
|
||||
return render_template(
|
||||
"manage/reference_requests_outgoing.html",
|
||||
@ -99,15 +98,18 @@ def event_reference_request_create(event_id):
|
||||
)
|
||||
|
||||
if form.validate_on_submit():
|
||||
request = EventReferenceRequest()
|
||||
form.populate_obj(request)
|
||||
request.event = event
|
||||
reference_request = EventReferenceRequest()
|
||||
form.populate_obj(reference_request)
|
||||
reference_request.event = event
|
||||
|
||||
try:
|
||||
db.session.add(request)
|
||||
db.session.add(reference_request)
|
||||
|
||||
msg = handle_request_according_to_relation(request, event)
|
||||
reference, msg = handle_request_according_to_relation(
|
||||
reference_request, event
|
||||
)
|
||||
db.session.commit()
|
||||
send_reference_request_mails(reference_request, reference)
|
||||
flash(msg, "success")
|
||||
return redirect(
|
||||
url_for(
|
||||
@ -127,30 +129,62 @@ def event_reference_request_create(event_id):
|
||||
def handle_request_according_to_relation(
|
||||
request: EventReferenceRequest, event: Event
|
||||
) -> str:
|
||||
admin_unit = get_admin_unit_by_id(request.admin_unit_id)
|
||||
relation = get_admin_unit_relation(request.admin_unit_id, event.admin_unit_id)
|
||||
admin_unit = (
|
||||
request.admin_unit
|
||||
if request.admin_unit
|
||||
else get_admin_unit_by_id(request.admin_unit_id)
|
||||
)
|
||||
relation = get_admin_unit_relation(admin_unit.id, event.admin_unit_id)
|
||||
auto_verify = relation and relation.auto_verify_event_reference_requests
|
||||
reference = None
|
||||
|
||||
if auto_verify:
|
||||
request.review_status = EventReferenceRequestReviewStatus.verified
|
||||
reference = create_event_reference_for_request(request)
|
||||
send_auto_reference_inbox_mails(reference)
|
||||
|
||||
msg = gettext(
|
||||
"%(organization)s accepted your reference request",
|
||||
organization=admin_unit.name,
|
||||
)
|
||||
else:
|
||||
request.review_status = EventReferenceRequestReviewStatus.inbox
|
||||
send_reference_request_inbox_mails(request)
|
||||
|
||||
msg = gettext(
|
||||
"Reference request to %(organization)s successfully created. You will be notified after the other organization reviews the event.",
|
||||
organization=admin_unit.name,
|
||||
)
|
||||
|
||||
return msg
|
||||
return reference, msg
|
||||
|
||||
|
||||
def send_member_reference_request_verify_mails(
|
||||
def send_reference_request_mails(
|
||||
request: EventReferenceRequest, reference: EventReference
|
||||
):
|
||||
if reference:
|
||||
_send_auto_reference_mails(reference)
|
||||
else:
|
||||
_send_reference_request_inbox_mails(request)
|
||||
|
||||
|
||||
def _send_reference_request_inbox_mails(request):
|
||||
_send_member_reference_request_verify_mails(
|
||||
request.admin_unit_id,
|
||||
gettext("New reference request"),
|
||||
"reference_request_notice",
|
||||
request=request,
|
||||
)
|
||||
|
||||
|
||||
def _send_auto_reference_mails(reference):
|
||||
_send_member_reference_request_verify_mails(
|
||||
reference.admin_unit_id,
|
||||
gettext("New reference automatically verified"),
|
||||
"reference_auto_verified_notice",
|
||||
reference=reference,
|
||||
)
|
||||
|
||||
|
||||
def _send_member_reference_request_verify_mails(
|
||||
admin_unit_id, subject, template, **context
|
||||
):
|
||||
# Benachrichtige alle Mitglieder der AdminUnit, die Requests verifizieren können
|
||||
@ -160,21 +194,3 @@ def send_member_reference_request_verify_mails(
|
||||
emails = list(map(lambda member: member.user.email, members))
|
||||
|
||||
send_mails_async(emails, subject, template, **context)
|
||||
|
||||
|
||||
def send_reference_request_inbox_mails(request):
|
||||
send_member_reference_request_verify_mails(
|
||||
request.admin_unit_id,
|
||||
gettext("New reference request"),
|
||||
"reference_request_notice",
|
||||
request=request,
|
||||
)
|
||||
|
||||
|
||||
def send_auto_reference_inbox_mails(reference):
|
||||
send_member_reference_request_verify_mails(
|
||||
reference.admin_unit_id,
|
||||
gettext("New reference automatically verified"),
|
||||
"reference_auto_verified_notice",
|
||||
reference=reference,
|
||||
)
|
||||
|
||||
@ -44,12 +44,6 @@ def event_reference_request_review(id):
|
||||
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)
|
||||
|
||||
@ -38,12 +38,6 @@ def admin_unit_verification_request_review(id):
|
||||
if form.validate_on_submit():
|
||||
form.populate_obj(request)
|
||||
|
||||
if request.review_status != AdminUnitVerificationRequestReviewStatus.rejected:
|
||||
request.rejection_reason = None
|
||||
|
||||
if request.rejection_reason == 0:
|
||||
request.rejection_reason = None
|
||||
|
||||
try:
|
||||
if (
|
||||
request.review_status
|
||||
|
||||
126
tests/api/test_event_reference_request.py
Normal file
126
tests/api/test_event_reference_request.py
Normal file
@ -0,0 +1,126 @@
|
||||
from tests.seeder import Seeder
|
||||
from tests.utils import UtilActions
|
||||
|
||||
|
||||
def test_read(client, seeder: Seeder, utils: UtilActions):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
(
|
||||
other_user_id,
|
||||
other_admin_unit_id,
|
||||
event_id,
|
||||
reference_request_id,
|
||||
) = seeder.create_outgoing_reference_request(admin_unit_id)
|
||||
|
||||
url = utils.get_url("api_v1_event_reference_request", id=reference_request_id)
|
||||
utils.get_json_ok(url)
|
||||
|
||||
|
||||
def test_read_noAccess(client, seeder: Seeder, utils: UtilActions):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
third_user_id = seeder.create_user("third@test.de")
|
||||
third_admin_unit_id = seeder.create_admin_unit(third_user_id, "Third Crew")
|
||||
(
|
||||
other_user_id,
|
||||
other_admin_unit_id,
|
||||
event_id,
|
||||
reference_request_id,
|
||||
) = seeder.create_outgoing_reference_request(third_admin_unit_id)
|
||||
|
||||
url = utils.get_url("api_v1_event_reference_request", id=reference_request_id)
|
||||
response = utils.get_json(url)
|
||||
utils.assert_response_unauthorized(response)
|
||||
|
||||
|
||||
def test_delete(client, app, db, seeder: Seeder, utils: UtilActions):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
(
|
||||
other_user_id,
|
||||
other_admin_unit_id,
|
||||
event_id,
|
||||
reference_request_id,
|
||||
) = seeder.create_outgoing_reference_request(admin_unit_id)
|
||||
|
||||
url = utils.get_url("api_v1_event_reference_request", id=reference_request_id)
|
||||
response = utils.delete(url)
|
||||
utils.assert_response_no_content(response)
|
||||
|
||||
with app.app_context():
|
||||
from project.models import EventReferenceRequest
|
||||
|
||||
reference = db.session.get(EventReferenceRequest, reference_request_id)
|
||||
assert reference is None
|
||||
|
||||
|
||||
def test_verify(client, app, db, seeder: Seeder, utils: UtilActions):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
(
|
||||
other_user_id,
|
||||
other_admin_unit_id,
|
||||
event_id,
|
||||
reference_request_id,
|
||||
) = seeder.create_incoming_reference_request(admin_unit_id)
|
||||
|
||||
url = utils.get_url(
|
||||
"api_v1_event_reference_request_verify", id=reference_request_id
|
||||
)
|
||||
data = {
|
||||
"rating": 70,
|
||||
}
|
||||
response = utils.post_json(url, data)
|
||||
utils.assert_response_created(response)
|
||||
assert "id" in response.json
|
||||
|
||||
with app.app_context():
|
||||
from project.models import (
|
||||
EventReference,
|
||||
EventReferenceRequest,
|
||||
EventReferenceRequestReviewStatus,
|
||||
)
|
||||
|
||||
reference_request = db.session.get(EventReferenceRequest, reference_request_id)
|
||||
assert (
|
||||
reference_request.review_status
|
||||
== EventReferenceRequestReviewStatus.verified
|
||||
)
|
||||
|
||||
reference = db.session.get(EventReference, int(response.json["id"]))
|
||||
assert reference is not None
|
||||
assert reference.admin_unit_id == admin_unit_id
|
||||
assert reference.event_id == event_id
|
||||
assert reference.rating == 70
|
||||
|
||||
|
||||
def test_reject(client, app, db, seeder: Seeder, utils: UtilActions):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
(
|
||||
other_user_id,
|
||||
other_admin_unit_id,
|
||||
event_id,
|
||||
reference_request_id,
|
||||
) = seeder.create_incoming_reference_request(admin_unit_id)
|
||||
|
||||
url = utils.get_url(
|
||||
"api_v1_event_reference_request_reject", id=reference_request_id
|
||||
)
|
||||
data = {
|
||||
"rejection_reason": "duplicate",
|
||||
}
|
||||
response = utils.post_json(url, data)
|
||||
utils.assert_response_no_content(response)
|
||||
|
||||
with app.app_context():
|
||||
from project.models import (
|
||||
EventReferenceRequest,
|
||||
EventReferenceRequestRejectionReason,
|
||||
EventReferenceRequestReviewStatus,
|
||||
)
|
||||
|
||||
reference_request = db.session.get(EventReferenceRequest, reference_request_id)
|
||||
assert (
|
||||
reference_request.review_status
|
||||
== EventReferenceRequestReviewStatus.rejected
|
||||
)
|
||||
assert (
|
||||
reference_request.rejection_reason
|
||||
== EventReferenceRequestRejectionReason.duplicate
|
||||
)
|
||||
@ -508,6 +508,160 @@ def test_references_outgoing(client, seeder: Seeder, utils: UtilActions):
|
||||
utils.get_json_ok(url)
|
||||
|
||||
|
||||
def test_reference_requests_incoming(client, seeder: Seeder, utils: UtilActions):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
seeder.create_incoming_reference_request(admin_unit_id)
|
||||
|
||||
url = utils.get_url(
|
||||
"api_v1_organization_incoming_event_reference_request_list",
|
||||
id=admin_unit_id,
|
||||
)
|
||||
utils.get_json_ok(url)
|
||||
|
||||
|
||||
def test_reference_requests_outgoing(client, seeder: Seeder, utils: UtilActions):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
seeder.create_outgoing_reference_request(admin_unit_id)
|
||||
|
||||
url = utils.get_url(
|
||||
"api_v1_organization_outgoing_event_reference_request_list",
|
||||
id=admin_unit_id,
|
||||
)
|
||||
utils.get_json_ok(url)
|
||||
|
||||
|
||||
def test_reference_requests_outgoing_post(
|
||||
client, app, seeder: Seeder, utils: UtilActions, db, mocker
|
||||
):
|
||||
mail_mock = utils.mock_send_mails_async(mocker)
|
||||
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")
|
||||
event_id = seeder.create_event(admin_unit_id)
|
||||
|
||||
url = utils.get_url(
|
||||
"api_v1_organization_outgoing_event_reference_request_list",
|
||||
id=admin_unit_id,
|
||||
)
|
||||
data = {
|
||||
"event": {"id": event_id},
|
||||
"target_organization": {"id": other_admin_unit_id},
|
||||
}
|
||||
|
||||
response = utils.post_json(url, data)
|
||||
utils.assert_response_created(response)
|
||||
assert "id" in response.json
|
||||
utils.assert_send_mail_called(mail_mock, "other@test.de")
|
||||
|
||||
with app.app_context():
|
||||
from project.models import (
|
||||
EventReferenceRequest,
|
||||
EventReferenceRequestReviewStatus,
|
||||
)
|
||||
|
||||
reference_request = db.session.get(
|
||||
EventReferenceRequest, int(response.json["id"])
|
||||
)
|
||||
assert reference_request is not None
|
||||
assert reference_request.admin_unit_id == other_admin_unit_id
|
||||
assert reference_request.event_id == event_id
|
||||
assert (
|
||||
reference_request.review_status == EventReferenceRequestReviewStatus.inbox
|
||||
)
|
||||
|
||||
|
||||
def test_reference_requests_outgoing_post_autoVerify(
|
||||
client, app, seeder: Seeder, utils: UtilActions, db, mocker
|
||||
):
|
||||
mail_mock = utils.mock_send_mails_async(mocker)
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
event_id = seeder.create_event(admin_unit_id)
|
||||
other_user_id = seeder.create_user("other@test.de")
|
||||
other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew")
|
||||
seeder.create_admin_unit_relation(other_admin_unit_id, admin_unit_id, True)
|
||||
|
||||
url = utils.get_url(
|
||||
"api_v1_organization_outgoing_event_reference_request_list",
|
||||
id=admin_unit_id,
|
||||
)
|
||||
data = {
|
||||
"event": {"id": event_id},
|
||||
"target_organization": {"id": other_admin_unit_id},
|
||||
}
|
||||
|
||||
response = utils.post_json(url, data)
|
||||
utils.assert_response_created(response)
|
||||
assert "id" in response.json
|
||||
utils.assert_send_mail_called(mail_mock, "other@test.de")
|
||||
|
||||
with app.app_context():
|
||||
from project.models import (
|
||||
EventReference,
|
||||
EventReferenceRequest,
|
||||
EventReferenceRequestReviewStatus,
|
||||
)
|
||||
|
||||
reference_request = db.session.get(
|
||||
EventReferenceRequest, int(response.json["id"])
|
||||
)
|
||||
assert reference_request is not None
|
||||
assert reference_request.admin_unit_id == other_admin_unit_id
|
||||
assert reference_request.event_id == event_id
|
||||
assert (
|
||||
reference_request.review_status
|
||||
== EventReferenceRequestReviewStatus.verified
|
||||
)
|
||||
|
||||
reference = (
|
||||
EventReference.query.filter(
|
||||
EventReference.admin_unit_id == other_admin_unit_id
|
||||
)
|
||||
.filter(EventReference.event_id == event_id)
|
||||
.first()
|
||||
)
|
||||
assert reference is not None
|
||||
|
||||
|
||||
def test_reference_requests_outgoing_post_foreignEvent(
|
||||
client, app, seeder: Seeder, utils: UtilActions, db
|
||||
):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
other_admin_unit_id = seeder.create_admin_unit(user_id, "Other Crew")
|
||||
event_id = seeder.create_event(other_admin_unit_id)
|
||||
|
||||
url = utils.get_url(
|
||||
"api_v1_organization_outgoing_event_reference_request_list",
|
||||
id=admin_unit_id,
|
||||
)
|
||||
data = {
|
||||
"event": {"id": event_id},
|
||||
"target_organization": {"id": other_admin_unit_id},
|
||||
}
|
||||
|
||||
response = utils.post_json(url, data)
|
||||
utils.assert_response_notFound(response)
|
||||
|
||||
|
||||
def test_reference_requests_outgoing_post_draft(
|
||||
client, app, seeder: Seeder, utils: UtilActions, db
|
||||
):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
other_admin_unit_id = seeder.create_admin_unit(user_id, "Other Crew")
|
||||
event_id = seeder.create_event(admin_unit_id, draft=True)
|
||||
|
||||
url = utils.get_url(
|
||||
"api_v1_organization_outgoing_event_reference_request_list",
|
||||
id=admin_unit_id,
|
||||
)
|
||||
data = {
|
||||
"event": {"id": event_id},
|
||||
"target_organization": {"id": other_admin_unit_id},
|
||||
}
|
||||
|
||||
response = utils.post_json(url, data)
|
||||
utils.assert_response_unauthorized(response)
|
||||
|
||||
|
||||
def test_outgoing_relation_read(client, seeder: Seeder, utils: UtilActions):
|
||||
user_id, admin_unit_id = seeder.setup_api_access()
|
||||
(
|
||||
|
||||
@ -758,6 +758,15 @@ class Seeder(object):
|
||||
reference_request_id = self.create_reference_request(event_id, admin_unit_id)
|
||||
return (other_user_id, other_admin_unit_id, event_id, reference_request_id)
|
||||
|
||||
def create_outgoing_reference_request(self, admin_unit_id):
|
||||
other_user_id = self.create_user("other@test.de")
|
||||
other_admin_unit_id = self.create_admin_unit(other_user_id, "Other Crew")
|
||||
event_id = self.create_event(admin_unit_id)
|
||||
reference_request_id = self.create_reference_request(
|
||||
event_id, other_admin_unit_id
|
||||
)
|
||||
return (other_user_id, other_admin_unit_id, event_id, reference_request_id)
|
||||
|
||||
def get_now_by_minute(self):
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
@ -157,11 +157,7 @@ def test_admin_unit_reference_requests_incoming(client, seeder, utils):
|
||||
|
||||
def test_admin_unit_reference_requests_outgoing(client, seeder, utils):
|
||||
user_id, admin_unit_id = seeder.setup_base()
|
||||
event_id = seeder.create_event(admin_unit_id)
|
||||
|
||||
other_user_id = seeder.create_user("other@test.de")
|
||||
other_admin_unit_id = seeder.create_admin_unit(other_user_id, "Other Crew")
|
||||
seeder.create_reference_request(event_id, other_admin_unit_id)
|
||||
seeder.create_outgoing_reference_request(admin_unit_id)
|
||||
|
||||
utils.get_endpoint_ok(
|
||||
"manage_admin_unit_reference_requests_outgoing", id=admin_unit_id
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user