subscription_fu 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +16 -0
  3. data/LICENSE +20 -0
  4. data/README.md +96 -0
  5. data/Rakefile +6 -0
  6. data/app/models/subscription_fu/plan.rb +43 -0
  7. data/app/models/subscription_fu/subscription.rb +117 -0
  8. data/app/models/subscription_fu/transaction.rb +131 -0
  9. data/config/locales/en.yml +7 -0
  10. data/examples/routes.rb +7 -0
  11. data/examples/subscriptions_controller.rb +12 -0
  12. data/examples/transactions_controller.rb +33 -0
  13. data/lib/generators/subscription_fu/install_generator.rb +23 -0
  14. data/lib/generators/subscription_fu/templates/en.yml +17 -0
  15. data/lib/generators/subscription_fu/templates/initializer.rb +24 -0
  16. data/lib/generators/subscription_fu/templates/migration.rb +38 -0
  17. data/lib/subscription_fu/config.rb +36 -0
  18. data/lib/subscription_fu/engine.rb +5 -0
  19. data/lib/subscription_fu/models.rb +54 -0
  20. data/lib/subscription_fu/paypal.rb +101 -0
  21. data/lib/subscription_fu/railtie.rb +12 -0
  22. data/lib/subscription_fu/version.rb +3 -0
  23. data/lib/subscription_fu.rb +15 -0
  24. data/spec/app/.gitignore +1 -0
  25. data/spec/app/Rakefile +8 -0
  26. data/spec/app/app/controllers/application_controller.rb +6 -0
  27. data/spec/app/app/models/initiator.rb +2 -0
  28. data/spec/app/app/models/subject.rb +4 -0
  29. data/spec/app/app/views/layouts/application.html.haml +6 -0
  30. data/spec/app/config/application.rb +11 -0
  31. data/spec/app/config/boot.rb +4 -0
  32. data/spec/app/config/database.yml +18 -0
  33. data/spec/app/config/environment.rb +5 -0
  34. data/spec/app/config/environments/development.rb +18 -0
  35. data/spec/app/config/environments/test.rb +22 -0
  36. data/spec/app/config/initializers/backtrace_silencers.rb +7 -0
  37. data/spec/app/config/initializers/inflections.rb +2 -0
  38. data/spec/app/config/initializers/secret_token.rb +2 -0
  39. data/spec/app/config/initializers/subscription_fu.rb +28 -0
  40. data/spec/app/config/locales/subscription_fu.en.yml +17 -0
  41. data/spec/app/config/routes.rb +3 -0
  42. data/spec/app/config.ru +4 -0
  43. data/spec/app/db/.gitignore +1 -0
  44. data/spec/app/db/migrate/20110516061428_create_subjects.rb +13 -0
  45. data/spec/app/db/migrate/20110516061443_create_initiators.rb +14 -0
  46. data/spec/app/db/migrate/20110516070948_create_subscription_fu_tables.rb +38 -0
  47. data/spec/app/db/schema.rb +62 -0
  48. data/spec/app/script/rails +10 -0
  49. data/spec/factories/initiator.rb +4 -0
  50. data/spec/factories/subject.rb +2 -0
  51. data/spec/factories/subscription.rb +6 -0
  52. data/spec/factories/transaction.rb +7 -0
  53. data/spec/models/subscription_spec.rb +277 -0
  54. data/spec/models/subscription_transaction_spec.rb +135 -0
  55. data/spec/spec_helper.rb +18 -0
  56. data/spec/support/paypal_test_helper.rb +82 -0
  57. data/subscription_fu.gemspec +23 -0
  58. metadata +134 -0
