2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-18 04:55:44 +00:00

Refactor states/status (#4857)

* add file for states

* move general definition out

* add some tests and docs

* add tests for invalid definitions

* make status_label tag generic

* move templatetags

* remove unused tag

* rename test file

* make status label a lookup

* rename tags

* move import structure

* add missing tag

* collect states dynamically

* fix context function

* move api function out

* add tests for tags

* rename tests

* refactor imports

* Add test for API function

* improve errors and add tests for imporved errors

* make test calls simpler

* refactor definitions to use enums

* switch to enum

* refactor definitions to use enums

* fix lookup

* fix tag name

* make _TAG lookup a function

* cleanup BaseEnum

* make _TAG definition simpler

* restructure status codes to enum

* reduce LoC

* type status codes as int

* add specific function for template context

* Add definition for lookups

* fix filter lookup

* TEST: "fix" action lookup

* Add missing migrations

* Make all group code references explict

* change default on models to value

* switch to IntEnum

* move groups into a seperate class

* only request _TAG if it exsists

* use value and list

* use dedicated groups

* fix stock assigment

* fix order code

* more fixes

* fix borked change

* fix render lookup

* add group

* fix import

* fix syntax

* clenup

* fix migrations

* fix typo

* fix wrong value usage

* fix test

* remove group section

* remove group section

* add more test cases

* Add more docstring

* move choices out of migrations

* change import ordeR?

* last try before I revert

* Update part.migrations.0112

- Add custom migration class which handles errors

* Add unit test for migration

- Ensure that the new fields are added to the model

* Update reference to PR

---------

Co-authored-by: Oliver Walters <oliver.henry.walters@gmail.com>
This commit is contained in:
Matthias Mair
2023-06-09 02:27:26 +02:00
committed by GitHub
parent 005c8341bf
commit 5d1d8ec889
51 changed files with 677 additions and 586 deletions

View File

@ -29,8 +29,9 @@ from InvenTree.mixins import (CreateAPI, CustomRetrieveUpdateDestroyAPI,
RetrieveUpdateAPI, RetrieveUpdateDestroyAPI,
UpdateAPI)
from InvenTree.permissions import RolePermission
from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus,
SalesOrderStatus)
from InvenTree.status_codes import (BuildStatusGroups,
PurchaseOrderStatusGroups,
SalesOrderStatusGroups)
from part.admin import PartCategoryResource, PartResource
from . import serializers as part_serializers
@ -479,7 +480,7 @@ class PartScheduling(RetrieveAPI):
# Add purchase order (incoming stock) information
po_lines = order.models.PurchaseOrderLineItem.objects.filter(
part__part=part,
order__status__in=PurchaseOrderStatus.OPEN,
order__status__in=PurchaseOrderStatusGroups.OPEN,
)
for line in po_lines:
@ -502,7 +503,7 @@ class PartScheduling(RetrieveAPI):
# Add sales order (outgoing stock) information
so_lines = order.models.SalesOrderLineItem.objects.filter(
part=part,
order__status__in=SalesOrderStatus.OPEN,
order__status__in=SalesOrderStatusGroups.OPEN,
)
for line in so_lines:
@ -522,7 +523,7 @@ class PartScheduling(RetrieveAPI):
# Add build orders (incoming stock) information
build_orders = Build.objects.filter(
part=part,
status__in=BuildStatus.ACTIVE_CODES
status__in=BuildStatusGroups.ACTIVE_CODES
)
for build in build_orders:
@ -567,12 +568,12 @@ class PartScheduling(RetrieveAPI):
# An "inherited" BOM item filters down to variant parts also
children = bom_item.part.get_descendants(include_self=True)
builds = Build.objects.filter(
status__in=BuildStatus.ACTIVE_CODES,
status__in=BuildStatusGroups.ACTIVE_CODES,
part__in=children,
)
else:
builds = Build.objects.filter(
status__in=BuildStatus.ACTIVE_CODES,
status__in=BuildStatusGroups.ACTIVE_CODES,
part=bom_item.part,
)
@ -1197,7 +1198,7 @@ class PartList(PartMixin, APIDownloadMixin, ListCreateAPI):
if stock_to_build is not None:
# Get active builds
builds = Build.objects.filter(status__in=BuildStatus.ACTIVE_CODES)
builds = Build.objects.filter(status__in=BuildStatusGroups.ACTIVE_CODES)
# Store parts with builds needing stock
parts_needed_to_complete_builds = []
# Filter required parts

View File

