Skip to content

Commit

Permalink
Merge branch 'master' into dependabot/pip/src/backend/djangorestframe…
Browse files Browse the repository at this point in the history
…work-3.15.2
  • Loading branch information
SchrodingersGat authored Aug 21, 2024
2 parents 4c5dada + d5086b2 commit a8951d9
Show file tree
Hide file tree
Showing 72 changed files with 1,552 additions and 186 deletions.
15 changes: 15 additions & 0 deletions docs/docs/concepts/custom_states.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
title: Custom States
---

## Custom States

Several models within InvenTree support the use of custom states. The custom states are display only - the business logic is not affected by the state.

States can be added in the Admin Center under the "Custom States" section. Each state has a name, label and a color that are used to display the state in the user interface. Changes to these settings will only be reflected in the user interface after a full reload of the interface.

States need to be assigned to a model, state (for example status on a StockItem) and a logical key - that will be used for business logic. These 3 values combined need to be unique throughout the system.

Custom states can be used in the following models:
- StockItem
- Orders (PurchaseOrder, SalesOrder, ReturnOrder, ReturnOrderLine)
8 changes: 5 additions & 3 deletions docs/docs/extend/machines/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ If you want to create your own machine type, please also take a look at the alre

```py
from django.utils.translation import gettext_lazy as _

from generic.states import ColorEnum
from plugin.machine import BaseDriver, BaseMachineType, MachineStatus

class ABCBaseDriver(BaseDriver):
Expand All @@ -72,9 +74,9 @@ class ABCMachine(BaseMachineType):
base_driver = ABCBaseDriver

class ABCStatus(MachineStatus):
CONNECTED = 100, _('Connected'), 'success'
STANDBY = 101, _('Standby'), 'success'
PRINTING = 110, _('Printing'), 'primary'
CONNECTED = 100, _('Connected'), ColorEnum.success
STANDBY = 101, _('Standby'), ColorEnum.success
PRINTING = 110, _('Printing'), ColorEnum.primary

MACHINE_STATUS = ABCStatus
default_machine_status = ABCStatus.DISCONNECTED
Expand Down
2 changes: 2 additions & 0 deletions docs/docs/order/purchase_order.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ Refer to the source code for the Purchase Order status codes:
show_source: True
members: []

Purchase Order Status supports [custom states](../concepts/custom_states.md).

### Purchase Order Currency

The currency code can be specified for an individual purchase order. If not specified, the default currency specified against the [supplier](./company.md#suppliers) will be used.
Expand Down
2 changes: 2 additions & 0 deletions docs/docs/order/return_order.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ Refer to the source code for the Return Order status codes:
show_source: True
members: []

Return Order Status supports [custom states](../concepts/custom_states.md).

## Create a Return Order

From the Return Order index, click on <span class='badge inventree add'><span class='fas fa-plus-circle'></span> New Return Order</span> which opens the "Create Return Order" form.
Expand Down
2 changes: 2 additions & 0 deletions docs/docs/order/sales_order.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Refer to the source code for the Sales Order status codes:
show_source: True
members: []

Sales Order Status supports [custom states](../concepts/custom_states.md).

### Sales Order Currency

The currency code can be specified for an individual sales order. If not specified, the default currency specified against the [customer](./company.md#customers) will be used.
Expand Down
4 changes: 3 additions & 1 deletion docs/docs/stock/status.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Certain stock item status codes will restrict the availability of the stock item

Below is the list of available stock status codes and their meaning:

| Status | Description | Available |
| Status | Description | Available |
| ----------- | ----------- | --- |
| <span class='badge inventree success'>OK</span> | Stock item is healthy, nothing wrong to report | <span class='badge inventree success'>Yes</span> |
| <span class='badge inventree warning'>Attention needed</span> | Stock item hasn't been checked or tested yet | <span class='badge inventree success'>Yes</span> |
Expand Down Expand Up @@ -38,6 +38,8 @@ Refer to the source code for the Stock status codes:
show_source: True
members: []

Stock Status supports [custom states](../concepts/custom_states.md).

### Default Status Code

The default status code for any newly created Stock Item is <span class='badge inventree success'>OK</span>
Expand Down
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ nav:
- Core Concepts:
- Terminology: concepts/terminology.md
- Physical Units: concepts/units.md
- Custom States: concepts/custom_states.md
- Development:
- Contributing: develop/contributing.md
- Devcontainer: develop/devcontainer.md
Expand Down
6 changes: 5 additions & 1 deletion src/backend/InvenTree/InvenTree/api_version.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
"""InvenTree API version information."""

# InvenTree API version
INVENTREE_API_VERSION = 245
INVENTREE_API_VERSION = 246

"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""


INVENTREE_API_TEXT = """
v246 - 2024-08-21 : https://github.com/inventree/InvenTree/pull/7862
- Adds custom status fields to various serializers
- Adds endpoints to admin custom status fields
v245 - 2024-08-21 : https://github.com/inventree/InvenTree/pull/7520
- Documented pagination fields (no functional changes)
Expand Down
9 changes: 6 additions & 3 deletions src/backend/InvenTree/InvenTree/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"""Provides extra global data to all templates."""

import InvenTree.email
import InvenTree.ready
import InvenTree.status
from generic.states import StatusCode
from InvenTree.helpers import inheritors
from generic.states.custom import get_custom_classes
from users.models import RuleSet, check_user_role


Expand Down Expand Up @@ -53,7 +53,10 @@ def status_codes(request):
return {}

request._inventree_status_codes = True
return {cls.__name__: cls.template_context() for cls in inheritors(StatusCode)}
get_custom = InvenTree.ready.isRebuildingData() is False
return {
cls.__name__: cls.template_context() for cls in get_custom_classes(get_custom)
}


def user_roles(request):
Expand Down
14 changes: 11 additions & 3 deletions src/backend/InvenTree/InvenTree/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -953,8 +953,15 @@ def get_target(self, obj):
Inheritors_T = TypeVar('Inheritors_T')


def inheritors(cls: type[Inheritors_T]) -> set[type[Inheritors_T]]:
"""Return all classes that are subclasses from the supplied cls."""
def inheritors(
cls: type[Inheritors_T], subclasses: bool = True
) -> set[type[Inheritors_T]]:
"""Return all classes that are subclasses from the supplied cls.
Args:
cls: The class to search for subclasses
subclasses: Include subclasses of subclasses (default = True)
"""
subcls = set()
work = [cls]

Expand All @@ -963,7 +970,8 @@ def inheritors(cls: type[Inheritors_T]) -> set[type[Inheritors_T]]:
for child in parent.__subclasses__():
if child not in subcls:
subcls.add(child)
work.append(child)
if subclasses:
work.append(child)
return subcls


Expand Down
10 changes: 9 additions & 1 deletion src/backend/InvenTree/InvenTree/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ def get_field_info(self, field):
field_info['type'] = 'related field'
field_info['model'] = model._meta.model_name

# Special case for 'user' model
# Special case for special models
if field_info['model'] == 'user':
field_info['api_url'] = '/api/user/'
elif field_info['model'] == 'contenttype':
Expand All @@ -381,6 +381,14 @@ def get_field_info(self, field):
if field_info['type'] == 'dependent field':
field_info['depends_on'] = field.depends_on

# Extend field info if the field has a get_field_info method
if (
not field_info.get('read_only')
and hasattr(field, 'get_field_info')
and callable(field.get_field_info)
):
field_info = field.get_field_info(field, field_info)

return field_info


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Generated by Django 4.2.14 on 2024-08-07 22:40

import django.core.validators
from django.db import migrations

import generic.states.fields
import InvenTree.status_codes


class Migration(migrations.Migration):

dependencies = [
("build", "0051_delete_buildorderattachment"),
]

operations = [
migrations.AddField(
model_name="build",
name="status_custom_key",
field=generic.states.fields.ExtraInvenTreeCustomStatusModelField(
blank=True,
default=None,
help_text="Additional status information for this item",
null=True,
verbose_name="Custom status key",
),
),
migrations.AlterField(
model_name="build",
name="status",
field=generic.states.fields.InvenTreeCustomStatusModelField(
choices=InvenTree.status_codes.BuildStatus.items(),
default=10,
help_text="Build status code",
validators=[django.core.validators.MinValueValidator(0)],
verbose_name="Build Status",
),
),
]
3 changes: 2 additions & 1 deletion src/backend/InvenTree/build/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import report.mixins
import stock.models
import users.models
import generic.states


logger = logging.getLogger('inventree')
Expand Down Expand Up @@ -315,7 +316,7 @@ def get_absolute_url(self):
help_text=_('Number of stock items which have been completed')
)

status = models.PositiveIntegerField(
status = generic.states.fields.InvenTreeCustomStatusModelField(
verbose_name=_('Build Status'),
default=BuildStatus.PENDING.value,
choices=BuildStatus.items(),
Expand Down
55 changes: 32 additions & 23 deletions src/backend/InvenTree/build/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,53 @@

from decimal import Decimal

from django.db import transaction
from django.core.exceptions import ValidationError as DjangoValidationError
from django.utils.translation import gettext_lazy as _

from django.db import models
from django.db.models import ExpressionWrapper, F, FloatField
from django.db.models import Case, Sum, When, Value
from django.db.models import BooleanField, Q
from django.db import models, transaction
from django.db.models import (
BooleanField,
Case,
ExpressionWrapper,
F,
FloatField,
Q,
Sum,
Value,
When,
)
from django.db.models.functions import Coalesce
from django.utils.translation import gettext_lazy as _

from rest_framework import serializers
from rest_framework.serializers import ValidationError

from InvenTree.serializers import InvenTreeModelSerializer, UserSerializer

import InvenTree.helpers
import InvenTree.tasks
from InvenTree.serializers import InvenTreeDecimalField, NotesFieldMixin
from stock.status_codes import StockStatus

from stock.generators import generate_batch_code
from stock.models import StockItem, StockLocation
from stock.serializers import StockItemSerializerBrief, LocationBriefSerializer

import build.tasks
import common.models
from common.serializers import ProjectCodeSerializer
from common.settings import get_global_setting
from importer.mixins import DataImportExportSerializerMixin
import company.serializers
import InvenTree.helpers
import InvenTree.tasks
import part.filters
import part.serializers as part_serializers
from common.serializers import ProjectCodeSerializer
from common.settings import get_global_setting
from generic.states.fields import InvenTreeCustomStatusSerializerMixin
from importer.mixins import DataImportExportSerializerMixin
from InvenTree.serializers import (
InvenTreeDecimalField,
InvenTreeModelSerializer,
NotesFieldMixin,
UserSerializer,
)
from stock.generators import generate_batch_code
from stock.models import StockItem, StockLocation
from stock.serializers import LocationBriefSerializer, StockItemSerializerBrief
from stock.status_codes import StockStatus
from users.serializers import OwnerSerializer

from .models import Build, BuildLine, BuildItem
from .models import Build, BuildItem, BuildLine
from .status_codes import BuildStatus


class BuildSerializer(NotesFieldMixin, DataImportExportSerializerMixin, InvenTreeModelSerializer):
class BuildSerializer(NotesFieldMixin, DataImportExportSerializerMixin, InvenTreeCustomStatusSerializerMixin, InvenTreeModelSerializer):
"""Serializes a Build object."""

class Meta:
Expand Down Expand Up @@ -69,6 +77,7 @@ class Meta:
'quantity',
'status',
'status_text',
'status_custom_key',
'target_date',
'take_from',
'notes',
Expand Down
12 changes: 6 additions & 6 deletions src/backend/InvenTree/build/status_codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@

from django.utils.translation import gettext_lazy as _

from generic.states import StatusCode
from generic.states import ColorEnum, StatusCode


class BuildStatus(StatusCode):
"""Build status codes."""

PENDING = 10, _('Pending'), 'secondary' # Build is pending / active
PRODUCTION = 20, _('Production'), 'primary' # Build is in production
ON_HOLD = 25, _('On Hold'), 'warning' # Build is on hold
CANCELLED = 30, _('Cancelled'), 'danger' # Build was cancelled
COMPLETE = 40, _('Complete'), 'success' # Build is complete
PENDING = 10, _('Pending'), ColorEnum.secondary # Build is pending / active
PRODUCTION = 20, _('Production'), ColorEnum.primary # Build is in production
ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Build is on hold
CANCELLED = 30, _('Cancelled'), ColorEnum.danger # Build was cancelled
COMPLETE = 40, _('Complete'), ColorEnum.success # Build is complete


class BuildStatusGroups:
Expand Down
4 changes: 2 additions & 2 deletions src/backend/InvenTree/build/templates/build/build_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@
<td><span class='fas fa-info'></span></td>
<td>{% trans "Status" %}</td>
<td>
{% status_label 'build' build.status %}
{% display_status_label 'build' build.status_custom_key build.status %}
</td>
</tr>
{% if build.target_date %}
Expand Down Expand Up @@ -225,7 +225,7 @@

{% block page_data %}
<h3>
{% status_label 'build' build.status large=True %}
{% display_status_label 'build' build.status_custom_key build.status large=True %}
{% if build.is_overdue %}
<span class='badge rounded-pill bg-danger'>{% trans "Overdue" %}</span>
{% endif %}
Expand Down
2 changes: 1 addition & 1 deletion src/backend/InvenTree/build/templates/build/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ <h4>{% trans "Build Details" %}</h4>
<tr>
<td><span class='fas fa-info'></span></td>
<td>{% trans "Status" %}</td>
<td>{% status_label 'build' build.status %}</td>
<td>{% display_status_label 'build' build.status_custom_key build.status %}</td>
</tr>
<tr>
<td><span class='fas fa-check-circle'></span></td>
Expand Down
Loading

0 comments on commit a8951d9

Please sign in to comment.