@@ -0,0 +1,54 @@
1
+ module SubscriptionFu
2
+ module Models
3
+ def self.included(base)
4
+ base.send(:extend, ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def needs_subscription
9
+ send(:include, InstanceMethods)
10
+ has_many :subscriptions, :class_name => "SubscriptionFu::Subscription", :as => :subject, :dependent => :destroy
11
+ delegate :plan, :sponsored?, :canceled?, :prefix => :subscription, :to => :active_subscription, :allow_nil => true
12
+ delegate :plan, :prefix => :upcoming_subscription, :to => :upcoming_subscription, :allow_nil => true
13
+ end
14
+ end
15
+
16
+ module InstanceMethods
17
+ def human_description_for_subscription
18
+ self.class.model_name.human
19
+ end
20
+
21
+ def active_subscription
22
+ @active_subscription ||= subscriptions.current(Time.now).last
23
+ end
24
+
25
+ def active_subscription?
26
+ !active_subscription.nil?
27
+ end
28
+
29
+ def upcoming_subscription
30
+ active_subscription ? active_subscription.next_subscriptions.activated.last : nil
31
+ end
32
+
33
+ def pending_transaction(identifier)
34
+ sub = subscriptions.last
35
+ if sub.activated?
36
+ logger.info("Latest subscription is already activated")
37
+ nil
38
+ else
39
+ sub.transactions.initiated.find_by_identifier(identifier)
40
+ end
41
+ end
42
+
43
+ def build_next_subscription(plan_key)
44
+ if active_subscription
45
+ # TODO refactor
46
+ subscriptions.build_for_initializing(plan_key, active_subscription.successor_start_date(plan_key), active_subscription.successor_billing_start_date, active_subscription)
47
+ else
48
+ subscriptions.build_for_initializing(plan_key)
49
+ end
50
+ end
51
+ end
52
+
53
+ end
54
+ end
@@ -0,0 +1,101 @@
1
+ require "rest-client"
2
+
3
+ class SubscriptionFu::Paypal
4
+
5
+ def self.paypal
6
+ new(SubscriptionFu.config.paypal_api_user_id,
7
+ SubscriptionFu.config.paypal_api_pwd,
8
+ SubscriptionFu.config.paypal_api_sig,
9
+ SubscriptionFu.config.paypal_nvp_api_url,
10
+ Rails.logger)
11
+ end
12
+
13
+ class Failure < RuntimeError
14
+ attr_reader :request_opts, :response
15
+
16
+ def initialize(request_opts, response)
17
+ @request_opts = request_opts
18
+ @response = response
19
+ super "PayPal did not return success: #{@response.inspect}"
20
+ end
21
+ alias :data :request_opts
22
+ end
23
+
24
+ def initialize(user, pwd, sig, api_url, logger)
25
+ @user = user
26
+ @pwd = pwd
27
+ @sig = sig
28
+ @api_url = api_url
29
+ @logger = logger
30
+ end
31
+
32
+ def start_checkout(return_url, cancel_url, email, maxamt, currency_code, desc)
33
+ res = call_paypal('SetExpressCheckout',
34
+ 'RETURNURL' => return_url,
35
+ 'CANCELURL' => cancel_url,
36
+ 'EMAIL' => email,
37
+ 'NOSHIPPING' => 1,
38
+ 'MAXAMT' => maxamt,
39
+ 'PAYMENTREQUEST_0_AMT' => 0,
40
+ 'PAYMENTREQUEST_0_CURRENCYCODE' => currency_code,
41
+ 'L_BILLINGTYPE0' => 'RecurringPayments',
42
+ 'L_BILLINGAGREEMENTDESCRIPTION0' => desc)
43
+ res['TOKEN'].first
44
+ end
45
+
46
+ def create_recurring(token, start_date, amt, taxamt, currency_code, desc)
47
+ res = call_paypal('CreateRecurringPaymentsProfile',
48
+ 'PROFILESTARTDATE' => start_date.utc.iso8601,
49
+ 'BILLINGPERIOD' => 'Month',
50
+ 'BILLINGFREQUENCY' => 1,
51
+ 'MAXFAILEDPAYMENTS' => 0,
52
+ 'AUTOBILLOUTAMT' => 'AddToNextBilling',
53
+ 'AMT' => amt,
54
+ 'TAXAMT' => taxamt,
55
+ 'CURRENCYCODE' => currency_code,
56
+ 'DESC' => desc,
57
+ 'TOKEN' => token)
58
+ [res['PROFILEID'].first, res['PROFILESTATUS'].first || res['STATUS'].first]
59
+ end
60
+
61
+ def recurring_details(profile_id)
62
+ utc = ActiveSupport::TimeZone.new("UTC")
63
+ res = call_paypal('GetRecurringPaymentsProfileDetails', 'PROFILEID' => profile_id)
64
+ { :id => res['PROFILEID'].first,
65
+ :status => res['PROFILESTATUS'].first || res['STATUS'].first,
66
+ :next_billing_date => utc.parse(res['NEXTBILLINGDATE'].first.to_s),
67
+ :start_date => utc.parse(res['PROFILESTARTDATE'].first.to_s),
68
+ :cycles_completed => res['NUMCYCLESCOMPLETED'].first.to_i,
69
+ :outstanding_balance => res['OUTSTANDINGBALANCE'].first.to_f,
70
+ :last_payment_date => utc.parse(res['LASTPAYMENTDATE'].first.to_s) }
71
+ end
72
+
73
+ def cancel_recurring(profile_id, reason)
74
+ call_paypal('ManageRecurringPaymentsProfileStatus',
75
+ 'PROFILEID' => profile_id,
76
+ 'ACTION' => 'Cancel',
77
+ 'NOTE' => I18n.t(reason, :scope => [:subscription_fu, :subscription, :cancel_notes]))
78
+ end
79
+
80
+ private
81
+
82
+ def call_paypal(method, opts)
83
+ full_opts = paypal_api_opts(method, opts)
84
+ CGI.parse(RestClient.post(@api_url, full_opts)).tap do |result|
85
+ if result['ACK'].first != 'Success'
86
+ @logger.warn("PayPal did not return success for call to #{method}")
87
+ @logger.info(" called with: #{full_opts.inspect}")
88
+ @logger.info(" result: #{result.inspect}")
89
+ raise Failure.new(full_opts, result)
90
+ else
91
+ @logger.info("PayPal returned success for call to #{method}")
92
+ @logger.info(" result: #{result.inspect}")
93
+ end
94
+ end
95
+ end
96
+
97
+ def paypal_api_opts(method, opts)
98
+ opts.merge('USER' => @user, 'PWD' => @pwd, 'SIGNATURE' => @sig, 'VERSION' => '65.0', 'METHOD' => method)
99
+ end
100
+
101
+ end
@@ -0,0 +1,12 @@
1
+ module SubscriptionFu
2
+ class Railtie < ::Rails::Railtie
3
+ config.subscription_fu = SubscriptionFu.config
4
+ initializer "subscription_fu.extend.active_record" do |app|
5
+ ActiveSupport.on_load :active_record do
6
+ include SubscriptionFu::Models
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ require "subscription_fu/models"
@@ -0,0 +1,3 @@
1
+ module SubscriptionFu
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,15 @@
1
+ module SubscriptionFu
2
+ autoload :Config, "subscription_fu/config"
3
+ autoload :Paypal, "subscription_fu/paypal"
4
+
5
+ def self.config
6
+ @config ||= SubscriptionFu::Config.new
7
+ end
8
+
9
+ def self.friendly_token
10
+ ActiveSupport::SecureRandom.base64(44).tr('+/=', 'xyz')
11
+ end
12
+ end
13
+
14
+ require 'subscription_fu/railtie'
15
+ require 'subscription_fu/engine'
@@ -0,0 +1 @@
1
+ log
data/spec/app/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+
6
+ require 'rake'
7
+
8
+ Rails.application.load_tasks
@@ -0,0 +1,6 @@
1
+ # Filters added to this controller apply to all controllers in the application.
2
+ # Likewise, all the methods added will be available for all controllers.
3
+
4
+ class ApplicationController < ActionController::Base
5
+ protect_from_forgery
6
+ end
@@ -0,0 +1,2 @@
1
+ class Initiator < ActiveRecord::Base
2
+ end
@@ -0,0 +1,4 @@
1
+ class Subject < ActiveRecord::Base
2
+ needs_subscription
3
+
4
+ end
@@ -0,0 +1,6 @@
1
+ %html
2
+ %head
3
+ %meta{"http-equiv" => "Content-Type", :content => "text/html;charset=UTF-8"}
4
+ = yield :head if content_for?(:head)
5
+ %body
6
+ = yield
@@ -0,0 +1,11 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require "action_controller/railtie"
4
+ require "active_record/railtie"
5
+ require "rails/test_unit/railtie"
6
+ require 'subscription_fu'
7
+
8
+ module RailsApp
9
+ class Application < Rails::Application
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ $:.unshift File.expand_path('../../../../lib', __FILE__)
4
+
@@ -0,0 +1,18 @@
1
+ # SQLite version 3.x
2
+ # gem install sqlite3-ruby (not necessary on OS X Leopard)
3
+ development:
4
+ adapter: sqlite3
5
+ database: db/development.sqlite3
6
+ pool: 5
7
+ timeout: 5000
8
+
9
+ # Warning: The database defined as "test" will be erased and
10
+ # re-generated from your development database when you run "rake".
11
+ # Do not set this db to the same as development or production.
12
+ test:
13
+ adapter: sqlite3
14
+ database: ":memory:"
15
+
16
+ production:
17
+ adapter: sqlite3
18
+ database: ":memory:"
@@ -0,0 +1,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ RailsApp::Application.initialize!
@@ -0,0 +1,18 @@
1
+ RailsApp::Application.configure do
2
+ # Settings specified here will take precedence over those in config/environment.rb
3
+
4
+ # In the development environment your application's code is reloaded on
5
+ # every request. This slows down response time but is perfect for development
6
+ # since you don't have to restart the webserver when you make code changes.
7
+ config.cache_classes = false
8
+
9
+ # Log error messages when you accidentally call methods on nil.
10
+ config.whiny_nils = true
11
+
12
+ # Show full error reports and disable caching
13
+ config.consider_all_requests_local = true
14
+ config.action_view.debug_rjs = true
15
+ config.action_controller.perform_caching = false
16
+
17
+ config.active_support.deprecation = :stderr
18
+ end
@@ -0,0 +1,22 @@
1
+ RailsApp::Application.configure do
2
+ # Settings specified here will take precedence over those in config/environment.rb
3
+
4
+ # The test environment is used exclusively to run your application's
5
+ # test suite. You never need to work with it otherwise. Remember that
6
+ # your test database is "scratch space" for the test suite and is wiped
7
+ # and recreated between test runs. Don't rely on the data there!
8
+ config.cache_classes = true
9
+
10
+ # Log error messages when you accidentally call methods on nil.
11
+ config.whiny_nils = true
12
+
13
+ # Show full error reports and disable caching
14
+ config.consider_all_requests_local = true
15
+ config.action_controller.perform_caching = false
16
+
17
+ # Disable request forgery protection in test environment
18
+ config.action_controller.allow_forgery_protection = false
19
+
20
+ config.action_dispatch.show_exceptions = false
21
+ config.active_support.deprecation = :stderr
22
+ end
@@ -0,0 +1,7 @@
1
+ # Be sure to restart your server when you modify this file.
2
+
3
+ # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4
+ # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
5
+
6
+ # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
7
+ Rails.backtrace_cleaner.remove_silencers!
@@ -0,0 +1,2 @@
1
+ ActiveSupport::Inflector.inflections do |inflect|
2
+ end
@@ -0,0 +1,2 @@
1
+ Rails.application.config.secret_token = 'afvrbanwvUY89vafbvahjkb'
2
+ Rails.application.config.session_store :cookie_store, :key => "_my_app"
@@ -0,0 +1,28 @@
1
+ class MyCustomPlan < SubscriptionFu::Plan
2
+ attr_accessor :tickets
3
+
4
+ def private_events?
5
+ price > 1000
6
+ end
7
+
8
+ def custom_email_from?
9
+ price > 1000
10
+ end
11
+
12
+ def extra_promotion?
13
+ ! free_plan?
14
+ end
15
+ end
16
+
17
+ RailsApp::Application.configure do
18
+ config.subscription_fu.paypal_api_user_id = "michae_1272617165_biz_api1.mobalean.com"
19
+ config.subscription_fu.paypal_api_pwd = "1272617171"
20
+ config.subscription_fu.paypal_api_sig = "ATpPRKe6SEGaLcgDfFD-kBQgVsGuA9iFQwK6d4x6Qs4iti0XYRkZQl9Q"
21
+
22
+ config.subscription_fu.plan_class_name = "MyCustomPlan"
23
+
24
+ config.subscription_fu.add_free_plan 'free', :tickets => 100
25
+ config.subscription_fu.add_plan 'basic', 1000, :tickets => 100
26
+ config.subscription_fu.add_plan 'premium', 5000, :tickets => 200
27
+ config.subscription_fu.add_plan 'profess', 20000, :tickets => 1000
28
+ end
@@ -0,0 +1,17 @@
1
+ en:
2
+ subscription_fu:
3
+ subscription:
4
+ # description used for Paypal
5
+ description: "%{plan_name} subscription for %{subject_desc}, %{price} per month"
6
+ # cancel notes used as description for Paypal
7
+ cancel_notes:
8
+ update: "Changed subscription plan"
9
+ cancel: "Subscription cancelled"
10
+ plan:
11
+ options:
12
+ # match this section with the plan names you are using in
13
+ # config/initializers/subscription_fu.rb to get human readable names
14
+ profess: Professional
15
+ premium: Premium
16
+ basic: Basic
17
+ free: Free
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ root :to => "home#index"
3
+ end
@@ -0,0 +1,4 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require ::File.expand_path('../config/environment', __FILE__)
4
+ run RailsApp::Application
@@ -0,0 +1 @@
1
+ *.sqlite3
@@ -0,0 +1,13 @@
1
+ class CreateSubjects < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :subjects do |t|
4
+ t.string :desc
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :subjects
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ class CreateInitiators < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :initiators do |t|
4
+ t.string :desc
5
+ t.string :email
6
+
7
+ t.timestamps
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ drop_table :initiators
13
+ end
14
+ end
@@ -0,0 +1,38 @@
1
+ class CreateSubscriptionFuTables < ActiveRecord::Migration
2
+ def self.up
3
+ create_table "subscriptions", :force => true do |t|
4
+ t.references "subject", :polymorphic => true
5
+ t.references "prev_subscription"
6
+ t.string "plan_key", :limit => 10, :null => false
7
+ t.boolean "sponsored", :null => false, :default => false
8
+ t.string "paypal_profile_id"
9
+ t.datetime "starts_at", :null => false
10
+ t.datetime "billing_starts_at", :null => false
11
+ t.datetime "activated_at"
12
+ t.datetime "canceled_at"
13
+ t.string "cancel_reason", :limit => 10
14
+ t.timestamps
15
+ end
16
+
17
+ add_index "subscriptions", ["subject_id", "subject_type"]
18
+
19
+ create_table "subscription_transactions" do |t|
20
+ t.references "subscription", :null => false
21
+ t.references "initiator", :null => false, :polymorphic => true
22
+ t.string "action", :limit => 15, :null => false
23
+ t.string "status", :limit => 15, :null => false
24
+ t.string "gateway", :limit => 10, :null => false
25
+ t.string "identifier"
26
+ t.references "related_transaction"
27
+ t.timestamps
28
+ end
29
+
30
+ add_index "subscription_transactions", ["identifier"]
31
+ add_index "subscription_transactions", ["subscription_id"]
32
+ end
33
+
34
+ def self.down
35
+ drop_table "subscriptions"
36
+ drop_table "subscription_transactions"
37
+ end
38
+ end
@@ -0,0 +1,62 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # Note that this schema.rb definition is the authoritative source for your
6
+ # database schema. If you need to create the application database on another
7
+ # system, you should be using db:schema:load, not running all the migrations
8
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
10
+ #
11
+ # It's strongly recommended to check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(:version => 20110516070948) do
14
+
15
+ create_table "initiators", :force => true do |t|
16
+ t.string "desc"
17
+ t.string "email"
18
+ t.datetime "created_at"
19
+ t.datetime "updated_at"
20
+ end
21
+
22
+ create_table "subjects", :force => true do |t|
23
+ t.string "desc"
24
+ t.datetime "created_at"
25
+ t.datetime "updated_at"
26
+ end
27
+
28
+ create_table "subscription_transactions", :force => true do |t|
29
+ t.integer "subscription_id", :null => false
30
+ t.integer "initiator_id", :null => false
31
+ t.string "initiator_type", :null => false
32
+ t.string "action", :limit => 15, :null => false
33
+ t.string "status", :limit => 15, :null => false
34
+ t.string "gateway", :limit => 10, :null => false
35
+ t.string "identifier"
36
+ t.integer "related_transaction_id"
37
+ t.datetime "created_at"
38
+ t.datetime "updated_at"
39
+ end
40
+
41
+ add_index "subscription_transactions", ["identifier"], :name => "index_subscription_transactions_on_identifier"
42
+ add_index "subscription_transactions", ["subscription_id"], :name => "index_subscription_transactions_on_subscription_id"
43
+
44
+ create_table "subscriptions", :force => true do |t|
45
+ t.integer "subject_id"
46
+ t.string "subject_type"
47
+ t.integer "prev_subscription_id"
48
+ t.string "plan_key", :limit => 10, :null => false
49
+ t.boolean "sponsored", :default => false, :null => false
50
+ t.string "paypal_profile_id"
51
+ t.datetime "starts_at", :null => false
52
+ t.datetime "billing_starts_at", :null => false
53
+ t.datetime "activated_at"
54
+ t.datetime "canceled_at"
55
+ t.string "cancel_reason", :limit => 10
56
+ t.datetime "created_at"
57
+ t.datetime "updated_at"
58
+ end
59
+
60
+ add_index "subscriptions", ["subject_id", "subject_type"], :name => "index_subscriptions_on_subject_id_and_subject_type"
61
+
62
+ end
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ ENV_PATH = File.expand_path('../../config/environment', __FILE__)
5
+ BOOT_PATH = File.expand_path('../../config/boot', __FILE__)
6
+ APP_PATH = File.expand_path('../../config/application', __FILE__)
7
+ ROOT_PATH = File.expand_path('../..', __FILE__)
8
+
9
+ require BOOT_PATH
10
+ require 'rails/commands'
@@ -0,0 +1,4 @@
1
+ Factory.sequence(:initiator_email) {|n| "mail#{n}@mobalean.com"}
2
+ Factory.define(:initiator) do |a|
3
+ a.email {|o| Factory.next(:initiator_email) }
4
+ end
@@ -0,0 +1,2 @@
1
+ Factory.define(:subject) do |s|
2
+ end
@@ -0,0 +1,6 @@
1
+ Factory.define :subscription, :class => "SubscriptionFu::Subscription" do |s|
2
+ s.subject {|s| Factory(:subject) }
3
+ s.starts_at Time.now
4
+ s.billing_starts_at Time.now
5
+ s.plan_key "premium"
6
+ end
@@ -0,0 +1,7 @@
1
+ Factory.define :transaction, :class => "SubscriptionFu::Transaction" do |t|
2
+ t.association :subscription
3
+ t.association :initiator
4
+ t.gateway "nogw"
5
+ t.status "initiated"
6
+ t.action "activation"
7
+ end