trollied 0.1.3 → 0.1.4

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.
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