mirror of
https://github.com/internetee/registry.git
synced 2025-08-06 01:35:10 +02:00
Merge remote-tracking branch 'origin/master' into story/110392672-domains-async
This commit is contained in:
commit
dd421f633b
62 changed files with 1204 additions and 333 deletions
|
@ -32,7 +32,7 @@ class BankLink
|
|||
hash["VK_AMOUNT"] = number_with_precision(invoice.sum_cache, :precision => 2, :separator => ".")
|
||||
hash["VK_CURR"] = invoice.currency
|
||||
hash["VK_REF"] = ""
|
||||
hash["VK_MSG"] = "Order nr. #{invoice.number}"
|
||||
hash["VK_MSG"] = invoice.description
|
||||
hash["VK_RETURN"] = controller.registrar_return_payment_with_url(type)
|
||||
hash["VK_CANCEL"] = controller.registrar_return_payment_with_url(type)
|
||||
hash["VK_DATETIME"] = Time.now.strftime("%Y-%m-%dT%H:%M:%S%z")
|
||||
|
@ -101,6 +101,7 @@ class BankLink
|
|||
transaction.buyer_iban = params["VK_SND_ACC"]
|
||||
transaction.buyer_name = params["VK_SND_NAME"]
|
||||
transaction.paid_at = Time.parse(params["VK_T_DATETIME"])
|
||||
transaction.save!
|
||||
|
||||
transaction.autobind_invoice
|
||||
end
|
||||
|
|
|
@ -2,6 +2,7 @@ class BankTransaction < ActiveRecord::Base
|
|||
include Versions
|
||||
belongs_to :bank_statement
|
||||
has_one :account_activity
|
||||
has_many :directo_records, as: :item, class_name: 'Directo'# Deprecated
|
||||
|
||||
scope :unbinded, lambda {
|
||||
where('id NOT IN (SELECT bank_transaction_id FROM account_activities where bank_transaction_id IS NOT NULL)')
|
||||
|
@ -16,21 +17,32 @@ class BankTransaction < ActiveRecord::Base
|
|||
account_activity.invoice
|
||||
end
|
||||
|
||||
|
||||
def invoice_num
|
||||
return @invoice_no if defined?(@invoice_no)
|
||||
|
||||
match = description.match(/^[^\d]*(\d+)/)
|
||||
return unless match
|
||||
|
||||
@invoice_no = match[1].try(:to_i)
|
||||
end
|
||||
|
||||
def invoice
|
||||
@invoice ||= registrar.invoices.find_by(number: invoice_num) if registrar
|
||||
end
|
||||
|
||||
def registrar
|
||||
@registrar ||= Registrar.find_by(reference_no: reference_no)
|
||||
end
|
||||
|
||||
|
||||
# For successful binding, reference number, invoice id and sum must match with the invoice
|
||||
# rubocop: disable Metrics/PerceivedComplexity
|
||||
# rubocop: disable Metrics/CyclomaticComplexity
|
||||
def autobind_invoice
|
||||
return if binded?
|
||||
registrar = Registrar.find_by(reference_no: reference_no)
|
||||
return unless registrar
|
||||
|
||||
match = description.match(/^[^\d]*(\d+)/)
|
||||
return unless match
|
||||
|
||||
invoice_no = match[1].to_i
|
||||
return unless invoice_no
|
||||
|
||||
invoice = registrar.invoices.find_by(number: invoice_no)
|
||||
return unless invoice_num
|
||||
return unless invoice
|
||||
|
||||
return if invoice.binded?
|
||||
|
|
|
@ -1,5 +1,56 @@
|
|||
class BlockedDomain < ActiveRecord::Base
|
||||
include Versions
|
||||
before_save :generate_data
|
||||
before_destroy :remove_data
|
||||
validates :name, domain_name: true, uniqueness: true
|
||||
|
||||
after_initialize -> { self.names = [] if names.nil? }
|
||||
|
||||
class << self
|
||||
def by_domain name
|
||||
where(name: name)
|
||||
end
|
||||
|
||||
def any_of_domains names
|
||||
where(name: names)
|
||||
end
|
||||
end
|
||||
|
||||
def name= val
|
||||
super SimpleIDN.to_unicode(val)
|
||||
end
|
||||
|
||||
def generate_data
|
||||
return if Domain.where(name: name).any?
|
||||
|
||||
@json = generate_json
|
||||
@body = generate_body
|
||||
update_whois_server
|
||||
end
|
||||
|
||||
alias_method :update_whois_record, :generate_data
|
||||
|
||||
def update_whois_server
|
||||
wr = Whois::Record.find_or_initialize_by(name: name)
|
||||
wr.body = @body
|
||||
wr.json = @json
|
||||
wr.save
|
||||
end
|
||||
|
||||
def generate_body
|
||||
template = Rails.root.join("app/views/for_models/whois_other.erb".freeze)
|
||||
ERB.new(template.read, nil, "-").result(binding)
|
||||
end
|
||||
|
||||
def generate_json
|
||||
h = HashWithIndifferentAccess.new
|
||||
h[:name] = self.name
|
||||
h[:status] = 'Blocked'
|
||||
h
|
||||
end
|
||||
|
||||
def remove_data
|
||||
return if Domain.where(name: name).any?
|
||||
|
||||
Whois::Record.where(name: name).delete_all
|
||||
end
|
||||
end
|
||||
|
|
|
@ -29,7 +29,7 @@ class Contact < ActiveRecord::Base
|
|||
uniqueness: { message: :epp_id_taken },
|
||||
format: { with: /\A[\w\-\:\.\_]*\z/i, message: :invalid },
|
||||
length: { maximum: 100, message: :too_long_contact_code }
|
||||
validate :ident_valid_format?
|
||||
validate :val_ident_valid_format?
|
||||
validate :uniq_statuses?
|
||||
validate :validate_html
|
||||
|
||||
|
@ -235,16 +235,17 @@ class Contact < ActiveRecord::Base
|
|||
name || '[no name]'
|
||||
end
|
||||
|
||||
def ident_valid_format?
|
||||
def val_ident_valid_format?
|
||||
case ident_country_code
|
||||
when 'EE'.freeze
|
||||
err_msg = "invalid_EE_identity_format#{"_update" if id}".to_sym
|
||||
case ident_type
|
||||
when 'priv'.freeze
|
||||
errors.add(:ident, :invalid_EE_identity_format) unless Isikukood.new(ident).valid?
|
||||
errors.add(:ident, err_msg) unless Isikukood.new(ident).valid?
|
||||
when 'org'.freeze
|
||||
# !%w(1 7 8 9).freeze.include?(ident.first) ||
|
||||
if ident.size != 8 || !(ident =~/\A[0-9]{8}\z/)
|
||||
errors.add(:ident, :invalid_EE_identity_format)
|
||||
errors.add(:ident, err_msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
49
app/models/directo.rb
Normal file
49
app/models/directo.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
class Directo < ActiveRecord::Base
|
||||
belongs_to :item, polymorphic: true
|
||||
|
||||
def self.send_receipts
|
||||
new_trans = Invoice.where(invoice_type: "DEB", in_directo: false).where.not(cancelled_at: nil)
|
||||
new_trans.find_in_batches(batch_size: 10).each do |group|
|
||||
mappers = {} # need them as no direct connection between invoice
|
||||
builder = Nokogiri::XML::Builder.new(encoding: "UTF-8") do |xml|
|
||||
xml.invoices {
|
||||
group.each do |invoice|
|
||||
next if invoice.account_activity.nil? || invoice.account_activity.bank_transaction.nil?
|
||||
# next if invoice.account_activity.bank_transaction.sum.nil? || invoice.account_activity.bank_transaction.sum != invoice.sum_cache
|
||||
|
||||
num = invoice.number
|
||||
mappers[num] = invoice
|
||||
xml.invoice(
|
||||
"SalesAgent" => Setting.directo_sales_agent,
|
||||
"Number" => num,
|
||||
"InvoiceDate" => invoice.created_at.strftime("%Y-%m-%dT%H:%M:%S"),
|
||||
"PaymentTerm" => Setting.directo_receipt_payment_term,
|
||||
"Currency" => invoice.currency,
|
||||
"CustomerCode"=> invoice.buyer.try(:directo_handle)
|
||||
){
|
||||
xml.line(
|
||||
"ProductID" => Setting.directo_receipt_product_name,
|
||||
"Quantity" => 1,
|
||||
"UnitPriceWoVAT" => ActionController::Base.helpers.number_with_precision(invoice.sum_cache/(1+invoice.vat_prc), precision: 2, separator: "."),
|
||||
"ProductName" => invoice.description
|
||||
)
|
||||
}
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
data = builder.to_xml.gsub("\n",'')
|
||||
response = RestClient::Request.execute(url: ENV['directo_invoice_url'], method: :post, payload: {put: "1", what: "invoice", xmldata: data}, verify_ssl: false).to_s
|
||||
dump_result_to_db(mappers, response)
|
||||
end
|
||||
end
|
||||
|
||||
def self.dump_result_to_db mappers, xml
|
||||
Nokogiri::XML(xml).css("Result").each do |res|
|
||||
obj = mappers[res.attributes["docid"].value.to_i]
|
||||
obj.directo_records.create!(response: res.as_json.to_h)
|
||||
obj.update_columns(in_directo: true)
|
||||
Rails.logger.info("[DIRECTO] Invoice #{res.attributes["docid"].value} was pushed and return is #{res.as_json.to_h.inspect}")
|
||||
end
|
||||
end
|
||||
end
|
|
@ -93,7 +93,7 @@ class Domain < ActiveRecord::Base
|
|||
def update_reserved_domains
|
||||
return unless in_reserved_list?
|
||||
rd = ReservedDomain.by_domain(name).first
|
||||
rd.names[name] = SecureRandom.hex
|
||||
rd.password = SecureRandom.hex
|
||||
rd.save
|
||||
end
|
||||
|
||||
|
@ -244,7 +244,7 @@ class Domain < ActiveRecord::Base
|
|||
if domain.pending_delete? || domain.pending_delete_confirmation?
|
||||
DomainMailer.pending_delete_expired_notification(domain.id, true).deliver
|
||||
end
|
||||
domain.clean_pendings!
|
||||
domain.clean_pendings_lowlevel
|
||||
unless Rails.env.test?
|
||||
STDOUT << "#{Time.zone.now.utc} Domain.clean_expired_pendings: ##{domain.id} (#{domain.name})\n"
|
||||
end
|
||||
|
@ -264,9 +264,9 @@ class Domain < ActiveRecord::Base
|
|||
domains.each do |domain|
|
||||
next unless domain.expirable?
|
||||
domain.set_graceful_expired
|
||||
DomainMailer.expiration_reminder(domain.id).deliver
|
||||
DomainMailer.expiration_reminder(domain.id).deliver_in(Setting.expiration_reminder_mail.to_i.days)
|
||||
STDOUT << "#{Time.zone.now.utc} Domain.start_expire_period: ##{domain.id} (#{domain.name}) #{domain.changes}\n" unless Rails.env.test?
|
||||
domain.save
|
||||
domain.save(validate: false)
|
||||
end
|
||||
|
||||
STDOUT << "#{Time.zone.now.utc} - Successfully expired #{domains.count} domains\n" unless Rails.env.test?
|
||||
|
@ -280,7 +280,7 @@ class Domain < ActiveRecord::Base
|
|||
next unless domain.server_holdable?
|
||||
domain.statuses << DomainStatus::SERVER_HOLD
|
||||
STDOUT << "#{Time.zone.now.utc} Domain.start_redemption_grace_period: ##{domain.id} (#{domain.name}) #{domain.changes}\n" unless Rails.env.test?
|
||||
domain.save
|
||||
domain.save(validate: false)
|
||||
end
|
||||
|
||||
STDOUT << "#{Time.zone.now.utc} - Successfully set server_hold to #{d.count} domains\n" unless Rails.env.test?
|
||||
|
@ -294,7 +294,7 @@ class Domain < ActiveRecord::Base
|
|||
next unless domain.delete_candidateable?
|
||||
domain.statuses << DomainStatus::DELETE_CANDIDATE
|
||||
STDOUT << "#{Time.zone.now.utc} Domain.start_delete_period: ##{domain.id} (#{domain.name}) #{domain.changes}\n" unless Rails.env.test?
|
||||
domain.save
|
||||
domain.save(validate: false)
|
||||
end
|
||||
|
||||
return if Rails.env.test?
|
||||
|
@ -408,8 +408,7 @@ class Domain < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
return false if statuses.include_any?(DomainStatus::DELETE_CANDIDATE, DomainStatus::SERVER_RENEW_PROHIBITED,
|
||||
DomainStatus::CLIENT_RENEW_PROHIBITED, DomainStatus::PENDING_RENEW,
|
||||
return false if statuses.include_any?(DomainStatus::DELETE_CANDIDATE, DomainStatus::PENDING_RENEW,
|
||||
DomainStatus::PENDING_TRANSFER, DomainStatus::PENDING_DELETE,
|
||||
DomainStatus::PENDING_UPDATE, DomainStatus::PENDING_DELETE_CONFIRMATION)
|
||||
true
|
||||
|
@ -439,6 +438,25 @@ class Domain < ActiveRecord::Base
|
|||
save
|
||||
end
|
||||
|
||||
|
||||
# state change shouln't be
|
||||
def clean_pendings_lowlevel
|
||||
statuses.delete(DomainStatus::PENDING_DELETE_CONFIRMATION)
|
||||
statuses.delete(DomainStatus::PENDING_UPDATE)
|
||||
statuses.delete(DomainStatus::PENDING_DELETE)
|
||||
|
||||
status_notes[DomainStatus::PENDING_UPDATE] = ''
|
||||
status_notes[DomainStatus::PENDING_DELETE] = ''
|
||||
|
||||
update_columns(
|
||||
registrant_verification_token: nil,
|
||||
registrant_verification_asked_at: nil,
|
||||
pending_json: {},
|
||||
status_notes: status_notes,
|
||||
statuses: statuses.presence || [DomainStatus::OK]
|
||||
)
|
||||
end
|
||||
|
||||
def pending_update!
|
||||
return true if pending_update?
|
||||
self.epp_pending_update = true # for epp
|
||||
|
@ -544,7 +562,7 @@ class Domain < ActiveRecord::Base
|
|||
|
||||
def validate_nameserver_ips
|
||||
nameservers.to_a.reject(&:marked_for_destruction?).each do |ns|
|
||||
next unless ns.hostname.end_with?(name)
|
||||
next unless ns.hostname.end_with?(".#{name}")
|
||||
next if ns.ipv4.present?
|
||||
errors.add(:nameservers, :invalid) if errors[:nameservers].blank?
|
||||
ns.errors.add(:ipv4, :blank)
|
||||
|
|
|
@ -123,6 +123,7 @@ class Epp::Contact < Contact
|
|||
[:email, :invalid],
|
||||
[:ident, :invalid],
|
||||
[:ident, :invalid_EE_identity_format],
|
||||
[:ident, :invalid_EE_identity_format_update],
|
||||
[:ident, :invalid_birthday_format],
|
||||
[:ident, :invalid_country_code],
|
||||
[:ident_type, :missing],
|
||||
|
@ -164,7 +165,7 @@ class Epp::Contact < Contact
|
|||
org_priv = %w(org priv).freeze
|
||||
if ident_country_code.blank? && org_priv.include?(ident_type) && org_priv.include?(ident_frame.attr('type'))
|
||||
at.merge!(ident_country_code: ident_frame.attr('cc'), ident_type: ident_frame.attr('type'))
|
||||
elsif ident_type == "birthday" && ident !=~ /\d{4}-\d{2}-\d{2}/ && (Date.parse(ident) rescue false)
|
||||
elsif ident_type == "birthday" && !ident[/\A\d{4}-\d{2}-\d{2}\z/] && (Date.parse(ident) rescue false)
|
||||
at.merge!(ident: ident_frame.text)
|
||||
at.merge!(ident_country_code: ident_frame.attr('cc')) if ident_frame.attr('cc').present?
|
||||
elsif ident_type.blank? && ident_country_code.blank?
|
||||
|
|
|
@ -8,7 +8,7 @@ class Epp::Domain < Domain
|
|||
before_validation :manage_permissions
|
||||
def manage_permissions
|
||||
return if is_admin # this bad hack for 109086524, refactor later
|
||||
return true if is_transfer
|
||||
return true if is_transfer || is_renewal
|
||||
return unless update_prohibited? || delete_prohibited?
|
||||
add_epp_error('2304', nil, nil, I18n.t(:object_status_prohibits_operation))
|
||||
false
|
||||
|
@ -507,18 +507,17 @@ class Epp::Domain < Domain
|
|||
frame = Nokogiri::XML(pending_json['frame'])
|
||||
|
||||
self.deliver_emails = true # turn on email delivery
|
||||
send_mail :registrant_updated_notification_for_old_registrant
|
||||
|
||||
statuses.delete(DomainStatus::PENDING_UPDATE)
|
||||
yield(self) if block_given? # need to skip statuses check here
|
||||
self.save
|
||||
|
||||
self.statuses.delete(DomainStatus::PENDING_UPDATE)
|
||||
::PaperTrail.whodunnit = user.id_role_username # updator str should be the request originator not the approval user
|
||||
|
||||
send_mail :registrant_updated_notification_for_old_registrant
|
||||
return unless update(frame, user, false)
|
||||
clean_pendings!
|
||||
|
||||
send_mail :registrant_updated_notification_for_new_registrant
|
||||
update_whois_record
|
||||
WhoisRecord.find_by(domain_id: id).save # need to reload model
|
||||
|
||||
save! # for notification if everything fails
|
||||
true
|
||||
end
|
||||
|
||||
|
@ -591,6 +590,7 @@ class Epp::Domain < Domain
|
|||
|
||||
statuses.delete(DomainStatus::SERVER_HOLD)
|
||||
statuses.delete(DomainStatus::EXPIRED)
|
||||
statuses.delete(DomainStatus::SERVER_UPDATE_PROHIBITED)
|
||||
|
||||
save
|
||||
end
|
||||
|
|
|
@ -2,14 +2,27 @@ class Invoice < ActiveRecord::Base
|
|||
include Versions
|
||||
belongs_to :seller, class_name: 'Registrar'
|
||||
belongs_to :buyer, class_name: 'Registrar'
|
||||
has_one :account_activity
|
||||
has_many :invoice_items
|
||||
has_one :account_activity
|
||||
has_many :directo_records, as: :item, class_name: 'Directo'
|
||||
|
||||
accepts_nested_attributes_for :invoice_items
|
||||
|
||||
scope :unbinded, lambda {
|
||||
where('id NOT IN (SELECT invoice_id FROM account_activities where invoice_id IS NOT NULL)')
|
||||
}
|
||||
scope :all_columns, ->{select("invoices.*")}
|
||||
scope :sort_due_date_column, ->{all_columns.select("CASE WHEN invoices.cancelled_at is not null THEN
|
||||
(invoices.cancelled_at + interval '100 year') ELSE
|
||||
invoices.due_date END AS sort_due_date")}
|
||||
scope :sort_by_sort_due_date_asc, ->{sort_due_date_column.order("sort_due_date ASC")}
|
||||
scope :sort_by_sort_due_date_desc, ->{sort_due_date_column.order("sort_due_date DESC")}
|
||||
scope :sort_receipt_date_column, ->{all_columns.includes(:account_activity).references(:account_activity).select(%Q{
|
||||
CASE WHEN account_activities.created_at is not null THEN account_activities.created_at
|
||||
WHEN invoices.cancelled_at is not null THEN invoices.cancelled_at + interval '100 year'
|
||||
ELSE NULL END AS sort_receipt_date })}
|
||||
scope :sort_by_sort_receipt_date_asc, ->{sort_receipt_date_column.order("sort_receipt_date ASC")}
|
||||
scope :sort_by_sort_receipt_date_desc, ->{sort_receipt_date_column.order("sort_receipt_date DESC")}
|
||||
|
||||
attr_accessor :billing_email
|
||||
validates :billing_email, email_format: { message: :invalid }, allow_blank: true
|
||||
|
@ -19,6 +32,8 @@ class Invoice < ActiveRecord::Base
|
|||
|
||||
before_create :set_invoice_number, :check_vat
|
||||
|
||||
before_save :check_vat
|
||||
|
||||
def set_invoice_number
|
||||
last_no = Invoice.order(number: :desc).where('number IS NOT NULL').limit(1).pluck(:number).first
|
||||
|
||||
|
@ -97,6 +112,10 @@ class Invoice < ActiveRecord::Base
|
|||
kit.to_pdf
|
||||
end
|
||||
|
||||
def description
|
||||
"Order nr. #{number}"
|
||||
end
|
||||
|
||||
def pdf_name
|
||||
"invoice-#{number}.pdf"
|
||||
end
|
||||
|
|
|
@ -1,25 +1,75 @@
|
|||
class ReservedDomain < ActiveRecord::Base
|
||||
include Versions # version/reserved_domain_version.rb
|
||||
before_save :fill_empty_passwords
|
||||
before_save :generate_data
|
||||
before_destroy :remove_data
|
||||
validates :name, domain_name: true, uniqueness: true
|
||||
|
||||
|
||||
|
||||
def fill_empty_passwords
|
||||
return unless names
|
||||
names.each { |k, v| names[k] = SecureRandom.hex if v.blank? }
|
||||
end
|
||||
|
||||
class << self
|
||||
def pw_for(domain_name)
|
||||
name_in_unicode = SimpleIDN.to_ascii(domain_name)
|
||||
by_domain(domain_name).select("names -> '#{domain_name}' AS pw").first.try(:pw) ||
|
||||
by_domain(name_in_unicode).select("names -> '#{name_in_unicode}' AS pw").first.try(:pw)
|
||||
name_in_ascii = SimpleIDN.to_ascii(domain_name)
|
||||
by_domain(domain_name).first.try(:password) || by_domain(name_in_ascii).first.try(:password)
|
||||
end
|
||||
|
||||
def by_domain name
|
||||
where("names ? '#{name}'")
|
||||
where(name: name)
|
||||
end
|
||||
|
||||
def any_of_domains names
|
||||
where("names ?| ARRAY['#{names.join("','")}']")
|
||||
where(name: names)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def fill_empty_passwords
|
||||
|
||||
if self.password.empty?
|
||||
|
||||
self.password = SecureRandom.hex
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def name= val
|
||||
super SimpleIDN.to_unicode(val)
|
||||
end
|
||||
|
||||
def generate_data
|
||||
return if Domain.where(name: name).any?
|
||||
|
||||
@json = generate_json
|
||||
@body = generate_body
|
||||
update_whois_server
|
||||
end
|
||||
|
||||
alias_method :update_whois_record, :generate_data
|
||||
|
||||
def update_whois_server
|
||||
wr = Whois::Record.find_or_initialize_by(name: name)
|
||||
wr.body = @body
|
||||
wr.json = @json
|
||||
wr.save
|
||||
end
|
||||
|
||||
def generate_body
|
||||
template = Rails.root.join("app/views/for_models/whois_other.erb".freeze)
|
||||
ERB.new(template.read, nil, "-").result(binding)
|
||||
end
|
||||
|
||||
def generate_json
|
||||
h = HashWithIndifferentAccess.new
|
||||
h[:name] = self.name
|
||||
h[:status] = 'Reserved'
|
||||
h
|
||||
end
|
||||
|
||||
def remove_data
|
||||
return if Domain.where(name: name).any?
|
||||
|
||||
Whois::Record.where(name: name).delete_all
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -106,7 +106,7 @@ class WhoisRecord < ActiveRecord::Base
|
|||
self.json = generated_json
|
||||
self.body = generated_body
|
||||
self.name = json['name']
|
||||
self.registrar_id = domain.registrar_id # for faster registrar updates
|
||||
self.registrar_id = domain.registrar_id if domain # for faster registrar updates
|
||||
end
|
||||
|
||||
def update_whois_server
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue