"""Contract Flowthrough logic.""" from abacus_common_logic.connectors.database import db from abacus_common_logic.utils.dates import current_timestamp from abacus_common_logic.utils.users import get_flask_user_id from marshmallow import ValidationError from owsresponse import response import sqlalchemy from abacus_contract.constants.constants import \ CONTRACT_FLOWTHROUGH_STATUSES from abacus_contract.constants.error import \ ERROR_CONTRACT_FLOWTHROUGH_ALREADY_EXISTS from abacus_contract.models.contract import Contract from abacus_contract.models.contract_flowthrough import \ ContractFlowthrough from abacus_contract.schemas.contract_flowthrough \ import ContractFlowthroughDetailSchema from abacus_contract.utils.exception import ObjectAlreadyExistException from abacus_contract.utils.format_error import validation_error def get_contract_flowthrough_by_contract_id( contract_id: int ) -> response.Response: """Get a contract_flowthrough by contract_id. Args: contract_id(int): id of the contract Returns: a contract_flowthrough record """ Contract.get_by_id_or_error(contract_id, 404) contract_flowthrough = ContractFlowthrough.get_by_contract_id(contract_id) return response.Response( message=ContractFlowthroughDetailSchema().dump(contract_flowthrough), status=200 ) def soft_delete_contract_flowthrough( contract_flowthrough: ContractFlowthrough ) -> response.Response: """Soft delete a specified contract_flowthrough. Args: contract_flowthrough(ContractFlowthrough): a contract_flowthrough object Returns: response object with status """ try: contract_flowthrough._soft_delete() ContractFlowthrough.commit_changes() except sqlalchemy.exc.SQLAlchemyError as e: raise e return response.Response(status=204) def update_contract_flowthrough( contract_flowthrough: ContractFlowthrough, **put_request_body: dict ) -> response.Response: """Update specified contract_flowthrough. Args: contract_flowthrough(ContractFlowthrough): a contract_flowthrough object put_request_body(dict): PUT request body - reference_flowthrough_calculation_id (Optional) - flowthrough_rate (Optional) - flowthrough_status (Optional) - has_automatic_shutoff (Optional) - recoupment_cap (Optional) Returns: updated contract_flowthrough record """ try: existing_flowthrough_status = contract_flowthrough.flowthrough_status new_flowthrough_status = put_request_body.get('flowthrough_status') has_automatic_shutoff = put_request_body.get('has_automatic_shutoff') if has_automatic_shutoff: new_flowthrough_status = CONTRACT_FLOWTHROUGH_STATUSES.ACTIVE put_request_body.update({ 'flowthrough_status': new_flowthrough_status }) if new_flowthrough_status is not None and \ new_flowthrough_status != existing_flowthrough_status: put_request_body.update({ 'previous_flowthrough_status': existing_flowthrough_status, 'status_last_modified_by': get_flask_user_id(), 'status_last_modified': current_timestamp() }) contract_flowthrough.update_attributes(**put_request_body) db.session.commit() except ValidationError as e: return validation_error(str(e)) except sqlalchemy.exc.SQLAlchemyError as e: db.session.rollback() raise e return response.Response( message=ContractFlowthroughDetailSchema().dump( contract_flowthrough ), status=200 ) def create_contract_flowthrough( contract_id: int, reference_flowthrough_calculation_id: int, flowthrough_rate: str, has_automatic_shutoff: bool, recoupment_cap: int = None ) -> response.Response: """Create a contract_flowthrough. Args: contract_id (int): id of the contract reference_flowthrough_calculation_id (int): id of the reference_flowthrough_calculation flowthrough_rate (str): percentage of revenue that would be paid has_automatic_shutoff (bool): whether to pay flowthrough recoupment_cap (str)(Optional): recoupment amount Returns: a contract_flowthrough record """ Contract.get_by_id_or_error(contract_id, 404) try: _check_whether_contract_flowthrough_exist(contract_id) contract_flowthrough = ContractFlowthrough.build( contract_id=contract_id, reference_flowthrough_calculation_id=reference_flowthrough_calculation_id, # noqa: E501 flowthrough_rate=flowthrough_rate, has_automatic_shutoff=has_automatic_shutoff, recoupment_cap=recoupment_cap ) db.session.commit() except sqlalchemy.exc.SQLAlchemyError as e: db.session.rollback() raise e except ObjectAlreadyExistException as e: return response.create_error_response( code='error', status=409, message=str(e) ) return response.Response( message=ContractFlowthroughDetailSchema().dump(contract_flowthrough), status=201 ) def _check_whether_contract_flowthrough_exist(contract_id: int): """Check whether flowthrough is already added to contract. Args: contract_id(int): id of the contract """ existing_contract_flowthrough = ContractFlowthrough.get_by_contract_id(contract_id) if existing_contract_flowthrough is not None: raise ObjectAlreadyExistException( ERROR_CONTRACT_FLOWTHROUGH_ALREADY_EXISTS.format( contract_id=contract_id ) ) return False