saasaparilla 0.1.6

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 (155) hide show
  1. data/.gitignore +13 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +36 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.rdoc +3 -0
  6. data/Rakefile +39 -0
  7. data/app/controllers/saasaparilla/admin/plans_controller.rb +87 -0
  8. data/app/controllers/saasaparilla/admin/subscriptions_controller.rb +34 -0
  9. data/app/controllers/saasaparilla/admin/transactions_controller.rb +14 -0
  10. data/app/controllers/saasaparilla/application_controller.rb +4 -0
  11. data/app/controllers/saasaparilla/billing_history_controller.rb +9 -0
  12. data/app/controllers/saasaparilla/contact_info_controller.rb +31 -0
  13. data/app/controllers/saasaparilla/credit_card_controller.rb +41 -0
  14. data/app/controllers/saasaparilla/invoices_controller.rb +19 -0
  15. data/app/controllers/saasaparilla/payments_controller.rb +71 -0
  16. data/app/controllers/saasaparilla/plans_controller.rb +34 -0
  17. data/app/controllers/saasaparilla/subscription_controller.rb +71 -0
  18. data/app/helpers/application_helper.rb +3 -0
  19. data/app/helpers/plans_helper.rb +2 -0
  20. data/app/helpers/saasaparilla/billing_history_helper.rb +4 -0
  21. data/app/mailers/saasaparilla/notifier.rb +38 -0
  22. data/app/models/billing_activity.rb +12 -0
  23. data/app/models/contact_info.rb +107 -0
  24. data/app/models/credit_card.rb +109 -0
  25. data/app/models/invoice.rb +31 -0
  26. data/app/models/invoice_line_item.rb +3 -0
  27. data/app/models/payment.rb +39 -0
  28. data/app/models/plan.rb +36 -0
  29. data/app/models/subscription.rb +363 -0
  30. data/app/models/transaction.rb +32 -0
  31. data/app/views/layouts/saasaparilla.html.haml +9 -0
  32. data/app/views/saasaparilla/admin/plans/_form.html.haml +45 -0
  33. data/app/views/saasaparilla/admin/plans/edit.html.erb +4 -0
  34. data/app/views/saasaparilla/admin/plans/index.html.erb +31 -0
  35. data/app/views/saasaparilla/admin/plans/new.html.haml +4 -0
  36. data/app/views/saasaparilla/admin/plans/show.html.haml +20 -0
  37. data/app/views/saasaparilla/admin/subscriptions/_subscription.html.haml +7 -0
  38. data/app/views/saasaparilla/admin/subscriptions/index.html.haml +14 -0
  39. data/app/views/saasaparilla/admin/subscriptions/show.html.haml +52 -0
  40. data/app/views/saasaparilla/admin/transactions/_transaction.html.haml +6 -0
  41. data/app/views/saasaparilla/admin/transactions/index.html.haml +16 -0
  42. data/app/views/saasaparilla/billing_history/_billing_activity.html.haml +10 -0
  43. data/app/views/saasaparilla/billing_history/show.html.haml +11 -0
  44. data/app/views/saasaparilla/contact_info/edit.html.haml +8 -0
  45. data/app/views/saasaparilla/credit_card/edit.html.haml +18 -0
  46. data/app/views/saasaparilla/invoices/show.html.haml +17 -0
  47. data/app/views/saasaparilla/notifier/billing_failed.html.haml +5 -0
  48. data/app/views/saasaparilla/notifier/billing_successful.html.haml +5 -0
  49. data/app/views/saasaparilla/notifier/invoice_created.html.haml +24 -0
  50. data/app/views/saasaparilla/notifier/pending_cancellation_notice.html.haml +6 -0
  51. data/app/views/saasaparilla/notifier/subscription_canceled.html.haml +4 -0
  52. data/app/views/saasaparilla/notifier/subscription_created.html.haml +5 -0
  53. data/app/views/saasaparilla/payments/edit.html.haml +10 -0
  54. data/app/views/saasaparilla/payments/new.html.haml +10 -0
  55. data/app/views/saasaparilla/payments/show.html.haml +8 -0
  56. data/app/views/saasaparilla/plans/edit.html.haml +34 -0
  57. data/app/views/saasaparilla/subscription/_contact_info_form.html.haml +19 -0
  58. data/app/views/saasaparilla/subscription/_credit_card_form.html.haml +10 -0
  59. data/app/views/saasaparilla/subscription/new.html.haml +24 -0
  60. data/app/views/saasaparilla/subscription/show.html.haml +73 -0
  61. data/autotest/discover.rb +2 -0
  62. data/config/routes.rb +27 -0
  63. data/lib/country_select/MIT-LICENSE +20 -0
  64. data/lib/country_select/README +15 -0
  65. data/lib/country_select/init.rb +1 -0
  66. data/lib/country_select/install.rb +2 -0
  67. data/lib/country_select/lib/country_select.rb +88 -0
  68. data/lib/country_select/uninstall.rb +1 -0
  69. data/lib/extensions/action_controller/base.rb +7 -0
  70. data/lib/extensions/active_record/nested_attributes.rb +36 -0
  71. data/lib/extensions/active_record/statuses.rb +16 -0
  72. data/lib/extensions/billable.rb +12 -0
  73. data/lib/generators/saasaparilla/install/install_generator.rb +29 -0
  74. data/lib/generators/saasaparilla/install/templates/create_saasaparilla_tables.rb +106 -0
  75. data/lib/generators/saasaparilla/install/templates/saasaparilla.yml +32 -0
  76. data/lib/initializers/auth_dot_net.rb +25 -0
  77. data/lib/initializers/simple_form.rb +77 -0
  78. data/lib/initializers/time_format.rb +3 -0
  79. data/lib/saasaparilla.rb +16 -0
  80. data/lib/saasaparilla/authentication.rb +18 -0
  81. data/lib/saasaparilla/authorization.rb +26 -0
  82. data/lib/saasaparilla/engine.rb +30 -0
  83. data/lib/saasaparilla/version.rb +3 -0
  84. data/saasaparilla.gemspec +48 -0
  85. data/spec/.livereload +21 -0
  86. data/spec/dummy/Rakefile +7 -0
  87. data/spec/dummy/app/controllers/application_controller.rb +11 -0
  88. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  89. data/spec/dummy/app/model/user.rb +4 -0
  90. data/spec/dummy/app/views/layouts/application.html.erb +15 -0
  91. data/spec/dummy/config.ru +4 -0
  92. data/spec/dummy/config/application.rb +46 -0
  93. data/spec/dummy/config/boot.rb +10 -0
  94. data/spec/dummy/config/database.yml +22 -0
  95. data/spec/dummy/config/environment.rb +5 -0
  96. data/spec/dummy/config/environments/development.rb +30 -0
  97. data/spec/dummy/config/environments/production.rb +49 -0
  98. data/spec/dummy/config/environments/test.rb +39 -0
  99. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  100. data/spec/dummy/config/initializers/inflections.rb +10 -0
  101. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  102. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  103. data/spec/dummy/config/initializers/session_store.rb +8 -0
  104. data/spec/dummy/config/initializers/simple_form.rb +77 -0
  105. data/spec/dummy/config/locales/en.yml +5 -0
  106. data/spec/dummy/config/locales/simple_form.en.yml +24 -0
  107. data/spec/dummy/config/routes.rb +58 -0
  108. data/spec/dummy/config/saasaparilla.yml +32 -0
  109. data/spec/dummy/lib/templates/erb/scaffold/_form.html.erb +13 -0
  110. data/spec/dummy/public/404.html +26 -0
  111. data/spec/dummy/public/422.html +26 -0
  112. data/spec/dummy/public/500.html +26 -0
  113. data/spec/dummy/public/favicon.ico +0 -0
  114. data/spec/dummy/public/index.html +0 -0
  115. data/spec/dummy/public/javascripts/application.js +2 -0
  116. data/spec/dummy/public/javascripts/jquery.js +8374 -0
  117. data/spec/dummy/public/javascripts/jquery.min.js +16 -0
  118. data/spec/dummy/public/javascripts/rails.js +159 -0
  119. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  120. data/spec/dummy/script/rails +6 -0
  121. data/spec/dummy/vendor/plugins/active_merchant_testing/MIT-LICENSE +20 -0
  122. data/spec/dummy/vendor/plugins/active_merchant_testing/README +32 -0
  123. data/spec/dummy/vendor/plugins/active_merchant_testing/Rakefile +23 -0
  124. data/spec/dummy/vendor/plugins/active_merchant_testing/init.rb +1 -0
  125. data/spec/dummy/vendor/plugins/active_merchant_testing/install.rb +1 -0
  126. data/spec/dummy/vendor/plugins/active_merchant_testing/lib/authorize_net_cim_gateway_test.rb +492 -0
  127. data/spec/dummy/vendor/plugins/active_merchant_testing/lib/authorize_net_gateway_test.rb +133 -0
  128. data/spec/dummy/vendor/plugins/active_merchant_testing/lib/paypal_express_gateway_test.rb +138 -0
  129. data/spec/dummy/vendor/plugins/active_merchant_testing/tasks/activemerchant_testing_tasks.rake +4 -0
  130. data/spec/dummy/vendor/plugins/active_merchant_testing/test/activemerchant_testing_test.rb +8 -0
  131. data/spec/dummy/vendor/plugins/active_merchant_testing/test/test_helper.rb +3 -0
  132. data/spec/dummy/vendor/plugins/active_merchant_testing/uninstall.rb +1 -0
  133. data/spec/factories/factories.rb +75 -0
  134. data/spec/integration/navigation_spec.rb +9 -0
  135. data/spec/mailers/notifier_spec.rb +167 -0
  136. data/spec/models/billing_activity_spec.rb +27 -0
  137. data/spec/models/contact_info_spec.rb +32 -0
  138. data/spec/models/credit_card_spec.rb +57 -0
  139. data/spec/models/invoice_line_item_spec.rb +7 -0
  140. data/spec/models/invoice_spec.rb +25 -0
  141. data/spec/models/payment_spec.rb +29 -0
  142. data/spec/models/plan_spec.rb +16 -0
  143. data/spec/models/subscription_spec.rb +414 -0
  144. data/spec/requests/admin_plans_spec.rb +32 -0
  145. data/spec/requests/admin_subscriptions_spec.rb +31 -0
  146. data/spec/requests/billing_history_spec.rb +26 -0
  147. data/spec/requests/contact_info_controller_spec.rb +42 -0
  148. data/spec/requests/credit_cards_spec.rb +79 -0
  149. data/spec/requests/invoices_spec.rb +23 -0
  150. data/spec/requests/payments_spec.rb +89 -0
  151. data/spec/requests/subscription_plans_spec.rb +34 -0
  152. data/spec/requests/subscriptions_spec.rb +80 -0
  153. data/spec/spec_helper.rb +68 -0
  154. data/spec/spec_helpers/spec_helpers.rb +8 -0
  155. metadata +611 -0
