"""Blueprint for Reference SAP Profit Center.""" from http import HTTPStatus from abacus_common_logic.views.create_view import CreateView from abacus_common_logic.views.item_view import ItemView from common_apispec import doc, marshal_with, use_kwargs from flask import Blueprint, request 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_CODE_FORBIDDEN, ERROR_INVALID_IDS, ERROR_MESSAGE_FORBIDDEN_USER, ) from abacus_contract.logic import reference_sap_profit_center as logic from abacus_contract.models.reference_sap_profit_center import ReferenceSapProfitCenter from abacus_contract.schemas.reference_sap_profit_center import ( ReferenceSapProfitCenterDataloaderSchema, ReferenceSapProfitCenterPostSchema, ReferenceSapProfitCenterPutSchema, ReferenceSapProfitCenterSchema, ) from abacus_contract.schemas.signing_entity_sap_profit_center import ( SapProfitCenterSigningEntityDataloaderSchema, ) from abacus_contract.utils.authorization import pdp_authorize_resource from abacus_contract.utils.format_error import validation_error from abacus_contract.utils.request import get_optional_numeric_list_from_params reference_sap_profit_center_api = Blueprint('reference_sap_profit_center_api', __name__) class ReferenceSapProfitCenterItemView(ItemView): """View for getting and updating an sap_profit_center by ID.""" model_class = ReferenceSapProfitCenter object_detail_schema = ReferenceSapProfitCenterSchema() put_schema = ReferenceSapProfitCenterPutSchema() def get(self, object_id, **kwargs): """Get sap_profit_center by ID.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: authorized = pdp_authorize_resource( object_id, 'reference_sap_profit_center' ) if not authorized: return flaskify( response.create_error_response( code=ERROR_CODE_FORBIDDEN, message=ERROR_MESSAGE_FORBIDDEN_USER, status=403, ) ) return super().get(object_id, **kwargs) def put(self, object_id, **kwargs): """Update sap_profit_center display_name (admin).""" 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 super().put(object_id, **kwargs) def update_handler(self, obj, **params): """Delegate to logic layer.""" return logic.update_reference_sap_profit_center(obj, **params) reference_sap_profit_center_api.add_url_rule( '/reference-sap-profit-center/', methods=['GET', 'PUT'], view_func=ReferenceSapProfitCenterItemView.as_view('reference_sap_profit_center'), ) @reference_sap_profit_center_api.route( '/reference-sap-profit-center//signing-entities/', methods=['GET'] ) def list_signing_entities_for_sap_profit_center(object_id: int): """GET signing entities authorized for the given profit center (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_FORBIDDEN, message=ERROR_MESSAGE_FORBIDDEN_USER, status=403, ) ) return flaskify( logic.list_signing_entities_for_sap_profit_center( reference_sap_profit_center_id=object_id, search_term=request.args.get('search_term'), limit=request.args.get('limit'), offset=request.args.get('offset'), ) ) @reference_sap_profit_center_api.route('/reference-sap-profit-centers', methods=['GET']) @doc( summary='Get the list of SAP profit centers.', description='Retrieves a paginated list of SAP profit centers.', params={ # Query Parameters (Pagination) 'limit': { 'in': 'query', 'description': 'The maximum number of records to return per page.', 'type': 'integer', 'default': 100, }, 'offset': { 'in': 'query', 'description': 'The number of records to skip before starting to return results.', 'type': 'integer', 'default': 0, }, # Sorting 'sort_by': { 'in': 'query', 'description': 'The column name used to sort the results.', 'type': 'string', }, 'sort_order': { 'in': 'query', 'description': 'The sort direction; must be either "asc" or "desc".', 'type': 'string', }, # Filters 'search_term': { 'in': 'query', 'description': 'Free-text search query matched against display_name and profit_center.', 'type': 'string', }, 'orphan': { 'in': 'query', 'description': 'If true, filters results to only return records that lack an active mapping/junction entry.', 'type': 'boolean', 'default': False, }, 'signing_entity_ids': { 'in': 'query', 'description': 'Comma separated signing entity ids', 'type': 'string', }, }, ) @marshal_with( ReferenceSapProfitCenterSchema(many=True), code=HTTPStatus.OK, description='the list of reference-sap-profit-centers', ) @marshal_with( None, code=HTTPStatus.BAD_REQUEST, description='Invalid query parameter syntax 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_reference_sap_profit_centers(): """GET endpoint for reference-sap-profit-centers.""" 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_sap_profit_centers(request.args)) @reference_sap_profit_center_api.route( '/reference-sap-profit-center/reference-signing-entities/dataloader', methods=['POST'], ) @doc( summary='Fetch signing entities by SAP profit center IDs.', description='Retrieves a list of active signing entities authorized for the provided SAP profit center IDs passed in the request body.', ) @marshal_with( SapProfitCenterSigningEntityDataloaderSchema(many=True), code=HTTPStatus.OK, description='A list of authorized signing entity 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_signing_entities_by_profit_center_dataloader(): """GET signing entities authorized for the given SAP profit center IDs (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: sap_profit_center_ids = get_optional_numeric_list_from_params() except ValueError: return flaskify( validation_error( ERROR_INVALID_IDS.format(object='ReferenceSapProfitCenter') ) ) return flaskify(logic.get_signing_entities_by_profit_centers(sap_profit_center_ids)) @reference_sap_profit_center_api.route( '/reference-sap-profit-centers/dataloader', methods=['POST'], ) @doc( summary='Fetch SAP profit centers by IDs.', description='Retrieves a list of SAP profit centers for the IDs passed in the request body.', ) @marshal_with( ReferenceSapProfitCenterDataloaderSchema(many=True), code=HTTPStatus.OK, description='A list of SAP profit centers.', ) @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_sap_profit_centers_dataloader(): """GET SAP profit centers 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: sap_profit_center_ids = get_optional_numeric_list_from_params() except ValueError: return flaskify( validation_error( ERROR_INVALID_IDS.format(object='ReferenceSapProfitCenter') ) ) return flaskify(logic.get_sap_profit_centers_by_ids(sap_profit_center_ids)) class ReferenceSapProfitCenterCreateView(CreateView): """Handles reference_sap_profit_center creation.""" post_schema = ReferenceSapProfitCenterPostSchema() def post(self, **kwargs): """Create a reference sap profit center.""" 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 super().post(**kwargs) def create_handler(self, **params): """Handle reference_sap_profit_center creation.""" return logic.create_reference_sap_profit_center(**params) sap_profit_center_create_view = ReferenceSapProfitCenterCreateView.as_view( 'reference_sap_profit_center_create' ) sap_profit_center_create_view = doc( summary='Create a new Reference SAP Profit Center and map its associated Signing Entities.', )(sap_profit_center_create_view) sap_profit_center_create_view = use_kwargs( ReferenceSapProfitCenterPostSchema, location='json', required=True, apply=False )(sap_profit_center_create_view) sap_profit_center_create_view = marshal_with( ReferenceSapProfitCenterSchema, code=HTTPStatus.CREATED, description='Profit Center successfully created', )(sap_profit_center_create_view) sap_profit_center_create_view = marshal_with( None, code=HTTPStatus.BAD_REQUEST, description='Invalid request body or validation error', )(sap_profit_center_create_view) sap_profit_center_create_view = marshal_with( None, code=HTTPStatus.UNAUTHORIZED, description=HTTPStatus.UNAUTHORIZED.phrase, )(sap_profit_center_create_view) sap_profit_center_create_view = marshal_with( None, code=HTTPStatus.INTERNAL_SERVER_ERROR, description='Internal server error', )(sap_profit_center_create_view) reference_sap_profit_center_api.add_url_rule( '/reference-sap-profit-center/', methods=['POST'], view_func=sap_profit_center_create_view, )