Skip to content

Commit

Permalink
Merge pull request #1909 from unicef/sharing-documents
Browse files Browse the repository at this point in the history
Add TPM Activity endpoint to handling linking attachments
  • Loading branch information
robertavram authored Oct 25, 2018
2 parents de8b6fc + 8f9ca01 commit aef1ce5
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/etools/applications/attachments/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ def assert_keys(self, response):
"object_link",
"filename",
"file_type",
"file_type_id",
"file_link",
"uploaded_by",
"created",
Expand Down
19 changes: 17 additions & 2 deletions src/etools/applications/tpm/serializers/attachments.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from django.utils.translation import ugettext as _

from rest_framework import serializers
from unicef_attachments.fields import FileTypeModelChoiceField
from unicef_attachments.models import FileType
from unicef_attachments.serializers import BaseAttachmentSerializer
from unicef_attachments.models import AttachmentLink, FileType
from unicef_attachments.serializers import AttachmentLinkSerializer, BaseAttachmentSerializer


class TPMPartnerAttachmentsSerializer(BaseAttachmentSerializer):
Expand Down Expand Up @@ -57,3 +58,17 @@ class Meta(BaseAttachmentSerializer.Meta):
def create(self, validated_data):
validated_data['code'] = 'visit_attachments'
return super().create(validated_data)


class TPMActivityAttachmentLinkSerializer(serializers.Serializer):
attachments = AttachmentLinkSerializer(many=True, allow_empty=False)

def create(self, validated_data):
links = []
for attachment in validated_data["attachments"]:
links.append(AttachmentLink.objects.create(
attachment=attachment["attachment"],
content_type=self.context["content_type"],
object_id=self.context["object_id"],
))
return {"attachments": links}
45 changes: 40 additions & 5 deletions src/etools/applications/tpm/tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@

from datetime import datetime

from django.core.files.uploadedfile import SimpleUploadedFile
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from factory import fuzzy

from factory import fuzzy
from rest_framework import status
from unicef_attachments.models import AttachmentLink

from etools.applications.action_points.tests.factories import ActionPointFactory
from etools.applications.attachments.tests.factories import AttachmentFileTypeFactory, AttachmentFactory
from etools.applications.attachments.tests.factories import AttachmentFactory, AttachmentFileTypeFactory
from etools.applications.EquiTrack.tests.cases import BaseTenantTestCase
from etools.applications.partners.models import PartnerType
from etools.applications.reports.tests.factories import SectionFactory
from etools.applications.tpm.models import TPMVisit, ThirdPartyMonitor
from etools.applications.tpm.models import ThirdPartyMonitor, TPMVisit
from etools.applications.tpm.tests.base import TPMTestCaseMixin
from etools.applications.tpm.tests.factories import TPMPartnerFactory, TPMVisitFactory, UserFactory, _FUZZY_END_DATE
from etools.applications.tpm.tests.factories import _FUZZY_END_DATE, TPMPartnerFactory, TPMVisitFactory, UserFactory
from etools.applications.utils.common.tests.test_utils import TestExportMixin


Expand Down Expand Up @@ -761,3 +761,38 @@ def test_add(self):
)
self.assertEqual(list_response.status_code, status.HTTP_200_OK)
self.assertEqual(len(list_response.data['results']), attachments_num + 1)


class TestActivityAttachmentLinkView(TPMTestCaseMixin, BaseTenantTestCase):
@classmethod
def setUpTestData(cls):
super().setUpTestData()

cls.visit = TPMVisitFactory(
status='draft',
tpm_partner=cls.tpm_user.tpmpartners_tpmpartnerstaffmember.tpm_partner,
tpm_partner_focal_points=[cls.tpm_user.tpmpartners_tpmpartnerstaffmember],
tpm_activities__count=1
)
cls.activity = cls.visit.tpm_activities.first()
partner = TPMPartnerFactory()
cls.attachment = AttachmentFactory(content_object=partner)

def test_add(self):
links_qs = AttachmentLink.objects
self.assertEqual(links_qs.count(), 0)
create_response = self.forced_auth_req(
'post',
reverse('tpm:activity-links', args=[self.activity.pk]),
user=self.pme_user,
data={'attachments': [{'attachment': self.attachment.pk}]}
)
self.assertEqual(create_response.status_code, status.HTTP_201_CREATED)

list_response = self.forced_auth_req(
'get',
reverse('tpm:activity-links', args=[self.activity.pk]),
user=self.pme_user
)
self.assertEqual(list_response.status_code, status.HTTP_200_OK)
self.assertEqual(links_qs.count(), 1)
7 changes: 6 additions & 1 deletion src/etools/applications/tpm/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from unicef_restlib.routers import NestedComplexRouter

from etools.applications.tpm.views import (
ActivityAttachmentLinksView,
ActivityAttachmentsViewSet,
ActivityReportAttachmentsViewSet,
PartnerAttachmentsViewSet,
Expand Down Expand Up @@ -36,7 +37,6 @@
base_name='activity-attachments')
visit_attachments_api.register('activities/report-attachments', ActivityReportAttachmentsViewSet,
base_name='activity-report-attachments')

