def test_rates(self): # Initially, there will not be any exchange rate information rates = Rate.objects.all() self.assertEqual(rates.count(), 0) # Without rate information, we cannot convert anything... with self.assertRaises(MissingRate): convert_money(Money(100, 'USD'), 'AUD') with self.assertRaises(MissingRate): convert_money(Money(100, 'AUD'), 'USD') InvenTree.tasks.update_exchange_rates() rates = Rate.objects.all() self.assertEqual(rates.count(), len(currency_codes())) # Now that we have some exchange rate information, we can perform conversions # Forwards convert_money(Money(100, 'USD'), 'AUD') # Backwards convert_money(Money(100, 'AUD'), 'USD') # Convert between non base currencies convert_money(Money(100, 'CAD'), 'NZD') # Convert to a symbol which is not covered with self.assertRaises(MissingRate): convert_money(Money(100, 'GBP'), 'ZWL')
def test_rates(self): # Initially, there will not be any exchange rate information rates = Rate.objects.all() self.assertEqual(rates.count(), 0) # Without rate information, we cannot convert anything... with self.assertRaises(MissingRate): convert_money(Money(100, 'USD'), 'AUD') with self.assertRaises(MissingRate): convert_money(Money(100, 'AUD'), 'USD') update_successful = False # Note: the update sometimes fails in CI, let's give it a few chances for idx in range(10): InvenTree.tasks.update_exchange_rates() rates = Rate.objects.all() if rates.count() == len(currency_codes()): update_successful = True break else: # pragma: no cover print("Exchange rate update failed - retrying") time.sleep(1) self.assertTrue(update_successful) # Now that we have some exchange rate information, we can perform conversions # Forwards convert_money(Money(100, 'USD'), 'AUD') # Backwards convert_money(Money(100, 'AUD'), 'USD') # Convert between non base currencies convert_money(Money(100, 'CAD'), 'NZD') # Convert to a symbol which is not covered with self.assertRaises(MissingRate): convert_money(Money(100, 'GBP'), 'ZWL')
def update_exchange_rates(): """ Update currency exchange rates """ try: from djmoney.contrib.exchange.models import ExchangeBackend, Rate from common.settings import currency_code_default, currency_codes from InvenTree.exchange import InvenTreeExchange except AppRegistryNotReady: # pragma: no cover # Apps not yet loaded! logger.info( "Could not perform 'update_exchange_rates' - App registry not ready" ) return except: # pragma: no cover # Other error? return # Test to see if the database is ready yet try: backend = ExchangeBackend.objects.get(name='InvenTreeExchange') except ExchangeBackend.DoesNotExist: pass except: # pragma: no cover # Some other error logger.warning("update_exchange_rates: Database not ready") return backend = InvenTreeExchange() logger.info(f"Updating exchange rates from {backend.url}") base = currency_code_default() logger.info(f"Using base currency '{base}'") try: backend.update_rates(base_currency=base) # Remove any exchange rates which are not in the provided currencies Rate.objects.filter(backend="InvenTreeExchange").exclude( currency__in=currency_codes()).delete() except Exception as e: # pragma: no cover logger.error(f"Error updating exchange rates: {e}")
def update_rates(self, base_currency=currency_code_default()): symbols = ','.join(currency_codes()) try: super().update_rates(base=base_currency, symbols=symbols) # catch connection errors except URLError: print('Encountered connection error while updating') except OperationalError as e: if 'SerializationFailure' in e.__cause__.__class__.__name__: print('Serialization Failure while updating exchange rates') # We are just going to swallow this exception because the # exchange rates will be updated later by the scheduled task else: # Other operational errors probably are still show stoppers # so reraise them so that the log contains the stacktrace raise