comable-backend 0.7.0.beta2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a9a4aab8272e2f6d7559b2b904eff5dae392ac9b
4
- data.tar.gz: 6a467557d5063f57772c037adddabc6099bfce7a
3
+ metadata.gz: 468193b091875f22c8f2f66c4c7a39f4303514ea
4
+ data.tar.gz: 32459c209919309b128b318c4e3292aa84fb13d1
5
5
  SHA512:
6
- metadata.gz: 74082e26be423fa71b1d3196d9daf07251b106665314a77bde732c3a77812bb63a27853149375dd8ee14f763e620107788328e657de86291782a5223603a9c61
7
- data.tar.gz: cfa9c867269a22cb149cea5f1a5e69f67dd73fe40dc9b7e69985a0972bd5718a21ad8d17858a4e7a24dde9483096aa27e146ae4cd0e3faf6ef422c478db08cac
6
+ metadata.gz: 2fcf1ee77d9ef16c1a212ab958953cb7678ca29cead72042c9dd5864ce1a5ddad930f65676ef1c6dcba55a3acee473e428e907be633c24130e69d69d93b60dce
7
+ data.tar.gz: f54d0897d8ce819717a88661c35f189d384022df41f19f63de831ff626ec85ef433ec02d12c331a67251917b6d51fbf0065685b48851e4ead33723632347b07a
@@ -54,11 +54,12 @@ initialize_select2 = ->
54
54
  $select = $(this)
55
55
  options = { theme: 'bootstrap' }
56
56
  if $select.hasClass('ajax')
57
+ term_column = $select.data('term') || ['name_cont']
57
58
  options.ajax = {
58
59
  url: $select.data('source')
59
60
  dataType: 'json'
60
61
  cache: true
61
- data: (params) -> { q: { name_cont: params.term }, page: params.page }
62
+ data: (params) -> { q: { "#{term_column}" : params.term }, page: params.page }
62
63
  processResults: (data, page) -> { results: data }
63
64
  }
64
65
  $select.select2(options)
@@ -15,7 +15,11 @@ class Dispatcher
15
15
  action_name = path[1]
16
16
 
17
17
  switch page
18
- when 'orders:edit', 'pages:update'
18
+ when 'draft_orders:new', 'draft_orders:create', 'draft_orders:edit', 'draft_orders:update'
19
+ new OrderItemBuilder
20
+ new UserSelector
21
+ new DynamicOrder
22
+ when 'orders:new', 'orders:create', 'orders:edit', 'orders:update'
19
23
  new DynamicOrder
20
24
  when 'pages:new', 'pages:show', 'pages:edit', 'pages:update', 'pages:create'
21
25
  new Page
@@ -7,7 +7,7 @@ class @DynamicOrder
7
7
 
8
8
  listen_events: ->
9
9
  self = this
