mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Implemented bidirectional traversal for PART and STOCK apps
- Added list view for StockItems
This commit is contained in:
parent
e30a089c76
commit
89ee09b01f
@ -6,7 +6,11 @@ from rest_framework.documentation import include_docs_urls
|
|||||||
from part.urls import part_api_urls, part_cat_api_urls
|
from part.urls import part_api_urls, part_cat_api_urls
|
||||||
from part.urls import bom_api_urls
|
from part.urls import bom_api_urls
|
||||||
from part.urls import part_urls
|
from part.urls import part_urls
|
||||||
from stock.urls import stock_urls, stock_loc_urls
|
|
||||||
|
|
||||||
|
from stock.urls import stock_api_urls, stock_api_loc_urls
|
||||||
|
from stock.urls import stock_urls
|
||||||
|
|
||||||
from supplier.urls import cust_urls, manu_urls, supplier_part_urls, price_break_urls, supplier_urls
|
from supplier.urls import cust_urls, manu_urls, supplier_part_urls, price_break_urls, supplier_urls
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -24,8 +28,8 @@ admin.site.site_header = "InvenTree Admin"
|
|||||||
apipatterns = [
|
apipatterns = [
|
||||||
|
|
||||||
# Stock URLs
|
# Stock URLs
|
||||||
url(r'^stock/', include(stock_urls)),
|
url(r'^stock/', include(stock_api_urls)),
|
||||||
url(r'^stock-location/', include(stock_loc_urls)),
|
url(r'^stock-location/', include(stock_api_loc_urls)),
|
||||||
|
|
||||||
# Part URLs
|
# Part URLs
|
||||||
url(r'^part/', include(part_api_urls)),
|
url(r'^part/', include(part_api_urls)),
|
||||||
@ -63,6 +67,7 @@ urlpatterns = [
|
|||||||
url(r'^api/', include(apipatterns)),
|
url(r'^api/', include(apipatterns)),
|
||||||
|
|
||||||
url(r'^part/', include(part_urls)),
|
url(r'^part/', include(part_urls)),
|
||||||
|
url(r'^stock/', include(stock_urls)),
|
||||||
|
|
||||||
url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
|
url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
|
||||||
|
|
||||||
|
@ -20,7 +20,8 @@ InvenTree
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
{% include "part/navbar.html" %}
|
{% include "navbar.html" %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<!-- Each view fills in here.. -->
|
<!-- Each view fills in here.. -->
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
{% for bom_item in part.bom_items.all %}
|
{% for bom_item in part.bom_items.all %}
|
||||||
{% with sub_part=bom_item.sub_part %}
|
{% with sub_part=bom_item.sub_part %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{% url 'detail' sub_part.id %}">{{ sub_part.name }}</a></td>
|
<td><a href="{% url 'part-detail' sub_part.id %}">{{ sub_part.name }}</a></td>
|
||||||
<td>{{ sub_part.description }}</td>
|
<td>{{ sub_part.description }}</td>
|
||||||
<td>{{ bom_item.quantity }}</td>
|
<td>{{ bom_item.quantity }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<a href="/part/list/">All</a> >
|
<a href="/part/list/">Parts</a> >
|
||||||
|
{% if category %}
|
||||||
{% for path_item in category.parentpath %}
|
{% for path_item in category.parentpath %}
|
||||||
<a href="/part/list/?category={{ path_item.id }}">{{ path_item.name }}</a> >
|
<a href="/part/list/?category={{ path_item.id }}">{{ path_item.name }}</a> >
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<a href="/part/list/?category={{ category.id }}">{{ category.name }}</a>
|
<a href="/part/list/?category={{ category.id }}">{{ category.name }}</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
@ -3,15 +3,15 @@
|
|||||||
{% block details %}
|
{% block details %}
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<a href="{% url 'bom' part.id %}">There are <b>{{ part.bomItemCount }}</b> BOM items for this part.</a>
|
<a href="{% url 'part-bom' part.id %}">There are <b>{{ part.bomItemCount }}</b> BOM items for this part.</a>
|
||||||
<br>
|
<br>
|
||||||
Used in {{ part.usedInCount }} other parts.<br>
|
Used in {{ part.usedInCount }} other parts.<br>
|
||||||
|
|
||||||
<a href="{% url 'stock' part.id %}">There are {{ part.stock }} units in stock.</a>
|
<a href="{% url 'part-stock' part.id %}">There are {{ part.stock }} units in stock.</a>
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
{% if part.trackable %}
|
{% if part.trackable %}
|
||||||
<a href="{% url 'track' part.id %}">Part tracking</a>
|
<a href="{% url 'part-track' part.id %}">Part tracking</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
{{ part.name }} does not have part tracking enabled
|
{{ part.name }} does not have part tracking enabled
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -2,32 +2,33 @@
|
|||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
|
||||||
<h1>Parts page!</h1>
|
|
||||||
|
|
||||||
{% if category %}
|
|
||||||
{% include "part/cat_link.html" with category=category %}
|
{% include "part/cat_link.html" with category=category %}
|
||||||
<h3>Child categories</h3>
|
|
||||||
<ul>
|
{% if children|length > 0 %}
|
||||||
{% for child in category.children.all %}
|
<table>
|
||||||
<li><a href="/part/list?category={{ child.id }}">{{ child.name }}</a></li>
|
<tr>
|
||||||
|
<th>Subcategories</th>
|
||||||
|
</tr>
|
||||||
|
{% for child in children %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="/part/list/?category={{ child.id }}">{{ child.name }}</a></td>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</table>
|
||||||
{% else %}
|
|
||||||
No category!
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<b>Here is a list of all the parts:</b>
|
{% if parts|length > 0 %}
|
||||||
|
<h3>Parts</h3>
|
||||||
|
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
{% for part in parts %}
|
{% for part in parts %}
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="{% url 'detail' part.id %}">{{ part.name }}</a></td>
|
<td><a href="{% url 'part-detail' part.id %}">{{ part.name }}</a></td>
|
||||||
<td>{{ part.description }}</td>
|
<td>{{ part.description }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
|
{% else %}
|
||||||
|
There are no parts in this category.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
{% include "part/cat_link.html" with category=part.category %}
|
{% include "part/cat_link.html" with category=part.category %}
|
||||||
|
|
||||||
<a href="{% url 'detail' part.id %}">{{ part.name }}</a>
|
<a href="{% url 'part-detail' part.id %}">{{ part.name }}</a>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
{{ part.description }}
|
{{ part.description }}
|
||||||
|
@ -17,7 +17,7 @@ Total in stock: {{ part.stock }}
|
|||||||
{% for stock in part.locations.all %}
|
{% for stock in part.locations.all %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ stock.quantity }}</td>
|
<td>{{ stock.quantity }}</td>
|
||||||
<td>{{ stock.location.name }}</td>
|
<td><a href="/stock/list/?location={{ stock.location.id }}">{{ stock.location.name }}</a></td>
|
||||||
<td>
|
<td>
|
||||||
{% if stock.supplier_part %}
|
{% if stock.supplier_part %}
|
||||||
{{ stock.supplier_part.supplier.name }} | {{ stock.supplier_part.SKU }}
|
{{ stock.supplier_part.supplier.name }} | {{ stock.supplier_part.SKU }}
|
||||||
|
@ -39,10 +39,10 @@ bom_api_urls = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
part_detail_urls = [
|
part_detail_urls = [
|
||||||
url(r'^track/?', views.track, name='track'),
|
url(r'^track/?', views.track, name='part-track'),
|
||||||
url(r'^bom/?', views.bom, name='bom'),
|
url(r'^bom/?', views.bom, name='part-bom'),
|
||||||
url(r'^stock/?', views.stock, name='stock'),
|
url(r'^stock/?', views.stock, name='part-stock'),
|
||||||
url('', views.detail, name='detail'),
|
url('', views.detail, name='part-detail'),
|
||||||
]
|
]
|
||||||
|
|
||||||
# URL list for part web interface
|
# URL list for part web interface
|
||||||
@ -50,10 +50,10 @@ part_urls = [
|
|||||||
# Individual
|
# Individual
|
||||||
url(r'^(?P<pk>\d+)/', include(part_detail_urls)),
|
url(r'^(?P<pk>\d+)/', include(part_detail_urls)),
|
||||||
|
|
||||||
url('list', views.index, name='index'),
|
url('list', views.index, name='part-index'),
|
||||||
# ex: /part/5/
|
# ex: /part/5/
|
||||||
|
|
||||||
url(r'^.*$', RedirectView.as_view(url='list', permanent=False), name='index'),
|
url(r'^.*$', RedirectView.as_view(url='list', permanent=False), name='part-index'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -22,16 +22,20 @@ def index(request):
|
|||||||
cat_id = request.GET['category']
|
cat_id = request.GET['category']
|
||||||
|
|
||||||
cat = get_object_or_404(PartCategory, pk=cat_id)
|
cat = get_object_or_404(PartCategory, pk=cat_id)
|
||||||
#cat = PartCategory.objects.get(pk=cat_id)
|
|
||||||
parts = parts.filter(category = cat_id)
|
parts = parts.filter(category = cat_id)
|
||||||
|
children = PartCategory.objects.filter(parent = cat_id)
|
||||||
|
|
||||||
|
else:
|
||||||
|
parts = parts.filter(category__isnull=True)
|
||||||
|
children = PartCategory.objects.filter(parent__isnull=True)
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'parts' : parts.order_by('category__name'),
|
'parts' : parts.order_by('category__name'),
|
||||||
|
'category' : cat,
|
||||||
|
'children' : children,
|
||||||
}
|
}
|
||||||
|
|
||||||
if cat:
|
|
||||||
context['category'] = cat
|
|
||||||
|
|
||||||
return HttpResponse(template.render(context, request))
|
return HttpResponse(template.render(context, request))
|
||||||
|
|
||||||
|
|
||||||
|
38
InvenTree/stock/templates/stock/index.html
Normal file
38
InvenTree/stock/templates/stock/index.html
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% include "stock/loc_link.html" with location=location %}
|
||||||
|
|
||||||
|
{% if children|length > 0 %}
|
||||||
|
<table>
|
||||||
|
<tr><th>Sublocations</th></tr>
|
||||||
|
{% for child in children %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="/stock/list/?location={{ child.id }}">{{ child.name }}</a></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if items|length > 0 %}
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Part</th>
|
||||||
|
<th>Stock</th>
|
||||||
|
<th>Stocktake</th>
|
||||||
|
<th>Notes</th>
|
||||||
|
</tr>
|
||||||
|
{% for item in items %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url 'part-detail' item.part.id %}">{{ item.part.name }}</a></td>
|
||||||
|
<td>{{ item.quantity }}</td>
|
||||||
|
<td>{{ item.stocktake_date }}</td>
|
||||||
|
<td>{{ item.notes }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
There are no parts in this location.
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
9
InvenTree/stock/templates/stock/loc_link.html
Normal file
9
InvenTree/stock/templates/stock/loc_link.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<div class="container">
|
||||||
|
<a href="/stock/list/">Stock</a> >
|
||||||
|
{% if location %}
|
||||||
|
{% for path_item in location.parentpath %}
|
||||||
|
<a href="/stock/list/?location={{ path_item.id }}">{{ path_item.name }}</a> >
|
||||||
|
{% endfor %}
|
||||||
|
<a href="/stock/list/?location={{ location.id }}">{{ location.name }}</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
@ -1,4 +1,5 @@
|
|||||||
from django.conf.urls import url, include
|
from django.conf.urls import url, include
|
||||||
|
from django.views.generic.base import RedirectView
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
from . import api
|
from . import api
|
||||||
@ -11,7 +12,7 @@ stock_endpoints = [
|
|||||||
url(r'^add-stock/?$', api.AddStockEndpoint.as_view(), name='stockitem-add-stock'),
|
url(r'^add-stock/?$', api.AddStockEndpoint.as_view(), name='stockitem-add-stock'),
|
||||||
]
|
]
|
||||||
|
|
||||||
stock_urls = [
|
stock_api_urls = [
|
||||||
# Detail for a single stock item
|
# Detail for a single stock item
|
||||||
url(r'^(?P<pk>[0-9]+)/', include(stock_endpoints)),
|
url(r'^(?P<pk>[0-9]+)/', include(stock_endpoints)),
|
||||||
|
|
||||||
@ -20,10 +21,25 @@ stock_urls = [
|
|||||||
url(r'^$', api.StockList.as_view()),
|
url(r'^$', api.StockList.as_view()),
|
||||||
]
|
]
|
||||||
|
|
||||||
stock_loc_urls = [
|
stock_api_loc_urls = [
|
||||||
url(r'^(?P<pk>[0-9]+)/?$', api.LocationDetail.as_view(), name='stocklocation-detail'),
|
url(r'^(?P<pk>[0-9]+)/?$', api.LocationDetail.as_view(), name='stocklocation-detail'),
|
||||||
|
|
||||||
url(r'^\?.*/?$', api.LocationList.as_view()),
|
url(r'^\?.*/?$', api.LocationList.as_view()),
|
||||||
|
|
||||||
url(r'^$', api.LocationList.as_view())
|
url(r'^$', api.LocationList.as_view())
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# URL list for web interface
|
||||||
|
stock_detail_urls = [
|
||||||
|
url('', views.detail, name='stock-detail'),
|
||||||
|
]
|
||||||
|
stock_urls = [
|
||||||
|
# Individual stock items
|
||||||
|
url(r'^(?P<pk>\d+)/', include(stock_detail_urls)),
|
||||||
|
|
||||||
|
url('list', views.index, name='stock=index'),
|
||||||
|
|
||||||
|
# Redirect any other patterns
|
||||||
|
url(r'^.*$', RedirectView.as_view(url='list', permanent=False), name='stock-index'),
|
||||||
|
]
|
@ -0,0 +1,43 @@
|
|||||||
|
from django.http import HttpResponse
|
||||||
|
from django.template import loader
|
||||||
|
|
||||||
|
from django.shortcuts import get_object_or_404, render
|
||||||
|
|
||||||
|
from .models import StockItem, StockLocation
|
||||||
|
|
||||||
|
def index(request):
|
||||||
|
template = loader.get_template('stock/index.html')
|
||||||
|
|
||||||
|
items = StockItem.objects.all()
|
||||||
|
|
||||||
|
location = None
|
||||||
|
|
||||||
|
if 'location' in request.GET:
|
||||||
|
loc_id = request.GET['location']
|
||||||
|
|
||||||
|
location = get_object_or_404(StockLocation, pk=loc_id)
|
||||||
|
|
||||||
|
items = items.filter(location = loc_id)
|
||||||
|
|
||||||
|
children = StockLocation.objects.filter(parent = loc_id)
|
||||||
|
|
||||||
|
else:
|
||||||
|
# No stock items can exist without a location
|
||||||
|
items = None
|
||||||
|
location = None
|
||||||
|
children = StockLocation.objects.filter(parent__isnull=True)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
'items' : items,
|
||||||
|
'location' : location,
|
||||||
|
'children' : children,
|
||||||
|
}
|
||||||
|
|
||||||
|
return HttpResponse(template.render(context, request))
|
||||||
|
|
||||||
|
|
||||||
|
def detail(request, pk):
|
||||||
|
|
||||||
|
item = get_object_or_404(Stock, pk=pk)
|
||||||
|
|
||||||
|
return render(request, 'stock/detail.html', {'item' : item})
|
Loading…
Reference in New Issue
Block a user