Make Build object into a MPTT tree model

- Builds can have child builds
This commit is contained in:
Oliver Walters 2020-04-25 15:25:17 +10:00
parent 2f0bbecc3d
commit c11b433d94
3 changed files with 74 additions and 2 deletions

View File

@ -0,0 +1,55 @@
# Generated by Django 3.0.5 on 2020-04-25 05:07
from django.db import migrations, models
import django.db.models.deletion
import mptt.fields
from build.models import Build
def update_tree(apps, schema_editor):
# Update the Build MPTT model
Build.objects.rebuild()
def nupdate_tree(apps, schema_editor):
pass
class Migration(migrations.Migration):
dependencies = [
('build', '0012_build_sales_order'),
]
operations = [
migrations.AddField(
model_name='build',
name='level',
field=models.PositiveIntegerField(default=0, editable=False),
preserve_default=False,
),
migrations.AddField(
model_name='build',
name='lft',
field=models.PositiveIntegerField(default=0, editable=False),
preserve_default=False,
),
migrations.AddField(
model_name='build',
name='parent',
field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='children', to='build.Build'),
),
migrations.AddField(
model_name='build',
name='rght',
field=models.PositiveIntegerField(default=0, editable=False),
preserve_default=False,
),
migrations.AddField(
model_name='build',
name='tree_id',
field=models.PositiveIntegerField(db_index=True, default=0, editable=False),
preserve_default=False,
),
migrations.RunPython(update_tree, reverse_code=nupdate_tree),
]

View File

@ -18,6 +18,8 @@ from django.core.validators import MinValueValidator
from markdownx.models import MarkdownxField from markdownx.models import MarkdownxField
from mptt.models import MPTTModel, TreeForeignKey
from InvenTree.status_codes import BuildStatus from InvenTree.status_codes import BuildStatus
from InvenTree.fields import InvenTreeURLField from InvenTree.fields import InvenTreeURLField
from InvenTree.helpers import decimal2string from InvenTree.helpers import decimal2string
@ -26,13 +28,14 @@ from stock.models import StockItem
from part.models import Part, BomItem from part.models import Part, BomItem
class Build(models.Model): class Build(MPTTModel):
""" A Build object organises the creation of new parts from the component parts. """ A Build object organises the creation of new parts from the component parts.
Attributes: Attributes:
part: The part to be built (from component BOM items) part: The part to be built (from component BOM items)
title: Brief title describing the build (required) title: Brief title describing the build (required)
quantity: Number of units to be built quantity: Number of units to be built
parent: Reference to a Build object for which this Build is required
sales_order: References to a SalesOrder object for which this Build is required (e.g. the output of this build will be used to fulfil a sales order) sales_order: References to a SalesOrder object for which this Build is required (e.g. the output of this build will be used to fulfil a sales order)
take_from: Location to take stock from to make this build (if blank, can take from anywhere) take_from: Location to take stock from to make this build (if blank, can take from anywhere)
status: Build status code status: Build status code
@ -44,7 +47,7 @@ class Build(models.Model):
""" """
def __str__(self): def __str__(self):
return "Build {q} x {part}".format(q=decimal2string(self.quantity), part=str(self.part)) return "{q} x {part}".format(q=decimal2string(self.quantity), part=str(self.part.full_name))
def get_absolute_url(self): def get_absolute_url(self):
return reverse('build-detail', kwargs={'pk': self.id}) return reverse('build-detail', kwargs={'pk': self.id})
@ -55,6 +58,13 @@ class Build(models.Model):
help_text=_('Brief description of the build') help_text=_('Brief description of the build')
) )
parent = TreeForeignKey(
'self',
on_delete=models.DO_NOTHING,
blank=True, null=True,
related_name='children'
)
part = models.ForeignKey( part = models.ForeignKey(
'part.Part', 'part.Part',
on_delete=models.CASCADE, on_delete=models.CASCADE,

View File

@ -75,6 +75,13 @@ src="{% static 'img/blank_image.png' %}"
<td>{% trans "Status" %}</td> <td>{% trans "Status" %}</td>
<td>{% build_status_label build.status %}</td> <td>{% build_status_label build.status %}</td>
</tr> </tr>
{% if build.parent %}
<tr>
<td><span class='fas fa-tools'></span></td>
<td>{% trans "Parent Build" %}</td>
<td><a href="{% url 'build-detail' build.parent.id %}">{{ build.parent }}</a></td>
</tr>
{% endif %}
{% if build.sales_order %} {% if build.sales_order %}
<tr> <tr>
<td><span class='fas fa-dolly'></span></td> <td><span class='fas fa-dolly'></span></td>