zillion 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/lib/zillion/plan.rb +16 -13
- data/spec/plans_spec.rb +39 -7
- data/zillion.gemspec +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: aa5e49662e1f608430f15149830de87cf410c8ff6fbcfdfb815b43a58224345c
|
4
|
+
data.tar.gz: d3a5d3476423dcf3c8bd35e7f22aefc6709f0d6134792cb1e6c465fdf97de466
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 698359ad81c9ba5a1af1b450fef3472c6b56bf41890f5a0f8d0c63d73e17d299c9d03b096bf2899e268c57b8735fb8bcf7066e87b90ebe01991207b7ba9c7f68
|
7
|
+
data.tar.gz: 9571b0b84a001b4139cf1566add53fc8847f2d6dd3c263f5d1ed825312c8d566536344dc76febc17ede68a0f2e635d30c93107bdb97cc578404ea2717cc36f20
|
data/lib/zillion/plan.rb
CHANGED
@@ -58,13 +58,13 @@ class Plan
|
|
58
58
|
self.monthly_fee <=> other_plan.monthly_fee
|
59
59
|
end
|
60
60
|
|
61
|
-
def amounts_for(counts)
|
62
|
-
{ monthly_fee: monthly_fee }
|
61
|
+
def amounts_for(counts, custom_monthly_fee: nil, fallback: false)
|
62
|
+
{ monthly_fee: custom_monthly_fee.nil? ? monthly_fee : custom_monthly_fee }
|
63
63
|
end
|
64
64
|
|
65
|
-
def monthly_fee_for(counts)
|
65
|
+
def monthly_fee_for(counts, custom_monthly_fee: nil)
|
66
66
|
ensure_available!(counts)
|
67
|
-
sum(amounts_for(counts))
|
67
|
+
sum(amounts_for(counts, custom_monthly_fee: custom_monthly_fee))
|
68
68
|
end
|
69
69
|
|
70
70
|
def available_for?(counts)
|
@@ -125,7 +125,8 @@ end
|
|
125
125
|
|
126
126
|
class TieredPlan < Plan
|
127
127
|
|
128
|
-
def amounts_for(counts)
|
128
|
+
def amounts_for(counts, custom_monthly_fee: nil, fallback: false)
|
129
|
+
raise "Tiered plans don't have fixed monthly fees! (Use FixedTieredPlan for that)" if custom_monthly_fee
|
129
130
|
tier = matching_tier_for(counts)
|
130
131
|
obj = {}
|
131
132
|
obj[tier.last.to_sym] = tier[1] # tier[1] is monthly cost
|
@@ -181,13 +182,13 @@ class TieredPlan < Plan
|
|
181
182
|
end
|
182
183
|
end
|
183
184
|
|
184
|
-
def matching_tiers_for(counts,
|
185
|
+
def matching_tiers_for(counts, fallback: false)
|
185
186
|
tier_groups.map do |key, tiers|
|
186
187
|
units = counts[key] or raise MissingCountError.new("Unit count required for #{key}")
|
187
188
|
begin
|
188
189
|
find_tier_for(tiers, units.to_i) + [key]
|
189
190
|
rescue TierNotFoundError
|
190
|
-
raise unless
|
191
|
+
raise unless fallback # to highest tier
|
191
192
|
last_existing_tier_for(key)
|
192
193
|
end
|
193
194
|
end.compact
|
@@ -201,9 +202,11 @@ end
|
|
201
202
|
|
202
203
|
class MeteredPlan < TieredPlan
|
203
204
|
|
204
|
-
def amounts_for(counts,
|
205
|
+
def amounts_for(counts, custom_monthly_fee: nil, fallback: false)
|
206
|
+
# raise "Tiered plans don't have fixed monthly fees! (Use FixedTieredPlan for that)" if custom_monthly_fee
|
207
|
+
|
205
208
|
obj = {}
|
206
|
-
matching_tiers_for(counts,
|
209
|
+
matching_tiers_for(counts, fallback: fallback).map do |tier|
|
207
210
|
units = units_for(tier.last, counts)
|
208
211
|
obj[tier.last.to_sym] = units * tier[1] # tier[1] is monthly unit cost
|
209
212
|
end
|
@@ -228,9 +231,9 @@ class FixedMeteredPlan < MeteredPlan
|
|
228
231
|
spec[:monthly_fee] ? spec[:monthly_fee].to_f : 0
|
229
232
|
end
|
230
233
|
|
231
|
-
def amounts_for(counts,
|
234
|
+
def amounts_for(counts, custom_monthly_fee: nil, fallback: false)
|
232
235
|
obj = super
|
233
|
-
obj[:base_fee] = base_fee
|
236
|
+
obj[:base_fee] = custom_monthly_fee.nil? ? base_fee : custom_monthly_fee
|
234
237
|
obj
|
235
238
|
end
|
236
239
|
|
@@ -275,7 +278,7 @@ class FixedMeteredPlan < MeteredPlan
|
|
275
278
|
:monthly_unit_cost
|
276
279
|
end
|
277
280
|
|
278
|
-
def matching_tiers_for(counts,
|
281
|
+
def matching_tiers_for(counts, fallback: false)
|
279
282
|
tier_groups.map do |key, tiers|
|
280
283
|
units = counts[key] or raise MissingCountError.new("Unit count required for #{key}")
|
281
284
|
next if limits[key] and limits[key] >= units.to_i
|
@@ -283,7 +286,7 @@ class FixedMeteredPlan < MeteredPlan
|
|
283
286
|
begin
|
284
287
|
find_tier_for(tiers, units.to_i) + [key]
|
285
288
|
rescue TierNotFoundError
|
286
|
-
raise unless
|
289
|
+
raise unless fallback # to_highest_tier
|
287
290
|
last_existing_tier_for(key)
|
288
291
|
end
|
289
292
|
end.compact
|
data/spec/plans_spec.rb
CHANGED
@@ -138,6 +138,10 @@ describe 'FixedPlan' do
|
|
138
138
|
expect(other.monthly_fee_for({ bananas: 10 })).to eql(10.0)
|
139
139
|
end
|
140
140
|
|
141
|
+
it 'uses custom_monthly_fee if passed' do
|
142
|
+
expect(plan.monthly_fee_for({ apples: 10 }, custom_monthly_fee: 20)).to eql(20)
|
143
|
+
end
|
144
|
+
|
141
145
|
it 'raises if not within limits' do
|
142
146
|
other = FixedPlan.new(monthly_fee: 10, limits: { bananas: 10 })
|
143
147
|
expect { other.monthly_fee_for({ bananas: 11 }) }.to raise_error(Zillion::Plan::OverLimitsError)
|
@@ -212,6 +216,10 @@ describe 'TieredPlan', 'Single tier' do
|
|
212
216
|
expect(plan.monthly_fee_for({ bananas: 5, products: 25 })).to eql(20)
|
213
217
|
end
|
214
218
|
|
219
|
+
it 'raises if custom_monthly_fee passed (because these plans dont have one)' do
|
220
|
+
expect { plan.monthly_fee_for({ bananas: 5, products: 25 }, custom_monthly_fee: 5) }.to raise_error
|
221
|
+
end
|
222
|
+
|
215
223
|
end
|
216
224
|
|
217
225
|
end
|
@@ -279,6 +287,10 @@ describe 'TieredPlan', 'Multiple tiers' do
|
|
279
287
|
expect(plan.monthly_fee_for({ bananas: 1, orders: 5, products: 25 })).to eql(20)
|
280
288
|
end
|
281
289
|
|
290
|
+
it 'raises if custom_monthly_fee passed (because these plans dont have one)' do
|
291
|
+
expect { plan.monthly_fee_for({ bananas: 1, orders: 5, products: 25 }, custom_monthly_fee: 100) }.to raise_error
|
292
|
+
end
|
293
|
+
|
282
294
|
end
|
283
295
|
|
284
296
|
end
|
@@ -342,6 +354,10 @@ describe 'MeteredPlan', 'Single tier' do
|
|
342
354
|
expect(plan.monthly_fee_for({ bananas: 5, products: 25 })).to eql(50)
|
343
355
|
end
|
344
356
|
|
357
|
+
xit 'raises if custom_monthly_fee passed (because these plans dont have one)' do
|
358
|
+
expect { plan.monthly_fee_for({ bananas: 5, products: 25 }, custom_monthly_fee: 100) }.to raise_error
|
359
|
+
end
|
360
|
+
|
345
361
|
end
|
346
362
|
|
347
363
|
describe '#amounts_for(counts)' do
|
@@ -363,14 +379,18 @@ describe 'MeteredPlan', 'Single tier' do
|
|
363
379
|
end
|
364
380
|
|
365
381
|
it 'doesnt raise if not within limits but second arg is true' do
|
366
|
-
expect { plan.amounts_for({ products: 250 }, true) }.not_to raise_error(Zillion::Plan::TierNotFoundError)
|
367
|
-
expect(plan.amounts_for({ products: 250 }, true)).to eql({ products: 375.0 })
|
382
|
+
expect { plan.amounts_for({ products: 250 }, fallback: true) }.not_to raise_error(Zillion::Plan::TierNotFoundError)
|
383
|
+
expect(plan.amounts_for({ products: 250 }, fallback: true)).to eql({ products: 375.0 })
|
368
384
|
end
|
369
385
|
|
370
386
|
it 'returns amounts if within limits' do
|
371
387
|
expect(plan.amounts_for({ bananas: 5, products: 25 })).to eql({ products: 50 })
|
372
388
|
end
|
373
389
|
|
390
|
+
xit 'raises if custom_monthly_fee passed (because these plans dont have one)' do
|
391
|
+
expect { plan.amounts_for({ bananas: 5, products: 25 }, custom_monthly_fee: 100) }.to raise_error
|
392
|
+
end
|
393
|
+
|
374
394
|
end
|
375
395
|
|
376
396
|
end
|
@@ -460,8 +480,8 @@ describe 'MeteredPlan', 'Multiple tiers' do
|
|
460
480
|
end
|
461
481
|
|
462
482
|
it 'doesnt raise if not within limits but second arg is true' do
|
463
|
-
expect { plan.amounts_for({ products: 250, orders: 5 }, true) }.not_to raise_error(Zillion::Plan::TierNotFoundError)
|
464
|
-
expect(plan.amounts_for({ products: 250, orders: 5 }, true)).to eql({ orders: 15, products: 375.0 })
|
483
|
+
expect { plan.amounts_for({ products: 250, orders: 5 }, fallback: true) }.not_to raise_error(Zillion::Plan::TierNotFoundError)
|
484
|
+
expect(plan.amounts_for({ products: 250, orders: 5 }, fallback: true)).to eql({ orders: 15, products: 375.0 })
|
465
485
|
end
|
466
486
|
|
467
487
|
it 'returns amounts if within limits' do
|
@@ -472,6 +492,10 @@ describe 'MeteredPlan', 'Multiple tiers' do
|
|
472
492
|
expect(plan.amounts_for({ bananas: 5, products: 25, orders: 1 })).to eql({ orders: 3, products: 50 })
|
473
493
|
end
|
474
494
|
|
495
|
+
xit 'raises if custom_monthly_fee passed (because these plans dont have one)' do
|
496
|
+
expect { plan.amounts_for({ bananas: 5, products: 25, orders: 1 }, custom_monthly_fee: 100) }.to raise_error
|
497
|
+
end
|
498
|
+
|
475
499
|
end
|
476
500
|
|
477
501
|
end
|
@@ -574,9 +598,13 @@ describe 'FixedMeteredPlan' do
|
|
574
598
|
expect(plan.monthly_fee_for({ bananas: 5, orders: 15, products: 25 })).to eql(55.0)
|
575
599
|
end
|
576
600
|
|
577
|
-
|
601
|
+
it 'uses custom_monthly_fee if passed' do
|
602
|
+
expect(plan.monthly_fee_for({ bananas: 5, orders: 15, products: 25 }, custom_monthly_fee: 100)).to eql(145)
|
603
|
+
end
|
578
604
|
|
579
605
|
|
606
|
+
end
|
607
|
+
|
580
608
|
describe '#amounts_for(counts)' do
|
581
609
|
|
582
610
|
it 'raises if missing unit for tier' do
|
@@ -592,8 +620,8 @@ describe 'FixedMeteredPlan' do
|
|
592
620
|
end
|
593
621
|
|
594
622
|
it 'doest raises if over limits but second arg is true' do
|
595
|
-
expect { plan.amounts_for({ orders: 1000, products: 5 }, true) }.not_to raise_error(Zillion::Plan::TierNotFoundError)
|
596
|
-
expect(plan.amounts_for({ orders: 1000, products: 5 }, true)).to eql({ orders: 990, base_fee: 10.0 })
|
623
|
+
expect { plan.amounts_for({ orders: 1000, products: 5 }, fallback: true) }.not_to raise_error(Zillion::Plan::TierNotFoundError)
|
624
|
+
expect(plan.amounts_for({ orders: 1000, products: 5 }, fallback: true)).to eql({ orders: 990, base_fee: 10.0 })
|
597
625
|
end
|
598
626
|
|
599
627
|
it 'doesnt explode if negative key for tiered count, but under fixed limit' do
|
@@ -616,6 +644,10 @@ describe 'FixedMeteredPlan' do
|
|
616
644
|
expect(plan.amounts_for({ bananas: 5, orders: 15, products: 25 })).to eql({:orders=>15, :products=>30, :base_fee=>10.0})
|
617
645
|
end
|
618
646
|
|
647
|
+
it 'uses custom_monthly_fee if passed' do
|
648
|
+
expect(plan.amounts_for({ bananas: 5, orders: 15, products: 25 }, custom_monthly_fee: 100)).to eql({:orders=>15, :products=>30, :base_fee=>100})
|
649
|
+
end
|
650
|
+
|
619
651
|
end
|
620
652
|
|
621
653
|
end
|
data/zillion.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zillion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomás Pollak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -78,7 +78,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
78
|
version: 1.3.6
|
79
79
|
requirements: []
|
80
80
|
rubyforge_project:
|
81
|
-
rubygems_version: 2.
|
81
|
+
rubygems_version: 2.7.3
|
82
82
|
signing_key:
|
83
83
|
specification_version: 4
|
84
84
|
summary: A model for SaaS plans with fixed, tiered and metered pricing.
|