1# frozen_string_literal: true
2
3require_relative "expiring_lock"
4
5class BillPlanCommand
6 def self.for(customer)
7 return ForUnregistered.new(customer) unless customer.registered?
8
9 unless customer.balance >= customer.monthly_price
10 return ForLowBalance.new(customer)
11 end
12
13 new(customer)
14 end
15
16 def initialize(customer)
17 @customer = customer
18 end
19
20 def reload_customer(db)
21 @customer = Command.execution.customer_repo.with(db: db)
22 .find(customer_id).sync
23 end
24
25 def call
26 ExpiringLock.new("jmp_customer_bill_plan-#{customer_id}").with {
27 @customer.bill_plan(note: note) { |db|
28 reload_customer(db).balance > @customer.monthly_price
29 }
30 }.then do |billed|
31 Command.reply do |reply|
32 reply.note_type = billed ? :info : :error
33 reply.note_text = "#{customer_id}#{billed ? '' : ' not'} billed"
34 end
35 end
36 end
37
38protected
39
40 def note
41 "Renew account plan for #{@customer.registered?.phone}"
42 end
43
44 def customer_id
45 @customer.customer_id
46 end
47
48 class ForLowBalance
49 def initialize(customer)
50 @customer = customer
51 end
52
53 def call
54 LowBalance.for(@customer).then(&:notify!).then do |amount|
55 next command_for(amount).call if amount&.positive?
56
57 notify_failure
58 Command.reply do |reply|
59 reply.note_type = :error
60 reply.note_text = "#{@customer.customer_id} balance is too low"
61 end
62 end
63 end
64
65 protected
66
67 def notify_failure
68 m = Blather::Stanza::Message.new
69 m.from = CONFIG[:notify_from]
70 m.xhtml =
71 "Failed to renew account for #{@customer.registered?.phone}. " \
72 "To keep your number, please " \
73 "<a href='xmpp:cheogram.com?command'>buy more credit soon</a>."
74 m.body = m.xhtml_node.text
75 @customer.stanza_to(m)
76 end
77
78 def command_for(amount)
79 BillPlanCommand.for(
80 @customer.with_balance(@customer.balance + amount)
81 )
82 end
83 end
84
85 class ForUnregistered
86 def initialize(customer)
87 @customer = customer
88 end
89
90 def call
91 Command.reply do |reply|
92 reply.note_type = :error
93 reply.note_text = "#{@customer.customer_id} is not registered"
94 end
95 end
96 end
97end