"""Blueprint for abacus event API.""" from abacus_common_logic.views.create_view import CreateView from abacus_common_logic.views.item_view import ItemView from abacus_common_logic.views.list_view import ListView from flask import Blueprint, request from owsresponse import response from owsresponse.adaptors.flask import flaskify from abacus_event.constants import error from abacus_event.constants.constants import DATALOADER_BATCH_LIMIT from abacus_event.logic import abacus_event as logic from abacus_event.models.abacus_event import AbacusEvent from abacus_event.schemas.abacus_event import AbacusEventSchema, RetryEventsSchema from abacus_event.utils.format_error import validation_error from abacus_event.utils.request import ( get_optional_numeric_list_from_params, validate_payload, ) abacus_event_api = Blueprint('abacus_event_api', __name__) class AbacusEventCreate(CreateView): """POST abacus event.""" post_schema = AbacusEventSchema( exclude=( 'abacus_event_id', 'created_by', ) ) def create_handler(self, **params): """Create abacus event.""" return response.Response(message=logic.create_event(**params), status=201) class AbacusEventItemView(ItemView): """Abacus event item view.""" model_class = AbacusEvent object_detail_schema = AbacusEventSchema() class AbacusEventDataloader(ListView): """View for events dataloader.""" model_class = AbacusEvent list_entry_schema = AbacusEventSchema() def post(self): """Get events by ids. NOTE: This endpoint uses a POST method to allow for a larger list of query args. """ try: event_ids = get_optional_numeric_list_from_params() if not event_ids: return flaskify( validation_error( error.ERROR_INVALID_IDS.format(object='AbacusEvent') ) ) except ValueError: return flaskify( validation_error(error.ERROR_INVALID_IDS.format(object='AbacusEvent')) ) return flaskify(logic.dataload_events_by_ids(event_ids)) abacus_event_api.add_url_rule( '/abacus-event', methods=['POST'], view_func=AbacusEventCreate.as_view('create_abacus_event'), ) abacus_event_api.add_url_rule( '/abacus-event/', methods=['GET'], view_func=AbacusEventItemView.as_view('abacus_event_item_view'), ) abacus_event_api.add_url_rule( '/abacus-event/dataloader', methods=['POST'], view_func=AbacusEventDataloader.as_view('abacus_event_dataloader'), ) @abacus_event_api.route( '/abacus-event/payment-group-payment//approval-count/', methods=['GET'], ) def get_payment_groups_approval_count(payment_group_payment_id): """Endpoint to GET payment group's approval count.""" message = logic.get_payment_approval_count(payment_group_payment_id) return flaskify(response.Response(message=message)) @abacus_event_api.route('/abacus-event/rollback/', methods=['PUT']) def rollback_events(): """Endpoint to rollback specified events.""" request_data = request.get_json() target_type = request_data['target_type'] target_id = request_data['target_id'] event_name = request_data['event_name'] return flaskify( response.Response( message=logic.update_rollback_time(target_type, target_id, event_name) ) ) @abacus_event_api.route('/abacus-event/retry/', methods=['PUT']) def retry_events(): """Endpoint to retry specified events.""" request_data = request.get_json() payload = validate_payload(request_data, RetryEventsSchema) return flaskify(response.Response(message=logic.retry_events(**payload))) @abacus_event_api.route( '/abacus-event//', methods=['GET'] ) def get_events_by_target_type(target_type, target_id): """Endpoint to GET event records for a specified target type and target ID.""" target_type = target_type.replace('-', '_') return flaskify( response.Response( message=logic.get_events_by_target_type(target_type, target_id) ) ) @abacus_event_api.route( '/abacus-event//dataloader', methods=['POST'] ) def dataload_events_by_target(target_type): """Batch active events for one target type across many target ids. POST so a large id list fits in the body. Body is a raw JSON array of target ids; the response is one entry per requested id in order (the /dataloader convention). No per-route access guard: access is enforced globally via access_rules.yml, matching the sibling /abacus-event/dataloader route. """ target_type = target_type.replace('-', '_') try: target_ids = get_optional_numeric_list_from_params() if not target_ids: return flaskify( validation_error(error.ERROR_INVALID_IDS.format(object='AbacusEvent')) ) except (ValueError, TypeError): return flaskify( validation_error(error.ERROR_INVALID_IDS.format(object='AbacusEvent')) ) if len(target_ids) > DATALOADER_BATCH_LIMIT: return flaskify( validation_error( error.ERROR_TOO_MANY_DATALOADER_IDS.format(limit=DATALOADER_BATCH_LIMIT) ) ) return flaskify(logic.dataload_events_by_target(target_type, target_ids))