[RUBY] Erstellen Sie eine EC-Site mit Rails 5 ⑩ ~ Erstellen Sie eine Bestellfunktion ~

Einführung

Dies ist eine Fortsetzung der Serie "Erstellen einer EC-Site mit Rails 5 ⑨" (https://qiita.com/GreenFingers_tk/items/3fd347dee907328d20e0), die eine EC-Site erstellt, auf der Sie in einer fiktiven Bäckerei einkaufen können. Wir werden das Order-Modell (Order-Funktion) implementieren, das die Hauptfunktion und der schwierigste Teil dieser Site ist.

Die Bewegung des Benutzers ist wie folgt.

Legen Sie den Artikel in den Warenkorb und klicken Sie auf die Schaltfläche "Weiter zum Bestellbildschirm"
↓
Bestellinformationen eingeben(orders/new)Bildschirm
·Zahlungsmethode
·Adressat
Klicken Sie auf die Schaltfläche "Weiter zum Bestätigungsbildschirm"
↓
Bestellinformationen bestätigen(orders/confirm)Bildschirm
Überprüfen Sie den Inhalt und klicken Sie auf die Schaltfläche "Bestellung bestätigen"
↓
orders/Dankesbildschirm anzeigen (statische Seite)

Sie können den Bestellverlauf auf dem Listen- und Detailbildschirm überprüfen.

Der Punkt ist, dass Sie die Lieferadresse, die auf dem Bildschirm Bestellungen / Neu eingegeben werden soll, aus "Ihre Adresse", "Registrierte Adresse" und "Neue Adresse" auswählen können. Wenn Sie eine neue Adresse auswählen und das Formular auf dem neuen Bildschirm ausfüllen, werden diese als Bestelldaten sowie als neue Daten im Adressmodell gespeichert. Das Verschachteln von Formularen und das Durchlaufen von Bestätigungsbildschirmen vor dem Speichern dieser Daten sind Faktoren, die die Implementierung dieser Funktion erschweren.

Quellcode

https://github.com/Sn16799/bakeryFUMIZUKI

Modellassoziation

fumizuki_ER.jpg

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

      #Passen Sie die Argumente entsprechend der Auswahl des Optionsfelds an
      @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_Adressmodellsuche nach Adresse, neu erstellen, wenn keine zutreffenden Daten vorhanden sind
      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_Bestellen Sie den Inhalt der Artikel_Neu in Artikeln registriert
      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_Nachdem Sie die Informationen in den Artikel verschoben haben, Warenkorb_Artikel wird gelöscht
      end
      render :thanks
    else
      redirect_to customer_top_path
   flash[:danger] = 'Der Wagen ist leer.'
    end
  end

  def show
    @order = Order.find(params[:id])
    if @order.customer_id != current_customer.id
      redirect_back(fallback_location: root_path)
      flash[:alert] = "Zugriff fehlgeschlagen."
    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]
    #Passen Sie die Argumente entsprechend der Auswahl des Optionsfelds an
    @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

Es wäre schön, wenn die von form_with gesendeten Informationen wie gewohnt gespeichert werden könnten, aber form_with den Bestätigungsbildschirm nicht einfügen kann. Daher rufen die Bestätigungs- und Erstellungsaktionen die aus der Ansicht empfangenen Parameter in Form von Parametern [: hoge] ab.

