rightnow_oms 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. data/CHANGELOG +8 -1
  2. data/README.md +10 -0
  3. data/app/assets/javascripts/rightnow_oms/app/app.js.coffee +2 -0
  4. data/app/assets/javascripts/rightnow_oms/app/controllers/cart.js.coffee +3 -3
  5. data/app/assets/javascripts/rightnow_oms/app/models/cart.js.coffee +14 -4
  6. data/app/assets/javascripts/rightnow_oms/app/models/cart_item.js.coffee +25 -15
  7. data/app/assets/javascripts/rightnow_oms/app/templates/cart_items/show.hjs +23 -9
  8. data/app/assets/javascripts/rightnow_oms/app/templates/cart_items/show_in_detail.hjs +45 -18
  9. data/app/assets/javascripts/rightnow_oms/app/templates/carts/show.hjs +0 -2
  10. data/app/assets/javascripts/rightnow_oms/app/templates/carts/show_in_detail.hjs +15 -23
  11. data/app/assets/javascripts/rightnow_oms/app/views/cart_items/show.js.coffee +5 -1
  12. data/app/assets/javascripts/rightnow_oms/app/views/cart_items/show_in_detail.js.coffee +9 -6
  13. data/app/assets/javascripts/rightnow_oms/app/views/carts/show_in_detail.js.coffee +1 -0
  14. data/app/assets/javascripts/rightnow_oms/vendor/ember-data.js +640 -236
  15. data/app/assets/javascripts/rightnow_oms/vendor/ember-data.min.js +1 -1
  16. data/app/assets/javascripts/rightnow_oms/vendor/ember.js +61 -37
  17. data/app/assets/javascripts/rightnow_oms/vendor/ember.min.js +2 -2
  18. data/app/assets/stylesheets/rightnow_oms/application.css.scss +17 -0
  19. data/app/assets/stylesheets/rightnow_oms/carts.css.scss +99 -72
  20. data/app/assets/stylesheets/rightnow_oms/orders.css.scss +50 -0
  21. data/app/controllers/rightnow_oms/cart_items_controller.rb +5 -5
  22. data/app/controllers/rightnow_oms/orders_controller.rb +30 -0
  23. data/app/models/rightnow_oms/cart.rb +22 -13
  24. data/app/models/rightnow_oms/cart_item.rb +20 -2
  25. data/app/models/rightnow_oms/order.rb +43 -0
  26. data/app/models/rightnow_oms/order_item.rb +16 -0
  27. data/app/views/rightnow_oms/carts/show.html.haml +2 -0
  28. data/app/views/rightnow_oms/orders/show.html.haml +45 -0
  29. data/config/routes.rb +1 -0
  30. data/db/migrate/20120214074943_create_rightnow_oms_orders.rb +20 -0
  31. data/db/migrate/20120214081113_create_rightnow_oms_order_items.rb +15 -0
  32. data/db/migrate/20120215064659_add_user_id_to_rightnow_oms_orders.rb +7 -0
  33. data/db/migrate/20120217081138_add_base_quantity_to_rightnow_oms_cart_items.rb +6 -0
  34. data/lib/rightnow_oms/order_no_generator.rb +13 -0
  35. data/lib/rightnow_oms/version.rb +1 -1
  36. data/lib/rightnow_oms.rb +19 -5
  37. metadata +41 -20
  38. data/app/assets/stylesheets/rightnow_oms/application.css +0 -7
@@ -5,8 +5,6 @@
5
5
  &:hover { text-decoration: underline; }
6
6
  }
7
7
  }
