trollied 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +294 -0
- data/README.rdoc +96 -0
- data/Rakefile +55 -0
- data/VERSION +1 -0
- data/app/controllers/line_items_controller.rb +168 -0
- data/app/controllers/notes_controller.rb +121 -0
- data/app/controllers/orders_controller.rb +210 -0
- data/app/controllers/trolleys_controller.rb +26 -0
- data/app/helpers/gets_trollied_helper.rb +31 -0
- data/app/helpers/line_items_helper.rb +5 -0
- data/app/helpers/orders_helper.rb +184 -0
- data/app/models/line_item.rb +14 -0
- data/app/models/note.rb +15 -0
- data/app/models/order.rb +29 -0
- data/app/models/trolley.rb +51 -0
- data/app/views/line_items/_form.html.erb +8 -0
- data/app/views/line_items/_line_item.html.erb +12 -0
- data/app/views/line_items/new.html.erb +11 -0
- data/app/views/notes/_form.html.erb +7 -0
- data/app/views/notes/_new.html.erb +14 -0
- data/app/views/notes/_note.html.erb +4 -0
- data/app/views/notes/index.html.erb +13 -0
- data/app/views/notes/new.html.erb +5 -0
- data/app/views/orders/_date_pickers.html.erb +15 -0
- data/app/views/orders/_order.html.erb +53 -0
- data/app/views/orders/index.html.erb +22 -0
- data/app/views/orders/show.html.erb +14 -0
- data/app/views/trolleys/_orders.html.erb +13 -0
- data/app/views/trolleys/show.html.erb +16 -0
- data/config/locales/en.yml +115 -0
- data/config/routes.rb +8 -0
- data/generators/trollied_migrations/USAGE +2 -0
- data/generators/trollied_migrations/templates/line_items_migration.rb +16 -0
- data/generators/trollied_migrations/templates/notes_migration.rb +15 -0
- data/generators/trollied_migrations/templates/orders_migration.rb +15 -0
- data/generators/trollied_migrations/templates/trolleys_migration.rb +14 -0
- data/generators/trollied_migrations/trollied_migrations_generator.rb +13 -0
- data/lib/gets_trollied.rb +38 -0
- data/lib/gets_trollied_controller_helpers.rb +29 -0
- data/lib/has_trolley.rb +42 -0
- data/lib/has_trolley_controller_helpers.rb +43 -0
- data/lib/order_status.rb +121 -0
- data/lib/trollied.rb +5 -0
- data/rails/init.rb +10 -0
- data/test/full_2_3_5_app_with_tests/.gitignore +27 -0
- data/test/full_2_3_5_app_with_tests/README +1 -0
- data/test/full_2_3_5_app_with_tests/Rakefile +10 -0
- data/test/full_2_3_5_app_with_tests/app/controllers/application_controller.rb +14 -0
- data/test/full_2_3_5_app_with_tests/app/controllers/items_controller.rb +85 -0
- data/test/full_2_3_5_app_with_tests/app/controllers/user_controller.rb +2 -0
- data/test/full_2_3_5_app_with_tests/app/helpers/application_helper.rb +3 -0
- data/test/full_2_3_5_app_with_tests/app/helpers/items_helper.rb +2 -0
- data/test/full_2_3_5_app_with_tests/app/helpers/user_helper.rb +2 -0
- data/test/full_2_3_5_app_with_tests/app/models/item.rb +4 -0
- data/test/full_2_3_5_app_with_tests/app/models/user.rb +3 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/edit.html.erb +20 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/index.html.erb +22 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/new.html.erb +19 -0
- data/test/full_2_3_5_app_with_tests/app/views/items/show.html.erb +13 -0
- data/test/full_2_3_5_app_with_tests/app/views/layouts/application.html.erb +19 -0
- data/test/full_2_3_5_app_with_tests/app/views/layouts/items.html.erb +19 -0
- data/test/full_2_3_5_app_with_tests/config/boot.rb +110 -0
- data/test/full_2_3_5_app_with_tests/config/database.yml +22 -0
- data/test/full_2_3_5_app_with_tests/config/environment.rb +57 -0
- data/test/full_2_3_5_app_with_tests/config/environments/development.rb +17 -0
- data/test/full_2_3_5_app_with_tests/config/environments/production.rb +28 -0
- data/test/full_2_3_5_app_with_tests/config/environments/test.rb +28 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/backtrace_silencers.rb +7 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/inflections.rb +10 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/mime_types.rb +5 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/new_rails_defaults.rb +21 -0
- data/test/full_2_3_5_app_with_tests/config/initializers/session_store.rb +15 -0
- data/test/full_2_3_5_app_with_tests/config/locales/en.yml +4 -0
- data/test/full_2_3_5_app_with_tests/config/locales/fr.yml +4 -0
- data/test/full_2_3_5_app_with_tests/config/locales/zh.yml +4 -0
- data/test/full_2_3_5_app_with_tests/config/locales.yml +5 -0
- data/test/full_2_3_5_app_with_tests/config/routes.rb +8 -0
- data/test/full_2_3_5_app_with_tests/config.ru +6 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20100407010602_create_items.rb +13 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110426030509_create_users.rb +13 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110426033906_create_trolleys.rb +14 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110426033907_create_orders.rb +15 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110426033908_create_line_items.rb +16 -0
- data/test/full_2_3_5_app_with_tests/db/migrate/20110615234040_create_notes.rb +15 -0
- data/test/full_2_3_5_app_with_tests/db/schema.rb +56 -0
- data/test/full_2_3_5_app_with_tests/db/seeds.rb +7 -0
- data/test/full_2_3_5_app_with_tests/doc/README_FOR_APP +2 -0
- data/test/full_2_3_5_app_with_tests/public/404.html +30 -0
- data/test/full_2_3_5_app_with_tests/public/422.html +30 -0
- data/test/full_2_3_5_app_with_tests/public/500.html +30 -0
- data/test/full_2_3_5_app_with_tests/public/favicon.ico +0 -0
- data/test/full_2_3_5_app_with_tests/public/images/rails.png +0 -0
- data/test/full_2_3_5_app_with_tests/public/index.html +275 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/application.js +2 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/controls.js +963 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/dragdrop.js +973 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/effects.js +1128 -0
- data/test/full_2_3_5_app_with_tests/public/javascripts/prototype.js +4320 -0
- data/test/full_2_3_5_app_with_tests/public/robots.txt +5 -0
- data/test/full_2_3_5_app_with_tests/public/stylesheets/scaffold.css +54 -0
- data/test/full_2_3_5_app_with_tests/script/about +4 -0
- data/test/full_2_3_5_app_with_tests/script/console +3 -0
- data/test/full_2_3_5_app_with_tests/script/dbconsole +3 -0
- data/test/full_2_3_5_app_with_tests/script/destroy +3 -0
- data/test/full_2_3_5_app_with_tests/script/generate +3 -0
- data/test/full_2_3_5_app_with_tests/script/performance/benchmarker +3 -0
- data/test/full_2_3_5_app_with_tests/script/performance/profiler +3 -0
- data/test/full_2_3_5_app_with_tests/script/plugin +3 -0
- data/test/full_2_3_5_app_with_tests/script/runner +3 -0
- data/test/full_2_3_5_app_with_tests/script/server +3 -0
- data/test/full_2_3_5_app_with_tests/test/factories.rb +22 -0
- data/test/full_2_3_5_app_with_tests/test/functional/line_items_controller_test.rb +69 -0
- data/test/full_2_3_5_app_with_tests/test/functional/orders_controller_test.rb +75 -0
- data/test/full_2_3_5_app_with_tests/test/integration/gets_trollied_test.rb +38 -0
- data/test/full_2_3_5_app_with_tests/test/integration/order_test.rb +79 -0
- data/test/full_2_3_5_app_with_tests/test/integration/trolley_test.rb +71 -0
- data/test/full_2_3_5_app_with_tests/test/performance/browsing_test.rb +9 -0
- data/test/full_2_3_5_app_with_tests/test/selenium.rb +83 -0
- data/test/full_2_3_5_app_with_tests/test/test_helper.rb +54 -0
- data/test/full_2_3_5_app_with_tests/test/unit/gets_trollied_test.rb +29 -0
- data/test/full_2_3_5_app_with_tests/test/unit/helpers/gets_trollied_helper_test.rb +75 -0
- data/test/full_2_3_5_app_with_tests/test/unit/helpers/orders_helper_test.rb +34 -0
- data/test/full_2_3_5_app_with_tests/test/unit/line_item_test.rb +28 -0
- data/test/full_2_3_5_app_with_tests/test/unit/note_test.rb +14 -0
- data/test/full_2_3_5_app_with_tests/test/unit/order_test.rb +65 -0
- data/test/full_2_3_5_app_with_tests/test/unit/trolley_test.rb +80 -0
- data/test/full_2_3_5_app_with_tests/tmp/restart.txt +0 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/init.rb +1 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/base.rb +31 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/force_extension.rb +57 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/locale.rb +70 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/pagination.rb +33 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter/uuid_token.rb +78 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/lib/routing_filter.rb +94 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/force_extension_spec.rb +65 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/generation_spec.rb +367 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/pagination_extension_spec.rb +19 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/recognition_spec.rb +76 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/routing_filter_spec.rb +114 -0
- data/test/full_2_3_5_app_with_tests/vendor/plugins/routing-filter/spec/spec_helper.rb +108 -0
- data/test/helper.rb +10 -0
- 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,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
|
data/app/models/note.rb
ADDED
@@ -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
|
+
|
data/app/models/order.rb
ADDED
@@ -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
|