Merge remote-tracking branch 'inventree/master'

This commit is contained in:
Oliver Walters 2019-09-04 08:57:24 +10:00
commit 8f3a022b3c
5 changed files with 84 additions and 20 deletions

View File

@ -8,11 +8,14 @@ from __future__ import unicode_literals
from InvenTree.forms import HelperForm
from django import forms
from django.utils.translation import ugettext as _
from .models import Part, PartCategory, PartAttachment
from .models import BomItem
from .models import PartParameterTemplate, PartParameter
from common.models import Currency
class PartImageForm(HelperForm):
""" Form for uploading a Part image """
@ -30,7 +33,7 @@ class BomValidateForm(HelperForm):
to confirm that the BOM for this part is valid
"""
validate = forms.BooleanField(required=False, initial=False, help_text='Confirm that the BOM is correct')
validate = forms.BooleanField(required=False, initial=False, help_text=_('Confirm that the BOM is correct'))
class Meta:
model = Part
@ -42,7 +45,7 @@ class BomValidateForm(HelperForm):
class BomUploadSelectFile(HelperForm):
""" Form for importing a BOM. Provides a file input box for upload """
bom_file = forms.FileField(label='BOM file', required=True, help_text="Select BOM file to upload")
bom_file = forms.FileField(label='BOM file', required=True, help_text=_("Select BOM file to upload"))
class Meta:
model = Part
@ -68,12 +71,12 @@ class EditPartForm(HelperForm):
deep_copy = forms.BooleanField(required=False,
initial=True,
help_text="Perform 'deep copy' which will duplicate all BOM data for this part",
help_text=_("Perform 'deep copy' which will duplicate all BOM data for this part"),
widget=forms.HiddenInput())
confirm_creation = forms.BooleanField(required=False,
initial=False,
help_text='Confirm part creation',
help_text=_('Confirm part creation'),
widget=forms.HiddenInput())
class Meta:
@ -160,11 +163,30 @@ class PartPriceForm(forms.Form):
quantity = forms.IntegerField(
required=True,
initial=1,
help_text='Input quantity for price calculation'
help_text=_('Input quantity for price calculation')
)
currency = forms.ChoiceField(label='Currency', help_text=_('Select currency for price calculation'))
def get_currency_choices(self):
""" Create options for Currency """
currencies = Currency.objects.all()
choices = [(None, '---------')]
for c in currencies:
choices.append((c.pk, str(c)))
return choices
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['currency'].choices = self.get_currency_choices()
class Meta:
model = Part
fields = [
'quantity'
'quantity',
'currency',
]

View File

@ -24,14 +24,14 @@ Pricing information for:<br>
{% if min_total_buy_price %}
<tr>
<td><b>Unit Cost</b></td>
<td>Min: {{ min_unit_buy_price }}</td>
<td>Max: {{ max_unit_buy_price }}</td>
<td>Min: {% include "price.html" with price=min_unit_buy_price %}</td>
<td>Max: {% include "price.html" with price=max_unit_buy_price %}</td>
</tr>
{% if quantity > 1 %}
<tr>
<td><b>Total Cost</b></td>
<td>Min: {{ min_total_buy_price }}</td>
<td>Max: {{ max_total_buy_price }}</td>
<td>Min: {% include "price.html" with price=min_total_buy_price %}</td>
<td>Max: {% include "price.html" with price=max_total_buy_price %}</td>
</tr>
{% endif %}
{% else %}
@ -50,14 +50,14 @@ Pricing information for:<br>
{% if min_total_bom_price %}
<tr>
<td><b>Unit Cost</b></td>
<td>Min: {{ min_unit_bom_price }}</td>
<td>Max: {{ max_unit_bom_price }}</td>
<td>Min: {% include "price.html" with price=min_unit_bom_price %}</td>
<td>Max: {% include "price.html" with price=max_unit_bom_price %}</td>
</tr>
{% if quantity > 1 %}
<tr>
<td><b>Total Cost</b></td>
<td>Min: {{ min_total_bom_price }}</td>
<td>Max: {{ max_total_bom_price }}</td>
<td>Min: {% include "price.html" with price=min_total_bom_price %}</td>
<td>Max: {% include "price.html" with price=max_total_bom_price %}</td>
</tr>
{% endif %}
{% if part.has_complete_bom_pricing == False %}

View File

@ -142,8 +142,8 @@ class PartAttachmentTests(PartViewTestCase):
def test_invalid_create(self):
""" test creation of an attachment for an invalid part """
with self.assertRaises(Part.DoesNotExist):
self.client.get(reverse('part-attachment-create'), {'part': 999}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
# TODO
pass
def test_edit(self):
""" test editing an attachment """

View File

@ -17,12 +17,14 @@ from django.forms import HiddenInput, CheckboxInput
import tablib
from fuzzywuzzy import fuzz
from decimal import Decimal
from .models import PartCategory, Part, PartAttachment
from .models import PartParameterTemplate, PartParameter
from .models import BomItem
from .models import match_part_names
from common.models import Currency
from company.models import SupplierPart
from . import forms as part_forms
@ -82,7 +84,10 @@ class PartAttachmentCreate(AjaxCreateView):
initials = super(AjaxCreateView, self).get_initial()
# TODO - If the proper part was not sent, return an error message
initials['part'] = Part.objects.get(id=self.request.GET.get('part'))
try:
initials['part'] = Part.objects.get(id=self.request.GET.get('part', None))
except (ValueError, Part.DoesNotExist):
pass
return initials
@ -1325,7 +1330,7 @@ class PartPricing(AjaxView):
except Part.DoesNotExist:
return None
def get_pricing(self, quantity=1):
def get_pricing(self, quantity=1, currency=None):
try:
quantity = int(quantity)
@ -1335,11 +1340,25 @@ class PartPricing(AjaxView):
if quantity < 1:
quantity = 1
if currency is None:
# No currency selected? Try to select a default one
try:
currency = Currency.objects.get(base=1)
except Currency.DoesNotExist:
currency = None
# Currency scaler
scaler = Decimal(1.0)
if currency is not None:
scaler = Decimal(currency.value)
part = self.get_part()
ctx = {
'part': part,
'quantity': quantity
'quantity': quantity,
'currency': currency,
}
if part is None:
@ -1352,6 +1371,12 @@ class PartPricing(AjaxView):
if buy_price is not None:
min_buy_price, max_buy_price = buy_price
min_buy_price /= scaler
max_buy_price /= scaler
min_buy_price = round(min_buy_price, 3)
max_buy_price = round(max_buy_price, 3)
if min_buy_price:
ctx['min_total_buy_price'] = min_buy_price
ctx['min_unit_buy_price'] = min_buy_price / quantity
@ -1368,6 +1393,12 @@ class PartPricing(AjaxView):
if bom_price is not None:
min_bom_price, max_bom_price = bom_price
min_bom_price /= scaler
max_bom_price /= scaler
min_bom_price = round(min_bom_price, 3)
max_bom_price = round(max_bom_price, 3)
if min_bom_price:
ctx['min_total_bom_price'] = min_bom_price
ctx['min_unit_bom_price'] = min_bom_price / quantity
@ -1384,17 +1415,27 @@ class PartPricing(AjaxView):
def post(self, request, *args, **kwargs):
currency = None
try:
quantity = int(self.request.POST.get('quantity', 1))
except ValueError:
quantity = 1
try:
currency_id = int(self.request.POST.get('currency', None))
if currency_id:
currency = Currency.objects.get(pk=currency_id)
except (ValueError, Currency.DoesNotExist):
currency = None
# Always mark the form as 'invalid' (the user may wish to keep getting pricing data)
data = {
'form_valid': False,
}
return self.renderJsonResponse(request, self.form_class(), data=data, context=self.get_pricing(quantity))
return self.renderJsonResponse(request, self.form_class(), data=data, context=self.get_pricing(quantity, currency))
class PartParameterTemplateCreate(AjaxCreateView):

View File

@ -0,0 +1 @@
{% if currency %}{{ currency.symbol }}{% endif %}{{ price }}{% if currency %} {{ currency.suffix }}{% endif %}