tpm_action_points_api = NestedComplexRouter(tpm_visits_api, r'visits', lookup='tpm_activity__tpm_visit')
tpm_action_points_api.register(r'action-points', TPMActionPointViewSet, base_name='action-points')

Expand All @@ -49,4 +49,9 @@
url(r'^', include(tpm_action_points_api.urls)),
url(r'^', include(visit_attachments_api.urls)),
url(r'^', include(tpm_visits_api.urls)),
url(
r'^visits/activities/(?P<object_pk>\d+)/links',
view=ActivityAttachmentLinksView.as_view(),
name='activity-links'
)
]
48 changes: 47 additions & 1 deletion src/etools/applications/tpm/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
from easy_pdf.rendering import render_to_pdf_response
from rest_framework import generics, mixins, viewsets
from rest_framework.decorators import action
from rest_framework.exceptions import NotFound
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from unicef_attachments.models import Attachment
from unicef_attachments.models import Attachment, AttachmentLink
from unicef_attachments.serializers import AttachmentLinkSerializer
from unicef_restlib.pagination import DynamicPageNumberPagination
from unicef_restlib.views import MultiSerializerViewSetMixin, NestedViewSetMixin, SafeTenantViewSetMixin

Expand Down Expand Up @@ -57,6 +59,7 @@
from etools.applications.tpm.serializers.attachments import (
ActivityAttachmentsSerializer,
ActivityReportSerializer,
TPMActivityAttachmentLinkSerializer,
TPMPartnerAttachmentsSerializer,
TPMVisitAttachmentsSerializer,
TPMVisitReportAttachmentsSerializer,
Expand Down Expand Up @@ -623,3 +626,46 @@ def get_parent_filter(self):

def perform_create(self, serializer):
serializer.save(content_type=ContentType.objects.get_for_model(TPMActivity))


class ActivityAttachmentLinksView(generics.ListCreateAPIView):
metadata_class = PermissionBasedMetadata
serializer_class = TPMActivityAttachmentLinkSerializer
permission_classes = [IsAuthenticated]

def set_content_object(self):
try:
self.content_type = ContentType.objects.get_by_natural_key(
"tpm",
"tpmactivity",
)
except ContentType.DoesNotExist:
raise NotFound()

try:
self.object_id = self.kwargs.get("object_pk")
model_cls = self.content_type.model_class()
self.content_object = model_cls.objects.get(
pk=self.object_id
)
except model_cls.DoesNotExist:
raise NotFound()

def get_serializer_context(self):
self.set_content_object()
context = super().get_serializer_context()
context["content_type"] = self.content_type
context["object_id"] = self.object_id
return context

def get_queryset(self):
self.set_content_object()
return AttachmentLink.objects.filter(
content_type=self.content_type,
object_id=self.object_id,
)

def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
serializer = AttachmentLinkSerializer(queryset, many=True)
return Response(serializer.data)
3 changes: 2 additions & 1 deletion src/requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ djangorestframework-recursive==0.1.2
djangorestframework-xml==1.3
djangorestframework==3.8.2
drf-nested-routers==0.90.2
drf-querystringfilter==1.0.0 # via unicef-attachments
drfpasswordless==1.2
et-xmlfile==1.0.1 # via openpyxl
etools-validator==0.3.2
Expand Down Expand Up @@ -94,7 +95,7 @@ static3==0.7.0 # via dj-static
tablib==0.12.1 # via django-import-export
tenant-schemas-celery==0.1.7
tornado==4.2.0 # via flower
unicef-attachments==0.3.0
unicef-attachments==0.4.1
unicef-djangolib==0.5
unicef-locations==1.4.1
unicef_notification==0.2.0
Expand Down
2 changes: 1 addition & 1 deletion src/requirements/input/base.in
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pyyaml==3.12
psycopg2==2.7.5
raven==6.9
tenant-schemas-celery==0.1.7
unicef-attachments==0.3.0
unicef-attachments==0.4.1
unicef-djangolib==0.5
unicef-locations==1.4.1
unicef_notification==0.2.0
Expand Down
3 changes: 2 additions & 1 deletion src/requirements/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ djangorestframework==3.8.2
docutils==0.14 # via sphinx
drf-api-checker==0.3.0
drf-nested-routers==0.90.2
drf-querystringfilter==1.0.0
drfpasswordless==1.2
et-xmlfile==1.0.1
etools-validator==0.3.2
Expand Down Expand Up @@ -139,7 +140,7 @@ text-unidecode==1.2 # via faker
tornado==4.2.0
tox==3.0.0
traitlets==4.3.2 # via ipython
unicef-attachments==0.3.0
unicef-attachments==0.4.1
unicef-djangolib==0.5
unicef-locations==1.4.1
unicef_notification==0.2.0
Expand Down

0 comments on commit aef1ce5

Please sign in to comment.