trollied 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.3
1
+ 0.1.4
@@ -92,7 +92,11 @@ class LineItemsController < ApplicationController
92
92
  # DELETE /line_items/1
93
93
  # DELETE /line_items/1.xml
94
94
  def destroy
95
- return_to = if params[:return_to_purchasable_item].present? && params[:return_to_purchasable_item]
95
+ return_to = if @order && @order.line_items.size > 1
96
+ url_for_order_or_trolley
97
+ elsif params[:return_to_purchasable_item].present? &&
98
+ (params[:return_to_purchasable_item] == true.to_s ||
99
+ params[:return_to_purchasable_item] == true)
96
100
  url_for_purchasable_item
97
101
  elsif params[:trolley_id].present?
98
102
  @trolley = Trolley.find(params[:trolley_id])
@@ -23,8 +23,9 @@ class OrdersController < ApplicationController
23
23
  @conditions = set_up_conditions_based_on_params
24
24
 
25
25
  options = { :page => params[:page],
26
- :per_page => 5,
27
- :conditions => @conditions }
26
+ :per_page => number_per_page,
27
+ :conditions => @conditions,
28
+ :order => 'updated_at DESC'}
28
29
 
29
30
  @orders = Order.paginate(options)
30
31
 
@@ -114,10 +115,35 @@ class OrdersController < ApplicationController
114
115
  end
115
116
  end
116
117
 
118
+ # optional checkout form
119
+ # that can be used for simple per order settings or allowing the user to add a note
120
+ def checkout_form
121
+ set_defaults_for_order_checkout
122
+ @order.notes.build unless @order.notes.any?
123
+ end
124
+
125
+ def checkout
126
+ respond_to do |format|
127
+ if checkout_order_including_note
128
+ @trolley ||= @order.trolley
129
+ flash[:notice] = t("orders.controllers.change_to_checkout")
130
+ format.html { redirect_to url_for_trolley }
131
+ else
132
+ # display errors
133
+ format.html { render :action => "checkout_form" }
134
+ end
135
+ end
136
+ end
137
+
117
138
  # additional actions that correspond to order_status events
