Stock location part list now uses bootstrap table

- Serializers within serializers!
This commit is contained in:
Oliver 2018-05-02 23:08:45 +10:00
parent 211edb23bb
commit 1899d8f3e9
7 changed files with 135 additions and 78 deletions

View File

@ -34,8 +34,6 @@ apipatterns = [
urlpatterns = [ urlpatterns = [
# API URL
url(r'^api/', include(apipatterns)),
# url(r'^api-doc/', include_docs_urls(title='InvenTree API')), # url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
url(r'^part/', include(part_urls)), url(r'^part/', include(part_urls)),
@ -50,6 +48,8 @@ urlpatterns = [
url(r'^admin/', admin.site.urls), url(r'^admin/', admin.site.urls),
url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')), url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')),
url(r'^api/', include(apipatterns)),
] ]
# Static file access # Static file access

View File

@ -1,6 +1,33 @@
from rest_framework import serializers from rest_framework import serializers
from .models import Part from .models import Part, PartCategory
class CategoryBriefSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
class Meta:
model = PartCategory
fields = [
'pk',
'name',
'pathstring',
'url',
]
class PartBriefSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
class Meta:
model = Part
fields = [
'pk',
'url',
'name',
]
class PartSerializer(serializers.ModelSerializer): class PartSerializer(serializers.ModelSerializer):
@ -8,18 +35,7 @@ class PartSerializer(serializers.ModelSerializer):
Used when displaying all details of a single component. Used when displaying all details of a single component.
""" """
def _category_name(self, part): category = CategoryBriefSerializer(many=False, read_only=True)
if part.category:
return part.category.name
return ''
def _category_url(self, part):
if part.category:
return part.category.get_absolute_url()
return ''
category_name = serializers.SerializerMethodField('_category_name')
category_url = serializers.SerializerMethodField('_category_url')
class Meta: class Meta:
model = Part model = Part
@ -31,8 +47,6 @@ class PartSerializer(serializers.ModelSerializer):
'URL', # Link to an external URL (optional) 'URL', # Link to an external URL (optional)
'description', 'description',
'category', 'category',
'category_name',
'category_url',
'total_stock', 'total_stock',
'available_stock', 'available_stock',
'units', 'units',

View File

@ -40,10 +40,15 @@
{% if category == None %} {% if category == None %}
{ {
sortable: true, sortable: true,
field: 'category_name', field: 'category',
title: 'Category', title: 'Category',
formatter: function(value, row, index, field) { formatter: function(value, row, index, field) {
return renderLink(value, row.category_url) if (row.category) {
return renderLink(row.category.name, row.category.url);
}
else {
return '';
}
} }
}, },
{% endif %} {% endif %}

View File

@ -2,10 +2,30 @@ from rest_framework import serializers
from .models import StockItem, StockLocation from .models import StockItem, StockLocation
from part.serializers import PartBriefSerializer
class LocationBriefSerializer(serializers.ModelSerializer):
url = serializers.CharField(source='get_absolute_url', read_only=True)
class Meta:
model = StockLocation
fields = [
'pk',
'name',
'pathstring',
'url',
]
class StockItemSerializer(serializers.ModelSerializer): class StockItemSerializer(serializers.ModelSerializer):
""" Serializer for a StockItem """ Serializer for a StockItem
""" """
url = serializers.CharField(source='get_absolute_url', read_only=True)
part = PartBriefSerializer(many=False, read_only=True)
location = LocationBriefSerializer(many=False, read_only=True)
class Meta: class Meta:
model = StockItem model = StockItem
@ -16,17 +36,17 @@ class StockItemSerializer(serializers.ModelSerializer):
'supplier_part', 'supplier_part',
'location', 'location',
'in_stock', 'in_stock',
'belongs_to', #'belongs_to',
'customer', #'customer',
'quantity', 'quantity',
'serial', 'serial',
'batch', 'batch',
'status', 'status',
'notes', 'notes',
'updated', #'updated',
'stocktake_date', #'stocktake_date',
'stocktake_user', #'stocktake_user',
'review_needed', #'review_needed',
] ]
""" These fields are read-only in this context. """ These fields are read-only in this context.

