mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Add "target_date" for Build model
- Add "overdue" status to Build serializer
This commit is contained in:
parent
a7d825158c
commit
802dd5174c
@ -46,6 +46,8 @@ class BuildList(generics.ListCreateAPIView):
|
|||||||
|
|
||||||
queryset = super().get_queryset().prefetch_related('part')
|
queryset = super().get_queryset().prefetch_related('part')
|
||||||
|
|
||||||
|
queryset = BuildSerializer.annotate_queryset(queryset)
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
def filter_queryset(self, queryset):
|
def filter_queryset(self, queryset):
|
||||||
|
@ -40,6 +40,7 @@ class EditBuildForm(HelperForm):
|
|||||||
'part',
|
'part',
|
||||||
'quantity',
|
'quantity',
|
||||||
'batch',
|
'batch',
|
||||||
|
'target_date',
|
||||||
'take_from',
|
'take_from',
|
||||||
'destination',
|
'destination',
|
||||||
'parent',
|
'parent',
|
||||||
|
18
InvenTree/build/migrations/0025_build_target_date.py
Normal file
18
InvenTree/build/migrations/0025_build_target_date.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 3.0.7 on 2020-12-15 12:13
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('build', '0024_auto_20201201_1023'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='build',
|
||||||
|
name='target_date',
|
||||||
|
field=models.DateField(blank=True, help_text='Target date for build completion. Build will be overdue after this date.', null=True, verbose_name='Target completion date'),
|
||||||
|
),
|
||||||
|
]
|
@ -47,7 +47,8 @@ class Build(MPTTModel):
|
|||||||
status: Build status code
|
status: Build status code
|
||||||
batch: Batch code transferred to build parts (optional)
|
batch: Batch code transferred to build parts (optional)
|
||||||
creation_date: Date the build was created (auto)
|
creation_date: Date the build was created (auto)
|
||||||
completion_date: Date the build was completed
|
target_date: Date the build will be overdue
|
||||||
|
completion_date: Date the build was completed (or, if incomplete, the expected date of completion)
|
||||||
link: External URL for extra information
|
link: External URL for extra information
|
||||||
notes: Text notes
|
notes: Text notes
|
||||||
"""
|
"""
|
||||||
@ -164,6 +165,12 @@ class Build(MPTTModel):
|
|||||||
|
|
||||||
creation_date = models.DateField(auto_now_add=True, editable=False)
|
creation_date = models.DateField(auto_now_add=True, editable=False)
|
||||||
|
|
||||||
|
target_date = models.DateField(
|
||||||
|
null=True, blank=True,
|
||||||
|
verbose_name=_('Target completion date'),
|
||||||
|
help_text=_('Target date for build completion. Build will be overdue after this date.')
|
||||||
|
)
|
||||||
|
|
||||||
completion_date = models.DateField(null=True, blank=True)
|
completion_date = models.DateField(null=True, blank=True)
|
||||||
|
|
||||||
completed_by = models.ForeignKey(
|
completed_by = models.ForeignKey(
|
||||||
@ -183,6 +190,22 @@ class Build(MPTTModel):
|
|||||||
blank=True, help_text=_('Extra build notes')
|
blank=True, help_text=_('Extra build notes')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def is_overdue(self):
|
||||||
|
"""
|
||||||
|
Returns true if this build is "overdue":
|
||||||
|
|
||||||
|
- Not completed
|
||||||
|
- Target date is "in the past"
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Cannot be deemed overdue if target_date is not set
|
||||||
|
if self.target_date is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
today = datetime.now().date()
|
||||||
|
|
||||||
|
return self.active and self.target_date < today
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def active(self):
|
def active(self):
|
||||||
"""
|
"""
|
||||||
|
@ -5,12 +5,21 @@ JSON serializers for Build API
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
from django.db.models import Q
|
||||||
|
from django.db.models import Case, When, Value
|
||||||
|
from django.db.models import BooleanField
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from InvenTree.serializers import InvenTreeModelSerializer
|
from InvenTree.serializers import InvenTreeModelSerializer
|
||||||
|
from InvenTree.status_codes import BuildStatus
|
||||||
|
|
||||||
from stock.serializers import StockItemSerializerBrief
|
from stock.serializers import StockItemSerializerBrief
|
||||||
|
from part.serializers import PartBriefSerializer
|
||||||
|
|
||||||
from .models import Build, BuildItem
|
from .models import Build, BuildItem
|
||||||
from part.serializers import PartBriefSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class BuildSerializer(InvenTreeModelSerializer):
|
class BuildSerializer(InvenTreeModelSerializer):
|
||||||
@ -23,6 +32,38 @@ class BuildSerializer(InvenTreeModelSerializer):
|
|||||||
|
|
||||||
quantity = serializers.FloatField()
|
quantity = serializers.FloatField()
|
||||||
|
|
||||||
|
overdue = serializers.BooleanField()
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def annotate_queryset(queryset):
|
||||||
|
"""
|
||||||
|
Add custom annotations to the BuildSerializer queryset,
|
||||||
|
performing database queries as efficiently as possible.
|
||||||
|
|
||||||
|
The following annoted fields are added:
|
||||||
|
|
||||||
|
- overdue: True if the build is outstanding *and* the completion date has past
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Annotate a boolean 'overdue' flag
|
||||||
|
|
||||||
|
# Construct a filter for finding overdue builds
|
||||||
|
today = datetime.datetime.now().date()
|
||||||
|
overdue = Q(status__in=BuildStatus.ACTIVE_CODES) & ~Q(target_date=None) & Q(target_date__lte=today)
|
||||||
|
|
||||||
|
queryset = queryset.annotate(
|
||||||
|
overdue=Case(
|
||||||
|
When(
|
||||||
|
overdue, then=Value(True, output_field=BooleanField()),
|
||||||
|
),
|
||||||
|
default=Value(False, output_field=BooleanField())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
part_detail = kwargs.pop('part_detail', False)
|
part_detail = kwargs.pop('part_detail', False)
|
||||||
|
|
||||||
@ -42,11 +83,13 @@ class BuildSerializer(InvenTreeModelSerializer):
|
|||||||
'completion_date',
|
'completion_date',
|
||||||
'part',
|
'part',
|
||||||
'part_detail',
|
'part_detail',
|
||||||
|
'overdue',
|
||||||
'reference',
|
'reference',
|
||||||
'sales_order',
|
'sales_order',
|
||||||
'quantity',
|
'quantity',
|
||||||
'status',
|
'status',
|
||||||
'status_text',
|
'status_text',
|
||||||
|
'target_date',
|
||||||
'notes',
|
'notes',
|
||||||
'link',
|
'link',
|
||||||
]
|
]
|
||||||
|
@ -95,33 +95,26 @@
|
|||||||
<td>{% trans "Created" %}</td>
|
<td>{% trans "Created" %}</td>
|
||||||
<td>{{ build.creation_date }}</td>
|
<td>{{ build.creation_date }}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
<tr>
|
||||||
</div>
|
<td><span class='fas fa-calendar-alt'></span></td>
|
||||||
<div class='col-sm-6'>
|
<td>{% trans "Target Date" %}</td>
|
||||||
<table class='table table-striped'>
|
{% if build.target_date %}
|
||||||
<col width='25'>
|
<td>
|
||||||
<tr>
|
{{ build.target_date }}{% if build.is_overdue %} <span class='fas fa-calendar-times icon-red'></span>{% endif %}
|
||||||
<td><span class='fas fa-dollar-sign'></span></td>
|
</td>
|
||||||
<td>{% trans "BOM Price" %}</td>
|
{% else %}
|
||||||
<td>
|
<td><i>{% trans "No target date set" %}</i></td>
|
||||||
{% if bom_price %}
|
|
||||||
{{ bom_price }}
|
|
||||||
{% if build.part.has_complete_bom_pricing == False %}
|
|
||||||
<br><span class='warning-msg'><i>{% trans "BOM pricing is incomplete" %}</i></span>
|
|
||||||
{% endif %}
|
|
||||||
{% else %}
|
|
||||||
<span class='warning-msg'><i>{% trans "No pricing information" %}</i></span>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% if build.completion_date %}
|
|
||||||
<tr>
|
|
||||||
<td><span class='fas fa-calendar-alt'></span></td>
|
|
||||||
<td>{% trans "Completed" %}</td>
|
|
||||||
<td>{{ build.completion_date }}{% if build.completed_by %}<span class='badge'>{{ build.completed_by }}</span>{% endif %}</td>
|
|
||||||
</tr>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><span class='fas fa-calendar-alt'></span></td>
|
||||||
|
<td>{% trans "Completed" %}</td>
|
||||||
|
{% if build.completion_date %}
|
||||||
|
<td>{{ build.completion_date }}{% if build.completed_by %}<span class='badge'>{{ build.completed_by }}</span>{% endif %}</td>
|
||||||
|
{% else %}
|
||||||
|
<td><i>{% trans "Build not complete" %}</i></td>
|
||||||
|
{% endif %}
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user