mirror of
https://github.com/inventree/InvenTree.git
synced 2025-04-29 12:06:44 +00:00
Added supplier web interface
- Display list of suppliers - Supplier detail page - Supplier part detail page - Part detail now includes list of supplier parts
This commit is contained in:
parent
ce854e3119
commit
6a98846a8f
@ -13,6 +13,7 @@ class Company(models.Model):
|
|||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
name = models.CharField(max_length=100, unique=True)
|
name = models.CharField(max_length=100, unique=True)
|
||||||
|
description = models.CharField(max_length=500, blank=True)
|
||||||
website = models.URLField(blank=True)
|
website = models.URLField(blank=True)
|
||||||
address = models.CharField(max_length=200,
|
address = models.CharField(max_length=200,
|
||||||
blank=True)
|
blank=True)
|
||||||
|
@ -11,7 +11,8 @@ from part.urls import part_urls
|
|||||||
from stock.urls import stock_api_urls, stock_api_loc_urls
|
from stock.urls import stock_api_urls, stock_api_loc_urls
|
||||||
from stock.urls import stock_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 supplier_api_urls, supplier_api_part_urls
|
||||||
|
from supplier.urls import supplier_urls
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.conf.urls.static import static
|
from django.conf.urls.static import static
|
||||||
@ -41,11 +42,11 @@ apipatterns = [
|
|||||||
url(r'^bom/', include(bom_api_urls)),
|
url(r'^bom/', include(bom_api_urls)),
|
||||||
|
|
||||||
# Supplier URLs
|
# Supplier URLs
|
||||||
url(r'^supplier/', include(supplier_urls)),
|
url(r'^supplier/', include(supplier_api_urls)),
|
||||||
url(r'^supplier-part/', include(supplier_part_urls)),
|
url(r'^supplier-part/', include(supplier_api_part_urls)),
|
||||||
url(r'^price-break/', include(price_break_urls)),
|
#url(r'^price-break/', include(price_break_urls)),
|
||||||
url(r'^manufacturer/', include(manu_urls)),
|
#url(r'^manufacturer/', include(manu_urls)),
|
||||||
url(r'^customer/', include(cust_urls)),
|
#url(r'^customer/', include(cust_urls)),
|
||||||
|
|
||||||
# Tracking URLs
|
# Tracking URLs
|
||||||
#url(r'^track/', include(part_track_urls)),
|
#url(r'^track/', include(part_track_urls)),
|
||||||
@ -69,6 +70,8 @@ urlpatterns = [
|
|||||||
url(r'^part/', include(part_urls)),
|
url(r'^part/', include(part_urls)),
|
||||||
url(r'^stock/', include(stock_urls)),
|
url(r'^stock/', include(stock_urls)),
|
||||||
|
|
||||||
|
url(r'^supplier/', include(supplier_urls)),
|
||||||
|
|
||||||
url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
|
url(r'^api-doc/', include_docs_urls(title='InvenTree API')),
|
||||||
|
|
||||||
url(r'^admin/', admin.site.urls),
|
url(r'^admin/', admin.site.urls),
|
||||||
|
@ -9,10 +9,18 @@ Used in {{ part.usedInCount }} other parts.<br>
|
|||||||
|
|
||||||
<a href="{% url 'part-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>
|
||||||
|
{% if part.supplier_parts.all|length > 0 %}
|
||||||
|
This part is available from <a href="{% url 'part-suppliers' part.id %}">{{ part.supplier_parts.all|length }} suppliers</a>.
|
||||||
|
{% else %}
|
||||||
|
There are no suppliers defined for this part.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<br><br>
|
<br><br>
|
||||||
{% if part.trackable %}
|
{% if part.trackable %}
|
||||||
<a href="{% url 'part-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 %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -20,7 +20,9 @@ Total in stock: {{ part.stock }}
|
|||||||
<td><a href="/stock/list/?location={{ stock.location.id }}">{{ stock.location.name }}</a></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 %}
|
||||||
|
<a href="{% url 'supplier-part-detail' stock.supplier_part.id %}">
|
||||||
{{ stock.supplier_part.supplier.name }} | {{ stock.supplier_part.SKU }}
|
{{ stock.supplier_part.supplier.name }} | {{ stock.supplier_part.SKU }}
|
||||||
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td>{% if stock.stocktake_date %}{{ stock.stocktake_date }}{% endif %}</td>
|
<td>{% if stock.stocktake_date %}{{ stock.stocktake_date }}{% endif %}</td>
|
||||||
|
24
InvenTree/part/templates/part/supplier.html
Normal file
24
InvenTree/part/templates/part/supplier.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% extends "part/part_base.html" %}
|
||||||
|
|
||||||
|
{% block details %}
|
||||||
|
|
||||||
|
{% if part.supplier_parts.all|length > 0 %}
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Supplier</th>
|
||||||
|
<th>SKU</th>
|
||||||
|
<th>URL</th>
|
||||||
|
</tr>
|
||||||
|
{% for spart in part.supplier_parts.all %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url 'supplier-detail' spart.supplier.id %}">{{ spart.supplier.name }}</a></td>
|
||||||
|
<td><a href="{% url 'supplier-part-detail' spart.id %}">{{ spart.SKU }}</a></td>
|
||||||
|
<td>{{ spart.URL }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
There are no suppliers defined for this part, sorry!
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -42,6 +42,7 @@ part_detail_urls = [
|
|||||||
url(r'^track/?', views.track, name='part-track'),
|
url(r'^track/?', views.track, name='part-track'),
|
||||||
url(r'^bom/?', views.bom, name='part-bom'),
|
url(r'^bom/?', views.bom, name='part-bom'),
|
||||||
url(r'^stock/?', views.stock, name='part-stock'),
|
url(r'^stock/?', views.stock, name='part-stock'),
|
||||||
|
url(r'^suppliers/?', views.suppliers, name='part-suppliers'),
|
||||||
url('', views.detail, name='part-detail'),
|
url('', views.detail, name='part-detail'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -64,3 +64,8 @@ def track(request, pk):
|
|||||||
|
|
||||||
return render(request, 'part/track.html', {'part': part})
|
return render(request, 'part/track.html', {'part': part})
|
||||||
|
|
||||||
|
|
||||||
|
def suppliers(request, pk):
|
||||||
|
part = get_object_or_404(Part, pk=pk)
|
||||||
|
|
||||||
|
return render(request, 'part/supplier.html', {'part' : part})
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<li>Part: <a href="{% url 'part-detail' item.part.id %}">{{ item.part.name }}</a></li>
|
<li>Part: <a href="{% url 'part-detail' item.part.id %}">{{ item.part.name }}</a></li>
|
||||||
{% if item.supplier_part %}
|
{% if item.supplier_part %}
|
||||||
<li>Supplier Part: {{ item.supplier_part.supplier.name }} | {{ item.supplier_part.SKU }}</li>
|
<li>Supplier Part: <a href="{% url 'supplier-part-detail' item.supplier_part.id %}">{{ item.supplier_part.supplier.name }} | {{ item.supplier_part.SKU }}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li>Quantity: {{ item.quantity }}</li>
|
<li>Quantity: {{ item.quantity }}</li>
|
||||||
{% if item.stocktake_date %}
|
{% if item.stocktake_date %}
|
||||||
|
@ -38,7 +38,7 @@ stock_urls = [
|
|||||||
# Individual stock items
|
# Individual stock items
|
||||||
url(r'^(?P<pk>\d+)/', include(stock_detail_urls)),
|
url(r'^(?P<pk>\d+)/', include(stock_detail_urls)),
|
||||||
|
|
||||||
url('list', views.index, name='stock=index'),
|
url('list', views.index, name='stock-index'),
|
||||||
|
|
||||||
# Redirect any other patterns
|
# Redirect any other patterns
|
||||||
url(r'^.*$', RedirectView.as_view(url='list', permanent=False), name='stock-index'),
|
url(r'^.*$', RedirectView.as_view(url='list', permanent=False), name='stock-index'),
|
||||||
|
@ -40,7 +40,10 @@ class SupplierPart(models.Model):
|
|||||||
part = models.ForeignKey(Part, null=True, blank=True, on_delete=models.CASCADE,
|
part = models.ForeignKey(Part, null=True, blank=True, on_delete=models.CASCADE,
|
||||||
related_name='supplier_parts')
|
related_name='supplier_parts')
|
||||||
|
|
||||||
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE)
|
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE,
|
||||||
|
related_name = 'parts')
|
||||||
|
|
||||||
|
|
||||||
SKU = models.CharField(max_length=100)
|
SKU = models.CharField(max_length=100)
|
||||||
|
|
||||||
manufacturer = models.ForeignKey(Manufacturer, blank=True, null=True, on_delete=models.CASCADE)
|
manufacturer = models.ForeignKey(Manufacturer, blank=True, null=True, on_delete=models.CASCADE)
|
||||||
|
34
InvenTree/supplier/templates/supplier/detail.html
Normal file
34
InvenTree/supplier/templates/supplier/detail.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Name: {{ supplier.name }}</li>
|
||||||
|
<li>Description: {{ supplier.description }}</li>
|
||||||
|
<li>Website: {{ supplier.website }}</li>
|
||||||
|
<li>Contact: {{ supplier.contact }}</li>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
{% if supplier.parts.all|length > 0 %}
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Part</th>
|
||||||
|
<th>SKU</th>
|
||||||
|
<th>Manufacturer</th>
|
||||||
|
<th>MPN</th>
|
||||||
|
<th>URL</th>
|
||||||
|
</tr>
|
||||||
|
{% for part in supplier.parts.all %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url 'part-detail' part.part.id %}">{{ part.part.name }}</a></td>
|
||||||
|
<td>{{ part.SKU }}</td>
|
||||||
|
<td>Manufacturer name goes here</td>
|
||||||
|
<td>MPN goes here</td>
|
||||||
|
<td>{{ part.URL }}</td>
|
||||||
|
{% endfor %}
|
||||||
|
</table>
|
||||||
|
{% else %}
|
||||||
|
There are currently no parts sourced from this supplier.
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endblock %}
|
19
InvenTree/supplier/templates/supplier/index.html
Normal file
19
InvenTree/supplier/templates/supplier/index.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Supplier</th>
|
||||||
|
<th>Description</th>
|
||||||
|
<th>URL</th>
|
||||||
|
</tr>
|
||||||
|
{% for supplier in suppliers %}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{% url 'supplier-detail' supplier.id %}">{{ supplier.name }}</a></td>
|
||||||
|
<td>{{ supplier.description }}</td>
|
||||||
|
<td>{{ supplier.website }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% endblock %}
|
14
InvenTree/supplier/templates/supplier/partdetail.html
Normal file
14
InvenTree/supplier/templates/supplier/partdetail.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Part: <a href="{% url 'part-detail' part.part.id %}">{{ part.part.name }}</a></li>
|
||||||
|
<li>Supplier: <a href="{% url 'supplier-detail' part.supplier.id %}">{{ part.supplier.name }}</a></li>
|
||||||
|
<li>SKU: {{ part.SKU }}</li>
|
||||||
|
<li>Manufacturer name goes here</li>
|
||||||
|
<li>MPN goes here</li>
|
||||||
|
<li>URL: {{ part.URL }}</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -1,4 +1,5 @@
|
|||||||
from django.conf.urls import url
|
from django.conf.urls import url
|
||||||
|
from django.views.generic.base import RedirectView
|
||||||
|
|
||||||
from . import views
|
from . import views
|
||||||
from . import api
|
from . import api
|
||||||
@ -21,7 +22,7 @@ manu_urls = [
|
|||||||
url(r'^$', api.ManufacturerList.as_view())
|
url(r'^$', api.ManufacturerList.as_view())
|
||||||
]
|
]
|
||||||
|
|
||||||
supplier_part_urls = [
|
supplier_api_part_urls = [
|
||||||
url(r'^(?P<pk>[0-9]+)/?$', api.SupplierPartDetail.as_view(), name='supplierpart-detail'),
|
url(r'^(?P<pk>[0-9]+)/?$', api.SupplierPartDetail.as_view(), name='supplierpart-detail'),
|
||||||
|
|
||||||
url(r'^\?.*/?$', api.SupplierPartList.as_view()),
|
url(r'^\?.*/?$', api.SupplierPartList.as_view()),
|
||||||
@ -35,7 +36,7 @@ price_break_urls = [
|
|||||||
url(r'^$', api.SupplierPriceBreakList.as_view())
|
url(r'^$', api.SupplierPriceBreakList.as_view())
|
||||||
]
|
]
|
||||||
|
|
||||||
supplier_urls = [
|
supplier_api_urls = [
|
||||||
|
|
||||||
# Display details of a supplier
|
# Display details of a supplier
|
||||||
url(r'^(?P<pk>[0-9]+)/$', api.SupplierDetail.as_view(), name='supplier-detail'),
|
url(r'^(?P<pk>[0-9]+)/$', api.SupplierDetail.as_view(), name='supplier-detail'),
|
||||||
@ -44,3 +45,12 @@ supplier_urls = [
|
|||||||
url(r'^\?.*/?$', api.SupplierList.as_view()),
|
url(r'^\?.*/?$', api.SupplierList.as_view()),
|
||||||
url(r'^$', api.SupplierList.as_view())
|
url(r'^$', api.SupplierList.as_view())
|
||||||
]
|
]
|
||||||
|
|
||||||
|
supplier_urls = [
|
||||||
|
url(r'^(?P<pk>\d+)/', views.detail, name='supplier-detail'),
|
||||||
|
url(r'^part/(?P<pk>\d+)/', views.partDetail, name='supplier-part-detail'),
|
||||||
|
url(r'', views.index, name='supplier-index'),
|
||||||
|
|
||||||
|
# Redirect any other patterns
|
||||||
|
url(r'^.*$', RedirectView.as_view(url='', permanent=False), name='supplier-index'),
|
||||||
|
]
|
@ -0,0 +1,34 @@
|
|||||||
|
from django.http import HttpResponse
|
||||||
|
from django.template import loader
|
||||||
|
|
||||||
|
from django.shortcuts import get_object_or_404, render
|
||||||
|
|
||||||
|
from .models import Supplier, SupplierPart
|
||||||
|
|
||||||
|
def index(request):
|
||||||
|
""" The supplier index page simply displays all the suppliers
|
||||||
|
"""
|
||||||
|
|
||||||
|
suppliers = Supplier.objects.order_by('name')
|
||||||
|
|
||||||
|
return render(request, 'supplier/index.html', {'suppliers' : suppliers})
|
||||||
|
|
||||||
|
|
||||||
|
def detail(request, pk):
|
||||||
|
""" The supplier detail page shown detailed information
|
||||||
|
on a particular supplier
|
||||||
|
"""
|
||||||
|
|
||||||
|
supplier = get_object_or_404(Supplier, pk=pk)
|
||||||
|
|
||||||
|
return render(request, 'supplier/detail.html', {'supplier' : supplier})
|
||||||
|
|
||||||
|
|
||||||
|
def partDetail(request, pk):
|
||||||
|
""" The supplier part-detail page shows detailed information
|
||||||
|
on a particular supplier part
|
||||||
|
"""
|
||||||
|
|
||||||
|
part = get_object_or_404(SupplierPart, pk=pk)
|
||||||
|
|
||||||
|
return render(request, 'supplier/partdetail.html', {'part': part})
|
Loading…
x
Reference in New Issue
Block a user