From 79ad54ed842a7f8b29991bc2d9aa08ea913ddacb Mon Sep 17 00:00:00 2001 From: Ivan <8611739+IRBorisov@users.noreply.github.com> Date: Sun, 11 Aug 2024 00:10:27 +0300 Subject: [PATCH] R: intorduce facade --- .../backend/apps/oss/models/ChangeManager.py | 2 +- .../apps/oss/models/PropagationFacade.py | 42 +++++++++++++++ rsconcept/backend/apps/oss/models/__init__.py | 1 + .../backend/apps/rsform/views/rsforms.py | 51 ++++++++----------- 4 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 rsconcept/backend/apps/oss/models/PropagationFacade.py diff --git a/rsconcept/backend/apps/oss/models/ChangeManager.py b/rsconcept/backend/apps/oss/models/ChangeManager.py index c006c163..e1f45dfe 100644 --- a/rsconcept/backend/apps/oss/models/ChangeManager.py +++ b/rsconcept/backend/apps/oss/models/ChangeManager.py @@ -26,7 +26,7 @@ CstMapping = dict[str, Constituenta] class ChangeManager: - ''' Change propagation API. ''' + ''' Change propagation wrapper for OSS. ''' class Cache: ''' Cache for RSForm constituents. ''' diff --git a/rsconcept/backend/apps/oss/models/PropagationFacade.py b/rsconcept/backend/apps/oss/models/PropagationFacade.py new file mode 100644 index 00000000..46169012 --- /dev/null +++ b/rsconcept/backend/apps/oss/models/PropagationFacade.py @@ -0,0 +1,42 @@ +''' Models: Change propagation facade - managing all changes in OSS. ''' +from apps.library.models import LibraryItem +from apps.rsform.models import Constituenta, RSForm + +from .ChangeManager import ChangeManager + + +def _get_oss_hosts(item: LibraryItem) -> list[LibraryItem]: + ''' Get all hosts for LibraryItem. ''' + return list(LibraryItem.objects.filter(operations__result=item).only('pk')) + + +class PropagationFacade: + ''' Change propagation API. ''' + + @classmethod + def on_create_cst(cls, new_cst: Constituenta, source: RSForm) -> None: + ''' Trigger cascade resolutions when new constituent is created. ''' + hosts = _get_oss_hosts(source.model) + for host in hosts: + ChangeManager(host).on_create_cst(new_cst, source) + + @classmethod + def on_change_cst_type(cls, target: Constituenta, source: RSForm) -> None: + ''' Trigger cascade resolutions when constituenta type is changed. ''' + hosts = _get_oss_hosts(source.model) + for host in hosts: + ChangeManager(host).on_change_cst_type(target, source) + + @classmethod + def on_update_cst(cls, target: Constituenta, data: dict, old_data: dict, source: RSForm) -> None: + ''' Trigger cascade resolutions when constituenta data is changed. ''' + hosts = _get_oss_hosts(source.model) + for host in hosts: + ChangeManager(host).on_update_cst(target, data, old_data, source) + + @classmethod + def before_delete(cls, delete_cst: list[Constituenta], source: RSForm) -> None: + ''' Trigger cascade resolutions before constituents are deleted. ''' + # hosts = _get_oss_hosts(source.model) + # for host in hosts: + # ChangeManager(host).before_delete(delete_cst, source) diff --git a/rsconcept/backend/apps/oss/models/__init__.py b/rsconcept/backend/apps/oss/models/__init__.py index fa3be516..0de32d63 100644 --- a/rsconcept/backend/apps/oss/models/__init__.py +++ b/rsconcept/backend/apps/oss/models/__init__.py @@ -6,3 +6,4 @@ from .Inheritance import Inheritance from .Operation import Operation, OperationType from .OperationSchema import OperationSchema from .Substitution import Substitution +from .PropagationFacade import PropagationFacade diff --git a/rsconcept/backend/apps/rsform/views/rsforms.py b/rsconcept/backend/apps/rsform/views/rsforms.py index e1844729..eeb61034 100644 --- a/rsconcept/backend/apps/rsform/views/rsforms.py +++ b/rsconcept/backend/apps/rsform/views/rsforms.py @@ -16,7 +16,7 @@ from rest_framework.serializers import ValidationError from apps.library.models import AccessPolicy, LibraryItem, LibraryItemType, LocationHead from apps.library.serializers import LibraryItemSerializer -from apps.oss.models import ChangeManager +from apps.oss.models import PropagationFacade from apps.users.models import User from shared import messages as msg from shared import permissions, utility @@ -84,15 +84,10 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr insert_after = None else: insert_after = data['insert_after'] - schema = m.RSForm(self._get_item()) with transaction.atomic(): new_cst = schema.create_cst(data, insert_after) - hosts = LibraryItem.objects.filter(operations__result=schema.model) - for host in hosts: - ChangeManager(host).on_create_cst(new_cst, schema) - - + PropagationFacade.on_create_cst(new_cst, schema) return Response( status=c.HTTP_201_CREATED, data={ @@ -118,16 +113,12 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr model = self._get_item() serializer = s.CstUpdateSerializer(data=request.data, partial=True, context={'schema': model}) serializer.is_valid(raise_exception=True) - cst = cast(m.Constituenta, serializer.validated_data['target']) schema = m.RSForm(model) data = serializer.validated_data['item_data'] with transaction.atomic(): - hosts = LibraryItem.objects.filter(operations__result=model) old_data = schema.update_cst(cst, data) - for host in hosts: - ChangeManager(host).on_update_cst(cst, data, old_data, schema) - + PropagationFacade.on_update_cst(cst, data, old_data, schema) return Response( status=c.HTTP_200_OK, data=s.CstSerializer(m.Constituenta.objects.get(pk=request.data['target'])).data @@ -164,13 +155,15 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr status=c.HTTP_400_BAD_REQUEST, data={f'{cst.pk}': msg.constituentaNoStructure()} ) + schema = m.RSForm(model) + with transaction.atomic(): - result = m.RSForm(model).produce_structure(cst, cst_parse) + result = schema.produce_structure(cst, cst_parse) return Response( status=c.HTTP_200_OK, data={ 'cst_list': result, - 'schema': s.RSFormParseSerializer(model).data + 'schema': s.RSFormParseSerializer(schema.model).data } ) @@ -191,28 +184,23 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr model = self._get_item() serializer = s.CstRenameSerializer(data=request.data, context={'schema': model}) serializer.is_valid(raise_exception=True) - cst = cast(m.Constituenta, serializer.validated_data['target']) changed_type = cst.cst_type != serializer.validated_data['cst_type'] mapping = {cst.alias: serializer.validated_data['alias']} - cst.alias = serializer.validated_data['alias'] - cst.cst_type = serializer.validated_data['cst_type'] schema = m.RSForm(model) - with transaction.atomic(): + cst.alias = serializer.validated_data['alias'] + cst.cst_type = serializer.validated_data['cst_type'] cst.save() schema.apply_mapping(mapping=mapping, change_aliases=False) cst.refresh_from_db() if changed_type: - hosts = LibraryItem.objects.filter(operations__result=model) - for host in hosts: - ChangeManager(host).on_change_cst_type(cst, schema) - + PropagationFacade.on_change_cst_type(cst, schema) return Response( status=c.HTTP_200_OK, data={ 'new_cst': s.CstSerializer(cst).data, - 'schema': s.RSFormParseSerializer(model).data + 'schema': s.RSFormParseSerializer(schema.model).data } ) @@ -236,19 +224,17 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr context={'schema': model} ) serializer.is_valid(raise_exception=True) - + schema = m.RSForm(model) + substitutions: list[tuple[m.Constituenta, m.Constituenta]] = [] with transaction.atomic(): - substitutions: list[tuple[m.Constituenta, m.Constituenta]] = [] for substitution in serializer.validated_data['substitutions']: original = cast(m.Constituenta, substitution['original']) replacement = cast(m.Constituenta, substitution['substitution']) substitutions.append((original, replacement)) - m.RSForm(model).substitute(substitutions) - - model.refresh_from_db() + schema.substitute(substitutions) return Response( status=c.HTTP_200_OK, - data=s.RSFormParseSerializer(model).data + data=s.RSFormParseSerializer(schema.model).data ) @extend_schema( @@ -271,11 +257,14 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr context={'schema': model} ) serializer.is_valid(raise_exception=True) + cst_list: list[m.Constituenta] = serializer.validated_data['items'] + schema = m.RSForm(model) with transaction.atomic(): - m.RSForm(model).delete_cst(serializer.validated_data['items']) + PropagationFacade.before_delete(cst_list, schema) + schema.delete_cst(cst_list) return Response( status=c.HTTP_200_OK, - data=s.RSFormParseSerializer(model).data + data=s.RSFormParseSerializer(schema.model).data ) @extend_schema(