diff --git a/TODO b/TODO index 02f35919..a1272b84 100644 --- a/TODO +++ b/TODO @@ -7,10 +7,20 @@ ✔ 身為消費者,當我下單時,我的信箱要能收到一張下單確認信 @done (14-06-13 17:44) ✔ 訂單狀態應分為未結帳、已結帳、出貨中、已出貨、辦理退貨 @done (14-06-13 17:44) ☐ 身為消費者,當我用信用卡結帳後,我的信箱要能收到一張訂購完成信 + ✔ 身為消費者,當我在結賬後,購物⾞應自動清空 @done (14-06-20 01:01) + ✔ 清空購物⾞ @done (14-06-20 00:36) + ✔ 身為消費者,我可以從購物車內刪掉某些物品 @done (14-06-20 00:41) + ✔ 身為消費者,我可以從購物車內更新購買數量 @done (14-06-20 00:54) + ✔ 購物車的總價 => 小計 x 數量 @done (14-06-20 00:54) + ✔ 數量為 0 的貨物不能「購買」 @done (14-06-20 00:56) + ✔ 訂單支援「多重購買數量」 @done (14-06-20 01:00) + ✔ 建立 account/orders 可以看到該使用者過去所有訂單 @done (14-06-20 01:08) + ✔ 結賬後跳轉到 account/orders#index @done (14-06-20 01:10) Admin 管理訂單: - ☐ 身為管理者,可以在後台看訂單,訂單狀態分為未結帳、已結帳、出貨中、已出貨、辦理退貨 - ☐ 身為管理者,我可以在後台對單張訂單做狀態改變 + ✔ 身為管理者,可以在後台看訂單,訂單狀態分為未結帳、已結帳、出貨中、已出貨、辦理退貨 @done (14-06-20 01:27) + ✔ 身為管理者,我可以在後台對單張訂單做狀態改變 @done (14-06-20 01:56) + ✔ admin 的 order 列表應要能顯示訂單狀態 @done (14-06-20 01:56) ☐ 身為管理者,當我在將商品設為已出貨時,消費者應該收到一張已出貨的通知信
 ☐ 身為商家,當消費者確定購物結帳後,該商品的庫存必須按照數量減少 diff --git a/app/assets/javascripts/account/orders.js.coffee b/app/assets/javascripts/account/orders.js.coffee new file mode 100644 index 00000000..24f83d18 --- /dev/null +++ b/app/assets/javascripts/account/orders.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/admin/orders.js.coffee b/app/assets/javascripts/admin/orders.js.coffee new file mode 100644 index 00000000..24f83d18 --- /dev/null +++ b/app/assets/javascripts/admin/orders.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/javascripts/cart_items.js.coffee b/app/assets/javascripts/cart_items.js.coffee new file mode 100644 index 00000000..24f83d18 --- /dev/null +++ b/app/assets/javascripts/cart_items.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://coffeescript.org/ diff --git a/app/assets/stylesheets/account/orders.css.scss b/app/assets/stylesheets/account/orders.css.scss new file mode 100644 index 00000000..782d07c6 --- /dev/null +++ b/app/assets/stylesheets/account/orders.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the account::orders controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/admin/orders.css.scss b/app/assets/stylesheets/admin/orders.css.scss new file mode 100644 index 00000000..7ed90c7e --- /dev/null +++ b/app/assets/stylesheets/admin/orders.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the admin::orders controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/cart_items.css.scss b/app/assets/stylesheets/cart_items.css.scss new file mode 100644 index 00000000..c8ba3800 --- /dev/null +++ b/app/assets/stylesheets/cart_items.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the cart_items controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/account/orders_controller.rb b/app/controllers/account/orders_controller.rb new file mode 100644 index 00000000..6eae3a80 --- /dev/null +++ b/app/controllers/account/orders_controller.rb @@ -0,0 +1,10 @@ +class Account::OrdersController < ApplicationController + + before_action :authenticate_user! + + def index + @orders = current_user.orders.recent + end + + +end diff --git a/app/controllers/admin/orders_controller.rb b/app/controllers/admin/orders_controller.rb new file mode 100644 index 00000000..a94dec30 --- /dev/null +++ b/app/controllers/admin/orders_controller.rb @@ -0,0 +1,42 @@ +class Admin::OrdersController < AdminController + + before_filter :find_order, :except => [:index] + + def index + @orders = Order.recent + end + + + def show + + @order_info = @order.info + @order_items = @order.items + end + + def ship + @order.ship! + redirect_to :back + end + + def shipped + @order.deliver! + redirect_to :back + end + + def cancel + @order.cancell_order! + redirect_to :back + end + + def return + @order.return_good! + redirect_to :back + end + + protected + + + def find_order + @order = Order.find_by_token(params[:id]) + end +end diff --git a/app/controllers/cart_items_controller.rb b/app/controllers/cart_items_controller.rb new file mode 100644 index 00000000..070864f4 --- /dev/null +++ b/app/controllers/cart_items_controller.rb @@ -0,0 +1,32 @@ +class CartItemsController < ApplicationController + before_action :authenticate_user! + + + def update + @cart = current_cart + @item = @cart.cart_items.find(params[:id]) + + @item.update(item_params) + + redirect_to carts_path + end + + + def destroy + @cart = current_cart + @item = @cart.cart_items.find(params[:id]) + + @item.destroy + + flash[:warning] = "成功清空物品" + redirect_to :back + + end + + private + + def item_params + params.require(:cart_item).permit(:quantity) + end + +end diff --git a/app/controllers/orders_controller.rb b/app/controllers/orders_controller.rb index 32032fb4..4ea6ce77 100644 --- a/app/controllers/orders_controller.rb +++ b/app/controllers/orders_controller.rb @@ -8,7 +8,7 @@ def create if @order.save @order.build_item_cache_from_cart(current_cart) @order.calculate_total!(current_cart) - + current_cart.clear! OrderMailer.notify_order_placed(@order).deliver redirect_to order_path(@order.token) @@ -29,7 +29,7 @@ def pay_with_credit_card @order.make_payment! # TODO: should move to stripe callbacks - redirect_to root_path, :notice => "成功完成付款" + redirect_to account_orders_path, :notice => "成功完成付款" end private diff --git a/app/controllers/products_controller.rb b/app/controllers/products_controller.rb index 6e30196c..e2ed10ec 100644 --- a/app/controllers/products_controller.rb +++ b/app/controllers/products_controller.rb @@ -14,8 +14,14 @@ def add_to_cart @product = Product.find(params[:id]) if !current_cart.items.include?(@product) - current_cart.add_product_to_cart(@product) - flash[:notice] = "你已成功將 #{@product.title} 加入購物車" + + if @product.quantity > 0 + current_cart.add_product_to_cart(@product, 1 ) + flash[:notice] = "你已成功將 #{@product.title} 加入購物車" + else + flash[:warning] = "此物品已停止銷售,你無法將它加入購物車" + end + else flash[:warning] = "你的購物車內已有此物品" end diff --git a/app/helpers/account/orders_helper.rb b/app/helpers/account/orders_helper.rb new file mode 100644 index 00000000..6f690c4e --- /dev/null +++ b/app/helpers/account/orders_helper.rb @@ -0,0 +1,2 @@ +module Account::OrdersHelper +end diff --git a/app/helpers/admin/orders_helper.rb b/app/helpers/admin/orders_helper.rb new file mode 100644 index 00000000..e5168e1b --- /dev/null +++ b/app/helpers/admin/orders_helper.rb @@ -0,0 +1,8 @@ +module Admin::OrdersHelper + + def render_order_options_for_admin(order) + + render :partial => "admin/orders/state_option", :locals => { :order => order} + + end +end diff --git a/app/helpers/cart_items_helper.rb b/app/helpers/cart_items_helper.rb new file mode 100644 index 00000000..f30f6834 --- /dev/null +++ b/app/helpers/cart_items_helper.rb @@ -0,0 +1,2 @@ +module CartItemsHelper +end diff --git a/app/helpers/orders_helper.rb b/app/helpers/orders_helper.rb index 443227fd..9ab64522 100644 --- a/app/helpers/orders_helper.rb +++ b/app/helpers/orders_helper.rb @@ -1,2 +1,23 @@ module OrdersHelper + + def render_order_link(order) + link_to(order.token, order_path(order.token)) + end + + def render_admin_order_link(order) + link_to(order.token, admin_order_path(order.token)) + end + + def render_order_created_time(order) + order.created_at.to_s(:short) + end + + + def render_order_user_name(user) + user.email + end + + def render_order_state(order) + t("orders.order_state.#{order.aasm_state}") + end end diff --git a/app/models/cart.rb b/app/models/cart.rb index 444036b9..ebbdc623 100644 --- a/app/models/cart.rb +++ b/app/models/cart.rb @@ -13,11 +13,18 @@ class Cart < ActiveRecord::Base has_many :items, :through => :cart_items, :source => :product - def add_product_to_cart(product) - items << product + def add_product_to_cart(product, amount) + cart_item = cart_items.build + cart_item.product = product + cart_item.quantity = amount + cart_item.save end def total_price - items.inject(0) {|sum, item| sum + item.price } + cart_items.inject(0) {|sum, item| sum + (item.product.price * item.quantity) } + end + + def clear! + cart_items.delete_all end end diff --git a/app/models/order.rb b/app/models/order.rb index 68cb5f06..af666a67 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -20,13 +20,14 @@ class Order < ActiveRecord::Base accepts_nested_attributes_for :info + scope :recent, -> { order("id DESC")} def build_item_cache_from_cart(cart) - cart.items.each do |cart_item| + cart.cart_items.each do |cart_item| item = items.build - item.product_name = cart_item.title - item.quantity = 1 - item.price = cart_item.price + item.product_name = cart_item.product.title + item.quantity = cart_item.quantity + item.price = cart_item.product.price item.save end end diff --git a/app/views/account/orders/index.html.erb b/app/views/account/orders/index.html.erb new file mode 100644 index 00000000..893f28af --- /dev/null +++ b/app/views/account/orders/index.html.erb @@ -0,0 +1,24 @@ + +

