diff --git a/activitystream/filters.py b/activitystream/filters.py index c965297fe0..277789a770 100644 --- a/activitystream/filters.py +++ b/activitystream/filters.py @@ -44,3 +44,12 @@ class ActivityStreamCmsContentFilter(FilterSet): def filter_after(self, queryset, name, value): value = value or '0' return queryset.filter(id__gt=value) + + +class ActivityStreamHCSATFilter(FilterSet): + after = CharFilter(method='filter_after') + + def filter_after(self, queryset, name, value): + value = value or '0.000000' + after_ts = datetime.datetime.fromtimestamp(float(value), tz=datetime.timezone.utc) + return queryset.filter(modified__gt=after_ts) diff --git a/activitystream/pagination.py b/activitystream/pagination.py index 25728dcd9e..a7ebc421d4 100644 --- a/activitystream/pagination.py +++ b/activitystream/pagination.py @@ -56,3 +56,14 @@ def paginate_queryset(self, queryset, request, view=None): self.next_value = page[-1].id if page else '' self.request = request return page + + +class ActivityStreamHCSATPagination(ActivityStreamBasePagination): + page_size = 100 + + def paginate_queryset(self, queryset, request, view=None): + self.has_next = queryset.count() > self.page_size + page = list(queryset[: self.page_size]) + self.next_value = page[-1].modified.timestamp() if page else '' + self.request = request + return page diff --git a/activitystream/serializers.py b/activitystream/serializers.py index ef847e2248..c608b6b4ba 100644 --- a/activitystream/serializers.py +++ b/activitystream/serializers.py @@ -5,7 +5,7 @@ from wagtail.models import Page from wagtail.rich_text import RichText, get_text_for_indexing -from core.models import GreatMedia, MicrositePage +from core.models import HCSAT, GreatMedia, MicrositePage from domestic.models import ArticlePage from export_academy.models import ( Booking, @@ -539,3 +539,46 @@ def to_representation(self, instance): 'videoTitle': instance.video.title if instance.video else None, }, } + + +class ActivityStreamDomesticHCSATUserFeedbackDataSerializer(serializers.ModelSerializer): + """ + Domestic HCSAT Feedback Data serializer for activity stream. + """ + + feedback_submission_date = serializers.DateTimeField(source='created') # noqa: N815 + url = serializers.CharField(source='URL') # noqa: N815 + + class Meta: + model = HCSAT + fields = [ + 'id', + 'feedback_submission_date', + 'url', + 'user_journey', + 'satisfaction_rating', + 'experienced_issues', + 'other_detail', + 'service_improvements_feedback', + 'likelihood_of_return', + 'service_name', + 'service_specific_feedback', + 'service_specific_feedback_other', + ] + + def to_representation(self, instance): + """ + Prefix field names to match activity stream format + """ + prefix = 'dit:domestic:HCSATFeedbackData' + type = 'Update' + + return { + 'id': f'{prefix}:{instance.id}:{type}', + 'type': f'{type}', + 'object': { + 'id': f'{prefix}:{instance.id}', + 'type': prefix, + **{f'{k}': v for k, v in super().to_representation(instance).items()}, + }, + } diff --git a/activitystream/urls.py b/activitystream/urls.py index 3e6c2e70f7..bb089aad82 100644 --- a/activitystream/urls.py +++ b/activitystream/urls.py @@ -56,4 +56,9 @@ skip_ga360(activitystream.views.ActivityStreamExportAcademyVideoOnDemandPageTrackingView.as_view()), name='ukea-videoondemandpagetracking', ), + path( + 'domestic-hcsats/', + skip_ga360(activitystream.views.ActivityStreamDomesticHCSATFeedbackDataView.as_view()), + name='domestic-hcsats', + ), ] diff --git a/activitystream/views.py b/activitystream/views.py index 949b151365..dd5d09edc2 100644 --- a/activitystream/views.py +++ b/activitystream/views.py @@ -18,15 +18,18 @@ ActivityStreamCmsContentFilter, ActivityStreamExpandYourBusinessFilter, ActivityStreamExportAcademyFilter, + ActivityStreamHCSATFilter, PageFilter, ) from activitystream.pagination import ( ActivityStreamCmsContentPagination, ActivityStreamExpandYourBusinessPagination, ActivityStreamExportAcademyPagination, + ActivityStreamHCSATPagination, ) from activitystream.serializers import ( ActivityStreamCmsContentSerializer, + ActivityStreamDomesticHCSATUserFeedbackDataSerializer, ActivityStreamExpandYourBusinessTriageDataSerializer, ActivityStreamExpandYourBusinessUserDataSerializer, ActivityStreamExportAcademyBookingSerializer, @@ -35,7 +38,7 @@ ActivityStreamExportAcademyVideoOnDemandPageTrackingSerializer, PageSerializer, ) -from core.models import MicrositePage +from core.models import HCSAT, MicrositePage from domestic.models import ArticlePage, CountryGuidePage from export_academy.models import ( Booking, @@ -256,3 +259,18 @@ class ActivityStreamExportAcademyBaseView(ActivityStreamBaseView): def get_queryset(self): return self.queryset.order_by('id') + + +class ActivityStreamHCSATBaseView(ActivityStreamBaseView): + filterset_class = ActivityStreamHCSATFilter + pagination_class = ActivityStreamHCSATPagination + + def get_queryset(self): + return self.queryset.order_by('id') + + +class ActivityStreamDomesticHCSATFeedbackDataView(ActivityStreamHCSATBaseView): + """View to list domestic HCSAT feedback data for the activity stream""" + + queryset = HCSAT.objects.all() + serializer_class = ActivityStreamDomesticHCSATUserFeedbackDataSerializer diff --git a/tests/unit/activitystream/test_serializers.py b/tests/unit/activitystream/test_serializers.py index a8df21de67..bfad5bc29a 100644 --- a/tests/unit/activitystream/test_serializers.py +++ b/tests/unit/activitystream/test_serializers.py @@ -8,6 +8,7 @@ from activitystream.serializers import ( ActivityStreamCmsContentSerializer, + ActivityStreamDomesticHCSATUserFeedbackDataSerializer, ActivityStreamExpandYourBusinessTriageDataSerializer, ActivityStreamExpandYourBusinessUserDataSerializer, ActivityStreamExportAcademyBookingSerializer, @@ -23,6 +24,7 @@ from domestic.models import ArticlePage from international_online_offer.models import TriageData, UserData from tests.unit.core.factories import ( + HCSATFactory, LandingPageFactory, MicrositeFactory, MicrositePageFactory, @@ -700,3 +702,35 @@ def test_ukea_videoondemandpagetracking_serializer(): 'modified': instance.modified.isoformat(), }, } + + +@pytest.mark.django_db +def test_domestic_hcsat_feedback_serializer(): + instance = HCSATFactory() + + serializer = ActivityStreamDomesticHCSATUserFeedbackDataSerializer() + output = serializer.to_representation(instance) + + # Remove date due to timezone mismatch + + del output['object']['feedback_submission_date'] + expected = { + 'id': f'dit:domestic:HCSATFeedbackData:{instance.id}:Update', + 'type': 'Update', + 'object': { + 'id': instance.id, + 'type': 'dit:domestic:HCSATFeedbackData', + 'url': instance.URL, + 'user_journey': instance.user_journey, + 'satisfaction_rating': instance.satisfaction_rating, + 'experienced_issues': instance.experienced_issues, + 'other_detail': instance.other_detail, + 'service_improvements_feedback': instance.service_improvements_feedback, + 'likelihood_of_return': instance.likelihood_of_return, + 'service_name': instance.service_name, + 'service_specific_feedback': instance.service_specific_feedback, + 'service_specific_feedback_other': instance.service_specific_feedback_other, + }, + } + + assert output == expected