trollied 0.1.0

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 (144) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +294 -0
  4. data/README.rdoc +96 -0
  5. data/Rakefile +55 -0
  6. data/VERSION +1 -0
  7. data/app/controllers/line_items_controller.rb +168 -0
  8. data/app/controllers/notes_controller.rb +121 -0
  9. data/app/controllers/orders_controller.rb +210 -0
  10. data/app/controllers/trolleys_controller.rb +26 -0
  11. data/app/helpers/gets_trollied_helper.rb +31 -0
  12. data/app/helpers/line_items_helper.rb +5 -0
  13. data/app/helpers/orders_helper.rb +184 -0
  14. data/app/models/line_item.rb +14 -0
  15. data/app/models/note.rb +15 -0
  16. data/app/models/order.rb +29 -0
  17. data/app/models/trolley.rb +51 -0
  18. data/app/views/line_items/_form.html.erb +8 -0
  19. data/app/views/line_items/_line_item.html.erb +12 -0
  20. data/app/views/line_items/new.html.erb +11 -0
  21. data/app/views/notes/_form.html.erb +7 -0
  22. data/app/views/notes/_new.html.erb +14 -0
  23. data/app/views/notes/_note.html.erb +4 -0
  24. data/app/views/notes/index.html.erb +13 -0
  25. data/app/views/notes/new.html.erb +5 -0
  26. data/app/views/orders/_date_pickers.html.erb +15 -0
  27. data/app/views/orders/_order.html.erb +53 -0
  28. data/app/views/orders/index.html.erb +22 -0
  29. data/app/views/orders/show.html.erb +14 -0
  30. data/app/views/trolleys/_orders.html.erb +13 -0
  31. data/app/views/trolleys/show.html.erb +16 -0
  32. data/config/locales/en.yml +115 -0
  33. data/config/routes.rb +8 -0
  34. data/generators/trollied_migrations/USAGE +2 -0
  35. data/generators/trollied_migrations/templates/line_items_migration.rb +16 -0
  36. data/generators/trollied_migrations/templates/notes_migration.rb +15 -0
  37. data/generators/trollied_migrations/templates/orders_migration.rb +15 -0
  38. data/generators/trollied_migrations/templates/trolleys_migration.rb +14 -0
  39. data/generators/trollied_migrations/trollied_migrations_generator.rb +13 -0
  40. data/lib/gets_trollied.rb +38 -0
  41. data/lib/gets_trollied_controller_helpers.rb +29 -0
  42. data/lib/has_trolley.rb +42 -0
  43. data/lib/has_trolley_controller_helpers.rb +43 -0
  44. data/lib/order_status.rb +121 -0
  45. data/lib/trollied.rb +5 -0
  46. data/rails/init.rb +10 -0
  47. data/test/full_2_3_5_app_with_tests/.gitignore +27 -0
  48. data/test/full_2_3_5_app_with_tests/README +1 -0
  49. data/test/full_2_3_5_app_with_tests/Rakefile +10 -0
  50. data/test/full_2_3_5_app_with_tests/app/controllers/application_controller.rb +14 -0
  51. data/test/full_2_3_5_app_with_tests/app/controllers/items_controller.rb +85 -0
  52. data/test/full_2_3_5_app_with_tests/app/controllers/user_controller.rb +2 -0
  53. data/test/full_2_3_5_app_with_tests/app/helpers/application_helper.rb +3 -0
  54. data/test/full_2_3_5_app_with_tests/app/helpers/items_helper.rb +2 -0
  55. data/test/full_2_3_5_app_with_tests/app/helpers/user_helper.rb +2 -0
  56. data/test/full_2_3_5_app_with_tests/app/models/item.rb +4 -0
  57. data/test/full_2_3_5_app_with_tests/app/models/user.rb +3 -0
  58. data/test/full_2_3_5_app_with_tests/app/views/items/edit.html.erb +20 -0
  59. data/test/full_2_3_5_app_with_tests/app/views/items/index.html.erb +22 -0
  60. data/test/full_2_3_5_app_with_tests/app/views/items/new.html.erb +19 -0
  61. data/test/full_2_3_5_app_with_tests/app/views/items/show.html.erb +13 -0
  62. data/test/full_2_3_5_app_with_tests/app/views/layouts/application.html.erb +19 -0
  63. data/test/full_2_3_5_app_with_tests/app/views/layouts/items.html.erb +19 -0
  64. data/test/full_2_3_5_app_with_tests/config/boot.rb +110 -0
  65. data/test/full_2_3_5_app_with_tests/config/database.yml +22 -0
  66. data/test/full_2_3_5_app_with_tests/config/environment.rb +57 -0
  67. data/test/full_2_3_5_app_with_tests/config/environments/development.rb +17 -0
  68. data/test/full_2_3_5_app_with_tests/config/environments/production.rb +28 -0
  69. data/test/full_2_3_5_app_with_tests/config/environments/test.rb +28 -0
  70. data/test/full_2_3_5_app_with_tests/config/initializers/backtrace_silencers.rb +7 -0
  71. data/test/full_2_3_5_app_with_tests/config/initializers/inflections.rb +10 -0
  72. data/test/full_2_3_5_app_with_tests/config/initializers/mime_types.rb +5 -0
  73. data/test/full_2_3_5_app_with_tests/config/initializers/new_rails_defaults.rb +21 -0
  74. data/test/full_2_3_5_app_with_tests/config/initializers/session_store.rb +15 -0
  75. data/test/full_2_3_5_app_with_tests/config/locales/en.yml +4 -0
  76. data/test/full_2_3_5_app_with_tests/config/locales/fr.yml +4 -0
  77. data/test/full_2_3_5_app_with_tests/config/locales/zh.yml +4 -0
  78. data/test/full_2_3_5_app_with_tests/config/locales.yml +5 -0
  79. data/test/full_2_3_5_app_with_tests/config/routes.rb +8 -0
  80. data/test/full_2_3_5_app_with_tests/config.ru +6 -0
  81. data/test/full_2_3_5_app_with_tests/db/migrate/20100407010602_create_items.rb +13 -0
  82. data/test/full_2_3_5_app_with_tests/db/migrate/20110426030509_create_users.rb +13 -0
  83. data/test/full_2_3_5_app_with_tests/db/migrate/20110426033906_create_trolleys.rb +14 -0
  84. data/test/full_2_3_5_app_with_tests/db/migrate/20110426033907_create_orders.rb +15 -0
  85. data/test/full_2_3_5_app_with_tests/db/migrate/20110426033908_create_line_items.rb +16 -0
  86. data/test/full_2_3_5_app_with_tests/db/migrate/20110615234040_create_notes.rb +15 -0
  87. data/test/full_2_3_5_app_with_tests/db/schema.rb +56 -0
  88. data/test/full_2_3_5_app_with_tests/db/seeds.rb +7 -0
  89. data/test/full_2_3_5_app_with_tests/doc/README_FOR_APP +2 -0
  90. data/test/full_2_3_5_app_with_tests/public/404.html +30 -0
  91. data/test/full_2_3_5_app_with_tests/public/422.html +30 -0
  92. data/test/full_2_3_5_app_with_tests/public/500.html +30 -0
  93. data/test/full_2_3_5_app_with_tests/public/favicon.ico +0 -0
  94. data/test/full_2_3_5_app_with_tests/public/images/rails.png +0 -0
  95. data/test/full_2_3_5_app_with_tests/public/index.html +275 -0
  96. data/test/full_2_3_5_app_with_tests/public/javascripts/application.js +2 -0
  97. data/test/full_2_3_5_app_with_tests/public/javascripts/controls.js +963 -0
  98. data/test/full_2_3_5_app_with_tests/public/javascripts/dragdrop.js +973 -0
  99. data/test/full_2_3_5_app_with_tests/public/javascripts/effects.js +1128 -0
  100. data/test/full_2_3_5_app_with_tests/public/javascripts/prototype.js +4320 -0
  101. data/test/full_2_3_5_app_with_tests/public/robots.txt +5 -0
  102. data/test/full_2_3_5_app_with_tests/public/stylesheets/scaffold.css +54 -0
  103. data/test/full_2_3_5_app_with_tests/script/about +4 -0
  104. data/test/full_2_3_5_app_with_tests/script/console +3 -0
  105. data/test/full_2_3_5_app_with_tests/script/dbconsole +3 -0
  106. data/test/full_2_3_5_app_with_tests/script/destroy +3 -0
  107. data/test/full_2_3_5_app_with_tests/script/generate +3 -0
  108. data/test/full_2_3_5_app_with_tests/script/performance/benchmarker +3 -0
  109. data/test/full_2_3_5_app_with_tests/script/performance/profiler +3 -0
  110. data/test/full_2_3_5_app_with_tests/script/plugin +3 -0
  111. data/test/full_2_3_5_app_with_tests/script/runner +3 -0
  112. data/test/full_2_3_5_app_with_tests/script/server +3 -0
  113. data/test/full_2_3_5_app_with_tests/test/factories.rb +22 -0
  114. data/test/full_2_3_5_app_with_tests/test/functional/line_items_controller_test.rb +69 -0
  115. data/test/full_2_3_5_app_with_tests/test/functional/orders_controller_test.rb +75 -0
  116. data/test/full_2_3_5_app_with_tests/test/integration/gets_trollied_test.rb +38 -0
  117. data/test/full_2_3_5_app_with_tests/test/integration/order_test.rb +79 -0
  118. data/test/full_2_3_5_app_with_tests/test/integration/trolley_test.rb +71 -0
  119. data/test/full_2_3_5_app_with_tests/test/performance/browsing_test.rb +9 -0
  120. data/test/full_2_3_5_app_with_tests/test/selenium.rb +83 -0
  121. data/test/full_2_3_5_app_with_tests/test/test_helper.rb +54 -0
  122. data/test/full_2_3_5_app_with_tests/test/unit/gets_trollied_test.rb +29 -0
  123. data/test/full_2_3_5_app_with_tests/test/unit/helpers/gets_trollied_helper_test.rb +75 -0
  124. data/test/full_2_3_5_app_with_tests/test/unit/helpers/orders_helper_test.rb +34 -0
  125. data/test/full_2_3_5_app_with_tests/test/unit/line_item_test.rb +28 -0
  126. data/test/full_2_3_5_app_with_tests/test/unit/note_test.rb +14 -0
  127. data/test/full_2_3_5_app_with_tests/test/unit/order_test.rb +65 -0
  128. data/test/full_2_3_5_app_with_tests/test/unit/trolley_test.rb +80 -0
  129. data/test/full_2_3_5_app_with_tests/tmp/restart.txt +0 -0
  130. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/init.rb +1 -0
  131. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/base.rb +31 -0
  132. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/force_extension.rb +57 -0
  133. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/locale.rb +70 -0
  134. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/pagination.rb +33 -0
  135. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/uuid_token.rb +78 -0
  136. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter.rb +94 -0
  137. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/force_extension_spec.rb +65 -0
  138. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/generation_spec.rb +367 -0
  139. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/pagination_extension_spec.rb +19 -0
  140. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/recognition_spec.rb +76 -0
  141. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/routing_filter_spec.rb +114 -0
  142. data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/spec_helper.rb +108 -0
  143. data/test/helper.rb +10 -0
  144. metadata +345 -0
