mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-28 19:46:46 +00:00
Specify 'default' functions for 'reference' field in SalesOrder and PurchaseOrder
- Refactor CreatePurchaseOrder form - Some migrations
This commit is contained in:
parent
7e5c9aa043
commit
984828f3bb
20
InvenTree/company/migrations/0040_alter_company_currency.py
Normal file
20
InvenTree/company/migrations/0040_alter_company_currency.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Generated by Django 3.2.4 on 2021-07-02 13:21
|
||||||
|
|
||||||
|
import InvenTree.validators
|
||||||
|
import common.settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('company', '0039_auto_20210701_0509'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='company',
|
||||||
|
name='currency',
|
||||||
|
field=models.CharField(blank=True, default=common.settings.currency_code_default, help_text='Default currency used for this company', max_length=3, validators=[InvenTree.validators.validate_currency_code], verbose_name='Currency'),
|
||||||
|
),
|
||||||
|
]
|
@ -115,16 +115,11 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$("#company-order-2").click(function() {
|
$("#company-order-2").click(function() {
|
||||||
launchModalForm("{% url 'po-create' %}",
|
createPurchaseOrder({
|
||||||
{
|
supplier: {{ company.pk }},
|
||||||
data: {
|
|
||||||
supplier: {{ company.id }},
|
|
||||||
},
|
|
||||||
follow: true,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$('#company-delete').click(function() {
|
$('#company-delete').click(function() {
|
||||||
constructForm('{% url "api-company-detail" company.pk %}', {
|
constructForm('{% url "api-company-detail" company.pk %}', {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
|
@ -39,14 +39,9 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function newOrder() {
|
function newOrder() {
|
||||||
launchModalForm("{% url 'po-create' %}",
|
createPurchaseOrder({
|
||||||
{
|
supplier: {{ company.pk }},
|
||||||
data: {
|
|
||||||
supplier: {{ company.id }},
|
|
||||||
},
|
|
||||||
follow: true,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,11 +5,12 @@ JSON API for the Order app
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.conf.urls import url, include
|
||||||
|
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
from rest_framework import generics
|
from rest_framework import generics
|
||||||
from rest_framework import filters
|
from rest_framework import filters, status
|
||||||
|
from rest_framework.response import Response
|
||||||
from django.conf.urls import url, include
|
|
||||||
|
|
||||||
from InvenTree.helpers import str2bool
|
from InvenTree.helpers import str2bool
|
||||||
from InvenTree.api import AttachmentMixin
|
from InvenTree.api import AttachmentMixin
|
||||||
@ -38,6 +39,20 @@ class POList(generics.ListCreateAPIView):
|
|||||||
queryset = PurchaseOrder.objects.all()
|
queryset = PurchaseOrder.objects.all()
|
||||||
serializer_class = POSerializer
|
serializer_class = POSerializer
|
||||||
|
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Save user information on create
|
||||||
|
"""
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
|
item = serializer.save()
|
||||||
|
item.created_by = request.user
|
||||||
|
item.save()
|
||||||
|
|
||||||
|
headers = self.get_success_headers(serializer.data)
|
||||||
|
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
def get_serializer(self, *args, **kwargs):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -279,6 +294,20 @@ class SOList(generics.ListCreateAPIView):
|
|||||||
queryset = SalesOrder.objects.all()
|
queryset = SalesOrder.objects.all()
|
||||||
serializer_class = SalesOrderSerializer
|
serializer_class = SalesOrderSerializer
|
||||||
|
|
||||||
|
def create(self, request, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Save user information on create
|
||||||
|
"""
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
||||||
|
item = serializer.save()
|
||||||
|
item.created_by = request.user
|
||||||
|
item.save()
|
||||||
|
|
||||||
|
headers = self.get_success_headers(serializer.data)
|
||||||
|
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||||
|
|
||||||
def get_serializer(self, *args, **kwargs):
|
def get_serializer(self, *args, **kwargs):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -97,41 +97,6 @@ class ReceivePurchaseOrderForm(HelperForm):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class EditPurchaseOrderForm(HelperForm):
|
|
||||||
""" Form for editing a PurchaseOrder object """
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
|
|
||||||
self.field_prefix = {
|
|
||||||
'reference': 'PO',
|
|
||||||
'link': 'fa-link',
|
|
||||||
'target_date': 'fa-calendar-alt',
|
|
||||||
}
|
|
||||||
|
|
||||||
self.field_placeholder = {
|
|
||||||
'reference': _('Purchase Order reference'),
|
|
||||||
}
|
|
||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
target_date = DatePickerFormField(
|
|
||||||
label=_('Target Date'),
|
|
||||||
help_text=_('Target date for order delivery. Order will be overdue after this date.'),
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = PurchaseOrder
|
|
||||||
fields = [
|
|
||||||
'reference',
|
|
||||||
'supplier',
|
|
||||||
'supplier_reference',
|
|
||||||
'description',
|
|
||||||
'target_date',
|
|
||||||
'link',
|
|
||||||
'responsible',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class EditSalesOrderForm(HelperForm):
|
class EditSalesOrderForm(HelperForm):
|
||||||
""" Form for editing a SalesOrder object """
|
""" Form for editing a SalesOrder object """
|
||||||
|
|
||||||
|
24
InvenTree/order/migrations/0048_auto_20210702_2321.py
Normal file
24
InvenTree/order/migrations/0048_auto_20210702_2321.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 3.2.4 on 2021-07-02 13:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import order.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('order', '0047_auto_20210701_0509'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='purchaseorder',
|
||||||
|
name='reference',
|
||||||
|
field=models.CharField(default=order.models.get_next_po_number, help_text='Order reference', max_length=64, unique=True, verbose_name='Reference'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='salesorder',
|
||||||
|
name='reference',
|
||||||
|
field=models.CharField(default=order.models.get_next_so_number, help_text='Order reference', max_length=64, unique=True, verbose_name='Reference'),
|
||||||
|
),
|
||||||
|
]
|
@ -31,6 +31,60 @@ from InvenTree.status_codes import PurchaseOrderStatus, SalesOrderStatus, StockS
|
|||||||
from InvenTree.models import InvenTreeAttachment
|
from InvenTree.models import InvenTreeAttachment
|
||||||
|
|
||||||
|
|
||||||
|
def get_next_po_number():
|
||||||
|
"""
|
||||||
|
Returns the next available PurchaseOrder reference number
|
||||||
|
"""
|
||||||
|
|
||||||
|
if PurchaseOrder.objects.count() == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
order = PurchaseOrder.objects.exclude(reference=None).last()
|
||||||
|
|
||||||
|
attempts = set([order.reference])
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
reference = increment(order.reference)
|
||||||
|
|
||||||
|
if reference in attempts:
|
||||||
|
# Escape infinite recursion
|
||||||
|
return reference
|
||||||
|
|
||||||
|
if PurchaseOrder.objects.filter(reference=reference).exists():
|
||||||
|
attempts.add(reference)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
return reference
|
||||||
|
|
||||||
|
|
||||||
|
def get_next_so_number():
|
||||||
|
"""
|
||||||
|
Returns the next available SalesOrder reference number
|
||||||
|
"""
|
||||||
|
|
||||||
|
if SalesOrder.objects.count() == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
order = SalesOrder.objects.exclude(reference=None).last()
|
||||||
|
|
||||||
|
attempts = set([order.reference])
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
reference = increment(order.reference)
|
||||||
|
|
||||||
|
if reference in attempts:
|
||||||
|
# Escape infinite recursion
|
||||||
|
return reference
|
||||||
|
|
||||||
|
if SalesOrder.objects.filter(reference=reference).exists():
|
||||||
|
attempts.add(reference)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
return reference
|
||||||
|
|
||||||
|
|
||||||
class Order(models.Model):
|
class Order(models.Model):
|
||||||
""" Abstract model for an order.
|
""" Abstract model for an order.
|
||||||
|
|
||||||
@ -72,6 +126,8 @@ class Order(models.Model):
|
|||||||
while 1:
|
while 1:
|
||||||
new_ref = increment(ref)
|
new_ref = increment(ref)
|
||||||
|
|
||||||
|
print("Reference:", new_ref)
|
||||||
|
|
||||||
if new_ref in tries:
|
if new_ref in tries:
|
||||||
# We are in a looping situation - simply return the original one
|
# We are in a looping situation - simply return the original one
|
||||||
return ref
|
return ref
|
||||||
@ -95,8 +151,6 @@ class Order(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
reference = models.CharField(unique=True, max_length=64, blank=False, verbose_name=_('Reference'), help_text=_('Order reference'))
|
|
||||||
|
|
||||||
description = models.CharField(max_length=250, verbose_name=_('Description'), help_text=_('Order description'))
|
description = models.CharField(max_length=250, verbose_name=_('Description'), help_text=_('Order description'))
|
||||||
|
|
||||||
link = models.URLField(blank=True, verbose_name=_('Link'), help_text=_('Link to external page'))
|
link = models.URLField(blank=True, verbose_name=_('Link'), help_text=_('Link to external page'))
|
||||||
@ -181,6 +235,15 @@ class PurchaseOrder(Order):
|
|||||||
|
|
||||||
return f"{prefix}{self.reference} - {self.supplier.name}"
|
return f"{prefix}{self.reference} - {self.supplier.name}"
|
||||||
|
|
||||||
|
reference = models.CharField(
|
||||||
|
unique=True,
|
||||||
|
max_length=64,
|
||||||
|
blank=False,
|
||||||
|
verbose_name=_('Reference'),
|
||||||
|
help_text=_('Order reference'),
|
||||||
|
default=get_next_po_number,
|
||||||
|
)
|
||||||
|
|
||||||
status = models.PositiveIntegerField(default=PurchaseOrderStatus.PENDING, choices=PurchaseOrderStatus.items(),
|
status = models.PositiveIntegerField(default=PurchaseOrderStatus.PENDING, choices=PurchaseOrderStatus.items(),
|
||||||
help_text=_('Purchase order status'))
|
help_text=_('Purchase order status'))
|
||||||
|
|
||||||
@ -459,6 +522,15 @@ class SalesOrder(Order):
|
|||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return reverse('so-detail', kwargs={'pk': self.id})
|
return reverse('so-detail', kwargs={'pk': self.id})
|
||||||
|
|
||||||
|
reference = models.CharField(
|
||||||
|
unique=True,
|
||||||
|
max_length=64,
|
||||||
|
blank=False,
|
||||||
|
verbose_name=_('Reference'),
|
||||||
|
help_text=_('Order reference'),
|
||||||
|
default=get_next_so_number,
|
||||||
|
)
|
||||||
|
|
||||||
customer = models.ForeignKey(
|
customer = models.ForeignKey(
|
||||||
Company,
|
Company,
|
||||||
on_delete=models.SET_NULL,
|
on_delete=models.SET_NULL,
|
||||||
|
@ -69,6 +69,8 @@ class POSerializer(InvenTreeModelSerializer):
|
|||||||
|
|
||||||
overdue = serializers.BooleanField(required=False, read_only=True)
|
overdue = serializers.BooleanField(required=False, read_only=True)
|
||||||
|
|
||||||
|
reference = serializers.CharField(required=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PurchaseOrder
|
model = PurchaseOrder
|
||||||
|
|
||||||
@ -212,6 +214,8 @@ class SalesOrderSerializer(InvenTreeModelSerializer):
|
|||||||
|
|
||||||
overdue = serializers.BooleanField(required=False, read_only=True)
|
overdue = serializers.BooleanField(required=False, read_only=True)
|
||||||
|
|
||||||
|
reference = serializers.CharField(required=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SalesOrder
|
model = SalesOrder
|
||||||
|
|
||||||
|
@ -176,18 +176,7 @@ $("#order-print").click(function() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
$("#po-create").click(function() {
|
$("#po-create").click(function() {
|
||||||
launchModalForm("{% url 'po-create' %}",
|
createPurchaseOrder();
|
||||||
{
|
|
||||||
follow: true,
|
|
||||||
secondary: [
|
|
||||||
{
|
|
||||||
field: 'supplier',
|
|
||||||
label: '{% trans "New Supplier" %}',
|
|
||||||
title: '{% trans "Create new Supplier" %}',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
loadPurchaseOrderTable("#purchase-order-table", {
|
loadPurchaseOrderTable("#purchase-order-table", {
|
||||||
|
@ -152,22 +152,6 @@ class POTests(OrderViewTestCase):
|
|||||||
keys = response.context.keys()
|
keys = response.context.keys()
|
||||||
self.assertIn('PurchaseOrderStatus', keys)
|
self.assertIn('PurchaseOrderStatus', keys)
|
||||||
|
|
||||||
def test_po_create(self):
|
|
||||||
""" Launch forms to create new PurchaseOrder"""
|
|
||||||
url = reverse('po-create')
|
|
||||||
|
|
||||||
# Without a supplier ID
|
|
||||||
response = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
# With a valid supplier ID
|
|
||||||
response = self.client.get(url, {'supplier': 1}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
# With an invalid supplier ID
|
|
||||||
response = self.client.get(url, {'supplier': 'goat'}, HTTP_X_REQUESTED_WITH='XMLHttpRequest')
|
|
||||||
self.assertEqual(response.status_code, 200)
|
|
||||||
|
|
||||||
def test_po_export(self):
|
def test_po_export(self):
|
||||||
""" Export PurchaseOrder """
|
""" Export PurchaseOrder """
|
||||||
|
|
||||||
|
@ -60,12 +60,6 @@ class OrderTest(TestCase):
|
|||||||
order.save()
|
order.save()
|
||||||
self.assertFalse(order.is_overdue)
|
self.assertFalse(order.is_overdue)
|
||||||
|
|
||||||
def test_increment(self):
|
|
||||||
|
|
||||||
next_ref = PurchaseOrder.getNextOrderNumber()
|
|
||||||
|
|
||||||
self.assertEqual(next_ref, '0008')
|
|
||||||
|
|
||||||
def test_on_order(self):
|
def test_on_order(self):
|
||||||
""" There should be 3 separate items on order for the M2x4 LPHS part """
|
""" There should be 3 separate items on order for the M2x4 LPHS part """
|
||||||
|
|
||||||
|
@ -28,8 +28,6 @@ purchase_order_detail_urls = [
|
|||||||
|
|
||||||
purchase_order_urls = [
|
purchase_order_urls = [
|
||||||
|
|
||||||
url(r'^new/', views.PurchaseOrderCreate.as_view(), name='po-create'),
|
|
||||||
|
|
||||||
url(r'^order-parts/', views.OrderParts.as_view(), name='order-parts'),
|
url(r'^order-parts/', views.OrderParts.as_view(), name='order-parts'),
|
||||||
url(r'^pricing/', views.LineItemPricing.as_view(), name='line-pricing'),
|
url(r'^pricing/', views.LineItemPricing.as_view(), name='line-pricing'),
|
||||||
|
|
||||||
|
@ -143,43 +143,6 @@ class SalesOrderNotes(InvenTreeRoleMixin, UpdateView):
|
|||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
class PurchaseOrderCreate(AjaxCreateView):
|
|
||||||
"""
|
|
||||||
View for creating a new PurchaseOrder object using a modal form
|
|
||||||
"""
|
|
||||||
|
|
||||||
model = PurchaseOrder
|
|
||||||
ajax_form_title = _("Create Purchase Order")
|
|
||||||
form_class = order_forms.EditPurchaseOrderForm
|
|
||||||
|
|
||||||
def get_initial(self):
|
|
||||||
initials = super().get_initial().copy()
|
|
||||||
|
|
||||||
initials['reference'] = PurchaseOrder.getNextOrderNumber()
|
|
||||||
initials['status'] = PurchaseOrderStatus.PENDING
|
|
||||||
|
|
||||||
supplier_id = self.request.GET.get('supplier', None)
|
|
||||||
|
|
||||||
if supplier_id:
|
|
||||||
try:
|
|
||||||
supplier = Company.objects.get(id=supplier_id)
|
|
||||||
initials['supplier'] = supplier
|
|
||||||
except (Company.DoesNotExist, ValueError):
|
|
||||||
pass
|
|
||||||
|
|
||||||
return initials
|
|
||||||
|
|
||||||
def save(self, form, **kwargs):
|
|
||||||
"""
|
|
||||||
Record the user who created this PurchaseOrder
|
|
||||||
"""
|
|
||||||
|
|
||||||
order = form.save(commit=False)
|
|
||||||
order.created_by = self.request.user
|
|
||||||
|
|
||||||
return super().save(form)
|
|
||||||
|
|
||||||
|
|
||||||
class SalesOrderCreate(AjaxCreateView):
|
class SalesOrderCreate(AjaxCreateView):
|
||||||
""" View for creating a new SalesOrder object """
|
""" View for creating a new SalesOrder object """
|
||||||
|
|
||||||
|
@ -2,17 +2,21 @@
|
|||||||
JSON API for the Stock app
|
JSON API for the Stock app
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django_filters.rest_framework import FilterSet, DjangoFilterBackend
|
|
||||||
from django_filters import NumberFilter
|
|
||||||
|
|
||||||
from rest_framework import status
|
|
||||||
|
|
||||||
from django.conf.urls import url, include
|
from django.conf.urls import url, include
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.http import JsonResponse
|
from django.http import JsonResponse
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from rest_framework import status
|
||||||
|
from rest_framework.serializers import ValidationError
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework import generics, filters, permissions
|
||||||
|
|
||||||
|
from django_filters.rest_framework import FilterSet, DjangoFilterBackend
|
||||||
|
from django_filters import NumberFilter
|
||||||
|
|
||||||
from .models import StockLocation, StockItem
|
from .models import StockLocation, StockItem
|
||||||
from .models import StockItemTracking
|
from .models import StockItemTracking
|
||||||
from .models import StockItemAttachment
|
from .models import StockItemAttachment
|
||||||
@ -44,11 +48,6 @@ from decimal import Decimal, InvalidOperation
|
|||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from rest_framework.serializers import ValidationError
|
|
||||||
from rest_framework.views import APIView
|
|
||||||
from rest_framework.response import Response
|
|
||||||
from rest_framework import generics, filters, permissions
|
|
||||||
|
|
||||||
|
|
||||||
class StockCategoryTree(TreeSerializer):
|
class StockCategoryTree(TreeSerializer):
|
||||||
title = _('Stock')
|
title = _('Stock')
|
||||||
|
@ -1,6 +1,38 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load inventree_extras %}
|
{% load inventree_extras %}
|
||||||
|
|
||||||
|
|
||||||
|
// Create a new purchase order
|
||||||
|
function createPurchaseOrder(options={}) {
|
||||||
|
|
||||||
|
constructForm('{% url "api-po-list" %}', {
|
||||||
|
method: 'POST',
|
||||||
|
fields: {
|
||||||
|
reference: {
|
||||||
|
prefix: "{% settings_value 'PURCHASEORDER_REFERENCE_PREFIX' %}",
|
||||||
|
},
|
||||||
|
supplier: {
|
||||||
|
value: options.supplier,
|
||||||
|
},
|
||||||
|
description: {},
|
||||||
|
target_date: {
|
||||||
|
icon: 'fa-calendar-alt',
|
||||||
|
},
|
||||||
|
link: {
|
||||||
|
icon: 'fa-link',
|
||||||
|
},
|
||||||
|
responsible: {
|
||||||
|
icon: 'fa-user',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSuccess: function(data) {
|
||||||
|
location.href = `/order/purchase-order/${data.pk}/`;
|
||||||
|
},
|
||||||
|
title: '{% trans "Create Purchase Order" %}',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function removeOrderRowFromOrderWizard(e) {
|
function removeOrderRowFromOrderWizard(e) {
|
||||||
/* Remove a part selection from an order form. */
|
/* Remove a part selection from an order form. */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user