Commit 857001a1 by Tran Hoang Viet

Merge branch 'vietth_feat_order_management' into vietth_feat_additional

Conflicts:
	Gemfile
	app/views/layouts/_header.html.haml
	app/views/layouts/application.html.haml
	app/views/orders/index.html.haml
parents e8423022 bae6f988
......@@ -68,7 +68,8 @@ gem 'draper', '~> 2.1.0'
gem 'devise', '~> 3.5.1'
gem 'rolify', '~> 4.0.0'
gem 'cancan', '~> 1.6.10'
gem 'pundit', '~> 1.0.1'
# gem 'cancan', '~> 1.6.10'
gem 'carrierwave', '~> 0.10.0'
gem 'mini_magick', '~> 3.8.1'
......@@ -100,4 +101,4 @@ gem 'font-awesome-rails', '~> 4.3.0.0'
gem 'meta-tags', '~> 2.0.0'
gem 'fog', '~> 1.32.0'
\ No newline at end of file
gem 'fog', '~> 1.32.0'
......@@ -48,7 +48,6 @@ GEM
builder (3.2.2)
byebug (5.0.0)
columnize (= 0.9.0)
cancan (1.6.10)
capistrano (3.4.0)
i18n
rake (>= 10.0.0)
......@@ -286,6 +285,8 @@ GEM
pry (~> 0.10)
pry-rails (0.3.4)
pry (>= 0.9.10)
pundit (1.0.1)
activesupport (>= 3.0.0)
quiet_assets (1.1.0)
railties (>= 3.1, < 5.0)
rack (1.6.4)
......@@ -433,7 +434,6 @@ PLATFORMS
DEPENDENCIES
byebug
cancan (~> 1.6.10)
capistrano-rails
capistrano-rvm
capistrano-sidekiq (~> 0.5.2)
......@@ -460,6 +460,7 @@ DEPENDENCIES
mysql2
pry-byebug
pry-rails (~> 0.3.4)
pundit (~> 1.0.1)
quiet_assets
rails (= 4.2.3)
rails_12factor (~> 0.0.3)
......
class Admin::OrdersController < ApplicationController
before_action :set_order, only: [:show, :update]
before_action -> { authorize(@order) }, only: [:show, :update]
def index
@orders = Order.all.includes(:user).order(created_at: :desc).page(params[:page])
end
def show
end
def update
if order_service.update(@order, order_params)[:status].present?
redirect_to admin_orders_path, notice: 'Update order successful!'
else
render :show
end
end
private
def order_params
params.require(:order).permit(:status)
end
def order_service
@order_service ||= OrderService.new(current_user, params)
end
def set_order
@order = Order.find(params[:id])
end
end
\ No newline at end of file
class ApplicationController < ActionController::Base
include Pundit
include MetaManagement
rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found
rescue_from CanCan::AccessDenied do |exception|
redirect_to root_path, :alert => exception.message
end
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
layout Proc.new { |controller| controller.devise_controller? ? 'devise' : 'application' }
......@@ -26,4 +25,8 @@ class ApplicationController < ActionController::Base
redirect_to(root_path, alert: "Resource not found")
end
def user_not_authorized
redirect_to root_path, alert: 'You are not authorized to perform this action.'
end
end
\ No newline at end of file
class OrdersController < ApplicationController
load_and_authorize_resource :order, only: [:show, :update]
before_action :authenticate_user!
before_action :set_order, only: [:show, :update]
before_action -> { authorize(@order) }, only: [:show, :update]
def index
@orders = current_user.orders.includes(:user).order(created_at: :desc).page(params[:page])
end
def create
......@@ -22,32 +22,19 @@ class OrdersController < ApplicationController
end
end
def management
@orders = current_user.admin? ? Order.all : current_user.orders
@orders = @orders.includes(:user).order(created_at: :desc).page(params[:page])
def checkout
end
def show
end
def update
if order_service.update(@order, order_params)[:status].present?
redirect_to management_orders_path, notice: 'Update order successful!'
else
render :show
end
end
private
def cart_params
params.require(:cart).permit(items: [:id, :quantity])
end
def order_params
params.require(:order).permit(:status)
end
def order_service
@order_service ||= OrderService.new(current_user, params)
end
......
class Ability
include CanCan::Ability
attr_reader :user
def initialize(current_user)
@user = current_user || User.new # guest user (not logged in)
if user.admin?
permission_admin
else
permission_user
end
end
def permission_admin
can :manage, :all
end
def permission_user
can :read, Order do |order|
order.user == user
end
end
end
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
@user = user
@record = record
end
def index?
false
end
def show?
scope.where(:id => record.id).exists?
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
def scope
Pundit.policy_scope!(user, record.class)
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
@user = user
@scope = scope
end
def resolve
scope
end
end
end
class OrderPolicy < ApplicationPolicy
def update?
user.admin?
end
def show?
record.user == user || user.admin?
end
end
\ No newline at end of file
......@@ -27,7 +27,7 @@ class CartService < BaseService
end
def update_cart(items)
products = Product.where(items.map { |item| item['id'] })
products = Product.where(id: items.map { |item| item['id'] })
products = products.inject({}) do |list, product|
list[product.id.to_s] = product
list
......
%h3.title Orders management
.module
#orders-list
.order-item.table-responsive
%table.table
%thead
%tr
%td.text-right #
%td Order number
/ %td Ordered by
%td Created at
%td Status
%tbody
- @orders.each_with_index do |order_item, index|
%tr
%td.number.text-right
= index + 1
%td.order-number
= link_to order_item.created_at.to_i, admin_order_path(order_item)
/ %td.created-by
/ = order_item.user.email
%td.created-at
= I18n.l(order_item.created_at)
%td.status{class: order_item.status}
= order_item.decorate.status
%tfooter
%tr
%td{colspan: 10}
= paginate @orders
%h3.title Order detail
#order-detail.module
= form_for @order, url: admin_order_path(@order), html: {class: 'form-horizontal'} do |f|
.form-group
%label.col-md-2.col-sm-3.col-xs-3.control-label Order number
.col-md-4.col-sm-9.col-xs-9.value
= f.object.created_at.to_i
.form-group
%label.col-md-2.col-sm-3.col-xs-3.control-label Created by
.col-md-4.col-sm-9.col-xs-9.value
= f.object.user.email
.form-group
%label.col-md-2.col-sm-3.col-xs-3.control-label Created at
.col-md-4.col-sm-9.col-xs-9.value
= I18n.l(f.object.created_at)
.form-group
%label.col-md-2.col-sm-3.col-xs-3.control-label Total price
.col-md-4.col-sm-9.col-xs-9.value
= f.object.total
.form-group
%label.col-md-2.col-sm-3.col-xs-3.control-label Status
.col-md-2.col-sm-9.col-xs-9.value
- if policy(f.object).update?
= f.select :status, Order.statuses.keys.map { |status| [status.titleize, status] }, {}, class: 'form-control'
- else
= f.object.status.titleize
- if policy(f.object).update?
.form-group
%label.col-md-2.col-sm-3.col-xs-3.control-label
.col-md-2.col-sm-4.col-xs-9
= f.submit 'Save', class: 'btn btn-primary'
.list-order-items.table-responsive
= render '/orders/order_items', order_items: @order.order_items
......@@ -15,4 +15,4 @@
Total:
= current_user.cart.total
.checkout.col-md-12
= link_to 'Checkout', orders_path, class: 'btn btn-primary'
= link_to 'Checkout', checkout_orders_path, class: 'btn btn-primary'
......@@ -11,10 +11,13 @@
#navbar.navbar-collapse.collapse
%ul.nav.navbar-nav.navbar-right
- if user_signed_in?
%li
= link_to 'Orders', management_orders_path
/ %li
/ = link_to 'My products', products_path(current_user)
- if current_user.admin?
%li
= link_to 'Orders', admin_orders_path
- else
%li
= link_to 'Orders', orders_path
%li
= link_to 'New product', new_product_path
%li
......
%h3.title Category
%ul.nav.nav-sidebar
= render Category.limit(Settings.limit_category).select(Category::JSON_DEFAULT)
\ No newline at end of file
= render partial: '/categories/category', collection: Category.limit(Settings.limit_category).select(Category::JSON_DEFAULT)
\ No newline at end of file
......@@ -9,10 +9,10 @@
%body
%nav.navbar.navbar-inverse.navbar-fixed-top
.container-fluid
= render 'layouts/header'
= render '/layouts/header'
#wrapper.container-fluid
= render 'layouts/message'
= render '/layouts/message'
.row.search-wrapper
= render 'layouts/breadcrumb'
......@@ -21,13 +21,13 @@
.col-md-2.sidebar
.row
.col-md-12
= render 'layouts/sidebar'
= render '/layouts/sidebar'
.row
.col-md-12
= render 'layouts/cart'
= render '/layouts/cart'
.row
.col-md-12
= render 'layouts/share_social'
= render '/layouts/share_social'
.col-md-10
= yield
......
%table.table
%thead
%tr
%td.text-right #
%td Title
%td Price
%td Quantity
%tbody
- order_items.each_with_index do |order_item, index|
%tr
%td.number.text-right
= index + 1
%td.title
= link_to order_item.product.title, product_path(order_item.product_id)
%td.price
= order_item.product.price
%td.quantity
= order_item.quantity
\ No newline at end of file
%h3.title Checkout
- if cart_valid?
#checkout-cart.table-responsive
= form_for Order.new do |f|
%table.table
%thead
%tr
%td.text-right #
%td Title
%td Price
%td Stock
%td Quantity
%tbody
- current_user.cart.items.each_with_index do |order_item, index|
%tr
%td.number.text-right
= index + 1
%td.title
= link_to order_item.name, product_path(order_item.id)
= hidden_field_tag "cart[items][#{index}][id]", order_item.id
%td.price
= order_item.unit_cost
%td
= order_item.stock
%td.quantity
.customize-spinner.input-group.spinner{"data-trigger" => "spinner"}
= text_field_tag "cart[items][#{index}][quantity]", order_item.quantity, data: {max: order_item.stock, min: 1, step: 1, id: order_item.id}, class: 'form-control'
.input-group-addon
%a.spin-up{"data-spin" => "up", href: "javascript:;"}
%i.fa.fa-sort-up
%a.spin-down{"data-spin" => "down", href: "javascript:;"}
%i.fa.fa-sort-down
%tfoot
%tr
%td#total-price-title.text-right{colspan: 2} Total:
%td#total-price{colspan: 3}
= format_price(current_user.cart.total)
%tr
%td.no-border.text-right{colspan: 5}
= f.submit 'Checkout', class: 'btn btn-primary'
:javascript
var items = #{current_user.cart.items.to_json.html_safe}
window.orderLib.setOptions({items: items})
window.orderLib.setEventChangeQuantity()
\ No newline at end of file
%h3.title Checkout
- if cart_valid?
#checkout-cart.table-responsive
= form_for Order.new do |f|
%table.table.table-hover
%h3.title Orders management
.module
#orders-list
.order-item.table-responsive
%table.table
%thead
%tr
%td.text-right #
%td.text-center Image
%td Title
%td Price
%td Stock
%td Quantity
%td Order number
/ %td Ordered by
%td Created at
%td Status
%tbody
- current_user.cart.items.each_with_index do |order_item, index|
- @orders.each_with_index do |order_item, index|
%tr
%td.number.text-right
= index + 1
%td
.image
= image_tag order_item.image
%td.title
= link_to order_item.name, product_path(order_item.id)
= hidden_field_tag "cart[items][#{index}][id]", order_item.id
%td.price
= order_item.unit_cost
%td
= order_item.stock
%td.quantity
.customize-spinner.input-group.spinner{"data-trigger" => "spinner"}
= text_field_tag "cart[items][#{index}][quantity]", order_item.quantity, data: {max: order_item.stock, min: 1, step: 1, id: order_item.id}, class: 'form-control'
.input-group-addon
%a.spin-up{"data-spin" => "up", href: "javascript:;"}
%i.fa.fa-sort-up
%a.spin-down{"data-spin" => "down", href: "javascript:;"}
%i.fa.fa-sort-down
%tfoot
%tr
%td#total-price-title.text-right{colspan: 3} Total:
%td#total-price{colspan: 4}
= format_price(current_user.cart.total)
%td.order-number
= link_to order_item.created_at.to_i, order_path(order_item)
/ %td.created-by
/ = order_item.user.email
%td.created-at
= I18n.l(order_item.created_at)
%td.status{class: order_item.status}
= order_item.decorate.status
%tfooter
%tr
%td.no-border.text-right{colspan: 6}
= f.submit 'Checkout', class: 'btn btn-primary'
:javascript
var items = #{current_user.cart.items.to_json.html_safe}
window.orderLib.setOptions({items: items})
window.orderLib.setEventChangeQuantity()
\ No newline at end of file
%td{colspan: 10}
= paginate @orders
%h3.title Orders management
.module
#orders-list
.order-item.table-responsive
%table.table
%thead
%tr
%td.text-right #
%td Order number
/ %td Ordered by
%td Created at
%td Status
%tbody
- @orders.each_with_index do |order_item, index|
%tr
%td.number.text-right
= index + 1
%td.order-number
= link_to order_item.created_at.to_i, order_path(order_item)
/ %td.created-by
/ = order_item.user.email
%td.created-at
= I18n.l(order_item.created_at)
%td.status{class: order_item.status}
= order_item.decorate.status
%tfooter
%tr
%td{colspan: 10}
= paginate @orders
......@@ -24,33 +24,17 @@
.form-group
%label.col-md-2.col-sm-3.col-xs-3.control-label Status
.col-md-2.col-sm-9.col-xs-9.value
- if can?(:update, f.object)
- if policy(f.object).update?
= f.select :status, Order.statuses.keys.map { |status| [status.titleize, status] }, {}, class: 'form-control'
- else
= f.object.status.titleize
- if can?(:update, f.object)
- if policy(f.object).update?
.form-group
%label.col-md-2.col-sm-3.col-xs-3.control-label
.col-md-2.col-sm-4.col-xs-9
= f.submit 'Save', class: 'btn btn-primary'
.list-order-items.table-responsive
%table.table
%thead
%tr
%td.text-right #
%td Title
%td Price
%td Quantity
%tbody
- @order.order_items.each_with_index do |order_item, index|
%tr
%td.number.text-right
= index + 1
%td.title
= link_to order_item.product.title, product_path(order_item.id)
%td.price
= order_item.product.price
%td.quantity
= order_item.quantity
= render '/orders/order_items', order_items: @order.order_items
......@@ -18,7 +18,11 @@ Rails.application.routes.draw do
resources :orders do
collection do
get :management
get :checkout
end
end
namespace :admin do
resources :orders
end
end
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment