1# frozen_string_literal: true
2
3require_relative "trust_level_repo"
4require_relative "credit_card_sale"
5
6class BuyAccountCreditForm
7 # Returns a TrustLevelRepo instance, allowing for dependency injection.
8 # Either creates a new instance given kwargs or returns the existing instance.
9 # @param kwargs [Hash] keyword arguments.
10 # @option kwargs [TrustLevelRepo] :trust_level_repo An existing TrustLevelRepo instance.
11 # @return [TrustLevelRepo] An instance of TrustLevelRepo.
12 def self.trust_level_repo(**kwargs)
13 kwargs[:trust_level_repo] || TrustLevelRepo.new(**kwargs)
14 end
15
16 # Factory method to create a BuyAccountCreditForm for a given customer.
17 # It fetches the customer's trust level to determine the maximum top-up amount.
18 # @param customer [Customer] The customer for whom the form is being created.
19 # @return [EMPromise<BuyAccountCreditForm>] A promise that resolves with the new form instance.
20 def self.for(customer)
21 trust_level_repo.find(customer).then do |trust_level|
22 customer.payment_methods.then do |payment_methods|
23 new(customer.balance, payment_methods, trust_level.max_top_up_amount)
24 end
25 end
26 end
27
28 # Initializes a new BuyAccountCreditForm.
29 # @param balance [BigDecimal] The current balance of the customer.
30 # @param payment_methods [PaymentMethods] The available payment methods for the customer.
31 # @param max_top_up_amount [Numeric] The maximum amount the customer is allowed to top up, based on their trust level.
32 def initialize(balance, payment_methods, max_top_up_amount)
33 @balance = balance
34 @payment_methods = payment_methods
35 @max_top_up_amount = max_top_up_amount
36 end
37
38 # Generates the form template for topping up account credit.
39 # The form will include a range for the amount field, constrained by a minimum of $15
40 # and the customer's specific maximum top-up amount.
41 # @return [FormTemplate::OneRender] The rendered form template.
42 def form
43 FormTemplate.render(
44 :top_up,
45 balance: @balance,
46 payment_methods: @payment_methods,
47 range: [15, @max_top_up_amount]
48 )
49 end
50
51 def parse(form)
52 amount = form.field("amount")&.value&.to_s
53 amount_value = amount.to_f
54
55 raise AmountTooLowError.new(amount_value, 15) if amount_value < 15
56
57 {
58 payment_method: @payment_methods.fetch(
59 form.field("payment_method")&.value.to_i
60 ),
61 amount: amount
62 }
63 end
64end