"""Exchange rate CSV formatter.""" from decimal import Decimal, InvalidOperation from abacus_common_data.currency import Currency from royalties.constants.constants import EXCHANGE_RATE_BULK_COLUMNS from royalties.constants.error import ( ERROR_CSV_EMPTY_FIELDS, ERROR_CSV_MISSING_FIELDS, ERROR_CSV_RATE_INVALID, ERROR_CSV_UNKNOWN_CURRENCY, ) from royalties.utils.csv_parser import CSVInputError class ExchangeRateCSVRowParser: """Formatter for exchange rate CSV data.""" def __init__(self, statement_period_id): """Set initial validation values.""" self.statement_period_id = statement_period_id self.headers = EXCHANGE_RATE_BULK_COLUMNS def format(self, row, line_number, **kwargs): # """Format data.""" row_data = dict((el, None) for el in self.headers) if len(row) != len(row_data): raise CSVInputError(ERROR_CSV_MISSING_FIELDS, line_number) for field in row: if field is None: raise CSVInputError(ERROR_CSV_EMPTY_FIELDS, line_number) row_data[self.headers[0]] = self.statement_period_id row_data[self.headers[1]] = self.set_currency_code(row[1], line_number) row_data[self.headers[2]] = self.set_currency_code(row[2], line_number) row_data[self.headers[3]] = self.set_rate(row, line_number) return row_data def set_currency_code(self, value, line_number): """Set from_currency_code.""" try: Currency(value) except KeyError: raise CSVInputError( ERROR_CSV_UNKNOWN_CURRENCY.format(code=value), line_number ) return value def set_rate(self, row, line_number): """Set rate.""" try: value = Decimal(row[3]) except InvalidOperation: raise CSVInputError(ERROR_CSV_RATE_INVALID, line_number) if value <= 0: raise CSVInputError(ERROR_CSV_RATE_INVALID, line_number) return value class ExchangeRateStandardFXParser(ExchangeRateCSVRowParser): """Formatter for standard FX rates sheet.""" def format(self, row, line_number, header_values): # """Format data.""" if len(row) != len(header_values): raise CSVInputError(ERROR_CSV_MISSING_FIELDS, line_number) result = [] for index, cell_value in enumerate(row): if index in (0, 1): # skip first two columns continue row_data = dict((el, None) for el in self.headers) if cell_value is None: raise CSVInputError(ERROR_CSV_EMPTY_FIELDS, line_number) row_data[self.headers[0]] = self.statement_period_id row_data[self.headers[1]] = self.set_currency_code(row[1], line_number) row_data[self.headers[2]] = self.set_currency_code( header_values[index], line_number ) row_data[self.headers[3]] = self.set_rate( cell_value.replace(',', '.'), line_number ) result.append(row_data) return result def set_rate(self, rate, line_number): """Set rate.""" try: value = Decimal(rate) except InvalidOperation: raise CSVInputError(ERROR_CSV_RATE_INVALID, line_number) if value <= 0: raise CSVInputError(ERROR_CSV_RATE_INVALID, line_number) return value