diff --git a/artel/store/models.py b/artel/store/models.py index ad9890b..1ab34f0 100644 --- a/artel/store/models.py +++ b/artel/store/models.py @@ -225,7 +225,6 @@ class Product(ClusterableModel): return main_image return self.product_images.first() - @property def tags(self): return self.template.tags.all() diff --git a/artel/store/tasks.py b/artel/store/tasks.py new file mode 100644 index 0000000..94e28f8 --- /dev/null +++ b/artel/store/tasks.py @@ -0,0 +1,30 @@ +import logging +from django.conf import settings + +from mailings.models import OutgoingEmail +from store.models import Product + + +logger = logging.getLogger(__name__) + +# TODO - those should be modified to be celery tasks + +def send_produt_request_email(variant_pk: int): + try: + variant = Product.objects.get(pk=variant_pk) + except Product.DoesNotExist: + logger.exception(f"Product with pk={variant_pk} does not exist") + + try: + send = OutgoingEmail.objects.send( + template_name="product_request", + subject="Zapytanie o produkt", + recipient=variant.template.author.email, + context={"product": variant}, + sender=settings.DEFAULT_FROM_EMAIL + ) + except Exception as e: + logger.exception(f"Could not send email for variant pk={variant_pk}, exception: {e} has occured") + else: + if not send: + logger.exception(f"Could not send email for variant pk={variant_pk}") diff --git a/artel/store/templates/store/configure_product_summary.html b/artel/store/templates/store/configure_product_summary.html index 6707231..f9ff2b2 100644 --- a/artel/store/templates/store/configure_product_summary.html +++ b/artel/store/templates/store/configure_product_summary.html @@ -18,10 +18,6 @@ -
- Wróć do konfiguratora -
-
@@ -51,14 +47,18 @@ Jeżeli jesteś zainteresowany tą konfiguracją złóż zapytanie ofertowe.
+ {% else %} +
+
+

Cena: {{variant.price}} zł

+
+
{% endif %}
-
- {% if variant.available %} -

Cena: {{variant.price}} zł