View File

@ -9,35 +9,7 @@
{% include "stock/location_list.html" with locations=locations %} {% include "stock/location_list.html" with locations=locations %}
{% endif %} {% endif %}
<table class="table table-striped" id='stock-table' data-filtering='true' data-sorting='true'> <table class="table table-striped" id='stock-table'>
<thead>
<tr>
<th>Part</th>
<th>Location</th>
<th data-type='number'>Stock</th>
<th>Status</th>
<th data-type='date'>Stocktake</th>
<th data-sortable='false'></th>
</tr>
</thead>
<tbody>
{% for item in items.all %}
<tr>
<td><a href="{% url 'part-stock' item.part.id %}">{{ item.part.name }}</a></td>
<td>
{% if item.location %}
<a href="{% url 'stock-location-detail' item.location.id %}">
{{ item.location.pathstring }}
</a>
{% endif %}
</td>
<td>{{ item.quantity }}</td>
<td>{{ item.get_status_display }}</td>
<td>{{ item.stocktake_date }}</td>
<td><a href="{% url 'stock-item-detail' item.id %}">Click</a></td>
</tr>
{% endfor %}
</tbody>
</table> </table>
<div class='container-fluid'> <div class='container-fluid'>
@ -60,4 +32,7 @@
follow: true follow: true
}); });
}); });
{% include "stock/stock_table.html" %}
{% endblock %} {% endblock %}

View File

@ -12,8 +12,10 @@
{% include "stock/location_list.html" with locations=location.children %} {% include "stock/location_list.html" with locations=location.children %}
{% endif %} {% endif %}
<h4>Stock Items</h4> {% if location.has_items %}
{% include "stock/stock_table.html" with items=location.items %} <table class='table table-striped table-condensed' id='stock-table'>
</table>
{% endif %}
<div class='container-fluid'> <div class='container-fluid'>
<button class='btn btn-success' id='location-create'>New Stock Location</button> <button class='btn btn-success' id='location-create'>New Stock Location</button>
@ -69,4 +71,7 @@
} }
}); });
}); });
{% include 'stock/stock_table.html' with location=location %}
{% endblock %} {% endblock %}

View File

@ -1,22 +1,60 @@
<table class="table table-striped" id='stock-table' data-filtering='true' data-sorting='true'> $("#stock-table").bootstrapTable({
<thead> sortable: true,
<tr> search: true,
<th>Part</th> method: 'get',
<th data-type='number'>Stock</th> pagination: true,
<th>Status</th> rememberOrder: true,
<th>Stocktake</th> {% if location %}
<th data-sortable='false'></th> queryParams: function(p) {
</tr> return {
</thead> location: {{ location.id }}
<tbody> }
{% for item in items.all %} },
<tr> {% endif %}
<td><a href="{% url 'part-stock' item.part.id %}">{{ item.part.name }}</a></td> columns: [
<td>{{ item.quantity }}</td> {
<td>{{ item.get_status_display }}</td> checkbox: true,
<td>{{ item.stocktake_date }}</td> title: 'Select',
<td><a href="{% url 'stock-item-detail' item.id %}">Click</a></td> searchable: false,
</tr> },
{% endfor %} {
</tbody> field: 'pk',
</table> title: 'ID',
visible: false,
},
{
field: 'part.name',
title: 'Part',
sortable: true,
formatter: function(value, row, index, field) {
return renderLink(value, row.part.url);
}
},
{% if location == None %}
{
field: 'location',
title: 'Location',
sortable: true,
formatter: function(value, row, index, field) {
if (row.location) {
return renderLink(row.location.name, row.location.url);
}
else {
return '';
}
}
},
{% endif %}
{
field: 'quantity',
title: 'Stock',
sortable: true,
},
{
field: 'status',
title: 'Status',
sortable: true,
}
],
url: "{% url 'api-stock-list' %}",
});