WebMatrix - Criando uma Loja Virtual - Fazendo o Checkout - 7


Na  sexta parte deste artigo implementamos as funcionalidades de membership como login, logout, registro e redefinição de senha bem como o envio de email e  o processo de continuar comprando; nesta etapa vamos implementar o checkout.

Implementando o checkout - Definindo as tabelas

O processo de checkout do nosso site irá requerer que os usuários informem os detalhes de suas compras e confirmem o pedido feito. Após isso o pedido será armazenado no banco de dados, um email de confirmação será enviado e os clientes serão redirecionados para a página - Confirmar Pedido.

Nossa primeira tarefa será criar as tabelas no banco de dados necessárias para armazenar os pedidos encerrados e confirmados.

Vamos adicionar duas novas tabelas no nosso banco de dados para tratar os pedidos:

  1. A primeira tabela chamada Pedidos armazenará os detalhes do pedido, incluindo o endereço de entrega e o código do cliente;
  2. A segunda tabela chamada PedidosItens será usada para armazenar os itens individuais que compõem o pedido;

Clique na guia DataBases e a seguir expanda as tabelas do banco de dados TecnoSite;

A seguir clique com o botão direito sobre o item Tables e a seguir clique em New Table;

A seguir defina a seguinte estrutura para esta tabela usando os recursos do editor conforme mostra a figura abaixo:

Obs: o campo pedidoid é definido como chave primária e do tipo identity.

Salve a tabela com o nome Pedidos.

Repita o procedimento acima e cria a tabela PedidoItens com a seguinte estrutura:

Agora que já criamos as tabelas para armazenar as informações vamos criar a página de Checkout.

Criando a página de Checkout

Na página Checkout, vamos mostrar o conteúdo do carrinho de compras do usuário e solicitar os detalhes do envio para o pedido.

Quando o usuário clicar no botão "Confirmar Pedido", o processo a seguir deverá ocorrer:

Clique na guia Files e a seguir clique com o botão direito do mouse sobre a raiz do site e selecione New File;

Selecione o template CSHTML e informe o nome Checkout.cshtml e clique em OK;

A seguir define o código abaixo neste arquivo:

@{
if (!WebSecurity.IsAuthenticated)
{
    string UrlAtual = Request.Url.ToString();
    Response.Redirect("~/Contas/Login?sender=" + UrlAtual);
}

Layout = "~/Shared/Layouts/_Layout.cshtml";
Page.Title = "Checkout";

var endereco = "";
var cidade = "";
var estado = "";
var cep = "";
var pais = "";

// Redireciona para Carrinho.cshtml se não existir na Session
if (Session["carrinho"] == null)
{
   Response.Redirect("Carrinho");
}

// Pega o carrinho atual da sessão
Carrinho carrinho = (Carrinho)Session["carrinho"];

// Redireciona para carrinho.cshtml se não existir itens
if(carrinho.Itens.Count() == 0)
{
    Response.Redirect("Carrinho");
}
}
<h1>Checkout</h1>
<div id="checkout">
<h2>Detalhes do Pedido</h2>
<table id="TabelaCarrinho">
<tr>
<th class="produto">Produto</th>
<th class="descricao">Descriçao</th>
<th class="preco">Preço</th>
</tr>
@foreach (var item in carrinho.Itens)
{
<tr>
    <td class="produto">@Produtos.GetNomeProdutoPorID(item.ProdutoID)</td>
    <td class="descricao">@item.Descricao</td>
    <td class="preco">R$@item.Preco</td>
</tr>
}
<tr class="carrinhoTotal">
   <td colspan="2">&nbsp;</td>
   <td>Total: R$@carrinho.ValorTotal</td>
</tr>
</table>
<h2>Endereço de Entrega</h2>
<form action="Checkout" method="post">
<p>
  @Html.Label("Endereço : ", "endereco")
  @Html.TextBox("endereco", endereco, new { maxlength = "100" } )
  @Html.ValidationMessage("endereco")
</p>
<p>
  @Html.Label("Cidade : ", "cidade")
  @Html.TextBox("cidade", cidade, new { maxlength = "50" } )
  @Html.ValidationMessage("cidade")
</p>
<p>
  @Html.Label("Estado : ", "estado")
  @Html.TextBox("estado", estado, new { maxlength = "50" } )
  @Html.ValidationMessage("estado")
</p>
<p>
  @Html.Label("Cep : ", "cep")
  @Html.TextBox("cep", cep, new { maxlength = "20" } )
