added product_request mechanism
rodzic
3a8ffd73c5
commit
24f98cc3de
|
@ -225,7 +225,6 @@ class Product(ClusterableModel):
|
||||||
return main_image
|
return main_image
|
||||||
return self.product_images.first()
|
return self.product_images.first()
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tags(self):
|
def tags(self):
|
||||||
return self.template.tags.all()
|
return self.template.tags.all()
|
||||||
|
|
|
@ -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}")
|
|
@ -18,10 +18,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<a class="btn btn-outline-primary btn-lg" href="{% url 'product-configure' variant.template.pk %}">Wróć do konfiguratora</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<section class="h-100">
|
<section class="h-100">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -51,14 +47,18 @@
|
||||||
Jeżeli jesteś zainteresowany tą konfiguracją złóż zapytanie ofertowe.
|
Jeżeli jesteś zainteresowany tą konfiguracją złóż zapytanie ofertowe.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-12 text-end">
|
||||||
|
<h3>Cena: {{variant.price}} zł</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="row mt-3">
|
<div class="row mt-3">
|
||||||
<div class="col-3 ">
|
<div class="col-6 ">
|
||||||
{% if variant.available %}
|
<a class="btn btn-outline-primary btn-lg" href="{% url 'product-configure' variant.template.pk %}">Wróć do konfiguratora</a>
|
||||||
<h3>Cena: {{variant.price}} zł</h3>
|
|
||||||
{% endif %}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-9 text-end">
|
<div class="col-6 text-end">
|
||||||
|
|
||||||
{% if variant.available %}
|
{% if variant.available %}
|
||||||
<button class="btn btn-outline-success btn-lg add-to-cart-button" data-product-id="{{variant.id}}"
|
<button class="btn btn-outline-success btn-lg add-to-cart-button" data-product-id="{{variant.id}}"
|
||||||
|
@ -67,7 +67,10 @@
|
||||||
Zamów produkt
|
Zamów produkt
|
||||||
</button>
|
</button>
|
||||||
{% else %}
|
{% else %}
|
||||||
<button class="btn btn-outline-success btn-lg">Złóż zapytanie ofertowe</button>
|
<form method="POST" action="">
|
||||||
|
{% csrf_token %}
|
||||||
|
<button class="btn btn-outline-success btn-lg" type="submit">Złóż zapytanie ofertowe</button>
|
||||||
|
</form>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -28,4 +28,4 @@
|
||||||
<a class="btn btn-outline-primary" href="{{store_url}}">Powrót do sklepu</a>
|
<a class="btn btn-outline-primary" href="{{store_url}}">Powrót do sklepu</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,11 +1,98 @@
|
||||||
from django.test import TestCase
|
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):
|
class ConfigureProductViewTestCase(TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
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):
|
||||||
|
...
|
||||||
|
|
|
@ -4,7 +4,10 @@ from django.views.generic import (
|
||||||
TemplateView,
|
TemplateView,
|
||||||
View
|
View
|
||||||
)
|
)
|
||||||
from django.shortcuts import render
|
from django.shortcuts import (
|
||||||
|
render,
|
||||||
|
get_object_or_404
|
||||||
|
)
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
|
@ -13,6 +16,7 @@ from rest_framework.viewsets import ViewSet
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
|
||||||
|
from store.tasks import send_produt_request_email
|
||||||
from store.cart import SessionCart
|
from store.cart import SessionCart
|
||||||
from store.serializers import (
|
from store.serializers import (
|
||||||
CartSerializer,
|
CartSerializer,
|
||||||
|
@ -96,14 +100,12 @@ class ConfigureProductView(View):
|
||||||
template_name = "store/configure_product.html"
|
template_name = "store/configure_product.html"
|
||||||
|
|
||||||
def get_context_data(self, pk: int, **kwargs: Any) -> Dict[str, Any]:
|
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)
|
form = ProductTemplateConfigForm(template=template)
|
||||||
context = {
|
context = {
|
||||||
"template": template,
|
"template": template,
|
||||||
"available_variants": Product.objects.filter(template__pk=pk),
|
|
||||||
"form": form
|
"form": form
|
||||||
}
|
}
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get(self, request, pk: int, *args, **kwargs):
|
def get(self, request, pk: int, *args, **kwargs):
|
||||||
|
@ -112,7 +114,7 @@ class ConfigureProductView(View):
|
||||||
|
|
||||||
def post(self, request, pk: int, *args, **kwargs):
|
def post(self, request, pk: int, *args, **kwargs):
|
||||||
# first select template
|
# first select template
|
||||||
template = ProductTemplate.objects.get(pk=pk)
|
template = get_object_or_404(ProductTemplate, pk=pk)
|
||||||
form = ProductTemplateConfigForm(template=template, data=request.POST)
|
form = ProductTemplateConfigForm(template=template, data=request.POST)
|
||||||
if not form.is_valid():
|
if not form.is_valid():
|
||||||
context = self.get_context_data(pk)
|
context = self.get_context_data(pk)
|
||||||
|
@ -125,16 +127,26 @@ class ConfigureProductView(View):
|
||||||
class ConfigureProductSummaryView(View):
|
class ConfigureProductSummaryView(View):
|
||||||
template_name = "store/configure_product_summary.html"
|
template_name = "store/configure_product_summary.html"
|
||||||
|
|
||||||
def get(self, request, variant_pk: int, *args, **kwargs):
|
def get_context_data(self, variant_pk):
|
||||||
variant = Product.objects.get(pk=variant_pk)
|
variant = get_object_or_404(Product, pk=variant_pk)
|
||||||
|
return {
|
||||||
context = {
|
|
||||||
"variant": variant,
|
"variant": variant,
|
||||||
"params_values": variant.params.all(),
|
"params_values": variant.params.all(),
|
||||||
"store_url": ProductListPage.objects.first().get_url()
|
"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)
|
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):
|
class OrderView(View):
|
||||||
template_name = "store/order.html"
|
template_name = "store/order.html"
|
||||||
|
|
Ładowanie…
Reference in New Issue