diff --git a/app/controllers/epp/domains_controller.rb b/app/controllers/epp/domains_controller.rb index 5ca4f0a0e..c2e92ea49 100644 --- a/app/controllers/epp/domains_controller.rb +++ b/app/controllers/epp/domains_controller.rb @@ -87,13 +87,27 @@ class Epp::DomainsController < EppController def renew authorize! :renew, @domain - handle_errors(@domain) and return unless @domain.renew( - params[:parsed_frame].css('curExpDate').text, - params[:parsed_frame].css('period').text, - params[:parsed_frame].css('period').first['unit'] - ) + period = params[:parsed_frame].css('period').text + period_unit = params[:parsed_frame].css('period').first['unit'] - render_epp_response '/epp/domains/renew' + ActiveRecord::Base.transaction do + success = @domain.renew( + params[:parsed_frame].css('curExpDate').text, + period, period_unit + ) + + if success + unless balance_ok?('renew', period, period_unit) + handle_errors + fail ActiveRecord::Rollback + end + + current_user.registrar.debit!(@domain_price, "#{I18n.t('renew')} #{@domain.name}") + render_epp_response '/epp/domains/renew' + else + handle_errors(@domain) + end + end end def transfer @@ -197,13 +211,14 @@ class Epp::DomainsController < EppController } end - def balance_ok?(operation) - @domain_price = @domain.price(operation).amount + def balance_ok?(operation, period = nil, unit = nil) + @domain_price = @domain.price(operation, period.try(:to_i), unit).amount if current_user.registrar.balance < @domain_price epp_errors << { code: '2104', msg: I18n.t('billing_failure_credit_balance_low') } + return false end true diff --git a/app/models/domain.rb b/app/models/domain.rb index 1800c98ec..ae81ce474 100644 --- a/app/models/domain.rb +++ b/app/models/domain.rb @@ -146,9 +146,9 @@ class Domain < ActiveRecord::Base class << self def convert_period_to_time(period, unit) - return period.to_i.days if unit == 'd' - return period.to_i.months if unit == 'm' - return period.to_i.years if unit == 'y' + return (period.to_i / 365).years if unit == 'd' + return (period.to_i / 12).years if unit == 'm' + return period.to_i.years if unit == 'y' end def included @@ -372,14 +372,22 @@ class Domain < ActiveRecord::Base DomainMailer.pending_deleted(self).deliver_now end - def price(operation) + def price(operation, period_i = nil, unit = nil) + period_i ||= period + unit ||= period_unit + zone = name.split('.').drop(1).join('.') - p = period / 365 if period_unit == 'd' - p = period / 12 if period_unit == 'm' - p = period if period_unit == 'y' + p = period_i / 365 if unit == 'd' + p = period_i / 12 if unit == 'm' + p = period_i if unit == 'y' + + if p > 1 + p = "#{p}years" + else + p = "#{p}year" + end - p = "#{p}year" Pricelist.price_for(zone, operation, p) end diff --git a/spec/epp/domain_spec.rb b/spec/epp/domain_spec.rb index c71e4117e..da2dcb162 100644 --- a/spec/epp/domain_spec.rb +++ b/spec/epp/domain_spec.rb @@ -20,6 +20,11 @@ describe 'EPP Domain', epp: true do Fabricate(:reserved_domain) Fabricate(:blocked_domain) Fabricate(:pricelist, valid_to: nil) + Fabricate(:pricelist, duration: '2years', price: 20, valid_to: nil) + Fabricate(:pricelist, duration: '3years', price: 30, valid_to: nil) + Fabricate(:pricelist, operation_category: 'renew', price: 15, valid_to: nil) + Fabricate(:pricelist, operation_category: 'renew', duration: '2years', price: 35, valid_to: nil) + Fabricate(:pricelist, operation_category: 'renew', duration: '3years', price: 62, valid_to: nil) @uniq_no = proc { @i ||= 0; @i += 1 } end @@ -340,7 +345,7 @@ describe 'EPP Domain', epp: true do it 'creates a domain with period in days' do old_balance = @registrar1.balance old_activities = @registrar1.cash_account.account_activities.count - xml = domain_create_xml(period_value: 365, period_unit: 'd') + xml = domain_create_xml(period: { value: '365', attrs: { unit: 'd' }}) response = epp_plain_request(xml) response[:msg].should == 'Command completed successfully' @@ -353,6 +358,38 @@ describe 'EPP Domain', epp: true do a.sum.should == -BigDecimal.new('10.0') end + it 'creates a domain with longer periods' do + old_balance = @registrar1.balance + old_activities = @registrar1.cash_account.account_activities.count + xml = domain_create_xml(period: { value: '2', attrs: { unit: 'y' }}) + + response = epp_plain_request(xml) + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + Domain.last.valid_to.should be_within(60).of(2.years.since) + @registrar1.balance.should be < old_balance + @registrar1.cash_account.account_activities.count.should == old_activities + 1 + a = @registrar1.cash_account.account_activities.last + a.description.should == "Create #{Domain.last.name}" + a.sum.should == -BigDecimal.new('20.0') + end + + it 'creates a domain with longer periods' do + old_balance = @registrar1.balance + old_activities = @registrar1.cash_account.account_activities.count + xml = domain_create_xml(period: { value: '36', attrs: { unit: 'm' }}) + + response = epp_plain_request(xml) + response[:msg].should == 'Command completed successfully' + response[:result_code].should == '1000' + Domain.last.valid_to.should be_within(60).of(3.years.since) + @registrar1.balance.should be < old_balance + @registrar1.cash_account.account_activities.count.should == old_activities + 1 + a = @registrar1.cash_account.account_activities.last + a.description.should == "Create #{Domain.last.name}" + a.sum.should == -BigDecimal.new('30.0') + end + it 'does not create a domain with invalid period' do old_balance = @registrar1.balance old_activities = @registrar1.cash_account.account_activities.count @@ -1995,6 +2032,9 @@ describe 'EPP Domain', epp: true do ### RENEW ### it 'renews a domain' do + old_balance = @registrar1.balance + old_activities = @registrar1.cash_account.account_activities.count + domain.valid_to = Time.zone.now.to_date + 10.days domain.save @@ -2013,6 +2053,99 @@ describe 'EPP Domain', epp: true do name = response[:parsed].css('renData name').text ex_date.should == "#{(exp_date + 1.year)}T00:00:00Z" name.should == domain.name + + @registrar1.balance.should == old_balance - 15.0 + @registrar1.cash_account.account_activities.count.should == old_activities + 1 + a = @registrar1.cash_account.account_activities.last + a.description.should == "Renew #{Domain.last.name}" + a.sum.should == -BigDecimal.new('15.0') + end + + it 'renews a domain with 2 year period' do + old_balance = @registrar1.balance + old_activities = @registrar1.cash_account.account_activities.count + + domain.valid_to = Time.zone.now.to_date + 10.days + domain.save + + exp_date = domain.valid_to.to_date + xml = @epp_xml.domain.renew( + name: { value: domain.name }, + curExpDate: { value: exp_date.to_s }, + period: { value: '730', attrs: { unit: 'd' } } + ) + + response = epp_plain_request(xml) + response[:results][0][:msg].should == 'Command completed successfully' + response[:results][0][:result_code].should == '1000' + + ex_date = response[:parsed].css('renData exDate').text + name = response[:parsed].css('renData name').text + ex_date.should == "#{(exp_date + 2.year)}T00:00:00Z" + name.should == domain.name + + @registrar1.balance.should == old_balance - 35.0 + @registrar1.cash_account.account_activities.count.should == old_activities + 1 + a = @registrar1.cash_account.account_activities.last + a.description.should == "Renew #{Domain.last.name}" + a.sum.should == -BigDecimal.new('35.0') + end + + it 'renews a domain with 3 year period' do + old_balance = @registrar1.balance + old_activities = @registrar1.cash_account.account_activities.count + + domain.valid_to = Time.zone.now.to_date + 10.days + domain.save + + exp_date = domain.valid_to.to_date + xml = @epp_xml.domain.renew( + name: { value: domain.name }, + curExpDate: { value: exp_date.to_s }, + period: { value: '36', attrs: { unit: 'm' } } + ) + + response = epp_plain_request(xml) + response[:results][0][:msg].should == 'Command completed successfully' + response[:results][0][:result_code].should == '1000' + + ex_date = response[:parsed].css('renData exDate').text + name = response[:parsed].css('renData name').text + ex_date.should == "#{(exp_date + 3.year)}T00:00:00Z" + name.should == domain.name + + @registrar1.balance.should == old_balance - 62.0 + @registrar1.cash_account.account_activities.count.should == old_activities + 1 + a = @registrar1.cash_account.account_activities.last + a.description.should == "Renew #{Domain.last.name}" + a.sum.should == -BigDecimal.new('62.0') + end + + it 'does not renew a domain if credit balance low' do + f = Fabricate(:pricelist, valid_to: Time.zone.now + 1.day, operation_category: 'renew', duration: '1year', price: 100000) + old_balance = @registrar1.balance + old_activities = @registrar1.cash_account.account_activities.count + + domain.valid_to = Time.zone.now.to_date + 10.days + domain.save + + exp_date = domain.valid_to.to_date + xml = @epp_xml.domain.renew( + name: { value: domain.name }, + curExpDate: { value: exp_date.to_s }, + period: { value: '1', attrs: { unit: 'y' } } + ) + + response = epp_plain_request(xml) + response[:results][0][:msg].should == 'Billing failure - credit balance low' + response[:results][0][:result_code].should == '2104' + + domain.reload + domain.valid_to.should == exp_date # ensure domain was not renewed + + @registrar1.balance.should == old_balance + @registrar1.cash_account.account_activities.count.should == old_activities + f.delete end it 'returns an error when given and current exp dates do not match' do