Skip to content

Commit

Permalink
Merge pull request #77 from dev-lymar/feat/dev-adding-sending-by-email
Browse files Browse the repository at this point in the history
Feat/dev adding sending by email
  • Loading branch information
dev-lymar committed Jul 1, 2024
2 parents ff943dd + 8f1ba2b commit 42f4d36
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 9 deletions.
12 changes: 12 additions & 0 deletions makedoc/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,27 @@
from rest_framework import serializers


class EmailInputSerializer(serializers.Serializer[Any]):
"""
Serializer for validating email input.
"""

email = serializers.EmailField()


class DocumentsSimpleSerializer(serializers.Serializer[Any]):
"""
A simple serializer for document data.
"""

pass


class OrderItemSerializer(serializers.Serializer[Any]):
"""
A serializer for order items.
"""

product_id = serializers.IntegerField()
quantity = serializers.FloatField(min_value=0.001)
discount = serializers.IntegerField(required=False, default=0, max_value=100)
Expand All @@ -23,6 +33,7 @@ class DataDocSerializer(serializers.Serializer[Any]):
"""
A serializer for document data.
"""

delivery_type = serializers.CharField()
client_id = serializers.IntegerField()
items = serializers.ListField(child=OrderItemSerializer())
Expand All @@ -35,4 +46,5 @@ class FileNameSerializer(serializers.Serializer[Any]):
"""
A serializer for file names.
"""

file_name = serializers.CharField(required=False, allow_blank=True)
26 changes: 26 additions & 0 deletions makedoc/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from celery import shared_task
from django.conf import settings
from django.core.mail import EmailMessage


@shared_task
Expand All @@ -27,3 +28,28 @@ def delete_files():
return f"Failed to delete {item_path}. Reason {e}"

return "Successfully deleted all user folders"


@shared_task(bind=True, max_retries=3)
def send_email_with_attachment(self, email, file_path, full_name):
"""
Task to send an email with an attachment.
"""
if not os.path.exists(file_path):
raise FileNotFoundError(f"File {file_path} does not exist")

email_message = EmailMessage(
subject=f"{full_name}",
body="Documents archive",
from_email=settings.EMAIL_HOST_USER,
to=[email],
)

try:
with open(file_path, "rb") as f:
email_message.attach(os.path.basename(file_path), f.read(), "application/zip")

email_message.send()

except Exception as e:
self.retry(exc=e, countdown=60)
6 changes: 3 additions & 3 deletions makedoc/tests/test_views_makedoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test__data_doc_view__authorized_user_post_data_response_is_correct(

@pytest.mark.django_db
def test__create_docs_view__authorized_user_get_valid_data(authorized_client, make_test_data):
url = reverse("file")
url = reverse("file-make")
cache_key = f"validated_data_{authorized_client.user.id}"
cache.set(cache_key, json.dumps(make_test_data), timeout=120)
response = authorized_client.get(url)
Expand All @@ -44,15 +44,15 @@ def test__create_docs_view__authorized_user_get_valid_data(authorized_client, ma

@pytest.mark.django_db
def test__create_docs_view__authorized_user_get_no_data(authorized_client):
url = reverse("file")
url = reverse("file-make")
response = authorized_client.get(url)
assert response.status_code == 400
assert response.json() == {"error": "No data found in cache"}


@pytest.mark.django_db
def test__download_doc_view__returns_404_when_no_file_exists(authorized_client):
url = reverse("downloadfile")
url = reverse("download-file")
response = authorized_client.post(url, {}, format="json")
assert response.status_code == 404
assert response.json() == {"error": "No file found"}
7 changes: 4 additions & 3 deletions makedoc/urls.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from django.urls import path

from .views import DataDocAPIView, CreateDocsAPIView, DownloadDocAPIView
from .views import DataDocAPIView, CreateDocsAPIView, DownloadDocAPIView, SendArchiveAPIView

urlpatterns = [
path("filemake/", CreateDocsAPIView.as_view(), name="file"),
path("downloadfile/", DownloadDocAPIView.as_view(), name="downloadfile"),
path("file-make/", CreateDocsAPIView.as_view(), name="file-make"),
path("download-file/", DownloadDocAPIView.as_view(), name="download-file"),
path("data/", DataDocAPIView.as_view(), name="data"),
path("send-archive/", SendArchiveAPIView.as_view(), name="send-archive"),
]
39 changes: 36 additions & 3 deletions makedoc/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@
from rest_framework.views import APIView

from makedoc.services import Documents
from .serializers import DataDocSerializer, DocumentsSimpleSerializer, FileNameSerializer
from .serializers import (
DataDocSerializer,
DocumentsSimpleSerializer,
FileNameSerializer,
EmailInputSerializer,
)
from .tasks import send_email_with_attachment


class CreateDocsAPIView(APIView):
Expand Down Expand Up @@ -78,8 +84,6 @@ def post(self, request, *args, **kwargs):
if not file_name:
return Response({"error": "No file found"}, status=status.HTTP_404_NOT_FOUND)

cache.delete(cache_key)

file_path = os.path.join("makedoc", "tempdoc", str(request.user.id), file_name)

if not os.path.exists(file_path):
Expand Down Expand Up @@ -114,3 +118,32 @@ def post(self, request, *args, **kwargs):
cache.set(cache_key, json.dumps(validated_data), 120)

return Response({"Success": True}, status=status.HTTP_200_OK)


class SendArchiveAPIView(APIView):
"""
API endpoint to send an email with an attachment.
"""

def post(self, request, *args, **kwargs):
serializer = EmailInputSerializer(data=request.data)
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

email = serializer.validated_data.get("email")
full_name = request.user.full_name

cache_key = f"last_created_file_user:{request.user.id}"
file_name = cache.get(cache_key)

if not file_name:
return Response({"error": "No file found in cache"}, status=status.HTTP_404_NOT_FOUND)

file_path = os.path.join("makedoc", "tempdoc", str(request.user.id), file_name)

if not os.path.exists(file_path):
return Response({"error": "File path not found!"}, status=status.HTTP_404_NOT_FOUND)

send_email_with_attachment.delay(email, file_path, full_name=full_name)

return Response({"message": "Email will be sent shortly."}, status=status.HTTP_200_OK)

0 comments on commit 42f4d36

Please sign in to comment.