"""Exchange Rate Logic.""" from typing import Type from owsresponse import response from sqlalchemy.exc import IntegrityError from royalties import models from royalties.constants.error import ( ERROR_CSV_EMPTY, ERROR_EXCHANGE_RATE_SAVE, ERROR_STATEMENT_PERIOD_NOT_ACCEPTING_FILES, ) from royalties.schemas.exchange_rate import ExchangeRateSchema from royalties.utils.csv_parser import CSVParser from royalties.utils.exchange_rate_format import ExchangeRateStandardFXParser from royalties.utils.format_error import validation_error from royalties.utils.strings import base64decode exchange_rates_schema = ExchangeRateSchema(many=True, exclude=['exchange_rate_id']) def bulk_load_exchange_rates(params: dict) -> Type[response.Response]: """Verify user data and import data. Args: params(dict): POST request body Required Parameters: statement_period_id: ID of statement period exchange_rates: Encoded string of csv data Returns: A List of newly created exchange rates record. """ statement_period_id = params.get('statement_period_id') csv_data = params.get('exchange_rates') if not csv_data: return validation_error(ERROR_CSV_EMPTY) statement_period = models.StatementPeriod.get_by_id_or_error(statement_period_id) if not statement_period.is_accepting_file_attachments(): return validation_error(ERROR_STATEMENT_PERIOD_NOT_ACCEPTING_FILES) return bulk_save_exchange_rates(statement_period_id, base64decode(csv_data)) def bulk_save_exchange_rates( statement_period_id: int, csv_data: str ) -> Type[response.Response]: """Save new exchange rates. Args: statement_period_id: ID of statement period csv_data: Decoded string of csv data Returns: A List of newly created exchange rates record. """ formatter = ExchangeRateStandardFXParser(statement_period_id) parser = CSVParser.init_from_standard_format(csv_data, formatter) parser.parse_string(csv_data) results = parser.get_results() if results.get('errors'): return validation_error({'rows': [], 'errors': results.get('errors')}) new_models = [] for row in results.get('rows'): if row['from_currency_code'] == row['to_currency_code']: continue new_models.append( models.ExchangeRate.build( statement_period_id=row['statement_period_id'], from_currency_code=row['from_currency_code'], to_currency_code=row['to_currency_code'], rate=row['rate'], ) ) try: models.ExchangeRate.commit_changes(*new_models) except IntegrityError as e: row = results.get('rows')[0] return validation_error( { 'rows': [], 'errors': [ ERROR_EXCHANGE_RATE_SAVE.format( period=row['statement_period_id'], from_cur=row['from_currency_code'], to_cur=row['to_currency_code'], reason=str(e), ) ], } ) return response.Response( status=201, message={'rows': exchange_rates_schema.dump(new_models), 'errors': []}, )