susply 0.0.1
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +8 -0
- data/Rakefile +30 -0
- data/app/assets/javascripts/susply/application.js +13 -0
- data/app/assets/stylesheets/susply/application.css +15 -0
- data/app/controllers/susply/application_controller.rb +4 -0
- data/app/helpers/susply/application_helper.rb +4 -0
- data/app/models/susply/payment.rb +19 -0
- data/app/models/susply/plan.rb +16 -0
- data/app/models/susply/subscription.rb +23 -0
- data/app/services/susply/calculations.rb +15 -0
- data/app/services/susply/cancel_subscription.rb +11 -0
- data/app/services/susply/change_subscription.rb +14 -0
- data/app/services/susply/close_subscription.rb +10 -0
- data/app/services/susply/create_payment.rb +30 -0
- data/app/services/susply/create_subscription.rb +21 -0
- data/app/services/susply/owner_methods.rb +28 -0
- data/app/services/susply/prorate.rb +22 -0
- data/app/services/susply/renews_subscription.rb +25 -0
- data/app/views/layouts/susply/application.html.erb +14 -0
- data/config/initializers/susply.rb +3 -0
- data/config/routes.rb +2 -0
- data/db/migrate/20150513155547_create_susply_plans.rb +14 -0
- data/db/migrate/20150513161513_add_status_to_plans.rb +6 -0
- data/db/migrate/20150513180124_create_susply_subscriptions.rb +17 -0
- data/db/migrate/20150521222634_create_susply_payments.rb +19 -0
- data/lib/generators/susply/install_generator.rb +20 -0
- data/lib/generators/templates/config/initializers/susply.rb +3 -0
- data/lib/susply/engine.rb +24 -0
- data/lib/susply/version.rb +3 -0
- data/lib/susply.rb +10 -0
- data/lib/tasks/susply_tasks.rake +4 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/organization.rb +5 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config/application.rb +32 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/susply.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20150513183555_create_organizations.rb +11 -0
- data/spec/dummy/db/production.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +67 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +950 -0
- data/spec/dummy/log/test.log +40824 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/spec/factories/organizations.rb +8 -0
- data/spec/dummy/spec/models/organization_spec.rb +4 -0
- data/spec/factories/susply_payments.rb +13 -0
- data/spec/factories/susply_plans.rb +15 -0
- data/spec/factories/susply_subscriptions.rb +19 -0
- data/spec/models/susply/payment_spec.rb +135 -0
- data/spec/models/susply/plan_spec.rb +106 -0
- data/spec/models/susply/subscription_spec.rb +102 -0
- data/spec/services/susply/calculations_spec.rb +29 -0
- data/spec/services/susply/cancel_subscription_spec.rb +20 -0
- data/spec/services/susply/change_subscription_spec.rb +68 -0
- data/spec/services/susply/close_subscription_spec.rb +36 -0
- data/spec/services/susply/create_payment_spec.rb +84 -0
- data/spec/services/susply/create_subscription_spec.rb +22 -0
- data/spec/services/susply/owner_methods_spec.rb +99 -0
- data/spec/services/susply/prorate_spec.rb +92 -0
- data/spec/services/susply/renews_subscription_spec.rb +98 -0
- data/spec/spec_helper.rb +19 -0
- metadata +282 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>The page you were looking for doesn't exist (404)</title>
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
background-color: #EFEFEF;
|
|
9
|
+
color: #2E2F30;
|
|
10
|
+
text-align: center;
|
|
11
|
+
font-family: arial, sans-serif;
|
|
12
|
+
margin: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
div.dialog {
|
|
16
|
+
width: 95%;
|
|
17
|
+
max-width: 33em;
|
|
18
|
+
margin: 4em auto 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
div.dialog > div {
|
|
22
|
+
border: 1px solid #CCC;
|
|
23
|
+
border-right-color: #999;
|
|
24
|
+
border-left-color: #999;
|
|
25
|
+
border-bottom-color: #BBB;
|
|
26
|
+
border-top: #B00100 solid 4px;
|
|
27
|
+
border-top-left-radius: 9px;
|
|
28
|
+
border-top-right-radius: 9px;
|
|
29
|
+
background-color: white;
|
|
30
|
+
padding: 7px 12% 0;
|
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
h1 {
|
|
35
|
+
font-size: 100%;
|
|
36
|
+
color: #730E15;
|
|
37
|
+
line-height: 1.5em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
div.dialog > p {
|
|
41
|
+
margin: 0 0 1em;
|
|
42
|
+
padding: 1em;
|
|
43
|
+
background-color: #F7F7F7;
|
|
44
|
+
border: 1px solid #CCC;
|
|
45
|
+
border-right-color: #999;
|
|
46
|
+
border-left-color: #999;
|
|
47
|
+
border-bottom-color: #999;
|
|
48
|
+
border-bottom-left-radius: 4px;
|
|
49
|
+
border-bottom-right-radius: 4px;
|
|
50
|
+
border-top-color: #DADADA;
|
|
51
|
+
color: #666;
|
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
</head>
|
|
56
|
+
|
|
57
|
+
<body>
|
|
58
|
+
<!-- This file lives in public/404.html -->
|
|
59
|
+
<div class="dialog">
|
|
60
|
+
<div>
|
|
61
|
+
<h1>The page you were looking for doesn't exist.</h1>
|
|
62
|
+
<p>You may have mistyped the address or the page may have moved.</p>
|
|
63
|
+
</div>
|
|
64
|
+
<p>If you are the application owner check the logs for more information.</p>
|
|
65
|
+
</div>
|
|
66
|
+
</body>
|
|
67
|
+
</html>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>The change you wanted was rejected (422)</title>
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
background-color: #EFEFEF;
|
|
9
|
+
color: #2E2F30;
|
|
10
|
+
text-align: center;
|
|
11
|
+
font-family: arial, sans-serif;
|
|
12
|
+
margin: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
div.dialog {
|
|
16
|
+
width: 95%;
|
|
17
|
+
max-width: 33em;
|
|
18
|
+
margin: 4em auto 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
div.dialog > div {
|
|
22
|
+
border: 1px solid #CCC;
|
|
23
|
+
border-right-color: #999;
|
|
24
|
+
border-left-color: #999;
|
|
25
|
+
border-bottom-color: #BBB;
|
|
26
|
+
border-top: #B00100 solid 4px;
|
|
27
|
+
border-top-left-radius: 9px;
|
|
28
|
+
border-top-right-radius: 9px;
|
|
29
|
+
background-color: white;
|
|
30
|
+
padding: 7px 12% 0;
|
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
h1 {
|
|
35
|
+
font-size: 100%;
|
|
36
|
+
color: #730E15;
|
|
37
|
+
line-height: 1.5em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
div.dialog > p {
|
|
41
|
+
margin: 0 0 1em;
|
|
42
|
+
padding: 1em;
|
|
43
|
+
background-color: #F7F7F7;
|
|
44
|
+
border: 1px solid #CCC;
|
|
45
|
+
border-right-color: #999;
|
|
46
|
+
border-left-color: #999;
|
|
47
|
+
border-bottom-color: #999;
|
|
48
|
+
border-bottom-left-radius: 4px;
|
|
49
|
+
border-bottom-right-radius: 4px;
|
|
50
|
+
border-top-color: #DADADA;
|
|
51
|
+
color: #666;
|
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
</head>
|
|
56
|
+
|
|
57
|
+
<body>
|
|
58
|
+
<!-- This file lives in public/422.html -->
|
|
59
|
+
<div class="dialog">
|
|
60
|
+
<div>
|
|
61
|
+
<h1>The change you wanted was rejected.</h1>
|
|
62
|
+
<p>Maybe you tried to change something you didn't have access to.</p>
|
|
63
|
+
</div>
|
|
64
|
+
<p>If you are the application owner check the logs for more information.</p>
|
|
65
|
+
</div>
|
|
66
|
+
</body>
|
|
67
|
+
</html>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<style>
|
|
7
|
+
body {
|
|
8
|
+
background-color: #EFEFEF;
|
|
9
|
+
color: #2E2F30;
|
|
10
|
+
text-align: center;
|
|
11
|
+
font-family: arial, sans-serif;
|
|
12
|
+
margin: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
div.dialog {
|
|
16
|
+
width: 95%;
|
|
17
|
+
max-width: 33em;
|
|
18
|
+
margin: 4em auto 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
div.dialog > div {
|
|
22
|
+
border: 1px solid #CCC;
|
|
23
|
+
border-right-color: #999;
|
|
24
|
+
border-left-color: #999;
|
|
25
|
+
border-bottom-color: #BBB;
|
|
26
|
+
border-top: #B00100 solid 4px;
|
|
27
|
+
border-top-left-radius: 9px;
|
|
28
|
+
border-top-right-radius: 9px;
|
|
29
|
+
background-color: white;
|
|
30
|
+
padding: 7px 12% 0;
|
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
h1 {
|
|
35
|
+
font-size: 100%;
|
|
36
|
+
color: #730E15;
|
|
37
|
+
line-height: 1.5em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
div.dialog > p {
|
|
41
|
+
margin: 0 0 1em;
|
|
42
|
+
padding: 1em;
|
|
43
|
+
background-color: #F7F7F7;
|
|
44
|
+
border: 1px solid #CCC;
|
|
45
|
+
border-right-color: #999;
|
|
46
|
+
border-left-color: #999;
|
|
47
|
+
border-bottom-color: #999;
|
|
48
|
+
border-bottom-left-radius: 4px;
|
|
49
|
+
border-bottom-right-radius: 4px;
|
|
50
|
+
border-top-color: #DADADA;
|
|
51
|
+
color: #666;
|
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
</head>
|
|
56
|
+
|
|
57
|
+
<body>
|
|
58
|
+
<!-- This file lives in public/500.html -->
|
|
59
|
+
<div class="dialog">
|
|
60
|
+
<div>
|
|
61
|
+
<h1>We're sorry, but something went wrong.</h1>
|
|
62
|
+
</div>
|
|
63
|
+
<p>If you are the application owner check the logs for more information.</p>
|
|
64
|
+
</div>
|
|
65
|
+
</body>
|
|
66
|
+
</html>
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
FactoryGirl.define do
|
|
2
|
+
factory :susply_payment, :class => 'Susply::Payment' do
|
|
3
|
+
owner_id 1
|
|
4
|
+
plan_id 1
|
|
5
|
+
subscription_id 1
|
|
6
|
+
amount 1
|
|
7
|
+
period_start "2015-05-21 17:26:35"
|
|
8
|
+
period_end "2015-05-21 17:26:35"
|
|
9
|
+
status "generated"
|
|
10
|
+
invoice "MyString"
|
|
11
|
+
generated_type "plan_renovation"
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
FactoryGirl.define do
|
|
2
|
+
factory :susply_plan, :class => 'Susply::Plan' do
|
|
3
|
+
sequence :sku do |n|
|
|
4
|
+
"basic-plan-#{n}"
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
name "Principal basic Plan"
|
|
8
|
+
description "Long price subscription"
|
|
9
|
+
price 1
|
|
10
|
+
interval "monthly"
|
|
11
|
+
highlight false
|
|
12
|
+
active false
|
|
13
|
+
published false
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
FactoryGirl.define do
|
|
2
|
+
factory :susply_subscription, :class => 'Susply::Subscription' do
|
|
3
|
+
trait :inactive do
|
|
4
|
+
deactivated_at Time.zone.now
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
trait :active do
|
|
8
|
+
deactivated_at nil
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
owner_id 1
|
|
12
|
+
association :plan, factory: :susply_plan
|
|
13
|
+
start "2015-05-13 13:01:24"
|
|
14
|
+
current_period_start "2015-05-13 13:01:24"
|
|
15
|
+
current_period_end "2015-05-13 13:01:24"
|
|
16
|
+
quantity 1
|
|
17
|
+
deactivated_at nil
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Susply
|
|
4
|
+
describe Payment, type: :model do
|
|
5
|
+
it "shoulda validate" do
|
|
6
|
+
payment = build(:susply_payment)
|
|
7
|
+
expect(payment).to be_valid
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "belogs to owner" do
|
|
11
|
+
a = Susply::Payment.reflect_on_association(:owner)
|
|
12
|
+
expect(a.macro).to eq :belongs_to
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "sets to owner the class on susply initializer" do
|
|
16
|
+
a = Susply::Payment.reflect_on_association(:owner)
|
|
17
|
+
expect(a.options[:class_name]).to eq Susply.subscription_owner_class
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "belongs to plan" do
|
|
21
|
+
a = Susply::Payment.reflect_on_association(:plan)
|
|
22
|
+
expect(a.macro).to eq :belongs_to
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "sets the plan class on susply" do
|
|
26
|
+
a = Susply::Payment.reflect_on_association(:plan)
|
|
27
|
+
expect(a.options[:class_name]).to eq 'Susply::Plan'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "belongs to subscription" do
|
|
31
|
+
a = Susply::Payment.reflect_on_association(:subscription)
|
|
32
|
+
expect(a.macro).to eq :belongs_to
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "sets the subscription class on susply" do
|
|
36
|
+
a = Susply::Payment.reflect_on_association(:subscription)
|
|
37
|
+
expect(a.options[:class_name]).to eq 'Susply::Subscription'
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "validates presence of owner_id" do
|
|
41
|
+
payment = build(:susply_payment, owner_id: nil)
|
|
42
|
+
expect(payment).not_to be_valid
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it "validates presence of plan_id" do
|
|
46
|
+
payment = build(:susply_payment, plan_id: nil)
|
|
47
|
+
expect(payment).not_to be_valid
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "validates presence of subscription_id" do
|
|
51
|
+
payment = build(:susply_payment, subscription_id: nil)
|
|
52
|
+
expect(payment).not_to be_valid
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "validates presence of period_start" do
|
|
56
|
+
payment = build(:susply_payment, period_start: nil)
|
|
57
|
+
expect(payment).not_to be_valid
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "validates presence of period_end" do
|
|
61
|
+
payment = build(:susply_payment, period_end: nil)
|
|
62
|
+
expect(payment).not_to be_valid
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "validates presence of status" do
|
|
66
|
+
payment = build(:susply_payment, status: nil)
|
|
67
|
+
expect(payment).not_to be_valid
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it "validates presence of amount" do
|
|
71
|
+
payment = build(:susply_payment, amount: nil)
|
|
72
|
+
expect(payment).not_to be_valid
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should validates amount is an integer" do
|
|
76
|
+
payment = build(:susply_payment, amount: 12.2)
|
|
77
|
+
expect(payment).not_to be_valid
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should validates amount equal to 0" do
|
|
81
|
+
payment = build(:susply_payment, amount: 0)
|
|
82
|
+
expect(payment).to be_valid
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should validates amount greater to 0" do
|
|
86
|
+
payment = build(:susply_payment, amount: 10)
|
|
87
|
+
expect(payment).to be_valid
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "should validates inclusion of generated_type" do
|
|
91
|
+
payments = [
|
|
92
|
+
build(:susply_payment, generated_type: 'plan_renovation'),
|
|
93
|
+
build(:susply_payment, generated_type: 'plan_change'),
|
|
94
|
+
build(:susply_payment, generated_type: 'plan_close'),
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
not_payments = [
|
|
98
|
+
build(:susply_payment, generated_type: 'invalid'),
|
|
99
|
+
build(:susply_payment, generated_type: 'not-valid'),
|
|
100
|
+
build(:susply_payment, generated_type: 'sopo'),
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
payments.each do |payment|
|
|
104
|
+
expect(payment).to be_valid
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
not_payments.each do |payment|
|
|
108
|
+
expect(payment).not_to be_valid
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
it "should validates inclusion of status" do
|
|
113
|
+
payments = [
|
|
114
|
+
build(:susply_payment, status: 'generated'),
|
|
115
|
+
build(:susply_payment, status: 'paid'),
|
|
116
|
+
build(:susply_payment, status: 'exonerated'),
|
|
117
|
+
build(:susply_payment, status: 'refunded')
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
not_payments = [
|
|
121
|
+
build(:susply_payment, status: 'geneted'),
|
|
122
|
+
build(:susply_payment, status: 'pad'),
|
|
123
|
+
build(:susply_payment, status: 'exated')
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
payments.each do |payment|
|
|
127
|
+
expect(payment).to be_valid
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
not_payments.each do |payment|
|
|
131
|
+
expect(payment).not_to be_valid
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Susply
|
|
4
|
+
describe Plan, type: :model do
|
|
5
|
+
describe "validations" do
|
|
6
|
+
it "should validate" do
|
|
7
|
+
plan = build(:susply_plan)
|
|
8
|
+
expect(plan).to be_valid
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should validates sku presence" do
|
|
12
|
+
plan = build(:susply_plan, sku: nil)
|
|
13
|
+
expect(plan).not_to be_valid
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should validates sku uniqueness" do
|
|
17
|
+
p1 = create(:susply_plan, sku: 'plan-du')
|
|
18
|
+
p2 = build(:susply_plan, sku: 'pLan-du')
|
|
19
|
+
expect(p2).not_to be_valid
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should validates presence of name" do
|
|
23
|
+
plan = build(:susply_plan, name: nil)
|
|
24
|
+
expect(plan).not_to be_valid
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should validates presence of description" do
|
|
28
|
+
plan = build(:susply_plan, description: nil)
|
|
29
|
+
expect(plan).not_to be_valid
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should validates price is an integer" do
|
|
33
|
+
plan = build(:susply_plan, price: 12.2)
|
|
34
|
+
expect(plan).not_to be_valid
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should validates price is equal to 0" do
|
|
38
|
+
plan = build(:susply_plan, price: 0)
|
|
39
|
+
expect(plan).to be_valid
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should validates price is less than 0" do
|
|
43
|
+
plan = build(:susply_plan, price: -1)
|
|
44
|
+
expect(plan).not_to be_valid
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "validates interval on montly or yearly" do
|
|
48
|
+
p1 = build(:susply_plan, interval: "wop")
|
|
49
|
+
p2 = build(:susply_plan, interval: "monthly")
|
|
50
|
+
p3 = build(:susply_plan, interval: "yearly")
|
|
51
|
+
|
|
52
|
+
expect(p1).not_to be_valid
|
|
53
|
+
expect(p2).to be_valid
|
|
54
|
+
expect(p3).to be_valid
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "validates highlight inclusion" do
|
|
58
|
+
p1 = build(:susply_plan, highlight: nil)
|
|
59
|
+
p2 = build(:susply_plan, highlight: true)
|
|
60
|
+
p3 = build(:susply_plan, highlight: false)
|
|
61
|
+
|
|
62
|
+
expect(p1).not_to be_valid
|
|
63
|
+
expect(p2).to be_valid
|
|
64
|
+
expect(p3).to be_valid
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "validates status inclusion" do
|
|
68
|
+
p1 = build(:susply_plan, active: nil)
|
|
69
|
+
p2 = build(:susply_plan, active: true)
|
|
70
|
+
p3 = build(:susply_plan, active: false)
|
|
71
|
+
|
|
72
|
+
expect(p1).not_to be_valid
|
|
73
|
+
expect(p2).to be_valid
|
|
74
|
+
expect(p3).to be_valid
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "validates publishdd inclusion" do
|
|
78
|
+
p1 = build(:susply_plan, published: nil)
|
|
79
|
+
p2 = build(:susply_plan, published: true)
|
|
80
|
+
p3 = build(:susply_plan, published: false)
|
|
81
|
+
|
|
82
|
+
expect(p1).not_to be_valid
|
|
83
|
+
expect(p2).to be_valid
|
|
84
|
+
expect(p3).to be_valid
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe ".actives" do
|
|
89
|
+
it "returns only plans where status is true" do
|
|
90
|
+
list = create_list(:susply_plan, 2, active: true)
|
|
91
|
+
not_in_list = create(:susply_plan, active: false)
|
|
92
|
+
|
|
93
|
+
expect(Susply::Plan.actives).to match_array list
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
describe ".published" do
|
|
98
|
+
it "returns only plans than can be published" do
|
|
99
|
+
list = create_list(:susply_plan, 2, published: true)
|
|
100
|
+
not_in_list = create(:susply_plan, published: false)
|
|
101
|
+
|
|
102
|
+
expect(Susply::Plan.published).to match_array list
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Susply
|
|
4
|
+
describe Subscription, type: :model do
|
|
5
|
+
describe "validations" do
|
|
6
|
+
it "shoulda validate" do
|
|
7
|
+
subscription = build(:susply_subscription)
|
|
8
|
+
expect(subscription).to be_valid
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "belogs to owner" do
|
|
12
|
+
a = Susply::Subscription.reflect_on_association(:owner)
|
|
13
|
+
expect(a.macro).to eq :belongs_to
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "sets to owner the class on susply initializer" do
|
|
17
|
+
a = Susply::Subscription.reflect_on_association(:owner)
|
|
18
|
+
expect(a.options[:class_name]).to eq Susply.subscription_owner_class
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "belongs to plan" do
|
|
22
|
+
a = Susply::Subscription.reflect_on_association(:plan)
|
|
23
|
+
expect(a.macro).to eq :belongs_to
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "sets the plan class on susply" do
|
|
27
|
+
a = Susply::Subscription.reflect_on_association(:plan)
|
|
28
|
+
expect(a.options[:class_name]).to eq 'Susply::Plan'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "validates presence of owner_id" do
|
|
32
|
+
subscription = build(:susply_subscription, owner_id: nil)
|
|
33
|
+
expect(subscription).not_to be_valid
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "validates presence of plan_id" do
|
|
37
|
+
subscription = build(:susply_subscription, plan_id: nil)
|
|
38
|
+
expect(subscription).not_to be_valid
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "validates presence of start" do
|
|
42
|
+
subscription = build(:susply_subscription, start: nil)
|
|
43
|
+
expect(subscription).not_to be_valid
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "validates presence of current period start" do
|
|
47
|
+
subscription = build(:susply_subscription, current_period_start: nil)
|
|
48
|
+
expect(subscription).not_to be_valid
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "validates presence of current_period_end" do
|
|
52
|
+
subscription = build(:susply_subscription, current_period_end: nil)
|
|
53
|
+
expect(subscription).not_to be_valid
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should validates quantity is an integer" do
|
|
57
|
+
subscription = build(:susply_subscription, quantity: 12.2)
|
|
58
|
+
expect(subscription).not_to be_valid
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "should validates price is greater than 0" do
|
|
62
|
+
subscription = build(:susply_subscription, quantity: 0)
|
|
63
|
+
expect(subscription).not_to be_valid
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe "#name" do
|
|
68
|
+
it "returns plan name" do
|
|
69
|
+
name = 'Basic plan'
|
|
70
|
+
plan = create(:susply_plan, name: name)
|
|
71
|
+
subscription = build(:susply_subscription, plan: plan)
|
|
72
|
+
|
|
73
|
+
expect(subscription.name).to eq name
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "#price" do
|
|
78
|
+
it "returns plan price" do
|
|
79
|
+
price = 5
|
|
80
|
+
plan = create(:susply_plan, price: price)
|
|
81
|
+
subscription = build(:susply_subscription, plan: plan)
|
|
82
|
+
|
|
83
|
+
expect(subscription.price).to eq price
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe "#active?" do
|
|
88
|
+
it "returns true when deactivated at is not present" do
|
|
89
|
+
subscription = build(:susply_subscription, deactivated_at: nil)
|
|
90
|
+
|
|
91
|
+
expect(subscription.active?).to eq true
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "returns false when deactivated at is present" do
|
|
95
|
+
subscription = build(:susply_subscription,
|
|
96
|
+
deactivated_at: Time.zone.now)
|
|
97
|
+
|
|
98
|
+
expect(subscription.active?).to eq false
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Susply
|
|
4
|
+
describe Calculations do
|
|
5
|
+
let(:start) { Time.zone.now }
|
|
6
|
+
describe ".end_period_calculation" do
|
|
7
|
+
it "returns one year when plan interval is yearly" do
|
|
8
|
+
interval = 'yearly'
|
|
9
|
+
result = Susply::Calculations.end_period_calculation(start, interval)
|
|
10
|
+
|
|
11
|
+
expect(result).to eq(start + 1.year)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it "returns one month when plan interval is monthly" do
|
|
15
|
+
interval = 'monthly'
|
|
16
|
+
result = Susply::Calculations.end_period_calculation(start, interval)
|
|
17
|
+
|
|
18
|
+
expect(result).to eq(start + 1.month)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "returns one month when there is not register interval" do
|
|
22
|
+
interval = 'not-registered-interval'
|
|
23
|
+
result = Susply::Calculations.end_period_calculation(start, interval)
|
|
24
|
+
|
|
25
|
+
expect(result).to eq(start + 1.month)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module Susply
|
|
4
|
+
describe CancelSubscription do
|
|
5
|
+
it "updates deactivated at with the current time" do
|
|
6
|
+
subscription = create(:susply_subscription, deactivated_at: nil)
|
|
7
|
+
s = Susply::CancelSubscription.call(subscription)
|
|
8
|
+
|
|
9
|
+
expect(s.deactivated_at).to be_within(1.second).of(Time.zone.now)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "does not updates deactivated at when its already cancelled" do
|
|
13
|
+
time = Time.zone.now - 3.days
|
|
14
|
+
subscription = create(:susply_subscription, deactivated_at: time)
|
|
15
|
+
s = Susply::CancelSubscription.call(subscription)
|
|
16
|
+
|
|
17
|
+
expect(s.deactivated_at).to eq time
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|