Außerdem können Sie beim Erstellen innerhalb einer Aktion "** Neue Bestelldaten erstellen " " Produktdaten von CartItem nach OrderItem verschieben ** (Neues Bestellelement erstellen und registriertes CartItem löschen)" ** Nur wenn das Adressmodell keine übereinstimmenden Daten enthält, müssen Sie die drei neuen Registrierungen durchführen ** ". Jede Operation ist nicht kompliziert, aber die Gesamtmenge an Code ist ziemlich groß.

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>Bestellinformationen eingeben</h2>
    </div>
  </div>

  <%= form_with(model: @order, local: true, url: {action: 'confirm'}) do |f| %>

  <!--Zahlungsmethode-->
  <div class="row space">
    <h3><strong><%= f.label :Zahlungsmethode%></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} %>Kreditkarte
      </label>
      <label class="btn btn-outline-secondary" style="width:50%">
        <%= f.radio_button :how_to_pay, false, {} %>Banküberweisung
      </label>
    </div>
  </div>

  <!--Adressat-->
  <div class="row space">
    <h3><strong><%= f.label :Adressat%></strong></h3>
  </div>
  <!--Eigene Adresse-->
  <div class="row">
    <p>
      <label><%= f.radio_button :add, 1, checked: true, checked: "checked" %>Ihre eigene Adresse</label><br>
      <%= @customer.post_code %>
      <%= @customer.address %>
      <%= @customer.full_name %>
    </p>
  </div>

  <!--Registrierte Adresse-->
  <div class="row space-sm">
    <p>
      <label><%= f.radio_button :add, 2, style: "display: inline-block" %>Wählen Sie aus der registrierten Adresse</label><br>
      <%= f.collection_select :send_to_address, @customer.addresses, :id, :address %>
    </p>
  </div>

  <!--Neue Adresse-->
  <div class="row space-sm">
    <p><label><%= f.radio_button :add, 3 %>Neues Ziel</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>Postleitzahl(kein Bindestrich)</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</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>
  <!--Bis hierhin-->

  <div class="row space">
    <div class="col-lg-2 offset-lg-7">
      <%= f.submit "Fahren Sie mit dem Bestätigungsbildschirm fort", 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>Bestellinformationen bestätigen</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>Produktname</h4></div>
      <div class="col-lg-2"><h4>Stückpreis (inkl. MwSt.)</h4></div>
      <div class="col-lg-2"><h4>Menge</h4></div>
      <div class="col-lg-2"><h4>Zwischensumme</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 %>Kreis
      <% 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>Versand</strong>
        </div>
        <div class="col-lg-3">
          <%= @order.deliver_fee %>Kreis
        </div>
      </div>
      <div class="row">
        <div class="col-lg-3">
          <strong>Produkt insgesamt</strong>
        </div>
        <div class="col-lg-3">
          <%= sum_all.to_i %>Kreis
        </div>
      </div>
      <div class="row">
        <div class="col-lg-3">
          <strong>Abgerechneter Betrag</strong>
        </div>
        <div class="col-lg-3">
          <% billling_amount = sum_all + @order.deliver_fee.to_i %>
          <%= billling_amount.to_i %>Kreis
        </div>
      </div>
    </div>
  </div>

  <div class="row space-sm">
    <div class="col-lg-2">
      <h3>Zahlungsmethode</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>Adressat</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 "Bestätige den Kauf", 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>Danke für Ihren Einkauf!</h2>
  <h3><%= link_to 'Zurück nach oben', customer_top_path %></h3>
</div>

Diese Seite wechselt nach dem Klicken auf die Schaltfläche "Kauf bestätigen". Da es sich um eine statische Seite handelt und keine solche Funktion hat, empfiehlt es sich, nur einfache Wörter wie oben beschrieben einzugeben oder ein Foto mit einem Schieberegler usw. anzuzeigen.

index

html:app/views/orders/.html.erb