118
- %w(checkout cancel fulfilled_without_acceptance finish).each do |event|
139
+ %w(cancel alteration_approve fulfilled_without_acceptance finish).each do |event|
119
140
  code = Proc.new {
120
- @order.send("#{event}!")
141
+ if event == 'cancel'
142
+ @order.send("#{event}!", current_user)
143
+ else
144
+ @order.send("#{event}!")
145
+ end
146
+
121
147
  @trolley ||= @order.trolley
122
148
 
123
149
  flash[:notice] = t("orders.controllers.change_to_#{event}")
@@ -170,7 +196,7 @@ class OrdersController < ApplicationController
170
196
  operator = ">="
171
197
  operator = "<=" if name == :until
172
198
 
173
- clauses_array << "created_at #{operator} :#{name}"
199
+ clauses_array << "updated_at #{operator} :#{name}"
174
200
  clauses_hash[name] = value
175
201
  rescue
176
202
  instance_variable_set(var_name, nil)
@@ -207,4 +233,34 @@ class OrdersController < ApplicationController
207
233
  end
208
234
 
209
235
  end
236
+
237
+ # override this if your additional attributes need calculation for defaults at checkout
238
+ def set_defaults_for_order_checkout
239
+ end
240
+
241
+ def checkout_order_including_note
242
+ # skip alerting the order (triggering a duplicate notification) that a new_note has been added
243
+ # assumes only one note in form
244
+ if params[:order][:notes_attributes].present?
245
+ params[:order][:notes_attributes]["0"][:do_not_alert_order] = true
246
+
247
+ if params[:order][:notes_attributes]["0"][:body].blank?
248
+ # don't add empty note
249
+ params[:order].delete(:notes_attributes)
250
+ end
251
+ end
252
+
253
+ # this will add note and any attributes you have in the checkout form for order
254
+ success = @order.update_attributes(params[:order])
255
+
256
+ if success
257
+ # we have to call checkout! separately to trigger event notifications
258
+ @order.checkout!
259
+ end
260
+ success
261
+ end
262
+
263
+ def number_per_page
264
+ 15
265
+ end
210
266
  end
@@ -9,7 +9,7 @@ class TrolleysController < ApplicationController
9
9
  # list orders
10
10
  def show
11
11
  respond_to do |format|
12
- format.html # index.html.erb
12
+ format.html
13
13
  end
14
14
  end
15
15
 
@@ -9,9 +9,10 @@ module OrdersHelper
9
9
  end
10
10
 
11
11
  def can_delete_line_item?(order)
12
- (params[:controller] == 'orders' &&
13
- order.workflow_state == 'in_process') ||
14
- order.state_ok_to_delete_line_item?
12
+ order.state_ok_to_delete_line_item? &&
13
+ (order.user != current_user &&
14
+ order.in_process?) ||
15
+ order.current?
15
16
  end
16
17
 
17
18
  # override the method can_trigger_...? methods with your own security checks
@@ -23,16 +24,22 @@ module OrdersHelper
23
24
  params[:controller] == 'orders'
24
25
  end
25
26
 
26
- def order_button_for(action, order)
27
- options = { :confirm => t('orders.order.are_you_sure'),
28
- :class => 'order-button' }
27
+ def order_button_for(action, order, options = {})
28
+ options = options.merge({ :confirm => t('orders.order.are_you_sure'),
29
+ :class => "order-button button-#{action}" })
29
30
 
30
31
  options[:method] = 'delete' if action.to_s == 'destroy'
31
32
 
33
+ target_action = options.delete(:target_action) || action
34
+
35
+ url_for_options = { :controller => :orders,
36
+ :action => target_action,
37
+ :id => order }
38
+
39
+ url_for_options = url_for_options.merge(options.delete(:url_for_options)) if options[:url_for_options]
40
+
32
41
  button_to(t("orders.order.#{action}"),
33
- { :controller => :orders,
34
- :action => action,
35
- :id => order },
42
+ url_for_options,
36
43
  options)
37
44
  end
38
45
 
@@ -64,6 +71,10 @@ module OrdersHelper
64
71
  :until => @until)
65
72
  end
66
73
 
74
+ def sorted_state_names
75
+ Order.workflow_spec.state_names.sort_by { |s| I18n.t("orders.index.#{s.to_s}") }
76
+ end
77
+
67
78
  # returns a list of links to order states
68
79
  # that have orders in their state
69
80
  # with number of orders in a given state indicated
@@ -72,7 +83,7 @@ module OrdersHelper
72
83
 
73
84
  states_count = 1
74
85
 
75
- states = Order.workflow_spec.state_names.sort_by { |s| I18n.t("orders.index.#{s.to_s}") }
86
+ states = sorted_state_names
76
87
 
77
88
  states.each do |state|
78
89
  adjusted_conditions = adjust_value_in_conditions_for(:workflow_state, state.to_s, @conditions)
@@ -181,4 +192,29 @@ module OrdersHelper
181
192
  def url_for_options_for_orders_index
182
193
  { :controller => 'orders', :action => 'index' }
183
194
  end
195
+
196
+ def meta_data_for(order)
197
+ html = '<div id="order-meta-data">'
198
+ html += '<h3>' + t('orders.helpers.order_number') + " #{order.id}</h3>"
199
+ html += '</div>'
200
+ end
201
+
202
+ # override this in your app to add your own fields at checkout
203
+ def order_checkout_fields(form)
204
+ end
205
+
206
+ # order number
207
+ # order user
208
+ # number of line_items
209
+ def link_to_as_summary_of(order, user = nil)
210
+ link_text = t('orders.helpers.order_number') + " #{order.id}"
211
+ link_text += " - #{user.trolley_user_display_name}" if user
212
+ link_text += " - (#{order.line_items.size} #{t 'orders.helpers.items'})" if order.line_items.size > 0
213
+
214
+ link_to(link_text, url_for_order(:order => order))
215
+ end
216
+
217
+ def checkout_form_target_action_url_hash
218
+ {:action => 'checkout', :id => @order}
219
+ end
184
220
  end
