mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-29 12:06:44 +00:00
Add 'currency' option for company
- e.g. an external supplier might have a default currency - Adds a form input which only allows selection of allowed currency codes - Add unit testing for currency validation
This commit is contained in:
parent
ebac06ebee
commit
1532be9c1e
@ -6,11 +6,22 @@ from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from moneyed import CURRENCIES
|
||||
|
||||
import common.models
|
||||
|
||||
import re
|
||||
|
||||
|
||||
def validate_currency_code(code):
|
||||
"""
|
||||
Check that a given code is a valid currency code.
|
||||
"""
|
||||
|
||||
if code not in CURRENCIES:
|
||||
raise ValidationError(_('Not a valid currency code'))
|
||||
|
||||
|
||||
def allowable_url_schemes():
|
||||
""" Return the list of allowable URL schemes.
|
||||
In addition to the default schemes allowed by Django,
|
||||
|
23
InvenTree/common/settings.py
Normal file
23
InvenTree/common/settings.py
Normal file
@ -0,0 +1,23 @@
|
||||
"""
|
||||
User-configurable settings for the common app
|
||||
"""
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from moneyed import CURRENCIES
|
||||
|
||||
from common.models import InvenTreeSetting
|
||||
|
||||
|
||||
def currency_code_default():
|
||||
"""
|
||||
Returns the default currency code (or USD if not specified)
|
||||
"""
|
||||
|
||||
code = InvenTreeSetting.get_setting('INVENTREE_DEFAULT_CURRENCY')
|
||||
|
||||
if code not in CURRENCIES:
|
||||
code = 'USD'
|
||||
|
||||
return code
|
@ -9,10 +9,13 @@ from InvenTree.forms import HelperForm
|
||||
from InvenTree.fields import RoundingDecimalFormField
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
import django.forms
|
||||
|
||||
import djmoney.settings
|
||||
from djmoney.forms.fields import MoneyField
|
||||
|
||||
from common.models import InvenTreeSetting
|
||||
import common.settings
|
||||
|
||||
from .models import Company
|
||||
from .models import SupplierPart
|
||||
@ -30,6 +33,13 @@ class EditCompanyForm(HelperForm):
|
||||
'phone': 'fa-phone',
|
||||
}
|
||||
|
||||
currency = django.forms.ChoiceField(
|
||||
required=False,
|
||||
help_text=_('Default currency used for this company'),
|
||||
choices=[('', '----------')] + djmoney.settings.CURRENCY_CHOICES,
|
||||
initial=common.settings.currency_code_default,
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = Company
|
||||
fields = [
|
||||
@ -37,6 +47,7 @@ class EditCompanyForm(HelperForm):
|
||||
'description',
|
||||
'website',
|
||||
'address',
|
||||
'currency',
|
||||
'phone',
|
||||
'email',
|
||||
'contact',
|
||||
|
19
InvenTree/company/migrations/0029_company_currency.py
Normal file
19
InvenTree/company/migrations/0029_company_currency.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.0.7 on 2020-11-11 23:22
|
||||
|
||||
import InvenTree.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('company', '0028_remove_supplierpricebreak_cost'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='company',
|
||||
name='currency',
|
||||
field=models.CharField(blank=True, help_text='Default currency used for this company', max_length=3, validators=[InvenTree.validators.validate_currency_code], verbose_name='Currency'),
|
||||
),
|
||||
]
|
@ -26,6 +26,8 @@ from InvenTree.helpers import normalize
|
||||
from InvenTree.fields import InvenTreeURLField
|
||||
from InvenTree.status_codes import PurchaseOrderStatus
|
||||
|
||||
import InvenTree.validators
|
||||
|
||||
import common.models
|
||||
|
||||
|
||||
@ -77,6 +79,7 @@ class Company(models.Model):
|
||||
is_customer: boolean value, is this company a customer
|
||||
is_supplier: boolean value, is this company a supplier
|
||||
is_manufacturer: boolean value, is this company a manufacturer
|
||||
currency_code: Specifies the default currency for the company
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
@ -126,6 +129,14 @@ class Company(models.Model):
|
||||
|
||||
is_manufacturer = models.BooleanField(default=False, help_text=_('Does this company manufacture parts?'))
|
||||
|
||||
currency = models.CharField(
|
||||
max_length=3,
|
||||
verbose_name=_('Currency'),
|
||||
blank=True,
|
||||
help_text=_('Default currency used for this company'),
|
||||
validators=[InvenTree.validators.validate_currency_code],
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
""" Get string representation of a Company """
|
||||
return "{n} - {d}".format(n=self.name, d=self.description)
|
||||
|
@ -8,25 +8,64 @@
|
||||
<h4>{% trans "Company Details" %}</h4>
|
||||
<hr>
|
||||
|
||||
<table class='table table-striped'>
|
||||
<col width='25'>
|
||||
<col>
|
||||
<tr>
|
||||
<td><span class='fas fa-industry'></span></td>
|
||||
<td>{% trans "Manufacturer" %}</td>
|
||||
<td>{% include "yesnolabel.html" with value=company.is_manufacturer %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-building'></span></td>
|
||||
<td>{% trans "Supplier" %}</td>
|
||||
<td>{% include 'yesnolabel.html' with value=company.is_supplier %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-user-tie'></span></td>
|
||||
<td>{% trans "Customer" %}</td>
|
||||
<td>{% include 'yesnolabel.html' with value=company.is_customer %}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class='row'>
|
||||
<div class='col-sm-6'>
|
||||
<table class='table table-striped'>
|
||||
<col width='25'>
|
||||
<col>
|
||||
<tr>
|
||||
<td><span class='fas fa-font'></span></td>
|
||||
<td>{% trans "Company Name" %}</td>
|
||||
<td>{{ company.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-info'></span></td>
|
||||
<td>{% trans "Description" %}</td>
|
||||
<td>{{ company.description }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-globe'></span></td>
|
||||
<td>{% trans "Website" %}</td>
|
||||
<td>
|
||||
{% if company.website %}<a href='{{ company.website }}'>{{ company.website }}</a>
|
||||
{% else %}<i>{% trans "No website specified" %}</i>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-dollar-sign'></span></td>
|
||||
<td>{% trans "Currency" %}</td>
|
||||
<td>
|
||||
{% if company.currency %}{{ company.currency }}
|
||||
{% else %}<i>{% trans "Uses default currency" %}</i>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class='col-sm-6'>
|
||||
<table class='table table-striped'>
|
||||
<col width='25'>
|
||||
<col>
|
||||
<tr>
|
||||
<td><span class='fas fa-industry'></span></td>
|
||||
<td>{% trans "Manufacturer" %}</td>
|
||||
<td>{% include "yesnolabel.html" with value=company.is_manufacturer %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-building'></span></td>
|
||||
<td>{% trans "Supplier" %}</td>
|
||||
<td>{% include 'yesnolabel.html' with value=company.is_supplier %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class='fas fa-user-tie'></span></td>
|
||||
<td>{% trans "Customer" %}</td>
|
||||
<td>{% include 'yesnolabel.html' with value=company.is_customer %}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
{% block js_ready %}
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django.test import TestCase
|
||||
from django.core.exceptions import ValidationError
|
||||
|
||||
import os
|
||||
|
||||
@ -119,6 +120,30 @@ class CompanySimpleTest(TestCase):
|
||||
self.assertIsNone(m3x12.get_price_info(3))
|
||||
self.assertIsNotNone(m3x12.get_price_info(50))
|
||||
|
||||
def test_currency_validation(self):
|
||||
"""
|
||||
Test validation for currency selection
|
||||
"""
|
||||
|
||||
# Create a company with a valid currency code (should pass)
|
||||
company = Company.objects.create(
|
||||
name='Test',
|
||||
description='Toast',
|
||||
currency='AUD',
|
||||
)
|
||||
|
||||
company.full_clean()
|
||||
|
||||
# Create a company with an invalid currency code (should fail)
|
||||
company = Company.objects.create(
|
||||
name='test',
|
||||
description='Toasty',
|
||||
currency='XZY',
|
||||
)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
company.full_clean()
|
||||
|
||||
|
||||
class ContactSimpleTest(TestCase):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user