<div class="col-lg-10 offset-1 space">

  <div class="row">
    <h2>Bestellverlaufsliste</h2>
  </div>

  <div class="d-none d-lg-block space">
    <div class="row">
      <div class="col-lg-2">Bestelldatum</div>
      <div class="col-lg-3">Lieferanschrift</div>
      <div class="col-lg-2">Bestelltes Produkt</div>
      <div class="col-lg-2">Zahlung</div>
      <div class="col-lg-1">Status</div>
      <div class="col-lg-2">Bestelldetails</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 %>Kreis
    </div>
    <div class="col-lg-1">
      <%= order_status(order) %>
    </div>
    <div class="col-lg-2">
      <%= link_to 'zeigen', 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>Details zur Bestellhistorie</h2>
  </div>

  <div class="row">
    <div class="col-lg-7">
      <div class="row space">
        <h3>Bestellinformationen</h3>
      </div>
      <div class="row">
        <div class="container">
          <div class="row space-sm">
            <div class="col-lg-3">
              <strong>Bestelldatum</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>Lieferanschrift</strong>
            </div>
            <div class="col-lg-9">
              <%= @order.send_to_address %>
            </div>
          </div>
          <div class="row space-sm">
            <div class="col-lg-3">
              <strong>Zahlungsmethode</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>Status</strong>
            </div>
            <div class="col-lg-9">
              <%= order_status(@order) %>
            </div>
          </div>
        </div>
      </div>

      <div class="row space">
        <h3>Bestelldetails</h3>
      </div>
      <div class="d-none d-lg-block">
        <div class="row">
          <div class="col-lg-4">
            <strong>Produkt</strong>
          </div>
          <div class="col-lg-3">
            <strong>Stückpreis (inkl. MwSt.)</strong>
          </div>
          <div class="col-lg-2">
            <strong>Menge</strong>
          </div>
          <div class="col-lg-2">
            <strong>Zwischensumme</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 %>Stücke
        </div>
        <div class="col-lg-2">
          <%= sub_total = price_include_tax(order_item.order_price).to_i * order_item.quantity %>Kreis
          <% sum_all += sub_total %>
        </div>
      </div>
      <% end %>
    </div>

    <div class="col-lg-5">
      <div class="row space">
        <h3>Abrechnungsdaten</h3>
      </div>
      <div class="row">
        <div class="container">
          <div class="row space-sm">
            <div class="col-lg-6">
              <strong>Produkt insgesamt</strong>
            </div>
            <div class="col-6">
              <%= sum_all %>Kreis
            </div>
          </div>
          <div class="row space-sm">
            <div class="col-lg-6">
              <strong>Liefergebühr</strong>
            </div>
            <div class="col-lg-6">
              <%= @order.deliver_fee %>Kreis
            </div>
          </div>
          <div class="row space-sm">
            <div class="col-lg-6">
              <strong>Abgerechneter Betrag</strong>
            </div>
            <div class="col-lg-6">
              <%= sum_all + @order.deliver_fee.to_i %>Kreis
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

orders_show.jpg

In der obigen Abbildung möchte ich die Gesamtmenge der Produkte in der Spalte "Rechnungsinformationen" anzeigen. Wenn ich den Bildschirm jedoch in der Reihenfolge von oben aufbaue, muss die Schleife für "Rechnungsinformationen" und "Bestelldetails" zweimal gedreht werden. Es wird ein Ärger sein. Wenn Sie also der Meinung sind, dass es sich um eine schlampige Methode handelt, teilen Sie den Bildschirm vertikal mit col in zwei Teile, erstellen Sie zuerst Spalten für "Bestellinformationen" und "Bestelldetails" und berechnen Sie dann den Gesamtbetrag in der Schleife "Bestelldetails". Es wird in einer Variablen gespeichert und im Feld "Rechnungsinformationen" aufgerufen. (In der Spalte "Rechnungsinformationen" habe ich vergessen, den Standardwert der Versandgebühr in der Datenbank festzulegen, sodass der Gesamtbetrag des Produkts und der Rechnungsbetrag gleich sind. Ursprünglich ist die Versandgebühr von 800 Yen der Rechnungsbetrag für das Gesamtprodukt. Es ist eine Spezifikation, die hinzugefügt werden muss, und der Ansichtscode entspricht auch dieser.)

Nachtrag

Es gab nur die Kernfunktion dieser EC-Site, und die Menge an Code war groß und der Inhalt war kompliziert. In dieser Implementierung wurden Änderungen vorgenommen, z. B. die neu definierten Hilfs- und Modellmethoden, um den Code besser sichtbar zu machen und den Bildschirm ansprechbar zu machen Wurde hinzugefügt.

Es ist ein zusätzlicher Hinweis zu der Spezifikation, dass Adressdaten gleichzeitig mit der Bestellung in Adresse registriert werden, wenn in der Erstellungsaktion eine neue Adresse ausgewählt wird. In der obigen Beschreibung wird die Adressspalte des Adressmodells durchsucht und registriert, wenn keine Übereinstimmung vorliegt. Für eine genauere Suche

unless Address.find_by(addressee: @order.addressee, address: @order.send_to_address).exists?

