mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Improved part logic
- Added field 'buildable' - can this part be made from other parts? - Added @propery 'supplier_count' - Improved part detail page with new features
This commit is contained in:
parent
e43439ef5b
commit
118d045e50
@ -8,7 +8,7 @@ from .models import PartAttachment
|
|||||||
|
|
||||||
class PartAdmin(ImportExportModelAdmin):
|
class PartAdmin(ImportExportModelAdmin):
|
||||||
|
|
||||||
list_display = ('name', 'IPN', 'description', 'stock', 'category')
|
list_display = ('name', 'IPN', 'description', 'total_stock', 'category')
|
||||||
|
|
||||||
|
|
||||||
class PartCategoryAdmin(admin.ModelAdmin):
|
class PartCategoryAdmin(admin.ModelAdmin):
|
||||||
|
@ -25,6 +25,7 @@ class EditPartForm(forms.ModelForm):
|
|||||||
'IPN',
|
'IPN',
|
||||||
'URL',
|
'URL',
|
||||||
'minimum_stock',
|
'minimum_stock',
|
||||||
|
'buildable',
|
||||||
'trackable',
|
'trackable',
|
||||||
'purchaseable',
|
'purchaseable',
|
||||||
]
|
]
|
||||||
@ -58,7 +59,7 @@ class EditBomItemForm(forms.ModelForm):
|
|||||||
|
|
||||||
self.helper.form_id = 'id-edit-part-form'
|
self.helper.form_id = 'id-edit-part-form'
|
||||||
self.helper.form_method = 'post'
|
self.helper.form_method = 'post'
|
||||||
|
|
||||||
self.helper.add_input(Submit('submit', 'Submit'))
|
self.helper.add_input(Submit('submit', 'Submit'))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
20
InvenTree/part/migrations/0018_part_buildable.py
Normal file
20
InvenTree/part/migrations/0018_part_buildable.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.11 on 2018-04-16 12:08
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('part', '0017_part_purchaseable'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='part',
|
||||||
|
name='buildable',
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
@ -110,6 +110,9 @@ class Part(models.Model):
|
|||||||
# Units of quantity for this part. Default is "pcs"
|
# Units of quantity for this part. Default is "pcs"
|
||||||
units = models.CharField(max_length=20, default="pcs", blank=True)
|
units = models.CharField(max_length=20, default="pcs", blank=True)
|
||||||
|
|
||||||
|
# Can this part be built?
|
||||||
|
buildable = models.BooleanField(default=False)
|
||||||
|
|
||||||
# Is this part "trackable"?
|
# Is this part "trackable"?
|
||||||
# Trackable parts can have unique instances
|
# Trackable parts can have unique instances
|
||||||
# which are assigned serial numbers (or batch numbers)
|
# which are assigned serial numbers (or batch numbers)
|
||||||
@ -139,7 +142,8 @@ class Part(models.Model):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# TODO - For now, just return total stock count
|
# TODO - For now, just return total stock count
|
||||||
return self.stock
|
# TODO - In future must take account of allocated stock
|
||||||
|
return self.total_stock
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def can_build(self):
|
def can_build(self):
|
||||||
@ -152,6 +156,7 @@ class Part(models.Model):
|
|||||||
|
|
||||||
total = None
|
total = None
|
||||||
|
|
||||||
|
# Calculate the minimum number of parts that can be built using each sub-part
|
||||||
for item in self.bom_items.all():
|
for item in self.bom_items.all():
|
||||||
stock = item.sub_part.available_stock
|
stock = item.sub_part.available_stock
|
||||||
n = int(1.0 * stock / item.quantity)
|
n = int(1.0 * stock / item.quantity)
|
||||||
@ -162,7 +167,7 @@ class Part(models.Model):
|
|||||||
return total
|
return total
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def stock(self):
|
def total_stock(self):
|
||||||
""" Return the total stock quantity for this part.
|
""" Return the total stock quantity for this part.
|
||||||
Part may be stored in multiple locations
|
Part may be stored in multiple locations
|
||||||
"""
|
"""
|
||||||
@ -176,16 +181,21 @@ class Part(models.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def has_bom(self):
|
def has_bom(self):
|
||||||
return self.bom_item_count > 0
|
return self.bom_count > 0
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def bom_item_count(self):
|
def bom_count(self):
|
||||||
return self.bom_items.all().count()
|
return self.bom_items.all().count()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def used_in_count(self):
|
def used_in_count(self):
|
||||||
return self.used_in.all().count()
|
return self.used_in.all().count()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def supplier_count(self):
|
||||||
|
# Return the number of supplier parts available for this part
|
||||||
|
return self.supplier_parts.all().count()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@property
|
@property
|
||||||
def projects(self):
|
def projects(self):
|
||||||
|
@ -25,6 +25,10 @@
|
|||||||
<td>Units</td>
|
<td>Units</td>
|
||||||
<td>{{ part.units }}</td>
|
<td>{{ part.units }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Buildable</td>
|
||||||
|
<td>{{ part.buildable }}</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Trackable</td>
|
<td>Trackable</td>
|
||||||
<td>{{ part.trackable }}</td>
|
<td>{{ part.trackable }}</td>
|
||||||
|
@ -41,12 +41,24 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>Available Stock</td>
|
<td>Available Stock</td>
|
||||||
<td>{{ part.available_stock }}</td>
|
<td>
|
||||||
|
{% if part.available_stock == 0 or part.available_stock < part.minimum_stock %}
|
||||||
|
<span class='label label-danger'>{{ part.available_stock }}</span>
|
||||||
|
{% else %}
|
||||||
|
{{ part.available_stock }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if part.has_bom %}
|
{% if part.buildable %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>Can Build</td>
|
<td>Can Build</td>
|
||||||
<td>{{ part.can_build }}</td>
|
<td>
|
||||||
|
{% if part.can_build == 0 %}
|
||||||
|
<span class='label label-danger'>0</span>
|
||||||
|
{% else %}
|
||||||
|
{{ part.can_build }}
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</table>
|
</table>
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
<li{% ifequal tab 'detail' %} class="active"{% endifequal %}><a href="{% url 'part-detail' part.id %}">Details</a></li>
|
<li{% ifequal tab 'detail' %} class="active"{% endifequal %}><a href="{% url 'part-detail' part.id %}">Details</a></li>
|
||||||
<li{% ifequal tab 'bom' %} class="active"{% endifequal %}><a href="{% url 'part-bom' part.id %}">BOM{% if part.has_bom > 0 %}<span class="badge">{{ part.bom_item_cout }}</span>{% endif %}</a></li>
|
{% if part.buildable %}
|
||||||
{% if part.has_bom %}
|
<li{% ifequal tab 'bom' %} class="active"{% endifequal %}><a href="{% url 'part-bom' part.id %}">BOM<span class="badge">{{ part.bom_count }}</span></a></li>
|
||||||
<li{% ifequal tab 'build' %} class "active"{% endifequal %}><a href="#">Build</a></li>
|
<li{% ifequal tab 'build' %} class "active"{% endifequal %}><a href="#">Build<span class='badge'>{{ part.can_build }}</span></a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if part.used_in_count > 0 %}
|
{% if part.used_in_count > 0 %}
|
||||||
<li{% ifequal tab 'used' %} class="active"{% endifequal %}><a href="{% url 'part-used-in' part.id %}">Used In{% if part.used_in_count > 0 %}<span class="badge">{{ part.used_in_count }}</span>{% endif %}</a></li>
|
<li{% ifequal tab 'used' %} class="active"{% endifequal %}><a href="{% url 'part-used-in' part.id %}">Used In{% if part.used_in_count > 0 %}<span class="badge">{{ part.used_in_count }}</span>{% endif %}</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li{% ifequal tab 'stock' %} class="active"{% endifequal %}><a href="{% url 'part-stock' part.id %}">Stock <span class="badge">{{ part.stock }}</span></a></li>
|
<li{% ifequal tab 'stock' %} class="active"{% endifequal %}><a href="{% url 'part-stock' part.id %}">Stock <span class="badge">{{ part.available_stock }}</span></a></li>
|
||||||
{% if part.purchaseable %}
|
{% if part.purchaseable %}
|
||||||
<li{% ifequal tab 'suppliers' %} class="active"{% endifequal %}><a href="{% url 'part-suppliers' part.id %}">Suppliers
|
<li{% ifequal tab 'suppliers' %} class="active"{% endifequal %}><a href="{% url 'part-suppliers' part.id %}">Suppliers
|
||||||
{% if part.supplier_parts.all|length > 0 %}
|
<span class="badge">{{ part.supplier_count }}<span>
|
||||||
<span class="badge">{{ part.supplier_parts.all|length }}<span>
|
|
||||||
{% endif %}
|
|
||||||
</a></li>
|
</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if part.trackable %}
|
{% if part.trackable %}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user