mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +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() {
|
||||
launchModalForm(
|
||||
"{% url 'so-create' %}",
|
||||
{
|
||||
data: {
|
||||
customer: {{ company.id }},
|
||||
},
|
||||
follow: true,
|
||||
},
|
||||
);
|
||||
|
||||
createSalesOrder({
|
||||
customer: {{ company.pk }},
|
||||
});
|
||||
});
|
||||
|
||||
{% endblock %}
|
@ -12,7 +12,6 @@ from mptt.fields import TreeNodeChoiceField
|
||||
|
||||
from InvenTree.forms import HelperForm
|
||||
from InvenTree.fields import InvenTreeMoneyField, RoundingDecimalFormField
|
||||
from InvenTree.fields import DatePickerFormField
|
||||
|
||||
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):
|
||||
""" Form for editing a PurchaseOrderLineItem object """
|
||||
|
||||
|
@ -231,6 +231,7 @@ class SalesOrderSerializer(InvenTreeModelSerializer):
|
||||
'notes',
|
||||
'overdue',
|
||||
'reference',
|
||||
'responsible',
|
||||
'status',
|
||||
'status_text',
|
||||
'shipment_date',
|
||||
|
@ -153,7 +153,28 @@ enableNavbar({
|
||||
});
|
||||
|
||||
$("#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,
|
||||
});
|
||||
});
|
||||
|
@ -178,18 +178,7 @@ $("#order-print").click(function() {
|
||||
})
|
||||
|
||||
$("#so-create").click(function() {
|
||||
launchModalForm("{% url 'so-create' %}",
|
||||
{
|
||||
follow: true,
|
||||
secondary: [
|
||||
{
|
||||
field: 'customer',
|
||||
label: '{% trans "New Customer" %}',
|
||||
title: '{% trans "Create new Customer" %}',
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
createSalesOrder();
|
||||
});
|
||||
|
||||
{% endblock %}
|
@ -11,7 +11,6 @@ from django.contrib.auth.models import Group
|
||||
from InvenTree.status_codes import PurchaseOrderStatus
|
||||
|
||||
from .models import PurchaseOrder, PurchaseOrderLineItem
|
||||
from .models import SalesOrder
|
||||
|
||||
import json
|
||||
|
||||
@ -60,88 +59,6 @@ class OrderListTest(OrderViewTestCase):
|
||||
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):
|
||||
""" Tests for PurchaseOrder views """
|
||||
|
||||
|
@ -47,8 +47,6 @@ purchase_order_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'^ship/', views.SalesOrderShip.as_view(), name='so-ship'),
|
||||
|
||||
@ -61,8 +59,6 @@ sales_order_detail_urls = [
|
||||
|
||||
sales_order_urls = [
|
||||
|
||||
url(r'^new/', views.SalesOrderCreate.as_view(), name='so-create'),
|
||||
|
||||
url(r'^line/', include([
|
||||
url(r'^new/', views.SOLineItemCreate.as_view(), name='so-line-item-create'),
|
||||
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.views import InvenTreeRoleMixin
|
||||
|
||||
from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus, StockStatus
|
||||
from InvenTree.status_codes import PurchaseOrderStatus, StockStatus
|
||||
|
||||
|
||||
logger = logging.getLogger("inventree")
|
||||
|
||||
@ -143,57 +144,6 @@ class SalesOrderNotes(InvenTreeRoleMixin, UpdateView):
|
||||
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):
|
||||
""" View for cancelling a purchase order """
|
||||
|
||||
|
@ -369,6 +369,75 @@
|
||||
});
|
||||
|
||||
$("#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(
|
||||
"{% url 'part-edit' part.id %}",
|
||||
{
|
||||
|
@ -2,7 +2,37 @@
|
||||
{% 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={}) {
|
||||
|
||||
constructForm('{% url "api-po-list" %}', {
|
||||
|
@ -146,4 +146,4 @@ user_urls = [
|
||||
|
||||
url(r'^(?P<pk>[0-9]+)/?$', UserDetail.as_view(), name='user-detail'),
|
||||
url(r'^$', UserList.as_view()),
|
||||
]
|
||||
]
|
||||
|
@ -1 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
Loading…
Reference in New Issue
Block a user