Detailed changes
@@ -81,18 +81,10 @@
}
, simpleswap_api_key : Text
, sims :
- { CAD : { per_gb : Natural }
- , USD : { per_gb : Natural }
- , esim :
- List
- { mapKey : < CAD | USD >
- , mapValue : { plan : Text, price : Natural }
- }
- , sim :
- List
- { mapKey : < CAD | USD >
- , mapValue : { plan : Text, price : Natural }
- }
+ { annual : { CAD : Natural, USD : Natural }
+ , esim : { CAD : Natural, USD : Natural }
+ , per_gb : { CAD : Natural, USD : Natural }
+ , sim : { CAD : Natural, USD : Natural }
}
, sip : { app : Text, realm : Text }
, sip_host : Text
@@ -67,14 +67,10 @@ in
}
],
sims = {
- CAD = { per_gb = 100 },
- USD = { per_gb = 100 },
- sim = [
- { mapKey = <CAD|USD>.CAD, mapValue = { price = 1, plan = "$1 / GB + $1 / year" } }
- ],
- esim = [
- { mapKey = <CAD|USD>.CAD, mapValue = { price = 1, plan = "$1 / GB + $1 / year" } }
- ]
+ annual = { CAD = 100, USD = 100 },
+ esim = { CAD = 1, USD = 1 },
+ per_gb = { CAD = 100, USD = 100 },
+ sim = { CAD = 1, USD = 1 }
},
electrum = {
rpc_uri = "",
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_relative "sim_pricing"
+
class SIMKind
def initialize(variant)
@klass =
@@ -19,13 +21,16 @@ class SIMKind
end
# @param [Customer] customer
- # @raise [ArgumentError] If matching `CONFIG[:sims]`
- # key not found for `@variant` and customer
+ # @raise [ArgumentError] If matching SIM price is missing from `CONFIG[:sims]`
def get_processor(customer)
- cfg = cfg(customer.currency)
- raise ArgumentError, "Invalid config" unless cfg
-
- @klass.for(customer, **cfg)
+ price = price_cents(customer.currency)
+ raise ArgumentError, "Invalid config" unless price
+
+ @klass.for(
+ customer,
+ price: price,
+ plan: SIMPricing.plan_label(customer.currency, CONFIG)
+ )
end
# @return [String] The result of either
@@ -38,15 +43,15 @@ class SIMKind
# @return [Float, NilClass] Returns nil if `customer.currency`
# is nil, or if @variant is malformed.
def price(customer)
- cfg = cfg(customer.currency || :USD)
- cfg[:price] / 100.to_d
+ price = price_cents(customer.currency || :USD)
+ price / 100.to_d if price
end
protected
# @param [Symbol] currency One of the currencies from
# CONFIG[:plans] entries
- def cfg(currency)
+ def price_cents(currency)
CONFIG.dig(:sims, @variant.to_sym, currency)
end
end
@@ -5,8 +5,34 @@ require "bigdecimal"
module SIMPricing
# SIM refill billing records currency amounts in transactions. Use BigDecimal
# because the configured per-GB price is stored in cents.
+ def self.per_gb_price(currency, config)
+ configured_price_dollars(:per_gb, currency, config)
+ end
+
+ def self.annual_price(currency, config)
+ configured_price_dollars(:annual, currency, config)
+ end
+
+ def self.configured_price_dollars(price_type, currency, config)
+ BigDecimal(
+ config.fetch(:sims).fetch(price_type).fetch(currency)
+ ) / 100
+ end
+ private_class_method :configured_price_dollars
+
def self.five_gb_refill_price(currency, config)
- (BigDecimal(config[:sims][currency][:per_gb]) / 100) * 5
+ per_gb_price(currency, config) * 5
+ end
+
+ def self.per_gb_label(currency, config)
+ "$%.2f / GB" % per_gb_price(currency, config)
+ end
+
+ def self.plan_label(currency, config)
+ "$%.2f / GB + $%.2f / year" % [
+ per_gb_price(currency, config),
+ annual_price(currency, config)
+ ]
end
# CustomerRepo#put_monthly_limits stores limits with to_i, so render monthly
@@ -783,11 +783,9 @@ Command.new(
}.then { |iq|
case iq.form.field("http://jabber.org/protocol/commands#actions")&.value
when "order-sim"
- SIMOrder.for(customer, **CONFIG.dig(:sims, :sim, customer.currency))
+ SIMKind.new("sim").get_processor(customer)
when "order-esim"
- SIMOrder::ESIM.for(
- customer, **CONFIG.dig(:sims, :esim, customer.currency)
- )
+ SIMKind.new("esim").get_processor(customer)
when "edit-nicknames"
EditSimNicknames.new(customer, sims)
else
@@ -161,15 +161,21 @@ CONFIG = {
electrum_notify_url: ->(*) { "http://notify.example.com" },
admin_notify: "admin_room@example.com",
sims: {
- USD: { per_gb: 100 },
- CAD: { per_gb: 120 },
+ annual: {
+ USD: 100,
+ CAD: 120
+ },
+ per_gb: {
+ USD: 100,
+ CAD: 120
+ },
sim: {
- USD: { price: 500, plan: "1GB" },
- CAD: { price: 600, plan: "1GB" }
+ USD: 500,
+ CAD: 600
},
esim: {
- USD: { price: 300, plan: "500MB" },
- CAD: { price: 400, plan: "500MB" }
+ USD: 300,
+ CAD: 400
}
},
keep_area_codes: [
@@ -63,13 +63,26 @@ class MonthlyDataLimitTest < Minitest::Test
assert_equal 60, limits[:max]
end
+ def test_formats_refill_price_for_display
+ assert_equal "$1.20 / GB", SIMPricing.per_gb_label(:CAD, CONFIG)
+ end
+
+ def test_formats_plan_price_for_display
+ assert_equal(
+ "$1.20 / GB + $1.20 / year",
+ SIMPricing.plan_label(:CAD, CONFIG)
+ )
+ end
+
def test_does_not_need_sim_pricing_without_sims
assert_equal({}, MonthlyDataLimit.for_sims([], :CAD, CONFIG))
end
def test_uses_integer_dollars_for_fractional_refill_price
config = CONFIG.merge(
- sims: CONFIG[:sims].merge(CAD: { per_gb: 125 })
+ sims: CONFIG[:sims].merge(
+ per_gb: CONFIG[:sims][:per_gb].merge(CAD: 125)
+ )
)
limits = MonthlyDataLimit.for_currency(:CAD, config)