R: intorduce facade

This commit is contained in:
Ivan 2024-08-11 00:10:27 +03:00
parent 39a18121c6
commit 79ad54ed84
4 changed files with 64 additions and 32 deletions

View File

@ -26,7 +26,7 @@ CstMapping = dict[str, Constituenta]
class ChangeManager: class ChangeManager:
''' Change propagation API. ''' ''' Change propagation wrapper for OSS. '''
class Cache: class Cache:
''' Cache for RSForm constituents. ''' ''' Cache for RSForm constituents. '''

View File

@ -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)

View File

@ -6,3 +6,4 @@ from .Inheritance import Inheritance
from .Operation import Operation, OperationType from .Operation import Operation, OperationType
from .OperationSchema import OperationSchema from .OperationSchema import OperationSchema
from .Substitution import Substitution from .Substitution import Substitution
from .PropagationFacade import PropagationFacade

View File

@ -16,7 +16,7 @@ from rest_framework.serializers import ValidationError
from apps.library.models import AccessPolicy, LibraryItem, LibraryItemType, LocationHead from apps.library.models import AccessPolicy, LibraryItem, LibraryItemType, LocationHead
from apps.library.serializers import LibraryItemSerializer 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 apps.users.models import User
from shared import messages as msg from shared import messages as msg
from shared import permissions, utility from shared import permissions, utility
@ -84,15 +84,10 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
insert_after = None insert_after = None
else: else:
insert_after = data['insert_after'] insert_after = data['insert_after']
schema = m.RSForm(self._get_item()) schema = m.RSForm(self._get_item())
with transaction.atomic(): with transaction.atomic():
new_cst = schema.create_cst(data, insert_after) new_cst = schema.create_cst(data, insert_after)
hosts = LibraryItem.objects.filter(operations__result=schema.model) PropagationFacade.on_create_cst(new_cst, schema)
for host in hosts:
ChangeManager(host).on_create_cst(new_cst, schema)
return Response( return Response(
status=c.HTTP_201_CREATED, status=c.HTTP_201_CREATED,
data={ data={
@ -118,16 +113,12 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
model = self._get_item() model = self._get_item()
serializer = s.CstUpdateSerializer(data=request.data, partial=True, context={'schema': model}) serializer = s.CstUpdateSerializer(data=request.data, partial=True, context={'schema': model})
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
cst = cast(m.Constituenta, serializer.validated_data['target']) cst = cast(m.Constituenta, serializer.validated_data['target'])
schema = m.RSForm(model) schema = m.RSForm(model)
data = serializer.validated_data['item_data'] data = serializer.validated_data['item_data']
with transaction.atomic(): with transaction.atomic():
hosts = LibraryItem.objects.filter(operations__result=model)
old_data = schema.update_cst(cst, data) old_data = schema.update_cst(cst, data)
for host in hosts: PropagationFacade.on_update_cst(cst, data, old_data, schema)
ChangeManager(host).on_update_cst(cst, data, old_data, schema)
return Response( return Response(
status=c.HTTP_200_OK, status=c.HTTP_200_OK,
data=s.CstSerializer(m.Constituenta.objects.get(pk=request.data['target'])).data 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, status=c.HTTP_400_BAD_REQUEST,
data={f'{cst.pk}': msg.constituentaNoStructure()} data={f'{cst.pk}': msg.constituentaNoStructure()}
) )
schema = m.RSForm(model)
with transaction.atomic(): with transaction.atomic():
result = m.RSForm(model).produce_structure(cst, cst_parse) result = schema.produce_structure(cst, cst_parse)
return Response( return Response(
status=c.HTTP_200_OK, status=c.HTTP_200_OK,
data={ data={
'cst_list': result, '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() model = self._get_item()
serializer = s.CstRenameSerializer(data=request.data, context={'schema': model}) serializer = s.CstRenameSerializer(data=request.data, context={'schema': model})
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
cst = cast(m.Constituenta, serializer.validated_data['target']) cst = cast(m.Constituenta, serializer.validated_data['target'])
changed_type = cst.cst_type != serializer.validated_data['cst_type'] changed_type = cst.cst_type != serializer.validated_data['cst_type']
mapping = {cst.alias: serializer.validated_data['alias']} 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) schema = m.RSForm(model)
with transaction.atomic(): with transaction.atomic():
cst.alias = serializer.validated_data['alias']
cst.cst_type = serializer.validated_data['cst_type']
cst.save() cst.save()
schema.apply_mapping(mapping=mapping, change_aliases=False) schema.apply_mapping(mapping=mapping, change_aliases=False)
cst.refresh_from_db() cst.refresh_from_db()
if changed_type: if changed_type:
hosts = LibraryItem.objects.filter(operations__result=model) PropagationFacade.on_change_cst_type(cst, schema)
for host in hosts:
ChangeManager(host).on_change_cst_type(cst, schema)
return Response( return Response(
status=c.HTTP_200_OK, status=c.HTTP_200_OK,
data={ data={
'new_cst': s.CstSerializer(cst).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} context={'schema': model}
) )
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
schema = m.RSForm(model)
substitutions: list[tuple[m.Constituenta, m.Constituenta]] = []
with transaction.atomic(): with transaction.atomic():
substitutions: list[tuple[m.Constituenta, m.Constituenta]] = []
for substitution in serializer.validated_data['substitutions']: for substitution in serializer.validated_data['substitutions']:
original = cast(m.Constituenta, substitution['original']) original = cast(m.Constituenta, substitution['original'])
replacement = cast(m.Constituenta, substitution['substitution']) replacement = cast(m.Constituenta, substitution['substitution'])
substitutions.append((original, replacement)) substitutions.append((original, replacement))
m.RSForm(model).substitute(substitutions) schema.substitute(substitutions)
model.refresh_from_db()
return Response( return Response(
status=c.HTTP_200_OK, status=c.HTTP_200_OK,
data=s.RSFormParseSerializer(model).data data=s.RSFormParseSerializer(schema.model).data
) )
@extend_schema( @extend_schema(
@ -271,11 +257,14 @@ class RSFormViewSet(viewsets.GenericViewSet, generics.ListAPIView, generics.Retr
context={'schema': model} context={'schema': model}
) )
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
cst_list: list[m.Constituenta] = serializer.validated_data['items']
schema = m.RSForm(model)
with transaction.atomic(): 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( return Response(
status=c.HTTP_200_OK, status=c.HTTP_200_OK,
data=s.RSFormParseSerializer(model).data data=s.RSFormParseSerializer(schema.model).data
) )
@extend_schema( @extend_schema(