forgeos_commerce_front 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/COPYING +339 -0
  2. data/COPYING.LESSER +165 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE +2 -0
  5. data/README.textile +28 -0
  6. data/app/assets/images/commerce_front/cart/calulate.png +0 -0
  7. data/app/assets/images/commerce_front/cart/cart.png +0 -0
  8. data/app/assets/images/commerce_front/cart/change_quantity.png +0 -0
  9. data/app/assets/images/commerce_front/cart/delete.png +0 -0
  10. data/app/assets/images/commerce_front/cart/reduction.png +0 -0
  11. data/app/assets/images/commerce_front/cart/steps_left.png +0 -0
  12. data/app/assets/images/commerce_front/cart/steps_right.png +0 -0
  13. data/app/assets/images/commerce_front/product.jpg +0 -0
  14. data/app/assets/javascripts/commerce_front/functions.js +10 -0
  15. data/app/assets/javascripts/commerce_front/init.js +4 -0
  16. data/app/assets/javascripts/commerce_front/jquery.jnotify.min.js +21 -0
  17. data/app/assets/stylesheets/commerce_front/_cart.css.sass +97 -0
  18. data/app/assets/stylesheets/commerce_front/_common.css.sass +13 -0
  19. data/app/assets/stylesheets/commerce_front/_forms.css.sass +15 -0
  20. data/app/assets/stylesheets/commerce_front/_jnotify.css.sass +65 -0
  21. data/app/assets/stylesheets/commerce_front/style.css.sass +4 -0
  22. data/app/controllers/addresses_controller.rb +71 -0
  23. data/app/controllers/application_controller.rb +21 -0
  24. data/app/controllers/cart_controller.rb +144 -0
  25. data/app/controllers/newsletters_controller.rb +20 -0
  26. data/app/controllers/order_controller.rb +413 -0
  27. data/app/controllers/orders_controller.rb +32 -0
  28. data/app/controllers/person_sessions_controller.rb +23 -0
  29. data/app/controllers/users_controller.rb +164 -0
  30. data/app/helpers/application_helper.rb +73 -0
  31. data/app/helpers/cart_helper.rb +25 -0
  32. data/app/helpers/order_helper.rb +59 -0
  33. data/app/models/address.rb +18 -0
  34. data/app/models/notifier.rb +88 -0
  35. data/app/models/order.rb +13 -0
  36. data/app/models/user.rb +16 -0
  37. data/app/models/user_address.rb +15 -0
  38. data/app/views/addresses/_address_form.html.haml +18 -0
  39. data/app/views/addresses/_multiple_address_form.html.haml +27 -0
  40. data/app/views/cart/_free_products.html.haml +3 -0
  41. data/app/views/cart/_tbody.html.haml +25 -0
  42. data/app/views/cart/_total.html.haml +46 -0
  43. data/app/views/cart/index.html.haml +32 -0
  44. data/app/views/notifier/newsletter.html.haml +2 -0
  45. data/app/views/notifier/reset_password.html.haml +9 -0
  46. data/app/views/notifier/validation_user_account.html.haml +9 -0
  47. data/app/views/notifier/waiting_for_cheque_notification.html.haml +2 -0
  48. data/app/views/order/_form_address.html.haml +44 -0
  49. data/app/views/order/_tbody.html.haml +21 -0
  50. data/app/views/order/_total.html.haml +50 -0
  51. data/app/views/order/cheque_payment.html.haml +1 -0
  52. data/app/views/order/create.html.haml +76 -0
  53. data/app/views/order/deliveries.html.haml +28 -0
  54. data/app/views/order/new.html.haml +26 -0
  55. data/app/views/order/so_colissimo.html.haml +8 -0
  56. data/app/views/orders/index.html.haml +34 -0
  57. data/app/views/person_sessions/_form.html.haml +23 -0
  58. data/app/views/person_sessions/new.html.haml +1 -0
  59. data/app/views/person_sessions/new_reset_password.html.haml +7 -0
  60. data/app/views/users/_edit_form.html.haml +61 -0
  61. data/app/views/users/_form_create.html.haml +27 -0
  62. data/app/views/users/_form_quick_create.html.haml +16 -0
  63. data/app/views/users/_login_or_new.html.haml +10 -0
  64. data/app/views/users/forgotten_password.html.haml +12 -0
  65. data/app/views/users/new.html.haml +1 -0
  66. data/app/views/users/new_password.html.haml +10 -0
  67. data/app/views/users/show.html.haml +1 -0
  68. data/config/commerce.example.yml +27 -0
  69. data/config/initializers/commerce_front.rb +6 -0
  70. data/config/locales/fr.yml +85 -0
  71. data/config/routes.rb +17 -0
  72. data/db/migrate/20110311134232_add_form_attributes_to_addresses.rb +9 -0
  73. data/lib/field_error_proc_changer.rb +19 -0
  74. data/lib/forgeos/commerce_front.rb +6 -0
  75. data/lib/forgeos/commerce_front/engine.rb +10 -0
  76. data/lib/forgeos/commerce_front/version.rb +5 -0
  77. data/lib/forgeos_commerce_front.rb +1 -0
  78. data/lib/tasks/install.rake +13 -0
  79. data/recipes/deploy.rb +6 -0
  80. data/test/dummy/Rakefile +7 -0
  81. data/test/dummy/app/assets/javascripts/application.js +9 -0
  82. data/test/dummy/app/assets/stylesheets/application.css +7 -0
  83. data/test/dummy/app/controllers/application_controller.rb +3 -0
  84. data/test/dummy/app/helpers/application_helper.rb +2 -0
  85. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  86. data/test/dummy/config.ru +4 -0
  87. data/test/dummy/config/application.rb +42 -0
  88. data/test/dummy/config/boot.rb +10 -0
  89. data/test/dummy/config/database.yml +25 -0
  90. data/test/dummy/config/environment.rb +5 -0
  91. data/test/dummy/config/environments/development.rb +27 -0
  92. data/test/dummy/config/environments/production.rb +51 -0
  93. data/test/dummy/config/environments/test.rb +39 -0
  94. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  95. data/test/dummy/config/initializers/inflections.rb +10 -0
  96. data/test/dummy/config/initializers/mime_types.rb +5 -0
  97. data/test/dummy/config/initializers/secret_token.rb +7 -0
  98. data/test/dummy/config/initializers/session_store.rb +8 -0
  99. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  100. data/test/dummy/config/locales/en.yml +5 -0
  101. data/test/dummy/config/routes.rb +58 -0
  102. data/test/dummy/log/development.log +0 -0
  103. data/test/dummy/public/404.html +26 -0
  104. data/test/dummy/public/422.html +26 -0
  105. data/test/dummy/public/500.html +26 -0
  106. data/test/dummy/public/favicon.ico +0 -0
  107. data/test/dummy/script/rails +6 -0
  108. data/test/forgeos_commerce_front_test.rb +7 -0
  109. data/test/test_helper.rb +10 -0
  110. metadata +197 -0