訂單列表

+ + + + + + + + + + + + <% @orders.each do |order| %> + + + + + <% end %> + + +
#生成時間
<%= render_order_link(order) %> <%= render_order_created_time(order) %>
+ + diff --git a/app/views/admin/index.html.erb b/app/views/admin/index.html.erb new file mode 100644 index 00000000..e69de29b diff --git a/app/views/admin/orders/_state_option.html.erb b/app/views/admin/orders/_state_option.html.erb new file mode 100644 index 00000000..b6295622 --- /dev/null +++ b/app/views/admin/orders/_state_option.html.erb @@ -0,0 +1,23 @@ + +
+ <% case order.aasm_state %> + <% when "order_placed" %> + <%= link_to("取消訂單", cancel_admin_order_path(order.token) , :class => "btn btn-default btn-sm", :method => :post) %> + + <% when "paid" %> + <%= link_to("取消訂單", cancel_admin_order_path(order.token) , :class => "btn btn-default btn-sm", :method => :post) %> + <%= link_to("出貨", ship_admin_order_path(order.token) , :class => "btn btn-default btn-sm", :method => :post) %> + <% when "shipping" %> + <%= link_to("設為已出貨", shipped_admin_order_path(order.token), :class => "btn btn-default btn-sm", :method => :post) %> + <% when "shipped" %> + <%= link_to("退貨", return_admin_order_path(order.token), :class => "btn btn-default btn-sm", :method => :post) %> + + <% when "order_cancelled" %> + 訂單已取消 + <% when "good_returned" %> + 已退貨 + + <% end %> + +
+ diff --git a/app/views/admin/orders/index.html.erb b/app/views/admin/orders/index.html.erb new file mode 100644 index 00000000..d81161a9 --- /dev/null +++ b/app/views/admin/orders/index.html.erb @@ -0,0 +1,25 @@ + +

