B: Prevent multiple instances of KS in synthesis

This commit is contained in:
Ivan 2025-08-06 14:32:09 +03:00
parent d4c7951966
commit 2ae0db5c2b
5 changed files with 53 additions and 5 deletions

View File

@ -328,6 +328,10 @@ class CreateSynthesisSerializer(StrictSerializer):
})
schemas = [arg.result_id for arg in attrs['arguments'] if arg.result is not None]
if len(schemas) != len(set(schemas)):
raise serializers.ValidationError({
'arguments': msg.duplicateSchemasInArguments()
})
substitutions = attrs['substitutions']
to_delete = {x['original'].pk for x in substitutions}
deleted = set()
@ -375,6 +379,7 @@ class UpdateOperationSerializer(StrictSerializer):
required=False
)
# pylint: disable=too-many-branches
def validate(self, attrs):
oss = cast(LibraryItem, self.context['oss'])
parent = attrs['item_data'].get('parent')
@ -405,6 +410,10 @@ class UpdateOperationSerializer(StrictSerializer):
if 'substitutions' not in attrs:
return attrs
schemas = [arg.result_id for arg in attrs['arguments'] if arg.result is not None]
if len(schemas) != len(set(schemas)):
raise serializers.ValidationError({
'arguments': msg.duplicateSchemasInArguments()
})
substitutions = attrs['substitutions']
to_delete = {x['original'].pk for x in substitutions}
deleted = set()

View File

@ -270,6 +270,37 @@ class TestOssOperations(EndpointTester):
self.assertNotEqual(new_operation['result'], None)
@decl_endpoint('/api/oss/{item}/create-synthesis', method='post')
def test_create_synthesis_replicas(self):
self.populateData()
operation4 = self.owned.create_replica(self.operation1)
operation5 = self.owned.create_replica(self.operation1)
data = {
'item_data': {
'alias': 'Test5',
'title': 'Test title',
'description': '',
'parent': None
},
'layout': self.layout_data,
'position': {
'x': 1,
'y': 1,
'width': 500,
'height': 50
},
'arguments': [self.operation1.pk, operation4.pk],
'substitutions': []
}
self.executeBadData(data=data, item=self.owned_id)
data['arguments'] = [operation4.pk, operation5.pk]
self.executeBadData(data=data, item=self.owned_id)
data['arguments'] = [operation4.pk, self.operation3.pk]
self.executeCreated(data=data, item=self.owned_id)
@decl_endpoint('/api/oss/{item}/delete-operation', method='patch')
def test_delete_operation(self):
self.populateData()

View File

@ -22,6 +22,10 @@ def operationNotInOSS():
return 'Операция не принадлежит ОСС'
def duplicateSchemasInArguments():
return 'Аргументы не должны содержать повторяющиеся КС'
def blockNotInOSS():
return 'Блок не принадлежит ОСС'

View File

@ -20,8 +20,11 @@ export function TabArguments() {
} = useFormContext<ICreateSynthesisDTO>();
const inputs = useWatch({ control, name: 'arguments' });
const references = manager.oss.replicas.filter(item => inputs.includes(item.original)).map(item => item.replica);
const filtered = manager.oss.operations.filter(item => !references.includes(item.id));
const replicas = manager.oss.replicas
.filter(item => inputs.includes(item.original))
.map(item => item.replica)
.concat(manager.oss.replicas.filter(item => inputs.includes(item.replica)).map(item => item.original));
const filtered = manager.oss.operations.filter(item => !replicas.includes(item.id));
return (
<div className='cc-fade-in cc-column'>

View File

@ -15,10 +15,11 @@ export function TabArguments() {
const { manager, target } = useDialogsStore(state => state.props as DlgEditOperationProps);
const args = useWatch({ control, name: 'arguments' });
const references = manager.oss.replicas
const replicas = manager.oss.replicas
.filter(item => args.includes(item.original) || item.original === target.id)
.map(item => item.replica);
const potentialCycle = [target.id, ...references, ...manager.oss.graph.expandAllOutputs([target.id])];
.map(item => item.replica)
.concat(manager.oss.replicas.filter(item => args.includes(item.replica)).map(item => item.original));
const potentialCycle = [target.id, ...replicas, ...manager.oss.graph.expandAllOutputs([target.id])];
const filtered = manager.oss.operations.filter(item => !potentialCycle.includes(item.id));
function handleChangeArguments(prev: number[], newValue: number[]) {