diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py
index e76e01ce06..2002165909 100644
--- a/InvenTree/part/models.py
+++ b/InvenTree/part/models.py
@@ -158,9 +158,11 @@ class Part(models.Model):
This subtracts stock which is already allocated
"""
- # TODO - For now, just return total stock count
- # TODO - In future must take account of allocated stock
- return self.total_stock
+ total = self.total_stock
+
+ total -= self.allocation_count
+
+ return max(total, 0)
@property
def can_build(self):
@@ -181,7 +183,7 @@ class Part(models.Model):
if total is None or n < total:
total = n
- return total
+ return max(total, 0)
@property
def active_builds(self):
@@ -205,6 +207,44 @@ class Part(models.Model):
return sum([b.quantity for b in self.active_builds])
+ @property
+ def allocated_builds(self):
+ """ Return list of builds to which this part is allocated
+ """
+
+ builds = []
+
+ for item in self.used_in.all():
+ for build in item.part.active_builds:
+ builds.append(build)
+
+ return builds
+
+ @property
+ def allocated_build_count(self):
+ """ Return the total number of this that are allocated for builds
+ """
+
+ total = 0
+
+ for item in self.used_in.all():
+ for build in item.part.active_builds:
+ n = build.quantity * item.quantity
+ total += n
+
+ return total
+
+ @property
+ def allocation_count(self):
+ """ Return true if any of this part is allocated
+ - To another build
+ - To a customer order
+ """
+
+ return sum([
+ self.allocated_build_count,
+ ])
+
@property
def total_stock(self):
""" Return the total stock quantity for this part.
diff --git a/InvenTree/part/templates/part/allocation.html b/InvenTree/part/templates/part/allocation.html
new file mode 100644
index 0000000000..35b8426815
--- /dev/null
+++ b/InvenTree/part/templates/part/allocation.html
@@ -0,0 +1,29 @@
+{% extends "part/part_base.html" %}
+
+{% block details %}
+
+{% include "part/tabs.html" with tab="allocation" %}
+
+
Part Allocation
+
+{% if part.allocated_build_count > 0 %}
+Allocated to Part Builds
+
+
+ Build |
+ Making |
+ Allocted |
+ Status |
+
+{% for build in part.allocated_builds %}
+
+ {{ build.title }} |
+ {{ build.part.name }} |
+ Quantity |
+ {% include "part/build_status.html" with build=build %} |
+
+{% endfor %}
+
+{% endif %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/InvenTree/part/templates/part/build_list.html b/InvenTree/part/templates/part/build_list.html
index a42518964a..8798323204 100644
--- a/InvenTree/part/templates/part/build_list.html
+++ b/InvenTree/part/templates/part/build_list.html
@@ -3,18 +3,8 @@
{{ build.title }} |
{{ build.quantity }} |
- {% if build.status == build.PENDING %}
-
- {% elif build.status == build.HOLDING %}
-
- {% elif build.status == build.CANCELLED %}
-
- {% elif build.status == build.COMPLETE %}
-
- {% endif %}
- {{ build.get_status_display }}
-
+ {% include "part/build_status.html" with build=build %}
|
- {{ build.completion_date }} |
+ {% if build.completion_date %}{{ build.completion_date }}{% endif %} |
{% endfor %}
\ No newline at end of file
diff --git a/InvenTree/part/templates/part/build_status.html b/InvenTree/part/templates/part/build_status.html
new file mode 100644
index 0000000000..1702ceccae
--- /dev/null
+++ b/InvenTree/part/templates/part/build_status.html
@@ -0,0 +1,11 @@
+{% if build.status == build.PENDING %}
+
+{% elif build.status == build.HOLDING %}
+
+{% elif build.status == build.CANCELLED %}
+
+{% elif build.status == build.COMPLETE %}
+
+{% endif %}
+{{ build.get_status_display }}
+
\ No newline at end of file
diff --git a/InvenTree/part/templates/part/part_base.html b/InvenTree/part/templates/part/part_base.html
index 69840829e3..a9f66a76b9 100644
--- a/InvenTree/part/templates/part/part_base.html
+++ b/InvenTree/part/templates/part/part_base.html
@@ -22,11 +22,6 @@
{% if part.description %}
{{ part.description }}
{% endif %}
-
-
-
-
-
{% if part.IPN %}
IPN |
@@ -39,15 +34,22 @@
{{ part.URL }} |
{% endif %}
+
+
+
+
+
+
Stock Status - {{ part.available_stock }} available
+
- Available Stock |
+ In Stock |
- {% if part.available_stock == 0 %}
- {{ part.available_stock }}
- {% elif part.available_stock < part.minimum_stock %}
- {{ part.available_stock }}
+ {% if part.stock == 0 %}
+ {{ part.total_stock }}
+ {% elif part.stock < part.minimum_stock %}
+ {{ part.total_stock }}
{% else %}
- {{ part.available_stock }}
+ {{ part.total_stock }}
{% endif %}
|
@@ -62,6 +64,23 @@
{% endif %}
+ {% if part.quantity_being_built > 0 %}
+
+ Underway |
+ {{ part.quantity_being_built }} |
+
+ {% endif %}
+ {% endif %}
+ {% if part.allocation_count > 0 %}
+
+ Allocated |
+ {% if part.allocation_count > part.total_stock %}
+ {{ part.allocation_count }}
+ {% else %}
+ {{ part.allocation_count }} {{ part.total_stock }}
+ {% endif %}
+ |
+
{% endif %}
diff --git a/InvenTree/part/templates/part/tabs.html b/InvenTree/part/templates/part/tabs.html
index ce1cb7645b..da0b1c9ec2 100644
--- a/InvenTree/part/templates/part/tabs.html
+++ b/InvenTree/part/templates/part/tabs.html
@@ -7,7 +7,10 @@
{% if part.used_in_count > 0 %}
Used In{% if part.used_in_count > 0 %}{{ part.used_in_count }}{% endif %}
{% endif %}
- Stock {{ part.available_stock }}
+ Stock {{ part.total_stock }}
+ {% if part.allocation_count > 0 %}
+ Allocated {{ part.allocation_count }}
+ {% endif %}
{% if part.purchaseable %}
Suppliers
{{ part.supplier_count }}
diff --git a/InvenTree/part/templates/part/used_in.html b/InvenTree/part/templates/part/used_in.html
index 86a57f0b69..4a691aac23 100644
--- a/InvenTree/part/templates/part/used_in.html
+++ b/InvenTree/part/templates/part/used_in.html
@@ -9,11 +9,13 @@
Part |
+ Uses |
Description |
{% for item in part.used_in.all %}
{{ item.part.name }} |
+ {{ item.quantity }} |
{{ item.part.description }} |
{% endfor %}
diff --git a/InvenTree/part/urls.py b/InvenTree/part/urls.py
index ab95b2f43f..97888dc20b 100644
--- a/InvenTree/part/urls.py
+++ b/InvenTree/part/urls.py
@@ -44,6 +44,7 @@ part_detail_urls = [
url(r'^build/?', views.PartDetail.as_view(template_name='part/build.html'), name='part-build'),
url(r'^stock/?', views.PartDetail.as_view(template_name='part/stock.html'), name='part-stock'),
url(r'^used/?', views.PartDetail.as_view(template_name='part/used_in.html'), name='part-used-in'),
+ url(r'^allocation/?', views.PartDetail.as_view(template_name='part/allocation.html'), name='part-allocation'),
url(r'^suppliers/?', views.PartDetail.as_view(template_name='part/supplier.html'), name='part-suppliers'),
# Any other URLs go to the part detail page