@ -28,8 +28,9 @@ from sql_util.utils import SubquerySum
import part.models
import stock.models
from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus,
SalesOrderStatus)
from InvenTree.status_codes import (BuildStatusGroups,
PurchaseOrderStatusGroups,
SalesOrderStatusGroups)
def annotate_on_order_quantity(reference: str = ''):
@ -46,7 +47,7 @@ def annotate_on_order_quantity(reference: str = ''):
# Filter only 'active' purhase orders
# Filter only line with outstanding quantity
order_filter = Q(
order__status__in=PurchaseOrderStatus.OPEN,
order__status__in=PurchaseOrderStatusGroups.OPEN,
quantity__gt=F('received'),
)
@ -111,7 +112,7 @@ def annotate_build_order_allocations(reference: str = ''):
"""
# Build filter only returns 'active' build orders
build_filter = Q(build__status__in=BuildStatus.ACTIVE_CODES)
build_filter = Q(build__status__in=BuildStatusGroups.ACTIVE_CODES)
return Coalesce(
SubquerySum(
@ -137,7 +138,7 @@ def annotate_sales_order_allocations(reference: str = ''):
# Order filter only returns incomplete shipments for open orders
order_filter = Q(
line__order__status__in=SalesOrderStatus.OPEN,
line__order__status__in=SalesOrderStatusGroups.OPEN,
shipment__shipment_date=None,
)

View File

@ -51,8 +51,9 @@ from InvenTree.helpers import (decimal2money, decimal2string, normalize,
from InvenTree.models import (DataImportMixin, InvenTreeAttachment,
InvenTreeBarcodeMixin, InvenTreeNotesMixin,
InvenTreeTree, MetadataMixin)
from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus,
SalesOrderStatus)
from InvenTree.status_codes import (BuildStatusGroups, PurchaseOrderStatus,
PurchaseOrderStatusGroups,
SalesOrderStatus, SalesOrderStatusGroups)
from order import models as OrderModels
from stock import models as StockModels
@ -1070,7 +1071,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
# Now, get a list of outstanding build orders which require this part
builds = BuildModels.Build.objects.filter(
part__in=self.get_used_in(),
status__in=BuildStatus.ACTIVE_CODES
status__in=BuildStatusGroups.ACTIVE_CODES
)
return builds
@ -1104,7 +1105,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
# Get a list of line items for open orders which match this part
open_lines = OrderModels.SalesOrderLineItem.objects.filter(
order__status__in=SalesOrderStatus.OPEN,
order__status__in=SalesOrderStatusGroups.OPEN,
part=self
)
@ -1117,7 +1118,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
"""Return the quantity of this part required for active sales orders."""
# Get a list of line items for open orders which match this part
open_lines = OrderModels.SalesOrderLineItem.objects.filter(
order__status__in=SalesOrderStatus.OPEN,
order__status__in=SalesOrderStatusGroups.OPEN,
part=self
)
@ -1329,7 +1330,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
Builds marked as 'complete' or 'cancelled' are ignored
"""
return self.builds.filter(status__in=BuildStatus.ACTIVE_CODES)
return self.builds.filter(status__in=BuildStatusGroups.ACTIVE_CODES)
@property
def quantity_being_built(self):
@ -1401,13 +1402,13 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
if pending is True:
# Look only for 'open' orders which have not shipped
queryset = queryset.filter(
line__order__status__in=SalesOrderStatus.OPEN,
line__order__status__in=SalesOrderStatusGroups.OPEN,
shipment__shipment_date=None,
)
elif pending is False:
# Look only for 'closed' orders or orders which have shipped
queryset = queryset.exclude(
line__order__status__in=SalesOrderStatus.OPEN,
line__order__status__in=SalesOrderStatusGroups.OPEN,
shipment__shipment_date=None,
)
@ -2161,7 +2162,7 @@ class Part(InvenTreeBarcodeMixin, InvenTreeNotesMixin, MetadataMixin, MPTTModel)
# Look at any incomplete line item for open orders
lines = sp.purchase_order_line_items.filter(
order__status__in=PurchaseOrderStatus.OPEN,
order__status__in=PurchaseOrderStatusGroups.OPEN,
quantity__gt=F('received'),
)
@ -2559,7 +2560,7 @@ class PartPricing(common.models.MetaMixin):
# Find all line items for completed orders which reference this part
line_items = OrderModels.PurchaseOrderLineItem.objects.filter(
order__status=PurchaseOrderStatus.COMPLETE,
order__status=PurchaseOrderStatus.COMPLETE.value,
received__gt=0,
part__part=self.part,
)