- {% endif %} + -
+
{% if variant.available %} +
+ {% csrf_token %} + +
{% endif %}
diff --git a/artel/store/templates/store/order_success.html b/artel/store/templates/store/order_success.html index 58f3ebc..3549124 100644 --- a/artel/store/templates/store/order_success.html +++ b/artel/store/templates/store/order_success.html @@ -28,4 +28,4 @@ Powrót do sklepu
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/artel/store/tests/test_views.py b/artel/store/tests/test_views.py index d5249a2..ca6acb1 100644 --- a/artel/store/tests/test_views.py +++ b/artel/store/tests/test_views.py @@ -1,11 +1,98 @@ from django.test import TestCase +from django.shortcuts import reverse + +from store.models import ( + ProductCategoryParam, + ProductCategoryParamValue, + CategoryParamTypeChoices +) +from store.tests.factories import ( + ProductTemplateFactory, + ProductCategoryFactory, + ProductFactory, + ProductCategoryParamValueFactory +) class ConfigureProductViewTestCase(TestCase): def setUp(self): - ... + super().setUp() + self.category = ProductCategoryFactory() + self.product_template = ProductTemplateFactory(category=self.category) + # create template params and values for those params + self.param1 = ProductCategoryParam.objects.create( + key="Mocowanie", category=self.category, + param_type=CategoryParamTypeChoices.STRING + ) + self.param1_value1 = ProductCategoryParamValueFactory(param=self.param1) + self.param1_value2 = ProductCategoryParamValueFactory(param=self.param1) + self.param2 = ProductCategoryParam.objects.create( + key="Format", category=self.category, + param_type=CategoryParamTypeChoices.STRING + ) + self.param2_value1 = ProductCategoryParamValueFactory(param=self.param2) + self.param2_value2 = ProductCategoryParamValueFactory(param=self.param2) + # create product variant + self.variant1 = ProductFactory( + template=self.product_template + ) + self.variant1.params.set([self.param1_value1, self.param2_value1]) + self.variant1.save() - def test_sdkfsdf(self): - ... + self.variant2 = ProductFactory( + template=self.product_template, + ) + self.variant2.params.set([self.param1_value2, self.param2_value2]) + self.variant2.save() + def test_get_success(self): + response = self.client.get( + reverse("product-configure", args=[self.product_template.pk]), + ) + self.assertEqual(response.status_code, 200) + self.assertTemplateUsed(response, "store/configure_product.html") + + def test_get_failure_wrong_pk(self): + response = self.client.get( + reverse("product-configure", args=[12312]), + ) + self.assertEqual(response.status_code, 404) + + def test_post_success(self): + data = { + self.param1.key: [str(self.param1_value1.pk)], + self.param2.key: [str(self.param2_value1.pk)] + } + response = self.client.post( + reverse("product-configure", args=[self.product_template.pk]), + data=data + ) + self.assertEqual(response.status_code, 302) + self.assertEqual(response.url, reverse("configure-product-summary", args=[self.variant1.pk])) + + def test_post_failure_not_existing_template(self): + data = { + self.param1.key: [str(self.param1_value1.pk)], + self.param2.key: [str(self.param2_value1.pk)] + } + response = self.client.post( + reverse("product-configure", args=[2137]), + data=data + ) + self.assertEqual(response.status_code, 404) + + def test_post_not_existing_config(self): + data = { + self.param1.key: [str(self.param1_value2.pk)], + self.param2.key: [str(self.param2_value1.pk)] + } + response = self.client.post( + reverse("product-configure", args=[self.product_template.pk]), + data=data + ) + self.assertEqual(response.status_code, 302) + + +class ConfigureProductSummaryViewTestCase(TestCase): + ... diff --git a/artel/store/views.py b/artel/store/views.py index 2609d47..336e7c7 100644 --- a/artel/store/views.py +++ b/artel/store/views.py @@ -4,7 +4,10 @@ from django.views.generic import ( TemplateView, View ) -from django.shortcuts import render +from django.shortcuts import ( + render, + get_object_or_404 +) from django.urls import reverse from django.http import HttpResponseRedirect from django.contrib import messages @@ -13,6 +16,7 @@ from rest_framework.viewsets import ViewSet from rest_framework.decorators import action from rest_framework.response import Response +from store.tasks import send_produt_request_email from store.cart import SessionCart from store.serializers import ( CartSerializer, @@ -96,14 +100,12 @@ class ConfigureProductView(View): template_name = "store/configure_product.html" def get_context_data(self, pk: int, **kwargs: Any) -> Dict[str, Any]: - template = ProductTemplate.objects.get(pk=pk) + template = get_object_or_404(ProductTemplate, pk=pk) form = ProductTemplateConfigForm(template=template) context = { "template": template, - "available_variants": Product.objects.filter(template__pk=pk), "form": form } - return context def get(self, request, pk: int, *args, **kwargs): @@ -112,7 +114,7 @@ class ConfigureProductView(View): def post(self, request, pk: int, *args, **kwargs): # first select template - template = ProductTemplate.objects.get(pk=pk) + template = get_object_or_404(ProductTemplate, pk=pk) form = ProductTemplateConfigForm(template=template, data=request.POST) if not form.is_valid(): context = self.get_context_data(pk) @@ -125,16 +127,26 @@ class ConfigureProductView(View): class ConfigureProductSummaryView(View): template_name = "store/configure_product_summary.html" - def get(self, request, variant_pk: int, *args, **kwargs): - variant = Product.objects.get(pk=variant_pk) - - context = { + def get_context_data(self, variant_pk): + variant = get_object_or_404(Product, pk=variant_pk) + return { "variant": variant, "params_values": variant.params.all(), "store_url": ProductListPage.objects.first().get_url() } + + def get(self, request, variant_pk: int, *args, **kwargs): + context = self.get_context_data(variant_pk) return render(request, self.template_name, context) + def post(self, request, variant_pk: int, *args, **kwargs): + # Here just send the email with product request + variant = Product.objects.get(pk=variant_pk) + send_produt_request_email(variant.pk) + messages.success(request, "Zapytanie o produkt zostało wysłane") + context = self.get_context_data(variant_pk) + return HttpResponseRedirect(context["store_url"]) + class OrderView(View): template_name = "store/order.html"