ConceptPortal-public/rsconcept/backend/apps/oss/models/OperationSchema.py

159 lines
5.1 KiB
Python
Raw Normal View History

2024-07-19 19:29:27 +03:00
''' Models: OSS API. '''
from typing import Optional
from django.core.exceptions import ValidationError
from django.db import transaction
from django.db.models import QuerySet
2024-07-19 19:29:27 +03:00
from apps.library.models import LibraryItem, LibraryItemType
2024-07-19 19:29:27 +03:00
from shared import messages as msg
from .Argument import Argument
from .Operation import Operation
from .Substitution import Substitution
2024-07-19 19:29:27 +03:00
class OperationSchema:
2024-07-19 19:29:27 +03:00
''' Operations schema API. '''
def __init__(self, model: LibraryItem):
self.model = model
2024-07-19 19:29:27 +03:00
@staticmethod
def create(**kwargs) -> 'OperationSchema':
''' Create LibraryItem via OperationSchema. '''
model = LibraryItem.objects.create(item_type=LibraryItemType.OPERATION_SCHEMA, **kwargs)
return OperationSchema(model)
2024-07-22 21:20:51 +03:00
@staticmethod
def from_id(pk: int) -> 'OperationSchema':
''' Get LibraryItem by pk. '''
model = LibraryItem.objects.get(pk=pk)
return OperationSchema(model)
2024-07-22 21:20:51 +03:00
def save(self, *args, **kwargs):
''' Save wrapper. '''
self.model.save(*args, **kwargs)
2024-07-22 21:20:51 +03:00
def refresh_from_db(self):
''' Model wrapper. '''
self.model.refresh_from_db()
2024-07-19 19:29:27 +03:00
def operations(self) -> QuerySet[Operation]:
''' Get QuerySet containing all operations of current OSS. '''
return Operation.objects.filter(oss=self.model)
2024-07-19 19:29:27 +03:00
def arguments(self) -> QuerySet[Argument]:
''' Operation arguments. '''
return Argument.objects.filter(operation__oss=self.model)
2024-07-19 19:29:27 +03:00
def substitutions(self) -> QuerySet[Substitution]:
2024-07-19 19:29:27 +03:00
''' Operation substitutions. '''
return Substitution.objects.filter(operation__oss=self.model)
2024-07-19 19:29:27 +03:00
def update_positions(self, data: list[dict]):
''' Update positions. '''
lookup = {x['id']: x for x in data}
operations = self.operations()
for item in operations:
if item.pk in lookup:
item.position_x = lookup[item.pk]['position_x']
item.position_y = lookup[item.pk]['position_y']
Operation.objects.bulk_update(operations, ['position_x', 'position_y'])
@transaction.atomic
def create_operation(self, **kwargs) -> Operation:
''' Insert new operation. '''
if kwargs['alias'] != '' and self.operations().filter(alias=kwargs['alias']).exists():
raise ValidationError(msg.aliasTaken(kwargs['alias']))
result = Operation.objects.create(oss=self.model, **kwargs)
2024-07-22 21:20:51 +03:00
self.save()
2024-07-19 19:29:27 +03:00
result.refresh_from_db()
return result
@transaction.atomic
def delete_operation(self, operation: Operation):
''' Delete operation. '''
operation.delete()
# deal with attached schema
# trigger on_change effects
2024-07-22 21:20:51 +03:00
self.save()
2024-07-19 19:29:27 +03:00
@transaction.atomic
def set_input(self, target: Operation, schema: Optional[LibraryItem]):
''' Set input schema for operation. '''
if schema == target.result:
return
if schema:
target.result = schema
target.alias = schema.alias
target.title = schema.title
target.comment = schema.comment
else:
target.result = None
target.save()
# trigger on_change effects
2024-07-22 21:20:51 +03:00
self.save()
2024-07-19 19:29:27 +03:00
@transaction.atomic
2024-07-29 22:31:11 +03:00
def set_arguments(self, operation: Operation, arguments: list[Operation]):
''' Set arguments to operation. '''
processed: list[Operation] = []
changed = False
for current in operation.getArguments():
if current.argument not in arguments:
changed = True
current.delete()
else:
processed.append(current.argument)
for arg in arguments:
if arg not in processed:
changed = True
processed.append(arg)
Argument.objects.create(operation=operation, argument=arg)
if not changed:
2024-07-19 19:29:27 +03:00
return
# trigger on_change effects
2024-07-22 21:20:51 +03:00
self.save()
2024-07-19 19:29:27 +03:00
@transaction.atomic
def set_substitutions(self, target: Operation, substitutes: list[dict]):
''' Clear all arguments for operation. '''
2024-07-29 22:31:11 +03:00
processed: list[dict] = []
changed = False
for current in target.getSubstitutions():
subs = [
x for x in substitutes
if x['original'] == current.original and x['substitution'] == current.substitution
]
if len(subs) == 0:
changed = True
current.delete()
continue
if current.transfer_term != subs[0]['transfer_term']:
current.transfer_term = subs[0]['transfer_term']
current.save()
continue
processed.append(subs[0])
2024-07-19 19:29:27 +03:00
2024-07-29 22:31:11 +03:00
for sub in substitutes:
if sub not in processed:
changed = True
Substitution.objects.create(
operation=target,
original=sub['original'],
substitution=sub['substitution'],
transfer_term=sub['transfer_term']
)
if not changed:
return
2024-07-19 19:29:27 +03:00
# trigger on_change effects
2024-07-22 21:20:51 +03:00
self.save()