Auto-extract StatusCode values for docs (#12686)

* Auto-extract StatusCode values for docs

* Extract user roles from code

* Fix links

* Remove extraneous source code in docs
This commit is contained in:
Oliver
2026-08-23 18:48:05 +10:00
committed by GitHub
parent f063a6c67f
commit bc98e4bab6
20 changed files with 486 additions and 238 deletions
+6
View File
@@ -39,6 +39,12 @@ Some models allow for mapping based on other "natural key" fields (e.g. the `ref
Importing data is a multi-step process, which is managed via an *import session*. An import session is created when the user initiates a data import, and is used to track the progress of the data import process. Importing data is a multi-step process, which is managed via an *import session*. An import session is created when the user initiates a data import, and is used to track the progress of the data import process.
### Import Session Status
Each import session has a specific status code, indicating where it is in the import process:
{{ statuscodes("DataImportStatusCode") }}
### Import Session List ### Import Session List
The import session is managed by the InvenTree server, and all import session data is stored on the server. As the import process can be time-consuming, the user can navigate away from the import page and return later to check on the progress of the import. The import session is managed by the InvenTree server, and all import session data is stored on the server. As the import process can be time-consuming, the user can navigate away from the import page and return later to check on the progress of the import.
+62 -1
View File
@@ -260,14 +260,75 @@ def on_config(config, *args, **kwargs):
return config return config
def check_status_codes_documented(gen_base):
"""Check that every 'StatusCode' class is documented somewhere in the docs.
A class counts as documented if the `statuscodes()` macro has been called
for it from at least one markdown page (recorded in 'observed_status_codes.json').
"""
expected_status_codes_file = gen_base.joinpath('inventree_status_codes.json')
observed_status_codes_file = gen_base.joinpath('observed_status_codes.json')
with open(observed_status_codes_file, encoding='utf-8') as f:
observed_status_codes = json.loads(f.read())
with open(expected_status_codes_file, encoding='utf-8') as f:
expected_status_codes = json.loads(f.read())
missing = [
name for name in expected_status_codes if name not in observed_status_codes
]
if missing:
raise NotImplementedError(
'Missing Status Codes:\n'
+ f'There are {len(missing)} status code classes not documented via the `statuscodes()` macro:\n- '
+ '\n- '.join(missing)
)
def check_status_code_values_documented(gen_base):
"""Check that every value of every 'StatusCode' class has a description.
Descriptions are sourced from the class docstring's `Attributes:` block (see
`export_status_codes.py` / e.g. `build.status_codes.BuildStatus`) - a status
value with no matching `Attributes:` entry exports with an empty description,
which this check catches.
"""
expected_status_codes_file = gen_base.joinpath('inventree_status_codes.json')
with open(expected_status_codes_file, encoding='utf-8') as f:
expected_status_codes = json.loads(f.read())
missing = [
f'{class_name}.{value["name"]}'
for class_name, info in expected_status_codes.items()
for value in info['values']
if not value['description']
]
if missing:
raise NotImplementedError(
'Missing Status Code Descriptions:\n'
+ f'There are {len(missing)} status code values with no description in their '
+ "class docstring's `Attributes:` block:\n- "
+ '\n- '.join(missing)
)
def on_post_build(*args, **kwargs): def on_post_build(*args, **kwargs):
"""Run after the build is complete. """Run after the build is complete.
Here we check that all global settings and user settings are documented. Here we check that all global settings and user settings are documented,
that every status code class is documented (via the `statuscodes` macro),
and that every individual status code value has a description.
""" """
here = Path(__file__).parent here = Path(__file__).parent
gen_base = here.parent.joinpath('generated') gen_base = here.parent.joinpath('generated')
check_status_codes_documented(gen_base)
check_status_code_values_documented(gen_base)
expected_settings_file = gen_base.joinpath('inventree_settings.json') expected_settings_file = gen_base.joinpath('inventree_settings.json')
observed_settings_file = gen_base.joinpath('observed_settings.json') observed_settings_file = gen_base.joinpath('observed_settings.json')
+1 -19
View File
@@ -71,25 +71,7 @@ Read more about build outputs [here](./output.md).
Each *Build Order* has an associated *Status* flag, which indicates the state of the build: Each *Build Order* has an associated *Status* flag, which indicates the state of the build:
| Status | Description | {{ statuscodes("BuildStatus") }}
| ----------- | ----------- |
| `Pending` | Build order has been created, but is not yet in production |
| `Production` | Build order is currently in production |
| `On Hold` | Build order has been placed on hold, but is still active |
| `Cancelled` | Build order has been cancelled |
| `Completed` | Build order has been completed |
**Source Code**
Refer to the source code for the Build Order status codes:
::: build.status_codes.BuildStatus
options:
show_bases: False
show_root_heading: False
show_root_toc_entry: False
show_source: True
members: []
### Stock Allocations ### Stock Allocations
+2 -6
View File
@@ -10,17 +10,13 @@ Label printer machines can directly print labels for various items in InvenTree.
To implement a custom label printer driver, you need to write a plugin which implements the [MachineDriverMixin](../mixins/machine.md) and returns a list of label printer drivers in the `get_machine_drivers` method. To implement a custom label printer driver, you need to write a plugin which implements the [MachineDriverMixin](../mixins/machine.md) and returns a list of label printer drivers in the `get_machine_drivers` method.
Take a look at the most basic required code for a driver in this [example](./overview.md#example-driver). Next either implement the [`print_label`](#machine.machine_types.LabelPrinterBaseDriver.print_label) or [`print_labels`](#machine.machine_types.LabelPrinterBaseDriver.print_labels) function. Take a look at the most basic required code for a driver in this [example](./overview.md#example-driver). Next either implement the [`print_label`](#labelprintingdriver-api) or [`print_labels`](#labelprintingdriver-api) function.
### Label Printer Status ### Label Printer Status
There are a couple of predefined status codes for label printers. By default the `UNKNOWN` status code is set for each machine, but they can be changed at any time by the driver. For more info about status code see [Machine status codes](./overview.md#machine-status). There are a couple of predefined status codes for label printers. By default the `UNKNOWN` status code is set for each machine, but they can be changed at any time by the driver. For more info about status code see [Machine status codes](./overview.md#machine-status).
::: machine.machine_types.label_printer.LabelPrinterStatus {{ statuscodes("LabelPrinterStatus") }}
options:
heading_level: 4
show_bases: false
show_docstring_description: false
### LabelPrintingDriver API ### LabelPrintingDriver API
+1 -21
View File
@@ -30,27 +30,7 @@ The following view modes are available:
Each Purchase Order has a specific status code which indicates the current state of the order: Each Purchase Order has a specific status code which indicates the current state of the order:
| Status | Description | {{ statuscodes("PurchaseOrderStatus") }}
| --- | --- |
| Pending | The purchase order has been created, but has not been submitted to the supplier |
| In Progress | The purchase order has been issued to the supplier, and is in progress |
| On Hold | The purchase order has been placed on hold, but is still active |
| Complete | The purchase order has been completed, and is now closed |
| Cancelled | The purchase order was cancelled, and is now closed |
| Lost | The purchase order was lost, and is now closed |
| Returned | The purchase order was returned, and is now closed |
**Source Code**
Refer to the source code for the Purchase Order status codes:
::: order.status_codes.PurchaseOrderStatus
options:
show_bases: False
show_root_heading: False
show_root_toc_entry: False
show_source: True
members: []
Purchase Order Status supports [custom states](../concepts/custom_states.md). Purchase Order Status supports [custom states](../concepts/custom_states.md).
+2 -27
View File
@@ -55,25 +55,7 @@ Various filters are available to configure which orders are displayed, and how t
Each Return Order has a specific status code, as follows: Each Return Order has a specific status code, as follows:
| Status | Description | {{ statuscodes("ReturnOrderStatus") }}
| --- | --- |
| Pending | The return order has been created, but not sent to the customer |
| In Progress | The return order has been issued to the customer |
| On Hold | The return order has been placed on hold, but is still active |
| Complete | The return order was marked as complete, and is now closed |
| Cancelled | The return order was cancelled, and is now closed |
**Source Code**
Refer to the source code for the Return Order status codes:
::: order.status_codes.ReturnOrderStatus
options:
show_bases: False
show_root_heading: False
show_root_toc_entry: False
show_source: True
members: []
Return Order Status supports [custom states](../concepts/custom_states.md). Return Order Status supports [custom states](../concepts/custom_states.md).
@@ -126,14 +108,7 @@ Each line item tracks a *Cost* (the cost associated with the return, repair, or
Each line item has an *Outcome*, which records the disposition decided for the returned item: Each line item has an *Outcome*, which records the disposition decided for the returned item:
| Outcome | Description | {{ statuscodes("ReturnOrderLineStatus") }}
| --- | --- |
| Pending | No outcome has been decided yet (default value for a new line item) |
| Return | The item is to be returned to the customer, with no further action |
| Repair | The item is to be repaired, and returned to the customer |
| Replace | The item is to be replaced with a new item |
| Refund | The item cannot be repaired, and a refund is to be issued |
| Reject | The return is rejected |
The *Outcome* is not available when a line item is first created - it can only be set afterwards, by editing the line item. Selecting an outcome is a manual, record-keeping step only: InvenTree does not automatically create a replacement order, issue a refund, or link to a [repair](../manufacturing/index.md) process based on the selected outcome. Any follow-up action (raising a new [Sales Order](./sales_order.md) for a replacement, processing a refund, or tracking a repair) must currently be actioned separately. The *Outcome* is not available when a line item is first created - it can only be set afterwards, by editing the line item. Selecting an outcome is a manual, record-keeping step only: InvenTree does not automatically create a replacement order, issue a refund, or link to a [repair](../manufacturing/index.md) process based on the selected outcome. Any follow-up action (raising a new [Sales Order](./sales_order.md) for a replacement, processing a refund, or tracking a repair) must currently be actioned separately.
+1 -22
View File
@@ -31,28 +31,7 @@ The following view modes are available:
Each Sales Order has a specific status code, which represents the state of the order: Each Sales Order has a specific status code, which represents the state of the order:
| Status | Description | {{ statuscodes("SalesOrderStatus") }}
| --- | --- |
| Pending | The sales order has been created, but has not been finalized or submitted |
| In Progress | The sales order has been issued, and is in progress |
| On Hold | The sales order has been placed on hold, but is still active |
| Shipped | The sales order has been shipped, but is not yet complete |
| Complete | The sales order is fully completed, and is now closed |
| Cancelled | The sales order was cancelled, and is now closed |
| Lost | The sales order was lost, and is now closed |
| Returned | The sales order was returned, and is now closed |
**Source Code**
Refer to the source code for the Sales Order status codes:
::: order.status_codes.SalesOrderStatus
options:
show_bases: False
show_root_heading: False
show_root_toc_entry: False
show_source: True
members: []
Sales Order Status supports [custom states](../concepts/custom_states.md). Sales Order Status supports [custom states](../concepts/custom_states.md).
+1 -12
View File
@@ -25,18 +25,7 @@ A *role* is a set of distinct permissions linked to a given subset of InvenTree
InvenTree functionality is split into a number of distinct roles. A group will have a set of permissions assigned to each of the following roles: InvenTree functionality is split into a number of distinct roles. A group will have a set of permissions assigned to each of the following roles:
| Role | Description | {{ roles() }}
| ---- | ----------- |
| **Admin** | The *admin* role is related to assigning user permissions. |
| **BOM** | The *bom* role is related to accessing Bill of Materials data |
| **Build** | The *build* role is related to accessing manufacturing / Build Order |
| **Part** | The *part* role is related to accessing Part data |
| **Part Category** | The *part category* role is related to accessing Part Category data |
| **Purchase Order** | The *purchase* role is related to accessing Purchase Order data |
| **Return Order** | The *return* role is related to accessing Return Order data |
| **Sales Order** | The *sales* role is related to accessing Sales Order data |
| **Stock Item** | The *stock item* role is related to accessing Stock Item data |
| **Stock Location** | The *stock location* role is related to accessing Stock Location data |
{{ image("admin/roles.png", "Roles") }} {{ image("admin/roles.png", "Roles") }}
+3 -21
View File
@@ -10,32 +10,14 @@ 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: Below is the list of available stock status codes and their meaning:
| Status | Description | Available | {{ statuscodes("StockStatus") }}
| ----------- | ----------- | --- |
| <span class='badge inventree success'>OK</span> | Stock item is healthy, nothing wrong to report | <span class='badge inventree success'>Yes</span> | Of these, only *OK*, *Attention needed*, *Damaged* and *Returned* count as "available" stock - the remainder are excluded from availability calculations.
| <span class='badge inventree warning'>Attention needed</span> | Stock item hasn't been checked or tested yet | <span class='badge inventree success'>Yes</span> |
| <span class='badge inventree warning'>Damaged</span> | Stock item is not functional in its present state | <span class='badge inventree success'>Yes</span> |
| <span class='badge inventree danger'>Destroyed</span> | Stock item has been destroyed | <span class='badge inventree danger'>No</span> |
| <span class='badge inventree'>Lost</span> | Stock item has been lost | <span class='badge inventree danger'>No</span> |
| <span class='badge inventree danger'>Rejected</span> | Stock item did not pass the quality control standards | <span class='badge inventree danger'>No</span> |
| <span class='badge inventree info'>Quarantined</span> | Stock item has been intentionally isolated and it unavailable | <span class='badge inventree danger'>No</span> |
The *status* of a given stock item is displayed on the stock item detail page: The *status* of a given stock item is displayed on the stock item detail page:
{{ image("stock/stock_status_label.png", title="Stock status label") }} {{ image("stock/stock_status_label.png", title="Stock status label") }}
**Source Code**
Refer to the source code for the Stock status codes:
::: stock.status_codes.StockStatus
options:
show_bases: False
show_root_heading: False
show_root_toc_entry: False
show_source: True
members: []
### Custom Status Codes ### Custom Status Codes
Stock Status supports [custom states](../concepts/custom_states.md). Stock Status supports [custom states](../concepts/custom_states.md).
+6
View File
@@ -17,6 +17,12 @@ Some examples of events that may trigger stock tracking entries include:
- Allocation of stock items to orders (e.g. shipping items against sales orders) - Allocation of stock items to orders (e.g. shipping items against sales orders)
- Consumption of stock items during build processes (e.g. using items to complete a build order) - Consumption of stock items during build processes (e.g. using items to complete a build order)
### Tracking Entry Types
Each stock tracking entry records a specific *type*, indicating which event triggered it:
{{ statuscodes("StockHistoryCode") }}
## Viewing Stock Tracking History ## Viewing Stock Tracking History
There are multiple ways to view the stock tracking history for a particular stock item or part via the user interface. There are multiple ways to view the stock tracking history for a particular stock item or part via the user interface.
+1 -19
View File
@@ -31,25 +31,7 @@ The following view modes are available:
Each Transfer Order has a specific status code, which represents the state of the order: Each Transfer Order has a specific status code, which represents the state of the order:
| Status | Description | {{ statuscodes("TransferOrderStatus") }}
| --- | --- |
| Pending | The transfer order has been created, but has not been finalized or submitted |
| Issued | The transfer order has been issued, and is in progress |
| On Hold | The transfer order has been placed on hold, but is still active |
| Complete | The transfer order is fully completed, and is now closed |
| Cancelled | The transfer order was cancelled, and is now closed |
**Source Code**
Refer to the source code for the Transfer Order status codes:
::: order.status_codes.TransferOrderStatus
options:
show_bases: False
show_root_heading: False
show_root_toc_entry: False
show_source: True
members: []
Transfer Order Status supports [custom states](../concepts/custom_states.md). Transfer Order Status supports [custom states](../concepts/custom_states.md).
+66
View File
@@ -40,6 +40,8 @@ global USER_SETTINGS
global TAGS global TAGS
global FILTERS global FILTERS
global REPORT_CONTEXT global REPORT_CONTEXT
global STATUS_CODES
global ROLES
# Read in the InvenTree settings file # Read in the InvenTree settings file
here = Path(__file__).parent here = Path(__file__).parent
@@ -60,6 +62,13 @@ with open(observed_settings_file, 'w', encoding='utf-8') as f:
# This is used to track which settings we have observed during the build process # This is used to track which settings we have observed during the build process
f.write(json.dumps(data, indent=4)) f.write(json.dumps(data, indent=4))
# File where we will *store* information on the status code classes we have observed
observed_status_codes_file = gen_base.joinpath('observed_status_codes.json')
# Overwrite the observed status codes file
with open(observed_status_codes_file, 'w', encoding='utf-8') as f:
f.write(json.dumps({}, indent=4))
with open(settings_file, encoding='utf-8') as sf: with open(settings_file, encoding='utf-8') as sf:
settings = json.load(sf) settings = json.load(sf)
@@ -73,9 +82,15 @@ with open(gen_base.joinpath('inventree_tags.yml'), encoding='utf-8') as f:
# Filters # Filters
with open(gen_base.joinpath('inventree_filters.yml'), encoding='utf-8') as f: with open(gen_base.joinpath('inventree_filters.yml'), encoding='utf-8') as f:
FILTERS = yaml.load(f, yaml.BaseLoader) FILTERS = yaml.load(f, yaml.BaseLoader)
# Status codes
with open(gen_base.joinpath('inventree_status_codes.json'), encoding='utf-8') as f:
STATUS_CODES = json.load(f)
# Report context # Report context
with open(gen_base.joinpath('inventree_report_context.json'), encoding='utf-8') as f: with open(gen_base.joinpath('inventree_report_context.json'), encoding='utf-8') as f:
REPORT_CONTEXT = json.load(f) REPORT_CONTEXT = json.load(f)
# User permission roles
with open(gen_base.joinpath('inventree_roles.json'), encoding='utf-8') as f:
ROLES = json.load(f)
def get_repo_url(raw=False): def get_repo_url(raw=False):
@@ -297,6 +312,38 @@ def define_env(env):
return includefile(fn, f'Template: {base}', fmt='html') return includefile(fn, f'Template: {base}', fmt='html')
@env.macro
def statuscodes(class_name: str):
"""Render a markdown table of status codes for the given StatusCode class.
Arguments:
class_name: The name of the `StatusCode` subclass to render (e.g. 'BuildStatus')
The table is built directly from `docs/generated/inventree_status_codes.json`
(produced by the `export_status_codes` management command), so it can never
drift out of sync with the status codes actually defined in the source code.
"""
global STATUS_CODES
status_class = STATUS_CODES[class_name]
# Record that this status code class has been rendered somewhere in the docs
with open(observed_status_codes_file, encoding='utf-8') as f:
data = json.load(f)
data[class_name] = True
with open(observed_status_codes_file, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4)
ret_data = '| Status | Value | Description |\n| --- | --- | --- |\n'
for item in status_class['values']:
description = item['description'] or item['label']
ret_data += f'| {item["label"]} | {item["key"]} | {description} |\n'
return ret_data
def observe_setting(key: str, group: str): def observe_setting(key: str, group: str):
"""Record that a particular setting has been observed. """Record that a particular setting has been observed.
@@ -429,6 +476,25 @@ def define_env(env):
return ret_data return ret_data
@env.macro
def roles():
"""Render a markdown table of the available user permission roles.
The table is built directly from `docs/generated/inventree_roles.json`
(produced by the `export_roles` management command, sourced from
`users.ruleset.RULESET_CHOICES`), so it can never drift out of sync with
the roles actually defined in the source code.
"""
global ROLES
ret_data = '| Role | Description |\n| --- | --- |\n'
for role in ROLES:
description = role['description'] or role['label']
ret_data += f'| **{role["label"]}** | {description} |\n'
return ret_data
@env.macro @env.macro
def report_context(type_: Literal['models', 'base'], model: str): def report_context(type_: Literal['models', 'base'], model: str):
"""Extract information on a particular report context.""" """Extract information on a particular report context."""
@@ -0,0 +1,58 @@
"""Custom management command to export all user permission roles.
This is used to generate a JSON file which contains all of the roles (rulesets)
available in InvenTree, so that they can be introspected by the InvenTree
documentation system. This allows the roles table to be documented without
having to manually duplicate the information (which otherwise silently drifts
out of sync with the source code - e.g. a newly added ruleset going undocumented).
"""
import json
from django.core.management.base import BaseCommand
from users.ruleset import RULESET_CHOICES, RuleSetEnum
from .export_report_context import parse_docstring
class Command(BaseCommand):
"""Extract user permission role information, and export to a JSON file."""
def add_arguments(self, parser):
"""Add custom arguments for this command."""
parser.add_argument(
'filename', type=str, help='Output filename for role definitions'
)
def handle(self, *args, **kwargs):
"""Export role information to a JSON file."""
roles = discover_roles()
filename = kwargs.get('filename', 'inventree_roles.json')
with open(filename, 'w', encoding='utf-8') as f:
json.dump(roles, f, indent=4)
print(f"Exported InvenTree role definitions to '{filename}'")
def discover_roles():
"""Discover all available user permission roles (rulesets).
Returns a list of roles, in the order they are declared in `RULESET_CHOICES`.
Each role's description is sourced from `RuleSetEnum`'s docstring `Attributes:`
block, rather than being manually curated here - so a role's description can
never drift out of sync with its source.
"""
attributes = parse_docstring(RuleSetEnum.__doc__ or '').get('Attributes', {})
return [
{
'name': key.name,
'key': str(key.value),
'label': str(label),
'description': attributes.get(key.name, ''),
}
for key, label in RULESET_CHOICES
]
@@ -0,0 +1,84 @@
"""Custom management command to export all status codes.
This is used to generate a JSON file which contains all of the 'StatusCode'
classes available in InvenTree, so that they can be introspected by the
InvenTree documentation system. This allows status code tables to be
documented without having to manually duplicate the information (which
otherwise silently drifts out of sync with the source code).
"""
import json
from django.core.management.base import BaseCommand
from generic.states import StatusCode
from InvenTree.helpers import inheritors
from .export_report_context import parse_docstring
class Command(BaseCommand):
"""Extract status code information, and export to a JSON file."""
def add_arguments(self, parser):
"""Add custom arguments for this command."""
parser.add_argument(
'filename', type=str, help='Output filename for status code definitions'
)
def handle(self, *args, **kwargs):
"""Export status code information to a JSON file."""
status_codes = discover_status_codes()
filename = kwargs.get('filename', 'inventree_status_codes.json')
with open(filename, 'w', encoding='utf-8') as f:
json.dump(status_codes, f, indent=4)
print(f"Exported InvenTree status code definitions to '{filename}'")
def discover_status_codes():
"""Discover all available status code classes.
Returns a dict, keyed by class name, of every concrete `StatusCode`
subclass (i.e. one which defines at least one status value - this
excludes abstract base classes such as `MachineStatus`, which is
subclassed per machine driver/plugin rather than used directly).
Each entry contains the class' module path and 'tag', plus a list of its
status values. The description of each value is sourced from the
class docstring's Google-style `Attributes:` block (see e.g.
`build.status_codes.BuildStatus`), rather than being manually curated
here - so a status code's description can never drift out of sync with
its source.
"""
data = {}
for cls in inheritors(StatusCode):
# custom=False: this is a definition of the *built-in* status codes as
# they exist in source - user/plugin-defined custom states are runtime data
values = cls.dict(custom=False)
if not values:
# Abstract base class with no concrete status values (e.g. MachineStatus)
continue
attributes = parse_docstring(cls.__doc__ or '').get('Attributes', {})
data[cls.__name__] = {
'module': cls.__module__,
'tag': cls.tag(),
'values': [
{
'name': item['name'],
'key': item['key'],
'label': str(item['label']),
'color': item['color'],
'description': attributes.get(item['name'], ''),
}
for item in values.values()
],
}
return dict(sorted(data.items()))
+14 -6
View File
@@ -6,13 +6,21 @@ from generic.states import ColorEnum, StatusCode
class BuildStatus(StatusCode): class BuildStatus(StatusCode):
"""Build status codes.""" """Build status codes.
PENDING = 10, _('Pending'), ColorEnum.secondary # Build is pending / active Attributes:
PRODUCTION = 20, _('Production'), ColorEnum.primary # Build is in production PENDING: Build is pending / active
ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Build is on hold PRODUCTION: Build is in production
CANCELLED = 30, _('Cancelled'), ColorEnum.danger # Build was cancelled ON_HOLD: Build is on hold
COMPLETE = 40, _('Complete'), ColorEnum.success # Build is complete CANCELLED: Build was cancelled
COMPLETE: Build is complete
"""
PENDING = 10, _('Pending'), ColorEnum.secondary
PRODUCTION = 20, _('Production'), ColorEnum.primary
ON_HOLD = 25, _('On Hold'), ColorEnum.warning
CANCELLED = 30, _('Cancelled'), ColorEnum.danger
COMPLETE = 40, _('Complete'), ColorEnum.success
class BuildStatusGroups: class BuildStatusGroups:
+14 -18
View File
@@ -6,22 +6,18 @@ from generic.states import ColorEnum, StatusCode
class DataImportStatusCode(StatusCode): class DataImportStatusCode(StatusCode):
"""Defines a set of status codes for a DataImportSession.""" """Defines a set of status codes for a DataImportSession.
INITIAL = ( Attributes:
0, INITIAL: Import session has been created
_('Initializing'), MAPPING: Import fields are being mapped
ColorEnum.secondary, IMPORTING: Data is being imported
) # Import session has been created PROCESSING: Data is being processed by the user
MAPPING = ( COMPLETE: Import has been completed
10, """
_('Mapping Columns'),
ColorEnum.primary, INITIAL = 0, _('Initializing'), ColorEnum.secondary
) # Import fields are being mapped MAPPING = 10, _('Mapping Columns'), ColorEnum.primary
IMPORTING = 20, _('Importing Data'), ColorEnum.primary # Data is being imported IMPORTING = 20, _('Importing Data'), ColorEnum.primary
PROCESSING = ( PROCESSING = 30, _('Processing Data'), ColorEnum.primary
30, COMPLETE = 40, _('Complete'), ColorEnum.success
_('Processing Data'),
ColorEnum.primary,
) # Data is being processed by the user
COMPLETE = 40, _('Complete'), ColorEnum.success # Import has been completed
+71 -46
View File
@@ -6,16 +6,25 @@ from generic.states import ColorEnum, StatusCode
class PurchaseOrderStatus(StatusCode): class PurchaseOrderStatus(StatusCode):
"""Defines a set of status codes for a PurchaseOrder.""" """Defines a set of status codes for a PurchaseOrder.
# Order status codes Attributes:
PENDING = 10, _('Pending'), ColorEnum.secondary # Order is pending (not yet placed) PENDING: Order is pending (not yet placed)
PLACED = 20, _('Placed'), ColorEnum.primary # Order has been placed with supplier PLACED: Order has been placed with supplier
ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Order is on hold ON_HOLD: Order is on hold
COMPLETE = 30, _('Complete'), ColorEnum.success # Order has been completed COMPLETE: Order has been completed
CANCELLED = 40, _('Cancelled'), ColorEnum.danger # Order was cancelled CANCELLED: Order was cancelled
LOST = 50, _('Lost'), ColorEnum.warning # Order was lost LOST: Order was lost
RETURNED = 60, _('Returned'), ColorEnum.warning # Order was returned RETURNED: Order was returned
"""
PENDING = 10, _('Pending'), ColorEnum.secondary
PLACED = 20, _('Placed'), ColorEnum.primary
ON_HOLD = 25, _('On Hold'), ColorEnum.warning
COMPLETE = 30, _('Complete'), ColorEnum.success
CANCELLED = 40, _('Cancelled'), ColorEnum.danger
LOST = 50, _('Lost'), ColorEnum.warning
RETURNED = 60, _('Returned'), ColorEnum.warning
class PurchaseOrderStatusGroups: class PurchaseOrderStatusGroups:
@@ -39,20 +48,27 @@ class PurchaseOrderStatusGroups:
class SalesOrderStatus(StatusCode): class SalesOrderStatus(StatusCode):
"""Defines a set of status codes for a SalesOrder.""" """Defines a set of status codes for a SalesOrder.
PENDING = 10, _('Pending'), ColorEnum.secondary # Order is pending Attributes:
IN_PROGRESS = ( PENDING: Order is pending
15, IN_PROGRESS: Order has been issued, and is in progress
_('In Progress'), SHIPPED: Order has been shipped to customer
ColorEnum.primary, ON_HOLD: Order is on hold
) # Order has been issued, and is in progress COMPLETE: Order is complete
SHIPPED = 20, _('Shipped'), ColorEnum.primary # Order has been shipped to customer CANCELLED: Order has been cancelled
ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Order is on hold LOST: Order was lost
COMPLETE = 30, _('Complete'), ColorEnum.success # Order is complete RETURNED: Order was returned
CANCELLED = 40, _('Cancelled'), ColorEnum.danger # Order has been cancelled """
LOST = 50, _('Lost'), ColorEnum.warning # Order was lost
RETURNED = 60, _('Returned'), ColorEnum.warning # Order was returned PENDING = 10, _('Pending'), ColorEnum.secondary
IN_PROGRESS = 15, _('In Progress'), ColorEnum.primary
SHIPPED = 20, _('Shipped'), ColorEnum.primary
ON_HOLD = 25, _('On Hold'), ColorEnum.warning
COMPLETE = 30, _('Complete'), ColorEnum.success
CANCELLED = 40, _('Cancelled'), ColorEnum.danger
LOST = 50, _('Lost'), ColorEnum.warning
RETURNED = 60, _('Returned'), ColorEnum.warning
class SalesOrderStatusGroups: class SalesOrderStatusGroups:
@@ -71,16 +87,19 @@ class SalesOrderStatusGroups:
class ReturnOrderStatus(StatusCode): class ReturnOrderStatus(StatusCode):
"""Defines a set of status codes for a ReturnOrder.""" """Defines a set of status codes for a ReturnOrder.
Attributes:
PENDING: Order is pending, waiting for receipt of items
IN_PROGRESS: Items have been received, and are being inspected
ON_HOLD: Order is on hold
COMPLETE: Order is complete
CANCELLED: Order has been cancelled
"""
# Order is pending, waiting for receipt of items
PENDING = 10, _('Pending'), ColorEnum.secondary PENDING = 10, _('Pending'), ColorEnum.secondary
# Items have been received, and are being inspected
IN_PROGRESS = 20, _('In Progress'), ColorEnum.primary IN_PROGRESS = 20, _('In Progress'), ColorEnum.primary
ON_HOLD = 25, _('On Hold'), ColorEnum.warning ON_HOLD = 25, _('On Hold'), ColorEnum.warning
COMPLETE = 30, _('Complete'), ColorEnum.success COMPLETE = 30, _('Complete'), ColorEnum.success
CANCELLED = 40, _('Cancelled'), ColorEnum.danger CANCELLED = 40, _('Cancelled'), ColorEnum.danger
@@ -98,35 +117,41 @@ class ReturnOrderStatusGroups:
class ReturnOrderLineStatus(StatusCode): class ReturnOrderLineStatus(StatusCode):
"""Defines a set of status codes for a ReturnOrderLineItem.""" """Defines a set of status codes for a ReturnOrderLineItem.
Attributes:
PENDING: No outcome has been decided yet (default value for a new line item)
RETURN: The item is to be returned to the customer, with no further action
REPAIR: The item is to be repaired, and returned to the customer
REPLACE: The item is to be replaced with a new item
REFUND: The item cannot be repaired, and a refund is to be issued
REJECT: The return is rejected
"""
PENDING = 10, _('Pending'), ColorEnum.secondary PENDING = 10, _('Pending'), ColorEnum.secondary
# Item is to be returned to customer, no other action
RETURN = 20, _('Return'), ColorEnum.success RETURN = 20, _('Return'), ColorEnum.success
# Item is to be repaired, and returned to customer
REPAIR = 30, _('Repair'), ColorEnum.primary REPAIR = 30, _('Repair'), ColorEnum.primary
# Item is to be replaced (new item shipped)
REPLACE = 40, _('Replace'), ColorEnum.warning REPLACE = 40, _('Replace'), ColorEnum.warning
# Item is to be refunded (cannot be repaired)
REFUND = 50, _('Refund'), ColorEnum.info REFUND = 50, _('Refund'), ColorEnum.info
# Item is rejected
REJECT = 60, _('Reject'), ColorEnum.danger REJECT = 60, _('Reject'), ColorEnum.danger
class TransferOrderStatus(StatusCode): class TransferOrderStatus(StatusCode):
"""Defines a set of status codes for a TransferOrder.""" """Defines a set of status codes for a TransferOrder.
# Order status codes Attributes:
PENDING = 10, _('Pending'), ColorEnum.secondary # Order is pending (not yet issued) PENDING: Order is pending (not yet issued)
ISSUED = 20, _('Issued'), ColorEnum.primary # Order has been issued ISSUED: Order has been issued
ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Order is on hold ON_HOLD: Order is on hold
COMPLETE = 30, _('Complete'), ColorEnum.success # Order has been completed COMPLETE: Order has been completed
CANCELLED = 40, _('Cancelled'), ColorEnum.danger # Order was cancelled CANCELLED: Order was cancelled
"""
PENDING = 10, _('Pending'), ColorEnum.secondary
ISSUED = 20, _('Issued'), ColorEnum.primary
ON_HOLD = 25, _('On Hold'), ColorEnum.warning
COMPLETE = 30, _('Complete'), ColorEnum.success
CANCELLED = 40, _('Cancelled'), ColorEnum.danger
class TransferOrderStatusGroups: class TransferOrderStatusGroups:
+70 -19
View File
@@ -6,24 +6,27 @@ from generic.states import ColorEnum, StatusCode
class StockStatus(StatusCode): class StockStatus(StatusCode):
"""Status codes for Stock.""" """Status codes for Stock.
OK = 10, _('OK'), ColorEnum.success # Item is OK Attributes:
ATTENTION = 50, _('Attention needed'), ColorEnum.warning # Item requires attention OK: Stock item is healthy, nothing wrong to report
DAMAGED = 55, _('Damaged'), ColorEnum.warning # Item is damaged ATTENTION: Stock item hasn't been checked or tested yet
DESTROYED = 60, _('Destroyed'), ColorEnum.danger # Item is destroyed DAMAGED: Stock item is not functional in its present state
REJECTED = 65, _('Rejected'), ColorEnum.danger # Item is rejected DESTROYED: Stock item has been destroyed
LOST = 70, _('Lost'), ColorEnum.dark # Item has been lost REJECTED: Stock item did not pass the quality control standards
QUARANTINED = ( LOST: Stock item has been lost
75, QUARANTINED: Stock item has been intentionally isolated and is unavailable
_('Quarantined'), RETURNED: Stock item has been returned from a customer
ColorEnum.info, """
) # Item has been quarantined and is unavailable
RETURNED = ( OK = 10, _('OK'), ColorEnum.success
85, ATTENTION = 50, _('Attention needed'), ColorEnum.warning
_('Returned'), DAMAGED = 55, _('Damaged'), ColorEnum.warning
ColorEnum.warning, DESTROYED = 60, _('Destroyed'), ColorEnum.danger
) # Item has been returned from a customer REJECTED = 65, _('Rejected'), ColorEnum.danger
LOST = 70, _('Lost'), ColorEnum.dark
QUARANTINED = 75, _('Quarantined'), ColorEnum.info
RETURNED = 85, _('Returned'), ColorEnum.warning
class StockStatusGroups: class StockStatusGroups:
@@ -39,7 +42,55 @@ class StockStatusGroups:
class StockHistoryCode(StatusCode): class StockHistoryCode(StatusCode):
"""Status codes for StockHistory.""" """Status codes for StockHistory.
Attributes:
LEGACY: Legacy stock tracking entry, created before tracking entry types existed
CREATED: Stock item created
EDITED: Stock item was manually edited
ASSIGNED_SERIAL: A serial number was assigned to the stock item
STOCK_COUNT: Stock was manually counted
STOCK_ADD: Stock was manually added
STOCK_REMOVE: Stock was manually removed
STOCK_SERIALIZED: Stock items were serialized
RETURNED_TO_STOCK: Stock item was returned to stock
STOCK_MOVE: The location of the stock item was changed
STOCK_UPDATE: Stock item was updated
INSTALLED_INTO_ASSEMBLY: Stock item was installed into an assembly
REMOVED_FROM_ASSEMBLY: Stock item was removed from an assembly
INSTALLED_CHILD_ITEM: A component item was installed into this stock item
REMOVED_CHILD_ITEM: A component item was removed from this stock item
SPLIT_FROM_PARENT: Stock item was split from a parent stock item
SPLIT_CHILD_ITEM: A child stock item was split from this stock item
MERGED_STOCK_ITEMS: Multiple stock items were merged into this one
DISASSEMBLED: Stock item was disassembled into its component items
CREATED_FROM_DISASSEMBLY: Stock item was created as a result of disassembly
CONVERTED_TO_VARIANT: Stock item was converted to a variant of its part
BUILD_OUTPUT_CREATED: Stock item was created as a build order output
BUILD_OUTPUT_COMPLETED: Stock item (a build order output) was completed
BUILD_OUTPUT_REJECTED: Stock item (a build order output) was rejected
BUILD_CONSUMED: Stock item was consumed by a build order
SHIPPED_AGAINST_SALES_ORDER: Stock item was shipped against a Sales Order
RECEIVED_AGAINST_PURCHASE_ORDER: Stock item was received against a Purchase Order
RETURNED_AGAINST_RETURN_ORDER: Stock item was returned against a Return Order
SENT_TO_CUSTOMER: Stock item was sent to a customer
RETURNED_FROM_CUSTOMER: Stock item was returned from a customer
"""
LEGACY = 0, _('Legacy stock tracking entry') LEGACY = 0, _('Legacy stock tracking entry')
@@ -55,7 +106,7 @@ class StockHistoryCode(StatusCode):
STOCK_REMOVE = 12, _('Stock manually removed') STOCK_REMOVE = 12, _('Stock manually removed')
STOCK_SERIALIZED = 13, _('Serialized stock items') STOCK_SERIALIZED = 13, _('Serialized stock items')
RETURNED_TO_STOCK = 15, _('Returned to stock') # Stock item returned to stock RETURNED_TO_STOCK = 15, _('Returned to stock')
# Location operations # Location operations
STOCK_MOVE = 20, _('Location changed') STOCK_MOVE = 20, _('Location changed')
+15 -1
View File
@@ -7,7 +7,21 @@ from generic.enums import StringEnum
class RuleSetEnum(StringEnum): class RuleSetEnum(StringEnum):
"""Enumeration of ruleset names.""" """Enumeration of ruleset names.
Attributes:
ADMIN: Assigning user permissions, and other administrative tasks
PART_CATEGORY: Accessing Part Category data
PART: Accessing Part data
BOM: Accessing Bill of Materials data
STOCK_LOCATION: Accessing Stock Location data
STOCK: Accessing Stock Item data
BUILD: Accessing manufacturing / Build Order data
PURCHASE_ORDER: Accessing Purchase Order data
SALES_ORDER: Accessing Sales Order data
RETURN_ORDER: Accessing Return Order data
TRANSFER_ORDER: Accessing Transfer Order data
"""
ADMIN = 'admin' ADMIN = 'admin'
PART_CATEGORY = 'part_category' PART_CATEGORY = 'part_category'
+8
View File
@@ -2037,6 +2037,8 @@ def export_definitions(c, basedir: str = ''):
base_path.joinpath('inventree_tags.yml'), base_path.joinpath('inventree_tags.yml'),
base_path.joinpath('inventree_filters.yml'), base_path.joinpath('inventree_filters.yml'),
base_path.joinpath('inventree_report_context.json'), base_path.joinpath('inventree_report_context.json'),
base_path.joinpath('inventree_status_codes.json'),
base_path.joinpath('inventree_roles.json'),
] ]
info('Exporting definitions...') info('Exporting definitions...')
@@ -2051,6 +2053,12 @@ def export_definitions(c, basedir: str = ''):
check_file_existence(filenames[3], overwrite=True) check_file_existence(filenames[3], overwrite=True)
manage(c, f'export_report_context {filenames[3]}', pty=True) manage(c, f'export_report_context {filenames[3]}', pty=True)
check_file_existence(filenames[4], overwrite=True)
manage(c, f'export_status_codes {filenames[4]}', pty=True)
check_file_existence(filenames[5], overwrite=True)
manage(c, f'export_roles {filenames[5]}', pty=True)
info('Exporting definitions complete') info('Exporting definitions complete')