@@ -0,0 +1,363 @@
1
+ class Subscription < ActiveRecord::Base
2
+
3
+ has_statuses "active", "overdue", "suspended", "pending_cancel", "canceled"
4
+ has_many :transactions
5
+ has_many :payments
6
+ has_one :contact_info
7
+ belongs_to :plan
8
+ belongs_to :downgrade_to_plan, :class_name => "Plan", :foreign_key => :downgrade_to_plan_id
9
+ accepts_nested_attributes_for :contact_info
10
+ has_many :billing_activities
11
+ belongs_to :billable, :polymorphic => true
12
+ has_one :credit_card
13
+ accepts_nested_attributes_for :credit_card
14
+ before_create :create_cim_profile
15
+ before_create :create_payment_profile
16
+ before_validation :set_status, :on => :create
17
+ before_validation :set_credit_card_name
18
+ before_create :set_initial_balance
19
+ after_rollback :delete_profile
20
+ after_create :initial_bill
21
+ after_create :send_subscription_created_email
22
+ after_save :check_if_should_bill_for_upgrade, :on => :update
23
+ validates_presence_of :plan, :message => "can't be blank"
24
+ validates_associated :credit_card, :contact_info, :on => :create
25
+
26
+
27
+ scope :active, where("status != ?", "canceled")
28
+
29
+ scope :all_billable_subscriptions, lambda {|date|
30
+ where("billing_date < ? and balance > 0.0", date.to_time)
31
+ }
32
+
33
+ scope :all_invoiceable, lambda {|date|
34
+ #find all subscriptions not been invoiced within the last month
35
+ where("billing_date <= ? and (invoiced_on > ? OR invoiced_on is null)", date + 5.days, (date - 1.months).to_time)
36
+ }
37
+
38
+ scope :all_paid, where("no_charge != ?", true)
39
+
40
+
41
+ Plan::BILLING_PERIODS.each do |period|
42
+ define_method "#{period.downcase}?" do
43
+ plan.billing_period.downcase == period.downcase
44
+ end
45
+ end
46
+
47
+ ContactInfo.column_names.each do |col|
48
+ unless col.include? "id"
49
+ define_method "#{col}" do
50
+ contact_info.send(col)
51
+ end
52
+ end
53
+ end
54
+
55
+ class << self
56
+ def find_and_bill_recurring_subscriptions
57
+ #find_all_subscriptions need billing
58
+ @billable_subscriptions = Subscription.active.all_paid.all_billable_subscriptions(Date.today)
59
+ for subscription in @billable_subscriptions
60
+
61
+ subscription.downgrade if subscription.downgrade_to_plan.present?
62
+ begin
63
+ subscription.bill!(subscription.balance)
64
+ rescue
65
+ subscription.billing_failed
66
+ end
67
+ end
68
+
69
+ end
70
+
71
+ def find_and_invoice_subscriptions
72
+ @invoiceable_subscriptions = Subscription.active.all_paid.all_invoiceable(Date.today)
73
+ for subscription in @invoiceable_subscriptions
74
+ subscription.invoice!
75
+ end
76
+ end
77
+ end
78
+
79
+ def downgrade
80
+ self.plan = downgrade_to_plan
81
+ self.downgrade_to_plan = nil
82
+ self.balance = plan.price
83
+
84
+ self.save!
85
+
86
+ end
87
+
88
+ def downgrade_plan_to(plan_id)
89
+
90
+ if self.update_attributes(:downgrade_to_plan => Plan.find(plan_id))
91
+ return true
92
+ else
93
+ return false
94
+ end
95
+ end
96
+
97
+ def last_transaction_date
98
+ @transaction = transactions.recent.first
99
+ if @transaction.nil?
100
+ "-"
101
+ else
102
+ @transaction.created_at.to_s(:month_day_year)
103
+ end
104
+ end
105
+
106
+ def last_transaction_amount
107
+ @transaction = transactions.recent.first
108
+ if @transaction.nil?
109
+ "-"
110
+ else
111
+ @transaction.amount
112
+ end
113
+ end
114
+
115
+ def plan_name
116
+ plan.name
117
+ end
118
+ def initial_bill
119
+ if Saasaparilla::CONFIG["trial_period"] > 0
120
+ set_next_billing_date(Saasaparilla::CONFIG["trial_period"])
121
+ else
122
+ bill!
123
+ end
124
+
125
+ end
126
+
127
+ def bill!(bill_amount = nil)
128
+ bill_amount ||= balance
129
+ if charge_amount(bill_amount)
130
+ set_next_billing_date
131
+ set_status_active if balance == 0.0
132
+ send_billing_successful_email(bill_amount)
133
+ return true
134
+ end
135
+
136
+ end
137
+
138
+
139
+ def invoice!
140
+ add_to_balance(plan.price)
141
+ create_invoice
142
+ self.update_attributes(:invoiced_on => Date.today)
143
+ #if invoice_subscription
144
+ # set_next_invoice_date()
145
+ end
146
+
147
+ def cancel
148
+ set_canceled
149
+ send_subscription_canceled_email
150
+ end
151
+
152
+ def reactivate!
153
+ self.update_attributes(:billing_date => nil)
154
+ self.balance = 0
155
+ add_to_balance(plan.price)
156
+ bill!
157
+ end
158
+
159
+ def billing_failed
160
+ set_status_overdue
161
+
162
+ if billing_date == Date.today
163
+ send_billing_failed_email
164
+ end
165
+
166
+ if billing_date == Date.today - Saasaparilla::CONFIG["grace_period"].days + 1
167
+ send_pending_cancellation_notice_email
168
+ end
169
+
170
+ if billing_date < Date.today - Saasaparilla::CONFIG["grace_period"].days
171
+ cancel
172
+ end
173
+ end
174
+
175
+
176
+ private
177
+
178
+ def create_invoice
179
+ @invoice = Invoice.create(:subscription => self, :price => plan.price, :from => get_beginning_of_billing_cycle, :to => billing_date)
180
+ end
181
+
182
+ def get_beginning_of_billing_cycle
183
+ if monthly?
184
+ return billing_date - 1.months
185
+ elsif annually?
186
+ return billing_date - 1.years
187
+ end
188
+ end
189
+
190
+ def set_next_billing_date(grace_period = 0)
191
+ grace_period = grace_period - 1 if grace_period > 0
192
+ if monthly?
193
+ if billing_date.nil?
194
+ self.update_attributes(:billing_date => Date.today + 1.months + grace_period.months)
195
+ else
196
+ self.update_attributes(:billing_date => billing_date + 1.months)
197
+ end
198
+
199
+ elsif annually?
200
+ if billing_date.nil?
201
+ self.update_attributes(:billing_date => Date.today + 1.years + grace_period.months)
202
+ else
203
+ self.update_attributes(:billing_date => billing_date + 1.years)
204
+ end
205
+ end
206
+ end
207
+
208
+ def set_status_active
209
+ self.update_attributes(:status => "active") if !active?
210
+ end
211
+
212
+ def set_canceled
213
+ self.update_attributes(:status => "canceled")
214
+ end
215
+
216
+ def set_status_overdue
217
+ unless overdue?
218
+ self.overdue_on = Date.today
219
+ end
220
+ self.status = "overdue"
221
+ self.save
222
+
223
+ end
224
+ def add_to_balance(cost)
225
+ self.increment!(:balance, cost)
226
+ end
227
+
228
+ def create_cim_profile
229
+ #Login to the gateway using your credentials in environment.rb
230
+ #setup the user object to save
231
+ @profile = {:profile => profile}
232
+
233
+ #send the create message to the gateway API
234
+ response = ::GATEWAYCIM.create_customer_profile(@profile)
235
+
236
+ if response.success? and response.authorization
237
+ self.customer_cim_id = response.authorization
238
+ return true
239
+ else
240
+ raise response.message
241
+ return false
242
+ end
243
+
244
+ end
245
+
246
+
247
+
248
+ def create_payment_profile
249
+
250
+ unless customer_payment_profile_id.nil?
251
+ return false
252
+ end
253
+ @profile = {:customer_profile_id => customer_cim_id,
254
+ :payment_profile => {:bill_to => contact_info.to_hash, :payment => {:credit_card => credit_card.active_merchant_card}
255
+ }
256
+ }
257
+
258
+ response = GATEWAYCIM.create_customer_payment_profile(@profile)
259
+
260
+ logger.info "payment_response #{response.to_yaml}"
261
+ if response.success? and response.params['customer_payment_profile_id']
262
+ self.customer_payment_profile_id = response.params['customer_payment_profile_id']
263
+ return true
264
+ end
265
+
266
+ raise response.message
267
+ return false
268
+ end
269
+
270
+ def profile
271
+ return {:merchant_customer_id => self.id, :email => contact_info.email, :description => contact_info.full_name}
272
+ end
273
+
274
+ def set_status
275
+ self.status = "active"
276
+ end
277
+
278
+ def set_initial_balance
279
+ self.balance = plan.price
280
+ end
281
+
282
+
283
+ def charge_amount(amount)
284
+ response = GATEWAYCIM.create_customer_profile_transaction(:transaction => {:type => :auth_capture,
285
+ :amount => amount,
286
+ :customer_profile_id => customer_cim_id,
287
+ :customer_payment_profile_id => customer_payment_profile_id})
288
+
289
+ transaction = self.transactions.create(:action => "purchase", :amount => amount, :response => response, :subscription => self)
290
+ if response.success?
291
+ self.update_attributes(:balance => balance - amount)
292
+ return true
293
+ else
294
+ raise response.message
295
+ return false
296
+ end
297
+ end
298
+
299
+ def delete_profile
300
+ if new_record?
301
+ response = GATEWAYCIM::delete_customer_profile(:customer_profile_id => self.customer_cim_id) if customer_cim_id
302
+ end
303
+ end
304
+
305
+ def check_if_should_bill_for_upgrade
306
+ if plan_id_changed? && !new_record? && plan_id_was != nil
307
+ old_plan_price = Plan.find(plan_id_was).price
308
+ if !old_plan_price.nil? && old_plan_price < plan.price
309
+ # Upgrade
310
+ if billing_date <= Date.today + 5.days
311
+ # For accounts w/ current invoice and close to renew date. Should recieve a few days free on new plan
312
+ balance = plan.price
313
+ old_plan_price = nil
314
+ else
315
+ # Pro-rate for account in the middle of billing cycle. Should recieve a credit.
316
+ if monthly?
317
+ time_to_credit = billing_date.to_time - Date.today.to_time
318
+ percentage = time_to_credit / 1.month
319
+ elsif yearly?
320
+ time_to_credit = billing_date.to_time - Date.today.to_time
321
+ percentage = time_to_credit / 1.year
322
+ end
323
+ credit = (old_plan_price * percentage).round(1)
324
+
325
+ # debugger
326
+
327
+ old_plan_price = nil
328
+ @changed_attributes.clear
329
+ add_to_balance(plan.price - credit)
330
+ self.update_attributes(:billing_date => nil)
331
+ bill!
332
+ end
333
+ end
334
+ # Do nothing for downgrade. Plan won't change until next cycle.
335
+ end
336
+ end
337
+
338
+ def set_credit_card_name
339
+ self.credit_card.first_name = contact_info.first_name
340
+ self.credit_card.last_name = contact_info.last_name
341
+ end
342
+
343
+ def send_subscription_created_email
344
+ Saasaparilla::Notifier.subscription_created(self).deliver
345
+ end
346
+
347
+ def send_billing_successful_email(amount)
348
+ Saasaparilla::Notifier.billing_successful(self, amount).deliver
349
+ end
350
+
351
+ def send_billing_failed_email
352
+ Saasaparilla::Notifier.billing_failed(self).deliver
353
+ end
354
+
355
+ def send_pending_cancellation_notice_email
356
+ Saasaparilla::Notifier.pending_cancellation_notice(self).deliver
357
+ end
358
+
359
+ def send_subscription_canceled_email
360
+ Saasaparilla::Notifier.subscription_canceled(self).deliver
361
+ end
362
+
363
+ end
@@ -0,0 +1,32 @@
1
+ class Transaction < ActiveRecord::Base
2
+
3
+ belongs_to :subscription
4
+ serialize :params
5
+ belongs_to :billing_activity
6
+ after_create :generate_billing_activity
7
+
8
+
9
+ def response=(response)
10
+ self.success = response.success?
11
+ self.authorization = response.authorization
12
+ self.message = response.message
13
+ self.params = response.params
14
+ rescue ActiveMerchant::ActiveMerchantError => e
15
+ self.success = false
16
+ self.authorization = nil
17
+ self.message = e.message
18
+ self.params = {}
19
+ end
20
+
21
+ scope :successful, lambda {
22
+ where("success = ?", true)
23
+ }
24
+ scope :recent, order("created_at DESC")
25
+
26
+ private
27
+ def generate_billing_activity
28
+ if success
29
+ self.create_billing_activity(:message => BillingActivity::MESSAGES[:success], :subscription => subscription, :amount => amount)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,9 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ = stylesheet_link_tag :all
5
+ = javascript_include_tag :defaults
6
+ = csrf_meta_tag
7
+ %body
8
+ = flash[:notice]
9
+ = yield
@@ -0,0 +1,45 @@
1
+ = simple_form_for([:admin, @plan]) do |f|
2
+ - if @plan.errors.any?
3
+ #error_explanation
4
+ %h2= "#{pluralize(@plan.errors.count, "error")} prohibited this plan from being saved:"
5
+
6
+ %ul
7
+ -@plan.errors.full_messages.each do |msg|
8
+ %li= msg
9
+
10
+
11
+ = f.input :name
12
+ = f.input :price
13
+ = f.input :billing_period, :collection => Plan::BILLING_PERIODS, :include_blank => false
14
+
15
+ %fieldset
16
+ %h4 Plan Attributes
17
+ = f.label "Add new attribute"
18
+ = text_field_tag "attribute_name"
19
+ = link_to "Add attribute", "#", :id => "add_attribute"
20
+ #optional_attributes
21
+ -begin
22
+ - @plan.dynamic_attributes.each do |da|
23
+ = f.label da[0].gsub("field_", "")
24
+ = text_field_tag "plan[#{da[0]}]", da[1]
25
+ %br
26
+ - rescue
27
+
28
+ .actions
29
+ = f.submit
30
+ = link_to 'Cancel', :back
31
+
32
+ :javascript
33
+ $(document).ready(function(){
34
+ $('#add_attribute').click(function(event) {
35
+ event.preventDefault();
36
+ if ($('#attribute_name').val() == '') {
37
+ alert("You must give your attribute a name.");
38
+ } else {
39
+ $('#optional_attributes').append("<br><label>" + $('#attribute_name').val() +"</label><input name='plan[field_" + $('#attribute_name').val() +"]' id='field_" + $('#attribute_name').val() +"'>");
40
+ }
41
+ })
42
+ })
43
+
44
+
45
+