subscription_fu 0.1.0

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 (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