mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Simplify settings view
- Show various currency exchange rates - Button to "refresh now"
This commit is contained in:
parent
af1904b6e4
commit
6085478672
@ -16,8 +16,6 @@ from crispy_forms.bootstrap import PrependedText, AppendedText, PrependedAppende
|
||||
from common.models import ColorTheme
|
||||
from part.models import PartCategory
|
||||
|
||||
from .exchange import InvenTreeManualExchangeBackend
|
||||
|
||||
|
||||
class HelperForm(forms.ModelForm):
|
||||
""" Provides simple integration of crispy_forms extension. """
|
||||
@ -240,35 +238,3 @@ class SettingCategorySelectForm(forms.ModelForm):
|
||||
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.base_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',
|
||||
'style': 'width: 200px;',
|
||||
'type': 'number',
|
||||
'min': '0',
|
||||
'step': 'any',
|
||||
'value': 0,
|
||||
})
|
||||
)
|
||||
|
@ -39,6 +39,7 @@ from rest_framework.documentation import include_docs_urls
|
||||
|
||||
from .views import IndexView, SearchView, DatabaseStatsView
|
||||
from .views import SettingsView, EditUserView, SetPasswordView
|
||||
from .views import CurrencySettingsView, CurrencyRefreshView
|
||||
from .views import AppearanceSelectView, SettingCategorySelectView
|
||||
from .views import DynamicJsView
|
||||
|
||||
@ -82,15 +83,16 @@ settings_urls = [
|
||||
url(r'^appearance/?', AppearanceSelectView.as_view(), name='settings-appearance'),
|
||||
url(r'^i18n/?', include('django.conf.urls.i18n')),
|
||||
|
||||
url(r'^global/?', SettingsView.as_view(template_name='InvenTree/settings/global.html'), name='settings-global'),
|
||||
url(r'^report/?', SettingsView.as_view(template_name='InvenTree/settings/report.html'), name='settings-report'),
|
||||
url(r'^category/?', SettingCategorySelectView.as_view(), name='settings-category'),
|
||||
url(r'^part/?', SettingsView.as_view(template_name='InvenTree/settings/part.html'), name='settings-part'),
|
||||
url(r'^stock/?', SettingsView.as_view(template_name='InvenTree/settings/stock.html'), name='settings-stock'),
|
||||
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'^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'^global/', SettingsView.as_view(template_name='InvenTree/settings/global.html'), name='settings-global'),
|
||||
url(r'^report/', SettingsView.as_view(template_name='InvenTree/settings/report.html'), name='settings-report'),
|
||||
url(r'^category/', SettingCategorySelectView.as_view(), name='settings-category'),
|
||||
url(r'^part/', SettingsView.as_view(template_name='InvenTree/settings/part.html'), name='settings-part'),
|
||||
url(r'^stock/', SettingsView.as_view(template_name='InvenTree/settings/stock.html'), name='settings-stock'),
|
||||
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'^sales-order/', SettingsView.as_view(template_name='InvenTree/settings/so.html'), name='settings-so'),
|
||||
url(r'^currencies/', CurrencySettingsView.as_view(), name='settings-currencies'),
|
||||
url(r'^currencies-refresh/', CurrencyRefreshView.as_view(), name='settings-currencies-refresh'),
|
||||
|
||||
url(r'^(?P<pk>\d+)/edit/', SettingEdit.as_view(), name='setting-edit'),
|
||||
|
||||
|
@ -12,12 +12,15 @@ from django.utils.translation import gettext_lazy as _
|
||||
from django.template.loader import render_to_string
|
||||
from django.http import JsonResponse, HttpResponseRedirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.conf import settings
|
||||
|
||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
|
||||
from django.views import View
|
||||
from django.views.generic import ListView, DetailView, CreateView, FormView, DeleteView, UpdateView
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.views.generic.base import RedirectView, TemplateView
|
||||
|
||||
from djmoney.contrib.exchange.models import ExchangeBackend, Rate
|
||||
|
||||
from part.models import Part, PartCategory
|
||||
from stock.models import StockLocation, StockItem
|
||||
@ -25,11 +28,11 @@ from common.models import InvenTreeSetting, ColorTheme
|
||||
from users.models import check_user_role, RuleSet
|
||||
from InvenTree.helpers import clean_decimal
|
||||
|
||||
import InvenTree.tasks
|
||||
|
||||
from .forms import DeleteForm, EditUserForm, SetPasswordForm
|
||||
from .forms import ColorThemeSelectForm, SettingCategorySelectForm
|
||||
from .forms import SettingExchangeRatesForm
|
||||
from .helpers import str2bool
|
||||
from .exchange import get_exchange_rate_backend
|
||||
|
||||
from rest_framework import views
|
||||
|
||||
@ -772,6 +775,50 @@ class SettingsView(TemplateView):
|
||||
return ctx
|
||||
|
||||
|
||||
|
||||
class CurrencyRefreshView(RedirectView):
|
||||
|
||||
url = reverse_lazy("settings-currencies")
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
"""
|
||||
On a POST request we will attempt to refresh the exchange rates
|
||||
"""
|
||||
|
||||
print("POST!")
|
||||
|
||||
# Will block for a little bit
|
||||
InvenTree.tasks.update_exchange_rates()
|
||||
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
|
||||
class CurrencySettingsView(TemplateView):
|
||||
"""
|
||||
View for configuring currency settings
|
||||
"""
|
||||
|
||||
template_name = "InvenTree/settings/currencies.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
ctx = super().get_context_data(**kwargs).copy()
|
||||
|
||||
ctx['settings'] = InvenTreeSetting.objects.all().order_by('key')
|
||||
ctx["base_currency"] = settings.BASE_CURRENCY
|
||||
ctx["currencies"] = settings.CURRENCIES
|
||||
|
||||
ctx["rates"] = Rate.objects.filter(backend="InvenTreeExchange")
|
||||
|
||||
# When were the rates last updated?
|
||||
try:
|
||||
backend = ExchangeBackend.objects.get(name='InvenTreeExchange')
|
||||
ctx["rates_updated"] = backend.last_update
|
||||
except:
|
||||
ctx["rates_updated"] = None
|
||||
|
||||
return ctx
|
||||
|
||||
class AppearanceSelectView(FormView):
|
||||
""" View for selecting a color theme """
|
||||
|
||||
@ -911,89 +958,3 @@ class DatabaseStatsView(AjaxView):
|
||||
"""
|
||||
|
||||
return ctx
|
||||
|
||||
|
||||
class CurrencySettingsView(FormView):
|
||||
|
||||
form_class = SettingExchangeRatesForm
|
||||
template_name = 'InvenTree/settings/currencies.html'
|
||||
success_url = reverse_lazy('settings-currencies')
|
||||
|
||||
exchange_rate_backend = None
|
||||
|
||||
def get_exchange_rate_backend(self):
|
||||
|
||||
if not self.exchange_rate_backend:
|
||||
self.exchange_rate_backend = get_exchange_rate_backend()
|
||||
|
||||
return self.exchange_rate_backend
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
# Set default API result
|
||||
if 'api_rates_success' not in context:
|
||||
context['default_currency'] = True
|
||||
else:
|
||||
# Update form
|
||||
context['form'] = self.get_form()
|
||||
|
||||
# Get exchange rate backend
|
||||
exchange_rate_backend = self.get_exchange_rate_backend()
|
||||
|
||||
context['default_currency'] = exchange_rate_backend.base_currency
|
||||
|
||||
context['custom_rates'] = exchange_rate_backend.custom_rates
|
||||
|
||||
context['exchange_backend'] = exchange_rate_backend.name
|
||||
|
||||
return context
|
||||
|
||||
def get_form(self):
|
||||
|
||||
form = super().get_form()
|
||||
|
||||
# Get exchange rate backend
|
||||
exchange_rate_backend = self.get_exchange_rate_backend()
|
||||
|
||||
# Get stored exchange rates
|
||||
stored_rates = exchange_rate_backend.get_stored_rates()
|
||||
|
||||
for field in form.fields:
|
||||
if not exchange_rate_backend.custom_rates:
|
||||
# Disable all the fields
|
||||
form.fields[field].disabled = True
|
||||
form.fields[field].initial = clean_decimal(stored_rates.get(field, 0))
|
||||
|
||||
return form
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
|
||||
form = self.get_form()
|
||||
|
||||
# Get exchange rate backend
|
||||
exchange_rate_backend = self.get_exchange_rate_backend()
|
||||
|
||||
if not exchange_rate_backend.custom_rates:
|
||||
# Refresh rate from Fixer.IO API
|
||||
exchange_rate_backend.update_rates(base_currency=exchange_rate_backend.base_currency)
|
||||
# Check if rates have been updated
|
||||
if not exchange_rate_backend.get_stored_rates():
|
||||
# Update context
|
||||
context = {'api_rates_success': False}
|
||||
# Return view with updated context
|
||||
return self.render_to_response(self.get_context_data(form=form, **context))
|
||||
else:
|
||||
# Update rates from form
|
||||
manual_rates = {}
|
||||
|
||||
if form.is_valid():
|
||||
for field, value in form.cleaned_data.items():
|
||||
manual_rates[field] = clean_decimal(value)
|
||||
|
||||
exchange_rate_backend.update_rates(base_currency=exchange_rate_backend.base_currency, **{'rates': manual_rates})
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
return self.form_valid(form)
|
||||
|
@ -13,40 +13,43 @@
|
||||
{% block settings %}
|
||||
|
||||
<table class='table table-striped table-condensed'>
|
||||
{% include "InvenTree/settings/header.html" %}
|
||||
<tbody>
|
||||
{% include "InvenTree/settings/setting.html" with key="INVENTREE_DEFAULT_CURRENCY" icon="fa-dollar-sign" %}
|
||||
{% include "InvenTree/settings/setting.html" with key="CUSTOM_EXCHANGE_RATES" icon="fa-edit" %}
|
||||
<tr>
|
||||
<th>{% trans "Base Currency" %}</th>
|
||||
<th>{{ base_currency }}</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan='2'>{% trans "Exchange Rates" %}</th>
|
||||
</tr>
|
||||
{% for rate in rates %}
|
||||
<tr>
|
||||
<td>{{ rate.currency }}</td>
|
||||
<td>{{ rate.value }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
<tr>
|
||||
<th>
|
||||
{% trans "Last Update" %}
|
||||
</th>
|
||||
<td>
|
||||
{% if rates_updated %}
|
||||
{{ rates_updated }}
|
||||
{% else %}
|
||||
<i>{% trans "Never" %}</i>
|
||||
{% endif %}
|
||||
<form action='{% url "settings-currencies-refresh" %}' method='post'>
|
||||
<div id='refresh-rates-form'>
|
||||
{% csrf_token %}
|
||||
<button type='submit' id='update-rates' class='btn btn-default float-right'>{% trans "Update Now" %}</button>
|
||||
</div>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class='row'>
|
||||
<div class='col-sm-6'>
|
||||
<h4>{% blocktrans with cur=default_currency %}Exchange Rates - Convert to {{cur}}{% endblocktrans %}</h4>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form action="{% url 'settings-currencies' %}" method="post">
|
||||
<div id='exchange_rate_form'>
|
||||
{% csrf_token %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% crispy form %}
|
||||
{% if custom_rates is False %}
|
||||
<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 %}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block js_ready %}
|
||||
{{ block.super }}
|
||||
|
||||
{% if api_rates_success is False %}
|
||||
var alert_msg = {% blocktrans %}"Failed to refresh exchange rates" {% endblocktrans %};
|
||||
showAlertOrCache("alert-danger", alert_msg, null, 5000);
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user