@@ -11,7 +11,8 @@ class LineItem < ActiveRecord::Base
11
11
  after_destroy { |record| record.order.line_item_destroyed }
12
12
 
13
13
  # needs to be unique to orders that are current (but not unique to orders generally)
14
- # validates_uniqueness_of :order_id, :scope => [:purchasable_item_type, :purchasable_item_id]
14
+ validates_uniqueness_of :order_id, :scope => [:purchasable_item_type, :purchasable_item_id]
15
+
15
16
  def validate
16
17
  errors.add(:order, I18n.t('line_item.already_in_order')) if !order.current? && !order.in_process? && order.contains?(purchasable_item)
17
18
  end
@@ -6,10 +6,12 @@ class Note < ActiveRecord::Base
6
6
 
7
7
  after_create :alert_order
8
8
 
9
+ attr_accessor :do_not_alert_order
10
+
9
11
  private
10
12
 
11
13
  def alert_order
12
- order.new_note(self)
14
+ order.new_note(self) unless do_not_alert_order
13
15
  end
14
16
  end
15
17
 
@@ -8,6 +8,8 @@ class Order < ActiveRecord::Base
8
8
 
9
9
  include OrderStatus
10
10
 
11
+ accepts_nested_attributes_for :notes, :allow_destroy => true
12
+
11
13
  # convenience method to add new line item based on item_to_order
12
14
  def add(purchasable_item)
13
15
  line_items.create!(:purchasable_item => purchasable_item)
@@ -10,7 +10,6 @@ class Trolley < ActiveRecord::Base
10
10
  orders[index] || orders.create!
11
11
  end
12
12
 
13
- # TODO: STUB: implement way to determine
14
13
  # correct order given an purchasable_item
15
14
  def correct_order(purchasable_item)
16
15
  orders.with_state_current.first || orders.create!
@@ -25,7 +24,6 @@ class Trolley < ActiveRecord::Base
25
24
  end
26
25
 
27
26
  # do any of this trolley's orders contain the purchasable_item?
28
- # TODO: when status is added to orders, limit by option for checking status
29
27
  def contains?(purchasable_item, state = nil)
30
28
  within_orders = state ? orders.send("with_state_#{state}") : orders
31
29
 
@@ -1,12 +1,13 @@
1
1
  <tr>
2
- <td><%= link_to_purchasable_in(line_item) -%></td>
3
- <% if can_delete_line_item?(order) -%>
2
+ <% if can_delete_line_item?(order) && !params[:action].include?('checkout') -%>
4
3
  <td>
5
- <%= link_to t('line_items.line_item.delete'), { :controller => :line_items,
4
+ <%= button_to t('line_items.line_item.delete'), { :controller => :line_items,
6
5
  :action => :destroy,
7
6
  :id => line_item,
8
7
  :order_id => order,
9
- :trolley_id => trolley },
10
- :confirm => t('line_items.line_item.are_you_sure'), :method => :delete %></td>
8
+ :trolley_id => trolley,
9
+ :confirm => t('line_items.line_item.are_you_sure') }, :method => :delete %>
10
+ </td>
11
11
  <% end -%>
12
+ <td><%= link_to_purchasable_in(line_item) -%></td>
12
13
  </tr>
@@ -2,44 +2,63 @@
2
2
 
3
3
  <fieldset class="order">
4
4
 
5
- <% if params[:controller] == 'orders' && !(params[:action] == 'show' && current_user == order.user) -%>
5
+ <%= meta_data_for(order) -%>
6
+
7
+ <% if current_user != order.user && params[:controller] == 'orders' -%>
6
8
  <h3><%= t '.user' -%> <%= link_to_orders_for(order.user) -%></h3>
