refinerycms-stores 0.0.1

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 (116) hide show
  1. data/Gemfile +26 -0
  2. data/Gemfile.lock +306 -0
  3. data/Guardfile +27 -0
  4. data/LICENSE.txt +20 -0
  5. data/Rakefile +65 -0
  6. data/VERSION +1 -0
  7. data/app/assets/stylesheets/refinery/refinerycms-stores.sass +76 -0
  8. data/app/controllers/refinery/addresses/admin/addresses_controller.rb +12 -0
  9. data/app/controllers/refinery/orders/admin/orders_controller.rb +12 -0
  10. data/app/controllers/refinery/orders/orders_controller.rb +96 -0
  11. data/app/controllers/refinery/products/admin/products_controller.rb +12 -0
  12. data/app/controllers/refinery/products/products_controller.rb +17 -0
  13. data/app/controllers/refinery/stores/admin/stores_controller.rb +12 -0
  14. data/app/controllers/refinery/stores/stores_controller.rb +80 -0
  15. data/app/helpers/refinery/orders/orders_helper.rb +11 -0
  16. data/app/models/refinery/addresses/address.rb +12 -0
  17. data/app/models/refinery/orders/line_item.rb +24 -0
  18. data/app/models/refinery/orders/order.rb +364 -0
  19. data/app/models/refinery/products/product.rb +17 -0
  20. data/app/models/refinery/stores/store.rb +33 -0
  21. data/app/views/refinery/addresses/admin/addresses/_actions.html.erb +25 -0
  22. data/app/views/refinery/addresses/admin/addresses/_address.html.erb +16 -0
  23. data/app/views/refinery/addresses/admin/addresses/_addresses.html.erb +2 -0
  24. data/app/views/refinery/addresses/admin/addresses/_form.html.erb +89 -0
  25. data/app/views/refinery/addresses/admin/addresses/_records.html.erb +18 -0
  26. data/app/views/refinery/addresses/admin/addresses/_sortable_list.html.erb +5 -0
  27. data/app/views/refinery/addresses/admin/addresses/edit.html.erb +1 -0
  28. data/app/views/refinery/addresses/admin/addresses/index.html.erb +7 -0
  29. data/app/views/refinery/addresses/admin/addresses/new.html.erb +1 -0
  30. data/app/views/refinery/orders/admin/orders/_actions.html.erb +25 -0
  31. data/app/views/refinery/orders/admin/orders/_form.html.erb +122 -0
  32. data/app/views/refinery/orders/admin/orders/_order.html.erb +20 -0
  33. data/app/views/refinery/orders/admin/orders/_orders.html.erb +2 -0
  34. data/app/views/refinery/orders/admin/orders/_records.html.erb +18 -0
  35. data/app/views/refinery/orders/admin/orders/_sortable_list.html.erb +5 -0
  36. data/app/views/refinery/orders/admin/orders/edit.html.erb +1 -0
  37. data/app/views/refinery/orders/admin/orders/index.html.erb +7 -0
  38. data/app/views/refinery/orders/admin/orders/new.html.erb +1 -0
  39. data/app/views/refinery/orders/orders/_address_form.html.haml +35 -0
  40. data/app/views/refinery/orders/orders/_card_form.html.haml +63 -0
  41. data/app/views/refinery/orders/orders/_order_snapshot.html.haml +44 -0
  42. data/app/views/refinery/orders/orders/confirmation.html.haml +26 -0
  43. data/app/views/refinery/orders/orders/edit.html.haml +36 -0
  44. data/app/views/refinery/orders/orders/index.html.haml +6 -0
  45. data/app/views/refinery/orders/orders/purchase.html.haml +25 -0
  46. data/app/views/refinery/orders/orders/show.html.haml +36 -0
  47. data/app/views/refinery/products/admin/products/_actions.html.erb +25 -0
  48. data/app/views/refinery/products/admin/products/_form.html.erb +127 -0
  49. data/app/views/refinery/products/admin/products/_product.html.erb +20 -0
  50. data/app/views/refinery/products/admin/products/_products.html.erb +2 -0
  51. data/app/views/refinery/products/admin/products/_records.html.erb +18 -0
  52. data/app/views/refinery/products/admin/products/_sortable_list.html.erb +5 -0
  53. data/app/views/refinery/products/admin/products/edit.html.erb +4 -0
  54. data/app/views/refinery/products/admin/products/index.html.erb +10 -0
  55. data/app/views/refinery/products/admin/products/new.html.erb +4 -0
  56. data/app/views/refinery/products/products/show.html.erb +105 -0
  57. data/app/views/refinery/stores/admin/stores/_actions.html.erb +57 -0
  58. data/app/views/refinery/stores/admin/stores/_form.html.erb +56 -0
  59. data/app/views/refinery/stores/admin/stores/_records.html.erb +18 -0
  60. data/app/views/refinery/stores/admin/stores/_sortable_list.html.erb +5 -0
  61. data/app/views/refinery/stores/admin/stores/_store.html.erb +20 -0
  62. data/app/views/refinery/stores/admin/stores/_stores.html.erb +2 -0
  63. data/app/views/refinery/stores/admin/stores/edit.html.erb +4 -0
  64. data/app/views/refinery/stores/admin/stores/index.html.erb +13 -0
  65. data/app/views/refinery/stores/admin/stores/new.html.erb +4 -0
  66. data/app/views/refinery/stores/stores/_cart.html.erb +22 -0
  67. data/app/views/refinery/stores/stores/_cart_item.html.erb +9 -0
  68. data/app/views/refinery/stores/stores/_list_product.html.erb +16 -0
  69. data/app/views/refinery/stores/stores/index.html.erb +11 -0
  70. data/app/views/refinery/stores/stores/show.html.erb +28 -0
  71. data/config/locales/en.yml +143 -0
  72. data/config/locales/es.yml +143 -0
  73. data/config/locales/fr.yml +139 -0
  74. data/config/locales/nb.yml +143 -0
  75. data/config/locales/nl.yml +143 -0
  76. data/config/routes.rb +81 -0
  77. data/db/migrate/1_create_stores_stores.rb +29 -0
  78. data/db/migrate/2_create_products_products.rb +44 -0
  79. data/db/migrate/3_create_orders_orders.rb +44 -0
  80. data/db/migrate/4_create_orders_line_items.rb +20 -0
  81. data/db/migrate/5_create_addresses_addresses.rb +39 -0
  82. data/db/seeds.rb +23 -0
  83. data/lib/generators/refinery/stores_generator.rb +17 -0
  84. data/lib/refinery/addresses/engine.rb +31 -0
  85. data/lib/refinery/addresses.rb +21 -0
  86. data/lib/refinery/cart.rb +36 -0
  87. data/lib/refinery/cart_item.rb +28 -0
  88. data/lib/refinery/orders/engine.rb +31 -0
  89. data/lib/refinery/orders.rb +21 -0
  90. data/lib/refinery/products/engine.rb +31 -0
  91. data/lib/refinery/products.rb +21 -0
  92. data/lib/refinery/store_gateway.rb +106 -0
  93. data/lib/refinery/stores/engine.rb +31 -0
  94. data/lib/refinery/stores.rb +21 -0
  95. data/lib/refinerycms-stores.rb +7 -0
  96. data/lib/tasks/refinery/stores.rake +13 -0
  97. data/readme.md +10 -0
  98. data/refinerycms-stores.gemspec +261 -0
  99. data/spec/models/refinery/addresses/address_spec.rb +18 -0
  100. data/spec/models/refinery/orders/order_spec.rb +18 -0
  101. data/spec/models/refinery/products/product_spec.rb +18 -0
  102. data/spec/models/refinery/stores/store_spec.rb +18 -0
  103. data/spec/requests/refinery/addresses/admin/addresses_spec.rb +101 -0
  104. data/spec/requests/refinery/orders/admin/orders_spec.rb +101 -0
  105. data/spec/requests/refinery/products/admin/products_spec.rb +101 -0
  106. data/spec/requests/refinery/stores/admin/stores_spec.rb +101 -0
  107. data/spec/spec_helper.rb +53 -0
  108. data/spec/support/factories/refinery/addresses.rb +7 -0
  109. data/spec/support/factories/refinery/orders.rb +7 -0
  110. data/spec/support/factories/refinery/products.rb +7 -0
  111. data/spec/support/factories/refinery/stores.rb +7 -0
  112. data/tasks/rspec.rake +6 -0
  113. data/tasks/testing.rake +8 -0
  114. data/test/helper.rb +17 -0
  115. data/test/test_refinerycms-cart.rb +7 -0
  116. metadata +571 -0
