mirror of
https://github.com/inventree/InvenTree.git
synced 2026-08-30 08:56:41 +00:00
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:
@@ -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.
|
||||
|
||||
### Import Session Status
|
||||
|
||||
Each import session has a specific status code, indicating where it is in the import process:
|
||||
|
||||
{{ statuscodes("DataImportStatusCode") }}
|
||||
|
||||
### 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.
|
||||
|
||||
+62
-1
@@ -260,14 +260,75 @@ def on_config(config, *args, **kwargs):
|
||||
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):
|
||||
"""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
|
||||
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')
|
||||
observed_settings_file = gen_base.joinpath('observed_settings.json')
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
| Status | Description |
|
||||
| ----------- | ----------- |
|
||||
| `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: []
|
||||
{{ statuscodes("BuildStatus") }}
|
||||
|
||||
### Stock Allocations
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
options:
|
||||
heading_level: 4
|
||||
show_bases: false
|
||||
show_docstring_description: false
|
||||
{{ statuscodes("LabelPrinterStatus") }}
|
||||
|
||||
### LabelPrintingDriver API
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
| Status | Description |
|
||||
| --- | --- |
|
||||
| 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: []
|
||||
{{ statuscodes("PurchaseOrderStatus") }}
|
||||
|
||||
Purchase Order Status supports [custom states](../concepts/custom_states.md).
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
| Status | Description |
|
||||
| --- | --- |
|
||||
| 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: []
|
||||
{{ statuscodes("ReturnOrderStatus") }}
|
||||
|
||||
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:
|
||||
|
||||
| Outcome | Description |
|
||||
| --- | --- |
|
||||
| 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 |
|
||||
{{ statuscodes("ReturnOrderLineStatus") }}
|
||||
|
||||
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.
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
| Status | Description |
|
||||
| --- | --- |
|
||||
| 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: []
|
||||
{{ statuscodes("SalesOrderStatus") }}
|
||||
|
||||
Sales Order Status supports [custom states](../concepts/custom_states.md).
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
| Role | Description |
|
||||
| ---- | ----------- |
|
||||
| **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 |
|
||||
{{ roles() }}
|
||||
|
||||
{{ image("admin/roles.png", "Roles") }}
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
| 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> |
|
||||
| <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> |
|
||||
{{ statuscodes("StockStatus") }}
|
||||
|
||||
Of these, only *OK*, *Attention needed*, *Damaged* and *Returned* count as "available" stock - the remainder are excluded from availability calculations.
|
||||
|
||||
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") }}
|
||||
|
||||
**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
|
||||
|
||||
Stock Status supports [custom states](../concepts/custom_states.md).
|
||||
|
||||
@@ -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)
|
||||
- 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
|
||||
|
||||
There are multiple ways to view the stock tracking history for a particular stock item or part via the user interface.
|
||||
|
||||
@@ -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:
|
||||
|
||||
| Status | Description |
|
||||
| --- | --- |
|
||||
| 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: []
|
||||
{{ statuscodes("TransferOrderStatus") }}
|
||||
|
||||
Transfer Order Status supports [custom states](../concepts/custom_states.md).
|
||||
|
||||
|
||||
@@ -40,6 +40,8 @@ global USER_SETTINGS
|
||||
global TAGS
|
||||
global FILTERS
|
||||
global REPORT_CONTEXT
|
||||
global STATUS_CODES
|
||||
global ROLES
|
||||
|
||||
# Read in the InvenTree settings file
|
||||
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
|
||||
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:
|
||||
settings = json.load(sf)
|
||||
|
||||
@@ -73,9 +82,15 @@ with open(gen_base.joinpath('inventree_tags.yml'), encoding='utf-8') as f:
|
||||
# Filters
|
||||
with open(gen_base.joinpath('inventree_filters.yml'), encoding='utf-8') as f:
|
||||
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
|
||||
with open(gen_base.joinpath('inventree_report_context.json'), encoding='utf-8') as 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):
|
||||
@@ -297,6 +312,38 @@ def define_env(env):
|
||||
|
||||
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):
|
||||
"""Record that a particular setting has been observed.
|
||||
|
||||
@@ -429,6 +476,25 @@ def define_env(env):
|
||||
|
||||
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
|
||||
def report_context(type_: Literal['models', 'base'], model: str):
|
||||
"""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()))
|
||||
@@ -6,13 +6,21 @@ from generic.states import ColorEnum, StatusCode
|
||||
|
||||
|
||||
class BuildStatus(StatusCode):
|
||||
"""Build status codes."""
|
||||
"""Build status codes.
|
||||
|
||||
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
|
||||
Attributes:
|
||||
PENDING: Build is pending / active
|
||||
PRODUCTION: Build is in production
|
||||
ON_HOLD: Build is on hold
|
||||
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:
|
||||
|
||||
@@ -6,22 +6,18 @@ from generic.states import ColorEnum, StatusCode
|
||||
|
||||
|
||||
class DataImportStatusCode(StatusCode):
|
||||
"""Defines a set of status codes for a DataImportSession."""
|
||||
"""Defines a set of status codes for a DataImportSession.
|
||||
|
||||
INITIAL = (
|
||||
0,
|
||||
_('Initializing'),
|
||||
ColorEnum.secondary,
|
||||
) # Import session has been created
|
||||
MAPPING = (
|
||||
10,
|
||||
_('Mapping Columns'),
|
||||
ColorEnum.primary,
|
||||
) # Import fields are being mapped
|
||||
IMPORTING = 20, _('Importing Data'), ColorEnum.primary # Data is being imported
|
||||
PROCESSING = (
|
||||
30,
|
||||
_('Processing Data'),
|
||||
ColorEnum.primary,
|
||||
) # Data is being processed by the user
|
||||
COMPLETE = 40, _('Complete'), ColorEnum.success # Import has been completed
|
||||
Attributes:
|
||||
INITIAL: Import session has been created
|
||||
MAPPING: Import fields are being mapped
|
||||
IMPORTING: Data is being imported
|
||||
PROCESSING: Data is being processed by the user
|
||||
COMPLETE: Import has been completed
|
||||
"""
|
||||
|
||||
INITIAL = 0, _('Initializing'), ColorEnum.secondary
|
||||
MAPPING = 10, _('Mapping Columns'), ColorEnum.primary
|
||||
IMPORTING = 20, _('Importing Data'), ColorEnum.primary
|
||||
PROCESSING = 30, _('Processing Data'), ColorEnum.primary
|
||||
COMPLETE = 40, _('Complete'), ColorEnum.success
|
||||
|
||||
@@ -6,16 +6,25 @@ from generic.states import ColorEnum, 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
|
||||
PENDING = 10, _('Pending'), ColorEnum.secondary # Order is pending (not yet placed)
|
||||
PLACED = 20, _('Placed'), ColorEnum.primary # Order has been placed with supplier
|
||||
ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Order is on hold
|
||||
COMPLETE = 30, _('Complete'), ColorEnum.success # Order has been completed
|
||||
CANCELLED = 40, _('Cancelled'), ColorEnum.danger # Order was cancelled
|
||||
LOST = 50, _('Lost'), ColorEnum.warning # Order was lost
|
||||
RETURNED = 60, _('Returned'), ColorEnum.warning # Order was returned
|
||||
Attributes:
|
||||
PENDING: Order is pending (not yet placed)
|
||||
PLACED: Order has been placed with supplier
|
||||
ON_HOLD: Order is on hold
|
||||
COMPLETE: Order has been completed
|
||||
CANCELLED: Order was cancelled
|
||||
LOST: Order was lost
|
||||
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:
|
||||
@@ -39,20 +48,27 @@ class PurchaseOrderStatusGroups:
|
||||
|
||||
|
||||
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
|
||||
IN_PROGRESS = (
|
||||
15,
|
||||
_('In Progress'),
|
||||
ColorEnum.primary,
|
||||
) # Order has been issued, and is in progress
|
||||
SHIPPED = 20, _('Shipped'), ColorEnum.primary # Order has been shipped to customer
|
||||
ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Order is on hold
|
||||
COMPLETE = 30, _('Complete'), ColorEnum.success # Order is complete
|
||||
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
|
||||
Attributes:
|
||||
PENDING: Order is pending
|
||||
IN_PROGRESS: Order has been issued, and is in progress
|
||||
SHIPPED: Order has been shipped to customer
|
||||
ON_HOLD: Order is on hold
|
||||
COMPLETE: Order is complete
|
||||
CANCELLED: Order has been cancelled
|
||||
LOST: Order was lost
|
||||
RETURNED: 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:
|
||||
@@ -71,16 +87,19 @@ class SalesOrderStatusGroups:
|
||||
|
||||
|
||||
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
|
||||
|
||||
# Items have been received, and are being inspected
|
||||
IN_PROGRESS = 20, _('In Progress'), ColorEnum.primary
|
||||
|
||||
ON_HOLD = 25, _('On Hold'), ColorEnum.warning
|
||||
|
||||
COMPLETE = 30, _('Complete'), ColorEnum.success
|
||||
CANCELLED = 40, _('Cancelled'), ColorEnum.danger
|
||||
|
||||
@@ -98,35 +117,41 @@ class ReturnOrderStatusGroups:
|
||||
|
||||
|
||||
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
|
||||
|
||||
# Item is to be returned to customer, no other action
|
||||
RETURN = 20, _('Return'), ColorEnum.success
|
||||
|
||||
# Item is to be repaired, and returned to customer
|
||||
REPAIR = 30, _('Repair'), ColorEnum.primary
|
||||
|
||||
# Item is to be replaced (new item shipped)
|
||||
REPLACE = 40, _('Replace'), ColorEnum.warning
|
||||
|
||||
# Item is to be refunded (cannot be repaired)
|
||||
REFUND = 50, _('Refund'), ColorEnum.info
|
||||
|
||||
# Item is rejected
|
||||
REJECT = 60, _('Reject'), ColorEnum.danger
|
||||
|
||||
|
||||
class TransferOrderStatus(StatusCode):
|
||||
"""Defines a set of status codes for a TransferOrder."""
|
||||
"""Defines a set of status codes for a TransferOrder.
|
||||
|
||||
# Order status codes
|
||||
PENDING = 10, _('Pending'), ColorEnum.secondary # Order is pending (not yet issued)
|
||||
ISSUED = 20, _('Issued'), ColorEnum.primary # Order has been issued
|
||||
ON_HOLD = 25, _('On Hold'), ColorEnum.warning # Order is on hold
|
||||
COMPLETE = 30, _('Complete'), ColorEnum.success # Order has been completed
|
||||
CANCELLED = 40, _('Cancelled'), ColorEnum.danger # Order was cancelled
|
||||
Attributes:
|
||||
PENDING: Order is pending (not yet issued)
|
||||
ISSUED: Order has been issued
|
||||
ON_HOLD: Order is on hold
|
||||
COMPLETE: Order has been completed
|
||||
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:
|
||||
|
||||
@@ -6,24 +6,27 @@ from generic.states import ColorEnum, StatusCode
|
||||
|
||||
|
||||
class StockStatus(StatusCode):
|
||||
"""Status codes for Stock."""
|
||||
"""Status codes for Stock.
|
||||
|
||||
OK = 10, _('OK'), ColorEnum.success # Item is OK
|
||||
ATTENTION = 50, _('Attention needed'), ColorEnum.warning # Item requires attention
|
||||
DAMAGED = 55, _('Damaged'), ColorEnum.warning # Item is damaged
|
||||
DESTROYED = 60, _('Destroyed'), ColorEnum.danger # Item is destroyed
|
||||
REJECTED = 65, _('Rejected'), ColorEnum.danger # Item is rejected
|
||||
LOST = 70, _('Lost'), ColorEnum.dark # Item has been lost
|
||||
QUARANTINED = (
|
||||
75,
|
||||
_('Quarantined'),
|
||||
ColorEnum.info,
|
||||
) # Item has been quarantined and is unavailable
|
||||
RETURNED = (
|
||||
85,
|
||||
_('Returned'),
|
||||
ColorEnum.warning,
|
||||
) # Item has been returned from a customer
|
||||
Attributes:
|
||||
OK: Stock item is healthy, nothing wrong to report
|
||||
ATTENTION: Stock item hasn't been checked or tested yet
|
||||
DAMAGED: Stock item is not functional in its present state
|
||||
DESTROYED: Stock item has been destroyed
|
||||
REJECTED: Stock item did not pass the quality control standards
|
||||
LOST: Stock item has been lost
|
||||
QUARANTINED: Stock item has been intentionally isolated and is unavailable
|
||||
RETURNED: Stock item has been returned from a customer
|
||||
"""
|
||||
|
||||
OK = 10, _('OK'), ColorEnum.success
|
||||
ATTENTION = 50, _('Attention needed'), ColorEnum.warning
|
||||
DAMAGED = 55, _('Damaged'), ColorEnum.warning
|
||||
DESTROYED = 60, _('Destroyed'), ColorEnum.danger
|
||||
REJECTED = 65, _('Rejected'), ColorEnum.danger
|
||||
LOST = 70, _('Lost'), ColorEnum.dark
|
||||
QUARANTINED = 75, _('Quarantined'), ColorEnum.info
|
||||
RETURNED = 85, _('Returned'), ColorEnum.warning
|
||||
|
||||
|
||||
class StockStatusGroups:
|
||||
@@ -39,7 +42,55 @@ class StockStatusGroups:
|
||||
|
||||
|
||||
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')
|
||||
|
||||
@@ -55,7 +106,7 @@ class StockHistoryCode(StatusCode):
|
||||
STOCK_REMOVE = 12, _('Stock manually removed')
|
||||
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
|
||||
STOCK_MOVE = 20, _('Location changed')
|
||||
|
||||
@@ -7,7 +7,21 @@ from generic.enums import 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'
|
||||
PART_CATEGORY = 'part_category'
|
||||
|
||||
@@ -2037,6 +2037,8 @@ def export_definitions(c, basedir: str = ''):
|
||||
base_path.joinpath('inventree_tags.yml'),
|
||||
base_path.joinpath('inventree_filters.yml'),
|
||||
base_path.joinpath('inventree_report_context.json'),
|
||||
base_path.joinpath('inventree_status_codes.json'),
|
||||
base_path.joinpath('inventree_roles.json'),
|
||||
]
|
||||
|
||||
info('Exporting definitions...')
|
||||
@@ -2051,6 +2053,12 @@ def export_definitions(c, basedir: str = ''):
|
||||
check_file_existence(filenames[3], overwrite=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')
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user