Daher möchten Sie möglicherweise sicherstellen, dass sowohl die Adresse als auch die Adresse übereinstimmen. Obwohl der Code länger sein wird.

Auf jeden Fall vervollständigt dies die Funktionalität des Kundenstandorts. Ich bin glücklich.

Recommended Posts

Erstellen Sie eine EC-Site mit Rails 5 ⑩ ~ Erstellen Sie eine Bestellfunktion ~
Erstellen einer EC-Site mit Rails 5 ⑨ ~ Erstellen einer Warenkorbfunktion ~
Erstellen Sie eine EC-Site mit Rails5 Address ~ Adresse, Genre-Modell ~
Erstellen Sie eine EC-Site mit Rails5 ④ ~ Kopf- und Fußzeile ~
Erstellen Sie eine EC-Site mit Rails5 seed ~ Startdateneingabe ~
Erstellen Sie eine EC-Site mit Rails5 Boot ~ Bootstrap4-Einstellungen, Controller- / Aktionsdefinition ~
[Rails] EC-Site-Cart-Funktion
Erstellen Sie eine EC-Site mit Rails5 ③-Set Model-Assoziationen und anderen Dingen-
[Schienenentnahme] Erstellen Sie eine einfache Entnahmefunktion mit Schienen
Erstellen Sie eine EC-Site mit Streifen! (Konto-Erstellung)
[Rails] Erstellen Sie eine Anwendung
Erstellen Sie mit JAVA eine unveränderliche Klasse
Erstellen Sie ein Portfolio mit Rails + Postgres SQL
Erstellen Sie eine App mit Spring Boot 2
[Rails] DB-Design für EC-Standort
Erstellen Sie eine Excel-Datei mit poi
Erstellen Sie eine App mit Spring Boot
Erstellen Sie eine App-Katalogsite mit CLI für Microsoft 365 mit Docker
(EC-Site) Validierung bei der Eingabe von Bestellinformationen
Lassen Sie uns eine Instanz mit .new selbst erstellen. .. ..
[Java] Erstellen Sie mit Gradle ein ausführbares Modul
[Rails6] Erstelle eine neue App mit Rails [Anfänger]
Einfache Bereitstellung mit Capistrano + AWS (EC2) + Rails
Erstellen Sie trotzdem eine Anmeldefunktion mit Rails
[Rails 5] Erstelle eine neue App mit Rails [Anfänger]
Lassen Sie uns mit Rails einen Fehlerbildschirm erstellen
Nuxt.js × Erstellen Sie eine Anwendung im Rails-API-Modus
Downgrade einer vorhandenen App, die mit Rails 5.2.4 erstellt wurde, auf 5.1.6
[Rails] Rails neu, um eine Datenbank mit PostgreSQL zu erstellen
Erstellen Sie eine JSON-API, die die RSA-Verschlüsselung mit Wicket unterstützt
Erstellen Sie einen Team-Chat mit Rails Action Cable
Lassen Sie uns eine Suchfunktion mit Rails (Ransack) machen
Rails6.0 ~ So erstellen Sie eine umweltfreundliche Entwicklungsumgebung
Erstellen Sie einen Annotator, der Kuromoji mit NLP4J verwendet. [007]
[Rails] So erstellen Sie eine Umgebung mit Docker
Ich habe versucht, mit Java und Spring eine Funktion / einen Bildschirm für den Administrator einer Einkaufsseite zu erstellen
Schienen folgen der Funktion
[Rails] Benachrichtigungsfunktion
[Nr.003] Erstellen Sie einen Bestelllistenbildschirm für den Besteller
[Rails] Implementierung der Drag & Drop-Funktion (mit Wirkung)
So pushen Sie mit Rails entwickelte Apps an Github
Erstellen Sie einen HTTPS-Dateiserver für die Entwicklung mit dem Ring-Jetty-Adapter
Erstellen Sie mit Docker x Cypress eine E2E-Testumgebung
Erstellen Sie einen Service mit einem leeren Modell Liferay 7.0 / DXP
Erstellen Sie mit Spring Security 2.1 eine einfache Demo-Site mit Spring Security