@@ -0,0 +1,80 @@
1
+ module Refinery
2
+ module Stores
3
+ class StoresController < ::ApplicationController
4
+
5
+ before_filter :find_all_stores, :only => :index
6
+ before_filter :find_page, :except => [:index, :add_to_cart, :empty_cart, :checkout]
7
+ before_filter :find_cart, :except => :empty_cart
8
+
9
+ def index
10
+ # you can use meta fields from your model instead (e.g. browser_title)
11
+ # by swapping @page for @store in the line below:
12
+ present(@page)
13
+ end
14
+
15
+ def show
16
+ @store = Store.find(params[:id])
17
+
18
+ # you can use meta fields from your model instead (e.g. browser_title)
19
+ # by swapping @page for @store in the line below:
20
+ present(@page)
21
+ end
22
+
23
+ def add_to_cart
24
+ begin
25
+ product = ::Refinery::Products::Product.find(params[:id])
26
+ rescue ActiveRecord::RecordNotFound
27
+ logger.error("Attempt to access invalid product #{params[:id]}")
28
+ redirect_to_index("Invalid product")
29
+ else
30
+ @current_item = @cart.add_product(product)
31
+ redirect_to_index unless request.xhr?
32
+ end
33
+ end
34
+
35
+ def empty_cart
36
+ session[:cart] = nil
37
+ redirect_to_index
38
+ end
39
+
40
+
41
+ def checkout
42
+ if @cart.items.empty?
43
+ redirect_to_index("Your cart is empty")
44
+ else
45
+ @order = ::Refinery::Orders::Order.checkout!( @cart )
46
+ session[:cart] = nil
47
+ redirect_to refinery.edit_orders_order_path( @order )
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def redirect_to_index(msg = nil)
54
+ flash[:notice] = msg if msg
55
+ redirect_to refinery.stores_store_path( find_first_store )
56
+ end
57
+
58
+
59
+ def find_cart
60
+ @cart = (session[:cart] ||= Cart.new)
61
+ end
62
+
63
+ protected
64
+
65
+ def find_first_store
66
+ @store = Store.order('position ASC').first
67
+ end
68
+
69
+
70
+ def find_all_stores
71
+ @stores = Store.order('position ASC')
72
+ end
73
+
74
+ def find_page
75
+ @page = ::Refinery::Page.where(:link_url => "/stores").first
76
+ end
77
+
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,11 @@
1
+ module Refinery
2
+ module Orders
3
+ module OrdersHelper
4
+
5
+ def pretty_total_price( li )
6
+ number_to_currency( ( li.quantity.to_f * li.unit_price ) )
7
+ end
8
+
9
+ end # module OrdersHelper
10
+ end # module Orders
11
+ end # module Refinery
@@ -0,0 +1,12 @@
1
+ module Refinery
2
+ module Addresses
3
+ class Address < Refinery::Core::BaseModel
4
+ self.table_name = :refinery_addresses
5
+ # acts_as_indexed :fields => [:first_name, :last_name, :phone, :email, :address1, :address2, :city, :state, :zip, :country]
6
+
7
+ validates :first_name, :presence => true
8
+ validates :last_name, :presence => true
9
+
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,24 @@
1
+ module Refinery
2
+ module Orders
3
+ class LineItem < Refinery::Core::BaseModel
4
+ self.table_name = :refinery_line_items
5
+
6
+ belongs_to :order
7
+ belongs_to :product, :class_name => ::Refinery::Products::Product
8
+
9
+ # validates :order_status, :presence => true, :uniqueness => true
10
+
11
+ def self.from_cart_item( item )
12
+ return self.create(
13
+ :product => item.product,
14
+ :quantity => item.quantity,
15
+ :unit_price => item.price
16
+ )
17
+
18
+ end
19
+
20
+ end # class LineItem
21
+
22
+ end # module Orders
23
+
24
+ end # module Refinery
@@ -0,0 +1,364 @@
1
+ module Refinery
2
+ module Orders
3
+ # #########################################################################
4
+ class OrderProcessingException < SecurityError; end
5
+ # #########################################################################
6
+ # #########################################################################
7
+ # #########################################################################
8
+ class Order < Refinery::Core::BaseModel
9
+
10
+ require 'aasm'
11
+
12
+ self.table_name = :refinery_orders
13
+
14
+ has_many :addresses, :class_name => ::Refinery::Addresses::Address
15
+ has_many :line_items
16
+
17
+ # belongs_to :customer
18
+ # belongs_to :shipping_type
19
+ # belongs_to :discount
20
+ # belongs_to :shipping_vendor
21
+
22
+ before_create :generate_order_number
23
+
24
+ has_one :billing_address, :class_name => ::Refinery::Addresses::Address,
25
+ :conditions => { :is_billing => true }
26
+
27
+ has_one :shipping_address, :class_name => ::Refinery::Addresses::Address,
28
+ :conditions => { :is_billing => false }
29
+
30
+ # #########################################################################
31
+ # attr_protected :order_number
32
+ attr_accessible :order_notes, :shipping_type
33
+ # #########################################################################
34
+
35
+ # t.integer :order_number, :null => false, :unique => true
36
+ # t.references :order_customer
37
+ # t.string :order_status, :default => '', :null => false
38
+ # t.text :order_notes
39
+ # t.references :shipping_type
40
+ # t.datetime :shipped_on
41
+ # t.float :product_cost, :default => 0.0, :limit => 10
42
+ # t.float :shipping_cost, :default => 0.0, :limit => 10
43
+ # t.float :tax_cost, :default => 0.0, :limit => 5
44
+
45
+ # #########################################################################
46
+ # AASM STATE MACHINE AREA ... try to keep generic!
47
+ # #########################################################################
48
+
49
+ include AASM
50
+
51
+ # #########################################################################
52
+ # STATE MACHINE STATES
53
+ # #########################################################################
54
+ aasm_column :order_status # expects this field for persistance of state
55
+
56
+ # default starting state for order objects
57
+ aasm_initial_state :checkout_started
58
+
59
+ # initial state: cart becomes an "empty" order (nothing else filled in)
60
+ aasm_state :checkout_started
61
+
62
+ # 1 order processing states
63
+ aasm_state :edit_stage_completed, :enter => :edit_done
64
+
65
+ # 2 automatic states for purchased
66
+ aasm_state :purchase_confirmed, :enter => :order_confirmed
67
+ aasm_state :order_completed, :enter => :order_completed
68
+
69
+ # 2 defunct or cancelled states
70
+ aasm_state :refunded_defunct, :enter => :refund2defunct
71
+
72
+ # #########################################################################
73
+ # STATE MACHINE EVENT HANDLING
74
+ # #########################################################################
75
+ #
76
+ # Further note:
77
+ # if all digital download, skip delivery method
78
+ # if all digital download && gateway_handles_billing, skip address
79
+ # if gateway_does_everything, skip payment selection
80
+ #
81
+ # ---------------------------------------------------------------------------
82
+ # next_in_process -- advances order thru order wizard stages
83
+ # ---------------------------------------------------------------------------
84
+ aasm_event :next_in_process do
85
+ transitions :to => :edit_stage_completed, :from => :checkout_started
86
+ end
87
+
88
+ # ---------------------------------------------------------------------------
89
+ # confirm_purchase -- user definitely confirms purchase intent
90
+ # ---------------------------------------------------------------------------
91
+ aasm_event :confirm_purchase do
92
+ transitions :to => :purchase_confirmed, :from => :edit_stage_completed
93
+ end
94
+
95
+ # ---------------------------------------------------------------------------
96
+ # payment_verfified -- payment gateway verifies funds transfer
97
+ # ---------------------------------------------------------------------------
98
+ aasm_event :payment_verified do
99
+ transitions :to => :order_completed, :from => :purchase_confirmed
100
+ end
101
+
102
+ # ---------------------------------------------------------------------------
103
+ # purchase_failed -- payment gateway failed
104
+ # backs state to select a payment method
105
+ # ---------------------------------------------------------------------------
106
+ aasm_event( :purchase_failed, :success => :void_payment ) do
107
+ transitions :to => :delivery_stage_completed, :from => :purchase_confirmed
108
+ end
109
+
110
+ # ---------------------------------------------------------------------------
111
+ # refund_order -- order fully refunded making it defunct
112
+ # ---------------------------------------------------------------------------
113
+ aasm_event :refund_order do
114
+ transitions :to => :refunded_defunct, :from => :order_completed
115
+ end
116
+
117
+
118
+ # ---------------------------------------------------------------------------
119
+ # restart_checkout -- return to the edit stage
120
+ # ---------------------------------------------------------------------------
121
+ aasm_event :restart_checkout do
122
+ transitions :to => :checkout_started,
123
+ :from => [:checkout_started, :edit_stage_completed,
124
+ :purchase_confirmed ]
125
+ end
126
+
127
+ # ---------------------------------------------------------------------------
128
+ # cancel_process -- cancel the order wizard process, void any payt tokens
129
+ # ---------------------------------------------------------------------------
130
+ aasm_event( :cancel_process, :success => :void_payment ) do
131
+ transitions :to => :checkout_started,
132
+ :from => [:checkout_started, :edit_stage_completed ]
133
+ end
134
+
135
+ # #########################################################################
136
+ # #########################################################################
137
+ # END OF AASM AREA
138
+ # #########################################################################
139
+ # #########################################################################
140
+
141
+ # ---------------------------------------------------------------------------
142
+ # get_render_template -- returns template name for next edit render
143
+ # returns nil if an invalid state
144
+ # ---------------------------------------------------------------------------
145
+ def get_render_template
146
+ action = {
147
+ :checkout_started => :edit,
148
+ :edit_stage_completed => :confirmation
149
+ }[ self.order_status.to_sym ]
150
+
151
+ end
152
+
153
+ # ---------------------------------------------------------------------------
154
+ # handle_update -- handle user params for updating order
155
+ # returns bill_address, ship_address objects (or nil for both)
156
+ # which might have errors
157
+ # ---------------------------------------------------------------------------
158
+ def handle_update( params )
159
+ if checkout_started?
160
+ bill_address, ship_address = update_addresses( params )
161
+ next_in_process! if bill_address.errors.empty? && ship_address.errors.empty?
162
+ end
163
+
164
+ self.cc_token = params[:stripeToken]
165
+ self.cc_last4 = params[:last4]
166
+ self.cc_card_type = params[:card_type]
167
+ self.cc_expiry_month = params[:expiry_month]
168
+ self.cc_expiry_year = params[:expiry_year]
169
+ self.save!
170
+
171
+
172
+ return bill_address, ship_address
173
+ end
174
+
175
+ # ---------------------------------------------------------------------------
176
+ # checkout! -- checkout converts the cart into a fledgling order
177
+ # ---------------------------------------------------------------------------
178
+ def self.checkout!( cart )
179
+ order = Order.new
180
+
181
+ # convert cart.items to order.line_items
182
+ cart.items.each do | item |
183
+ order.line_items.build(
184
+ :product => item.product,
185
+ :quantity => item.quantity,
186
+ :unit_price => item.price
187
+ )
188
+ end # do
189
+
190
+ order.save!
191
+
192
+ return order
193
+ end
194
+
195
+ # TODO: convert customer's billing/shipping addresses to order addresses
196
+
197
+ # ---------------------------------------------------------------------------
198
+ # ---------------------------------------------------------------------------
199
+ def get_billship_addresses()
200
+ bill_address = self.billing_address || ::Refinery::Addresses::Address.new( :is_billing => true )
201
+
202
+ # ship needs to be populated from bill if no ship already present
203
+ ship_address = self.shipping_address ||
204
+ ::Refinery::Addresses::Address.new(
205
+ :first_name => bill_address.first_name ,
206
+ :last_name => bill_address.last_name ,
207
+ :phone => bill_address.phone ,
208
+ :email => bill_address.email ,
209
+ :address1 => bill_address.address1 ,
210
+ :address2 => bill_address.address2 ,
211
+ :city => bill_address.city ,
212
+ :state => bill_address.state ,
213
+ :zip => bill_address.zip ,
214
+ :country => bill_address.country ,
215
+ :is_billing => false
216
+ )
217
+
218
+ return bill_address, ship_address
219
+ end
220
+
221
+
222
+ # ---------------------------------------------------------------------------
223
+ # update_addresses -- complex logic for dealing with 2 order addresses
224
+ # return bill_address, ship_address objects
225
+ # ---------------------------------------------------------------------------
226
+ def update_addresses( params )
227
+ # if bill exists; update with parameters
228
+ # else create bill
229
+ if (bill_address = self.billing_address)
230
+ bill_address.update_attributes( params[:billing_address] )
231
+ else
232
+ bill_address = self.addresses.create(
233
+ params[:billing_address].merge( { :is_billing => true } )
234
+ )
235
+ end # if..then..else billing address setup
236
+
237
+ # continue if error free
238
+ if bill_address.errors.empty?
239
+
240
+ # does customer wants same address for both ?
241
+ ship_params = ( params[:use_billing] ?
242
+ params[:billing_address] :
243
+ params[:shipping_address]
244
+ ).merge( { :is_billing => false } )
245
+
246
+ if (ship_address = self.shipping_address)
247
+ ship_address.update_attributes( ship_params )
248
+ else
249
+ ship_address = self.addresses.create( ship_params )
250
+ end # if..then..else shiping address setup
251
+
252
+ else # need placeholder for re-editing the order
253
+ ship_address = self.addresses.build( params[:shipping_address] )
254
+ end # if no bill address errors
255
+
256
+ return bill_address, ship_address
257
+ end
258
+
259
+ # ---------------------------------------------------------------------------
260
+ # ---------------------------------------------------------------------------
261
+
262
+ def total_items
263
+ line_items.sum { |item| item.quantity }
264
+ end
265
+
266
+
267
+ def total_price
268
+ line_items.sum { |item| item.unit_price * item.quantity }
269
+ end
270
+
271
+
272
+ # ---------------------------------------------------------------------------
273
+ # process_purchase -- charges CC for the purchase
274
+ # returns nil if error (self.errors captures), or result JSON obj
275
+ # ---------------------------------------------------------------------------
276
+ def process_purchase( store_gateway )
277
+ raise OrderProcessingException unless self.purchase_confirmed?
278
+
279
+ result = store_gateway.charge_purchase(
280
+ self.cc_token,
281
+ self.product_total + self.shipping_charges + self.tax_charges,
282
+ self,
283
+ self.billing_address.email
284
+ )
285
+
286
+ unless result.nil? # unless there were errors ...
287
+ self.cc_purchased_on = Time.now # date of purchase
288
+ self.cc_confirmation_id = result.id # confirmation code
289
+ # next step saves above changes IFF paid is true
290
+ self.payment_verified! if result.paid # state becomes paid & final
291
+ end # unless there were errors
292
+
293
+ return result
294
+
295
+ end
296
+
297
+ # ---------------------------------------------------------------------------
298
+ # ---------------------------------------------------------------------------
299
+
300
+ private
301
+
302
+ # ---------------------------------------------------------------------------
303
+ # edit_done -- things to do after edit input & verified
304
+ # ---------------------------------------------------------------------------
305
+ def edit_done()
306
+
307
+ end
308
+
309
+ # ---------------------------------------------------------------------------
310
+ # order_confirmed -- things to do after user confirmed purchase decision
311
+ # ---------------------------------------------------------------------------
312
+ def order_confirmed()
313
+ self.product_total = total_price
314
+ # shipping_charges
315
+ # tax_charges
316
+ save!
317
+ end
318
+
319
+ # ---------------------------------------------------------------------------
320
+ # order_completed -- things to do after purchase verified by gateway
321
+ # ---------------------------------------------------------------------------
322
+ def order_completed()
323
+ # create a confirmation code
324
+ # kick off shipping process
325
+ end
326
+
327
+ # ---------------------------------------------------------------------------
328
+ # refund2defunct -- things to do after refunding an order making it defunct
329
+ # ---------------------------------------------------------------------------
330
+ def refund2defunct()
331
+ end
332
+
333
+ # ---------------------------------------------------------------------------
334
+ # ---------------------------------------------------------------------------
335
+ def void_payment
336
+
337
+ end
338
+
339
+ # ---------------------------------------------------------------------------
340
+ # ---------------------------------------------------------------------------
341
+ def generate_order_number
342
+ nbr = 0
343
+ max = 0xfffffffe
344
+ tries = max # deadman counter to prevent infinite loop
345
+
346
+ while ( tries > 0 && Order.find_by_order_number(nbr = rand( max ) + 1) ) do
347
+ tries = tries - 1 # decrement deadman counter
348
+ end # while
349
+ raise ArgumentError, "maxed out store order numbers?!" if tries.zero?
350
+
351
+ self.order_number = nbr
352
+ end
353
+
354
+ # ---------------------------------------------------------------------------
355
+ # ---------------------------------------------------------------------------
356
+
357
+ # ---------------------------------------------------------------------------
358
+ # ---------------------------------------------------------------------------
359
+
360
+ # #########################################################################
361
+ end # class Order
362
+ # #########################################################################
363
+ end # module Orders
364
+ end # module Refinery
@@ -0,0 +1,17 @@
1
+ module Refinery
2
+ module Products
3
+ class Product < Refinery::Core::BaseModel
4
+ self.table_name = :refinery_products
5
+ acts_as_indexed :fields => [:name, :code, :description]
6
+
7
+ validates :name, :presence => true, :uniqueness => true
8
+
9
+ belongs_to :main_pic, :class_name => '::Refinery::Image'
10
+ belongs_to :store, :class_name => '::Refinery::Stores::Store'
11
+ has_many :line_items, :class_name => '::Refinery::Orders::LineItem'
12
+
13
+ scope :active, lambda { |i| where(["date_available <= ? ", Time.now ]) }
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,33 @@
1
+ module Refinery
2
+ module Stores
3
+ class Store < Refinery::Core::BaseModel
4
+ self.table_name = :refinery_stores
5
+
6
+ acts_as_indexed :fields => [:name, :meta_keywords, :description]
7
+
8
+ validates :name, :presence => true, :uniqueness => true
9
+
10
+ has_many :products
11
+ # we may want to expand the concept of active in the future
12
+ has_many :active_products, :class_name => '::Refinery::Products::Product', :foreign_key => 'store_id'
13
+
14
+ # -----------------------------------------------------------------------
15
+ # select_list -- returns an html select list suitable for selecting a store
16
+ # -----------------------------------------------------------------------
17
+ def self.select_list()
18
+ all.map{ |x| [x.name, x.id] }
19
+ end
20
+
21
+ # -----------------------------------------------------------------------
22
+ # -----------------------------------------------------------------------
23
+
24
+ # -----------------------------------------------------------------------
25
+ # -----------------------------------------------------------------------
26
+
27
+ # -----------------------------------------------------------------------
28
+ # -----------------------------------------------------------------------
29
+
30
+ end # class Store
31
+
32
+ end # module Stores
33
+ end # module Refineryd
@@ -0,0 +1,25 @@
1
+ <ul>
2
+ <% if ::Refinery::Addresses::Admin::AddressesController.searchable? %>
3
+ <li>
4
+ <%= render '/refinery/admin/search', :url => refinery.addresses_admin_addresses_path %>
5
+ </li>
6
+ <% end %>
7
+ <li>
8
+ <%= link_to t('.create_new'), refinery.new_addresses_admin_address_path,
9
+ :class => "add_icon" %>
10
+ </li>
11
+ <% if !searching? && ::Refinery::Addresses::Admin::AddressesController.sortable? && ::Refinery::Addresses::Address.any? %>
12
+ <li>
13
+ <%= link_to t('.reorder', :what => "Addresses"),
14
+ refinery.addresses_admin_addresses_path,
15
+ :id => "reorder_action",
16
+ :class => "reorder_icon" %>
17
+
18
+ <%= link_to t('.reorder_done', :what => "Addresses"),
19
+ refinery.addresses_admin_addresses_path,
20
+ :id => "reorder_action_done",
21
+ :style => "display: none;",
22
+ :class => "reorder_icon" %>
23
+ </li>
24
+ <% end %>
25
+ </ul>
@@ -0,0 +1,16 @@
1
+ <li class='clearfix record <%= cycle("on", "on-hover") %>' id="<%= dom_id(address) -%>">
2
+ <span class='title'>
3
+ <%= address.first_name %>
4
+
5
+ </span>
6
+ <span class='actions'>
7
+
8
+ <%= link_to refinery_icon_tag("application_edit.png"), refinery.edit_addresses_admin_address_path(address),
9
+ :title => t('.edit') %>
10
+ <%= link_to refinery_icon_tag("delete.png"), refinery.addresses_admin_address_path(address),
11
+ :class => "cancel confirm-delete",
12
+ :title => t('.delete'),
13
+ :confirm => t('message', :scope => 'refinery.admin.delete', :title => address.first_name),
14
+ :method => :delete %>
15
+ </span>
16
+ </li>
@@ -0,0 +1,2 @@
1
+ <%= will_paginate @addresses if Refinery::Addresses::Admin::AddressesController.pageable? %>
2
+ <%= render 'sortable_list' %>
@@ -0,0 +1,89 @@
1
+ <%= form_for [refinery, :addresses_admin, @address] do |f| -%>
2
+ <%= render '/refinery/admin/error_messages',
3
+ :object => @address,
4
+ :include_object_name => true %>
5
+
6
+
7
+ <div class='field'>
8
+ <%= f.label :customer -%>
9
+ <%= f.text_field :customer, :class => 'larger widest' -%>
10
+
11
+ </div>
12
+
13
+ <div class='field'>
14
+ <%= f.label :order -%>
15
+ <%= f.text_field :order -%>
16
+
17
+ </div>
18
+
19
+ <div class='field'>
20
+ <%= f.label :is_billing -%>
21
+ <%= f.check_box :is_billing, :checked => @address[:is_billing] -%>
22
+
23
+ </div>
24
+
25
+ <div class='field'>
26
+ <%= f.label :first_name -%>
27
+ <%= f.text_field :first_name -%>
28
+
29
+ </div>
30
+
31
+ <div class='field'>
32
+ <%= f.label :last_name -%>
33
+ <%= f.text_field :last_name -%>
34
+
35
+ </div>
36
+
37
+ <div class='field'>
38
+ <%= f.label :phone -%>
39
+ <%= f.text_field :phone -%>
40
+
41
+ </div>
42
+
43
+ <div class='field'>
44
+ <%= f.label :email -%>
45
+ <%= f.text_field :email -%>
46
+
47
+ </div>
48
+
49
+ <div class='field'>
50
+ <%= f.label :address1 -%>
51
+ <%= f.text_field :address1 -%>
52
+
53
+ </div>
54
+
55
+ <div class='field'>
56
+ <%= f.label :address2 -%>
57
+ <%= f.text_field :address2 -%>
58
+
59
+ </div>
60
+
61
+ <div class='field'>
62
+ <%= f.label :city -%>
63
+ <%= f.text_field :city -%>
64
+
65
+ </div>
66
+
67
+ <div class='field'>
68
+ <%= f.label :state -%>
69
+ <%= f.text_field :state -%>
70
+
71
+ </div>
72
+
73
+ <div class='field'>
74
+ <%= f.label :zip -%>
75
+ <%= f.text_field :zip -%>
76
+
77
+ </div>
78
+
79
+ <div class='field'>
80
+ <%= f.label :country -%>
81
+ <%= f.text_field :country -%>
82
+
83
+ </div>
84
+
85
+ <%= render '/refinery/admin/form_actions', :f => f,
86
+ :continue_editing => false,
87
+ :delete_title => t('delete', :scope => 'refinery.addresses.admin.addresses.address'),
88
+ :delete_confirmation => t('message', :scope => 'refinery.admin.delete', :title => @address.first_name) %>
89
+ <% end -%>