2
0
mirror of https://github.com/inventree/InvenTree.git synced 2026-04-14 15:28:52 +00:00

Order line number (#11692)

* Add "line number" field for external orders

* Updated serializers

* Add columns to UI tables

* Update form fields

* Adds API ordering

* Bump API version

* Update CHANGELOG.md
This commit is contained in:
Oliver
2026-04-08 15:36:08 +10:00
committed by GitHub
parent 4d2ed8fcba
commit 71373e3c19
15 changed files with 131 additions and 5 deletions

View File

@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- [#11692](https://github.com/inventree/InvenTree/pull/11692) adds line item numbering for external orders (purchase, sales and return orders). This allows users to specify a line number for each line item on the order, which can be used for reference purposes. The line number is optional, and can be left blank if not required. The line number is stored as a string, to allow for more flexible formatting (e.g. "1", "1.1", "A", etc).
- [#11641](https://github.com/inventree/InvenTree/pull/11641) adds support for custom parameters against the SalesOrderShipment model.
- [#11527](https://github.com/inventree/InvenTree/pull/11527) adds a new API endpoint for monitoring the status of a particular background task. This endpoint allows clients to check the status of a background task and receive updates when the task is complete. This is useful for long-running tasks that may take some time to complete, allowing clients to provide feedback to users about the progress of the task.
- [#11405](https://github.com/inventree/InvenTree/pull/11405) adds default table filters, which hide inactive items by default. The default table filters are overridden by user filter selection, and only apply to the table view initially presented to the user. This means that users can still view inactive items if they choose to, but they will not be shown by default.

View File

@@ -1,11 +1,16 @@
"""InvenTree API version information."""
# InvenTree API version
INVENTREE_API_VERSION = 472
INVENTREE_API_VERSION = 473
"""Increment this API version number whenever there is a significant change to the API that any clients need to know about."""
INVENTREE_API_TEXT = """
v473 -> 2026-04-08 : https://github.com/inventree/InvenTree/pull/11692
- Adds "line" field to PurchaseOrderLineItem and PurchaseOrderExtraLineItem API endpoints
- Adds "line" field to SalesOrderLineItem and SalesOrderExtraLineItem API endpoints
- Adds "line" field to ReturnOrderLineItem and ReturnOrderExtraLineItem API endpoints
v472 -> 2026-04-01 : https://github.com/inventree/InvenTree/pull/xxxx
- Fixes writable fields on the user detail endpoint

View File

@@ -82,7 +82,7 @@ class GeneralExtraLineList(SerializerContextMixin, DataExportViewMixin):
filter_backends = SEARCH_ORDER_FILTER
ordering_fields = ['quantity', 'notes', 'reference']
ordering_fields = ['quantity', 'notes', 'reference', 'line']
search_fields = ['quantity', 'notes', 'reference', 'description']
@@ -717,6 +717,7 @@ class PurchaseOrderLineItemList(
'order': 'order__reference',
'status': 'order__status',
'complete_date': 'order__complete_date',
'line': ['line', 'part__SKU'],
}
ordering_fields = [
@@ -733,6 +734,7 @@ class PurchaseOrderLineItemList(
'order',
'status',
'complete_date',
'line',
]
search_fields = [
@@ -1067,6 +1069,7 @@ class SalesOrderLineItemList(
'reference',
'sale_price',
'target_date',
'line',
]
ordering_field_aliases = {
@@ -1074,6 +1077,7 @@ class SalesOrderLineItemList(
'part': 'part__name',
'IPN': 'part__IPN',
'order': 'order__reference',
'line': ['line', 'part__name'],
}
search_fields = ['part__name', 'quantity', 'reference']
@@ -1720,9 +1724,11 @@ class ReturnOrderLineItemList(
'reference',
'target_date',
'received_date',
'line',
]
ordering_field_aliases = {
'line': ['line', 'item__part__name'],
'part': 'item__part__name',
'IPN': 'item__part__IPN',
'stock': ['item__quantity', 'item__serial_int', 'item__serial'],

View File

@@ -0,0 +1,79 @@
# Generated by Django 5.2.12 on 2026-04-08 03:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("order", "0115_purchaseorder_updated_at_returnorder_updated_at_and_more"),
]
operations = [
migrations.AddField(
model_name="purchaseorderextraline",
name="line",
field=models.CharField(
blank=True,
default="",
help_text="Line number for this item (optional)",
max_length=20,
verbose_name="Line Number",
),
),
migrations.AddField(
model_name="purchaseorderlineitem",
name="line",
field=models.CharField(
blank=True,
default="",
help_text="Line number for this item (optional)",
max_length=20,
verbose_name="Line Number",
),
),
migrations.AddField(
model_name="returnorderextraline",
name="line",
field=models.CharField(
blank=True,
default="",
help_text="Line number for this item (optional)",
max_length=20,
verbose_name="Line Number",
),
),
migrations.AddField(
model_name="returnorderlineitem",
name="line",
field=models.CharField(
blank=True,
default="",
help_text="Line number for this item (optional)",
max_length=20,
verbose_name="Line Number",
),
),
migrations.AddField(
model_name="salesorderextraline",
name="line",
field=models.CharField(
blank=True,
default="",
help_text="Line number for this item (optional)",
max_length=20,
verbose_name="Line Number",
),
),
migrations.AddField(
model_name="salesorderlineitem",
name="line",
field=models.CharField(
blank=True,
default="",
help_text="Line number for this item (optional)",
max_length=20,
verbose_name="Line Number",
),
),
]

View File

@@ -1793,6 +1793,15 @@ class OrderLineItem(InvenTree.models.InvenTreeMetadataModel):
if self.price:
return self.quantity * self.price
line = models.CharField(
max_length=20,
blank=True,
default='',
null=False,
verbose_name=_('Line Number'),
help_text=_('Line number for this item (optional)'),
)
reference = models.CharField(
max_length=100,
blank=True,

View File

@@ -276,6 +276,7 @@ class AbstractLineItemSerializer(FilterableSerializerMixin, serializers.Serializ
"""Construct a set of fields for this serializer."""
return [
'pk',
'line',
'link',
'notes',
'order',
@@ -309,6 +310,7 @@ class AbstractExtraLineSerializer(
"""Construct a set of fields for this serializer."""
return [
'pk',
'line',
'description',
'link',
'notes',

View File

@@ -83,6 +83,7 @@ export function extraLineItemFields(): ApiFormFieldSet {
order: {
hidden: true
},
line: {},
reference: {},
description: {},
quantity: {},

View File

@@ -144,6 +144,7 @@ export function usePurchaseOrderLineItemFields({
};
}
},
line: {},
reference: {},
quantity: {
onValueChange: (value) => {

View File

@@ -128,8 +128,9 @@ export function useReturnOrderLineItemFields({
part_detail: true
}
},
quantity: {},
line: {},
reference: {},
quantity: {},
outcome: {
hidden: create == true
},

View File

@@ -169,6 +169,7 @@ export function useSalesOrderLineItemFields({
},
onValueChange: (_: any, record?: any) => setPart(record)
},
line: {},
reference: {},
quantity: {
onValueChange: (value) => {

View File

@@ -767,3 +767,13 @@ export function TotalPriceColumn(): TableColumn {
title: t`Total Price`
});
}
export function LineItemColumn(props: TableColumnProps): TableColumn {
return {
accessor: 'line',
title: t`Line Item`,
sortable: true,
switchable: true,
...props
};
}

View File

@@ -24,6 +24,7 @@ import { useUserState } from '../../states/UserState';
import {
DecimalColumn,
DescriptionColumn,
LineItemColumn,
LinkColumn,
NoteColumn,
ProjectCodeColumn
@@ -50,6 +51,7 @@ export default function ExtraLineItemTable({
const tableColumns: TableColumn[] = useMemo(() => {
return [
LineItemColumn({}),
{
accessor: 'reference',
switchable: false
@@ -177,6 +179,7 @@ export default function ExtraLineItemTable({
params: {
order: orderId
},
defaultSortColumn: 'line',
rowActions: rowActions,
tableActions: tableActions
}}

View File

@@ -36,11 +36,11 @@ import {
import useStatusCodes from '../../hooks/UseStatusCodes';
import { useTable } from '../../hooks/UseTable';
import { useImporterState } from '../../states/ImporterState';
import { useGlobalSettingsState } from '../../states/SettingsStates';
import { useUserState } from '../../states/UserState';
import {
CurrencyColumn,
DescriptionColumn,
LineItemColumn,
LinkColumn,
LocationColumn,
NoteColumn,
@@ -74,7 +74,6 @@ export function PurchaseOrderLineItemTable({
}>) {
const table = useTable('purchase-order-line-item');
const globalSettings = useGlobalSettingsState();
const navigate = useNavigate();
const user = useUserState();
const openImporter = useImporterState((state) => state.openImporter);
@@ -134,6 +133,7 @@ export function PurchaseOrderLineItemTable({
const tableColumns: TableColumn[] = useMemo(() => {
return [
LineItemColumn({}),
PartColumn({
part: 'part_detail',
ordering: 'part_name'
@@ -435,6 +435,7 @@ export function PurchaseOrderLineItemTable({
props={{
enableSelection: true,
enableDownload: true,
defaultSortColumn: 'line',
params: {
...params,
order: orderId,

View File

@@ -31,6 +31,7 @@ import { useUserState } from '../../states/UserState';
import {
DateColumn,
DescriptionColumn,
LineItemColumn,
LinkColumn,
NoteColumn,
PartColumn,
@@ -110,6 +111,7 @@ export default function ReturnOrderLineItemTable({
const tableColumns: TableColumn[] = useMemo(() => {
return [
LineItemColumn({}),
PartColumn({
part: 'part_detail',
ordering: 'part'
@@ -267,6 +269,7 @@ export default function ReturnOrderLineItemTable({
item_detail: true,
order_detail: true
},
defaultSortColumn: 'line',
enableSelection:
inProgress && user.hasChangeRole(UserRoles.return_order),
tableActions: tableActions,

View File

@@ -48,6 +48,7 @@ import {
DecimalColumn,
DescriptionColumn,
IPNColumn,
LineItemColumn,
LinkColumn,
ProjectCodeColumn,
ReferenceColumn,
@@ -77,6 +78,7 @@ export default function SalesOrderLineItemTable({
const tableColumns: TableColumn[] = useMemo(() => {
return [
LineItemColumn({}),
{
accessor: 'part',
sortable: true,
@@ -539,6 +541,7 @@ export default function SalesOrderLineItemTable({
order: orderId,
part_detail: true
},
defaultSortColumn: 'line',
rowActions: rowActions,
tableActions: tableActions,
tableFilters: tableFilters,