diff --git a/requirements-dev.txt b/requirements-dev.txt index d9910564..01b58ef8 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -2,4 +2,4 @@ pycodestyle==2.5.0 coveralls==1.8.2 responses==0.10.6 six==1.12.0 -awscli==1.16.234 +awscli==1.16.237 diff --git a/requirements.txt b/requirements.txt index fd1e499c..0c33f6b7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,7 +11,7 @@ Pillow==6.1.0 django-simple-history==2.7.3 djangorestframework-filters==0.11.1 python-decouple==3.1 -django-storages==1.7.1 +django-storages==1.7.2 dj_database_url==0.5.0 zappa==0.47.0 psycopg2==2.7.5 diff --git a/retirement/resources.py b/retirement/resources.py index 1214544e..4451a96f 100644 --- a/retirement/resources.py +++ b/retirement/resources.py @@ -5,7 +5,7 @@ from import_export.widgets import (ForeignKeyWidget, ManyToManyWidget, DateTimeWidget) -from store.models import OrderLine +from store.models import OrderLine, OrderLineBaseProduct, OptionProduct from .models import Reservation, Retreat User = get_user_model() @@ -263,3 +263,52 @@ class Meta: 'city', 'phone' ) + + +class OptionProductResource(resources.ModelResource): + + last_name = fields.Field( + column_name='last_name', + attribute='order_line', + widget=ForeignKeyWidget(User, 'order__user__last_name'), + ) + + first_name = fields.Field( + column_name='first_name', + attribute='order_line', + widget=ForeignKeyWidget(User, 'order__user__first_name'), + ) + + email = fields.Field( + column_name='email', + attribute='order_line', + widget=ForeignKeyWidget(User, 'order__user__email'), + ) + + option_name = fields.Field( + column_name='name', + attribute='option', + widget=ForeignKeyWidget(OptionProduct, 'name') + ) + + quantity = fields.Field( + column_name='quantity', + attribute='quantity' + ) + + class Meta: + model = OrderLineBaseProduct + fields = ( + 'last_name', + 'first_name', + 'email', + 'option_name', + 'quantity' + ) + export_order = ( + 'last_name', + 'first_name', + 'email', + 'option_name', + 'quantity' + ) diff --git a/retirement/views.py b/retirement/views.py index fe986214..6fda5a0d 100644 --- a/retirement/views.py +++ b/retirement/views.py @@ -22,7 +22,7 @@ from blitz_api.models import ExportMedia from blitz_api.serializers import ExportMediaSerializer from store.exceptions import PaymentAPIError -from store.models import Refund +from store.models import Refund, OptionProduct, OrderLineBaseProduct from store.services import refund_amount, PAYSAFE_EXCEPTION from . import permissions, serializers @@ -30,7 +30,7 @@ WaitQueueNotification, RetreatInvitation) from .resources import (ReservationResource, RetreatResource, WaitQueueNotificationResource, WaitQueueResource, - RetreatReservationResource) + RetreatReservationResource, OptionProductResource) from .services import (send_retreat_7_days_email, send_post_retreat_email, ) @@ -216,6 +216,39 @@ def export_participation(self, request, pk=None): return response + @action(detail=True, permission_classes=[IsAdminUser]) + def export_options(self, request, pk=None): + + retreat: Retreat = self.get_object() + # Order queryset by ascending id, thus by descending age too + queryset = OrderLineBaseProduct.objects.filter( + order_line__object_id=retreat.id, + order_line__content_type__model='retreat') + # Build dataset using paginated queryset + dataset = OptionProductResource().export(queryset) + + date_file = LOCAL_TIMEZONE.localize(datetime.now()) \ + .strftime("%Y%m%d-%H%M%S") + filename = f'export-option-{retreat.name}-{date_file}.xls' + + new_exprt = ExportMedia.objects.create() + content = ContentFile(dataset.xls) + new_exprt.file.save(filename, content) + + export_url = ExportMediaSerializer( + new_exprt, + context={'request': request} + ).data.get('file') + + response = Response( + status=status.HTTP_200_OK, + data={ + 'file_url': export_url + } + ) + + return response + class PictureViewSet(viewsets.ModelViewSet): """