Apply pattern to BuildOrder

This commit is contained in:
Oliver Walters 2026-07-02 11:00:57 +00:00
parent 32fa0fc85a
commit 855c463528
3 changed files with 49 additions and 2 deletions

View File

@ -34,6 +34,7 @@ from generic.states.fields import InvenTreeCustomStatusSerializerMixin
from InvenTree.mixins import DataImportExportSerializerMixin from InvenTree.mixins import DataImportExportSerializerMixin
from InvenTree.serializers import ( from InvenTree.serializers import (
CustomStatusSerializerMixin, CustomStatusSerializerMixin,
DuplicateOptionsSerializer,
FilterableSerializerMixin, FilterableSerializerMixin,
InvenTreeDecimalField, InvenTreeDecimalField,
InvenTreeModelSerializer, InvenTreeModelSerializer,
@ -67,6 +68,11 @@ class BuildSerializer(
): ):
"""Serializes a Build object.""" """Serializes a Build object."""
export_exclude_fields = ['duplicate']
import_exclude_fields = ['duplicate']
SKIP_CREATE_FIELDS = ['duplicate']
class Meta: class Meta:
"""Serializer metaclass.""" """Serializer metaclass."""
@ -80,6 +86,7 @@ class BuildSerializer(
'completed', 'completed',
'completion_date', 'completion_date',
'destination', 'destination',
'duplicate',
'external', 'external',
'parent', 'parent',
'part', 'part',
@ -190,12 +197,29 @@ class BuildSerializer(
return queryset return queryset
duplicate = DuplicateOptionsSerializer(Build.objects.all(), copy_parameters=True)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
"""Determine if extra serializer fields are required.""" """Determine if extra serializer fields are required."""
kwargs.pop('create', False) kwargs.pop('create', False)
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@transaction.atomic
def create(self, validated_data):
"""Create a new Build instance, optionally copying data from an existing build."""
duplicate = validated_data.pop('duplicate', None)
instance = super().create(validated_data)
if duplicate:
original = duplicate['original']
if duplicate.get('copy_parameters', True):
instance.copy_parameters_from(original)
return instance
def validate_reference(self, reference): def validate_reference(self, reference):
"""Custom validation for the Build reference field.""" """Custom validation for the Build reference field."""
# Ensure the reference matches the required pattern # Ensure the reference matches the required pattern

View File

@ -43,9 +43,11 @@ import { ProjectCodeField, TagsField } from './CommonFields';
*/ */
export function useBuildOrderFields({ export function useBuildOrderFields({
create, create,
duplicateBuildId,
modalId modalId
}: { }: {
create: boolean; create: boolean;
duplicateBuildId?: number | null;
modalId: string; modalId: string;
}): ApiFormFieldSet { }): ApiFormFieldSet {
const [destination, setDestination] = useState<number | null | undefined>( const [destination, setDestination] = useState<number | null | undefined>(
@ -133,7 +135,16 @@ export function useBuildOrderFields({
is_active: true is_active: true
} }
}, },
external: {} external: {},
duplicate: {
children: {
original: {
value: duplicateBuildId,
hidden: true
},
copy_parameters: {}
}
}
}; };
if (!globalSettings.isSet('PROJECT_CODES_ENABLED', true)) { if (!globalSettings.isSet('PROJECT_CODES_ENABLED', true)) {
@ -144,8 +155,19 @@ export function useBuildOrderFields({
delete fields.external; delete fields.external;
} }
if (!duplicateBuildId) {
delete fields.duplicate;
}
return fields; return fields;
}, [create, destination, batchCode, batchGenerator.result, globalSettings]); }, [
create,
destination,
batchCode,
batchGenerator.result,
globalSettings,
duplicateBuildId
]);
} }
export function useBuildOrderOutputFields({ export function useBuildOrderOutputFields({

View File

@ -632,6 +632,7 @@ export default function BuildDetail() {
const duplicateBuildOrderFields = useBuildOrderFields({ const duplicateBuildOrderFields = useBuildOrderFields({
create: false, create: false,
duplicateBuildId: build.pk,
modalId: 'duplicate-build-order' modalId: 'duplicate-build-order'
}); });