View File

@ -25,7 +25,7 @@ import InvenTree.status
import part.filters
import part.tasks
import stock.models
from InvenTree.status_codes import BuildStatus
from InvenTree.status_codes import BuildStatusGroups
from InvenTree.tasks import offload_task
from .models import (BomItem, BomItemSubstitute, Part, PartAttachment,
@ -532,7 +532,7 @@ class PartSerializer(InvenTree.serializers.RemoteImageMixin, InvenTree.serialize
# Filter to limit builds to "active"
build_filter = Q(
status__in=BuildStatus.ACTIVE_CODES
status__in=BuildStatusGroups.ACTIVE_CODES
)
# Annotate with the total 'building' quantity

View File

@ -1,46 +0,0 @@
"""Provide templates for the various model status codes."""
from django import template
from django.utils.safestring import mark_safe
from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus,
ReturnOrderStatus, SalesOrderStatus,
StockStatus)
register = template.Library()
@register.simple_tag
def purchase_order_status_label(key, *args, **kwargs):
"""Render a PurchaseOrder status label."""
return mark_safe(PurchaseOrderStatus.render(key, large=kwargs.get('large', False)))
@register.simple_tag
def sales_order_status_label(key, *args, **kwargs):
"""Render a SalesOrder status label."""
return mark_safe(SalesOrderStatus.render(key, large=kwargs.get('large', False)))
@register.simple_tag
def return_order_status_label(key, *args, **kwargs):
"""Render a ReturnOrder status label"""
return mark_safe(ReturnOrderStatus.render(key, large=kwargs.get('large', False)))
@register.simple_tag
def stock_status_label(key, *args, **kwargs):
"""Render a StockItem status label."""
return mark_safe(StockStatus.render(key, large=kwargs.get('large', False)))
@register.simple_tag
def stock_status_text(key, *args, **kwargs):
"""Render the text value of a StockItem status value"""
return mark_safe(StockStatus.text(key))
@register.simple_tag
def build_status_label(key, *args, **kwargs):
"""Render a Build status label."""
return mark_safe(BuildStatus.render(key, large=kwargs.get('large', False)))

View File

@ -18,7 +18,7 @@ import company.models
import order.models
from common.models import InvenTreeSetting
from company.models import Company, SupplierPart
from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatus,
from InvenTree.status_codes import (BuildStatus, PurchaseOrderStatusGroups,
StockStatus)
from InvenTree.unit_test import InvenTreeAPITestCase
from part.models import (BomItem, BomItemSubstitute, Part, PartCategory,
@ -1628,7 +1628,7 @@ class PartDetailTests(PartAPITestBase):
# How many parts are 'on order' for this part?
lines = order.models.PurchaseOrderLineItem.objects.filter(
part__part__pk=1,
order__status__in=PurchaseOrderStatus.OPEN,
order__status__in=PurchaseOrderStatusGroups.OPEN,
)
on_order = 0
@ -1857,7 +1857,7 @@ class PartAPIAggregationTest(InvenTreeAPITestCase):
StockItem.objects.create(part=cls.part, quantity=300)
# Now create another 400 units which are LOST
StockItem.objects.create(part=cls.part, quantity=400, status=StockStatus.LOST)
StockItem.objects.create(part=cls.part, quantity=400, status=StockStatus.LOST.value)
def get_part_data(self):
"""Helper function for retrieving part data"""
@ -1992,7 +1992,7 @@ class PartAPIAggregationTest(InvenTreeAPITestCase):
quantity=10,
title='Making some assemblies',
reference='BO-9999',
status=BuildStatus.PRODUCTION,
status=BuildStatus.PRODUCTION.value,
)
bom_item = BomItem.objects.get(pk=6)
@ -2133,7 +2133,7 @@ class PartAPIAggregationTest(InvenTreeAPITestCase):
for line_item in sp.purchase_order_line_items.all():
po = line_item.order
if po.status in PurchaseOrderStatus.OPEN:
if po.status in PurchaseOrderStatusGroups.OPEN:
remaining = line_item.quantity - line_item.received
if remaining > 0:

View File

@ -345,7 +345,7 @@ class PartPricingTests(InvenTreeTestCase):
self.assertIsNone(pricing.purchase_cost_min)
self.assertIsNone(pricing.purchase_cost_max)
po.status = PurchaseOrderStatus.COMPLETE
po.status = PurchaseOrderStatus.COMPLETE.value
po.save()
pricing.update_purchase_cost()