7
9
  <% end -%>
8
10
 
9
11
  <table class="order">
10
12
  <tr>
13
+ <% if (order.current? && params[:action] != 'checkout_form') || (order.in_process? && current_user != order.user) -%>
14
+ <th abbr="Actions for Line Item"><%= t '.purchasable_item_actions' %></th>
15
+ <% end -%>
11
16
  <th abbr="Line Item"><%= t '.purchasable_item_description' %></th>
12
17
  </tr>
13
18
 
14
19
  <%= render :partial => 'line_items/line_item', :collection => order.line_items, :locals => { :order => order, :trolley => trolley } -%>
15
20
 
16
- <% if order.current? -%>
17
- <tr>
18
- <td><%= button_to_checkout order -%></td>
19
- <td><%= button_to_clear order -%></td>
20
- </tr>
21
+
22
+ <% show_order_buttons = params[:action] != 'checkout_form' &&
23
+ (order.current? ||
24
+ order.in_process? ||
25
+ (order.ready? && can_trigger_finish?) ||
26
+ (order.user_review? && current_user == order.user)) -%>
27
+
28
+ <% if show_order_buttons -%>
29
+ <tr class="order-buttons">
30
+ <td><%= t '.order_controls_preface' -%></td>
31
+ <% end -%>
32
+
33
+ <% if order.current? && params[:action] != 'checkout_form' -%>
34
+ <td><%= button_to_checkout order -%><%= button_to_clear order -%></td>
21
35
  <% end -%>
22
36
 
23
37
  <% if order.in_process? -%>
24
- <tr>
25
- <td><%= button_to_cancel order -%></td>
26
-
27
- <% if can_trigger_fulfilled_without_acceptance? -%>
28
- <td><%= button_to_fulfilled_without_acceptance order -%></td>
29
- <% end -%>
30
- </tr>
38
+ <td><% if can_trigger_fulfilled_without_acceptance? -%>
39
+ <%= button_to_fulfilled_without_acceptance order -%>
40
+ <% end -%>
41
+ <%= button_to_cancel order -%>
42
+ </td>
31
43
  <% end -%>
32
44
 
33
45
  <% if order.ready? && can_trigger_finish? -%>
34
- <tr>
35
46
  <td><%= button_to_finish order -%></td>
36
- </tr>
47
+ <% end -%>
48
+
49
+ <% if order.user_review? && current_user == order.user -%>
50
+ <td><%= button_to_alteration_approve order -%></td>
51
+ <% end -%>
52
+
53
+ <% if show_order_buttons -%>
54
+ </tr>
37
55
  <% end -%>
38
56
 
39
57
  </table>
40
58
 
41
59
  </fieldset>
42
60
 
61
+ <% if params[:action] != 'checkout_form' -%>
43
62
  <% if order.notes.size != 0 -%>
44
63
  <h3><%= t('.order_notes') -%></h3>
45
64
  <% end -%>
@@ -51,3 +70,5 @@
51
70
  </ul>
52
71
 
53
72
  <%= render :partial => 'notes/new', :locals => { :order => order, :user => current_user } if order.may_note? -%>
