mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Update 'Build'
- Part model now has active_builds and inactive_builds properties -
This commit is contained in:
parent
256f8eb924
commit
0b40197cd2
@ -3,18 +3,19 @@ from __future__ import unicode_literals
|
||||
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Build, BuildOutput
|
||||
from .models import Build
|
||||
|
||||
|
||||
class BuildAdmin(admin.ModelAdmin):
|
||||
|
||||
list_display = ('status', )
|
||||
|
||||
|
||||
class BuildOutputAdmin(admin.ModelAdmin):
|
||||
|
||||
list_display = ('build', 'part', 'batch', 'quantity', )
|
||||
|
||||
list_display = ('part',
|
||||
'status',
|
||||
'batch',
|
||||
'quantity',
|
||||
'creation_date',
|
||||
'completion_date',
|
||||
'title',
|
||||
'notes',
|
||||
)
|
||||
|
||||
admin.site.register(Build, BuildAdmin)
|
||||
admin.site.register(BuildOutput, BuildOutputAdmin)
|
66
InvenTree/build/migrations/0006_auto_20180417_0933.py
Normal file
66
InvenTree/build/migrations/0006_auto_20180417_0933.py
Normal file
@ -0,0 +1,66 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.12 on 2018-04-17 09:33
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('part', '0022_auto_20180417_0819'),
|
||||
('build', '0005_buildoutput_batch'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='buildoutput',
|
||||
name='build',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='buildoutput',
|
||||
name='part',
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='build',
|
||||
name='batch',
|
||||
field=models.CharField(blank=True, help_text='Batch code for this build output', max_length=100, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='build',
|
||||
name='completion_date',
|
||||
field=models.DateField(blank=True, null=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='build',
|
||||
name='creation_date',
|
||||
field=models.DateField(auto_now=True),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='build',
|
||||
name='notes',
|
||||
field=models.CharField(blank=True, max_length=500),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='build',
|
||||
name='part',
|
||||
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='builds', to='part.Part'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='build',
|
||||
name='quantity',
|
||||
field=models.PositiveIntegerField(default=1, help_text='Number of parts to build', validators=[django.core.validators.MinValueValidator(1)]),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='build',
|
||||
name='title',
|
||||
field=models.CharField(default='Build title', help_text='Brief description of the build', max_length=100),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='BuildOutput',
|
||||
),
|
||||
]
|
21
InvenTree/build/migrations/0007_auto_20180417_1025.py
Normal file
21
InvenTree/build/migrations/0007_auto_20180417_1025.py
Normal file
@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.11.12 on 2018-04-17 10:25
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('build', '0006_auto_20180417_0933'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='build',
|
||||
name='status',
|
||||
field=models.PositiveIntegerField(choices=[(40, 'Complete'), (10, 'Pending'), (20, 'Holding'), (30, 'Cancelled')], default=10, validators=[django.core.validators.MinValueValidator(0)]),
|
||||
),
|
||||
]
|
@ -15,44 +15,64 @@ class Build(models.Model):
|
||||
"""
|
||||
|
||||
# Build status codes
|
||||
PENDING = 10
|
||||
ALLOCATED = 20
|
||||
HOLDING = 30
|
||||
CANCELLED = 40
|
||||
COMPLETE = 50
|
||||
PENDING = 10 # Build is pending / active
|
||||
HOLDING = 20 # Build is currently being held
|
||||
CANCELLED = 30 # Build was cancelled
|
||||
COMPLETE = 40 # Build is complete
|
||||
|
||||
BUILD_STATUS_CODES = {
|
||||
PENDING : _("Pending"),
|
||||
ALLOCATED : _("Allocated"),
|
||||
HOLDING : _("Holding"),
|
||||
CANCELLED : _("Cancelled"),
|
||||
COMPLETE : _("Complete"),
|
||||
}
|
||||
|
||||
batch = models.CharField(max_length=100, blank=True, null=True,
|
||||
help_text='Batch code for this build output')
|
||||
|
||||
# Status of the build
|
||||
status = models.PositiveIntegerField(default=PENDING,
|
||||
choices=BUILD_STATUS_CODES.items(),
|
||||
validators=[MinValueValidator(0)])
|
||||
|
||||
|
||||
class BuildOutput(models.Model):
|
||||
"""
|
||||
A build output represents a single build part/quantity combination
|
||||
"""
|
||||
# Date the build model was 'created'
|
||||
creation_date = models.DateField(auto_now=True, editable=False)
|
||||
|
||||
batch = models.CharField(max_length=100, blank=True,
|
||||
help_text='Batch code for this build output')
|
||||
# Date the build was 'completed'
|
||||
completion_date = models.DateField(null=True, blank=True)
|
||||
|
||||
# Reference to the build object of which this output is a part
|
||||
# A build can have multiple outputs
|
||||
build = models.ForeignKey(Build, on_delete=models.CASCADE,
|
||||
related_name='outputs')
|
||||
# Brief build title
|
||||
title = models.CharField(max_length=100, help_text='Brief description of the build')
|
||||
|
||||
# A reference to the part being built
|
||||
# Only 'buildable' parts can be selected
|
||||
part = models.ForeignKey(Part, on_delete=models.CASCADE,
|
||||
related_name='builds')
|
||||
related_name='builds',
|
||||
limit_choices_to={'buildable': True},
|
||||
)
|
||||
|
||||
# How many parts to build?
|
||||
quantity = models.PositiveIntegerField(default=1,
|
||||
validators=[MinValueValidator(1)],
|
||||
help_text='Number of parts to build')
|
||||
|
||||
# Notes can be attached to each build output
|
||||
notes = models.CharField(max_length=500, blank=True)
|
||||
|
||||
@property
|
||||
def is_active(self):
|
||||
""" Is this build active?
|
||||
An active build is either:
|
||||
- Pending
|
||||
- Holding
|
||||
"""
|
||||
|
||||
return self.status in [
|
||||
self.PENDING,
|
||||
self.HOLDING
|
||||
]
|
||||
|
||||
@property
|
||||
def is_complete(self):
|
||||
return self.status == self.COMPLETE
|
||||
|
@ -183,6 +183,28 @@ class Part(models.Model):
|
||||
|
||||
return total
|
||||
|
||||
@property
|
||||
def active_builds(self):
|
||||
""" Return a list of outstanding builds.
|
||||
Builds marked as 'complete' or 'cancelled' are ignored
|
||||
"""
|
||||
|
||||
return [b for b in self.builds.all() if b.is_active]
|
||||
|
||||
@property
|
||||
def inactive_builds(self):
|
||||
""" Return a list of inactive builds
|
||||
"""
|
||||
|
||||
return [b for b in self.builds.all() if not b.is_active]
|
||||
|
||||
@property
|
||||
def quantity_being_built(self):
|
||||
""" Return the current number of parts currently being built
|
||||
"""
|
||||
|
||||
return sum([b.quantity for b in self.active_builds])
|
||||
|
||||
@property
|
||||
def total_stock(self):
|
||||
""" Return the total stock quantity for this part.
|
||||
|
@ -4,10 +4,31 @@
|
||||
|
||||
{% include 'part/tabs.html' with tab='build' %}
|
||||
|
||||
<h3>Build Part</h3>
|
||||
<h3>Part Builds</h3>
|
||||
|
||||
TODO
|
||||
<br><br>
|
||||
You can build {{ part.can_build }} of this part with current stock.
|
||||
<table class='table table-striped'>
|
||||
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<th>Quantity</th>
|
||||
<th>Status</th>
|
||||
<th>Completion Date</th>
|
||||
</tr>
|
||||
{% if part.active_builds|length > 0 %}
|
||||
<tr>
|
||||
<td colspan="4"><b>Active Builds</b></td>
|
||||
</tr>
|
||||
{% include "part/build_list.html" with builds=part.active_builds %}
|
||||
{% endif %}
|
||||
|
||||
{% if part.inactive_builds|length > 0 %}
|
||||
<tr><td colspan="4"></td></tr>
|
||||
<tr>
|
||||
<td colspan="4"><b>Inactive Builds</b></td>
|
||||
</tr>
|
||||
{% include "part/build_list.html" with builds=part.inactive_builds %}
|
||||
{% endif %}
|
||||
|
||||
</table>
|
||||
|
||||
{% endblock %}
|
20
InvenTree/part/templates/part/build_list.html
Normal file
20
InvenTree/part/templates/part/build_list.html
Normal file
@ -0,0 +1,20 @@
|
||||
{% for build in builds %}
|
||||
<tr>
|
||||
<td><a href="{% url 'build-detail' build.id %}">{{ build.title }}</a></td>
|
||||
<td>{{ build.quantity }}</td>
|
||||
<td>
|
||||
{% if build.status == build.PENDING %}
|
||||
<span class='label label-info'>
|
||||
{% elif build.status == build.HOLDING %}
|
||||
<span class='label label-warning'>
|
||||
{% elif build.status == build.CANCELLED %}
|
||||
<span class='label label-danger'>
|
||||
{% elif build.status == build.COMPLETE %}
|
||||
<span class='label label-success'>
|
||||
{% endif %}
|
||||
{{ build.get_status_display }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ build.completion_date }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
Loading…
Reference in New Issue
Block a user