"""Blueprint for Contract Reserve API.""" from http import HTTPStatus from abacus_common_logic.views.create_view import CreateView from abacus_common_logic.views.validations import validated_request_body from common_apispec import doc, marshal_with from common_apispec.views import MethodResource from flask import Blueprint, request from owsrequest import flask_request from owsresponse import response from owsresponse.adaptors.flask import flaskify from abacus_contract.constants import error from abacus_contract.logic import contract as contract_logic, contract_reserve as logic from abacus_contract.schemas.contract_reserve import ContractReservePostSchema from abacus_contract.utils import authorization from abacus_contract.utils.features import is_abacus_bulk_entity_update_enabled from abacus_contract.utils.format_error import validation_error from abacus_contract.utils.request import get_optional_numeric_list_from_params contract_reserve_api = Blueprint('contract_reserve_api', __name__) class ContractReserveCreateView(CreateView): """Handles contract reserve.""" post_schema = ContractReservePostSchema() def post(self, **kwargs): """Create a contract reserve.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, ) ) return super().post(**kwargs) def create_handler(self, **params): """Create a contract reserve.""" return logic.create_contract_reserve(**params) contract_reserve_api.add_url_rule( '/contract//reserves/', view_func=ContractReserveCreateView.as_view('create_contract_reserve'), ) @contract_reserve_api.route('/contract//reserves/', methods=['GET']) def get_reserve_by_contract_id(contract_id: int): """Get reserve by contract_id. Args: contract_id(int): ID of the contract """ access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: account_id = contract_logic.get_account_id_by_contract_id(contract_id) if not account_id or not authorization.pdp_authorize_many_accounts( [account_id] ): return flaskify( response.create_error_response( code=error.ERROR_CODE_FORBIDDEN, message=error.ERROR_MESSAGE_FORBIDDEN_USER, status=403, ) ) return flaskify(logic.get_reserve_by_contract_id(contract_id)) @contract_reserve_api.route('/contract//reserves/', methods=['PUT']) def update_reserve_by_contract_id(contract_id: int): """Update contract reserve by contract id. Args: contract_id (int): ID of the contract reserve """ access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, ) ) put_schema = ContractReservePostSchema() reserve_params = validated_request_body(put_schema) return flaskify( logic.update_contract_reserve_by_contract_id( contract_id=contract_id, **reserve_params ) ) @contract_reserve_api.route('/contract-reserves/', methods=['POST']) def get_contract_reserves_by_ids(): """POST request to get contract reserves by list of contract_reserve_ids. This endpoint will be used by lambda-abacus-reserves-schedule. """ access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, ) ) try: contract_reserve_ids = get_optional_numeric_list_from_params() except ValueError: return flaskify( validation_error(error.ERROR_INVALID_IDS.format(object='Contract Reserve')) ) if not contract_reserve_ids: return flaskify( validation_error( error.ERROR_INVALID_BODY.format( expected_body_type='List of Contract Reserve IDs' ) ) ) return flaskify(logic.get_contract_reserves_by_ids(contract_reserve_ids)) @contract_reserve_api.route('/contract/contract-reserves/', methods=['POST']) def get_contract_reserves_by_contract_ids(): """POST request to get contract reserves by list of contract_ids. This endpoint will be used by lambda-abacus-reserves-take. """ access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, ) ) try: contract_ids = get_optional_numeric_list_from_params() except ValueError: return flaskify( validation_error(error.ERROR_INVALID_IDS.format(object='Contract')) ) if not contract_ids: return flaskify( validation_error( error.ERROR_INVALID_BODY.format( expected_body_type='List of Contract IDs' ) ) ) return flaskify(logic.get_contract_reserves_by_contract_ids(contract_ids)) class ContractReserveDeleteView(MethodResource): """Handles deletion of a contract reserve by contract_id.""" @doc( description='Delete the active contract reserve for a contract', summary='Delete a contract reserve by contract ID', params={ 'contract_id': { 'description': 'ID of the contract', }, }, ) @marshal_with( None, code=HTTPStatus.NO_CONTENT, description=HTTPStatus.NO_CONTENT.phrase ) @marshal_with( None, code=HTTPStatus.BAD_REQUEST, description=HTTPStatus.BAD_REQUEST.phrase ) @marshal_with( None, code=HTTPStatus.FORBIDDEN, description=HTTPStatus.FORBIDDEN.phrase ) @marshal_with( None, code=HTTPStatus.UNAUTHORIZED, description=HTTPStatus.UNAUTHORIZED.phrase ) def delete(self, contract_id, **kwargs): """Soft delete the active contract reserve for the given contract.""" access_rule_decision = flask_request.verify_rules_access_standalone(request) if not access_rule_decision: return flaskify( response.create_error_response( code=error.ERROR_CODE_AUTHORIZATION, message='Unauthorized', status=401, ) ) if not is_abacus_bulk_entity_update_enabled(): return flaskify( response.create_error_response( code=error.ERROR_CODE_FORBIDDEN, message='Feature not enabled', status=403, ) ) return flaskify(logic.delete_contract_reserve_by_contract_id(contract_id)) contract_reserve_api.add_url_rule( '/contract//reserves/', methods=['DELETE'], view_func=ContractReserveDeleteView.as_view('delete_contract_reserve'), )