73
+
74
+ <% end -%>
@@ -0,0 +1,3 @@
1
+ <% trolley ||= order_summary.trolley -%>
2
+ <li class="order-summary" id="order-summary-<%= order_summary.id -%>"><%= link_to_as_summary_of(order_summary, trolley.user) -%></li>
3
+
@@ -0,0 +1,35 @@
1
+ <% @button_text = t(".confirm")
2
+ @title = t(".confirm_order")
3
+ -%>
4
+
5
+ <h1><%= @title -%></h1>
6
+
7
+ <%= render @order -%>
8
+
9
+ <% form_for(@order, :url => checkout_form_target_action_url_hash, :html => {:method => 'post'} ) do |f| %>
10
+
11
+ <%= f.error_messages %>
12
+
13
+ <fieldset>
14
+
15
+ <%# overridable helper method that will set up fields appropriately -%>
16
+
17
+ <%= order_checkout_fields(f) -%>
18
+
19
+ <% if @order.notes.size == 1 -%>
20
+ <% f.fields_for :notes do |note_form| -%>
21
+
22
+ <label><%= t '.additional_info_for_order' -%></label>
23
+
24
+ <%= note_form.hidden_field :user_id, :value => current_user.id -%>
25
+
26
+ <%= note_form.text_area :body, { :cols => 90, :rows => 5 } %>
27
+
28
+ <% end -%>
29
+ <% end -%>
30
+
31
+ </fieldset>
32
+
33
+ <%= f.submit @button_text %>
34
+ <% end %>
35
+
@@ -12,9 +12,9 @@
12
12
  <% if @orders.size > 0 -%>
13
13
 
14
14
  <h2><%= orders_state_headline -%><%= clear_extra_params -%></h2>
15
-
16
- <%= render :partial => 'orders/order', :collection => @orders, :locals => { :trolley => @trolley, :status => @state } -%>
17
-
15
+ <ul id="order-summaries-list">
16
+ <%= render :partial => 'orders/order_summary', :collection => @orders, :locals => { :trolley => @trolley, :status => @state } -%>
17
+ </ul>
18
18
  <div id="prev-next"><%= will_paginate @orders, :params => params %></div>
19
19
  <% else -%>
20
20
  <p><%= t("orders.index.no_orders") %></p>
@@ -2,10 +2,15 @@
2
2
 
3
3
  <h2><%= t("trolleys.orders.#{status}") -%></h2>
4
4
 
5
- <%= render :partial => 'orders/order',
6
- :collection => @trolley.orders.send("with_state_#{status}"),
7
- :locals => { :trolley => trolley, :status => status } -%>
8
-
5
+ <% if status == 'current' -%>
6
+ <%= render :partial => 'orders/order',
7
+ :collection => @trolley.orders.send("with_state_#{status}"),
8
+ :locals => { :trolley => trolley, :status => status } -%>
9
+ <% else -%>
10
+ <ul id="order-summaries-list">
11
+ <%= render :partial => 'orders/order_summary', :collection => @trolley.orders.send("with_state_#{status}"), :locals => { :trolley => @trolley, :status => status } -%>
12
+ </ul>
13
+ <% end -%>
9
14
  <% elsif status == 'current' -%>
10
15
  <h2><%= t("trolleys.orders.current") -%></h2>
11
16
  <p><%= t("trolleys.orders.none_pending") %></p>
@@ -2,7 +2,6 @@
2
2
  if current_user == @trollied_user
3
3
  @title = t(".your_title")
4
4
  else
5
- # TODO: interpolate user name
6
5
  # (means name method has to be implemented for user model)
7
6
  @title = t(".for_user_title", :name => @trollied_user.trolley_user_display_name)
8
7
  end
@@ -39,6 +39,10 @@ en:
39
39
  add_note_to_order_for_admin: "Add a note about this order for staff."
40
40
  add_note_to_order_for_user: "Add a note about this order for the owner."
41
41
  orders:
42
+ checkout_form:
43
+ confirm: "Confirm Checkout"
44
+ confirm_order: "Confirm order details"
45
+ additional_info_for_order: "Anything else you would like to tell us about this order?"
42
46
  edit:
43
47
  update: "Update"
44
48
  date_pickers:
@@ -54,6 +58,8 @@ en:
54
58
  current_orders: "Current Orders"
55
59
  from: "from"
56
60
  in_process_orders: "Orders Awaiting processing"
61
+ items: "items"
62
+ order_number: "Order:"
57
63
  ready_orders: "Ready Orders"
58
64
  until: "until"
59
65
  user_review_orders: "Orders needing user attention"
@@ -75,13 +81,16 @@ en:
75
81
  new:
76
82
  create: "Create"