@@ -0,0 +1,20 @@
1
+ class NewslettersController < ApplicationController
2
+ skip_before_filter :verify_authenticity_token
3
+
4
+ def create
5
+ newsletter = Newsletter.new(params[:newsletter])
6
+ newsletter.email = newsletter.email.to_s.strip
7
+ if newsletter.save
8
+ flash[:notice] = t(:success, :scope => [:newsletter, :create])
9
+ @page = Page.find_by_single_key('inscription_reussie')
10
+ else
11
+ if error = newsletter.errors.on(:email)
12
+ flash[:error] = t(:invalid_email, :scope => [:newsletter, :create], :error => error.last)
13
+ else
14
+ flash[:error] = newsletter.errors.full_messages.first
15
+ end
16
+ end
17
+ return redirect_to :back
18
+ end
19
+
20
+ end
@@ -0,0 +1,413 @@
1
+ require 'sha1'
2
+ require 'CMCIC_Config'
3
+ require 'CMCIC_Tpe'
4
+ require 'cgi'
5
+ require 'ruleby'
6
+ class OrderController < ApplicationController
7
+ before_filter :must_be_logged, :only => [:new, :deliveries]
8
+ before_filter :validate_and_update_address, :only => [:new]
9
+ skip_before_filter :verify_authenticity_token, :only => [:call_autoresponse_cyberplus, :paypal_notification, :success, :cancel, :call_autoresponse_cmc_cic, :call_autoresponse_elysnet, :create, :debug_colissimo]
10
+ include Ruleby
11
+
12
+ def new
13
+ setting = Setting.first
14
+ colissimo = setting.colissimo_method_list
15
+ special_offer
16
+ voucher
17
+ @order = Order.from_cart(current_cart)
18
+
19
+ if @order.valid_for_payment?
20
+ if colissimo[:active] == 1 && current_cart.address_delivery.country.name == 'FRANCE'
21
+ return redirect_to :action => 'so_colissimo'
22
+ else
23
+ options = current_cart.options || {}
24
+ options[:colissimo] = nil
25
+ current_cart.save
26
+ render :action => 'new'
27
+ end
28
+ end
29
+ end
30
+
31
+ def so_colissimo
32
+ special_offer
33
+ voucher
34
+
35
+ setting = Setting.first
36
+ colissimo = setting.colissimo_method_list
37
+
38
+ if colissimo && colissimo[:active] == 1
39
+ if @order = Order.from_cart(current_cart)
40
+ @_url = "#{colissimo[:url_prod]}?trReturnUrlKo=#{colissimo[:urlko]}"
41
+ order_infos = @order.to_colissimo_params
42
+ @colissimo = order_infos
43
+ else
44
+ render(:action => 'new')
45
+ end
46
+ end
47
+ end
48
+
49
+ def update_order_with_colissimo
50
+ setting = Setting.first
51
+ colissimo = setting.colissimo_method_list
52
+ #pudoFOId + ceName + dyPreparationTime + dyForwardingCharges + trClientNumber+ trOrderNumber+ orderId+cléSHA
53
+ s_chaine_mac = [params[:PUDOFOID], params[:CENAME], params[:DYPREPARATIONTIME], params[:DYFORWARDINGCHARGES], params[:TRCLIENTNUMBER], params[:TRORDERNUMBER], params[:ORDERID], colissimo[:sha] ].join('')
54
+
55
+ if Digest::SHA1.hexdigest(s_chaine_mac) == params[:SIGNATURE]
56
+ if @order && @order.reference.to_i == params[:ORDERID].split('m').last.to_i
57
+ options = current_cart.options || {}
58
+ options[:colissimo] = params
59
+ current_cart.save
60
+ @order.update_attributes_from_colissimo(params)
61
+ if @order.valid_for_payment?
62
+ return render :action => 'new'
63
+ else
64
+ return render :action => 'deliveries'
65
+ end
66
+ else
67
+ @params = { :order => @order, :order_ref => @order.reference }
68
+ flash[:error] = "La commande n° #{params[:ORDERID].split('m').last.to_i} est introuvable, identifiant de votre panier est #{@order.reference}"
69
+ return render :action => 'deliveries'
70
+ end
71
+ else
72
+ flash[:error] = 'Une erreur est survenue lors la vérification des données'
73
+ @params = { :order => @order, :order_ref => @order.reference }
74
+ render :action => 'deliveries'
75
+ end
76
+ end
77
+
78
+ def create
79
+ special_offer
80
+ voucher
81
+ setting = Setting.first
82
+ colissimo = setting.colissimo_method_list
83
+
84
+ @order = Order.from_cart(current_cart)
85
+ #If so colissimo enabled && params[SIGNATURE]
86
+ if colissimo && colissimo[:active] == 1 && !params[:SIGNATURE].nil?
87
+ update_order_with_colissimo
88
+ return true
89
+ end
90
+
91
+ payment_type = params[:payment_type]
92
+ unless payment_type.present?
93
+ flash[:error] = "Vous devez choisir un moyen de paiement"
94
+ return render :action => 'new'
95
+ else
96
+ payment_type = payment_type.to_sym
97
+ end
98
+
99
+ if payment_type == :cyberplus_multi
100
+ payment_type = :cyberplus
101
+ @order.payment_plans = true
102
+ else
103
+ @order.payment_plans = false
104
+ end
105
+
106
+ unless setting.payment_method_available?(payment_type)
107
+ flash[:error] = "Ce moyen de paiement n'est pas disponible"
108
+ return render :action => 'new'
109
+ end
110
+
111
+ settings = setting.payment_method_settings_with_env(payment_type)
112
+
113
+ if params[:validchk]
114
+ @order.payment_type = t(payment_type, :scope => 'payment', :count => 1)
115
+ if @order.valid_for_payment?
116
+ @order.save
117
+ case @order.payment_type
118
+ when t("cmc_cic", :scope => 'payment', :count => 1)
119
+ @payment = @order.cmc_cic_encrypted
120
+ when t("cyberplus", :scope => 'payment', :count => 1)
121
+ @payment = @order.cyberplus_encrypted
122
+ when t("cheque", :scope => 'payment', :count => 1)
123
+ @order.wait_for_cheque!
124
+ Cart.destroy(@order.reference)
125
+ render :action => 'cheque_payment'
126
+ when t("paypal", :scope => 'payment', :count => 1)
127
+ @url_paypal = settings[:url]
128
+ when t("elysnet", :scope => 'payment', :count => 1)
129
+ @payment = @order.elysnet_encrypted
130
+ end
131
+ end
132
+ else
133
+ #TODO use translations
134
+ flash[:error] = "Vous devez accepter les conditions générales de vente"
135
+ render :action => 'new'
136
+ end
137
+ end
138
+
139
+
140
+ def cheque_payment
141
+ end
142
+
143
+ def call_autoresponse_cmc_cic
144
+ setting = Setting.first
145
+ if setting.payment_method_available?(:cmc_cic)
146
+ oTpe = CMCIC_Tpe.new()
147
+ oHmac = CMCIC_Hmac.new(oTpe)
148
+
149
+ sChaineMAC = [oTpe.sNumero, params["date"], params['montant'], params['reference'], params['texte-libre'], oTpe.sVersion, params['code-retour'], params['cvx'], params['vld'], params['brand'], params['status3ds'], params['numauto'], params['motifrefus'], params['originecb'], params['bincb'], params['hpancb'], params['ipclient'], params['originetr'], params['veres'], params['pares']].join('*') + "*";
150
+
151
+
152
+ if oHmac.isValidHmac?(sChaineMAC, params['MAC'])
153
+ case params['code-retour']
154
+ when "payetest":
155
+ # Payment has been accepted on the test server
156
+ # put your code here (email sending / Database update)
157
+ @order = Order.find_by_reference(params[:reference].split('A').last)
158
+ if @order
159
+ @order.pay!
160
+ Cart.destroy(@order.reference)
161
+ else
162
+ status = :bad_request
163
+ end
164
+ when "paiement":
165
+ # Payment has been accepted on the productive server
166
+ # put your code here (email sending / Database update)
167
+ @order = Order.find_by_reference(params[:reference].split('A').last)
168
+ if @order
169
+ @order.pay!
170
+ Cart.destroy(@order.reference)
171
+ else
172
+ status = :bad_request
173
+ end
174
+ else
175
+ status = :bad_request
176
+ end
177
+ sResult = "0"
178
+ else
179
+ # your code if the HMAC doesn't match
180
+ sResult = "1\n" + sChaineMAC
181
+ end
182
+
183
+ #-----------------------------------------------------------------------------
184
+ # Send receipt to CMCIC server
185
+ #-----------------------------------------------------------------------------
186
+ render :text => "Pragma: no-cache\nContent-type: text/plain\n\nversion=2\ncdr=" + sResult
187
+ else
188
+ render :text => false, :status => 500
189
+ end
190
+ end
191
+
192
+ def call_autoresponse_cyberplus
193
+ setting = Setting.first
194
+ if setting.payment_method_available?(:cyberplus)
195
+ if @order = Order.find_by_id(params[:order_id])
196
+ Cart.destroy(@order.reference)
197
+ @order.update_attribute(:transaction_number,params[:trans_id])
198
+ if params[:result] == '00'
199
+ @order.pay!
200
+ elsif params[:result] == '17'
201
+ @order.cancel!
202
+ end
203
+ render :text => true
204
+ else
205
+ render :text => false, :status => 500
206
+ end
207
+ else
208
+ render :text => false, :status => 500
209
+ end
210
+ end
211
+
212
+ def cancel
213
+ flash[:error] = 'Le paiement a été annulé'
214
+ redirect_to '/commande-anulee'
215
+ end
216
+
217
+ def success
218
+ flash[:success] = 'Le paiement a été validé'
219
+ redirect_to '/commande-validee'
220
+ end
221
+
222
+ def deliveries
223
+ params[:order] ||= {}
224
+ params[:order][:address_invoice_attributes] ||= current_user.address_invoice.attributes.merge(:id => nil) if current_user.address_invoice
225
+ params[:order][:address_delivery_attributes] ||= current_user.address_delivery.attributes.merge(:id => nil) if current_user.address_delivery
226
+ params[:order][:address_invoice_attributes] ||= current_cart.address_invoice.attributes if current_cart.address_invoice
227
+ params[:order][:address_delivery_attributes] ||= current_cart.address_delivery.attributes if current_cart.address_delivery
228
+ @order = Order.new(params[:order])
229
+ end
230
+
231
+ def paypal_notification
232
+ @order = Order.find_by_id(params[:invoice])
233
+ unless @order.nil?
234
+ setting = Setting.first
235
+ if setting.payment_method_available?(:paypal)
236
+ secret = setting.payment_method_settings_with_env(:paypal)[:secret]
237
+ email = setting.payment_method_settings_with_env(:paypal)[:email]
238
+ if params[:payment_status] == "Completed" && params[:secret] == secret && params[:receiver_email] == email && params[:mc_gross].to_f.to_s == @order.total.to_f.to_s
239
+ if cart = Cart.find_by_id(@order.reference)
240
+ cart.destroy
241
+ end
242
+ @order.pay!
243
+ end
244
+ end
245
+ end
246
+ render :nothing => true
247
+ end
248
+
249
+ def call_autoresponse_elysnet
250
+ message = params['DATA']
251
+ @result = `./lib/elysnet/bin/response pathfile=./lib/elysnet/param/pathfile message=#{message}` #execution of response script
252
+
253
+ @response = @result.split("!")
254
+
255
+ @code = @response[1]
256
+ @error = @response[2]
257
+ @merchant_id = @response[3]
258
+ @merchant_country = @response[4]
259
+ @amount = @response[5]
260
+ @transaction_id = @response[6]
261
+ @payment_means = @response[7]
262
+ @transmission_date = @response[8]
263
+ @payment_time = @response[9]
264
+ @payment_date = @response[10]
265
+ @response_code = @response[11]
266
+ @payment_certificate = @response[12]
267
+ @authorisation_id = @response[13]
268
+ @currency_code = @response[14]
269
+ @card_number = @response[15]
270
+ @cvv_flag = @response[16]
271
+ @cvv_response_code = @response[17]
272
+ @bank_response_code = @response[18]
273
+ @complementary_code = @response[19]
274
+ @complementary_info= @response[20]
275
+ @return_context = @response[21]
276
+ @caddie = @response[22]
277
+ @receipt_complement = @response[23]
278
+ @merchant_language = @response[24]
279
+ @language = @response[25]
280
+ @customer_id = @response[26]
281
+ @order_id = @response[27]
282
+ @customer_email = @response[28]
283
+ @customer_ip_address = @response[29]
284
+ @capture_day = @response[30]
285
+ @capture_mode = @response[31]
286
+ @data = @response[32]
287
+
288
+ if @response_code == "00"
289
+ @order = Order.find(@order_id)
290
+ if @order.pay!
291
+ @order.update_attributes!(:transaction_number => @transaction_id)
292
+ if cart = Cart.find_by_id(@order.reference)
293
+ cart.destroy
294
+ end
295
+ render :text => true
296
+ else
297
+ render :text => false, :status => 500
298
+ end
299
+ else
300
+ render :text => false, :status => 500
301
+ end
302
+ end
303
+
304
+ private
305
+ def must_be_logged
306
+ unless current_user
307
+ session[:return_to] = {:controller => 'order', :action => 'new'}
308
+ return redirect_to(login_path(:quick => '1'))
309
+ end
310
+ end
311
+
312
+ def validate_and_update_address
313
+ if params[:order] and params[:order][:address_invoice_attributes] and params[:order][:address_delivery_attributes]
314
+ address_invoice = current_user.address_invoices.find_or_create_by_id(params[:order][:address_invoice_attributes])
315
+ address_delivery = current_user.address_deliveries.find_or_create_by_id(params[:order][:address_delivery_attributes])
316
+
317
+ if address_delivery.update_attributes(params[:order][:address_delivery_attributes]) && address_invoice.update_attributes(params[:order][:address_invoice_attributes])
318
+ options = current_cart.options || {}
319
+ options[:address_invoice_id] = address_invoice.id
320
+ options[:address_delivery_id] = address_delivery.id
321
+ current_cart.save
322
+
323
+ special_offer
324
+ voucher
325
+ #have to check transporter after upodate address_delivery => 2 saves :/
326
+ transporter_rule
327
+
328
+ options[:transporter_rule_id] = @transporter_ids
329
+
330
+ change = false
331
+ if current_user.lastname.blank?
332
+ change = true
333
+ current_user.lastname = address_invoice.name
334
+ end
335
+
336
+ if current_user.firstname.blank?
337
+ change = true
338
+ current_user.firstname = address_invoice.firstname
339
+ end
340
+
341
+ if change
342
+ current_user.save
343
+ end
344
+
345
+ current_cart.save
346
+ else
347
+ @order = Order.new(params[:order])
348
+ @order.valid?
349
+ flash[:error] = "Il y a une erreur dans l'adresse de facturation ou de livraison"
350
+ render :action => "deliveries"
351
+ end
352
+ else
353
+ redirect_to :action => 'deliveries'
354
+ end
355
+ end
356
+
357
+ def special_offer
358
+ begin
359
+ engine :special_offer_engine do |e|
360
+ rule_builder = SpecialOffer.new(e)
361
+ rule_builder.cart = current_cart
362
+ @free_product_ids = []
363
+ rule_builder.free_product_ids = @free_product_ids
364
+ rule_builder.rules
365
+ current_cart.cart_items.each do |cart_product|
366
+ e.assert cart_product.product
367
+ end
368
+ e.assert current_cart
369
+ e.match
370
+ end
371
+ rescue Exception
372
+ end
373
+ end
374
+
375
+ def voucher
376
+ begin
377
+ engine :voucher_engine do |e|
378
+ rule_builder = Voucher.new(e)
379
+ rule_builder.cart = current_cart
380
+ rule_builder.code = @voucher_code || session[:voucher_code]
381
+ rule_builder.free_product_ids = @free_product_ids
382
+ rule_builder.rules
383
+ current_cart.cart_items.each do |cart_product|
384
+ e.assert cart_product.product
385
+ end
386
+ e.assert current_cart
387
+ e.match
388
+ end
389
+ rescue Exception
390
+ end
391
+ end
392
+
393
+ def transporter_rule
394
+ @transporter_ids = []
395
+ begin
396
+ engine :transporter_engine do |e|
397
+ rule_builder = Transporter.new(e)
398
+ rule_builder.transporter_ids = @transporter_ids
399
+ rule_builder.cart = current_cart
400
+ rule_builder.rules
401
+ current_cart.cart_items.each do |cart_product|
402
+ e.assert cart_product.product
403
+ end
404
+ e.assert current_cart
405
+ e.match
406
+ end
407
+ rescue Exception => e
408
+ logger.warn e.message
409
+ end
410
+ end
411
+
412
+
413
+ end
@@ -0,0 +1,32 @@
1
+ class OrdersController < ApplicationController
2
+
3
+ before_filter :login_required
4
+
5
+ def index
6
+ @orders = current_user.orders(:conditions => {:status => ['paid', 'shipped']}, :order => :updated_at).paginate(:page => page, :per_page => per_page)
7
+ end
8
+
9
+ def show
10
+ @order = Order.first(:conditions => {:id => params[:id], :status => ['paid', 'shipped']})
11
+ if not @order
12
+ flash[:error] = t(:not_found, :scope => :order)
13
+ return render :text => '', :status => 404
14
+ elsif current_user.id != @order.user_id
15
+ flash[:error] = t(:not_authorized)
16
+ return render :text => '', :status => 401
17
+ end
18
+ #WTF ???
19
+ #@order = current_user.orders
20
+ end
21
+
22
+ private
23
+
24
+ def page
25
+ params[:page].to_i > 0 ? params[:page] : 1
26
+ end
27
+
28
+ def per_page
29
+ params[:per_page].to_i > 0 ? params[:per_page] : 10
30
+ end
31
+
32
+ end