Aula 63 – Loja Online – Finalizando o Checkout
Aula 63 – Loja Online – Checkout
Voltar para página principal do blog
Todas as aulas desse curso
Aula 62 Aula 64
Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook
Esse é o link do código fluente no Pinterest
Meus links de afiliados:
Hostinger
Digital Ocean
One.com
Melhore seu NETWORKING
https://digitalinnovation.one/
Participe de comunidades de desenvolvedores:
Fiquem a vontade para me adicionar ao linkedin.
E também para me seguir no https://github.com/toticavalcanti.
Código final da aula:
https://github.com/toticavalcanti
Quer aprender python3 de graça e com certificado? Acesse então:
https://workover.com.br/python-codigo-fluente
Toti:
https://www.youtube.com/channel/UCUEtjLuDpcOvR3mIUr-viOA
Backing track / Play-along:
https://www.youtube.com/channel/UCT3TryVMqTqYBjf5g5WAHfA
Código Fluente
https://www.youtube.com/channel/UCgn-O-88XBAwdG9gUWkkb0w
Putz!
https://www.youtube.com/channel/UCZXop2-CECwyFYmHbhnAkAw
Aula 63 – Loja Online – Finalizando o Checkout
Criamos um objeto carrinho no views.py do carts:
def cart_home(request):
cart_obj, new_obj = Cart.objects.new_or_get(request)
return render(request, "carts/home.html", {"cart": cart_obj})
Temos o método de atualização do carrinho:
def cart_update(request):
product_id = request.POST.get('product_id')
if product_id is not None:
try:
product_obj = Product.objects.get(id=product_id)
except Product.DoesNotExist:
print("Mostrar mensagem ao usuário, esse produto acabou!")
return redirect("cart:home")
cart_obj, new_obj = Cart.objects.new_or_get(request)
if product_obj in cart_obj.products.all():
cart_obj.products.remove(product_obj)
else:
cart_obj.products.add(product_obj) # cart_obj.products.add(product_id)
request.session['cart_items'] = cart_obj.products.count()
# return redirect(product_obj.get_absolute_url())
return redirect("cart:home")
No model.py do carts na classe CartManager função new_or_get() na linha 25 temos:
request.session['cart_id'] = cart_obj.id
Precisamos trazer esse objeto carrinho para o views.py do carts, onde teremos um método para finalizar o pedido, e nele iremos deletar o carrinho com aquele id específico, uma vez que o pedido foi concluído.
Precisaremos fazer o update do status do order para: done (concluído) ou paid (pago).
E também precisaremos redirecionar o usuário para uma página de sucesso.
Então vamos começar a implementar isso.
Abra o views.py do cart e faça as modificações indicadas em azul no código abaixo.
django_ecommerce/e_commerce/carts/views.py
from django.shortcuts import render, redirect
from accounts.forms import LoginForm, GuestForm
from accounts.models import GuestEmail
from addresses.forms import AddressForm
from addresses.models import Address
from billing.models import BillingProfile
from orders.models import Order
from products.models import Product
from .models import Cart
def cart_home(request):
cart_obj, new_obj = Cart.objects.new_or_get(request)
return render(request, "carts/home.html", {"cart": cart_obj})
def cart_update(request):
product_id = request.POST.get('product_id')
if product_id is not None:
try:
product_obj = Product.objects.get(id=product_id)
except Product.DoesNotExist:
print("Mostrar mensagem ao usuário, esse produto acabou!")
return redirect("cart:home")
cart_obj, new_obj = Cart.objects.new_or_get(request)
if product_obj in cart_obj.products.all():
cart_obj.products.remove(product_obj)
else:
cart_obj.products.add(product_obj) # cart_obj.products.add(product_id)
request.session['cart_items'] = cart_obj.products.count()
# return redirect(product_obj.get_absolute_url())
return redirect("cart:home")
def checkout_home(request):
#aqui a gente pega o carrinho
cart_obj, cart_created = Cart.objects.new_or_get(request)
order_obj = None
#se o carrinho acabou de ser criado, ele tá zerado
#ou se o carrinho já existir mas não tiver nada dentro
if cart_created or cart_obj.products.count() == 0:
return redirect("cart:home")
login_form = LoginForm()
guest_form = GuestForm()
address_form = AddressForm()
billing_address_id = request.session.get("billing_address_id", None)
shipping_address_id = request.session.get("shipping_address_id", None)
billing_profile, billing_profile_created = BillingProfile.objects.new_or_get(request)
if billing_profile is not None:
order_obj, order_obj_created = Order.objects.new_or_get(billing_profile, cart_obj)
if shipping_address_id:
order_obj.shipping_address = Address.objects.get(id = shipping_address_id)
del request.session["shipping_address_id"]
if billing_address_id:
order_obj.billing_address = Address.objects.get(id = billing_address_id)
del request.session["billing_address_id"]
if billing_address_id or shipping_address_id:
order_obj.save()
if request.method == "POST":
#verifica se o pedido foi feito
is_done = order_obj.check_done()
if is_done:
order_obj.mark_paid()
request.session['cart_items'] = 0
del request.session['cart_id']
return redirect("/cart/success")
context = {
"object": order_obj,
"billing_profile": billing_profile,
"login_form": login_form,
"guest_form": guest_form,
"address_form": address_form,
}
return render(request, "carts/checkout.html", context)
Checando se o pedido está concluído
Para checar se o Order está done, vamos abrir o models.py do orders e fazer as modificações indicadas em azul abaixo.
django_ecommerce/e_commerce/orders/models.py
import math
from django.db import models
from django.db.models.signals import pre_save, post_save
from addresses.models import Address
from billing.models import BillingProfile
from carts.models import Cart
from e_commerce.utils import unique_order_id_generator
ORDER_STATUS_CHOICES = (
('created', 'Criado'),
('paid', 'Pago'),
('shipped', 'Enviado'),
('refunded', 'Devolvido'),
)
class OrderManager(models.Manager):
def new_or_get(self, billing_profile, cart_obj):
created = False
qs = self.get_queryset().filter(
billing_profile=billing_profile,
cart=cart_obj,
active=True,
status='created'
)
if qs.count() == 1:
obj = qs.first()
else:
obj = self.model.objects.create(
billing_profile=billing_profile,
cart=cart_obj)
created = True
return obj, created
class Order(models.Model):
billing_profile = models.ForeignKey(BillingProfile, on_delete=models.CASCADE, null = True, blank = True)
order_id = models.CharField(max_length = 120, blank = True)
# billing_profile = ?
shipping_address = models.ForeignKey(Address, related_name="shipping_address", on_delete=models.CASCADE, null=True, blank=True)
billing_address = models.ForeignKey(Address, related_name="billing_address", on_delete=models.CASCADE, null=True, blank=True)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, null = True)
status = models.CharField(max_length = 120, default = 'created', choices = ORDER_STATUS_CHOICES )
shipping_total = models.DecimalField(default = 5.99, max_digits = 100, decimal_places = 2)
total = models.DecimalField(default = 0.00, max_digits = 100, decimal_places = 2)
active = models.BooleanField(default=True)
def __str__(self):
return self.order_id
objects = OrderManager()
def update_total(self):
cart_total = self.cart.total
shipping_total = self.shipping_total
new_total = math.fsum([cart_total, shipping_total])
formatted_total = format(new_total, '.2f')
self.total = formatted_total
self.save()
return new_total
def check_done(self):
billing_profile = self.billing_profile
shipping_address = self.shipping_address
billing_address = self.billing_address
total = self.total
if billing_profile and shipping_address and billing_address and total > 0:
return True
return False
def mark_paid(self):
if self.check_done():
self.status = "paid"
self.save()
return self.status
def pre_save_create_order_id(sender, instance, *args, **kwargs):
if not instance.order_id:
instance.order_id = unique_order_id_generator(instance)
# return all orders with this Cart instance, excluding those
# that have the same billing profile instance
qs = Order.objects.filter(cart = instance.cart).exclude(billing_profile = instance.billing_profile)
print("QuerySet: ", qs)
if qs.exists():
qs.update = False
pre_save.connect(pre_save_create_order_id, sender = Order)
def post_save_cart_total(sender, instance, created, *args, **kwargs):
if not created:
cart_obj = instance
cart_total = cart_obj.total
cart_id = cart_obj.id
qs = Order.objects.filter(cart__id=cart_id)
if qs.count() == 1:
order_obj = qs.first()
order_obj.update_total()
post_save.connect(post_save_cart_total, sender=Cart)
def post_save_order(sender, instance, created, *args, **kwargs):
print("Executando")
if created:
print("Atualizando")
instance.update_total()
post_save.connect(post_save_order, sender=Order)
Agora vamos alterar o checkout.html do carts.
django_ecommerce/e_commerce/carts/templates/carts/checkout.html
{% extends "base.html" %}
{% block content %}
{{ object.order_id }} -- {{ object.cart }}
{% if not billing_profile %}
<div class='row text-center'>
<div class='col-12 col-md-6'>
<p class='lead'>Login</p>
{% include 'accounts/snippets/form.html' with form=login_form next_url=request.build_absolute_uri %}
</div>
<div class='col-12 col-md-6'>
Continuar como Convidado
{% url "guest_register" as guest_register_url %}
{% include 'accounts/snippets/form.html' with form=guest_form next_url=request.build_absolute_uri action_url=guest_register_url %}
</div>
</div>
{% else %}
{% if not object.shipping_address %}
<div class='row'>
<div class='col-md-6 mx-auto col-10'>
<p class='lead'>Endereço de envio</p>
<hr/>
{% url "checkout_address_create" as checkout_address_create %}
{% include 'addresses/form.html' with form=address_form next_url=request.build_absolute_uri action_url=checkout_address_create address_type='shipping' %}
</div>
</div>
{% elif not object.billing_address %}
<div class='row'>
<div class='col-md-6 mx-auto col-10'>
<p class='lead'>Endereço de Cobrança</p>
<hr/>
{% url "checkout_address_create" as checkout_address_create %}
{% include 'addresses/form.html' with form=address_form next_url=request.build_absolute_uri action_url=checkout_address_create address_type='billing' %}
</div>
</div>
{% else %}
<h1>Finalizar Checkout</h1>
<p>Total do Carrinho: {{ object.cart.total }}</p>
<p>Total do Frete: {{ object.shipping_total }}</p>
<p>Total do Pedido: {{ object.total }}</p>
<form class='form' method='POST' action="">{% csrf_token %}
<button type='submit'>Checkout</button>
</form>
{% endif %}
{% endif %}
{% endblock %}
Na próxima aula a gente vai construir a funcionalidade que dará a opção ao usuário de escolher o endereço ao invés de ter que escrever toda vez que fizer uma compra.
É isso, ficamos por aqui e até a próxima. 😉
Voltar para página principal do blog
Todas as aulas desse curso
Aula 62 Aula 64
Código final da aula:
https://github.com/toticavalcanti
Outros canais
Toti:
https://www.youtube.com/channel/UCUEtjLuDpcOvR3mIUr-viOA
Backing track / Play-along:
https://www.youtube.com/channel/UCT3TryVMqTqYBjf5g5WAHfA
Código Fluente
https://www.youtube.com/channel/UCgn-O-88XBAwdG9gUWkkb0w
Putz!
https://www.youtube.com/channel/UCZXop2-CECwyFYmHbhnAkAw
Se gostarem do conteúdo dêem um joinha 👍 na página do Código Fluente no
Facebook
Esse é o link do código fluente no Pinterest
Meus links de afiliados:
Hostinger
Digital Ocean
One.com
Nos vemos na próxima então, \o/ 😉 Bons Estudos!
Obrigado, o Sr ensina os detalhes, o pulo do gato e opções diferentes para chegar ao mesmo resultado. Isso é muito bom.
Obrigado José, que bom. \o/ e bons estudos.