mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Refactoring forms for order line items
- Required some fixes for money serializer -
This commit is contained in:
parent
1cdf03ef49
commit
8c3a4b60ab
@ -5,16 +5,58 @@ Serializers used in various InvenTree apps
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from decimal import Decimal
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.core.exceptions import ValidationError as DjangoValidationError
|
from django.core.exceptions import ValidationError as DjangoValidationError
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from djmoney.contrib.django_rest_framework.fields import MoneyField
|
||||||
|
from djmoney.money import Money
|
||||||
|
from djmoney.utils import MONEY_CLASSES, get_currency_field_name
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.utils import model_meta
|
from rest_framework.utils import model_meta
|
||||||
from rest_framework.fields import empty
|
from rest_framework.fields import empty
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
from rest_framework.serializers import DecimalField
|
||||||
|
|
||||||
|
|
||||||
|
class InvenTreeMoneySerializer(MoneyField):
|
||||||
|
"""
|
||||||
|
Custom serializer for 'MoneyField',
|
||||||
|
which ensures that passed values are numerically valid
|
||||||
|
|
||||||
|
Ref: https://github.com/django-money/django-money/blob/master/djmoney/contrib/django_rest_framework/fields.py
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_value(self, data):
|
||||||
|
"""
|
||||||
|
Test that the returned amount is a valid Decimal
|
||||||
|
"""
|
||||||
|
|
||||||
|
amount = super(DecimalField, self).get_value(data)
|
||||||
|
|
||||||
|
# Convert an empty string to None
|
||||||
|
if len(str(amount).strip()) == 0:
|
||||||
|
amount = None
|
||||||
|
|
||||||
|
try:
|
||||||
|
if amount is not None:
|
||||||
|
amount = Decimal(amount)
|
||||||
|
except:
|
||||||
|
raise ValidationError(_("Must be a valid number"))
|
||||||
|
|
||||||
|
currency = data.get(get_currency_field_name(self.field_name), self.default_currency)
|
||||||
|
|
||||||
|
if currency and amount is not None and not isinstance(amount, MONEY_CLASSES) and amount is not empty:
|
||||||
|
return Money(amount, currency)
|
||||||
|
|
||||||
|
return amount
|
||||||
|
|
||||||
|
|
||||||
class UserSerializer(serializers.ModelSerializer):
|
class UserSerializer(serializers.ModelSerializer):
|
||||||
|
@ -514,7 +514,7 @@ class SOLineItemList(generics.ListCreateAPIView):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class SOLineItemDetail(generics.RetrieveUpdateAPIView):
|
class SOLineItemDetail(generics.RetrieveUpdateDestroyAPIView):
|
||||||
""" API endpoint for detail view of a SalesOrderLineItem object """
|
""" API endpoint for detail view of a SalesOrderLineItem object """
|
||||||
|
|
||||||
queryset = SalesOrderLineItem.objects.all()
|
queryset = SalesOrderLineItem.objects.all()
|
||||||
|
@ -698,7 +698,13 @@ class OrderLineItem(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
quantity = RoundingDecimalField(max_digits=15, decimal_places=5, validators=[MinValueValidator(0)], default=1, verbose_name=_('Quantity'), help_text=_('Item quantity'))
|
quantity = RoundingDecimalField(
|
||||||
|
verbose_name=_('Quantity'),
|
||||||
|
help_text=_('Item quantity'),
|
||||||
|
default=1,
|
||||||
|
max_digits=15, decimal_places=5,
|
||||||
|
validators=[MinValueValidator(0)],
|
||||||
|
)
|
||||||
|
|
||||||
reference = models.CharField(max_length=100, blank=True, verbose_name=_('Reference'), help_text=_('Line item reference'))
|
reference = models.CharField(max_length=100, blank=True, verbose_name=_('Reference'), help_text=_('Line item reference'))
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ from sql_util.utils import SubqueryCount
|
|||||||
import djmoney.settings
|
import djmoney.settings
|
||||||
|
|
||||||
from InvenTree.serializers import InvenTreeModelSerializer
|
from InvenTree.serializers import InvenTreeModelSerializer
|
||||||
|
from InvenTree.serializers import InvenTreeMoneySerializer
|
||||||
from InvenTree.serializers import InvenTreeAttachmentSerializerField
|
from InvenTree.serializers import InvenTreeAttachmentSerializerField
|
||||||
|
|
||||||
from company.serializers import CompanyBriefSerializer, SupplierPartSerializer
|
from company.serializers import CompanyBriefSerializer, SupplierPartSerializer
|
||||||
@ -124,6 +125,8 @@ class POLineItemSerializer(InvenTreeModelSerializer):
|
|||||||
part_detail = PartBriefSerializer(source='get_base_part', many=False, read_only=True)
|
part_detail = PartBriefSerializer(source='get_base_part', many=False, read_only=True)
|
||||||
supplier_part_detail = SupplierPartSerializer(source='part', many=False, read_only=True)
|
supplier_part_detail = SupplierPartSerializer(source='part', many=False, read_only=True)
|
||||||
|
|
||||||
|
purchase_price = InvenTreeMoneySerializer(max_digits=19, decimal_places=4)
|
||||||
|
|
||||||
purchase_price_string = serializers.CharField(source='purchase_price', read_only=True)
|
purchase_price_string = serializers.CharField(source='purchase_price', read_only=True)
|
||||||
|
|
||||||
destination = LocationBriefSerializer(source='get_destination', read_only=True)
|
destination = LocationBriefSerializer(source='get_destination', read_only=True)
|
||||||
@ -335,13 +338,20 @@ class SOLineItemSerializer(InvenTreeModelSerializer):
|
|||||||
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||||
allocations = SalesOrderAllocationSerializer(many=True, read_only=True)
|
allocations = SalesOrderAllocationSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
# TODO: Once https://github.com/inventree/InvenTree/issues/1687 is fixed, remove default values
|
quantity = serializers.FloatField()
|
||||||
quantity = serializers.FloatField(default=1)
|
|
||||||
|
|
||||||
allocated = serializers.FloatField(source='allocated_quantity', read_only=True)
|
allocated = serializers.FloatField(source='allocated_quantity', read_only=True)
|
||||||
fulfilled = serializers.FloatField(source='fulfilled_quantity', read_only=True)
|
fulfilled = serializers.FloatField(source='fulfilled_quantity', read_only=True)
|
||||||
|
|
||||||
|
sale_price = InvenTreeMoneySerializer(max_digits=19, decimal_places=4)
|
||||||
|
|
||||||
sale_price_string = serializers.CharField(source='sale_price', read_only=True)
|
sale_price_string = serializers.CharField(source='sale_price', read_only=True)
|
||||||
|
|
||||||
|
sale_price_currency = serializers.ChoiceField(
|
||||||
|
choices=djmoney.settings.CURRENCY_CHOICES,
|
||||||
|
help_text=_('Sale price currency'),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SalesOrderLineItem
|
model = SalesOrderLineItem
|
||||||
|
|
||||||
|
@ -377,16 +377,26 @@ function setupCallbacks() {
|
|||||||
|
|
||||||
var pk = $(this).attr('pk');
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
launchModalForm(`/order/sales-order/line/${pk}/edit/`, {
|
constructForm(`/api/order/so-line/${pk}/`, {
|
||||||
success: reloadTable,
|
fields: {
|
||||||
|
quantity: {},
|
||||||
|
reference: {},
|
||||||
|
sale_price: {},
|
||||||
|
sale_price_currency: {},
|
||||||
|
notes: {},
|
||||||
|
},
|
||||||
|
title: '{% trans "Edit Line Item" %}',
|
||||||
|
onSuccess: reloadTable,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
table.find(".button-delete").click(function() {
|
table.find(".button-delete").click(function() {
|
||||||
var pk = $(this).attr('pk');
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
launchModalForm(`/order/sales-order/line/${pk}/delete/`, {
|
constructForm(`/api/order/so-line/${pk}/`, {
|
||||||
success: reloadTable,
|
method: 'DELETE',
|
||||||
|
title: '{% trans "Delete Line Item" %}',
|
||||||
|
onSuccess: reloadTable,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
{% extends "modal_delete_form.html" %}
|
|
||||||
{% load i18n %}
|
|
||||||
|
|
||||||
{% block pre_form_content %}
|
|
||||||
{% trans "Are you sure you wish to delete this line item?" %}
|
|
||||||
{% endblock %}
|
|
@ -57,10 +57,6 @@ sales_order_urls = [
|
|||||||
|
|
||||||
url(r'^line/', include([
|
url(r'^line/', include([
|
||||||
url(r'^new/', views.SOLineItemCreate.as_view(), name='so-line-item-create'),
|
url(r'^new/', views.SOLineItemCreate.as_view(), name='so-line-item-create'),
|
||||||
url(r'^(?P<pk>\d+)/', include([
|
|
||||||
url(r'^edit/', views.SOLineItemEdit.as_view(), name='so-line-item-edit'),
|
|
||||||
url(r'^delete/', views.SOLineItemDelete.as_view(), name='so-line-item-delete'),
|
|
||||||
])),
|
|
||||||
])),
|
])),
|
||||||
|
|
||||||
# URLs for sales order allocations
|
# URLs for sales order allocations
|
||||||
|
@ -1197,34 +1197,6 @@ class SOLineItemCreate(AjaxCreateView):
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
class SOLineItemEdit(AjaxUpdateView):
|
|
||||||
""" View for editing a SalesOrderLineItem """
|
|
||||||
|
|
||||||
model = SalesOrderLineItem
|
|
||||||
form_class = order_forms.EditSalesOrderLineItemForm
|
|
||||||
ajax_form_title = _('Edit Line Item')
|
|
||||||
|
|
||||||
def get_form(self):
|
|
||||||
form = super().get_form()
|
|
||||||
|
|
||||||
form.fields.pop('order')
|
|
||||||
form.fields.pop('part')
|
|
||||||
|
|
||||||
return form
|
|
||||||
|
|
||||||
|
|
||||||
class SOLineItemDelete(AjaxDeleteView):
|
|
||||||
|
|
||||||
model = SalesOrderLineItem
|
|
||||||
ajax_form_title = _("Delete Line Item")
|
|
||||||
ajax_template_name = "order/so_lineitem_delete.html"
|
|
||||||
|
|
||||||
def get_data(self):
|
|
||||||
return {
|
|
||||||
'danger': _('Deleted line item'),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class SalesOrderAssignSerials(AjaxView, FormMixin):
|
class SalesOrderAssignSerials(AjaxView, FormMixin):
|
||||||
"""
|
"""
|
||||||
View for assigning stock items to a sales order,
|
View for assigning stock items to a sales order,
|
||||||
|
Loading…
Reference in New Issue
Block a user