@@ -0,0 +1,121 @@
1
+ class NotesController < ApplicationController
2
+ # Prevents the following error from showing up, common in Rails engines
3
+ # A copy of ApplicationController has been removed from the module tree but is still active!
4
+ unloadable
5
+
6
+ before_filter :get_order
7
+ before_filter :get_note, :except => [:new, :index, :create]
8
+
9
+ # GET /notes
10
+ # GET /notes.xml
11
+ def index
12
+ # TODO: add permission check of admin mechanism
13
+ # TODO: add pagination
14
+
15
+ @notes = @order.notes
16
+
17
+ respond_to do |format|
18
+ format.html # index.html.erb
19
+ # format.xml { render :xml => @line_items }
20
+ end
21
+ end
22
+
23
+ # GET /notes/1
24
+ # GET /notes/1.xml
25
+ def show
26
+ respond_to do |format|
27
+ format.html # show.html.erb
28
+ # format.xml { render :xml => @line_item }
29
+ end
30
+ end
31
+
32
+ # GET /notes/new
33
+ # GET /notes/new.xml
34
+ def new
35
+ @order.notes.new
36
+
37
+ respond_to do |format|
38
+ format.html # new.html.erb
39
+ # format.js { render :layout => false } # needs to come after html for IE to work
40
+ # format.xml { render :xml => @line_item }
41
+ end
42
+ end
43
+
44
+ # GET /notes/1/edit
45
+ def edit
46
+ end
47
+
48
+ # POST /notes
49
+ # POST /notes.xml
50
+ def create
51
+ note_params = params[:note] || params[:order_note] || Hash.new
52
+
53
+ @note = @order.notes.new(note_params)
54
+
55
+ respond_to do |format|
56
+ if @note.save
57
+ flash[:notice] = t('notes.controllers.created')
58
+ # we redirect to purchasable_item object in the new purchasable_item version
59
+ # assumes controller name is tableized version of class
60
+ format.html { redirect_to url_for_order_or_trolley }
61
+ # TODO: adjust :location accordingly for being a nested route
62
+ # format.xml { render :xml => @line_item, :status => :created, :location => @line_item }
63
+ else
64
+ format.html { render :action => "new" }
65
+ # format.xml { render :xml => @line_item.errors, :status => :unprocessable_entity }
66
+ end
67
+ end
68
+ end
69
+
70
+ # PUT /notes/1
71
+ # PUT /notes/1.xml
72
+ def update
73
+ respond_to do |format|
74
+ note_params = params[:note] || params[:order_note]
75
+ if @note.update_attributes(note_params)
76
+ flash[:notice] = t('notes.controllers.updated')
77
+ format.html { redirect_to url_for_order_or_trolley }
78
+ # format.xml { head :ok }
79
+ else
80
+ format.html { render :action => "edit" }
81
+ # format.xml { render :xml => @line_item.errors, :status => :unprocessable_entity }
82
+ end
83
+ end
84
+ end
85
+
86
+ # DELETE /notes/1
87
+ # DELETE /notes/1.xml
88
+ def destroy
89
+ @order ||= @note.order
90
+ return_to = @order ? url_for_order_or_trolley : { :action => :index }
91
+
92
+ @note.destroy
93
+
94
+ respond_to do |format|
95
+ flash[:notice] = t('notes.controllers.deleted')
96
+ format.html { redirect_to return_to }
97
+ # format.xml { head :ok }
98
+ end
99
+ end
100
+
101
+ protected
102
+
103
+ def get_note
104
+ @note ||= if @order
105
+ if params[:id].present?
106
+ @order.notes.find(params[:id])
107
+ end
108
+ elsif params[:id].present?
109
+ Note.find(params[:id])
110
+ end
111
+ end
112
+
113
+ def get_order
114
+ @order = if params[:order_id].present?
115
+ Order.find(params[:order_id])
116
+ elsif params[:id].present?
117
+ @note = Note.find(params[:id])
118
+ @note.order
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,210 @@
1
+ class OrdersController < ApplicationController
2
+ # Prevents the following error from showing up, common in Rails engines
3
+ # A copy of ApplicationController has been removed from the module tree but is still active!
4
+ unloadable
5
+
6
+ before_filter :get_user, :only => [:index]
7
+ before_filter :get_trolley
8
+ before_filter :get_order, :except => [:new, :index, :create]
9
+
10
+ # GET /orders
11
+ # GET /orders.xml
12
+ def index
13
+ # TODO: add permission check of admin mechanism
14
+
15
+ # 'all' will return what you expect, i.e. orders for all states
16
+ # other valid values are specific state names
17
+ # default should be set depending on rights of current_user
18
+ # we'll start with an assumption of staff view
19
+ # as a user's trolley lists their own current orders by default
20
+ @state = params[:state].present? ? params[:state] : 'in_process'
21
+ params[:state] = @state
22
+
23
+ @conditions = set_up_conditions_based_on_params
24
+
25
+ options = { :page => params[:page],
26
+ :per_page => 5,
27
+ :conditions => @conditions }
28
+
29
+ @orders = Order.paginate(options)
30
+
31
+ respond_to do |format|
32
+ format.html # index.html.erb
33
+ # format.xml { render :xml => @line_items }
34
+ end
35
+ end
36
+
37
+ # GET /orders/1
38
+ # GET /orders/1.xml
39
+ def show
40
+ respond_to do |format|
41
+ format.html # show.html.erb
42
+ # format.xml { render :xml => @line_item }
43
+ end
44
+ end
45
+
46
+ # GET /orders/new
47
+ # GET /orders/new.xml
48
+ def new
49
+ @trolley ||= current_user ? current_user.trolley : raise # trolley not found
50
+
51
+ @trolley.orders.new
52
+
53
+ respond_to do |format|
54
+ format.html # new.html.erb
55
+ # format.js { render :layout => false } # needs to come after html for IE to work
56
+ # format.xml { render :xml => @line_item }
57
+ end
58
+ end
59
+
60
+ # GET /orders/1/edit
61
+ def edit
62
+ end
63
+
64
+ # POST /orders
65
+ # POST /orders.xml
66
+ def create
67
+ order_params = params[:order] || params[:trolley_order] || Hash.new
68
+
69
+ @order = @trolley.orders.new(order_params)
70
+
71
+ respond_to do |format|
72
+ if @order.save
73
+ flash[:notice] = t('orders.controllers.created')
74
+ # we redirect to purchasable_item object in the new purchasable_item version
75
+ # assumes controller name is tableized version of class
76
+ format.html { redirect_to url_for_trolley }
77
+ # TODO: adjust :location accordingly for being a nested route
78
+ # format.xml { render :xml => @line_item, :status => :created, :location => @line_item }
79
+ else
80
+ format.html { render :action => "new" }
81
+ # format.xml { render :xml => @line_item.errors, :status => :unprocessable_entity }
82
+ end
83
+ end
84
+ end
85
+
86
+ # PUT /orders/1
87
+ # PUT /orders/1.xml
88
+ def update
89
+ respond_to do |format|
90
+ order_params = params[:order] || params[:trolley_order]
91
+ if @order.update_attributes(order_params)
92
+ flash[:notice] = t('orders.controllers.updated')
93
+ format.html { redirect_to @order }
94
+ # format.xml { head :ok }
95
+ else
96
+ format.html { render :action => "edit" }
97
+ # format.xml { render :xml => @line_item.errors, :status => :unprocessable_entity }
98
+ end
99
+ end
100
+ end
101
+
102
+ # DELETE /orders/1
103
+ # DELETE /orders/1.xml
104
+ def destroy
105
+ @trolley ||= @order.trolley
106
+ return_to = @trolley ? url_for_trolley : { :action => :index }
107
+
108
+ @order.destroy
109
+
110
+ respond_to do |format|
111
+ flash[:notice] = t('orders.controllers.deleted')
112
+ format.html { redirect_to return_to }
113
+ # format.xml { head :ok }
114
+ end
115
+ end
116
+
117
+ # additional actions that correspond to order_status events
118
+ %w(checkout cancel fulfilled_without_acceptance finish).each do |event|
119
+ code = Proc.new {
120
+ @order.send("#{event}!")
121
+ @trolley ||= @order.trolley
122
+
123
+ flash[:notice] = t("orders.controllers.change_to_#{event}")
124
+ redirect_to url_for_trolley
125
+ }
126
+
127
+ define_method(event, &code)
128
+ end
129
+
130
+ private
131
+ # accepts line_item.locale or line_item.id for lookup
132
+ # line_item.locale should be unique within the scope of @purchasable_item
133
+ def get_order
134
+ @order = if @trolley
135
+ if params[:id].present?
136
+ @trolley.orders.find(params[:id])
137
+ else
138
+ @trolley.selected_order
139
+ end
140
+ elsif params[:id].present?
141
+ Order.find(params[:id])
142
+ end
143
+ end
144
+
145
+ def get_trolley
146
+ @trolley = if params[:trolley_id].present?
147
+ Trolley.find(params[:trolley_id])
148
+ elsif @user
149
+ @user.trolley
150
+ end
151
+ end
152
+
153
+ def get_user
154
+ @user = if params[:user_id].present? || params[:user].present?
155
+ id = params[:user_id].present? ? params[:user_id] : params[:user]
156
+ User.find(id)
157
+ end
158
+ end
159
+
160
+ # validate and add them as conditions
161
+ def add_date_clause_and_var_for(name, clauses_array, clauses_hash)
162
+ if params[name].present?
163
+ value = params[name]
164
+ var_name = "@" + name.to_s
165
+
166
+ instance_variable_set(var_name, value)
167
+
168
+ begin
169
+ Date.parse(value)
170
+ operator = ">="
171
+ operator = "<=" if name == :until
172
+
173
+ clauses_array << "created_at #{operator} :#{name}"
174
+ clauses_hash[name] = value
175
+ rescue
176
+ instance_variable_set(var_name, nil)
177
+ end
178
+ end
179
+ end
180
+
181
+ def default_conditions_hash
182
+ { :workflow_state => @state }
183
+ end
184
+
185
+ def set_up_conditions_based_on_params
186
+ conditions_clauses = Array.new
187
+ conditions_hash = default_conditions_hash
188
+
189
+ # handle date range
190
+ add_date_clause_and_var_for(:from, conditions_clauses, conditions_hash)
191
+ add_date_clause_and_var_for(:until, conditions_clauses, conditions_hash)
192
+
193
+ # user is a little funnier because trolley is what has the direct user relation
194
+ # so trolley is really what will give us a user's orders
195
+ conditions_hash[:trolley_id] = @trolley.id if @trolley
196
+
197
+ if conditions_clauses.size > 0
198
+ conditions_hash.each do |k,v|
199
+ conditions_clauses << "#{k} = :#{k}" unless conditions_clauses.join.include?(':' + k.to_s)
200
+ end
201
+ end
202
+
203
+ conditions = if conditions_clauses.size == 0
204
+ conditions_hash
205
+ else
206
+ [conditions_clauses.join(" AND "), conditions_hash]
207
+ end
208
+
209
+ end
210
+ end
@@ -0,0 +1,26 @@
1
+ class TrolleysController < ApplicationController
2
+ # Prevents the following error from showing up, common in Rails engines
3
+ # A copy of ApplicationController has been removed from the module tree but is still active!
4
+ unloadable
5
+
6
+ before_filter :get_trollied_user
7
+ before_filter :get_trolley
8
+
9
+ # list orders
10
+ def show
11
+ respond_to do |format|
12
+ format.html # index.html.erb
13
+ end
14
+ end
15
+
16
+ protected
17
+
18
+ def get_trollied_user
19
+ @trollied_user = User.find(params[:user_id])
20
+ end
21
+
22
+ def get_trolley
23
+ @trolley = @trollied_user.trolley
24
+ end
25
+
26
+ end
@@ -0,0 +1,31 @@
1
+ # include this to gain helpers for shopping trolley
2
+ module GetsTrolliedHelper
3
+ include HasTrolleyControllerHelpers::UrlFor
4
+
5
+ # wrapped in a div to allow for styling the form to be inline
6
+ def button_to_place_in_trolley(purchasable_item)
7
+ "<div class=\"add-to-trolley\">" +
8
+ button_to(t('gets_trollied_helper.add_to_trolley'),
9
+ :controller => :line_items,
10
+ :action => :create,
11
+ purchasable_item.class.as_foreign_key_sym => purchasable_item) +
12
+ "</div>"
13
+ end
14
+
15
+ # TODO: trolley link
16
+
17
+ def in_trolley_status_or_button_to_place_in_trolley(purchasable_item)
18
+ html = String.new
19
+ if current_user && current_user != false &&
20
+ current_user.respond_to?(:trolley) &&
21
+ current_user.trolley.has_active_order_for?(purchasable_item)
22
+ html = "<div class=\"in-trolley\">" +
23
+ t('gets_trollied_helper.in_trolley') +
24
+ "</div>"
25
+ else
26
+ html = button_to_place_in_trolley(purchasable_item)
27
+ end
28
+ html
29
+ end
30
+
31
+ end
@@ -0,0 +1,5 @@
1
+ module LineItemsHelper
2
+ def link_to_purchasable_in(line_item)
3
+ link_to line_item.description_for_purchasing, line_item.purchasable_item
4
+ end
5
+ end
@@ -0,0 +1,184 @@
1
+ module OrdersHelper
2
+ # implement in your application
3
+ def link_to_profile_for(user)
4
+ link_to user.trolley_user_display_name, url_for_trolley(:user => user)
5
+ end
6
+
7
+ def link_to_orders_for(user)
8
+ link_to(user.trolley_user_display_name, :user => user)
9
+ end
10
+
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?
15
+ end
16
+
17
+ # override the method can_trigger_...? methods with your own security checks
18
+ def can_trigger_fulfilled_without_acceptance?
19
+ params[:controller] == 'orders'
20
+ end
21
+
22
+ def can_trigger_finish?
23
+ params[:controller] == 'orders'
24
+ end
25
+
26
+ def order_button_for(action, order)
27
+ options = { :confirm => t('orders.order.are_you_sure'),
28
+ :class => 'order-button' }
29
+
30
+ options[:method] = 'delete' if action.to_s == 'destroy'
31
+
32
+ button_to(t("orders.order.#{action}"),
33
+ { :controller => :orders,
34
+ :action => action,
35
+ :id => order },
36
+ options)
37
+ end
38
+
39
+ # define button_to methods for each possible event name for Order
40
+ Order.workflow_event_names.each do |event_name|
41
+ code = lambda { |order|
42
+ order_button_for(event_name.to_s, order)
43
+ }
44
+
45
+ define_method("button_to_#{event_name}", &code)
46
+ end
47
+
48
+ # special case
49
+ def button_to_clear(order)
50
+ order_button_for('destroy', order)
51
+ end
52
+
53
+ # single definition helper for format of displaying number of something
54
+ def show_count_for(number)
55
+ " (#{number})"
56
+ end
57
+
58
+ def link_to_state_unless_current(state, count)
59
+ link_to_unless_current(t("orders.index.#{state}") + show_count_for(count),
60
+ :state => state,
61
+ :user => @user,
62
+ :trolley => @trolley,
63
+ :from => @from,
64
+ :until => @until)
65
+ end
66
+
67
+ # returns a list of links to order states
68
+ # that have orders in their state
69
+ # with number of orders in a given state indicated
70
+ def state_links
71
+ html = '<ul id="state-links" class="horizontal-list">'
72
+
73
+ states_count = 1
74
+
75
+ states = Order.workflow_spec.state_names.sort_by { |s| I18n.t("orders.index.#{s.to_s}") }
76
+
77
+ states.each do |state|
78
+ adjusted_conditions = adjust_value_in_conditions_for(:workflow_state, state.to_s, @conditions)
79
+
80
+ with_state_count = Order.count(:conditions => adjusted_conditions)
81
+
82
+ if with_state_count > 0
83
+ classes = 'state-link'
84
+ classes += ' first' if states_count == 1
85
+
86
+ if state == :in_process && @state == state.to_s
87
+ html += content_tag('li',
88
+ t("orders.index.#{state}") + show_count_for(with_state_count),
89
+ :class => classes)
90
+ else
91
+ html += content_tag('li',
92
+ link_to_state_unless_current(state, with_state_count),
93
+ :class => classes)
94
+
95
+ end
96
+ states_count += 1
97
+ end
98
+ end
99
+
100
+ html += '</ul>'
101
+ end
102
+
103
+ def order_date_value(direction)
104
+ return String.new unless @conditions
105
+
106
+ new_conditions = drop_key_from_conditions(:from, @conditions)
107
+ new_conditions = drop_key_from_conditions(:until, new_conditions)
108
+
109
+ value = Order.find(:first,
110
+ :select => 'created_at',
111
+ :order => "created_at #{direction}",
112
+ :conditions => new_conditions)
113
+
114
+ value.created_at.to_s(:db).split('\s')[0]
115
+ end
116
+
117
+ def oldest_order_value
118
+ default_date_value('asc')
119
+ end
120
+
121
+ def newest_order_value
122
+ default_date_value('desc')
123
+ end
124
+
125
+ def orders_state_headline
126
+ html = t("orders.helpers.#{@state}_orders")
127
+
128
+ if @from
129
+ html += ' ' + t('orders.helpers.from') + ' '
130
+ html += @from
131
+ end
132
+
133
+ if @until
134
+ html += ' ' + t('orders.helpers.until') + ' '
135
+ html += @until
136
+ end
137
+
138
+ if @user
139
+ html += ' ' + t('orders.helpers.by') + ' '
140
+ html += @user.trolley_user_display_name
141
+ end
142
+
143
+ html
144
+ end
145
+
146
+ def clear_extra_params
147
+ if @user || @from || @until
148
+ clear_link = link_to(t("orders.helpers.clear_params"),
149
+ :state => @state,
150
+ :user => nil,
151
+ :trolley => nil,
152
+ :from => nil,
153
+ :until => nil)
154
+
155
+ clear_link = ' [ ' + clear_link + ' ]'
156
+ content_tag('span', clear_link, :class => 'clear-params')
157
+ end
158
+ end
159
+
160
+ private
161
+
162
+ def adjust_value_in_conditions_for(key, value, conditions)
163
+ new_conditions_hash = Hash.new
164
+ if conditions.is_a?(Array)
165
+ new_conditions_hash = conditions[1]
166
+ else
167
+ new_conditions_hash = conditions
168
+ end
169
+
170
+ new_conditions_hash.delete(:key)
171
+
172
+ new_conditions_hash[key] = value unless value == nil
173
+
174
+ new_conditions = conditions.is_a?(Array) ? [conditions[0], new_conditions_hash] : new_conditions_hash
175
+ end
176
+
177
+ def drop_key_from_conditions(key, conditions)
178
+ adjust_value_in_conditions_for(key, nil, conditions)
179
+ end
180
+
181
+ def url_for_options_for_orders_index
182
+ { :controller => 'orders', :action => 'index' }
183
+ end
184
+ end
@@ -0,0 +1,14 @@
1
+ class LineItem < ActiveRecord::Base
2
+ belongs_to :order
3
+ belongs_to :purchasable_item, :polymorphic => true
4
+
5
+ delegate :description_for_purchasing, :to => :purchasable_item
6
+
7
+ delegate :user, :to => :order
8
+
9
+ # needs to be unique to orders that are current (but not unique to orders generally)
10
+ # validates_uniqueness_of :order_id, :scope => [:purchasable_item_type, :purchasable_item_id]
11
+ def validate
12
+ errors.add(:order, I18n.t('line_item.already_in_order')) if !order.current? && !order.in_process? && order.contains?(purchasable_item)
13
+ end
14
+ end
@@ -0,0 +1,15 @@
1
+ # simple model for adding notes by either staff or ordering user to an order
2
+ # note is body attribute
3
+ class Note < ActiveRecord::Base
4
+ belongs_to :order
5
+ belongs_to :user
6
+
7
+ after_create :alert_order
8
+
9
+ private
10
+
11
+ def alert_order
12
+ order.new_note(self)
13
+ end
14
+ end
15
+
@@ -0,0 +1,29 @@
1
+ class Order < ActiveRecord::Base
2
+ belongs_to :trolley
3
+ has_many :line_items, :dependent => :destroy
4
+ has_many :notes, :dependent => :destroy
5
+
6
+ # has user by its relation to trolley
7
+ delegate :user, :to => :trolley
8
+
9
+ include OrderStatus
10
+
11
+ # convenience method to add new line item based on item_to_order
12
+ def add(purchasable_item)
13
+ line_items.create!(:purchasable_item => purchasable_item)
14
+ end
15
+
16
+ # do any of this order's line_items contain the purchasable_item?
17
+ def contains?(purchasable_item)
18
+ return false if line_items.size == 0
19
+
20
+ line_items.each do |line_item|
21
+ return true if line_item.purchasable_item == purchasable_item
22
+ end
23
+ false
24
+ end
25
+
26
+ def may_note?
27
+ in_process? || ready? || user_review?
28
+ end
29
+ end
@@ -0,0 +1,51 @@
1
+ class Trolley < ActiveRecord::Base
2
+ belongs_to :user
3
+ has_many :orders
4
+
5
+ # get specified order (or first, if not specified)
6
+ # or create one if none exists
7
+ def selected_order(position = 1)
8
+ index = position - 1
9
+
10
+ orders[index] || orders.create!
11
+ end
12
+
13
+ # TODO: STUB: implement way to determine
14
+ # correct order given an purchasable_item
15
+ def correct_order(purchasable_item)
16
+ orders.with_state_current.first || orders.create!
17
+ end
18
+
19
+ # add item or array of items to trolley
20
+ def add(*items_to_order)
21
+ # get order
22
+ items_to_order.each do |item|
23
+ selected_order.add(item)
24
+ end
25
+ end
26
+
27
+ # 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
+ def contains?(purchasable_item, state = nil)
30
+ within_orders = state ? orders.send("with_state_#{state}") : orders
31
+
32
+ these_contain?(within_orders, purchasable_item)
33
+ end
34
+
35
+ def these_contain?(within_orders, purchasable_item)
36
+ return false if within_orders.size == 0
37
+
38
+ within_orders.each do |order|
39
+ return true if order.contains?(purchasable_item)
40
+ end
41
+ false
42
+ end
43
+
44
+ # active is defined as either current or in_process order
45
+ def has_active_order_for?(purchasable_item)
46
+ within_orders = orders.with_state_current + orders.with_state_in_process + orders.with_state_ready
47
+
48
+ these_contain?(within_orders, purchasable_item)
49
+ end
50
+
51
+ end
@@ -0,0 +1,8 @@
1
+ <%= form.error_messages %>
2
+ <%= hidden_field_tag :user, @user.id %>
3
+
4
+ <! -- display details, so user can confirm -->
5
+
6
+
7
+ <%= form.submit @button_text %>
8
+