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 = BuildSerializer.annotate_queryset(queryset)
|
||||
|
||||
return queryset
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
|
@ -40,6 +40,7 @@ class EditBuildForm(HelperForm):
|
||||
'part',
|
||||
'quantity',
|
||||
'batch',
|
||||
'target_date',
|
||||
'take_from',
|
||||
'destination',
|
||||
'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
|
||||
batch: Batch code transferred to build parts (optional)
|
||||
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
|
||||
notes: Text notes
|
||||
"""
|
||||
@ -164,6 +165,12 @@ class Build(MPTTModel):
|
||||
|
||||
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)
|
||||
|
||||
completed_by = models.ForeignKey(
|
||||
@ -183,6 +190,22 @@ class Build(MPTTModel):
|
||||
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
|
||||
def active(self):
|
||||
"""
|
||||
|
@ -5,12 +5,21 @@ JSON serializers for Build API
|
||||
# -*- coding: utf-8 -*-
|
||||
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 InvenTree.serializers import InvenTreeModelSerializer
|
||||
from InvenTree.status_codes import BuildStatus
|
||||
|
||||
from stock.serializers import StockItemSerializerBrief
|
||||
from part.serializers import PartBriefSerializer
|
||||
|
||||
from .models import Build, BuildItem
|
||||
from part.serializers import PartBriefSerializer
|
||||
|
||||
|
||||
class BuildSerializer(InvenTreeModelSerializer):
|
||||
@ -23,6 +32,38 @@ class BuildSerializer(InvenTreeModelSerializer):
|
||||
|
||||
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):
|
||||
part_detail = kwargs.pop('part_detail', False)
|
||||
|
||||
@ -42,11 +83,13 @@ class BuildSerializer(InvenTreeModelSerializer):
|
||||
'completion_date',
|
||||
'part',
|
||||
'part_detail',
|
||||
'overdue',
|
||||
'reference',
|
||||
'sales_order',
|
||||
'quantity',
|
||||
'status',
|
||||
'status_text',
|
||||
'target_date',
|
||||
'notes',
|
||||
'link',
|
||||
]
|
||||
|
@ -95,33 +95,26 @@
|
||||
<td>{% trans "Created" %}</td>
|
||||
<td>{{ build.creation_date }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class='col-sm-6'>
|
||||
<table class='table table-striped'>
|
||||
<col width='25'>
|
||||
<tr>
|
||||
<td><span class='fas fa-dollar-sign'></span></td>
|
||||
<td>{% trans "BOM Price" %}</td>
|
||||
<td><span class='fas fa-calendar-alt'></span></td>
|
||||
<td>{% trans "Target Date" %}</td>
|
||||
{% if build.target_date %}
|
||||
<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 %}
|
||||
{{ build.target_date }}{% if build.is_overdue %} <span class='fas fa-calendar-times icon-red'></span>{% endif %}
|
||||
</td>
|
||||
{% else %}
|
||||
<td><i>{% trans "No target date set" %}</i></td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% if build.completion_date %}
|
||||
<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>
|
||||
</tr>
|
||||
{% else %}
|
||||
<td><i>{% trans "Build not complete" %}</i></td>
|
||||
{% endif %}
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user