susply 0.0.1 → 0.0.2

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