susply 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.rdoc +1 -0
  3. data/app/controllers/susply/application_controller.rb +1 -1
  4. data/app/controllers/susply/change_plans_controller.rb +32 -0
  5. data/app/controllers/susply/renovations_controller.rb +37 -0
  6. data/app/models/susply/subscription.rb +8 -0
  7. data/app/services/susply/renews_subscription.rb +4 -4
  8. data/config/locales/susply.en.yml +8 -0
  9. data/config/routes.rb +4 -0
  10. data/lib/generators/susply/install_generator.rb +11 -0
  11. data/lib/generators/templates/config/initializers/susply.rb +1 -0
  12. data/lib/susply.rb +6 -0
  13. data/lib/susply/version.rb +1 -1
  14. data/spec/controllers/susply/change_plans_controller_spec.rb +95 -0
  15. data/spec/controllers/susply/renovations_controller_spec.rb +87 -0
  16. data/spec/dummy/app/assets/javascripts/companies.js +2 -0
  17. data/spec/dummy/app/assets/stylesheets/companies.css +4 -0
  18. data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
  19. data/spec/dummy/app/controllers/companies_controller.rb +58 -0
  20. data/spec/dummy/app/helpers/companies_helper.rb +2 -0
  21. data/spec/dummy/app/models/company.rb +2 -0
  22. data/spec/dummy/app/views/companies/_form.html.erb +21 -0
  23. data/spec/dummy/app/views/companies/edit.html.erb +6 -0
  24. data/spec/dummy/app/views/companies/index.html.erb +27 -0
  25. data/spec/dummy/app/views/companies/new.html.erb +5 -0
  26. data/spec/dummy/app/views/companies/show.html.erb +9 -0
  27. data/spec/dummy/config/initializers/susply.rb +1 -0
  28. data/spec/dummy/config/locales/susply.en.yml +6 -0
  29. data/spec/dummy/config/routes.rb +2 -2
  30. data/spec/dummy/db/migrate/20150525181508_create_companies.rb +9 -0
  31. data/spec/dummy/log/development.log +300 -0
  32. data/spec/dummy/log/test.log +26916 -0
  33. data/spec/models/susply/subscription_spec.rb +39 -0
  34. data/spec/services/susply/renews_subscription_spec.rb +25 -16
  35. metadata +35 -6
  36. data/spec/dummy/spec/factories/organizations.rb +0 -8
  37. data/spec/dummy/spec/models/organization_spec.rb +0 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7b3829fb3458ce9daf9f83a8155fc4c2f0410385
4
- data.tar.gz: 244df39807a39516b83e48c70ecf8d502f61a2c3
3
+ metadata.gz: d45e6b7802160d8581a0d6a13dd282b9d04fad14
4
+ data.tar.gz: 2978c1e66d5bb7334cbfe7b7f052e7136056508e
5
5
  SHA512:
6
- metadata.gz: f5f794f190d0a7f75efb993fed32272b4dd132f07a3ff8f2747326384e5c9aaf1208bbf9e9578f6786e83bded40c25d75a6fa1c3e1abd8df1c5996b1f038c197
7
- data.tar.gz: 7958f7464dcfc9efd7a0e1b075f57a9994c6a5f5872f6d51785337f3c464911d055f4e077533c3a846d62718971ebcee2f680bfdf56a2f7283d6cf7d6438a6cc
6
+ metadata.gz: da42b7708ef8a48d7600717c7843906ccda69817b78fccd21101390973610fcb99f5a4cb4ab3c83a201a05196f80159ff2db7abdcac5897df070cd390b7076aa
7
+ data.tar.gz: 52029ee2fde8fab1b1b0deb44e2f917b5071d2c530dc245fedee9ff2232d392512bbbfcf04a6a2781cca851402b3df1a7ec426554c2373d3406b75d0ddd9ac53
@@ -1,6 +1,7 @@
1
1
  = Susply
2
2
 
