B: Copy attributions when cloning

This commit is contained in:
Ivan 2025-08-23 16:05:43 +03:00
parent 15b4298b22
commit 6cf794f13b
2 changed files with 17 additions and 3 deletions

View File

@ -9,7 +9,7 @@ from apps.library.models import (
LibraryTemplate, LibraryTemplate,
LocationHead LocationHead
) )
from apps.rsform.models import RSForm from apps.rsform.models import Attribution, RSForm
from shared.EndpointTester import EndpointTester, decl_endpoint from shared.EndpointTester import EndpointTester, decl_endpoint
from shared.testing_utils import response_contains from shared.testing_utils import response_contains
@ -343,6 +343,7 @@ class TestLibraryViewset(EndpointTester):
term_raw='@{X12|plur}', term_raw='@{X12|plur}',
term_resolved='люди' term_resolved='люди'
) )
Attribution.objects.create(container=d2, attribute=x12)
data = {'item_data': {'title': 'Title1337'}, 'items': []} data = {'item_data': {'title': 'Title1337'}, 'items': []}
self.executeNotFound(data, item=self.invalid_item) self.executeNotFound(data, item=self.invalid_item)
@ -351,6 +352,7 @@ class TestLibraryViewset(EndpointTester):
response = self.executeCreated(data, item=self.owned.pk) response = self.executeCreated(data, item=self.owned.pk)
self.assertEqual(response.data['title'], data['item_data']['title']) self.assertEqual(response.data['title'], data['item_data']['title'])
self.assertEqual(len(response.data['items']), 2) self.assertEqual(len(response.data['items']), 2)
self.assertEqual(len(response.data['attribution']), 1)
self.assertEqual(response.data['items'][0]['alias'], x12.alias) self.assertEqual(response.data['items'][0]['alias'], x12.alias)
self.assertEqual(response.data['items'][0]['term_raw'], x12.term_raw) self.assertEqual(response.data['items'][0]['term_raw'], x12.term_raw)
self.assertEqual(response.data['items'][0]['term_resolved'], x12.term_resolved) self.assertEqual(response.data['items'][0]['term_resolved'], x12.term_resolved)

View File

@ -14,7 +14,7 @@ from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from apps.oss.models import Layout, Operation, OperationSchema, PropagationFacade from apps.oss.models import Layout, Operation, OperationSchema, PropagationFacade
from apps.rsform.models import RSFormCached from apps.rsform.models import Attribution, RSFormCached
from apps.rsform.serializers import RSFormParseSerializer from apps.rsform.serializers import RSFormParseSerializer
from apps.users.models import User from apps.users.models import User
from shared import permissions from shared import permissions
@ -157,8 +157,8 @@ class LibraryViewSet(viewsets.ModelViewSet):
serializer = s.LibraryItemCloneSerializer(data=request.data, context={'schema': item}) serializer = s.LibraryItemCloneSerializer(data=request.data, context={'schema': item})
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
data = serializer.validated_data['item_data'] data = serializer.validated_data['item_data']
with transaction.atomic(): with transaction.atomic():
clone = deepcopy(item) clone = deepcopy(item)
clone.pk = None clone.pk = None
@ -171,12 +171,24 @@ class LibraryViewSet(viewsets.ModelViewSet):
clone.access_policy = data.get('access_policy', m.AccessPolicy.PUBLIC) clone.access_policy = data.get('access_policy', m.AccessPolicy.PUBLIC)
clone.location = data.get('location', m.LocationHead.USER) clone.location = data.get('location', m.LocationHead.USER)
clone.save() clone.save()
cst_map: dict[int, int] = {}
cst_list: list[int] = []
need_filter = 'items' in request.data and request.data['items'] need_filter = 'items' in request.data and request.data['items']
for cst in RSFormCached(item).constituentsQ(): for cst in RSFormCached(item).constituentsQ():
if not need_filter or cst.pk in request.data['items']: if not need_filter or cst.pk in request.data['items']:
old_pk = cst.pk
cst.pk = None cst.pk = None
cst.schema = clone cst.schema = clone
cst.save() cst.save()
cst_map[old_pk] = cst.pk
cst_list.append(old_pk)
for attr in Attribution.objects.filter(container__in=cst_list, attribute__in=cst_list):
attr.pk = None
attr.container_id = cst_map[attr.container_id]
attr.attribute_id = cst_map[attr.attribute_id]
attr.save()
return Response( return Response(
status=c.HTTP_201_CREATED, status=c.HTTP_201_CREATED,
data=RSFormParseSerializer(clone).data data=RSFormParseSerializer(clone).data