mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Rebuild the "PurchaseOrder" detail
- Use AJAX and bootstrap-table - Display progress bar
This commit is contained in:
parent
ba1d2063af
commit
9d25ed335c
@ -116,7 +116,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-green {
|
.icon-green {
|
||||||
color: #5c5;
|
color: #43bb43;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-blue {
|
.icon-blue {
|
||||||
|
@ -64,15 +64,11 @@ class CompanySerializer(InvenTreeModelSerializer):
|
|||||||
class SupplierPartSerializer(InvenTreeModelSerializer):
|
class SupplierPartSerializer(InvenTreeModelSerializer):
|
||||||
""" Serializer for SupplierPart object """
|
""" Serializer for SupplierPart object """
|
||||||
|
|
||||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
|
||||||
|
|
||||||
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
part_detail = PartBriefSerializer(source='part', many=False, read_only=True)
|
||||||
|
|
||||||
supplier_detail = CompanyBriefSerializer(source='supplier', many=False, read_only=True)
|
supplier_detail = CompanyBriefSerializer(source='supplier', many=False, read_only=True)
|
||||||
manufacturer_detail = CompanyBriefSerializer(source='manufacturer', many=False, read_only=True)
|
manufacturer_detail = CompanyBriefSerializer(source='manufacturer', many=False, read_only=True)
|
||||||
|
|
||||||
pricing = serializers.CharField(source='unit_pricing', read_only=True)
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
part_detail = kwargs.pop('part_detail', False)
|
part_detail = kwargs.pop('part_detail', False)
|
||||||
@ -94,7 +90,6 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
|
|||||||
model = SupplierPart
|
model = SupplierPart
|
||||||
fields = [
|
fields = [
|
||||||
'pk',
|
'pk',
|
||||||
'url',
|
|
||||||
'part',
|
'part',
|
||||||
'part_detail',
|
'part_detail',
|
||||||
'supplier',
|
'supplier',
|
||||||
@ -105,7 +100,6 @@ class SupplierPartSerializer(InvenTreeModelSerializer):
|
|||||||
'description',
|
'description',
|
||||||
'MPN',
|
'MPN',
|
||||||
'link',
|
'link',
|
||||||
'pricing',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -162,6 +162,17 @@ class POLineItemList(generics.ListCreateAPIView):
|
|||||||
queryset = PurchaseOrderLineItem.objects.all()
|
queryset = PurchaseOrderLineItem.objects.all()
|
||||||
serializer_class = POLineItemSerializer
|
serializer_class = POLineItemSerializer
|
||||||
|
|
||||||
|
def get_serializer(self, *args, **kwargs):
|
||||||
|
|
||||||
|
try:
|
||||||
|
kwargs['part_detail'] = str2bool(self.request.query_params.get('part_detail', False))
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
kwargs['context'] = self.get_serializer_context()
|
||||||
|
|
||||||
|
return self.serializer_class(*args, **kwargs)
|
||||||
|
|
||||||
permission_classes = [
|
permission_classes = [
|
||||||
permissions.IsAuthenticated,
|
permissions.IsAuthenticated,
|
||||||
]
|
]
|
||||||
|
@ -417,6 +417,10 @@ class PurchaseOrderLineItem(OrderLineItem):
|
|||||||
help_text=_('Purchase Order')
|
help_text=_('Purchase Order')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_base_part(self):
|
||||||
|
""" Return the base-part for the line item """
|
||||||
|
return self.part.part
|
||||||
|
|
||||||
# TODO - Function callback for when the SupplierPart is deleted?
|
# TODO - Function callback for when the SupplierPart is deleted?
|
||||||
|
|
||||||
part = models.ForeignKey(
|
part = models.ForeignKey(
|
||||||
|
@ -10,7 +10,7 @@ from rest_framework import serializers
|
|||||||
from django.db.models import Count
|
from django.db.models import Count
|
||||||
|
|
||||||
from InvenTree.serializers import InvenTreeModelSerializer
|
from InvenTree.serializers import InvenTreeModelSerializer
|
||||||
from company.serializers import CompanyBriefSerializer
|
from company.serializers import CompanyBriefSerializer, SupplierPartSerializer
|
||||||
from part.serializers import PartBriefSerializer
|
from part.serializers import PartBriefSerializer
|
||||||
|
|
||||||
from .models import PurchaseOrder, PurchaseOrderLineItem
|
from .models import PurchaseOrder, PurchaseOrderLineItem
|
||||||
@ -74,6 +74,22 @@ class POSerializer(InvenTreeModelSerializer):
|
|||||||
|
|
||||||
class POLineItemSerializer(InvenTreeModelSerializer):
|
class POLineItemSerializer(InvenTreeModelSerializer):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
|
part_detail = kwargs.pop('part_detail', False)
|
||||||
|
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
if part_detail is not True:
|
||||||
|
self.fields.pop('part_detail')
|
||||||
|
self.fields.pop('supplier_part_detail')
|
||||||
|
|
||||||
|
quantity = serializers.FloatField()
|
||||||
|
received = serializers.FloatField()
|
||||||
|
|
||||||
|
part_detail = PartBriefSerializer(source='get_base_part', many=False, read_only=True)
|
||||||
|
supplier_part_detail = SupplierPartSerializer(source='part', many=False, read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = PurchaseOrderLineItem
|
model = PurchaseOrderLineItem
|
||||||
|
|
||||||
@ -84,6 +100,8 @@ class POLineItemSerializer(InvenTreeModelSerializer):
|
|||||||
'notes',
|
'notes',
|
||||||
'order',
|
'order',
|
||||||
'part',
|
'part',
|
||||||
|
'part_detail',
|
||||||
|
'supplier_part_detail',
|
||||||
'received',
|
'received',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -28,16 +28,16 @@ src="{% static 'img/blank_image.png' %}"
|
|||||||
<div class='btn-row'>
|
<div class='btn-row'>
|
||||||
<div class='btn-group action-buttons'>
|
<div class='btn-group action-buttons'>
|
||||||
<button type='button' class='btn btn-default' id='edit-order' title='Edit order information'>
|
<button type='button' class='btn btn-default' id='edit-order' title='Edit order information'>
|
||||||
<span class='fas fa-edit'></span>
|
<span class='fas fa-edit icon-green'></span>
|
||||||
</button>
|
</button>
|
||||||
<button type='button' class='btn btn-default' id='export-order' title='Export order to file'>
|
<button type='button' class='btn btn-default' id='export-order' title='Export order to file'>
|
||||||
<span class='fas fa-file-download'></span>
|
<span class='fas fa-file-download'></span>
|
||||||
</button>
|
</button>
|
||||||
{% if order.status == OrderStatus.PENDING and order.lines.count > 0 %}
|
{% if order.status == PurchaseOrderStatus.PENDING and order.lines.count > 0 %}
|
||||||
<button type='button' class='btn btn-default' id='place-order' title='Place order'>
|
<button type='button' class='btn btn-default' id='place-order' title='Place order'>
|
||||||
<span class='fas fa-paper-plane'></span>
|
<span class='fas fa-paper-plane icon-blue'></span>
|
||||||
</button>
|
</button>
|
||||||
{% elif order.status == OrderStatus.PLACED %}
|
{% elif order.status == PurchaseOrderStatus.PLACED %}
|
||||||
<button type='button' class='btn btn-default' id='receive-order' title='Receive items'>
|
<button type='button' class='btn btn-default' id='receive-order' title='Receive items'>
|
||||||
<span class='fas fa-clipboard-check'></span>
|
<span class='fas fa-clipboard-check'></span>
|
||||||
</button>
|
</button>
|
||||||
@ -45,9 +45,9 @@ src="{% static 'img/blank_image.png' %}"
|
|||||||
<span class='fas fa-check-circle'></span>
|
<span class='fas fa-check-circle'></span>
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if order.status == OrderStatus.PENDING or order.status == OrderStatus.PLACED %}
|
{% if order.status == PurchaseOrderStatus.PENDING or order.status == PurchaseOrderStatus.PLACED %}
|
||||||
<button type='button' class='btn btn-default' id='cancel-order' title='Cancel order'>
|
<button type='button' class='btn btn-default' id='cancel-order' title='Cancel order'>
|
||||||
<span class='fas fa-times-circle'></span>
|
<span class='fas fa-times-circle icon-red'></span>
|
||||||
</button>
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
@ -100,7 +100,7 @@ src="{% static 'img/blank_image.png' %}"
|
|||||||
<td>{{ order.issue_date }}</td>
|
<td>{{ order.issue_date }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if order.status == OrderStatus.COMPLETE %}
|
{% if order.status == PurchaseOrderStatus.COMPLETE %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class='fas fa-calendar-alt'></span></td>
|
<td><span class='fas fa-calendar-alt'></span></td>
|
||||||
<td>{% trans "Received" %}</td>
|
<td>{% trans "Received" %}</td>
|
||||||
@ -113,7 +113,7 @@ src="{% static 'img/blank_image.png' %}"
|
|||||||
{% block js_ready %}
|
{% block js_ready %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
|
||||||
{% if order.status == OrderStatus.PENDING and order.lines.count > 0 %}
|
{% if order.status == PurchaseOrderStatus.PENDING and order.lines.count > 0 %}
|
||||||
$("#place-order").click(function() {
|
$("#place-order").click(function() {
|
||||||
launchModalForm("{% url 'po-issue' order.id %}",
|
launchModalForm("{% url 'po-issue' order.id %}",
|
||||||
{
|
{
|
||||||
|
@ -12,73 +12,14 @@
|
|||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
|
<div id='order-toolbar-buttons' class='btn-group' style='float: right;'>
|
||||||
{% if order.status == OrderStatus.PENDING %}
|
{% if order.status == PurchaseOrderStatus.PENDING %}
|
||||||
<button type='button' class='btn btn-default' id='new-po-line'>{% trans "Add Line Item" %}</button>
|
<button type='button' class='btn btn-default' id='new-po-line'>{% trans "Add Line Item" %}</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4>{% trans "Purchase Order Items" %}</h4>
|
<h4>{% trans "Purchase Order Items" %}</h4>
|
||||||
|
|
||||||
<table class='table table-striped table-condensed' id='po-lines-table' data-toolbar='#order-toolbar-buttons'>
|
<table class='table table-striped table-condensed' id='po-table' data-toolbar='#order-toolbar-buttons'>
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th data-sortable='true'>{% trans "Line" %}</th>
|
|
||||||
<th data-sortable='true'>{% trans "Part" %}</th>
|
|
||||||
<th>{% trans "Description" %}</th>
|
|
||||||
<th data-sortable='true'>{% trans "Order Code" %}</th>
|
|
||||||
<th data-sortable='true'>{% trans "Reference" %}</th>
|
|
||||||
<th data-sortable='true'>{% trans "Quantity" %}</th>
|
|
||||||
{% if not order.status == OrderStatus.PENDING %}
|
|
||||||
<th data-sortable='true'>{% trans "Received" %}</th>
|
|
||||||
{% endif %}
|
|
||||||
<th>{% trans "Note" %}</th>
|
|
||||||
<th></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for line in order.lines.all %}
|
|
||||||
<tr{% if order.status == OrderStatus.PLACED %} class={% if line.received < line.quantity %}'rowinvalid'{% else %}'rowvalid'{% endif %}{% endif %}>
|
|
||||||
<td>
|
|
||||||
{{ forloop.counter }}
|
|
||||||
</td>
|
|
||||||
{% if line.part %}
|
|
||||||
<td>
|
|
||||||
{% include "hover_image.html" with image=line.part.part.image hover=True %}
|
|
||||||
<a href="{% url 'part-detail' line.part.part.id %}">{{ line.part.part.full_name }}</a>
|
|
||||||
</td>
|
|
||||||
<td>{{ line.part.part.description }}</td>
|
|
||||||
<td><a href="{% url 'supplier-part-detail' line.part.id %}">{{ line.part.SKU }}</a></td>
|
|
||||||
{% else %}
|
|
||||||
<td colspan='3'><strong>Warning: Part has been deleted.</strong></td>
|
|
||||||
{% endif %}
|
|
||||||
<td>{{ line.reference }}</td>
|
|
||||||
<td>{% decimal line.quantity %}</td>
|
|
||||||
{% if not order.status == OrderStatus.PENDING %}
|
|
||||||
<td>{% decimal line.received %}</td>
|
|
||||||
{% endif %}
|
|
||||||
<td>
|
|
||||||
{{ line.notes }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class='btn-group'>
|
|
||||||
{% if order.status == OrderStatus.PENDING %}
|
|
||||||
<button class='btn btn-default btn-glyph' line='{{ line.id }}' id='edit-line-item-{{ line.id }} title='Edit line item' onclick='editPurchaseOrderLineItem()'>
|
|
||||||
<span url="{% url 'po-line-item-edit' line.id %}" line='{{ line.id }}' class='glyphicon glyphicon-edit'></span>
|
|
||||||
</button>
|
|
||||||
<button class='btn btn-default btn-glyph' line='{{ line.id }}' id='remove-line-item-{{ line.id }' title='Remove line item' type='button' onclick='removePurchaseOrderLineItem()'>
|
|
||||||
<span url="{% url 'po-line-item-delete' line.id %}" line='{{ line.id }}' class='glyphicon glyphicon-remove'></span>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
{% if order.status == OrderStatus.PLACED and line.received < line.quantity %}
|
|
||||||
<button class='btn btn-default btn-glyph line-receive' pk='{{ line.pk }}' title='Receive item(s)'>
|
|
||||||
<span class='glyphicon glyphicon-check'></span>
|
|
||||||
</button>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -87,27 +28,6 @@
|
|||||||
|
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
|
|
||||||
$("#po-lines-table").on('click', ".line-receive", function() {
|
|
||||||
|
|
||||||
var button = $(this);
|
|
||||||
|
|
||||||
console.log('clicked! ' + button.attr('pk'));
|
|
||||||
|
|
||||||
launchModalForm("{% url 'po-receive' order.id %}", {
|
|
||||||
reload: true,
|
|
||||||
data: {
|
|
||||||
line: button.attr('pk')
|
|
||||||
},
|
|
||||||
secondary: [
|
|
||||||
{
|
|
||||||
field: 'location',
|
|
||||||
label: 'New Location',
|
|
||||||
title: 'Create new stock location',
|
|
||||||
url: "{% url 'stock-location-create' %}",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#receive-order").click(function() {
|
$("#receive-order").click(function() {
|
||||||
launchModalForm("{% url 'po-receive' order.id %}", {
|
launchModalForm("{% url 'po-receive' order.id %}", {
|
||||||
@ -115,8 +35,8 @@ $("#receive-order").click(function() {
|
|||||||
secondary: [
|
secondary: [
|
||||||
{
|
{
|
||||||
field: 'location',
|
field: 'location',
|
||||||
label: 'New Location',
|
label: '{% trans "New Location" %}',
|
||||||
title: 'Create new stock location',
|
title: '{% trans "Create new stock location" %}',
|
||||||
url: "{% url 'stock-location-create' %}",
|
url: "{% url 'stock-location-create' %}",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -133,7 +53,7 @@ $("#export-order").click(function() {
|
|||||||
location.href = "{% url 'po-export' order.id %}";
|
location.href = "{% url 'po-export' order.id %}";
|
||||||
});
|
});
|
||||||
|
|
||||||
{% if order.status == OrderStatus.PENDING %}
|
{% if order.status == PurchaseOrderStatus.PENDING %}
|
||||||
$('#new-po-line').click(function() {
|
$('#new-po-line').click(function() {
|
||||||
launchModalForm("{% url 'po-line-item-create' %}",
|
launchModalForm("{% url 'po-line-item-create' %}",
|
||||||
{
|
{
|
||||||
@ -144,8 +64,8 @@ $('#new-po-line').click(function() {
|
|||||||
secondary: [
|
secondary: [
|
||||||
{
|
{
|
||||||
field: 'part',
|
field: 'part',
|
||||||
label: 'New Supplier Part',
|
label: '{% trans "New Supplier Part" %}',
|
||||||
title: 'Create new supplier part',
|
title: '{% trans "Create new supplier part" %}',
|
||||||
url: "{% url 'supplier-part-create' %}",
|
url: "{% url 'supplier-part-create' %}",
|
||||||
data: {
|
data: {
|
||||||
supplier: {{ order.supplier.id }},
|
supplier: {{ order.supplier.id }},
|
||||||
@ -157,7 +77,153 @@ $('#new-po-line').click(function() {
|
|||||||
});
|
});
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
$("#po-lines-table").inventreeTable({
|
function reloadTable() {
|
||||||
|
$("#po-table").bootstrapTable("refresh");
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupCallbacks() {
|
||||||
|
// Setup callbacks for the line buttons
|
||||||
|
|
||||||
|
var table = $("#po-table");
|
||||||
|
|
||||||
|
{% if order.status == PurchaseOrderStatus.PENDING %}
|
||||||
|
table.find(".button-line-edit").click(function() {
|
||||||
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
|
launchModalForm(`/order/purchase-order/line/${pk}/edit/`, {
|
||||||
|
success: reloadTable,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
table.find(".button-line-delete").click(function() {
|
||||||
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
|
launchModalForm(`/order/purchase-order/line/${pk}/delete/`, {
|
||||||
|
success: reloadTable,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
table.find(".button-line-receive").click(function() {
|
||||||
|
var pk = $(this).attr('pk');
|
||||||
|
|
||||||
|
launchModalForm("{% url 'po-receive' order.id %}", {
|
||||||
|
success: reloadTable,
|
||||||
|
data: {
|
||||||
|
line: pk,
|
||||||
|
},
|
||||||
|
secondary: [
|
||||||
|
{
|
||||||
|
field: 'location',
|
||||||
|
label: '{% trans "New Location" %}',
|
||||||
|
title: '{% trans "Create new stock location" %}',
|
||||||
|
url: "{% url 'stock-location-create' %}",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$("#po-table").inventreeTable({
|
||||||
|
onPostBody: setupCallbacks,
|
||||||
|
formatNoMatches: function() { return "{% trans 'No line items found' %}"; },
|
||||||
|
queryParams: {
|
||||||
|
order: {{ order.id }},
|
||||||
|
part_detail: true,
|
||||||
|
},
|
||||||
|
url: "{% url 'api-po-line-list' %}",
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
field: 'pk',
|
||||||
|
title: 'ID',
|
||||||
|
visible: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'part',
|
||||||
|
sortable: true,
|
||||||
|
title: '{% trans "Part" %}',
|
||||||
|
formatter: function(value, row, index, field) {
|
||||||
|
if (row.part) {
|
||||||
|
return imageHoverIcon(row.part_detail.thumbnail) + renderLink(row.part_detail.full_name, `/part/${value}/`);
|
||||||
|
} else {
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sortable: true,
|
||||||
|
field: 'part_detail.description',
|
||||||
|
title: '{% trans "Description" %}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sortable: true,
|
||||||
|
field: 'supplier_part_detail.SKU',
|
||||||
|
title: '{% trans "Order Code" %}',
|
||||||
|
formatter: function(value, row, index, field) {
|
||||||
|
return renderLink(value, `/supplier-part/${row.part}/`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sortable: true,
|
||||||
|
field: 'reference',
|
||||||
|
title: '{% trans "Reference" %}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sortable: true,
|
||||||
|
field: 'quantity',
|
||||||
|
title: '{% trans "Quantity" %}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sortable: true,
|
||||||
|
field: 'received',
|
||||||
|
title: '{% trans "Received" %}',
|
||||||
|
formatter: function(value, row, index, field) {
|
||||||
|
return makeProgressBar(row.received, row.quantity, {
|
||||||
|
id: `order-line-progress-${row.pk}`,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
sorter: function(valA, valB, rowA, rowB) {
|
||||||
|
|
||||||
|
if (rowA.received == 0 && rowB.received == 0) {
|
||||||
|
return (rowA.quantity > rowB.quantity) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var progressA = parseFloat(rowA.received) / rowA.quantity;
|
||||||
|
var progressB = parseFloat(rowB.received) / rowB.quantity;
|
||||||
|
|
||||||
|
return (progressA < progressB) ? 1 : -1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'notes',
|
||||||
|
title: '{% trans "Notes" %}',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'buttons',
|
||||||
|
title: '',
|
||||||
|
formatter: function(value, row, index, field) {
|
||||||
|
var html = `<div class='btn-group'>`;
|
||||||
|
|
||||||
|
var pk = row.pk;
|
||||||
|
|
||||||
|
{% if order.status == PurchaseOrderStatus.PENDING %}
|
||||||
|
html += makeIconButton('fa-edit', 'button-line-edit', pk, '{% trans "Edit line item" %}');
|
||||||
|
html += makeIconButton('fa-trash-alt icon-red', 'button-line-delete', pk, '{% trans "Delete line item" %}');
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if order.status == PurchaseOrderStatus.PLACED %}
|
||||||
|
if (row.received < row.quantity) {
|
||||||
|
html += makeIconButton('fa-clipboard-check', 'button-line-receive', pk, '{% trans "Receive line item" %}');
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
html += `</div>`;
|
||||||
|
|
||||||
|
return html;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ src="{% static 'img/blank_image.png' %}"
|
|||||||
<td>{{ order.shipment_date }}<span class='badge'>{{ order.shipped_by }}</span></td>
|
<td>{{ order.shipment_date }}<span class='badge'>{{ order.shipped_by }}</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if order.status == OrderStatus.COMPLETE %}
|
{% if order.status == PurchaseOrderStatus.COMPLETE %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><span class='fas fa-calendar-alt'></span></td>
|
<td><span class='fas fa-calendar-alt'></span></td>
|
||||||
<td>{% trans "Received" %}</td>
|
<td>{% trans "Received" %}</td>
|
||||||
|
@ -160,8 +160,8 @@ $("#so-lines-table").inventreeTable({
|
|||||||
return (rowA.quantity > rowB.quantity) ? 1 : -1;
|
return (rowA.quantity > rowB.quantity) ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
var progressA = rowA.allocated / rowA.quantity;
|
var progressA = parseFloat(rowA.allocated) / rowA.quantity;
|
||||||
var progressB = rowB.allocated / rowA.quantity;
|
var progressB = parseFloat(rowB.allocated) / rowB.quantity;
|
||||||
|
|
||||||
return (progressA < progressB) ? 1 : -1;
|
return (progressA < progressB) ? 1 : -1;
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ $("#so-lines-table").inventreeTable({
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupCallbacks(table) {
|
function setupCallbacks() {
|
||||||
|
|
||||||
var table = $("#so-lines-table");
|
var table = $("#so-lines-table");
|
||||||
|
|
||||||
|
@ -52,14 +52,12 @@ class PartThumbSerializer(serializers.Serializer):
|
|||||||
class PartBriefSerializer(InvenTreeModelSerializer):
|
class PartBriefSerializer(InvenTreeModelSerializer):
|
||||||
""" Serializer for Part (brief detail) """
|
""" Serializer for Part (brief detail) """
|
||||||
|
|
||||||
url = serializers.CharField(source='get_absolute_url', read_only=True)
|
|
||||||
thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True)
|
thumbnail = serializers.CharField(source='get_thumbnail_url', read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Part
|
model = Part
|
||||||
fields = [
|
fields = [
|
||||||
'pk',
|
'pk',
|
||||||
'url',
|
|
||||||
'full_name',
|
'full_name',
|
||||||
'description',
|
'description',
|
||||||
'thumbnail',
|
'thumbnail',
|
||||||
|
Loading…
Reference in New Issue
Block a user