sforkowany z mtyton/comfy
added data encrption for customer
rodzic
24f98cc3de
commit
3580a3b1e1
|
@ -42,6 +42,11 @@ class PaymentMethodAdmin(ModelAdmin):
|
|||
list_display = ("name", "active")
|
||||
|
||||
|
||||
class DeliveryMethodAdmin(ModelAdmin):
|
||||
model = models.DeliveryMethod
|
||||
list_display = ("name", "active")
|
||||
|
||||
|
||||
class DocumentTemplateAdmin(ModelAdmin):
|
||||
model = models.DocumentTemplate
|
||||
list_display = ("name", )
|
||||
|
@ -58,7 +63,8 @@ class StoreAdminGroup(ModelAdminGroup):
|
|||
ProductTemplateAdmin,
|
||||
ProductAdmin,
|
||||
DocumentTemplateAdmin,
|
||||
PaymentMethodAdmin
|
||||
PaymentMethodAdmin,
|
||||
DeliveryMethodAdmin
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ from typing import (
|
|||
from dataclasses import dataclass
|
||||
from django.http.request import HttpRequest
|
||||
from django.conf import settings
|
||||
from django.core import signing
|
||||
|
||||
from store.models import (
|
||||
Product,
|
||||
|
@ -116,3 +117,25 @@ class SessionCart(BaseCart):
|
|||
def clear(self) -> None:
|
||||
self._cart = {}
|
||||
self.save_cart()
|
||||
|
||||
|
||||
class CustomerData:
|
||||
|
||||
def _encrypt_data(self, data: dict[str, Any]) -> str:
|
||||
signer = signing.Signer()
|
||||
return signer.sign_object(data)
|
||||
|
||||
def _decrypt_data(self, data: str) -> dict[str, Any]:
|
||||
signer = signing.Signer()
|
||||
return signer.unsign_object(data)
|
||||
|
||||
def __init__(self, data: dict[str, Any]=None, encrypted_data: str=None) -> None:
|
||||
self._data = self._encrypt_data(data) if data else encrypted_data
|
||||
|
||||
@property
|
||||
def data(self) -> dict[str, Any]:
|
||||
return self._data
|
||||
|
||||
@property
|
||||
def decrypted_data(self) -> dict[str, Any]:
|
||||
return self._decrypt_data(self._data)
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
from django import forms
|
||||
from phonenumber_field.formfields import PhoneNumberField
|
||||
from phonenumber_field.phonenumber import PhoneNumber
|
||||
from django.db.models import Model
|
||||
|
||||
from store.models import (
|
||||
ProductTemplate,
|
||||
ProductCategoryParamValue,
|
||||
Product
|
||||
Product,
|
||||
PaymentMethod,
|
||||
DeliveryMethod
|
||||
)
|
||||
|
||||
|
||||
|
@ -38,6 +42,27 @@ class CustomerDataForm(forms.Form):
|
|||
choices=(("PL", "Polska"), ), label="Kraj",
|
||||
widget=forms.Select(attrs={"class": "form-control"})
|
||||
)
|
||||
payment_method = forms.ModelChoiceField(
|
||||
queryset=PaymentMethod.objects.filter(active=True), label="Sposób płatności",
|
||||
widget=forms.Select(attrs={"class": "form-control"})
|
||||
)
|
||||
delivery_method = forms.ModelChoiceField(
|
||||
queryset=DeliveryMethod.objects.filter(active=True), label="Sposób dostawy",
|
||||
widget=forms.Select(attrs={"class": "form-control"})
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
"""Clean method should return JSON serializable"""
|
||||
cleaned_data = super().clean()
|
||||
new_cleaned_data = {}
|
||||
for key, value in cleaned_data.items():
|
||||
if isinstance(value, PhoneNumber):
|
||||
new_cleaned_data[key] = str(value)
|
||||
elif isinstance(value, Model):
|
||||
new_cleaned_data[key] = value.pk
|
||||
else:
|
||||
new_cleaned_data[key] = value
|
||||
return new_cleaned_data
|
||||
|
||||
|
||||
class ButtonToggleSelect(forms.RadioSelect):
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# Generated by Django 4.1.9 on 2023-07-22 17:18
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("store", "0011_productparam_delete_templateparamvalue_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="DeliveryMethod",
|
||||
fields=[
|
||||
("id", models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
|
||||
("name", models.CharField(max_length=255)),
|
||||
("description", models.TextField(blank=True)),
|
||||
("price", models.FloatField(default=0)),
|
||||
("active", models.BooleanField(default=True)),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="order",
|
||||
name="uuid",
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="product",
|
||||
name="uuid",
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="order",
|
||||
name="delivery_method",
|
||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to="store.deliverymethod"),
|
||||
),
|
||||
]
|
|
@ -1,23 +0,0 @@
|
|||
# Generated by Django 4.1.9 on 2023-07-20 16:50
|
||||
|
||||
from django.db import migrations, models
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("store", "0011_productparam_delete_templateparamvalue_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="order",
|
||||
name="uuid",
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="product",
|
||||
name="uuid",
|
||||
field=models.UUIDField(default=uuid.uuid4, editable=False),
|
||||
),
|
||||
]
|
|
@ -432,9 +432,22 @@ class PaymentMethod(models.Model):
|
|||
description = models.TextField(blank=True)
|
||||
active = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
class DeliveryMethod(models.Model):
|
||||
name = models.CharField(max_length=255)
|
||||
description = models.TextField(blank=True)
|
||||
price = models.FloatField(default=0)
|
||||
active = models.BooleanField(default=True)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.name
|
||||
|
||||
|
||||
class Order(models.Model):
|
||||
payment_method = models.ForeignKey(PaymentMethod, on_delete=models.CASCADE)
|
||||
delivery_method = models.ForeignKey(DeliveryMethod, on_delete=models.CASCADE, null=True)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
updated_at = models.DateTimeField(auto_now=True)
|
||||
sent = models.BooleanField(default=False)
|
||||
|
@ -449,10 +462,12 @@ class Order(models.Model):
|
|||
|
||||
@property
|
||||
def total_price(self) -> Decimal:
|
||||
return sum(
|
||||
price = sum(
|
||||
[order_product.product.price * order_product.quantity
|
||||
for order_product in self.products.all()]
|
||||
)
|
||||
delivery_price = self.delivery_method.price if self.delivery_method else 5.0
|
||||
return price + delivery_price
|
||||
|
||||
@property
|
||||
def total_price_words(self) -> str:
|
||||
|
|
|
@ -8,9 +8,9 @@
|
|||
<div class="container pt-4">
|
||||
<div class="row">
|
||||
<div class="col-12 px-4">
|
||||
<h1>Twoje dane</h1>
|
||||
<hr class="mt-1" />
|
||||
<h2>Twoje dane</h2>
|
||||
</div>
|
||||
<hr class="mt-2" />
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="row mx-4">
|
||||
|
@ -42,12 +42,13 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3 mx-4">
|
||||
|
||||
<div class="col-12">
|
||||
<label class="order-form-label">Dane Kontaktowe</label>
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 px-4">
|
||||
<h2>Dane do wysyłki</h2>
|
||||
</div>
|
||||
<hr class="mt-1" />
|
||||
<hr class="mt-2" />
|
||||
</div>
|
||||
<div class="row mt-3 mx-4">
|
||||
<div class="col-sm-6 mt-2 pe-sm-2">
|
||||
<div class="form-outline">
|
||||
<label class="form-label" for="{{form.street.id}}">{{form.street.label}}</label>
|
||||
|
@ -72,7 +73,30 @@
|
|||
{{form.zip_code}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 px-4">
|
||||
<h2>Płatność i wysyłka</h2>
|
||||
</div>
|
||||
<hr class="mt-2" />
|
||||
</div>
|
||||
|
||||
<div class="row mt-3 mx-4">
|
||||
<div class="col-sm-12 mt-2 pe-sm-2">
|
||||
<div class="form-outline">
|
||||
<label class="form-label" for="{{form.street.id}}">{{form.payment_method.label}}</label>
|
||||
{{form.payment_method}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 mt-2 pe-sm-2">
|
||||
<div class="form-outline">
|
||||
<label class="form-label" for="{{form.street.id}}">{{form.delivery_method.label}}</label>
|
||||
{{form.delivery_method}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 text-end mt-3">
|
||||
<div class="form-outline">
|
||||
<input type="submit" value="Dalej" class="btn btn-success btn-lg">
|
||||
|
|
|
@ -11,13 +11,15 @@ from django.shortcuts import (
|
|||
from django.urls import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.contrib import messages
|
||||
from django.forms import modelformset_factory
|
||||
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.cart import (
|
||||
SessionCart,
|
||||
CustomerData
|
||||
)
|
||||
from store.serializers import (
|
||||
CartSerializer,
|
||||
CartProductAddSerializer
|
||||
|
@ -174,9 +176,8 @@ class OrderView(View):
|
|||
context = self.get_context_data()
|
||||
context["form"] = form
|
||||
return render(request, self.template_name, context)
|
||||
customer_data = form.data
|
||||
# TODO - add encryption
|
||||
request.session["customer_data"] = customer_data
|
||||
customer_data = CustomerData(data=form.cleaned_data)
|
||||
request.session["customer_data"] = customer_data.data
|
||||
return HttpResponseRedirect(reverse("order-confirm"))
|
||||
|
||||
|
||||
|
@ -184,7 +185,9 @@ class OrderConfirmView(View):
|
|||
template_name = "store/order_confirm.html"
|
||||
|
||||
def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
|
||||
customer_data = self.request.session["customer_data"]
|
||||
customer_data = CustomerData(
|
||||
encrypted_data=self.request.session["customer_data"]
|
||||
).decrypted_data
|
||||
return {
|
||||
"cart": SessionCart(self.request),
|
||||
"customer_data": customer_data
|
||||
|
@ -193,7 +196,7 @@ class OrderConfirmView(View):
|
|||
def get(self, request, *args, **kwargs):
|
||||
cart = SessionCart(self.request)
|
||||
if cart.is_empty():
|
||||
# TODO - messages
|
||||
messages.error(request, "Twój koszyk jest pusty")
|
||||
return HttpResponseRedirect(reverse("cart"))
|
||||
return render(request, self.template_name, self.get_context_data())
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue