mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-30 04:26:44 +00:00
Refactor forms for sales orders
This commit is contained in:
parent
984828f3bb
commit
993abd9d91
@ -42,15 +42,10 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("#new-sales-order").click(function() {
|
$("#new-sales-order").click(function() {
|
||||||
launchModalForm(
|
|
||||||
"{% url 'so-create' %}",
|
createSalesOrder({
|
||||||
{
|
customer: {{ company.pk }},
|
||||||
data: {
|
});
|
||||||
customer: {{ company.id }},
|
|
||||||
},
|
|
||||||
follow: true,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -12,7 +12,6 @@ from mptt.fields import TreeNodeChoiceField
|
|||||||
|
|
||||||
from InvenTree.forms import HelperForm
|
from InvenTree.forms import HelperForm
|
||||||
from InvenTree.fields import InvenTreeMoneyField, RoundingDecimalFormField
|
from InvenTree.fields import InvenTreeMoneyField, RoundingDecimalFormField
|
||||||
from InvenTree.fields import DatePickerFormField
|
|
||||||
|
|
||||||
from InvenTree.helpers import clean_decimal
|
from InvenTree.helpers import clean_decimal
|
||||||
|
|
||||||
@ -97,41 +96,6 @@ class ReceivePurchaseOrderForm(HelperForm):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class EditSalesOrderForm(HelperForm):
|
|
||||||
""" Form for editing a SalesOrder object """
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
|
|
||||||
self.field_prefix = {
|
|
||||||
'reference': 'SO',
|
|
||||||
'link': 'fa-link',
|
|
||||||
'target_date': 'fa-calendar-alt',
|
|
||||||
}
|
|
||||||
|
|
||||||
self.field_placeholder = {
|
|
||||||
'reference': _('Enter sales order number'),
|
|
||||||
}
|
|
||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
target_date = DatePickerFormField(
|
|
||||||
label=_('Target Date'),
|
|
||||||
help_text=_('Target date for order completion. Order will be overdue after this date.'),
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = SalesOrder
|
|
||||||
fields = [
|
|
||||||
'reference',
|
|
||||||
'customer',
|
|
||||||
'customer_reference',
|
|
||||||
'description',
|
|
||||||
'target_date',
|
|
||||||
'link',
|
|
||||||
'responsible',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class EditPurchaseOrderLineItemForm(HelperForm):
|
class EditPurchaseOrderLineItemForm(HelperForm):
|
||||||
""" Form for editing a PurchaseOrderLineItem object """
|
""" Form for editing a PurchaseOrderLineItem object """
|
||||||
|
|
||||||
|
@ -231,6 +231,7 @@ class SalesOrderSerializer(InvenTreeModelSerializer):
|
|||||||
'notes',
|
'notes',
|
||||||
'overdue',
|
'overdue',
|
||||||
'reference',
|
'reference',
|
||||||
|
'responsible',
|
||||||
'status',
|
'status',
|
||||||
'status_text',
|
'status_text',
|
||||||
'shipment_date',
|
'shipment_date',
|
||||||
|
@ -153,7 +153,28 @@ enableNavbar({
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("#edit-order").click(function() {
|
$("#edit-order").click(function() {
|
||||||
launchModalForm("{% url 'so-edit' order.id %}", {
|
|
||||||
|
constructForm('{% url "api-so-detail" order.pk %}', {
|
||||||
|
fields: {
|
||||||
|
reference: {
|
||||||
|
prefix: "{% settings_value 'SALESORDER_REFERENCE_PREFIX' %}",
|
||||||
|
},
|
||||||
|
{% if order.lines.count == 0 and order.status == SalesOrderStatus.PENDING %}
|
||||||
|
customer: {
|
||||||
|
},
|
||||||
|
{% endif %}
|
||||||
|
description: {},
|
||||||
|
target_date: {
|
||||||
|
icon: 'fa-calendar-alt',
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
icon: 'fa-link',
|
||||||
|
},
|
||||||
|
responsible: {
|
||||||
|
icon: 'fa-user',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
title: '{% trans "Edit Sales Order" %}',
|
||||||
reload: true,
|
reload: true,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -178,18 +178,7 @@ $("#order-print").click(function() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
$("#so-create").click(function() {
|
$("#so-create").click(function() {
|
||||||
launchModalForm("{% url 'so-create' %}",
|
createSalesOrder();
|
||||||
{
|
|
||||||
follow: true,
|
|
||||||
secondary: [
|
|
||||||
{
|
|
||||||
field: 'customer',
|
|
||||||
label: '{% trans "New Customer" %}',
|
|
||||||
title: '{% trans "Create new Customer" %}',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -11,7 +11,6 @@ from django.contrib.auth.models import Group
|
|||||||
from InvenTree.status_codes import PurchaseOrderStatus
|
from InvenTree.status_codes import PurchaseOrderStatus
|
||||||
|
|
||||||
from .models import PurchaseOrder, PurchaseOrderLineItem
|
from .models import PurchaseOrder, PurchaseOrderLineItem
|
||||||
from .models import SalesOrder
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
@ -60,88 +59,6 @@ class OrderListTest(OrderViewTestCase):
|
|||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
|
||||||
class SalesOrderCreate(OrderViewTestCase):
|
|
||||||
"""
|
|
||||||
Create a SalesOrder using the form view
|
|
||||||
"""
|
|
||||||
|
|
||||||
URL = reverse('so-create')
|
|
||||||
|
|
||||||
def test_create_view(self):
|
|
||||||
"""
|
|
||||||
Retrieve the view for creating a sales order'
|
|
||||||
"""
|
|
||||||
|
|
||||||
response = self.client.get(self.URL, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
def post(self, data, **kwargs):
|
|
||||||
|
|
||||||
return self.client.post(self.URL, data, HTTP_X_REQUESTED_WITH='XMLHttpRequest', **kwargs)
|
|
||||||
|
|
||||||
def test_post_error(self):
|
|
||||||
"""
|
|
||||||
POST with errors
|
|
||||||
"""
|
|
||||||
|
|
||||||
n = SalesOrder.objects.count()
|
|
||||||
|
|
||||||
data = {
|
|
||||||
'reference': '12345678',
|
|
||||||
}
|
|
||||||
|
|
||||||
response = self.post(data)
|
|
||||||
|
|
||||||
data = json.loads(response.content)
|
|
||||||
|
|
||||||
self.assertIn('form_valid', data.keys())
|
|
||||||
|
|
||||||
# Customer is not specified - should return False
|
|
||||||
self.assertFalse(data['form_valid'])
|
|
||||||
|
|
||||||
errors = json.loads(data['form_errors'])
|
|
||||||
|
|
||||||
self.assertIn('customer', errors.keys())
|
|
||||||
self.assertIn('description', errors.keys())
|
|
||||||
|
|
||||||
# No new SalesOrder objects should have been created
|
|
||||||
self.assertEqual(SalesOrder.objects.count(), n)
|
|
||||||
|
|
||||||
def test_post_valid(self):
|
|
||||||
"""
|
|
||||||
POST a valid SalesOrder
|
|
||||||
"""
|
|
||||||
|
|
||||||
n = SalesOrder.objects.count()
|
|
||||||
|
|
||||||
data = {
|
|
||||||
'reference': '12345678',
|
|
||||||
'customer': 4,
|
|
||||||
'description': 'A description',
|
|
||||||
}
|
|
||||||
|
|
||||||
response = self.post(data)
|
|
||||||
|
|
||||||
json_data = json.loads(response.content)
|
|
||||||
|
|
||||||
self.assertTrue(json_data['form_valid'])
|
|
||||||
|
|
||||||
# Create another SalesOrder, this time with a target date
|
|
||||||
data = {
|
|
||||||
'reference': '12345679',
|
|
||||||
'customer': 4,
|
|
||||||
'description': 'Another order, this one with a target date!',
|
|
||||||
'target_date': '2020-12-25',
|
|
||||||
}
|
|
||||||
|
|
||||||
response = self.post(data)
|
|
||||||
|
|
||||||
json_data = json.loads(response.content)
|
|
||||||
|
|
||||||
self.assertEqual(SalesOrder.objects.count(), n + 2)
|
|
||||||
|
|
||||||
|
|
||||||
class POTests(OrderViewTestCase):
|
class POTests(OrderViewTestCase):
|
||||||
""" Tests for PurchaseOrder views """
|
""" Tests for PurchaseOrder views """
|
||||||
|
|
||||||
|
@ -47,8 +47,6 @@ purchase_order_urls = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
sales_order_detail_urls = [
|
sales_order_detail_urls = [
|
||||||
|
|
||||||
url(r'^edit/', views.SalesOrderEdit.as_view(), name='so-edit'),
|
|
||||||
url(r'^cancel/', views.SalesOrderCancel.as_view(), name='so-cancel'),
|
url(r'^cancel/', views.SalesOrderCancel.as_view(), name='so-cancel'),
|
||||||
url(r'^ship/', views.SalesOrderShip.as_view(), name='so-ship'),
|
url(r'^ship/', views.SalesOrderShip.as_view(), name='so-ship'),
|
||||||
|
|
||||||
@ -61,8 +59,6 @@ sales_order_detail_urls = [
|
|||||||
|
|
||||||
sales_order_urls = [
|
sales_order_urls = [
|
||||||
|
|
||||||
url(r'^new/', views.SalesOrderCreate.as_view(), name='so-create'),
|
|
||||||
|
|
||||||
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'^(?P<pk>\d+)/', include([
|
||||||
|
@ -42,7 +42,8 @@ from InvenTree.helpers import DownloadFile, str2bool
|
|||||||
from InvenTree.helpers import extract_serial_numbers
|
from InvenTree.helpers import extract_serial_numbers
|
||||||
from InvenTree.views import InvenTreeRoleMixin
|
from InvenTree.views import InvenTreeRoleMixin
|
||||||
|
|
||||||
from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus, StockStatus
|
from InvenTree.status_codes import PurchaseOrderStatus, StockStatus
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger("inventree")
|
logger = logging.getLogger("inventree")
|
||||||
|
|
||||||
@ -143,57 +144,6 @@ class SalesOrderNotes(InvenTreeRoleMixin, UpdateView):
|
|||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class SalesOrderCreate(AjaxCreateView):
|
|
||||||
""" View for creating a new SalesOrder object """
|
|
||||||
|
|
||||||
model = SalesOrder
|
|
||||||
ajax_form_title = _("Create Sales Order")
|
|
||||||
form_class = order_forms.EditSalesOrderForm
|
|
||||||
|
|
||||||
def get_initial(self):
|
|
||||||
initials = super().get_initial().copy()
|
|
||||||
|
|
||||||
initials['reference'] = SalesOrder.getNextOrderNumber()
|
|
||||||
initials['status'] = SalesOrderStatus.PENDING
|
|
||||||
|
|
||||||
customer_id = self.request.GET.get('customer', None)
|
|
||||||
|
|
||||||
if customer_id is not None:
|
|
||||||
try:
|
|
||||||
customer = Company.objects.get(id=customer_id)
|
|
||||||
initials['customer'] = customer
|
|
||||||
except (Company.DoesNotExist, ValueError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
return initials
|
|
||||||
|
|
||||||
def save(self, form, **kwargs):
|
|
||||||
"""
|
|
||||||
Record the user who created this SalesOrder
|
|
||||||
"""
|
|
||||||
|
|
||||||
order = form.save(commit=False)
|
|
||||||
order.created_by = self.request.user
|
|
||||||
|
|
||||||
return super().save(form)
|
|
||||||
|
|
||||||
|
|
||||||
class SalesOrderEdit(AjaxUpdateView):
|
|
||||||
""" View for editing a SalesOrder """
|
|
||||||
|
|
||||||
model = SalesOrder
|
|
||||||
ajax_form_title = _('Edit Sales Order')
|
|
||||||
form_class = order_forms.EditSalesOrderForm
|
|
||||||
|
|
||||||
def get_form(self):
|
|
||||||
form = super().get_form()
|
|
||||||
|
|
||||||
# Prevent user from editing customer
|
|
||||||
form.fields['customer'].widget = HiddenInput()
|
|
||||||
|
|
||||||
return form
|
|
||||||
|
|
||||||
|
|
||||||
class PurchaseOrderCancel(AjaxUpdateView):
|
class PurchaseOrderCancel(AjaxUpdateView):
|
||||||
""" View for cancelling a purchase order """
|
""" View for cancelling a purchase order """
|
||||||
|
|
||||||
|
@ -369,6 +369,75 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("#part-edit").click(function() {
|
$("#part-edit").click(function() {
|
||||||
|
|
||||||
|
constructForm('{% url "api-part-detail" part.id %}', {
|
||||||
|
focus: 'name',
|
||||||
|
fields: {
|
||||||
|
category: {
|
||||||
|
secondary: {
|
||||||
|
label: '{% trans "New Category" %}',
|
||||||
|
title: '{% trans "Create New Part Category" %}',
|
||||||
|
api_url: '{% url "api-part-category-list" %}',
|
||||||
|
method: 'POST',
|
||||||
|
fields: {
|
||||||
|
name: {},
|
||||||
|
description: {},
|
||||||
|
parent: {
|
||||||
|
secondary: {
|
||||||
|
title: '{% trans "New Parent" %}',
|
||||||
|
api_url: '{% url "api-part-category-list" %}',
|
||||||
|
method: 'POST',
|
||||||
|
fields: {
|
||||||
|
name: {},
|
||||||
|
description: {},
|
||||||
|
parent: {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
placeholder: 'part name',
|
||||||
|
},
|
||||||
|
IPN: {},
|
||||||
|
description: {},
|
||||||
|
revision: {},
|
||||||
|
keywords: {
|
||||||
|
icon: 'fa-key',
|
||||||
|
},
|
||||||
|
variant_of: {},
|
||||||
|
link: {
|
||||||
|
icon: 'fa-link',
|
||||||
|
},
|
||||||
|
default_location: {
|
||||||
|
secondary: {
|
||||||
|
label: '{% trans "New Location" %}',
|
||||||
|
title: '{% trans "Create new stock location" %}',
|
||||||
|
|
||||||
|
},
|
||||||
|
},
|
||||||
|
default_supplier: {
|
||||||
|
filters: {
|
||||||
|
part: {{ part.pk }},
|
||||||
|
part_detail: true,
|
||||||
|
manufacturer_detail: true,
|
||||||
|
supplier_detail: true,
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
label: '{% trans "New Supplier Part" %}',
|
||||||
|
title: '{% trans "Create new supplier part" %}',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
units: {},
|
||||||
|
minimum_stock: {},
|
||||||
|
},
|
||||||
|
title: '{% trans "Edit Part" %}',
|
||||||
|
reload: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
launchModalForm(
|
launchModalForm(
|
||||||
"{% url 'part-edit' part.id %}",
|
"{% url 'part-edit' part.id %}",
|
||||||
{
|
{
|
||||||
|
@ -2,7 +2,37 @@
|
|||||||
{% load inventree_extras %}
|
{% load inventree_extras %}
|
||||||
|
|
||||||
|
|
||||||
// Create a new purchase order
|
// Create a new SalesOrder
|
||||||
|
function createSalesOrder(options={}) {
|
||||||
|
|
||||||
|
constructForm('{% url "api-so-list" %}', {
|
||||||
|
method: 'POST',
|
||||||
|
fields: {
|
||||||
|
reference: {
|
||||||
|
prefix: '{% settings_value "SALESORDER_REFERENCE_PREFIX" %}',
|
||||||
|
},
|
||||||
|
customer: {
|
||||||
|
value: options.customer,
|
||||||
|
},
|
||||||
|
description: {},
|
||||||
|
target_date: {
|
||||||
|
icon: 'fa-calendar-alt',
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
icon: 'fa-link',
|
||||||
|
},
|
||||||
|
responsible: {
|
||||||
|
icon: 'fa-user',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSuccess: function(data) {
|
||||||
|
location.href = `/order/sales-order/${data.pk}/`;
|
||||||
|
},
|
||||||
|
title: '{% trans "Create Sales Order" %}',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new PurchaseOrder
|
||||||
function createPurchaseOrder(options={}) {
|
function createPurchaseOrder(options={}) {
|
||||||
|
|
||||||
constructForm('{% url "api-po-list" %}', {
|
constructForm('{% url "api-po-list" %}', {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user