3
3
  {<img alt="Status?branch=master" src="https://codeship.com/projects/9749e880-e313-0132-4e7b-0e8782f5ebb8/status?branch=master" />}[https://codeship.com/projects/81636]
4
+ {<img src="https://badge.fury.io/rb/susply.svg" alt="Gem Version" />}[http://badge.fury.io/rb/susply]
4
5
  {<img src="https://codeclimate.com/github/wcpaez/susply/badges/gpa.svg" />}[https://codeclimate.com/github/wcpaez/susply]
5
6
  {<img src="https://codeclimate.com/github/wcpaez/susply/badges/coverage.svg" />}[https://codeclimate.com/github/wcpaez/susply/coverage]
6
7
 
@@ -1,4 +1,4 @@
1
1
  module Susply
2
- class ApplicationController < ActionController::Base
2
+ class ApplicationController < ::ApplicationController
3
3
  end
4
4
  end
@@ -0,0 +1,32 @@
1
+ require_dependency "susply/application_controller"
2
+
3
+ module Susply
4
+ class ChangePlansController < ApplicationController
5
+ def create
6
+ plan = Susply::Plan.find(params[:plan_id])
7
+ if current_owner.can_change_plan?(plan)
8
+ Susply::ChangeSubscription.call(current_owner, plan)
9
+ redirect_to after_change_plan_success_path,
10
+ alert: t('susply.messages.success_changed_plan')
11
+ else
12
+ redirect_to after_change_plan_fail_path,
13
+ alert: t('susply.messages.failed_changed_plan')
14
+ end
15
+ end
16
+
17
+ private
18
+ def current_owner
19
+ @current_owner ||= send(Susply.billable_entity)
20
+ end
21
+
22
+ def after_change_plan_fail_path
23
+ return super(@current_owner) if defined?(super)
24
+ susply.owner_path(@current_owner)
25
+ end
26
+
27
+ def after_change_plan_success_path
28
+ return super(@current_owner) if defined?(super)
29
+ susply.owner_path(@current_owner)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,37 @@
1
+ require_dependency "susply/application_controller"
2
+
3
+ module Susply
4
+ class RenovationsController < ApplicationController
5
+ before_filter :load_owner
6
+
7
+ def create
8
+ subscription = Susply::RenewsSubscription.call(@owner)
9
+ if subscription
10
+ redirect_to after_renovation_success_path,
11
+ notice: t('susply.messages.success_renovation')
12
+ else
13
+ redirect_to after_renovation_fail_path,
14
+ alert: t('susply.messages.failed_renovation')
15
+ end
16
+ end
17
+
18
+ private
19
+ def load_owner
20
+ unless params[:owner_id].nil?
21
+ searched_owner = Susply.subscription_owner_class.constantize.
22
+ find(params[:owner_id])
23
+ @owner = searched_owner
24
+ end
25
+ end
26
+
27
+ def after_renovation_fail_path
28
+ return super(@owner) if defined?(super)
29
+ susply.owner_path(@owner)
30
+ end
31
+
32
+ def after_renovation_success_path
33
+ return super(@owner) if defined?(super)
34
+ susply.owner_path(@owner)
35
+ end
36
+ end
37
+ end
@@ -19,5 +19,13 @@ module Susply
19
19
  def active?
20
20
  deactivated_at.nil?
21
21
  end
22
+
23
+ def expired?
24
+ current_period_end < Time.zone.now
25
+ end
26
+
27
+ def allowed_to_renew?
28
+ active? && expired?
29
+ end
22
30
  end
23
31
  end
@@ -1,10 +1,10 @@
1
1
  module Susply
2
2
  class RenewsSubscription
3
3
  def self.call(owner)
4
- if owner.has_active_subscription?
5
- subscription = owner.active_subscription
6
- Susply::CreatePayment.call(subscription, "plan_renovation")
7
- calculate_renewed_subscription(subscription)
4
+ active_subscription = owner.active_subscription
5
+ if active_subscription && active_subscription.expired?
6
+ Susply::CreatePayment.call(active_subscription, "plan_renovation")
7
+ calculate_renewed_subscription(active_subscription)
8
8
  else
9
9
  nil
10
10
  end
@@ -0,0 +1,8 @@
1
+ en:
2
+ susply:
3
+ messages:
4
+ failed_renovation: 'Failed renovation'
5
+ success_renovation: 'Success renovation'
6
+ failed_changed_plan: 'Failed change plan'
7
+ success_changed_plan: 'Success change plan'
8
+
@@ -1,2 +1,6 @@
1
1
  Susply::Engine.routes.draw do
2
+ resource :change_plan, only: [:create]
3
+ resources Susply.owner_resource, as: :owner, only: [:show] do
4
+ resources :renovations, only: [:create]
5
+ end
2
6
  end
@@ -9,12 +9,23 @@ module Susply
9
9
  @subscription_owner_model.capitalize
10
10
  end
11
11
 
12
+ def billable_entity
13
+ @subscription_owner_model.downcase
14
+ end
15
+
12
16
  def install
13
17
  template "config/initializers/susply.rb"
14
18
 
15
19
  inject_into_class "app/models/#{subscription_owner_model.downcase}.rb",
16
20
  subscription_owner_model.downcase.camelize.constantize,
17
21
  "# Added by Susply\n include Susply::OwnerMethods \n\n"
22
+
23
+ copy_locales
24
+ end
25
+
26
+ def copy_locales
27
+ copy_file "../../../config/locales/susply.en.yml",
28
+ "config/locales/susply.en.yml"
18
29
  end
19
30
  end
20
31
  end
@@ -1,3 +1,4 @@
1
1
  Susply.setup do |config|
2
2
  config.subscription_owner_class = "<%= subscription_owner_model %>"
3
+ config.billable_entity = "current_<%= billable_entity %>"
3
4
  end
@@ -3,8 +3,14 @@ require "decorators"
3
3
 
4
4
  module Susply
5
5
  mattr_accessor :subscription_owner_class
6
+ mattr_accessor :billable_entity
6
7
 
7
8
  def self.setup(&block)
8
9
  yield self
9
10
  end
11
+
12
+ #ejm :organizations
13
+ def self.owner_resource
14
+ subscription_owner_class.downcase.pluralize.to_sym
15
+ end
10
16
  end
@@ -1,3 +1,3 @@
1
1
  module Susply
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ module Susply
4
+ describe ChangePlansController, type: :controller do
5
+ let(:time) { Time.zone.now }
6
+
7
+ describe "#create" do
8
+ before do
9
+ @routes = Susply::Engine.routes
10
+ end
11
+
12
+ it "raises errors on not found plan" do
13
+ expect{
14
+ post :create, plan_id: 1
15
+ }.to raise_error(ActiveRecord::RecordNotFound)
16
+ end
17
+
18
+ it "raises errors when there is not a current billable entity" do
19
+ plan = create(:susply_plan)
20
+ expect{
21
+ post :create, plan_id: plan.id
22
+ }.to raise_error(NoMethodError)
23
+ end
24
+
25
+ context "when billable entity cannot change plan" do
26
+ before do
27
+ @owner = Organization.create
28
+
29
+ allow(@owner).to receive(:can_change_plan?).and_return(false)
30
+ allow_any_instance_of(ApplicationController).
31
+ to receive(:current_organization).and_return(@owner)
32
+
33
+ @plan = create(:susply_plan, sku: 'new_plan')
34
+ end
35
+
36
+ it "redirects to owner path by default" do
37
+ post :create, plan_id: @plan.id
38
+
39
+ expect(response).to redirect_to owner_path(@owner)
40
+ end
41
+
42
+ it "redirects to provided path when set" do
43
+ path = "/after_change_plan_fail"
44
+ allow_any_instance_of(ApplicationController).
45
+ to receive(:after_change_plan_fail_path).and_return(path)
46
+
47
+ post :create, plan_id: @plan.id
48
+ expect(response).to redirect_to path
49
+ end
50
+
51
+ it "sets the flash alert message" do
52
+ post :create, plan_id: @plan.id
53
+
54
+ expect(flash[:alert]).
55
+ to eq I18n.t('susply.messages.failed_changed_plan')
56
+ end
57
+ end
58
+
59
+ context "when billable entity change plan" do
60
+ before do
61
+ @owner = Organization.create
62
+ create(:susply_subscription, :active, owner: @owner)
63
+
64
+ allow(@owner).to receive(:can_change_plan?).and_return(true)
65
+ allow_any_instance_of(ApplicationController).
66
+ to receive(:current_organization).and_return(@owner)
67
+
68
+ @plan = create(:susply_plan, sku: 'new_plan')
69
+ end
70
+
71
+ it "redirects to owner path by default" do
72
+ post :create, plan_id: @plan.id
73
+
74
+ expect(response).to redirect_to owner_path(@owner)
75
+ end
76
+
77
+ it "redirects to provided path when set" do
78
+ path = "/after_change_plan_success"
79
+ allow_any_instance_of(ApplicationController).
80
+ to receive(:after_change_plan_success_path).and_return(path)
81
+
82
+ post :create, plan_id: @plan.id
83
+ expect(response).to redirect_to path
84
+ end
85
+
86
+ it "sets the flash alert message" do
87
+ post :create, plan_id: @plan.id
88
+
89
+ expect(flash[:alert]).
90
+ to eq I18n.t('susply.messages.success_changed_plan')
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,87 @@
1
+ require 'spec_helper'
2
+
3
+ module Susply
4
+ describe RenovationsController, type: :controller do
5
+ let(:time) { Time.zone.now }
6
+
7
+ describe "#create" do
8
+ before do
9
+ @routes = Susply::Engine.routes
10
+ end
11
+
12
+ it "raise an exception when no owner is finded" do
13
+ expect{
14
+ post :create, owner_id: 1
15
+ }.to raise_error()
16
+ end
17
+
18
+ it "sets the owner variable to the searched one" do
19
+ owner = Susply.subscription_owner_class.constantize.create
20
+ post :create, owner_id: owner.id
21
+
22
+ expect(assigns(:owner)).to eq owner
23
+ end
24
+
25
+ context "success response" do
26
+ it "redirects to owner path by default" do
27
+ owner = Susply.subscription_owner_class.constantize.create
28
+ create(:susply_subscription, :active, owner: owner,
29
+ current_period_end: time - 1.day)
30
+ post :create, owner_id: owner.id
31
+
32
+ expect(response).to redirect_to owner_path(owner)
33
+ end
34
+
35
+ it "redirects to provided path when set" do
36
+ path = "/new_after_success_path"
37
+ allow_any_instance_of(ApplicationController).
38
+ to receive(:after_renovation_success_path).and_return(path)
39
+ owner = Susply.subscription_owner_class.constantize.create
40
+ create(:susply_subscription, :active, owner: owner,
41
+ current_period_end: time - 1.day)
42
+ post :create, owner_id: owner.id
43
+
44
+ expect(response).to redirect_to path
45
+ end
46
+
47
+ it "sets the notice alert message" do
48
+ owner = Susply.subscription_owner_class.constantize.create
49
+ create(:susply_subscription, :active, owner: owner,
50
+ current_period_end: time - 1.day)
51
+ post :create, owner_id: owner.id
52
+
53
+ expect(flash[:notice]).
54
+ to eq I18n.t('susply.messages.success_renovation')
55
+ end
56
+ end
57
+
58
+ context "fail response" do
59
+ it "redirects to owner path by default" do
60
+ owner = Susply.subscription_owner_class.constantize.create
61
+ post :create, owner_id: owner.id
62
+
63
+ expect(response).to redirect_to owner_path(owner)
64
+ end
65
+
66
+ it "redirects to provided path when set" do
67
+ path = "/new_after_fail_path"
68
+ allow_any_instance_of(ApplicationController).
69
+ to receive(:after_renovation_fail_path).and_return(path)
70
+
71
+ owner = Susply.subscription_owner_class.constantize.create
72
+ post :create, owner_id: owner.id
73
+
74
+ expect(response).to redirect_to path
75
+ end
76
+
77
+ it "sets the alert flash message" do
78
+ owner = Susply.subscription_owner_class.constantize.create
79
+ post :create, owner_id: owner.id
80
+
81
+ expect(flash[:alert]).
82
+ to eq I18n.t('susply.messages.failed_renovation')
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,2 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,56 @@
1
+ body { background-color: #fff; color: #333; }
2
+
3
+ body, p, ol, ul, td {
4
+ font-family: verdana, arial, helvetica, sans-serif;
5
+ font-size: 13px;
6
+ line-height: 18px;
7
+ }
8
+
9
+ pre {
10
+ background-color: #eee;
11
+ padding: 10px;
12
+ font-size: 11px;
13
+ }
14
+
15
+ a { color: #000; }
16
+ a:visited { color: #666; }
17
+ a:hover { color: #fff; background-color:#000; }
18
+
19
+ div.field, div.actions {
20
+ margin-bottom: 10px;
21
+ }
22
+
23
+ #notice {
24
+ color: green;
25
+ }
26
+
27
+ .field_with_errors {
28
+ padding: 2px;
29
+ background-color: red;
30
+ display: table;
31
+ }
32
+
33
+ #error_explanation {
34
+ width: 450px;
35
+ border: 2px solid red;
36
+ padding: 7px;
37
+ padding-bottom: 0;
38
+ margin-bottom: 20px;
39
+ background-color: #f0f0f0;
40
+ }
41
+
42
+ #error_explanation h2 {
43
+ text-align: left;
44
+ font-weight: bold;
45
+ padding: 5px 5px 5px 15px;
46
+ font-size: 12px;
47
+ margin: -7px;
48
+ margin-bottom: 0px;
49
+ background-color: #c00;
50
+ color: #fff;
51
+ }
52
+
53
+ #error_explanation ul li {
54
+ font-size: 12px;
55
+ list-style: square;
56
+ }