10
- $('input').on('change', ->
10
+ $(document).on('change', 'input', ->
11
11
  attribute_name = $(this).attr('data-name')
12
12
  return unless jQuery.inArray(attribute_name, self.refresh_trigger_attributes)
13
13
  self.refresh_order_item_prices_for(this)
@@ -18,7 +18,7 @@ class @DynamicOrder
18
18
 
19
19
  $price = $group.find('[data-name="price"]')
20
20
  $quantity = $group.find('[data-name="quantity"]')
21
- $subtotal_price = $group.find('[data-name="subtotal_price"]')
21
+ $subtotal_price = $group.find('[data-name="subtotal-price"]')
22
22
 
23
23
  price = Number($price.val())
24
24
  quantity = Number($quantity.val())
@@ -28,14 +28,14 @@ class @DynamicOrder
28
28
 
29
29
  refresh_order_prices: ->
30
30
  item_total_price = 0
31
- $('[data-name="subtotal_price"]').each( ->
31
+ $('[data-name="subtotal-price"]').each( ->
32
32
  item_total_price += Number($(this).val())
33
33
  )
34
34
 
35
- $item_total_price = $('[data-name="item_total_price"]')
36
- $payment_fee = $('[data-name="payment_fee"]')
37
- $shipment_fee = $('[data-name="shipment_fee"]')
38
- $total_price = $('[data-name="total_price"]')
35
+ $item_total_price = $('[data-name="item-total-price"]')
36
+ $payment_fee = $('[data-name="payment-fee"]')
37
+ $shipment_fee = $('[data-name="shipment-fee"]')
38
+ $total_price = $('[data-name="total-price"]')
39
39
 
40
40
  payment_fee = Number($payment_fee.val())
41
41
  shipment_fee = Number($shipment_fee.val())
@@ -0,0 +1,42 @@
1
+ class @OrderItemBuilder
2
+ NEW_ORDER_ITEM_SELECTOR = '.js-new-order-item'
3
+ LINK_TO_REMOVE_ORDER_ITEM_SELECTOR = '.js-remove-order-item'
4
+
5
+ constructor: ->
6
+ @setSelectors()
7
+ @$variantSelector.on('select2:select', (event) => @buildOrderItem(event.params.data))
8
+ $(document).on('click', LINK_TO_REMOVE_ORDER_ITEM_SELECTOR, (event) => @removeOrderItem(event.target))
9
+
10
+ setSelectors: ->
11
+ @$variantSelector = $('#js-variant-selector')
12
+ @$linkToAddOrderItem = $('#js-add-order-item')
13
+ @$orderItemsTable = $('#js-order-items-table').find('tbody')
14
+
15
+ buildOrderItem: (variant) ->
16
+ $orderItem = @newOrderItem()
17
+ @fillOrderItem($orderItem, variant)
18
+ @$orderItemsTable.append($orderItem)
19
+ @refreshPricesFor($orderItem)
20
+
21
+ # TODO: Commonize this method
22
+ newOrderItem: ->
23
+ newId = new Date().getTime()
24
+ @$linkToAddOrderItem.click()
25
+ $orderItem = $(NEW_ORDER_ITEM_SELECTOR).filter('.hidden').last()
26
+ $orderItem.removeClass('hidden')
27
+ $orderItem.html($orderItem.html().replace(/new_order_item/g, newId))
28
+ $orderItem
29
+
30
+ fillOrderItem: ($orderItem, variant) ->
31
+ $orderItem.find('[data-name="variant-id"]').val(variant.id)
32
+ $orderItem.find('[data-name="name"]').val(variant.text)
33
+ $orderItem.find('[data-name="sku"]').val(variant.sku)
34
+ $orderItem.find('[data-name="price"]').val(variant.price)
35
+ $orderItem.find('[data-name="subtotal-price"]').val(variant.price)
36
+ $orderItem.find('[data-name="image-url"]').attr('src', variant.image_url)
37
+
38
+ removeOrderItem: (element) ->
39
+ $(element).closest(NEW_ORDER_ITEM_SELECTOR).remove()
40
+
41
+ refreshPricesFor: ($orderItem) ->
42
+ $orderItem.find('[data-name="price"]').trigger('change')
@@ -0,0 +1,15 @@
1
+ class @UserSelector
2
+ constructor: ->
3
+ @setSelectors()
4
+ @$userSelector.on('select2:select', (event) => @fillUser(event.params.data))
5
+
6
+ setSelectors: ->
7
+ @$userSelector = $('#js-user-selector')
8
+ @$user = $('#js-user-fields')
9
+
10
+ fillUser: (user) ->
11
+ @$user.find('[data-name="email"]').val(user.email)
12
+ @$user.find('[data-name="bill-family-name"]').val(user.bill_address.family_name)
13
+ @$user.find('[data-name="bill-first-name"]').val(user.bill_address.first_name)
14
+ @$user.find('[data-name="bill-zip-code"]').val(user.bill_address.zip_code)
15
+ @$user.find('[data-name="bill-state-name"]').val(user.bill_address.state_name)
@@ -0,0 +1,88 @@
1
+ require_dependency 'comable/admin/application_controller'
2
+
3
+ module Comable
4
+ module Admin
5
+ class DraftOrdersController < Comable::Admin::ApplicationController
6
+ include Comable::PermittedAttributes
7
+
8
+ load_and_authorize_resource :order, parent: false, class: Comable::DraftOrder.name
9
+
10
+ def index
11
+ @q = Comable::Order.draft.ransack(params[:q])
12
+ @orders = @q.result.page(params[:page]).per(15).recent.accessible_by(current_ability)
13
+ end
14
+
15
+ def show
16
+ render :edit
17
+ end
18
+
19
+ def new
20
+ build_associations
21
+ end
22
+
23
+ def create
24
+ if save_order_as_draft
25
+ @order.update!(draft: false) if @order.completed?
26
+ redirect_to admin_order_path, notice: Comable.t('successful')
27
+ else
28
+ build_associations
29
+ flash.now[:alert] = Comable.t('failure')
30
+ render :new
31
+ end
32
+ end
33
+
34
+ def edit
35
+ end
36
+
37
+ def update
38
+ @order.attributes = order_params
39
+
40
+ if save_order_as_draft
41
+ @order.update!(draft: false) if @order.completed?
42
+ redirect_to admin_order_path, notice: Comable.t('successful')
43
+ else
44
+ flash.now[:alert] = Comable.t('failure')
45
+ render :edit
46
+ end
47
+ end
48
+
49
+ private
50
+
51
+ def admin_order_path
52
+ if @order.draft?
53
+ comable.admin_draft_order_path(@order)
54
+ else
55
+ comable.admin_order_path(@order)
56
+ end
57
+ end
58
+
59
+ def save_order_as_draft
60
+ @order.next_draft_state
61
+ rescue ActiveRecord::RecordInvalid
62
+ false
63
+ end
64
+
65
+ # rubocop:disable Metrics/MethodLength
66
+ def order_params
67
+ params.require(:order).permit(
68
+ :id,
69
+ :user_id,
70
+ :email,
71
+ :same_as_bill_address,
72
+ bill_address_attributes: permitted_address_attributes,
73
+ ship_address_attributes: permitted_address_attributes,
74
+ order_items_attributes: [:id, :name, :sku, :price, :quantity, :variant_id],
75
+ payment_attributes: [:id, :_destroy, :payment_method_id],
76
+ shipments_attributes: [:id, :_destroy, :shipment_method_id]
77
+ )
78
+ end
79
+ # rubocop:enable Metrics/MethodLength
80
+
81
+ def build_associations
82
+ @order.build_bill_address unless @order.bill_address
83
+ @order.build_ship_address unless @order.ship_address
84
+ @order.build_payment unless @order.payment
85
+ end
86
+ end
87
+ end
88
+ end
@@ -18,6 +18,10 @@ module Comable
18
18
  def show
19
19
  end
20
20
 
21
+ def new
22
+ redirect_to comable.new_admin_draft_order_path
23
+ end
24
+
21
25
  def edit
22
26
  end
23
27
 
@@ -87,7 +91,7 @@ module Comable
87
91
  :total_price,
88
92
  bill_address_attributes: permitted_address_attributes,
89
93
  ship_address_attributes: permitted_address_attributes,
90
- order_items_attributes: [:id, :name, :code, :price, :quantity]
94
+ order_items_attributes: [:id, :name, :price, :quantity]
91
95
  )
92
96
  end
93
97
 
@@ -10,6 +10,11 @@ module Comable
10
10
  def index
11
11
  @q = Comable::User.ransack(params[:q])
12
12
  @users = @q.result.page(params[:page]).accessible_by(current_ability).by_newest
13
+
14
+ respond_to do |format|
15
+ format.html
16
+ format.json { render json: @users }
17
+ end
13
18
  end
14
19
 
15
20
  def show
@@ -3,12 +3,20 @@ require_dependency 'comable/admin/application_controller'
3
3
  module Comable
4
4
  module Admin
5
5
  class VariantsController < Comable::Admin::ApplicationController
6
- load_and_authorize_resource :product, class: Comable::Product.name
7
- load_and_authorize_resource :variant, class: Comable::Variant.name, through: :product
6
+ # for /admin/variants
7
+ load_and_authorize_resource :variant, class: Comable::Variant.name, only: :index
8
+
9
+ # for /admin/products/:product_id/variants/:id
10
+ load_and_authorize_resource :product, class: Comable::Product.name, except: :index
11
+ load_and_authorize_resource :variant, class: Comable::Variant.name, except: :index, through: :product
8
12
 
9
13
  def index
10
14
  @q = @variants.ransack(params[:q])
11
15
  @variants = @q.result.includes(:product).page(params[:page]).accessible_by(current_ability).by_newest
16
+
17
+ respond_to do |format|
18
+ format.json { render json: @variants }
19
+ end
12
20
  end
13
21
 
14
22
  def show
@@ -13,7 +13,7 @@ AwesomeAdminLayout.define(only: Comable::Admin::ApplicationController) do |contr
13
13
  end
14
14
 
15
15
  item Comable.t('admin.nav.order') do
16
- link comable.admin_orders_path
16
+ nest :orders
17
17
  icon 'shopping-cart'
18
18
  end
19
19
 
@@ -43,6 +43,18 @@ AwesomeAdminLayout.define(only: Comable::Admin::ApplicationController) do |contr
43
43
  end
44
44
  end
45
45
 
46
+ navigation :orders do
47
+ brand Comable.t('admin.nav.order')
48
+
49
+ item Comable.t('admin.nav.order') do
50
+ link comable.admin_orders_path
51
+ end
52
+
53
+ item Comable.t('admin.nav.draft_order') do
54
+ link comable.admin_draft_orders_path
55
+ end
56
+ end
57
+
46
58
  navigation :products do
47
59
  brand Comable.t('admin.nav.product')
48
60
 
@@ -0,0 +1,179 @@
1
+ = error_messages_for @order
2
+
3
+ = form_for [comable, :admin, :draft, @order] do |f|
4
+ .hidden
5
+ = f.submit
6
+
7
+ .col-md-6
8
+ .row
9
+ fieldset
10
+ .col-md-3
11
+ legend
12
+ = f.object.class.human_attribute_name(:order_items)
13
+ .help-block
14
+
15
+ .col-md-9
16
+ - if @order.new_record?
17
+ .form-group
18
+ = select_tag :variant, nil, id: 'js-variant-selector', class: 'select2 ajax', data: { source: comable.admin_variants_path, term: :product_name_cont }
19
+ = link_to_add_fields nil, f, :order_items, id: 'js-add-order-item', class: 'hidden'
20
+
21
+ table.table#js-order-items-table
22
+ thead
23
+ tr
24
+ th colspan="2"
25
+ = f.object.order_items.klass.human_attribute_name(:product)
26
+ th
27
+ = f.object.order_items.klass.human_attribute_name(:price)
28
+ th
29
+ = f.object.order_items.klass.human_attribute_name(:quantity)
30
+ th
31
+ = f.object.order_items.klass.human_attribute_name(:subtotal_price)
32
+ tbody
33
+ = f.fields_for :order_items do |ff|
34
+ = render 'comable/admin/shared/order_items_fields', f: ff
35
+ tfoot
36
+ tr
37
+ th.text-right colspan="4"
38
+ = f.object.class.human_attribute_name(:item_total_price)
39
+ td
40
+ = f.text_field :item_total_price, disabled: true, data: { name: 'item-total-price' }
41
+
42
+ .form-group
43
+ = f.fields_for :payment do |ff|
44
+ .panel.panel-default
45
+ .panel-heading
46
+ = f.object.class.human_attribute_name(:payment_method)
47
+
48
+ ul.list-group
49
+ = ff.collection_radio_buttons :payment_method_id, Comable::PaymentMethod.all, :id, :name do |b|
50
+ li.list-group-item
51
+ .radio
52
+ = b.label do
53
+ = b.radio_button
54
+ strong
55
+ = b.text
56
+ p
57
+ = "#{b.object.class.human_attribute_name(:fee)}: "
58
+ = number_to_currency b.object.fee
59
+
60
+ - if @order.shipment?
61
+ .form-group
62
+ = f.fields_for :shipments do |ff|
63
+ .panel.panel-default
64
+ .panel-heading
65
+ | #{f.object.class.human_attribute_name(:shipment_method)} ##{ff.index.next}
66
+
67
+ ul.list-group
68
+ = ff.collection_radio_buttons :shipment_method_id, Comable::ShipmentMethod.all, :id, :name do |b|
69
+ li.list-group-item
70
+ .radio
71
+ = b.label do
72
+ = b.radio_button
73
+ strong
74
+ = b.text
75
+ p
76
+ = "#{b.object.class.human_attribute_name(:fee)}: "
77
+ = number_to_currency b.object.fee
78
+
79
+ .col-md-6#js-user-fields
80
+ .row
81
+ fieldset
82
+ .col-md-3
83
+ legend
84
+ = Comable.t('admin.user')
85
+ .help-block
86
+
87
+ .col-md-9
88
+ - if @order.new_record?
89
+ .form-group
90
+ = f.collection_select :user_id, [@order.user].compact, :id, :text, {}, id: 'js-user-selector', class: 'select2 ajax', data: { source: comable.admin_users_path, term: :email_or_bill_address_full_name_cont }
91
+
92
+ .form-group
93
+ = f.label :email
94
+ = f.email_field :email, data: { name: 'email' }
95
+
96
+ - if f.object.bill_address
97
+ hr
98
+
99
+ fieldset
100
+ .col-md-3
101
+ legend
102
+ = f.object.class.human_attribute_name(:bill_address)
103
+ .help-block
104
+
105
+ .col-md-9
106
+ = f.fields_for :bill_address do |ff|
107
+ .form-group
108
+ = ff.label :full_name
109
+ .row
110
+ .col-sm-6
111
+ = ff.text_field :family_name, placeholder: ff.object.class.human_attribute_name(:family_name), data: { name: 'bill-family-name' }
112
+ .col-sm-6
113
+ = ff.text_field :first_name, placeholder: ff.object.class.human_attribute_name(:first_name), data: { name: 'bill-first-name' }
114
+
115
+ .form-group
116
+ = ff.label :zip_code
117
+ = ff.text_field :zip_code, max_length: 8, data: { name: 'bill-zip-code' }
118
+
119
+ .form-group
120
+ = ff.label :state_name
121
+ = ff.text_field :state_name, data: { name: 'bill-state-name' }
122
+
123
+ .form-group
124
+ = ff.label :city
125
+ = ff.text_field :city, data: { name: 'bill-city' }
126
+
127
+ .form-group
128
+ = ff.label :detail
129
+ = ff.text_field :detail, data: { name: 'bill-detail' }
130
+
131
+ .form-group
132
+ = ff.label :phone_number
133
+ = ff.text_field :phone_number, max_length: 18, data: { name: 'bill-phone-number' }
134
+
135
+ - if f.object.ship_address
136
+ hr
137
+
138
+ fieldset
139
+ .col-md-3
140
+ legend
141
+ = f.object.class.human_attribute_name(:ship_address)
142
+ .help-block
143
+
144
+ .col-md-9
145
+ .form-group
146
+ .checkbox
147
+ label
148
+ = f.check_box :same_as_bill_address, data: { name: 'same-as-bill-address' }
149
+ = f.object.class.human_attribute_name(:same_as_bill_address)
150
+
151
+ #js-ship-address-fields
152
+ = f.fields_for :ship_address do |ff|
153
+ .form-group
154
+ = ff.label :full_name
155
+ .row
156
+ .col-sm-6
157
+ = ff.text_field :family_name, placeholder: ff.object.class.human_attribute_name(:family_name), data: { name: 'ship-family-name' }
158
+ .col-sm-6
159
+ = ff.text_field :first_name, placeholder: ff.object.class.human_attribute_name(:first_name), data: { name: 'ship-first-name' }
160
+
161
+ .form-group
162
+ = ff.label :zip_code
163
+ = ff.text_field :zip_code, max_length: 8, data: { name: 'ship-zip-code' }
164
+
165
+ .form-group
166
+ = ff.label :state_name
167
+ = ff.text_field :state_name, data: { name: 'ship-state-name' }
168
+
169
+ .form-group
170
+ = ff.label :city
171
+ = ff.text_field :city, data: { name: 'ship-city' }
172
+
173
+ .form-group
174
+ = ff.label :detail
175
+ = ff.text_field :detail, data: { name: 'ship-detail' }
176
+
177
+ .form-group
178
+ = ff.label :phone_number
179
+ = ff.text_field :phone_number, max_length: 18, data: { name: 'ship-phone-number' }
@@ -0,0 +1,18 @@
1
+ .comable-page
2
+ .comable-main-fixed-top
3
+ .comable-page-heading
4
+ ul.pull-right.list-inline
5
+ li
6
+ = link_to_save
7
+
8
+ h1.page-header
9
+ ol.breadcrumb
10
+ li>
11
+ = link_to Comable.t('admin.nav.draft_order'), comable.admin_draft_orders_path
12
+ li>
13
+ = link_to @order.code, comable.admin_draft_order_path(@order)
14
+ li.active
15
+ = Comable.t('admin.actions.edit')
16
+
17
+ .comable-page-body
18
+ = render 'form'
@@ -0,0 +1,92 @@
1
+ .comable-page
2
+ .comable-page-heading
3
+ ul.pull-right.list-inline
4
+ li
5
+ .btn-group role="group"
6
+ = link_to_previous_page @orders, '<', class: 'btn btn-default' do
7
+ .btn.btn-default disabled="disabled"
8
+ | <
9
+ = link_to_next_page @orders, '>', class: 'btn btn-default' do
10
+ .btn.btn-default disabled="disabled"
11
+ | >
12
+ li
13
+ = link_to Comable.t('admin.actions.new'), comable.new_admin_draft_order_path, class: 'btn btn-default'
14
+ li.dropdown
15
+ = link_to '#', class: 'btn btn-default', 'data-toggle' => 'dropdown' do
16
+ = Comable.t('admin.more')
17
+ i.fa.fa-angle-down<
18
+
19
+ h1.page-header
20
+ = Comable.t('admin.nav.draft_order')
21
+ small<
22
+ | #{@orders.total_count} #{Comable.t('admin.results')}
23
+
24
+ .comable-page-body
25
+ .comable-search
26
+ = search_form_for @q, url: comable.admin_draft_orders_path do |f|
27
+ .input-group
28
+ span.input-group-btn
29
+ button.btn.btn-default.dropdown-toggle type="button" data-toggle="dropdown"
30
+ i.fa.fa-search
31
+ span.caret<
32
+ ul.dropdown-menu role="menu"
33
+ li
34
+ = link_to Comable.t('admin.advanced_search'), 'javascript:void(0)', 'data-toggle' => 'collapse', 'data-target' => '#comable-advanced-search'
35
+ li
36
+ = link_to Comable.t('admin.clear_search_conditions'), comable.admin_draft_orders_path
37
+ = f.text_field :code_cont, class: 'form-control'
38
+ span.input-group-btn
39
+ = f.submit Comable.t('admin.search'), class: 'btn btn-default'
40
+ .hidden
41
+ = f.label :user_id
42
+ = f.text_field :user_id_eq
43
+
44
+ = render 'comable/admin/shared/advanced_search', f: f
45
+
46
+ section
47
+ - if @orders.empty?
48
+ = Comable.t('admin.not_found')
49
+ - else
50
+ table.table.table-striped
51
+ thead
52
+ th
53
+ = sort_link [:comable, @q], :code
54
+ th
55
+ = sort_link [:comable, @q], :state
56
+ th
57
+ = @orders.klass.human_attribute_name(:payment_state)
58
+ th
59
+ = @orders.klass.human_attribute_name(:shipment_state)
60
+ th
61
+ = @orders.klass.human_attribute_name(:bill_full_name)
62
+ th
63
+ = @orders.klass.human_attribute_name(:order_items)
64
+ th
65
+ = sort_link [:comable, @q], :total_price
66
+ th
67
+ = sort_link [:comable, @q], :created_at
68
+ tbody
69
+ - @orders.each do |order|
70
+ tr
71
+ td
72
+ = link_to order.code, comable.admin_draft_order_path(order)
73
+ td
74
+ = order.human_state_name
75
+ td
76
+ = order.payment_human_state_name
77
+ td
78
+ = order.shipment_human_state_name
79
+ td
80
+ = order.bill_full_name
81
+ td
82
+ ul.list-unstyled
83
+ - order.order_items.each do |order_item|
84
+ li
85
+ | #{order_item.name_with_sku} x #{order_item.quantity}
86
+ td
87
+ = number_to_currency order.total_price
88
+ td
89
+ = l order.created_at
90
+
91
+ .text-center
92
+ = paginate @orders, theme: :comable_backend
@@ -0,0 +1,16 @@
1
+ .comable-page
2
+ .comable-main-fixed-top
3
+ .comable-page-heading
4
+ ul.pull-right.list-inline
5
+ li
6
+ = link_to_save
7
+
8
+ h1.page-header
9
+ ol.breadcrumb
10
+ li>
11
+ = link_to Comable.t('admin.nav.draft_order'), comable.admin_draft_orders_path
12
+ li.active
13
+ = Comable.t('admin.actions.new')
14
+
15
+ .comable-page-body
16
+ = render 'form'
@@ -0,0 +1,157 @@
1
+ = error_messages_for @order
2
+
3
+ = form_for [comable, :admin, @order] do |f|
4
+ .hidden
5
+ = f.submit
6
+
7
+ .col-md-6
8
+ .row
9
+ fieldset
10
+ .col-md-3
11
+ legend
12
+ = f.object.class.human_attribute_name(:order_items)
13
+ .help-block
14
+
15
+ .col-md-9
16
+ - if @order.new_record?
17
+ .form-group
18
+ = select_tag :variant, nil, id: 'js-variant-selector', class: 'select2 ajax', data: { source: comable.admin_variants_path, term: :product_name_cont }
19
+ = link_to_add_fields nil, f, :order_items, id: 'js-add-order-item', class: 'hidden'
20
+
21
+ table.table#js-order-items-table
22
+ thead
23
+ tr
24
+ th colspan="2"
25
+ = f.object.order_items.klass.human_attribute_name(:product)
26
+ th
27
+ = f.object.order_items.klass.human_attribute_name(:price)
28
+ th
29
+ = f.object.order_items.klass.human_attribute_name(:quantity)
30
+ th
31
+ = f.object.order_items.klass.human_attribute_name(:subtotal_price)
32
+ tbody
33
+ = f.fields_for :order_items do |ff|
34
+ = render 'comable/admin/shared/order_items_fields', f: ff
35
+ tfoot
36
+ tr
37
+ th.text-right colspan="4"
38
+ = f.object.class.human_attribute_name(:item_total_price)
39
+ td
40
+ = f.text_field :item_total_price, disabled: true, data: { name: 'item-total-price' }
41
+ tr
42
+ th.text-right colspan="4"
43
+ = f.object.class.human_attribute_name(:payment_fee)
44
+ td
45
+ = f.text_field :payment_fee, data: { name: 'payment-fee' }
46
+ tr
47
+ th.text-right colspan="4"
48
+ = f.object.class.human_attribute_name(:shipment_fee)
49
+ td
50
+ = f.text_field :shipment_fee, data: { name: 'shipment-fee' }
51
+ tr
52
+ th.text-right colspan="4"
53
+ = f.object.class.human_attribute_name(:total_price)
54
+ td
55
+ = f.text_field :total_price, disabled: true, data: { name: 'total-price' }
56
+
57
+ .col-md-6#js-user-fields
58
+ .row
59
+ fieldset
60
+ .col-md-3
61
+ legend
62
+ = Comable.t('admin.user')
63
+ .help-block
64
+
65
+ .col-md-9
66
+ - if @order.new_record?
67
+ .form-group
68
+ = f.collection_select :user_id, [@order.user].compact, :id, :text, {}, id: 'js-user-selector', class: 'select2 ajax', data: { source: comable.admin_users_path, term: :email_or_bill_address_full_name_cont }
69
+
70
+ .form-group
71
+ = f.label :email
72
+ = f.email_field :email, data: { name: 'email' }
73
+
74
+ - if f.object.bill_address
75
+ hr
76
+
77
+ fieldset
78
+ .col-md-3
79
+ legend
80
+ = f.object.class.human_attribute_name(:bill_address)
81
+ .help-block
82
+
83
+ .col-md-9
84
+ = f.fields_for :bill_address do |ff|
85
+ .form-group
86
+ = ff.label :full_name
87
+ .row
88
+ .col-sm-6
89
+ = ff.text_field :family_name, placeholder: ff.object.class.human_attribute_name(:family_name), data: { name: 'bill-family-name' }
90
+ .col-sm-6
91
+ = ff.text_field :first_name, placeholder: ff.object.class.human_attribute_name(:first_name), data: { name: 'bill-first-name' }
92
+
93
+ .form-group
94
+ = ff.label :zip_code
95
+ = ff.text_field :zip_code, max_length: 8, data: { name: 'bill-zip-code' }
96
+
97
+ .form-group
98
+ = ff.label :state_name
99
+ = ff.text_field :state_name, data: { name: 'bill-state-name' }
100
+
101
+ .form-group
102
+ = ff.label :city
103
+ = ff.text_field :city, data: { name: 'bill-city' }
104
+
105
+ .form-group
106
+ = ff.label :detail
107
+ = ff.text_field :detail, data: { name: 'bill-detail' }
108
+
109
+ .form-group
110
+ = ff.label :phone_number
111
+ = ff.text_field :phone_number, max_length: 18, data: { name: 'bill-phone-number' }
112
+
113
+ - if f.object.ship_address
114
+ hr
115
+
116
+ fieldset
117
+ .col-md-3
118
+ legend
119
+ = f.object.class.human_attribute_name(:ship_address)
120
+ .help-block
121
+
122
+ .col-md-9
123
+ .form-group
124
+ .checkbox
125
+ label
126
+ = f.check_box :same_as_bill_address, data: { name: 'same-as-bill-address' }
127
+ = f.object.class.human_attribute_name(:same_as_bill_address)
128
+
129
+ #js-ship-address-fields
130
+ = f.fields_for :ship_address do |ff|
131
+ .form-group
132
+ = ff.label :full_name
133
+ .row
134
+ .col-sm-6
135
+ = ff.text_field :family_name, placeholder: ff.object.class.human_attribute_name(:family_name), data: { name: 'ship-family-name' }
136
+ .col-sm-6
137
+ = ff.text_field :first_name, placeholder: ff.object.class.human_attribute_name(:first_name), data: { name: 'ship-first-name' }
138
+
139
+ .form-group
140
+ = ff.label :zip_code
141
+ = ff.text_field :zip_code, max_length: 8, data: { name: 'ship-zip-code' }
142
+
143
+ .form-group
144
+ = ff.label :state_name
145
+ = ff.text_field :state_name, data: { name: 'ship-state-name' }
146
+
147
+ .form-group
148
+ = ff.label :city
149
+ = ff.text_field :city, data: { name: 'ship-city' }
150
+
151
+ .form-group
152
+ = ff.label :detail
153
+ = ff.text_field :detail, data: { name: 'ship-detail' }
154
+
155
+ .form-group
156
+ = ff.label :phone_number
157
+ = ff.text_field :phone_number, max_length: 18, data: { name: 'ship-phone-number' }
@@ -15,156 +15,4 @@
15
15
  = Comable.t('admin.actions.edit')
16
16
 
17
17
  .comable-page-body
18
- section
19
- = error_messages_for @order
20
-
21
- = form_for @order, url: comable.admin_order_path(@order) do |f|
22
- .hidden
23
- = f.submit
24
-
25
- fieldset
26
- .col-md-3
27
- legend
28
- = Comable.t('admin.general')
29
- .help-block
30
-
31
- .col-md-9
32
- .form-group
33
- = f.label :email
34
- = f.email_field :email
35
-
36
- - if f.object.bill_address
37
- hr
38
-
39
- fieldset
40
- .col-md-3
41
- legend
42
- = f.object.class.human_attribute_name(:bill_address)
43
- .help-block
44
-
45
- .col-md-9
46
- = f.fields_for :bill_address do |ff|
47
- .form-group
48
- = ff.label :full_name
49
- .row
50
- .col-sm-6
51
- = ff.text_field :family_name, placeholder: ff.object.class.human_attribute_name(:family_name)
52
- .col-sm-6
53
- = ff.text_field :first_name, placeholder: ff.object.class.human_attribute_name(:first_name)
54
-
55
- .form-group
56
- = ff.label :zip_code
57
- = ff.text_field :zip_code, max_length: 8
58
-
59
- .form-group
60
- = ff.label :state_name
61
- = ff.text_field :state_name
62
-
63
- .form-group
64
- = ff.label :city
65
- = ff.text_field :city
66
-
67
- .form-group
68
- = ff.label :detail
69
- = ff.text_field :detail
70
-
71
- .form-group
72
- = ff.label :phone_number
73
- = ff.text_field :phone_number, max_length: 18
74
-
75
- - if f.object.ship_address
76
- hr
77
-
78
- fieldset
79
- .col-md-3
80
- legend
81
- = f.object.class.human_attribute_name(:ship_address)
82
- .help-block
83
-
84
- .col-md-9
85
- = f.fields_for :ship_address do |ff|
86
- .form-group
87
- = ff.label :full_name
88
- .row
89
- .col-sm-6
90
- = ff.text_field :family_name, placeholder: ff.object.class.human_attribute_name(:family_name)
91
- .col-sm-6
92
- = ff.text_field :first_name, placeholder: ff.object.class.human_attribute_name(:first_name)
93
-
94
- .form-group
95
- = ff.label :zip_code
96
- = ff.text_field :zip_code, max_length: 8
97
-
98
- .form-group
99
- = ff.label :state_name
100
- = ff.text_field :state_name
101
-
102
- .form-group
103
- = ff.label :city
104
- = ff.text_field :city
105
-
106
- .form-group
107
- = ff.label :detail
108
- = ff.text_field :detail
109
-
110
- .form-group
111
- = ff.label :phone_number
112
- = ff.text_field :phone_number, max_length: 18
113
-
114
- - if f.object.order_items
115
- hr
116
-
117
- fieldset
118
- .col-md-3
119
- legend
120
- = f.object.class.human_attribute_name(:order_items)
121
- .help-block
122
-
123
- .col-md-9
124
- table.table
125
- thead
126
- tr
127
- th colspan="2"
128
- = f.object.order_items.klass.human_attribute_name(:product)
129
- th
130
- = f.object.order_items.klass.human_attribute_name(:price)
131
- th
132
- = f.object.order_items.klass.human_attribute_name(:quantity)
133
- th
134
- = f.object.order_items.klass.human_attribute_name(:subtotal_price)
135
- tbody
136
- = f.fields_for :order_items do |ff|
137
- tr.comable-order-items
138
- td width="180"
139
- = image_tag ff.object.image_url, width: '100%'
140
- td
141
- p
142
- = ff.text_field :name, placeholder: ff.object.class.human_attribute_name(:name), data: { name: 'name' }
143
- p.text-muted
144
- = ff.text_field :sku, placeholder: ff.object.class.human_attribute_name(:sku), data: { name: 'sku' }
145
- td
146
- = ff.text_field :price, placeholder: ff.object.class.human_attribute_name(:price), data: { name: 'price' }
147
- td
148
- = ff.text_field :quantity, placeholder: ff.object.class.human_attribute_name(:quantity), data: { name: 'quantity' }
149
- td
150
- = ff.text_field :subtotal_price, disabled: true, data: { name: 'subtotal_price' }
151
- tr
152
- th.text-right colspan="4"
153
- = f.object.class.human_attribute_name(:item_total_price)
154
- td
155
- = f.text_field :item_total_price, disabled: true, data: { name: 'item_total_price' }
156
- tr
157
- th.text-right colspan="4"
158
- = f.object.class.human_attribute_name(:payment_fee)
159
- td
160
- = f.text_field :payment_fee, data: { name: 'payment_fee' }
161
- tr
162
- th.text-right colspan="4"
163
- = f.object.class.human_attribute_name(:shipment_fee)
164
- td
165
- = f.text_field :shipment_fee, data: { name: 'shipment_fee' }
166
- tr
167
- th.text-right colspan="4"
168
- = f.object.class.human_attribute_name(:total_price)
169
- td
170
- = f.text_field :total_price, disabled: true, data: { name: 'total_price' }
18
+ = render 'form'
@@ -9,6 +9,8 @@
9
9
  = link_to_next_page @orders, '>', class: 'btn btn-default' do
10
10
  .btn.btn-default disabled="disabled"
11
11
  | >
12
+ li
13
+ = link_to Comable.t('admin.actions.new'), comable.new_admin_order_path, class: 'btn btn-default'
12
14
  li.dropdown
13
15
  = link_to '#', class: 'btn btn-default', 'data-toggle' => 'dropdown' do
14
16
  = Comable.t('admin.more')
@@ -0,0 +1,16 @@
1
+ .comable-page
2
+ .comable-main-fixed-top
3
+ .comable-page-heading
4
+ ul.pull-right.list-inline
5
+ li
6
+ = link_to_save
7
+
8
+ h1.page-header
9
+ ol.breadcrumb
10
+ li>
11
+ = link_to Comable.t('admin.nav.order'), comable.admin_orders_path
12
+ li.active
13
+ = Comable.t('admin.actions.new')
14
+
15
+ .comable-page-body
16
+ = render 'form'
@@ -6,11 +6,11 @@
6
6
  = link_to comable.ship_admin_order_path(@order), class: 'btn btn-primary', method: :post, disabled: !@order.can_ship? do
7
7
  i.fa.fa-truck>
8
8
  = Comable.t('admin.ship')
9
- - if @order.completed?
9
+ - if @order.can_cancel?
10
10
  li
11
11
  = link_to comable.cancel_admin_order_path(@order), class: 'btn btn-default', method: :post do
12
12
  = @order.class.human_state_event_name(:cancel)
13
- - if @order.canceled?
13
+ - if @order.can_resume?
14
14
  li
15
15
  = button_to comable.resume_admin_order_path(@order), class: 'btn btn-default', method: :post do
16
16
  = @order.class.human_state_event_name(:resume)
@@ -10,8 +10,7 @@
10
10
  .btn.btn-default disabled="disabled"
11
11
  | >
12
12
  li
13
- = link_to comable.root_path do
14
- = link_to Comable.t('admin.actions.new'), comable.new_admin_product_path, class: 'btn btn-default'
13
+ = link_to Comable.t('admin.actions.new'), comable.new_admin_product_path, class: 'btn btn-default'
15
14
  li.dropdown
16
15
  = link_to '#', class: 'btn btn-default', 'data-toggle' => 'dropdown' do
17
16
  = Comable.t('admin.more')
@@ -0,0 +1,20 @@
1
+ - dynamic_field = f.index.is_a? String
2
+ - css_class = ['js-new-order-item', 'hidden'].join(' ') if dynamic_field
3
+
4
+ tr.comable-order-items class="#{css_class}"
5
+ td width="180"
6
+ = image_tag f.object.image_url, width: '100%', data: { name: 'image-url' }
7
+ td
8
+ p
9
+ = f.text_field :name, placeholder: f.object.class.human_attribute_name(:name), data: { name: 'name' }
10
+ p.text-muted
11
+ = f.text_field :sku, placeholder: f.object.class.human_attribute_name(:sku), data: { name: 'sku' }
12
+ td
13
+ = f.text_field :price, placeholder: f.object.class.human_attribute_name(:price), data: { name: 'price' }
14
+ td
15
+ = f.text_field :quantity, placeholder: f.object.class.human_attribute_name(:quantity), data: { name: 'quantity' }
16
+ td
17
+ = f.text_field :subtotal_price, disabled: true, data: { name: 'subtotal-price' }
18
+ br
19
+ = f.text_field :variant_id, data: { name: 'variant-id' }, class: 'hidden'
20
+ = link_to Comable.t('admin.actions.destroy'), 'javascript:void(0)', class: 'js-remove-order-item'
data/config/routes.rb CHANGED
@@ -5,7 +5,7 @@ Comable::Core::Engine.routes.draw do
5
5
  resource :dashboard, only: :show
6
6
 
7
7
  resources :products do
8
- resources :variants
8
+ resources :variants, except: :index
9
9
 
10
10
  resources :stocks
11
11
 
@@ -22,7 +22,9 @@ Comable::Core::Engine.routes.draw do
22
22
  end
23
23
  end
24
24
 
25
- resources :orders do
25
+ resources :variants, only: :index
26
+
27
+ resources :orders, except: :create do
26
28
  collection do
27
29
  get :export
28
30
  end
@@ -38,6 +40,8 @@ Comable::Core::Engine.routes.draw do
38
40
  end
39
41
  end
40
42
 
43
+ resources :draft_orders
44
+
41
45
  resources :categories
42
46
  resources :stock_locations
43
47
  resources :pages
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: comable-backend
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0.beta2
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - YOSHIDA Hiroki
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-31 00:00:00.000000000 Z
11
+ date: 2015-11-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: comable-core
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 0.7.0.beta2
19
+ version: 0.7.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 0.7.0.beta2
26
+ version: 0.7.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rails
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -487,13 +487,15 @@ files:
487
487
  - app/assets/javascripts/comable/admin/categories.coffee
488
488
  - app/assets/javascripts/comable/admin/dashboard.coffee
489
489
  - app/assets/javascripts/comable/admin/dispatcher.coffee
490
+ - app/assets/javascripts/comable/admin/dynamic_order.coffee
490
491
  - app/assets/javascripts/comable/admin/navigations.coffee
491
- - app/assets/javascripts/comable/admin/orders.coffee
492
+ - app/assets/javascripts/comable/admin/order_item_builder.coffee
492
493
  - app/assets/javascripts/comable/admin/pages.coffee
493
494
  - app/assets/javascripts/comable/admin/products.coffee
494
495
  - app/assets/javascripts/comable/admin/search.coffee
495
496
  - app/assets/javascripts/comable/admin/stocks.coffee
496
497
  - app/assets/javascripts/comable/admin/themes.coffee
498
+ - app/assets/javascripts/comable/admin/user_selector.coffee
497
499
  - app/assets/javascripts/comable/admin/variants.coffee
498
500
  - app/assets/stylesheets/comable/admin/_common.scss
499
501
  - app/assets/stylesheets/comable/admin/_dashboard.scss
@@ -517,6 +519,7 @@ files:
517
519
  - app/controllers/comable/admin/application_controller.rb
518
520
  - app/controllers/comable/admin/categories_controller.rb
519
521
  - app/controllers/comable/admin/dashboard_controller.rb
522
+ - app/controllers/comable/admin/draft_orders_controller.rb
520
523
  - app/controllers/comable/admin/navigations_controller.rb
521
524
  - app/controllers/comable/admin/orders_controller.rb
522
525
  - app/controllers/comable/admin/pages_controller.rb
@@ -543,17 +546,23 @@ files:
543
546
  - app/views/comable/admin/categories/index.slim
544
547
  - app/views/comable/admin/dashboard/_widget.slim
545
548
  - app/views/comable/admin/dashboard/show.slim
549
+ - app/views/comable/admin/draft_orders/_form.slim
550
+ - app/views/comable/admin/draft_orders/edit.slim
551
+ - app/views/comable/admin/draft_orders/index.slim
552
+ - app/views/comable/admin/draft_orders/new.slim
546
553
  - app/views/comable/admin/navigations/_form.slim
547
554
  - app/views/comable/admin/navigations/_navigation_item_fields.slim
548
555
  - app/views/comable/admin/navigations/edit.slim
549
556
  - app/views/comable/admin/navigations/index.slim
550
557
  - app/views/comable/admin/navigations/new.slim
551
558
  - app/views/comable/admin/navigations/search_linkable_ids.coffee
559
+ - app/views/comable/admin/orders/_form.slim
552
560
  - app/views/comable/admin/orders/_google_map.slim
553
561
  - app/views/comable/admin/orders/_payment_state.slim
554
562
  - app/views/comable/admin/orders/_shipment_state.slim
555
563
  - app/views/comable/admin/orders/edit.slim
556
564
  - app/views/comable/admin/orders/index.slim
565
+ - app/views/comable/admin/orders/new.slim
557
566
  - app/views/comable/admin/orders/show.slim
558
567
  - app/views/comable/admin/pages/_form.slim
559
568
  - app/views/comable/admin/pages/edit.slim
@@ -577,6 +586,7 @@ files:
577
586
  - app/views/comable/admin/shared/_notifier.slim
578
587
  - app/views/comable/admin/shared/_option_type_fields.slim
579
588
  - app/views/comable/admin/shared/_option_types_fields.slim
589
+ - app/views/comable/admin/shared/_order_items_fields.slim
580
590
  - app/views/comable/admin/shared/_stocks_fields.slim
581
591
  - app/views/comable/admin/shared/_value_fields.slim
582
592
  - app/views/comable/admin/shared/_variant_form.slim
@@ -612,7 +622,6 @@ files:
612
622
  - app/views/comable/admin/users/show.slim
613
623
  - app/views/comable/admin/variants/_form.slim
614
624
  - app/views/comable/admin/variants/edit.slim
615
- - app/views/comable/admin/variants/index.slim
616
625
  - app/views/comable/admin/variants/new.slim
617
626
  - app/views/kaminari/comable_backend/_first_page.html.slim
618
627
  - app/views/kaminari/comable_backend/_gap.html.slim
@@ -641,9 +650,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
641
650
  version: '0'
642
651
  required_rubygems_version: !ruby/object:Gem::Requirement
643
652
  requirements:
644
- - - ">"
653
+ - - ">="
645
654
  - !ruby/object:Gem::Version
646
- version: 1.3.1
655
+ version: '0'
647
656
  requirements: []
648
657
  rubyforge_project:
649
658
  rubygems_version: 2.4.5
@@ -1,97 +0,0 @@
1
- .comable-page
2
- .comable-page-heading
3
- ul.pull-right.list-inline
4
- li
5
- .btn-group role="group"
6
- = link_to_previous_page @products, '<', class: 'btn btn-default' do
7
- .btn.btn-default disabled="disabled"
8
- | <
9
- = link_to_next_page @products, '>', class: 'btn btn-default' do
10
- .btn.btn-default disabled="disabled"
11
- | >
12
- li
13
- = link_to comable.root_path do
14
- = link_to Comable.t('admin.actions.new'), comable.new_admin_product_path, class: 'btn btn-default'
15
- li.dropdown
16
- = link_to '#', class: 'btn btn-default', 'data-toggle' => 'dropdown' do
17
- = Comable.t('admin.more')
18
- i.fa.fa-angle-down<
19
- ul.dropdown-menu.dropdown-menu-right
20
- li
21
- = link_to Comable.t('admin.export_to_csv'), comable.export_admin_products_path(format: :csv, q: params[:q])
22
- li
23
- = link_to Comable.t('admin.export_to_excel'), comable.export_admin_products_path(format: :xlsx, q: params[:q])
24
- li.divider
25
- li
26
- a.btn-file
27
- span>
28
- = Comable.t('admin.import')
29
- = form_tag comable.import_admin_products_path, multipart: true do
30
- = file_field_tag :file
31
-
32
- h1.page-header
33
- = Comable.t('admin.nav.product')
34
- small<
35
- | #{@products.total_count} #{Comable.t('admin.results')}
36
-
37
- .comable-page-body
38
- .comable-search
39
- = search_form_for @q, url: comable.admin_products_path do |f|
40
- .input-group
41
- span.input-group-btn
42
- button.btn.btn-default.dropdown-toggle type="button" data-toggle="dropdown"
43
- i.fa.fa-search
44
- span.caret<
45
- ul.dropdown-menu role="menu"
46
- li
47
- = link_to Comable.t('admin.advanced_search'), 'javascript:void(0)', 'data-toggle' => 'collapse', 'data-target' => '#comable-advanced-search'
48
- li
49
- = link_to Comable.t('admin.clear_search_conditions'), comable.admin_products_path
50
- = f.text_field :name_or_variants_sku_cont_any_splitted, class: 'form-control'
51
- span.input-group-btn
52
- = f.submit Comable.t('admin.search'), class: 'btn btn-default'
53
-
54
- = render 'comable/admin/shared/advanced_search', f: f
55
-
56
- section
57
- - if @products.empty?
58
- = Comable.t('admin.not_found')
59
- - else
60
- table.table.table-striped
61
- thead
62
- th
63
- th
64
- = sort_link [:comable, @q], :code
65
- th
66
- = sort_link [:comable, @q], :name
67
- th
68
- = sort_link [:comable, @q], :price
69
- th
70
- = Comable.t('admin.stocks')
71
- tbody
72
- - @products.each do |product|
73
- - quantity = product.stocks.to_a.sum(&:quantity)
74
- tr
75
- td.comable-image
76
- = link_to comable.admin_product_path(product), class: 'thumbnail' do
77
- = image_tag product.image_url, width: '100%'
78
- td
79
- = link_to product.code, comable.admin_product_path(product)
80
- - unless product.published?
81
- span.fa.fa-eye-slash.text-muted<
82
- td
83
- = product.name
84
- td
85
- = number_to_currency product.price
86
- td
87
- ul.list-unstyled
88
- - product.stocks.each do |stock|
89
- li
90
- strong class="#{(quantity <= 0) ? 'text-danger' : (quantity <= 10) ? 'text-warning' : 'text-success'}"
91
- = number_with_delimiter stock.quantity
92
- - if stock.sku?
93
- span<
94
- | (#{stock.sku_name})
95
-
96
- .text-center
97
- = paginate @products, theme: :comable_backend