77
83
  order:
84
+ alteration_approve: "Approve changes"
78
85
  are_you_sure: "Are you sure?"
79
86
  cancel: "Cancel"
80
87
  checkout: "Checkout"
81
88
  destroy: "Clear all"
82
89
  finish: "Mark as completed"
83
90
  fulfilled_without_acceptance: "Mark as ready"
91
+ order_controls_preface: "Order actions:"
84
92
  order_notes: "Notes for this order:"
93
+ purchasable_item_actions: "Actions"
85
94
  purchasable_item_description: "Item"
86
95
  user: "User:"
87
96
  show:
@@ -92,6 +101,7 @@ en:
92
101
  change_to_checkout: "Order Checked Out"
93
102
  change_to_finish: "Order Completed"
94
103
  change_to_fulfilled_without_acceptance: "Order Ready"
104
+ change_to_alteration_approve: "You approved the changes to the order. It is now back in process."
95
105
  created: "Created order"
96
106
  updated: "Updated order"
97
107
  deleted: "Deleted order"
@@ -3,6 +3,8 @@ members = Order.workflow_event_names.inject(Hash.new) do |hash, event_name|
3
3
  hash
4
4
  end
5
5
 
6
+ members[:checkout_form] = :get
7
+
6
8
  ActionController::Routing::Routes.draw do |map|
7
9
  map.resources :orders, :member => members, :except => [:new, :create], :has_many => :line_items, :has_many => :notes
8
10
  end
@@ -1,6 +1,6 @@
1
1
  module HasTrolleyControllerHelpers
2
2
  def self.included(klass)
3
- klass.send :helper_method, :url_for_trolley
3
+ klass.send :helper_method, :url_for_trolley, :url_for_order
4
4
  klass.send :include, UrlFor
5
5
  end
6
6
 
@@ -30,7 +30,8 @@ module HasTrolleyControllerHelpers
30
30
  trolley = @order.trolley if @order && trolley.blank?
31
31
 
32
32
  order = options[:order] || @order || trolley.selected_order
33
-
33
+ trolley = order.trolley
34
+
34
35
  url_for [trolley.user, trolley, order]
35
36
  end
36
37
 
@@ -62,7 +62,7 @@ module OrderStatus
62
62
  # create a named_scope for each of our declared states
63
63
  workflow_spec.state_names.each do |name|
64
64
  scope_name = "with_state_#{name}".to_sym
65
- named_scope scope_name, :conditions => { :workflow_state => name.to_s }
65
+ named_scope scope_name, :conditions => { :workflow_state => name.to_s }, :order => 'updated_at DESC'
66
66
  end
67
67
 
68
68
  # in(state_name)
@@ -7,4 +7,4 @@ ActionController::Base.send(:helper, OrdersHelper)
7
7
  ActionController::Base.send(:helper, LineItemsHelper)
8
8
 
9
9
  # load our locales
10
- I18n.load_path += Dir[ File.join(File.dirname(__FILE__), '..', 'config', 'locales', '*.{rb,yml}') ]
10
+ # I18n.load_path += Dir[ File.join(File.dirname(__FILE__), '..', 'config', 'locales', '*.{rb,yml}') ]
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trollied
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 3
10
- version: 0.1.3
9
+ - 4
10
+ version: 0.1.4
11
11
  platform: ruby
12
12
  authors:
13
13
  - Walter McGinnis
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-29 00:00:00 +12:00
18
+ date: 2011-09-29 00:00:00 +13:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -135,6 +135,8 @@ files:
135
135
  - app/views/notes/new.html.erb
136
136
  - app/views/orders/_date_pickers.html.erb
137
137
  - app/views/orders/_order.html.erb
138
+ - app/views/orders/_order_summary.html.erb
139
+ - app/views/orders/checkout_form.html.erb
138
140
  - app/views/orders/index.html.erb
139
141
  - app/views/orders/show.html.erb
140
142
  - app/views/trolleys/_orders.html.erb