"""Blueprint for Reference Signing Entity.""" from http import HTTPStatus from abacus_common_logic.constants.error import ERROR_ENTITY_DOES_NOT_EXIST from abacus_common_logic.views.item_view import ItemView from abacus_common_logic.views.list_view import ListView from common_apispec import doc, marshal_with, use_kwargs from common_apispec.views import MethodResource from flask import Blueprint, request from marshmallow import fields from owsrequest import flask_request from owsresponse import response from owsresponse.adaptors.flask import flaskify from abacus_contract.constants.error import ( ERROR_CODE_AUTHORIZATION, ERROR_INVALID_IDS, ERROR_TOO_MANY_DATALOADER_IDS, ) from abacus_contract.logic import ( reference_signing_entity as logic, ) from abacus_contract.models.reference_signing_entity import ReferenceSigningEntity from abacus_contract.schemas.reference_signing_entity import ( ReferenceSigningEntityDataloaderSchema, ReferenceSigningEntityListResponseSchema, ReferenceSigningEntitySchema, ) from abacus_contract.schemas.signing_entity_sap_profit_center import ( SigningEntitySapProfitCenterDataloaderSchema, ) from abacus_contract.utils.format_error import validation_error from abacus_contract.utils.request import get_optional_numeric_list_from_params from core.cache import cache_reference_data from core.config import Config reference_signing_entity_api = Blueprint('reference_signing_entity_api', __name__) class ReferenceSigningEntityItemView(ItemView, MethodResource): """View to get a reference_signing_entity by ID.""" model_class = ReferenceSigningEntity object_detail_schema = ReferenceSigningEntitySchema() @doc( description='Get a reference_signing_entity by reference_signing_entity_id', summary='GET a reference_signing_entity by ID', params={ 'object_id': { 'description': 'ID of the reference_signing_entity', }, }, ) @marshal_with( object_detail_schema, code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) @marshal_with( None, code=HTTPStatus.NOT_FOUND, description=HTTPStatus.NOT_FOUND.phrase, ) @cache_reference_data def get(self, object_id, **kwargs): """Get reference_signing_entity by ID.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, ) ) obj = self.model_class.get_by_id(object_id) if not obj or obj.deleted_at is not None or obj.deleted_by is not None: return flaskify( response.create_not_found_response( message=ERROR_ENTITY_DOES_NOT_EXIST.format( object_type='Reference Signing Entity', object_id=object_id ) ) ) return super().get(object_id, **kwargs) class ReferenceSigningEntityListView(ListView, MethodResource): """View to get a list of reference_signing_entity.""" model_class = ReferenceSigningEntity list_entry_schema = ReferenceSigningEntitySchema @doc( description='GET a list of reference signing entities', summary='GET a list of reference signing entities', ) @marshal_with( ReferenceSigningEntityListResponseSchema, code=HTTPStatus.OK, description=HTTPStatus.OK.phrase, ) @cache_reference_data def get(self): """Override base GET method.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, ) ) return flaskify(logic.get_reference_signing_entities(request.args)) reference_signing_entity_api.add_url_rule( '/reference-signing-entity//', methods=['GET'], view_func=ReferenceSigningEntityItemView.as_view('reference_signing_entity'), ) reference_signing_entity_api.add_url_rule( '/reference-signing-entities/', methods=['GET'], view_func=ReferenceSigningEntityListView.as_view('reference_signing_entities'), ) @reference_signing_entity_api.route( '/reference-signing-entity//reference-sap-profit-centers/', methods=['GET'], ) def list_sap_profit_centers_for_signing_entity(object_id: int): """GET SAP profit centers authorized for the given signing entity (live mappings). Powers the cascading dropdown on contract creation (user picks SE, then PC). """ access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, ) ) return flaskify( logic.list_sap_profit_centers_for_signing_entity( reference_signing_entity_id=object_id, search_term=request.args.get('search_term'), limit=request.args.get('limit'), offset=request.args.get('offset'), ) ) @reference_signing_entity_api.route( '/reference-signing-entity/reference-sap-profit-centers/dataloader', methods=['POST'], ) @doc( summary='Fetch SAP profit centers by signing entity IDs.', description='Retrieves a list of active SAP profit centers authorized for the provided signing entity IDs passed in the request body.', ) @marshal_with( SigningEntitySapProfitCenterDataloaderSchema(many=True), code=HTTPStatus.OK, description='A list of authorized SAP profit center mappings matching the provided IDs.', ) @marshal_with( None, code=HTTPStatus.BAD_REQUEST, description='Invalid request body payload or validation error.', ) @marshal_with( None, code=HTTPStatus.UNAUTHORIZED, description=HTTPStatus.UNAUTHORIZED.phrase, ) @marshal_with( None, code=HTTPStatus.INTERNAL_SERVER_ERROR, description='Internal server error.', ) def get_profit_centers_by_signing_entity_dataloader(): """GET SAP profit centers authorized for the given signing entities (live mappings).""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, ) ) try: signing_entity_ids = get_optional_numeric_list_from_params() except ValueError: return flaskify( validation_error(ERROR_INVALID_IDS.format(object='ReferenceSigningEntity')) ) return flaskify(logic.get_profit_centers_by_signing_entities(signing_entity_ids)) @reference_signing_entity_api.route( '/reference-signing-entities/dataloader', methods=['POST'], ) @doc( summary='Fetch signing entities by IDs.', description='Retrieves a list of signing entity ids passed in the request body.', ) @marshal_with( ReferenceSigningEntityDataloaderSchema(many=True), code=HTTPStatus.OK, description='A list of signing entities.', ) @marshal_with( None, code=HTTPStatus.BAD_REQUEST, description='Invalid request body payload or validation error.', ) @marshal_with( None, code=HTTPStatus.UNAUTHORIZED, description=HTTPStatus.UNAUTHORIZED.phrase, ) @marshal_with( None, code=HTTPStatus.INTERNAL_SERVER_ERROR, description='Internal server error.', ) def get_signing_entities_dataloader(): """GET signing entities for the given ids.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, ) ) try: signing_entity_ids = get_optional_numeric_list_from_params() except (ValueError, TypeError): return flaskify( validation_error(ERROR_INVALID_IDS.format(object='ReferenceSigningEntity')) ) if len(signing_entity_ids) > Config.OWS_BATCH_LIMIT: return flaskify( validation_error( ERROR_TOO_MANY_DATALOADER_IDS.format(limit=Config.OWS_BATCH_LIMIT) ) ) return flaskify(logic.get_signing_entities_by_ids(signing_entity_ids))