8
- .r-clear { clear: both; }
9
- .r-money { color: red; }
10
8
  .r-mini-cart {
11
9
  @extend .r-links;
12
10
  position: relative;
@@ -33,22 +31,45 @@
33
31
  border: 1px solid #ccc;
34
32
  background-color: white;
35
33
  display: none;
36
- table {
37
- td {
38
- padding: 5px 8px;
39
- text-align: right;
40
- }
41
- td.name {
42
- width: 150px;
43
- text-align: left;
44
- overflow: hidden;
45
- }
46
- td.money { @extend .money }
47
- td.delete {
48
- a {
49
- color: #BF0000;
50
- }
51
- }
34
+ dl {
35
+ margin: 0px;
36
+ width: 100%;
37
+ }
38
+ dl ul {
39
+ list-style-type: none;
40
+ padding: 0px;
41
+ margin: 0px;
42
+ border: 0px;
43
+ width: 100%;
44
+ }
45
+ dl li{
46
+ padding-top: 5px;
47
+ padding-left: 8px;
48
+ text-align: right;
49
+ float: left;
50
+ }
51
+ dl li.name {
52
+ width: 165px;
53
+ text-align: left;
54
+ cursor: pointer;
55
+ }
56
+ dl li.price {
57
+ width: 50px;
58
+ }
59
+ dl li.delete {
60
+ width: 30px;
61
+ }
62
+ ul.child {
63
+ clear: both;
64
+ }
65
+ dd {
66
+ margin-left: 12px;
67
+ }
68
+ dd li.price {
69
+ margin-left: -12px;
70
+ }
71
+ dd li.name {
72
+ cursor: default;
52
73
  }
53
74
  }
54
75
  .r-bottom-bar {
@@ -65,74 +86,80 @@
65
86
  margin: 0 auto;
66
87
  font-size: 12px;
67
88
  background-color: white;
89
+
68
90
  h2 {
69
91
  font-size: 24px;
70
92
  line-height: 36px;
71
93
  }
72
- table {
73
- display: table;
94
+
95
+ ul {
96
+ text-align: left;
97
+ list-style-type: none;
98
+ border: 0px;
99
+ margin: 0px;
100
+ padding: 0px;
74
101
  width: 100%;
75
- margin-bottom: 18px;
76
- border-collapse: collapse;
77
- border-spacing: 0;
78
- vertical-align: middle;
79
- tr:nth-child(odd) {
80
- td { background-color: #F9F9F9; }
102
+
103
+ li {
104
+ padding: 12px 8px;
105
+ float: left;
81
106
  }
107
+ li.others {
108
+ float: right;
109
+ div {
110
+ float: left;
111
+ }
82
112
 
83
- th, td {
84
- padding: 8px;
85
- line-height: 18px;
86
- text-align: left;
87
- display: table-cell;
88
- }
89
- thead {
90
- display: table-header-group;
91
- tr {
92
- display: table-row;
93
- th {
94
- border-top: 0;
95
- font-weight: bold;
96
- vertical-align: bottom;
113
+ div.price {
114
+ width: 100px;
115
+ }
116
+
117
+ div.quantity {
118
+ width: 100px;
119
+ span {
120
+ border: 1px solid #CCC;
121
+ float: left;
122
+ display: block;
123
+ width: 14px;
124
+ text-align: center;
97
125
  }
126
+ span.decrease { margin-right: -1px; }
127
+ span.increase { margin-left: -1px; }
128
+ span.quantity { width: 30px; }
129
+ span.quantity-only { width: 60px; }
98
130
  }
131
+ div.subtotal { width: 85px; }
132
+ div.delete { width: 50px; }
99
133
  }
100
- tbody {
101
- display: table-row-group;
102
- tr {
103
- display: table-row;
104
- td {
105
- border-top: 1px solid #DDD;
106
- vertical-align: top;
107
- }
108
- td.price { width: 80px; }
109
- td.quantity {
110
- width: 100px;
111
- span {
112
- float: left;
113
- text-align: center;
114
- min-width: 12px;
115
- border: 1px solid #CCC;
116
- background-color: white;
117
- }
118
- span.quantity-only { width: 56px; }
119
- span.quantity { width: 30px; }
120
- span.increase {
121
- margin-left: -1px;
122
- a { text-decoration: none }
123
- }
124
- span.decrease {
125
- margin-right: -1px;
126
- a { text-decoration: none }
127
- }
128
- }
129
- td.subtotal { width: 80px; }
130
- td.delete { width: 50px; }
134
+ }
135
+
136
+ ul.title {
137
+ font-size: 16px;
138
+ font-weight: bold;
139
+ li.price {
140
+ text-align: left;
141
+ }
142
+ }
143
+
144
+ dl {
145
+ margin: 0;
146
+ dt, dd {
147
+ margin: 0;
148
+ border-top: 1px solid #CCC;
149
+ }
150
+ dt ul {
151
+ li.name { cursor: pointer; }
152
+ }
153
+ dd {
154
+ background-color: #EEE;
155
+ ul {
156
+ li.name { padding-left: 20px; }
131
157
  }
132
158
  }
133
- tfoot { display: none; }
134
159
  }
160
+
135
161
  .r-bottom-bar {
162
+ margin-top: 30px;
136
163
  position: relative;
137
164
  width: 100%;
138
165
  font-size: 20px;
@@ -0,0 +1,50 @@
1
+ .r-order {
2
+ margin: 0 auto;
3
+ max-width: 940px;
4
+ h3 { margin: 0px; }
5
+ p {
6
+ margin: 0px;
7
+ padding: 20px 20px;
8
+ }
9
+ label { font-weight: bold; }
10
+ table {
11
+ width: 100%;
12
+ margin-bottom: 18px;
13
+ border-collapse: collapse;
14
+ border-spacing: 0;
15
+ vertical-align: middle;
16
+ tr:nth-child(odd) {
17
+ td { background-color: #F9F9F9; }
18
+ }
19
+
20
+ th, td {
21
+ padding: 8px;
22
+ line-height: 18px;
23
+ text-align: left;
24
+ }
25
+ thead {
26
+ tr {
27
+ th {
28
+ border-top: 0;
29
+ font-weight: bold;
30
+ vertical-align: bottom;
31
+ padding-top: 20px;
32
+ padding-left: 20px;
33
+ }
34
+ }
35
+ }
36
+ tbody {
37
+ tr {
38
+ td {
39
+ padding-left: 20px;
40
+ border-top: 1px solid #DDD;
41
+ vertical-align: top;
42
+ }
43
+ td.price { width: 80px; }
44
+ td.quantity { width: 100px; }
45
+ td.subtotal { width: 80px; }
46
+ }
47
+ }
48
+ tfoot { display: none; }
49
+ }
50
+ }
@@ -10,11 +10,6 @@ module RightnowOms
10
10
  end
11
11
 
12
12
  def create
13
- if @cart.new_record?
14
- @cart.save
15
- session[:cart_id] = @cart.id
16
- end
17
-
18
13
  params[:cart_item][:quantity] = 1 if params[:cart_item][:quantity].blank?
19
14
  cart_item = @cart.add_item(find_cartable, params[:cart_item])
20
15
 
@@ -28,6 +23,11 @@ module RightnowOms
28
23
  end
29
24
 
30
25
  def update
26
+ if params[:cart_item]
27
+ params[:cart_item].delete(:original_price)
28
+ params[:cart_item].delete(:base_quantity)
29
+ end
30
+
31
31
  respond_to do |format|
32
32
  if @cart_item.update_attributes(params[:cart_item])
33
33
  format.json { render_for_api :default, json: @cart_item, root: :cart_item, status: :ok }
@@ -0,0 +1,30 @@
1
+ module RightnowOms
2
+ class OrdersController < ApplicationController
3
+ before_filter :load_cart, only: :create
4
+
5
+ def show
6
+ @order = Order.find(params[:id])
7
+ end
8
+
9
+ def create
10
+ @order = Order.new_with_items(params[:order], get_order_items)
11
+
12
+ respond_to do |format|
13
+ if @order.save
14
+ @cart.destroy
15
+
16
+ format.html { redirect_to @order }
17
+ else
18
+ format.html { redirect_to ::RightnowOms.config.new_order_url }
19
+ end
20
+ end
21
+ end
22
+
23
+ private
24
+ def get_order_items
25
+ @cart.cart_items.inject([]) do |c, i|
26
+ c << { name: i.name, price: i.price, quantity: i.quantity }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -11,32 +11,41 @@ module RightnowOms
11
11
  end
12
12
 
13
13
  def total
14
- cart_items.map.sum(&:total_price) || 0
14
+ cart_items.roots.map.sum(&:total) || 0
15
15
  end
16
16
 
17
17
  def cartable_count
18
- cart_items.map.sum(&:quantity)
18
+ cart_items.roots.map.sum(&:quantity)
19
19
  end
20
20
 
21
- def add_item(cartable, opts = { quantity: 1 })
22
- cart_item = cart_items.find_by_cartable(cartable)
21
+ def add_item(cartable, opts = {})
22
+ quantity = opts[:quantity] || 1
23
+ mergable = true if opts[:mergable].nil?
24
+
25
+ return create_item(cartable, opts) unless mergable
23
26
 
27
+ cart_item = cart_items.find_by_cartable(cartable)
24
28
  if cart_item
25
29
  cart_item.update_attributes(
26
- quantity: cart_item.quantity + opts[:quantity].to_i,
30
+ quantity: cart_item.quantity + quantity.to_i,
27
31
  )
28
32
  else
29
- cart_item = cart_items.create(
30
- cartable: cartable,
31
- name: cartable.cartable_name,
32
- price: opts[:price] || cartable.cartable_price,
33
- quantity: opts[:quantity],
34
- group: opts[:group],
35
- parent_id: opts[:parent_id]
36
- )
33
+ cart_item = create_item(cartable, opts)
37
34
  end
38
35
 
39
36
  cart_item
40
37
  end
38
+
39
+ private
40
+ def create_item(cartable, opts)
41
+ cart_items.create(
42
+ cartable: cartable,
43
+ name: cartable.cartable_name,
44
+ price: opts[:price] || cartable.cartable_price,
45
+ quantity: opts[:quantity] || 1,
46
+ group: opts[:group],
47
+ parent_id: opts[:parent_id]
48
+ )
49
+ end
41
50
  end
42
51
  end
@@ -12,6 +12,7 @@ module RightnowOms
12
12
  validates :name, presence: true
13
13
  validates :price, presence: true, numericality: { greater_than_or_equal_to: 0 }
14
14
  validates :quantity, presence: true, numericality: { greater_than: 0 }
15
+ validates :base_quantity, presence: true, numericality: { greater_than: 0 }
15
16
 
16
17
  api_accessible :default do |t|
17
18
  t.add :id
@@ -19,21 +20,38 @@ module RightnowOms
19
20
  t.add :cartable_id
20
21
  t.add :cartable_type
21
22
  t.add :name
23
+ t.add :original_price
24
+ t.add :group
25
+ t.add :base_quantity
22
26
  t.add :price
23
27
  t.add :quantity
24
- t.add :group
25
28
  end
26
29
 
27
30
  default_scope order("id ASC")
28
31
 
29
- def total_price
32
+ before_validation :set_base_quantity
33
+
34
+ def total
30
35
  price * quantity
31
36
  end
32
37
 
38
+ def original_price
39
+ cartable.cartable_price
40
+ end
41
+
33
42
  class << self
43
+ def roots
44
+ where(parent_id: nil)
45
+ end
46
+
34
47
  def find_by_cartable(cartable)
35
48
  find_by_cartable_id_and_cartable_type(cartable.id, cartable.class)
36
49
  end
37
50
  end
51
+
52
+ private
53
+ def set_base_quantity
54
+ self.base_quantity = quantity unless base_quantity
55
+ end
38
56
  end
39
57
  end
@@ -0,0 +1,43 @@
1
+ module RightnowOms
2
+ class Order < ActiveRecord::Base
3
+ REQUIRED_ATTRS = %W(
4
+ province city district neighborhood room
5
+ receiver payment_mode order_items user_id
6
+ )
7
+
8
+ has_many :order_items
9
+
10
+ REQUIRED_ATTRS.each do |attr|
11
+ validates attr, presence: true
12
+ end
13
+
14
+ validate :validates_mobile_and_tel
15
+
16
+ def order_no
17
+ @generator ||= OrderNoGenerator.new(self)
18
+ @generator.generate
19
+ end
20
+
21
+ def delivery_address
22
+ "#{province}#{city}#{district}#{street}#{neighborhood}#{room}"
23
+ end
24
+
25
+ class << self
26
+ def new_with_items(base, items)
27
+ Order.new(base) do |o|
28
+ items.each do |i|
29
+ children = i.delete(:children)
30
+
31
+ oi = o.order_items.build(i.merge(order: o))
32
+ children.each { |c| oi.children.build(c.merge(order: o)) } if children
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+ def validates_mobile_and_tel
40
+ errors[:base] = 'One of mobile and tel must be present.' unless self.mobile || self.tel
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,16 @@
1
+ module RightnowOms
2
+ class OrderItem < ActiveRecord::Base
3
+ belongs_to :order
4
+ belongs_to :parent, class_name: 'RightnowOms::OrderItem', foreign_key: :parent_id
5
+ has_many :children, class_name: 'RightnowOms::OrderItem', foreign_key: :parent_id, dependent: :destroy
6
+
7
+ validates :order, presence: true
8
+ validates :name, presence: true
9
+ validates :price, presence: true, numericality: { greater_than_or_equal_to: 0 }
10
+ validates :quantity, presence:true, numericality: { greater_than: 0 }
11
+
12
+ def total
13
+ price * quantity
14
+ end
15
+ end
16
+ end
@@ -4,5 +4,7 @@
4
4
 
5
5
  :javascript
6
6
  $(function() {
7
+ RightnowOms.config.set('newOrderUrl', '#{RightnowOms.config.new_order_url}')
8
+
7
9
  RightnowOms.cartController.load(#{@cart.as_api_response(:default).to_json.html_safe});
8
10
  });
@@ -0,0 +1,45 @@
1
+ .r-order
2
+ .r-order-no
3
+ %h3 订单号
4
+ %p= @order.order_no
5
+ .r-order-address
6
+ %h3 送货地址
7
+ %p= @order.delivery_address
8
+ .r-order-contact
9
+ %h3 联系方式
10
+ %p
11
+ %label 收货人姓名:
12
+ = @order.receiver
13
+ - unless @order.mobile.blank?
14
+ %label 手机:
15
+ = @order.mobile
16
+ - unless @order.tel.blank?
17
+ %label 电话:
18
+ = @order.tel
19
+ .r-order-payment
20
+ %h3 支付方式
21
+ %p= @order.payment_mode
22
+ .r-order-items
23
+ %h3 商品清单
24
+ %table
25
+ %thead
26
+ %tr
27
+ %th 名称
28
+ %th 价格
29
+ %th 数量
30
+ %th 小计
31
+ %tbody
32
+ - @order.order_items.each do |oi|
33
+ %tr
34
+ %td.name= oi.name
35
+ %td.price= "¥#{oi.price}"
36
+ %td.quantity= oi.quantity
37
+ %td.subtotal= "¥#{oi.total}"
38
+ - unless @order.remarks.blank?
39
+ .r-order-remarks
40
+ %h3 备注
41
+ %p= @order.remarks
42
+ - unless @order.vbrk.blank?
43
+ .r-order-vbrk
44
+ %h3 发票抬头
45
+ %p= @order.vbrk
data/config/routes.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  RightnowOms::Engine.routes.draw do
2
2
  resource :cart
3
3
  resources :cart_items
4
+ resources :orders
4
5
  end
@@ -0,0 +1,20 @@
1
+ class CreateRightnowOmsOrders < ActiveRecord::Migration
2
+ def change
3
+ create_table :rightnow_oms_orders do |t|
4
+ t.string :province
5
+ t.string :city
6
+ t.string :district
7
+ t.string :street
8
+ t.string :neighborhood
9
+ t.string :room
10
+ t.string :receiver
11
+ t.string :mobile
12
+ t.string :tel
13
+ t.string :payment_mode
14
+ t.string :remarks
15
+ t.string :vbrk
16
+
17
+ t.timestamps
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ class CreateRightnowOmsOrderItems < ActiveRecord::Migration
2
+ def change
3
+ create_table :rightnow_oms_order_items do |t|
4
+ t.string :name
5
+ t.decimal :price, precision: 10, scale: 2
6
+ t.integer :quantity
7
+ t.integer :parent_id
8
+ t.belongs_to :order
9
+
10
+ t.timestamps
11
+ end
12
+ add_index :rightnow_oms_order_items, :parent_id
13
+ add_index :rightnow_oms_order_items, :order_id
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ class AddUserIdToRightnowOmsOrders < ActiveRecord::Migration
2
+ def change
3
+ add_column :rightnow_oms_orders, :user_id, :integer
4
+ add_index :rightnow_oms_orders, :user_id
5
+
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ class AddBaseQuantityToRightnowOmsCartItems < ActiveRecord::Migration
2
+ def change
3
+ add_column :rightnow_oms_cart_items, :base_quantity, :integer
4
+
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ module RightnowOms
2
+ class OrderNoGenerator
3
+ NO_FORMAT = '%s%06d'
4
+
5
+ def initialize(order)
6
+ @order = order
7
+ end
8
+
9
+ def generate
10
+ NO_FORMAT % [@order.created_at.strftime('%Y%m%d'), @order.id]
11
+ end
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module RightnowOms
2
- VERSION = "0.1.2"
2
+ VERSION = "0.1.3"
3
3
  end
data/lib/rightnow_oms.rb CHANGED
@@ -1,9 +1,23 @@
1
- require "acts_as_api"
1
+ require 'acts_as_api'
2
+ require 'confstruct'
2
3
 
3
- require "rightnow_oms/engine"
4
- require "rightnow_oms/cartable_validator"
5
- require "rightnow_oms/acts_as_cartable"
6
- require "rightnow_oms/controller_helpers"
4
+ require 'rightnow_oms/engine'
5
+ require 'rightnow_oms/cartable_validator'
6
+ require 'rightnow_oms/acts_as_cartable'
7
+ require 'rightnow_oms/controller_helpers'
8
+ require 'rightnow_oms/order_no_generator'
9
+
10
+ module RightnowOms
11
+ @@config = ::Confstruct::Configuration.new
12
+
13
+ def self.config
14
+ @@config
15
+ end
16
+
17
+ def self.configure(&block)
18
+ @@config.configure(&block)
19
+ end
20
+ end
7
21
 
8
22
  ActiveRecord::Base.extend(RightnowOms::ActsAsCartable)
9
23
  ActionController::Base.send(:include, RightnowOms::ControllerHelpers)