</p>
<p>
  @Html.Label("País : ", "pais")
  @Html.TextBox("pais", pais, new { maxlength = "50" } )
</p>
<h2>Confirmar Pedido</h2>
<p>
<input type="submit" value="Confirmar Pedido"/>
</p>
</form>
</div>

Vamos aproveitar e aplicar um estilo a nossa página Checkout.cshtml incluindo o código abaixo no arquivo Style.css:

#checkout p {
padding: 5px 0px 5px 0px;
}
#checkout input[type="submit"] {
padding: 5px 45px 5px 45px;
}

Executando o projeto, fazendo o login e selecionando alguns produtos ao realizar o checkout iremos obter a seguinte página como resultado:

A primeira ação realizada pela página é verificar se o usuário atual esta conectado ao site verificando a propriedade WebSecurity.IsAuthenticated. Se o usuário estiver autenticado, ele será redirecionado imediatamente para a página de login.

Em seguida, vamos definir o layout e título da página de Checkout e declarar um conjunto de variáveis para armazenar os dados do detalhes da remessa do pedido. Se o usuário não tiver um carrinho de compras em sua sessão , vamos redirecioná-lo para a página Carrinho.cshtml. Se ele já possuir um carrinho na sessão, vamos recuperá-lo e obter a contagem dos itens do carrinho, e novamente redirecioná-lo a página Carrinho.cshtml se o carrinho estiver vazio.

Definimos na página Checkout uma tabela HTML e iteramos sobre a coleção de itens do carrinho exibindo um resumo de cada item e na linha final apresentamos o total do pedido via propriedade carrinho.ValoTotal.

A seguir exibimos um formulário para coletar os detalhes para enviar o pedido usando um simples formulário HTML contendo seis caixas de texto e um botão submit. O atributo maxlength de cada caixa de texto é definida para igualar o comprimento das colunas de banco de dados correspondentes na tabela Pedidos.

Agora temos que incluir o tratamento de requisição POST para armazenar os dados do pedido e enviar um email quando o usuário clicar no botão Confirmar Pedido. Para isso vamos incluir o código (destacado em azul) abaixo na página Checkout.cshtml que verifica se esta ocorrendo um POST e realiza as ações desejadas:

@{
if (!WebSecurity.IsAuthenticated)
{
    string UrlAtual = Request.Url.ToString();
    Response.Redirect("~/Contas/Login?sender=" + UrlAtual);
}

Layout = "~/Shared/Layouts/_Layout.cshtml";
Page.Title = "Checkout";

var endereco = "";
var cidade = "";
var estado = "";
var cep = "";
var pais = "";

// Redireciona para Carrinho.cshtml se não existir na Session
if (Session["carrinho"] == null)
{
   Response.Redirect("Carrinho");
}

// Pega o carrinho atual da sessão
Carrinho carrinho = (Carrinho)Session["carrinho"];

// Redireciona para carrinho.cshtml se não existir itens
if(carrinho.Itens.Count() == 0)
{
    Response.Redirect("Carrinho");
}
//---------POST------------------------------------------------------------------------------
if (IsPost)
{
    endereco = Request["endereco"];
    cidade = Request["cidade"];
    estado = Request["estado"];
    cep = Request["cep"];
    pais = Request["pais"];
    
    // valida os detalhes do endereço da remessa
    if (endereco.IsEmpty()) {
        ModelState.AddError("endereco", "O endereço é obrigatório.");
    }
    if (cidade.IsEmpty()) {
        ModelState.AddError("cidade", "A cidade é obrigatória.");
    }
    if (estado.IsEmpty()) {
        ModelState.AddError("estado", "O estado é obrigatório.");
    }
    if(ModelState.IsValid)
    {
        // salva pedido
        var UsuarioID = WebSecurity.GetUserId(WebSecurity.CurrentUserName);
        var db = Database.Open("TecnoSite");
        
        var pedidoSQL = "INSERT INTO Pedidos (usuarioid, pedidoEnviado, pedidoTotal, " +
        "pedidoDataHora, endereco, cidade, estado, pais, cep) VALUES ( @0, @1, @2, @3, @4, @5, @6, @7, @8)";
        
        db.Execute(pedidoSQL,UsuarioID,false,carrinho.ValorTotal,DateTime.Now,endereco,cidade,estado,pais,cep);
        
        var pedidoId = db.GetLastInsertId();
        
        foreach(var item in carrinho.Itens)
        {
            pedidoSQL = "INSERT INTO PedidoItens (pedidoid, produtoid, preco, descricao) VALUES (@0, @1, @2, @3)";
            db.Execute(pedidoSQL, pedidoId, item.ProdutoID,  item.Preco, item.Descricao);
        }
        // Envia email de confirmação
        WebMail.Send(to: WebSecurity.CurrentUserName,subject: "TecnoSite - Confirmação de Pedido",
        body: "Muito obrigado pelo seu pedido. Seu pedido será despachado imediatamente e deverá chegar dentro de 4 dias.");
        // limpa o carrinho
        carrinho.Limpar();
        Response.Redirect("EncerrarPedido");
   }
}
//--------------------------fim POST-----------------------------------------------------------------------------
}
<h1>Checkout</h1>
<div id="checkout">
<h2>Detalhes do Pedido</h2>
<table id="TabelaCarrinho">
<tr>
<th class="produto">Produto</th>
<th class="descricao">Descriçao</th>
<th class="preco">Preço</th>
</tr>
@foreach (var item in carrinho.Itens)
{
<tr>
    <td class="produto">@Produtos.GetNomeProdutoPorID(item.ProdutoID)</td>
    <td class="descricao">@item.Descricao</td>
    <td class="preco">R$@item.Preco</td>
</tr>
}
<tr class="carrinhoTotal">
   <td colspan="2">&nbsp;</td>
   <td>Total: R$@carrinho.ValorTotal</td>
