trollied 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+