~singpolyma/sgx-jmp

25d74f5ca5489ca98140c8edfde2a5b176e9fa3f — Stephen Paul Weber 1 year, 11 months ago 6e32ea1 + 5000e1b
Merge branch 'show-remaining-included-calling-credit'

* show-remaining-included-calling-credit:
  Show remaining included calling credit in customer info
  Add missing require
M forms/customer_info_partial.rb => forms/customer_info_partial.rb +6 -0
@@ 26,4 26,10 @@ field(
	value: "$%.4f" % @info.balance
)

field(
	var: "remaining_included_calling_credit",
	label: "Remaining Included Calling Credit",
	value: "$%.4f" % @info.remaining_included_calling_credit
)

render @info.plan_info.template

M lib/customer.rb => lib/customer.rb +2 -1
@@ 27,7 27,8 @@ class Customer
	               :expires_at, :monthly_price, :save_plan!
	def_delegators :@sgx, :deregister!, :register!, :registered?, :set_ogm_url,
	               :fwd, :transcription_enabled
	def_delegators :@usage, :usage_report, :message_usage, :incr_message_usage
	def_delegators :@usage, :usage_report, :message_usage, :incr_message_usage,
	               :calling_charges_this_month
	def_delegators :@financials, :payment_methods, :btc_addresses,
	               :add_btc_address, :declines, :mark_decline,
	               :transactions

M lib/customer_info.rb => lib/customer_info.rb +10 -1
@@ 6,6 6,7 @@ require "relative_time"
require "value_semantics/monkey_patched"

require_relative "api"
require_relative "call_attempt_repo"
require_relative "customer"
require_relative "customer_plan"
require_relative "form_template"


@@ 79,6 80,8 @@ class CustomerInfo
		tel Either(String, nil)
		balance BigDecimal
		cnam Either(String, nil)
		calling_credit BigDecimal
		calling_charges_this_month BigDecimal
	end

	def self.for(customer)


@@ 86,10 89,16 @@ class CustomerInfo
			plan_info: PlanInfo.for(customer),
			tel: customer.registered? ? customer.registered?.phone : nil,
			balance: customer.balance,
			cnam: customer.tndetails.dig(:features, :lidb, :subscriber_information)
			cnam: customer.tndetails.dig(:features, :lidb, :subscriber_information),
			calling_credit: customer.minute_limit.to_d,
			calling_charges_this_month: customer.calling_charges_this_month
		).then(&method(:new))
	end

	def remaining_included_calling_credit
		[calling_credit - calling_charges_this_month, 0].max
	end

	def form
		FormTemplate.render("customer_info", info: self)
	end

M lib/customer_usage.rb => lib/customer_usage.rb +8 -0
@@ 72,4 72,12 @@ class CustomerUsage
			end
		end
	end

	def calling_charges_this_month
		DB.query_one(<<~SQL, @customer_id).then { |r| r[:charges] }
			SELECT COALESCE(SUM(charge), 0) AS charges
			FROM cdr_with_charge
			WHERE customer_id=$1 AND start >= DATE_TRUNC('month', LOCALTIMESTAMP)
		SQL
	end
end

M test/test_customer_info.rb => test/test_customer_info.rb +86 -0
@@ 6,7 6,9 @@ require "trust_level_repo"
require "trust_level"

API::REDIS = FakeRedis.new
CustomerPlan::DB = Minitest::Mock.new
CustomerPlan::REDIS = Minitest::Mock.new
CustomerUsage::DB = Minitest::Mock.new
PlanInfo::DB = FakeDB.new(
	["test"] => [
		{


@@ 27,6 29,12 @@ class CustomerInfoTest < Minitest::Test
			[String, "test"]
		)

		CustomerUsage::DB.expect(
			:query_one,
			EMPromise.resolve({ charges: 0.to_d }),
			[String, "test"]
		)

		cust = customer(sgx: sgx, plan_name: "test_usd")

		assert CustomerInfo.for(cust).sync.form


@@ 34,6 42,60 @@ class CustomerInfoTest < Minitest::Test
	end
	em :test_info_does_not_crash

	def test_info_has_remaining_included_calling_credit
		sgx = Minitest::Mock.new
		sgx.expect(:registered?, false)

		CustomerPlan::DB.expect(
			:query_one,
			EMPromise.resolve({ start_date: Time.now }),
			[String, "test"]
		)

		CustomerUsage::DB.expect(
			:query_one,
			EMPromise.resolve({ charges: 0.044.to_d }),
			[String, "test"]
		)

		cust = customer(sgx: sgx, plan_name: "test_usd")

		assert_equal(
			"$1.0000",
			CustomerInfo.for(cust).sync.form
				.field("remaining_included_calling_credit").value
		)
		assert_mock sgx
	end
	em :test_info_has_remaining_included_calling_credit

	def test_info_out_of_remaining_included_calling_credit
		sgx = Minitest::Mock.new
		sgx.expect(:registered?, false)

		CustomerPlan::DB.expect(
			:query_one,
			EMPromise.resolve({ start_date: Time.now }),
			[String, "test"]
		)

		CustomerUsage::DB.expect(
			:query_one,
			EMPromise.resolve({ charges: 10.to_d }),
			[String, "test"]
		)

		cust = customer(sgx: sgx, plan_name: "test_usd")

		assert_equal(
			"$0.0000",
			CustomerInfo.for(cust).sync.form
				.field("remaining_included_calling_credit").value
		)
		assert_mock sgx
	end
	em :test_info_out_of_remaining_included_calling_credit

	def test_admin_info_does_not_crash
		sgx = Minitest::Mock.new
		sgx.expect(:registered?, false)


@@ 47,6 109,12 @@ class CustomerInfoTest < Minitest::Test
			[String, "test"]
		)

		CustomerUsage::DB.expect(
			:query_one,
			EMPromise.resolve({ charges: 0.to_d }),
			[String, "test"]
		)

		cust = customer(sgx: sgx, plan_name: "test_usd")

		trust_repo = Minitest::Mock.new


@@ 69,6 137,12 @@ class CustomerInfoTest < Minitest::Test
			[String, "test"]
		)

		CustomerUsage::DB.expect(
			:query_one,
			EMPromise.resolve({ charges: 0.to_d }),
			[String, "test"]
		)

		cust = customer(sgx: sgx, plan_name: "test_usd")

		call_attempt_repo = Minitest::Mock.new


@@ 92,6 166,12 @@ class CustomerInfoTest < Minitest::Test
	em :test_admin_info_with_tel_does_not_crash

	def test_inactive_info_does_not_crash
		CustomerUsage::DB.expect(
			:query_one,
			EMPromise.resolve({ charges: 0.to_d }),
			[String, "test"]
		)

		sgx = Minitest::Mock.new
		sgx.expect(:registered?, false)



@@ 108,6 188,12 @@ class CustomerInfoTest < Minitest::Test
	em :test_inactive_info_does_not_crash

	def test_inactive_admin_info_does_not_crash
		CustomerUsage::DB.expect(
			:query_one,
			EMPromise.resolve({ charges: 0.to_d }),
			[String, "test"]
		)

		sgx = Minitest::Mock.new
		sgx.expect(:registered?, false)
		sgx.expect(:registered?, false)