訂單列表

+ + + + + + + + + + + + + <% @orders.each do |order| %> + + + + + + + <% end %> + + +
#生成時間訂購者訂單狀態
<%= render_admin_order_link(order) %> <%= render_order_created_time(order) %> <%= render_order_user_name(order.user) %> <%= render_order_state(order) %>
\ No newline at end of file diff --git a/app/views/admin/orders/show.html.erb b/app/views/admin/orders/show.html.erb new file mode 100644 index 00000000..5807e4f2 --- /dev/null +++ b/app/views/admin/orders/show.html.erb @@ -0,0 +1,89 @@ +
+
+ +

訂單明細

+ + <%= render_order_options_for_admin(@order) %> + + + + + + + + + + + <% @order_items.each do |order_item| %> + + + + + + <% end %> + + +
商品明細單價數量
+ <%= order_item.product_name %> + <%= order_item.price %> <%= order_item.quantity %>
+ +
+ + 總計 <%= @order.total %> NTD + +
+ +
+ +

寄送資訊

+ + + + + + + + + + + + + + + + + + + + + + + +
訂購人
+ <%= @order_info.billing_name %> - <%= @order_info.billing_address %> +
訂購人
+ <%= @order_info.billing_name %> - <%= @order_info.billing_address %> +
+ + + <% if !@order.paid? %> + +
+ <%= link_to("以信用卡付款", pay_with_credit_card_order_path(@order.token), :class => "btn btn-primary btn-lg btn-danger ") %> + + <%= link_to("以 ATM 付款", "#", :class => "btn btn-primary btn-lg btn-danger ") %> +
+ + <% else %> + + 此訂單已完成付款 + + <% end %> + + + + +
+ + +
diff --git a/app/views/carts/checkout.html.erb b/app/views/carts/checkout.html.erb index a1637402..a6bfc7ac 100644 --- a/app/views/carts/checkout.html.erb +++ b/app/views/carts/checkout.html.erb @@ -8,16 +8,18 @@ 商品明細 單價 + 數量 - <% current_cart.items.each do |product| %> + <% current_cart.cart_items.each do |cart_item| %> - <%= link_to(product.title, admin_product_path(product)) %> + <%= link_to(cart_item.product.title, admin_product_path(cart_item.product)) %> - <%= product.price %> + <%= cart_item.product.price %> + <%= cart_item.quantity %> <% end %> diff --git a/app/views/carts/index.html.erb b/app/views/carts/index.html.erb index 14c5a65f..e6a6f74c 100644 --- a/app/views/carts/index.html.erb +++ b/app/views/carts/index.html.erb @@ -9,19 +9,42 @@ 商品資訊 單價 + + - <% current_cart.items.each do |product| %> + <% current_cart.cart_items.each do |item| %> - <%= render_product_photo(product.default_photo) %> + <%= render_product_photo(item.product.default_photo) %> - <%= link_to(product.title, admin_product_path(product)) %> + <%= link_to(item.product.title, admin_product_path(item.product)) %> - <%= product.price %> + <%= item.product.price %> + + + + <%= form_for item, :url => cart_item_path(current_cart, item) do |f| %> + <%= f.select :quantity, [1,2,3,4,5] %> + + <%= button_tag(type: 'submit', class: "btn btn-default btn-xs") do %> + + <% end %> + + + <% end -%> + + + + + + <%= link_to cart_item_path(current_cart, item), :method => :delete do %> + + <% end %> + <% end %> diff --git a/app/views/common/_navbar.html.erb b/app/views/common/_navbar.html.erb index 4ecfa912..41356da3 100644 --- a/app/views/common/_navbar.html.erb +++ b/app/views/common/_navbar.html.erb @@ -37,6 +37,7 @@