Update 'Build'

- Part model now has active_builds and inactive_builds properties
-
This commit is contained in:
Oliver 2018-04-17 20:25:43 +10:00
parent 256f8eb924
commit 0b40197cd2
7 changed files with 201 additions and 30 deletions

View File

@ -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)

View 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',
),
]

View 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)]),
),
]

View File

@ -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

View File

@ -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.

View File

@ -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 %}

View 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 %}