From a47d93a59bae1ef70bdc3217f6393e79ba3d779a Mon Sep 17 00:00:00 2001 From: IRBorisov <8611739+IRBorisov@users.noreply.github.com> Date: Fri, 22 Mar 2024 20:14:32 +0300 Subject: [PATCH] Implement InlineSynthesis backend --- rsconcept/backend/apps/rsform/messages.py | 6 +++ .../apps/rsform/serializers/data_access.py | 37 +++++++++++++++++++ .../backend/apps/rsform/views/operations.py | 27 ++++++++++---- 3 files changed, 63 insertions(+), 7 deletions(-) diff --git a/rsconcept/backend/apps/rsform/messages.py b/rsconcept/backend/apps/rsform/messages.py index 7c293f14..ba1f9cbb 100644 --- a/rsconcept/backend/apps/rsform/messages.py +++ b/rsconcept/backend/apps/rsform/messages.py @@ -4,6 +4,12 @@ def constituentaNotOwned(title: str): return f'Конституента не принадлежит схеме: {title}' +def substitutionNotInList(): + return 'Отождествляемая конституента отсутствует в списке' + +def schemaNotOwned(): + return 'Нет доступа к схеме' + def renameTrivial(name: str): return f'Имя должно отличаться от текущего: {name}' diff --git a/rsconcept/backend/apps/rsform/serializers/data_access.py b/rsconcept/backend/apps/rsform/serializers/data_access.py index a56acfbc..346cedf0 100644 --- a/rsconcept/backend/apps/rsform/serializers/data_access.py +++ b/rsconcept/backend/apps/rsform/serializers/data_access.py @@ -1,5 +1,7 @@ ''' Serializers for persistent data manipulation. ''' from typing import Optional, cast +from django.contrib.auth.models import User +from django.core.exceptions import PermissionDenied from rest_framework import serializers from rest_framework.serializers import PrimaryKeyRelatedField as PKField @@ -297,4 +299,39 @@ class InlineSynthesisSerializer(serializers.Serializer): ) def validate(self, attrs): + user = cast(User, self.context['user']) + schema_in = cast(LibraryItem, attrs['source']) + schema_out = cast(LibraryItem, attrs['receiver']) + if user.is_anonymous or (schema_out.owner != user and not user.is_staff): + raise PermissionDenied({ + 'message': msg.schemaNotOwned(), + 'object_id': schema_in.id + }) + constituents = cast(list[Constituenta], attrs['items']) + for cst in constituents: + if cst.schema != schema_in: + raise serializers.ValidationError({ + f'{cst.id}': msg.constituentaNotOwned(schema_in.title) + }) + for item in attrs['substitutions']: + original_cst = cast(Constituenta, item['original']) + substitution_cst = cast(Constituenta, item['substitution']) + if original_cst.schema == schema_in: + if original_cst not in constituents: + raise serializers.ValidationError({ + f'{original_cst.id}': msg.substitutionNotInList() + }) + if substitution_cst.schema != schema_out: + raise serializers.ValidationError({ + f'{substitution_cst.id}': msg.constituentaNotOwned(schema_out.title) + }) + else: + if substitution_cst not in constituents: + raise serializers.ValidationError({ + f'{substitution_cst.id}': msg.substitutionNotInList() + }) + if original_cst.schema != schema_out: + raise serializers.ValidationError({ + f'{original_cst.id}': msg.constituentaNotOwned(schema_out.title) + }) return attrs diff --git a/rsconcept/backend/apps/rsform/views/operations.py b/rsconcept/backend/apps/rsform/views/operations.py index 2fa38bdc..34ae2542 100644 --- a/rsconcept/backend/apps/rsform/views/operations.py +++ b/rsconcept/backend/apps/rsform/views/operations.py @@ -1,4 +1,6 @@ ''' Endpoints for RSForm. ''' +from typing import cast +from django.db import transaction from rest_framework.decorators import api_view from rest_framework.response import Response from rest_framework.request import Request @@ -14,19 +16,30 @@ from .. import serializers as s request=s.InlineSynthesisSerializer, responses={c.HTTP_200_OK: s.RSFormParseSerializer} ) +@transaction.atomic @api_view(['PATCH']) def inline_synthesis(request: Request): ''' Endpoint: Inline synthesis. ''' - serializer = s.InlineSynthesisSerializer(data=request.data) + serializer = s.InlineSynthesisSerializer( + data=request.data, + context={'user': request.user} + ) serializer.is_valid(raise_exception=True) schema = m.RSForm(serializer.validated_data['receiver']) - # schema.substitute( - # original=serializer.validated_data['original'], - # substitution=serializer.validated_data['substitution'], - # transfer_term=serializer.validated_data['transfer_term'] - # ) - schema.item.refresh_from_db() + items = cast(list[m.Constituenta], serializer.validated_data['items']) + new_items = schema.insert_copy(items) + + for substitution in serializer.validated_data['substitutions']: + original = cast(m.Constituenta, substitution['original']) + replacement = cast(m.Constituenta, substitution['substitution']) + if original in items: + index = next(i for (i, cst) in enumerate(items) if cst == original) + original = new_items[index] + else: + index = next(i for (i, cst) in enumerate(items) if cst == replacement) + replacement = new_items[index] + schema.substitute(original, replacement, serializer.validated_data['transfer_term']) return Response( status=c.HTTP_200_OK, data=s.RSFormParseSerializer(schema.item).data