</tr>
</table>
<h2>Endereço de Entrega</h2>
<form action="Checkout" method="post">
<p>
  @Html.Label("Endereço : ", "endereco")
  @Html.TextBox("endereco", endereco, new { maxlength = "100" } )
  @Html.ValidationMessage("endereco")
</p>
<p>
  @Html.Label("Cidade : ", "cidade")
  @Html.TextBox("cidade", cidade, new { maxlength = "50" } )
  @Html.ValidationMessage("cidade")
</p>
<p>
  @Html.Label("Estado : ", "estado")
  @Html.TextBox("estado", estado, new { maxlength = "50" } )
  @Html.ValidationMessage("estado")
</p>
<p>
  @Html.Label("Cep : ", "cep")
  @Html.TextBox("cep", cep, new { maxlength = "20" } )
</p>
<p>
  @Html.Label("País : ", "pais")
  @Html.TextBox("pais", pais, new { maxlength = "50" } )
</p>
<h2>Confirmar Pedido</h2>
<p>
<input type="submit" value="Confirmar Pedido"/>
</p>
</form>
</div>

No manipulador da requisição POST, nós recuperamos os valores dos detalhes referente ao endereço para remessa do campos do formulário, e os atribuímos a variáveis declaradas anteriormente validando os campos necessários. Se todos os campos de formulário contêm dados inválidos, adicionamos um erro ao ModelState e exibimos uma mensagem de erro no formulário.

E assim concluímos o processamento na página checkout.

Criando a página EncerrarPedido

A página EncerrarPedido simplesmente exibe a mensagem ao usuário agradecendo pelo pedido e informando que um email lhe foi enviado. Vamos agora criar a página EncerrarPedido.chstml.

Clique com o botão direito do mouse sobre a raiz do site e selecione New File;

Marque o template CSHTML e informe o nome EncerrarPedido.cshtml incluindo o código abaixo neste arquivo:

@{
Layout = "~/Shared/Layouts/_Layout.cshtml";
Page.Title = "Encerrar Pedido";
}
<h1>Pedido Concluído</h1>
<p>Muito obrigado pelo seu pedido. Um email de confirmação foi enviado para o seu email.</p>
<br />
<p>Seu pedido será despachado de imediato e deverá estar chegando dentro de 3 dias úteis.</p>

Agora ao completar o processo de checkout iremos obter o seguinte resultado:

Concluímos assim o processo de compras definido para o nosso site, naturalmente faltou implementar a modalidade de pagamentos do pedido com boleto, cartão de crédito, etc.

Como essa tarefa varia muito e pode depender de componentes de terceiros eu vou parar por aqui deixando essa tarefa a seu cargo.

Na próxima etapa vamos criar a área de administração do site que usaremos para gerenciar e manter o site atualizado.

Aguarde a quinta parte do artigo: WebMatrix - Criando uma Loja Virtual - Criando a área de administração - 8

Referências:


José Carlos Macoratti