mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Added exchange rates form
This commit is contained in:
parent
6d5b2d3227
commit
bed6a7e49c
@ -1,12 +1,21 @@
|
|||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.conf import settings as inventree_settings
|
from django.conf import settings as inventree_settings
|
||||||
|
|
||||||
from djmoney import settings as djmoney_settings
|
from djmoney import settings as djmoney_settings
|
||||||
from djmoney.contrib.exchange.backends.base import BaseExchangeBackend
|
from djmoney.contrib.exchange.backends.base import BaseExchangeBackend
|
||||||
from djmoney.contrib.exchange.backends import FixerBackend
|
|
||||||
|
|
||||||
from common.models import InvenTreeSetting
|
from common.models import InvenTreeSetting
|
||||||
|
|
||||||
|
|
||||||
|
def get_exchange_rate_backend():
|
||||||
|
""" Return the exchange rate backend set by user """
|
||||||
|
|
||||||
|
if 'InvenTreeManualExchangeBackend' in inventree_settings.EXCHANGE_BACKEND:
|
||||||
|
return InvenTreeManualExchangeBackend()
|
||||||
|
else:
|
||||||
|
return InvenTreeFixerExchangeBackend()
|
||||||
|
|
||||||
|
|
||||||
class InvenTreeManualExchangeBackend(BaseExchangeBackend):
|
class InvenTreeManualExchangeBackend(BaseExchangeBackend):
|
||||||
"""
|
"""
|
||||||
Backend for manually updating currency exchange rates
|
Backend for manually updating currency exchange rates
|
||||||
@ -16,22 +25,39 @@ class InvenTreeManualExchangeBackend(BaseExchangeBackend):
|
|||||||
Specifically: https://github.com/django-money/django-money/tree/master/djmoney/contrib/exchange/backends
|
Specifically: https://github.com/django-money/django-money/tree/master/djmoney/contrib/exchange/backends
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = "inventree"
|
name = 'inventree'
|
||||||
url = None
|
url = None
|
||||||
|
default_currency = None
|
||||||
|
currencies = []
|
||||||
|
|
||||||
|
def update_default_currency(self):
|
||||||
|
|
||||||
|
self.default_currency = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY', inventree_settings.BASE_CURRENCY)
|
||||||
|
|
||||||
|
def __init__(self, url=None):
|
||||||
|
|
||||||
|
self.url = url
|
||||||
|
|
||||||
|
self.update_default_currency()
|
||||||
|
|
||||||
|
self.currencies = inventree_settings.CURRENCIES
|
||||||
|
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
def get_rates(self, **kwargs):
|
def get_rates(self, **kwargs):
|
||||||
"""
|
""" Returns a mapping <currency>: <rate> """
|
||||||
Do not get any rates...
|
|
||||||
"""
|
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
class InvenTreeFixerExchangeBackend(FixerBackend):
|
class InvenTreeFixerExchangeBackend(InvenTreeManualExchangeBackend):
|
||||||
"""
|
"""
|
||||||
Backend for updating currency exchange rates using Fixer.IO API
|
Backend for updating currency exchange rates using Fixer.IO API
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
name = 'fixer.io'
|
||||||
|
access_key = None
|
||||||
|
|
||||||
def get_api_key(self):
|
def get_api_key(self):
|
||||||
""" Get API key from global settings """
|
""" Get API key from global settings """
|
||||||
|
|
||||||
@ -48,18 +74,17 @@ class InvenTreeFixerExchangeBackend(FixerBackend):
|
|||||||
|
|
||||||
fixer_api_key = self.get_api_key()
|
fixer_api_key = self.get_api_key()
|
||||||
|
|
||||||
super().__init__(url=djmoney_settings.FIXER_URL, access_key=fixer_api_key)
|
if fixer_api_key is None:
|
||||||
|
raise ImproperlyConfigured("fixer.io API key is needed to use InvenTreeFixerExchangeBackend")
|
||||||
|
|
||||||
|
self.access_key = fixer_api_key
|
||||||
|
|
||||||
|
super().__init__(url=djmoney_settings.FIXER_URL)
|
||||||
|
|
||||||
def update_rates(self):
|
def update_rates(self):
|
||||||
""" Override update_rates method using currencies found in the settings """
|
""" Override update_rates method using currencies found in the settings
|
||||||
|
"""
|
||||||
|
|
||||||
|
symbols = ','.join(self.currencies)
|
||||||
|
|
||||||
currencies = ','.join(inventree_settings.CURRENCIES)
|
super().update_rates(base_currency=self.base_currency, symbols=symbols)
|
||||||
|
|
||||||
base = inventree_settings.BASE_CURRENCY
|
|
||||||
|
|
||||||
super().update_rates(base_currency=base, symbols=currencies)
|
|
||||||
|
|
||||||
def get_rates(self, **kwargs):
|
|
||||||
""" Returns a mapping <currency>: <rate> """
|
|
||||||
|
|
||||||
return {}
|
|
||||||
|
@ -7,12 +7,15 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
from crispy_forms.helper import FormHelper
|
from crispy_forms.helper import FormHelper
|
||||||
from crispy_forms.layout import Layout, Field
|
from crispy_forms.layout import Layout, Field
|
||||||
from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppendedText, StrictButton, Div
|
from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppendedText, StrictButton, Div
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from common.models import ColorTheme
|
from common.models import ColorTheme
|
||||||
from part.models import PartCategory
|
from part.models import PartCategory
|
||||||
|
from .exchange import InvenTreeManualExchangeBackend
|
||||||
|
|
||||||
|
|
||||||
class HelperForm(forms.ModelForm):
|
class HelperForm(forms.ModelForm):
|
||||||
@ -236,3 +239,34 @@ class SettingCategorySelectForm(forms.ModelForm):
|
|||||||
css_class='row',
|
css_class='row',
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SettingExchangeRatesForm(forms.Form):
|
||||||
|
""" Form for displaying and setting currency exchange rates manually """
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
exchange_rate_backend = InvenTreeManualExchangeBackend()
|
||||||
|
|
||||||
|
# Update default currency (in case it has changed)
|
||||||
|
exchange_rate_backend.update_default_currency()
|
||||||
|
|
||||||
|
for currency in exchange_rate_backend.currencies:
|
||||||
|
if currency != exchange_rate_backend.default_currency:
|
||||||
|
# Set field name
|
||||||
|
field_name = currency
|
||||||
|
# Set field input box
|
||||||
|
self.fields[field_name] = forms.CharField(
|
||||||
|
label=field_name,
|
||||||
|
required=False,
|
||||||
|
widget=forms.NumberInput(attrs={
|
||||||
|
'name': field_name,
|
||||||
|
'class': 'numberinput',
|
||||||
|
'type': 'number',
|
||||||
|
'min': '0',
|
||||||
|
'step': 'any',
|
||||||
|
'value': '',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
@ -167,17 +167,13 @@ def update_exchange_rates():
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from .exchange import InvenTreeManualExchangeBackend, InvenTreeFixerExchangeBackend
|
from .exchange import get_exchange_rate_backend
|
||||||
from django.conf import settings
|
|
||||||
except AppRegistryNotReady:
|
except AppRegistryNotReady:
|
||||||
# Apps not yet loaded!
|
# Apps not yet loaded!
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get backend
|
# Get exchange rate backend
|
||||||
if 'InvenTreeManualExchangeBackend' in settings.EXCHANGE_BACKEND:
|
backend = get_exchange_rate_backend()
|
||||||
backend = InvenTreeManualExchangeBackend()
|
|
||||||
else:
|
|
||||||
backend = InvenTreeFixerExchangeBackend()
|
|
||||||
|
|
||||||
# Update rates
|
# Update rates
|
||||||
backend.update_rates()
|
backend.update_rates()
|
||||||
|
@ -41,7 +41,7 @@ from .views import IndexView, SearchView, DatabaseStatsView
|
|||||||
from .views import SettingsView, EditUserView, SetPasswordView
|
from .views import SettingsView, EditUserView, SetPasswordView
|
||||||
from .views import AppearanceSelectView, SettingCategorySelectView
|
from .views import AppearanceSelectView, SettingCategorySelectView
|
||||||
from .views import DynamicJsView
|
from .views import DynamicJsView
|
||||||
from .views import ExchangeRatesView
|
from .views import CurrencySettingsView
|
||||||
|
|
||||||
from common.views import SettingEdit
|
from common.views import SettingEdit
|
||||||
|
|
||||||
@ -91,8 +91,7 @@ settings_urls = [
|
|||||||
url(r'^build/?', SettingsView.as_view(template_name='InvenTree/settings/build.html'), name='settings-build'),
|
url(r'^build/?', SettingsView.as_view(template_name='InvenTree/settings/build.html'), name='settings-build'),
|
||||||
url(r'^purchase-order/?', SettingsView.as_view(template_name='InvenTree/settings/po.html'), name='settings-po'),
|
url(r'^purchase-order/?', SettingsView.as_view(template_name='InvenTree/settings/po.html'), name='settings-po'),
|
||||||
url(r'^sales-order/?', SettingsView.as_view(template_name='InvenTree/settings/so.html'), name='settings-so'),
|
url(r'^sales-order/?', SettingsView.as_view(template_name='InvenTree/settings/so.html'), name='settings-so'),
|
||||||
url(r'^currencies/?', SettingsView.as_view(template_name='InvenTree/settings/currencies.html'), name='settings-currencies'),
|
url(r'^currencies/?', CurrencySettingsView.as_view(), name='settings-currencies'),
|
||||||
url(r'^echange-rates/?', ExchangeRatesView.as_view(), name='refresh-exchange-rates'),
|
|
||||||
|
|
||||||
url(r'^(?P<pk>\d+)/edit/', SettingEdit.as_view(), name='setting-edit'),
|
url(r'^(?P<pk>\d+)/edit/', SettingEdit.as_view(), name='setting-edit'),
|
||||||
|
|
||||||
|
@ -26,8 +26,9 @@ from users.models import check_user_role, RuleSet
|
|||||||
|
|
||||||
from .forms import DeleteForm, EditUserForm, SetPasswordForm
|
from .forms import DeleteForm, EditUserForm, SetPasswordForm
|
||||||
from .forms import ColorThemeSelectForm, SettingCategorySelectForm
|
from .forms import ColorThemeSelectForm, SettingCategorySelectForm
|
||||||
|
from .forms import SettingExchangeRatesForm
|
||||||
from .helpers import str2bool
|
from .helpers import str2bool
|
||||||
from .tasks import update_exchange_rates
|
from .exchange import get_exchange_rate_backend
|
||||||
|
|
||||||
from rest_framework import views
|
from rest_framework import views
|
||||||
|
|
||||||
@ -911,14 +912,44 @@ class DatabaseStatsView(AjaxView):
|
|||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class ExchangeRatesView(SettingsView):
|
class CurrencySettingsView(FormView):
|
||||||
|
|
||||||
|
form_class = SettingExchangeRatesForm
|
||||||
|
template_name = 'InvenTree/settings/currencies.html'
|
||||||
success_url = reverse_lazy('settings-currencies')
|
success_url = reverse_lazy('settings-currencies')
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
|
||||||
|
context = super().get_context_data(**kwargs)
|
||||||
|
|
||||||
|
# Get exchange rate backend
|
||||||
|
exchange_rate_backend = get_exchange_rate_backend()
|
||||||
|
|
||||||
|
context['exchange_backend'] = exchange_rate_backend.name
|
||||||
|
|
||||||
|
return context
|
||||||
|
|
||||||
|
def get_form(self):
|
||||||
|
|
||||||
|
form = super().get_form()
|
||||||
|
|
||||||
|
# Get exchange rate backend
|
||||||
|
exchange_rate_backend = get_exchange_rate_backend()
|
||||||
|
|
||||||
|
if exchange_rate_backend.name == 'fixer.io':
|
||||||
|
# Disable all the fields
|
||||||
|
for field in form.fields:
|
||||||
|
form.fields[field].disabled = True
|
||||||
|
|
||||||
|
return form
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
|
|
||||||
|
# Get exchange rate backend
|
||||||
|
exchange_rate_backend = get_exchange_rate_backend()
|
||||||
|
|
||||||
# Process exchange rates
|
# Process exchange rates
|
||||||
update_exchange_rates()
|
exchange_rate_backend.update_rates()
|
||||||
|
|
||||||
# TODO: Update context
|
# TODO: Update context
|
||||||
|
|
||||||
|
@ -26,18 +26,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class='table table-striped table-condensed' id='exchange-rates'>
|
<form action="{% url 'settings-currencies' %}" method="post">
|
||||||
</table>
|
|
||||||
|
|
||||||
<form action="{% url 'refresh-exchange-rates' %}" method="post">
|
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<button type="submit" class='btn btn-primary'>{% trans "Refresh Exchange Rates" %}</button>
|
{% load crispy_forms_tags %}
|
||||||
|
{% crispy form %}
|
||||||
|
{% if exchange_backend == 'fixer.io' %}
|
||||||
|
<button type="submit" class='btn btn-primary'>{% trans "Refresh Exchange Rates" %}</button>
|
||||||
|
{% else %}
|
||||||
|
<button type="submit" class='btn btn-primary'>{% trans "Update Exchange Rates" %}</button>
|
||||||
|
{% endif %}
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block js_ready %}
|
|
||||||
{{ block.super }}
|
|
||||||
{% comment %} TODO: Update exchange-rates table! {% endcomment %}
|
|
||||||
{% comment %} Or do it using context instead of JS? {% endcomment %}
|
|
||||||
{% endblock %}
|
|
Loading…
Reference in New Issue
Block a user