diff --git a/app/controllers/registrar/bulk_change_controller.rb b/app/controllers/registrar/bulk_change_controller.rb index 60bde9b6f..002aaaff4 100644 --- a/app/controllers/registrar/bulk_change_controller.rb +++ b/app/controllers/registrar/bulk_change_controller.rb @@ -16,12 +16,14 @@ class Registrar if domain_ids_for_bulk_renew.present? domains = Epp::Domain.where(id: domain_ids_for_bulk_renew).to_a - task = Domains::BulkRenew::Start.run(domains: domains, period_element: @period) - if task.valid? - flash[:notice] = t(:bulk_renew_completed) - else - flash[:notice] = task.errors.full_messages.join(' and ') - end + task = Domains::BulkRenew::Start.run(domains: domains, + period_element: @period, + registrar: current_registrar_user.registrar) + flash[:notice] = if task.valid? + t(:bulk_renew_completed) + else + task.errors.full_messages.join(' and ') + end end render file: 'registrar/bulk_change/new', locals: { active_tab: :bulk_renew } end diff --git a/app/interactions/domains/bulk_renew/single_domain_renew.rb b/app/interactions/domains/bulk_renew/single_domain_renew.rb index 96b9678c0..ecd89f5dd 100644 --- a/app/interactions/domains/bulk_renew/single_domain_renew.rb +++ b/app/interactions/domains/bulk_renew/single_domain_renew.rb @@ -3,9 +3,46 @@ module Domains class SingleDomainRenew < ActiveInteraction::Base object :domain, class: Epp::Domain + integer :period + string :unit + object :registrar def execute + in_transaction_with_retries_do { + success = domain.renew(domain.valid_to, period, unit) + if success + check_balance + reduce_balance + else + errors.add(:domain, I18n.t('domain_renew_error_for_domain', domain: domain.name)) + end + } + end + + def check_balance + compose(Domains::CheckBalance::SingleDomain, + domain: domain, + operation: 'renew', + period: period, + unit: unit) + end + + def reduce_balance + domain_pricelist = domain.pricelist('renew', period, unit) + registrar.debit!(sum: domain_pricelist.price.amount, + description: "#{I18n.t('renew')} #{domain.name}", + activity_type: AccountActivity::RENEW, + price: domain_pricelist) + end + + def in_transaction_with_retries_do + ActiveRecord::Base.transaction(isolation: :serializable) do + yield if block_given? + end + rescue ActiveRecord::StatementInvalid + sleep rand / 100 + retry end end end diff --git a/app/interactions/domains/bulk_renew/start.rb b/app/interactions/domains/bulk_renew/start.rb index e00e7e984..202f16b71 100644 --- a/app/interactions/domains/bulk_renew/start.rb +++ b/app/interactions/domains/bulk_renew/start.rb @@ -5,18 +5,37 @@ module Domains object class: Epp::Domain end string :period_element + object :registrar def execute - period = (period_element.to_i == 0) ? 1 : period_element.to_i - unit = period_element[-1] || 'y' - task = Domains::CheckBalance::Mass.run(domains: domains, - operation: 'renew', - period: period, - unit: unit) - unless task.valid? - errors.merge!(task.errors) + if mass_check_balance.valid? + domains.each do |domain| + Domains::BulkRenew::SingleDomainRenew.run(domain: domain, + period: period, + unit: unit, + registrar: registrar) + end + else + errors.merge!(mass_check_balance.errors) end end + + private + + def period + period_element.to_i.zero? ? 1 : period_element.to_i + end + + def unit + period_element[-1] || 'y' + end + + def mass_check_balance + Domains::CheckBalance::Mass.run(domains: domains, + operation: 'renew', + period: period, + unit: unit) + end end end end diff --git a/app/interactions/domains/check_balance/mass.rb b/app/interactions/domains/check_balance/mass.rb index 68dee0019..f5946b2c5 100644 --- a/app/interactions/domains/check_balance/mass.rb +++ b/app/interactions/domains/check_balance/mass.rb @@ -4,7 +4,6 @@ module Domains array :domains do object class: Epp::Domain end - string :operation integer :period string :unit diff --git a/app/interactions/domains/check_balance/single_domain.rb b/app/interactions/domains/check_balance/single_domain.rb index a9e7f0e1a..ad1a6f271 100644 --- a/app/interactions/domains/check_balance/single_domain.rb +++ b/app/interactions/domains/check_balance/single_domain.rb @@ -9,18 +9,25 @@ module Domains string :unit def execute - domain_pricelist = domain.pricelist(operation, period.try(:to_i), unit) if domain_pricelist.try(:price) # checking if price list is not found if current_user.registrar.balance < domain_pricelist.price.amount - errors.add(:domain, I18n.t('billing_failure_credit_balance_low_for_domain', domain: domain.name)) + errors.add(:domain, I18n.t('billing_failure_credit_balance_low_for_domain', + domain: domain.name)) return false end else - errors.add(:domain, I18n.t(:active_price_missing_for_operation_with_domain, domain: domain.name)) + errors.add(:domain, I18n.t(:active_price_missing_for_operation_with_domain, + domain: domain.name)) return false end true end + + private + + def domain_pricelist + domain.pricelist(operation, period.try(:to_i), unit) + end end end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 2470062ab..3547b049f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -589,6 +589,7 @@ en: create_new_invoice: 'Create new invoice' billing_failure_credit_balance_low: 'Billing failure - credit balance low' billing_failure_credit_balance_low_for_domain: 'Billing failure - credit balance low for %{domain}' + domain_renew_error_for_domain: 'Domain renew error for %{domain}' create: 'Create' activity_type: 'Activity type' receipt_date_from: 'Receipt date from'