Il s'agit d'une suite de la série "Créer un site EC avec Rails 5 ⑨](https://qiita.com/GreenFingers_tk/items/3fd347dee907328d20e0), qui crée un site EC sur lequel vous pouvez faire vos achats dans une boulangerie fictive. Nous implémenterons le modèle Order (fonction de commande), qui est la fonction principale et la partie la plus difficile de ce site.
Le mouvement de l'utilisateur est le suivant.
Mettez l'article dans le panier et appuyez sur le bouton "Passer à l'écran de commande"
↓
Entrez les informations de commande(orders/new)écran
·Mode de paiement
·Destinataire
Et appuyez sur le bouton "Passer à l'écran de confirmation"
↓
Confirmer les informations de commande(orders/confirm)écran
Vérifiez le contenu et appuyez sur le bouton "Confirmer la commande"
↓
orders/Afficher l'écran de remerciement (page statique)
Vous pouvez consulter l'historique des commandes sur l'écran de liste et de détails.
Le fait est que vous pouvez sélectionner l'adresse de livraison à saisir sur les commandes / nouvel écran parmi «votre adresse», «adresse enregistrée» et «nouvelle adresse». Lorsque vous sélectionnez une nouvelle adresse et remplissez le formulaire sur le nouvel écran, elle sera enregistrée en tant que données de commande ainsi que de nouvelles données dans le modèle d'adresse. L'imbrication des formulaires et le passage des écrans de confirmation avant d'enregistrer ces données sont des facteurs qui rendent difficile la mise en œuvre de cette fonctionnalité.
https://github.com/Sn16799/bakeryFUMIZUKI
Controller
app/controllers/orders_controller.rb
class OrdersController < ApplicationController
before_action :authenticate_customer!
before_action :set_customer
def index
@orders = @customer.orders
end
def create
if current_customer.cart_items.exists?
@order = Order.new(order_params)
@order.customer_id = current_customer.id
#Ajuster les arguments en fonction de la sélection du bouton radio d'adresse
@add = params[:order][:add].to_i
case @add
when 1
@order.post_code = @customer.post_code
@order.send_to_address = @customer.address
@order.addressee = full_name(@customer)
when 2
@order.post_code = params[:order][:post_code]
@order.send_to_address = params[:order][:send_to_address]
@order.addressee = params[:order][:addressee]
when 3
@order.post_code = params[:order][:post_code]
@order.send_to_address = params[:order][:send_to_address]
@order.addressee = params[:order][:addressee]
end
@order.save
# send_to_Recherche de modèle d'adresse par adresse, créer un nouveau s'il n'y a pas de données applicables
if Address.find_by(address: @order.send_to_address).nil?
@address = Address.new
@address.post_code = @order.post_code
@address.address = @order.send_to_address
@address.addressee = @order.addressee
@address.customer_id = current_customer.id
@address.save
end
# cart_Commander le contenu des articles_Nouvellement enregistré dans les articles
current_customer.cart_items.each do |cart_item|
order_item = @order.order_items.build
order_item.order_id = @order.id
order_item.product_id = cart_item.product_id
order_item.quantity = cart_item.quantity
order_item.order_price = cart_item.product.price
order_item.save
cart_item.destroy #order_Après avoir déplacé les informations vers l'article, le panier_l'élément est effacé
end
render :thanks
else
redirect_to customer_top_path
flash[:danger] = 'Le chariot est vide.'
end
end
def show
@order = Order.find(params[:id])
if @order.customer_id != current_customer.id
redirect_back(fallback_location: root_path)
flash[:alert] = "L'accès a échoué."
end
end
def new
@order = Order.new
end
def confirm
@order = Order.new
@cart_items = current_customer.cart_items
@order.how_to_pay = params[:order][:how_to_pay]
#Ajuster les arguments en fonction de la sélection du bouton radio d'adresse
@add = params[:order][:add].to_i
case @add
when 1
@order.post_code = @customer.post_code
@order.send_to_address = @customer.address
@order.addressee = @customer.family_name + @customer.first_name
when 2
@sta = params[:order][:send_to_address].to_i
@send_to_address = Address.find(@sta)
@order.post_code = @send_to_address.post_code
@order.send_to_address = @send_to_address.address
@order.addressee = @send_to_address.addressee
when 3
@order.post_code = params[:order][:new_add][:post_code]
@order.send_to_address = params[:order][:new_add][:address]
@order.addressee = params[:order][:new_add][:addressee]
end
end
def thanks
end
private
def set_customer
@customer = current_customer
end
def order_params
params.require(:order).permit(
:created_at, :send_to_address, :addressee, :order_status, :how_to_pay, :post_code, :deliver_fee,
order_items_attributes: [:order_id, :product_id, :quantity, :order_price, :make_status]
)
end
end
Ce serait bien si les informations envoyées par form_with pouvaient être sauvegardées telles quelles, mais form_with ne peut pas insérer l'écran de confirmation. Par conséquent, les actions de confirmation et de création récupèrent les paramètres reçus de la vue sous la forme de paramètres [: hoge].
De plus, lors de la création, en une seule action, "** Créer de nouvelles données de commande " " Déplacer les données de produit de CartItem vers OrderItem ** (Créer un nouvel article de commande et supprimer un article de panier enregistré)" ** Seulement lorsqu'il n'y a pas de données correspondantes dans le modèle d'adresse, vous devez effectuer les trois nouveaux enregistrements ** ". Chaque opération n'est pas compliquée, mais la quantité totale de code est assez importante.
View new
html:app/views/orders/.html.erb
<div class="col-lg-10 offset-1 space">
<div class="row">
<div class="col-lg-4">
<h2>Entrez les informations de commande</h2>
</div>
</div>
<%= form_with(model: @order, local: true, url: {action: 'confirm'}) do |f| %>
<!--Mode de paiement-->
<div class="row space">
<h3><strong><%= f.label :Mode de paiement%></strong></h3>
</div>
<div class="row">
<div class="col-lg-4 btn-group" data-toggle="buttons">
<label class="btn btn-outline-secondary active" style="width:50%">
<%= f.radio_button :how_to_pay, true, {checked: true} %>carte de crédit
</label>
<label class="btn btn-outline-secondary" style="width:50%">
<%= f.radio_button :how_to_pay, false, {} %>virement
</label>
</div>
</div>
<!--Destinataire-->
<div class="row space">
<h3><strong><%= f.label :Destinataire%></strong></h3>
</div>
<!--Propre adresse-->
<div class="row">
<p>
<label><%= f.radio_button :add, 1, checked: true, checked: "checked" %>Votre propre adresse</label><br>
<%= @customer.post_code %>
<%= @customer.address %>
<%= @customer.full_name %>
</p>
</div>
<!--Adresse enregistrée-->
<div class="row space-sm">
<p>
<label><%= f.radio_button :add, 2, style: "display: inline-block" %>Sélectionnez à partir de l'adresse enregistrée</label><br>
<%= f.collection_select :send_to_address, @customer.addresses, :id, :address %>
</p>
</div>
<!--Nouvelle adresse-->
<div class="row space-sm">
<p><label><%= f.radio_button :add, 3 %>Nouvelle destination</label></p>
</div>
<div class="row">
<div class="col-lg-12">
<%= f.fields_for :new_add do |na| %>
<div class="row">
<div class="col-lg-3">
<strong>Code postal(pas de trait d'union)</strong>
</div>
<div class="col-lg-6">
<%= na.text_field :post_code, class: 'form-control' %>
</div>
</div>
<div class="row">
<div class="col-lg-3">
<strong>adresse de rue</strong>
</div>
<div class="col-lg-6">
<%= na.text_field :address, class: 'form-control' %>
</div>
</div>
<div class="row">
<div class="col-lg-3">
<strong>adresse</strong>
</div>
<div class="col-lg-6">
<%= na.text_field :addressee, class: 'form-control' %>
</div>
</div>
<% end %>
</div>
</div>
<!--Jusqu'ici-->
<div class="row space">
<div class="col-lg-2 offset-lg-7">
<%= f.submit "Passer à l'écran de confirmation", class: "btn btn-danger"%>
</div>
</div>
<% end %>
</div>
confirm
html:app/views/orders/.html.erb
<div class="col-lg-10 offset-1 space">
<div class="row">
<h2>Confirmer les informations de commande</h2>
</div>
<%= form_with(model: @order, local: true) do |f| %>
<div class="d-none d-lg-block space">
<div class="row">
<div class="col-lg-5"><h4>Nom du produit</h4></div>
<div class="col-lg-2"><h4>Prix unitaire (taxes incluses)</h4></div>
<div class="col-lg-2"><h4>quantité</h4></div>
<div class="col-lg-2"><h4>total</h4></div>
</div>
</div>
<% sum_all = 0 %>
<% @cart_items.each do |cart_item| %>
<div class="row space-sm">
<div class="col-lg-3">
<%= link_to product_path(cart_item.product) do %>
<%= attachment_image_tag(cart_item.product, :image, :fill, 100, 100, fallback: "no_img.jpg ") %>
<% end %>
</div>
<div class="col-lg-2">
<%= link_to product_path(cart_item.product) do %>
<%= cart_item.product.name %>
<% end %>
</div>
<div class="col-lg-2">
<%= price_include_tax(cart_item.product.price) %>
</div>
<div class="col-lg-2">
<%= cart_item.quantity %>
</div>
<div class="col-lg-2">
<%= sum_product = price_include_tax(cart_item.product.price).to_i * cart_item.quantity %>Cercle
<% sum_all += sum_product %>
</div>
</div>
<% end %>
<div class="row space">
<div class="col-lg-12">
<div class="row">
<div class="col-lg-3">
<strong>livraison</strong>
</div>
<div class="col-lg-3">
<%= @order.deliver_fee %>Cercle
</div>
</div>
<div class="row">
<div class="col-lg-3">
<strong>Total produit</strong>
</div>
<div class="col-lg-3">
<%= sum_all.to_i %>Cercle
</div>
</div>
<div class="row">
<div class="col-lg-3">
<strong>Montant facturé</strong>
</div>
<div class="col-lg-3">
<% billling_amount = sum_all + @order.deliver_fee.to_i %>
<%= billling_amount.to_i %>Cercle
</div>
</div>
</div>
</div>
<div class="row space-sm">
<div class="col-lg-2">
<h3>Mode de paiement</h3>
</div>
<div class="col-lg-4">
<%= how_to_pay(@order.how_to_pay) %>
</div>
</div>
<div class="row space-sm">
<div class="col-lg-2">
<h3>Destinataire</h3>
</div>
<div class="col-lg-4">
<%= @order.post_code %>
<%= @order.send_to_address %>
<%= @order.addressee %>
</div>
</div>
<%= f.hidden_field :customer_id, :value => current_customer.id %>
<%= f.hidden_field :post_code, :value => "#{@order.post_code}" %>
<%= f.hidden_field :send_to_address, :value => "#{@order.send_to_address}" %>
<%= f.hidden_field :addressee, :value => "#{@order.addressee}" %>
</div>
<div class="row space">
<div class="col-lg-2 offset-lg-5">
<%= f.submit "Confirmer l'achat", class: "btn btn-danger btn-lg" %>
</div>
</div>
<% end %>
</div>
thanks
html:app/views/orders/.html.erb
<div class="col-lg-10 offset-1 space">
<h2>Merci pour votre achat!</h2>
<h3><%= link_to 'Retourner en haut', customer_top_path %></h3>
</div>
Cette page passe après avoir cliqué sur le bouton «Confirmer l'achat». Puisqu'il s'agit d'une page statique et n'a pas une telle fonction, il est bon de ne mettre que des mots simples comme décrit ci-dessus, ou d'afficher une photo avec un curseur, etc.
index
html:app/views/orders/.html.erb
<div class="col-lg-10 offset-1 space">
<div class="row">
<h2>Liste de l'historique des commandes</h2>
</div>
<div class="d-none d-lg-block space">
<div class="row">
<div class="col-lg-2">Date de commande</div>
<div class="col-lg-3">Adresse de livraison</div>
<div class="col-lg-2">Produit commandé</div>
<div class="col-lg-2">Paiement</div>
<div class="col-lg-1">Statut</div>
<div class="col-lg-2">Détails de la commande</div>
</div>
</div>
<% @orders.each do |order| %>
<div class="row space-sm">
<div class="col-lg-2">
<%= simple_time(order.created_at) %>
</div>
<div class="col-lg-3">
<div class="row">
<%= order.post_code + " " + order.send_to_address %>
</div>
<div class="row">
<%= order.addressee %>
</div>
</div>
<div class="col-lg-2">
<% sum_all = 0 %>
<% order.order_items.each do |order_item| %>
<%= order_item.product.name %><br>
<% sub_total = price_include_tax(order_item.order_price).to_i * order_item.quantity %>
<% sum_all += sub_total.to_i %>
<% end %>
</div>
<div class="col-lg-2">
<%= sum_all += order.deliver_fee.to_i %>Cercle
</div>
<div class="col-lg-1">
<%= order_status(order) %>
</div>
<div class="col-lg-2">
<%= link_to 'indiquer', order_path(order), class: "btn btn-sm btn-danger" %>
</div>
</div>
<% end %>
</div>
show
html:app/views/orders/.html.erb
<div class="col-lg-10 offset-1 space">
<div class="row">
<h2>Détails de l'historique des commandes</h2>
</div>
<div class="row">
<div class="col-lg-7">
<div class="row space">
<h3>Informations sur la commande</h3>
</div>
<div class="row">
<div class="container">
<div class="row space-sm">
<div class="col-lg-3">
<strong>Date de commande</strong>
</div>
<div class="col-lg-9">
<%= simple_time(@order.created_at) %>
</div>
</div>
<div class="row space-sm">
<div class="col-lg-3">
<strong>Adresse de livraison</strong>
</div>
<div class="col-lg-9">
<%= @order.send_to_address %>
</div>
</div>
<div class="row space-sm">
<div class="col-lg-3">
<strong>Mode de paiement</strong>
</div>
<div class="col-lg-9">
<%= how_to_pay(@order.how_to_pay) %>
</div>
</div>
<div class="row space-sm">
<div class="col-lg-3">
<strong>Statut</strong>
</div>
<div class="col-lg-9">
<%= order_status(@order) %>
</div>
</div>
</div>
</div>
<div class="row space">
<h3>Détails de la commande</h3>
</div>
<div class="d-none d-lg-block">
<div class="row">
<div class="col-lg-4">
<strong>Produit</strong>
</div>
<div class="col-lg-3">
<strong>Prix unitaire (taxes incluses)</strong>
</div>
<div class="col-lg-2">
<strong>Quantité</strong>
</div>
<div class="col-lg-2">
<strong>total</strong>
</div>
</div>
</div>
<% sum_all = 0 %>
<% @order.order_items.each do |order_item| %>
<div class="row space-sm">
<div class="col-lg-4">
<%= order_item.product.name %>
</div>
<div class="col-lg-3">
<%= price_include_tax(order_item.order_price) %>
</div>
<div class="col-lg-2">
<%= order_item.quantity %>Pièces
</div>
<div class="col-lg-2">
<%= sub_total = price_include_tax(order_item.order_price).to_i * order_item.quantity %>Cercle
<% sum_all += sub_total %>
</div>
</div>
<% end %>
</div>
<div class="col-lg-5">
<div class="row space">
<h3>Détails de facturation</h3>
</div>
<div class="row">
<div class="container">
<div class="row space-sm">
<div class="col-lg-6">
<strong>Total produit</strong>
</div>
<div class="col-6">
<%= sum_all %>Cercle
</div>
</div>
<div class="row space-sm">
<div class="col-lg-6">
<strong>Frais de livraison</strong>
</div>
<div class="col-lg-6">
<%= @order.deliver_fee %>Cercle
</div>
</div>
<div class="row space-sm">
<div class="col-lg-6">
<strong>Montant facturé</strong>
</div>
<div class="col-lg-6">
<%= sum_all + @order.deliver_fee.to_i %>Cercle
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Dans la figure ci-dessus, je voudrais afficher le montant total des produits dans la colonne "Informations de facturation", mais si je construis l'écran dans l'ordre du haut, il sera nécessaire de passer deux fois par une boucle pour "Informations de facturation" et "Détails de la commande". Ce sera un problème. Donc, en pensant que c'est une méthode bâclée, divisez l'écran verticalement en deux avec col, créez d'abord des colonnes pour «informations de commande» et «détails de commande», puis calculez le montant total dans la boucle «détails de la commande». Il est stocké dans une variable et appelé dans le champ "Informations de facturation". (Dans la colonne "Informations de facturation", j'ai oublié de définir la valeur par défaut des frais d'expédition dans la base de données. Le montant total du produit et le montant de facturation sont donc identiques. À l'origine, les frais d'expédition de 800 yens correspondent au montant de facturation pour le produit total. C'est une spécification à ajouter, et le code de vue y correspond également.)
Il n'y avait que la fonction principale de ce site EC, et la quantité de code était importante et le contenu était compliqué. Dans cette implémentation, tout en suivant à peu près ce que j'ai fait dans l'implémentation de l'équipe de l'école auparavant, des modifications telles que la définition de nouvelles méthodes d'aide et de modèle pour rendre le code plus facile à voir et rendre l'écran réactif Était ajouté.
Il s'agit d'une note supplémentaire sur la spécification selon laquelle les données d'adresse sont enregistrées dans Address en même temps que Order lorsqu'une nouvelle adresse est sélectionnée dans l'action de création. Dans la description ci-dessus, la colonne d'adresse du modèle d'adresse est recherchée, et s'il n'y a pas de correspondance, elle est enregistrée. Pour une recherche plus précise
unless Address.find_by(addressee: @order.addressee, address: @order.send_to_address).exists?
En tant que tel, vous souhaiterez peut-être vous assurer que l'adresse et l'adresse correspondent. Bien que le code sera plus long.
Quoi qu'il en soit, cela complète la fonctionnalité du site client. Je suis heureux.
Recommended Posts