~singpolyma/sgx-jmp

655624ddc816cffeeb47ec50a0715bc6a24e5ff0 — Stephen Paul Weber 6 months ago 456a45b
Bill plan command

Implements the full logic of the billing_monthly_cronjob for one customer by
reusing code that has been written more robustly in sgx-jmp for some time.  This
will allow the cronjob to just execute this command once a day for each expiring
customer to get all the correct billing behaviours.
4 files changed, 78 insertions(+), 2 deletions(-)

M forms/admin_menu.rb
M lib/admin_command.rb
A lib/bill_plan_command.rb
M lib/customer.rb
M forms/admin_menu.rb => forms/admin_menu.rb +2 -1
@@ 9,6 9,7 @@ field(
	description: "or put a new customer info",
	options: [
		{ value: "info", label: "Customer Info" },
		{ value: "financial", label: "Customer Billing Information" }
		{ value: "financial", label: "Customer Billing Information" },
		{ value: "bill_plan", label: "Bill Customer" }
	]
)

M lib/admin_command.rb => lib/admin_command.rb +5 -0
@@ 1,5 1,6 @@
# frozen_string_literal: true

require_relative "bill_plan_command"
require_relative "customer_info_form"
require_relative "financial_info"
require_relative "form_template"


@@ 65,6 66,10 @@ class AdminCommand
		end
	end

	def action_bill_plan
		BillPlanCommand.for(@target_customer).call
	end

	def pay_methods(financial_info)
		reply(FormTemplate.render(
			"admin_payment_methods",

A lib/bill_plan_command.rb => lib/bill_plan_command.rb +69 -0
@@ 0,0 1,69 @@
# frozen_string_literal: true

class BillPlanCommand
	def self.for(customer)
		return ForUnregistered.new unless customer.registered?

		unless customer.balance > customer.monthly_price
			return ForLowBalance.new(customer)
		end

		new(customer)
	end

	def initialize(customer)
		@customer = customer
	end

	def call
		@customer.bill_plan
		Command.reply do |reply|
			reply.note_type = :info
			reply.note_text = "Customer billed"
		end
	end

	class ForLowBalance
		def initialize(customer)
			@customer = customer
		end

		def call
			LowBalance.for(@customer).then(&:notify!).then do |amount|
				return command_for(amount).call if amount&.positive?

				notify_failure
				Command.reply do |reply|
					reply.note_type = :error
					reply.note_text = "Customer balance is too low"
				end
			end
		end

	protected

		def notify_failure
			m = Blather::Stanza::Message.new
			m.from = CONFIG[:notify_from]
			m.body =
				"Failed to renew account for #{@customer.registered?.phone}. " \
				"To keep your number, please buy more credit soon."
			@customer.stanza_to(m)
		end

		def command_for(amount)
			BillPlanCommand.for(
				@customer.with_balance(@customer.balance + amount)
			)
		end
	end

	class ForUnregistered
		def call
			Command.reply do |reply|
				reply.note_type = :error
				reply.note_text = "Customer is not registered"
			end
		end
	end
end

M lib/customer.rb => lib/customer.rb +2 -1
@@ 24,7 24,8 @@ class Customer

	def_delegators :@plan, :active?, :activate_plan_starting_now, :bill_plan,
	               :currency, :merchant_account, :plan_name, :minute_limit,
	               :message_limit, :auto_top_up_amount, :monthly_overage_limit
	               :message_limit, :auto_top_up_amount, :monthly_overage_limit,
	               :monthly_price
	def_delegators :@sgx, :register!, :registered?, :set_ogm_url,
	               :fwd, :transcription_enabled
	def_delegators :@usage, :usage_report, :message_usage, :incr_message_usage